Compare commits

...

986 Commits

Author SHA1 Message Date
Hiroshi Mimaki 58fb6f421a Set the mruby-1.4.0 release date to 2018-1-16. 2018-01-16 10:15:19 +09:00
Yukihiro "Matz" Matsumoto 623436276e Merge pull request #3916 from mimaki/mruby-socket-cygwin-test
Passed mruby-test on Cygwin.
2017-12-26 15:51:18 +09:00
Hiroshi Mimaki f55df0da7b addrinfo.ai_protocol was not set on Cygwin. 2017-12-26 11:12:49 +09:00
Hiroshi Mimaki bce811a53a Disabled UNIXSocket test on Cygwin 2017-12-26 11:05:28 +09:00
Yukihiro "Matz" Matsumoto 6b09692684 Add `Integer#{allbits?,anybits?,nobits?}. [Ruby2.5]
In mruby, those methods are defined in `Integral` module.
2017-12-26 09:44:39 +09:00
Yukihiro "Matz" Matsumoto 3d7141b7fe Move Intefer#chr to Integral#chr.
Since mruby mixes `Integer` and `Float`, integer operations have
been moved to `Integral` module.
2017-12-26 09:42:34 +09:00
Yukihiro "Matz" Matsumoto ad17ba0e11 KeyError from Hash#fetch should inspect key.
To distinguish string keys and symbol keys.
2017-12-25 23:52:40 +09:00
Yukihiro "Matz" Matsumoto e4a9b4a3ad `Enumerable#{one?,none?,all?,any?} to take pattern argument [Ruby2.5] 2017-12-25 23:43:43 +09:00
Yukihiro "Matz" Matsumoto 421819dc2c Add Hash#slice [Ruby 2.5] 2017-12-25 23:43:37 +09:00
Yukihiro "Matz" Matsumoto df68a3345d assert_equal() takes result as the first argument 2017-12-25 15:39:45 +09:00
Yukihiro "Matz" Matsumoto 2a5545cc25 Update Kernel#method_missing tests for new NoMethodError message.
Also removed tests that depends on implementation details of the default
`method_missing` behavior.
2017-12-23 15:18:13 +09:00
Yukihiro "Matz" Matsumoto 6999e45742 Do not include object string representation in NoMethodError message.
This information is not mandatory but causes a lot of problems in the
past due to infinite recursion by redefining `to_str`, `inspect` etc.
2017-12-23 15:15:03 +09:00
Yukihiro "Matz" Matsumoto ca0f32a208 super should raise TypeError when the receiver is switched; fix #3911
The receiver can be switched using `#instance_eval` etc.
2017-12-23 11:14:12 +09:00
Yukihiro "Matz" Matsumoto aa8786f79c Do not initialize a local variable soon to be assigned. 2017-12-23 11:14:12 +09:00
Yukihiro "Matz" Matsumoto 7e520838b3 Avoid infinite recursion in method_missing; ref #3908 2017-12-23 11:13:27 +09:00
Yukihiro "Matz" Matsumoto 44b4f69fce May need more stack space in mrb_funcall_with_block; fix #3908 2017-12-23 10:01:30 +09:00
Yukihiro "Matz" Matsumoto 8d7e95282c Add #module_exec and #class_exec in mruby-class-ext gem. 2017-12-23 10:01:30 +09:00
Yukihiro "Matz" Matsumoto 7fbbd7ab9f Should not overwrite ci->target_class in mrb_exec_irep().
For example, the following code behaved wrong:

```ruby
Object.instance_exec(1,2,3){|*a|
  def foo
    42
  end
}
p foo()
```
2017-12-23 10:01:30 +09:00
Yukihiro "Matz" Matsumoto 7990bb7fa7 Merge pull request #3913 from llothar/master
Make source compilable with C++17
2017-12-23 09:44:00 +09:00
Lothar Scholz 06f90a3b45 Make source compilable with C++17
Changes applied:

- Removing "register" keyword
- Fixing const pointer to pointer assignments
- Adding type casts to rb_malloc calls
2017-12-23 01:10:43 +01:00
Yukihiro "Matz" Matsumoto 100f0e6759 Do not need to take target_class from the upper proc.
Since it is already set in `mrb_proc_new()`.
2017-12-20 19:37:26 +09:00
Yukihiro "Matz" Matsumoto 73b05f0130 Should not overwrite MRB_PROC_TARGET_CLASS(p) if p has env; fix #3905 2017-12-20 19:37:26 +09:00
Yukihiro "Matz" Matsumoto 165e7b181b Fixed method look-up for method_missing in OP_SUPER; ref #3905
Method look-up for `OP_SUPER` should start from the superclass of
the `target_class` but if it fails, the look-up for `method_missing`
should start from the class of the receiver.

The following code explains the case:
```ruby
class Bar
  def foo
    super
  end
end

class Foo<Bar
  def method_missing(mid, *)
    p mid
  end
end
```
Foo.new.foo
2017-12-20 19:37:26 +09:00
Yukihiro "Matz" Matsumoto d0f60182af The superclass info should be taken from `TARGET_CLASS(ci->proc).
Not from `ci->target_class` that may be switched using `class_eval` etc.
fix #3899, fix #3906

We found out there is a mruby specific limitation that `super` may be
screwed up when a method is defined in a module and `super` is called
in the block with the target class switched (for example, `super` in
`class_eval` block).  Now we raise `RuntimeError` for such cases.

The following code works in CRuby but not in mruby.
```
module M
  def foo
    "aaa".singleton_class.class_eval{super 2}
  end
end
class Foo
  def foo(*); end
end
class Bar<Foo
  include M
end
Bar.new.foo
```
2017-12-20 10:34:54 +09:00
Yukihiro "Matz" Matsumoto d9049c10fa Merge pull request #3904 from ksss/mruby-method
Add mruby-method
2017-12-18 11:59:36 +09:00
Yukihiro "Matz" Matsumoto bba6c9a1ce Fix descriptor leakage; ref #3903 2017-12-18 11:55:12 +09:00
Yukihiro "Matz" Matsumoto e5056d058a Fix fptr leakage; ref #3903 2017-12-18 11:55:12 +09:00
Yukihiro "Matz" Matsumoto 83d02bcd5a Use _dup2 instead of dup2 on Windows; ref #3903 2017-12-18 11:55:12 +09:00
Yukihiro "Matz" Matsumoto 5e22e8e350 open on Windows takes int 3rd argument instead of mode_t. 2017-12-18 11:15:27 +09:00
ksss c0914dbb65 mruby/data.h doesn't need 2017-12-18 11:11:44 +09:00
Yukihiro "Matz" Matsumoto b4dcb8f286 Use _dup instead of dup on Windows; ref #3903 2017-12-18 11:10:49 +09:00
ksss 615f296fcf Clean up some files and docs 2017-12-18 11:10:10 +09:00
ksss ae786b18d5 Shouldn't use alloca 2017-12-18 11:05:55 +09:00
Yukihiro "Matz" Matsumoto a510564d6d Merge pull request #3903 from ksss/io-dup
Implement IO#initialize_copy
2017-12-18 10:58:12 +09:00
ksss b83ff8ccd8 Add mrbgems/mruby-method
from https://github.com/ksss/mruby-method/commit/0837a0b507a5b4cdf8a1f1039ee371cee4e3b7fb
2017-12-18 10:54:37 +09:00
ksss 35185e69bf Implement IO#initialize_copy 2017-12-17 18:02:37 +09:00
Yukihiro "Matz" Matsumoto ddb1aae41d Need to set ci->proc before calling methods; fix #3902 2017-12-16 09:33:37 +09:00
Yukihiro "Matz" Matsumoto 03614ed918 Need to clear exception handler on return; fix #3898 2017-12-16 09:17:07 +09:00
Yukihiro "Matz" Matsumoto 05129ab9b3 Check if destinations are too distant; fix #3900 fix #3901 2017-12-15 17:57:45 +09:00
Yukihiro "Matz" Matsumoto 7ecb96a00a Merge pull request #3897 from mimaki/initialize-is_socket
Initialized mrb_io.is_socket
2017-12-14 13:58:27 +09:00
Hiroshi Mimaki 41039524a9 Initialized mrb_io.is_socket 2017-12-14 12:36:25 +09:00
Yukihiro "Matz" Matsumoto 5b304c156c On Windows, _S_IREAD and _S_IWRITE is defined in sys/stat.h. 2017-12-14 01:19:44 +09:00
Yukihiro "Matz" Matsumoto 7ac39333b5 Use _open and _close on Windows. 2017-12-14 01:19:21 +09:00
Yukihiro "Matz" Matsumoto ebf49932c7 Merge pull request #3895 from mattn/fix-mkstemp
fix mkstemp implementation for MSVC
2017-12-14 00:46:19 +09:00
Yasuhiro Matsumoto e7e5db51de fix mkstemp implementation for MSVC 2017-12-14 00:43:38 +09:00
Yukihiro "Matz" Matsumoto f0379c8c45 Merge pull request #3892 from mimaki/ipproto-winsock
Use IPPROTO enum values on WinSock.
2017-12-14 00:09:45 +09:00
Yukihiro "Matz" Matsumoto 16e473caad Rename BasicSocket#is_socket= to #_is_socket; ref #3878 2017-12-14 00:07:42 +09:00
Yukihiro "Matz" Matsumoto 69ad12de06 Exclude UNIXSocket tests again; ref #3878 2017-12-14 00:05:23 +09:00
Takeshi Watanabe d2163d13a8 Declare super class in socket.rb. 2017-12-14 00:05:23 +09:00
Takeshi Watanabe 949bf6ca43 Fix socket closing by using closesocket API in windows instead. 2017-12-14 00:05:23 +09:00
Yukihiro "Matz" Matsumoto 2300c9f737 Merge pull request #3893 from mimaki/add-mrbgem-summary
Added mrbgem's summary.
2017-12-14 00:00:10 +09:00
Yukihiro "Matz" Matsumoto dc5de38414 Merge pull request #3894 from mattn/mirb-locale
fix locale message in mirb
2017-12-13 23:11:49 +09:00
Yukihiro "Matz" Matsumoto 1a150a6e48 Merge pull request #3891 from mimaki/set-addrinfo-protocol
Set protocol of AddrInfo
2017-12-13 23:00:25 +09:00
Yasuhiro Matsumoto 0ab9ac6b22 fix locale in mirb 2017-12-13 22:28:18 +09:00
Hiroshi Mimaki 584e4e413a Added mrbgem's summary. 2017-12-13 16:05:06 +09:00
Hiroshi Mimaki 9fac1a3f8b Use IPPROTO enum values on WinSock. 2017-12-13 15:58:23 +09:00
Hiroshi Mimaki 398da99d05 Set protocol of AddrInfo 2017-12-13 14:44:13 +09:00
Yukihiro "Matz" Matsumoto 55fced30cd Use _tempnam instead of tempnam on Windows. 2017-12-13 14:17:49 +09:00
Yukihiro "Matz" Matsumoto a3925f3dec Merge pull request #3889 from mattn/fix-crash
fix crash bug on Windows
2017-12-13 14:10:44 +09:00
Yukihiro "Matz" Matsumoto aec65f2605 Merge pull request #3890 from mimaki/mruby-socket-windows-test
Skip tests on Windows platform
2017-12-13 13:59:28 +09:00
Hiroshi Mimaki 4353623b72 Skip tests on Windows platform 2017-12-13 13:02:59 +09:00
Yasuhiro Matsumoto 6123d653b7 fix crash bug on Windows 2017-12-13 12:48:26 +09:00
Yukihiro "Matz" Matsumoto fa33bd86a8 Remove VC++ compiler warnings. 2017-12-13 11:39:32 +09:00
Yukihiro "Matz" Matsumoto 7d940e3682 Merge pull request #3888 from mattn/fix-locale
fix path locales
2017-12-13 10:24:52 +09:00
Yasuhiro Matsumoto 16c2ac2588 fix path locales 2017-12-13 10:12:59 +09:00
Yukihiro "Matz" Matsumoto e14387440e Skip test/t/float.rb tests; ref #3827 2017-12-13 08:45:46 +09:00
Yukihiro "Matz" Matsumoto 11b6696ce2 Retrieve operands at the beginning of OP_SCLASS. 2017-12-13 08:43:15 +09:00
Yukihiro "Matz" Matsumoto e647b16d1d Should not define Float class in mrblib/00class.rb; ref #3828
Unless it is defined in `numeric.c`.
2017-12-13 08:42:07 +09:00
Yukihiro "Matz" Matsumoto ad06781107 Fixed wrong MRB_WITHOUT_FLOAT condition; ref #3827 2017-12-13 08:38:34 +09:00
Yukihiro "Matz" Matsumoto c66978521d Reduce VC++ type mismatch warnings. 2017-12-13 08:10:35 +09:00
Yukihiro "Matz" Matsumoto 5a5adafabf Merge pull request #3886 from mattn/io-windows
implement popen/flock on Windows
2017-12-13 07:56:24 +09:00
Yasuhiro Matsumoto b07269584c fix build for MSVC 2017-12-13 00:21:30 +09:00
Yasuhiro Matsumoto e0e23b1765 close file descriptors 2017-12-13 00:18:02 +09:00
Yasuhiro Matsumoto 7c8c9f9532 mingw have mkstemp 2017-12-13 00:08:10 +09:00
Yasuhiro Matsumoto 7ff907f680 fix test 2017-12-13 00:07:51 +09:00
Yasuhiro Matsumoto f1ea7a31c0 implement flock on Windows 2017-12-12 23:21:41 +09:00
Yasuhiro Matsumoto df2c3771f8 fix compilation error 2017-12-12 22:39:21 +09:00
Yasuhiro Matsumoto f6f8bb2416 fix compilation error 2017-12-12 22:39:20 +09:00
Yasuhiro Matsumoto 06ec17de60 add definition for pid_t on MSVC 2017-12-12 22:39:19 +09:00
Yasuhiro Matsumoto d549603a8a close handle 2017-12-12 22:39:18 +09:00
Yasuhiro Matsumoto b8ca0b7cd8 implement popen on Windows 2017-12-12 22:39:17 +09:00
Yukihiro "Matz" Matsumoto c863e0dac8 Merge pull request #3885 from Shokuji/cygwin_mruby_io_test
fixed mruby-io so that the test passes on cygwin
2017-12-12 22:34:10 +09:00
Yukihiro "Matz" Matsumoto c6ea948030 Revert "Update .travis.yml to use gcc-6"
This change caused Travis CI errors on OSX.  This reverts
commit c76631d445.
2017-12-12 22:31:14 +09:00
Yukihiro "Matz" Matsumoto 346ebfb0ea Merge pull request #3882 from mattn/fix-filename
use filename in locale
2017-12-12 22:27:25 +09:00
Yukihiro "Matz" Matsumoto 25bee356b1 Merge pull request #3884 from mimaki/mruby-io-test-on-windows
Fixed mruby-io test failure on Windows platform.
2017-12-12 22:21:08 +09:00
Yasuhiro Matsumoto 17cd7a65e7 fix wrong variable name 2017-12-12 18:52:41 +09:00
Yasuhiro Matsumoto bceb6640fa fix compilation error 2017-12-12 18:52:41 +09:00
Yasuhiro Matsumoto 977f79478f use filename in locale 2017-12-12 18:52:40 +09:00
Yukihiro "Matz" Matsumoto bbb0882343 Modifying frozen objects will raise FrozenError.
`FrozenError` is a subclass of `RuntimeError` which used to be
raised.  [Ruby2.5]
2017-12-12 18:41:18 +09:00
Yukihiro "Matz" Matsumoto d4ff92bcf6 Do not use FIXABLE when mrb_int is big enough. 2017-12-12 17:45:15 +09:00
Yukihiro "Matz" Matsumoto 3d98fa2e46 Reduce type mismatch warnings in pack.c. 2017-12-12 17:45:15 +09:00
Yukihiro "Matz" Matsumoto a5b8603aa2 Winsock uses int where UNIX uses size_t. 2017-12-12 17:45:15 +09:00
Yukihiro "Matz" Matsumoto a9e434e69a Merge pull request #3883 from mattn/fix-ssize_t
fix build on mingw
2017-12-12 17:31:26 +09:00
窪山 翔士 e71a6a7b2c fixed mruby-io so that the test passes on cygwin 2017-12-12 17:29:05 +09:00
Hiroshi Mimaki 5ef8f18e9b Fixed mruby-io test failure on Windows platform. 2017-12-12 16:57:13 +09:00
Yasuhiro Matsumoto 99328695e3 fix build on mingw 2017-12-12 16:47:34 +09:00
Yukihiro "Matz" Matsumoto 9c0426c990 Winsock does not provide ssize_t; Use int instead. 2017-12-12 09:52:39 +09:00
Yukihiro "Matz" Matsumoto 2db06c471e Revert "Update .travis.yml"
This reverts commit f73ac4112f.
This change caused Travis errors.
2017-12-12 09:49:26 +09:00
Yukihiro "Matz" Matsumoto 08a508cbee Fixed the mixture of int and long in mruby-pack. 2017-12-12 09:48:53 +09:00
Yukihiro "Matz" Matsumoto 5bf60b4837 Merge pull request #3881 from mame/mrb_without_float-for-mruby-io-and-mruby-pack
Support MRB_WITHOUT_FLOAT to mruby-io and mruby-pack
2017-12-12 07:49:30 +09:00
Yusuke Endoh d96b2c9a76 Support MRB_WITHOUT_FLOAT to mruby-io and mruby-pack 2017-12-12 00:47:56 +09:00
Yukihiro "Matz" Matsumoto 85fc9b88d0 Merge pull request #3880 from mruby/matz-patch-1
Update .travis.yml
2017-12-11 23:23:10 +09:00
Yukihiro "Matz" Matsumoto f73ac4112f Update .travis.yml 2017-12-11 22:17:30 +09:00
Yukihiro "Matz" Matsumoto 0e452a75ac Update .travis.yml 2017-12-11 19:36:52 +09:00
Yukihiro "Matz" Matsumoto b763759972 Reduce VC++ compiler warnings. 2017-12-11 17:22:46 +09:00
Yukihiro "Matz" Matsumoto c76631d445 Update .travis.yml to use gcc-6
The patch is created by @take_cheese in #3872
2017-12-11 17:19:49 +09:00
Yukihiro "Matz" Matsumoto 6d42195fb2 Add enable_sanitizer method for clang and gcc.
The patch is created by @take_cheese in #3872
2017-12-11 17:14:50 +09:00
Yukihiro "Matz" Matsumoto 274884abe5 Reduce VC++ compiler warnings. 2017-12-09 16:14:12 +09:00
Yukihiro "Matz" Matsumoto 761218e70b Skip socket tests on Windows platform.
Some test may be OK but we skip everything as a starting point.
2017-12-09 14:22:53 +09:00
Yukihiro "Matz" Matsumoto b103fa229d File.symlink may not be implemented on some platforms; ref #3877 2017-12-09 14:22:03 +09:00
Yukihiro "Matz" Matsumoto bda273f35d Merge pull request #3877 from bamchoh/patch-3
Skip "File.readlink fails" test on MSVC
2017-12-09 14:16:20 +09:00
Yukihiro "Matz" Matsumoto 6bc38f4637 Merge pull request #3876 from bamchoh/patch-2
Use same format between Fail and Skip
2017-12-09 13:15:10 +09:00
bamchoh 0ded91c806 Skip "File.readlink fails" test on MSVC
When MSVC, "File.readlink fails with non-symlink" test was failed even if raising NotImplementedError
2017-12-09 03:27:05 +09:00
bamchoh 81dc383291 Use same format between Fail and Skip
We can see gem name in skip message by this fix
2017-12-09 02:12:37 +09:00
Yukihiro "Matz" Matsumoto 550c878216 Use RL_READLINE_VERSION to determine rl_free existence; fix #3875 2017-12-08 21:49:12 +09:00
Yukihiro "Matz" Matsumoto e17092debd Merge pull request #3874 from mimaki/fix-mingw-compile-error
Fixed compile error of `mruby-io` gem on MinGW.
2017-12-08 14:34:10 +09:00
Yukihiro "Matz" Matsumoto c47a1984b4 Merge pull request #3873 from take-cheeze/fix_socket_test_leak
Fix memory leak found by leak sanitizer.
2017-12-08 14:33:49 +09:00
Hiroshi Mimaki 7f3bda5653 Fixed compile error of mruby-io gem on MinGW. 2017-12-08 12:58:26 +09:00
Takeshi Watanabe 5de7dc2948 Fix memory leak found by leak sanitizer. 2017-12-08 12:10:28 +09:00
Yukihiro "Matz" Matsumoto 83065df67a Reduce compiler warnings from mruby-io gem. 2017-12-08 10:07:41 +09:00
Yukihiro "Matz" Matsumoto f9d1d72217 Avoid VC++ reserved word template. 2017-12-08 09:55:55 +09:00
Yukihiro "Matz" Matsumoto 36a0b864ba Reduce VC++ compiler warnings. 2017-12-08 09:50:02 +09:00
Yukihiro "Matz" Matsumoto f1207573bd Uninitialized value returned. 2017-12-08 09:50:02 +09:00
Yukihiro "Matz" Matsumoto 6ebcb7417a AppVeyor compile errors resolution. 2017-12-08 09:37:50 +09:00
Yukihiro "Matz" Matsumoto 9df7bceb15 AppVeyor compiler does not proved some POSIX functions.
- `mode_t` by `int`
- `umask` by `_umask`
- `rmdir` by `_rmdir`
- `mkstemp` and `mkdtemp` by using `_mktemp`
2017-12-08 09:19:59 +09:00
Yukihiro "Matz" Matsumoto b724e06cf2 Avoid uninitialized local variables in mruby-pack. 2017-12-07 20:28:30 +09:00
Yukihiro "Matz" Matsumoto bc9e3e6fd0 Add type cast to readline(2) return value. 2017-12-07 20:26:34 +09:00
Yukihiro "Matz" Matsumoto 764a568aa4 Remove unused variable usock from mruby-socket/src/socket.c. 2017-12-07 20:25:40 +09:00
Yukihiro "Matz" Matsumoto ff1194c134 fixup! Fix type casting errors when mruby-socket compiled by C++. 2017-12-07 20:24:13 +09:00
Yukihiro "Matz" Matsumoto a5412d48fd Add 'mrbgems/mruby-pack/' from commit '383a9c79e191d524a9a2b4107cc5043ecbf6190b'
git-subtree-dir: mrbgems/mruby-pack
git-subtree-mainline: 842e6945f2
git-subtree-split: 383a9c79e1
2017-12-07 18:35:09 +09:00
Yukihiro "Matz" Matsumoto 842e6945f2 Fix type casting errors when mruby-socket compiled by C++.
Also `bool` is a reserved word in C++.
2017-12-07 18:23:01 +09:00
Yukihiro "Matz" Matsumoto 73ef548c63 Add 'mrbgems/mruby-socket/' from commit 'ab54185005ec87fe4f5b10df95ad29659884141b'
git-subtree-dir: mrbgems/mruby-socket
git-subtree-mainline: d75266dd1b
git-subtree-split: ab54185005
2017-12-07 18:11:13 +09:00
Yukihiro "Matz" Matsumoto d75266dd1b Add 'mrbgems/mruby-io/' from commit '3c8e1f94c44252c836f79a48bb17726da28e2756'
git-subtree-dir: mrbgems/mruby-io
git-subtree-mainline: 10ed730e4b
git-subtree-split: 3c8e1f94c4
2017-12-07 18:11:06 +09:00
Yukihiro "Matz" Matsumoto 10ed730e4b Cancel df3507660 that does not do any good. 2017-12-07 15:18:41 +09:00
Yukihiro "Matz" Matsumoto cdf173d32c Avoid updating to reallocated stack in OP_RETURN; fix #3870
The code was introduced to address #3175 but it's no longer needed.
2017-12-07 15:05:14 +09:00
Yukihiro "Matz" Matsumoto 0e46b14b9e The ci should not be equal to cibase with OP_R_BREAK; #3871 2017-12-06 17:28:20 +09:00
Yukihiro "Matz" Matsumoto 6975258efd The proc with top-level env must be 'proc-closure'; fix #3871 2017-12-06 17:28:20 +09:00
Yukihiro "Matz" Matsumoto ae44e80668 Limit ecall() depth to 32 (default). 2017-12-06 17:28:20 +09:00
Yukihiro "Matz" Matsumoto b00d45b095 mrb_method_search_vm() should gives the defined class.
Otherwise `super` may call a wrong method.
2017-12-06 17:28:20 +09:00
Yukihiro "Matz" Matsumoto 4a99f4949e Need to set ci->proc when we have RProc structure.
Mentioned in https://qiita.com/bamchoh/items/eabebbbb330cb0e0470a
2017-12-05 11:43:12 +09:00
Yukihiro "Matz" Matsumoto cbb6f29875 Merge pull request #3868 from bamchoh/patch-1
Revise MRB_METHOD_PROC macro's argument
2017-12-05 06:47:22 +09:00
bamchoh 940133b627 Revise MRB_METHOD_PROC macro's argument
I revised MRB_METHOD_PROC macro's argument fn to m.
2017-12-05 01:22:43 +09:00
Yukihiro "Matz" Matsumoto 1fea63429e Some OS uses libedit that does not provide rl_free().
`libedit` is a `readline` compatible library with BSD license.
2017-12-04 11:53:19 +09:00
Yukihiro "Matz" Matsumoto 0b5d97ec42 Need to unshare env stack on break; fix #3866 2017-12-04 10:15:12 +09:00
Yukihiro "Matz" Matsumoto 6f4d4bbcc7 Remove temporary objects from GC arena in `mrb_vformat()'; #3863 2017-12-04 08:56:11 +09:00
Yukihiro "Matz" Matsumoto 5d04e3316b Check if ci->proc is not NULL and MRB_PROC_CFUNC_P(); fix #3867 2017-12-04 08:56:11 +09:00
Yukihiro "Matz" Matsumoto ff8b608c52 Free read lines using the deallocation function from the library.
To avoid potential `malloc/free` mismatch.
2017-12-04 08:56:11 +09:00
Yukihiro "Matz" Matsumoto cd9f53d42e Pop exception objects from the bottom of GC arena; fix #3863 2017-12-04 08:56:11 +09:00
Yukihiro "Matz" Matsumoto c35a402676 The stack shift width should be determined by p->upper; fix #3864
And check required register number from `ci->proc` as well.
The fixes for #3859 and #3862 were incomplete.
2017-12-01 10:01:46 +09:00
Yukihiro "Matz" Matsumoto 86ef9a2806 Avoid calling mrb_env_unshare() when env is NULL.
Small performance improvement by reducing function invocations.
2017-11-30 08:19:38 +09:00
Yukihiro "Matz" Matsumoto 2b9f762ba1 Avoid double free() of env stack; fix #3860
Should turn on `MRB_ENV_STACK_UNSHARED` flag only after env stack
reallocation.  `malloc()` may fail.
2017-11-30 08:17:14 +09:00
Yukihiro "Matz" Matsumoto d3e273ba4e Wrong stack adjustment in ecall() (f35f975 #3859); fix #3862 2017-11-30 08:04:27 +09:00
Yukihiro "Matz" Matsumoto f3279b41e6 Stop infinite recursion in Class#to_s; fix #3861 2017-11-30 07:58:11 +09:00
Yukihiro "Matz" Matsumoto 5f7cdecdc9 Clear c->prev on fiber termination. 2017-11-29 20:25:55 +09:00
Yukihiro "Matz" Matsumoto b746a0f0d2 Need to free contexts when freeing fibers.
Memory leak fixed; ref #3711
2017-11-29 20:24:03 +09:00
Yukihiro "Matz" Matsumoto 9c78a9bfa2 Set MRB_FIBER_TERMINATED flag on exception termination of a fiber. 2017-11-29 20:17:33 +09:00
Yukihiro "Matz" Matsumoto b7c3a876f1 Add most recent call last message to the backtrace. 2017-11-29 16:56:10 +09:00
Yukihiro "Matz" Matsumoto 3e67a116d1 Call all ensure clauses pushed at OP_STOP. 2017-11-29 12:16:16 +09:00
Yukihiro "Matz" Matsumoto afa53809e2 No need to use ecall_adjust(). 2017-11-29 12:15:24 +09:00
Yukihiro "Matz" Matsumoto f35f975d26 Fixed stack address adjustment in ecall(); fix #3859 2017-11-29 12:14:05 +09:00
Yukihiro "Matz" Matsumoto d4fc980527 Need to evaluate ensure clauses at fiber termination. 2017-11-29 11:57:33 +09:00
Yukihiro "Matz" Matsumoto 6bb5ad786c Remove unnecessary code; ref #3711 2017-11-29 11:44:07 +09:00
Yukihiro "Matz" Matsumoto 597149ae23 Change newline style of test/t/lang.rb (from DOS) 2017-11-22 16:10:28 +09:00
Yukihiro "Matz" Matsumoto b4f9b031de Some cosmetic changes 2017-11-22 16:09:50 +09:00
Yukihiro "Matz" Matsumoto 284a1d12ee Provide shortcut comparison methods for numbers for performance. 2017-11-22 15:43:48 +09:00
Yukihiro "Matz" Matsumoto 0ab21a9a5e Stack adjustment should be based on p->upper; fix #3857
It used to be based on `ci->proc` but the callinfo position may be
wrong when `ecall()` is called during stack rewinding from `OP_RETURN`.
2017-11-22 14:05:11 +09:00
Yukihiro "Matz" Matsumoto fbafa78098 Clear ensure stack after calling in OP_EPOP; #3855 3856 2017-11-22 12:22:45 +09:00
Yukihiro "Matz" Matsumoto 4665b07f7b No need to pop ensure stack if eidx is smaller than epos; #3855 #3856 2017-11-22 12:21:24 +09:00
Yukihiro "Matz" Matsumoto fe3ac50845 fixup! Remove fixed argument of ecall(); ref #3855 #3856 2017-11-22 12:20:56 +09:00
Yukihiro "Matz" Matsumoto cb4b042777 Remove fixed argument of ecall(); ref #3855 #3856 2017-11-22 12:19:40 +09:00
Yukihiro "Matz" Matsumoto 393133e741 Should have marked all ensure stack entries; fix #3855 fix #3856 2017-11-22 12:18:20 +09:00
Yukihiro "Matz" Matsumoto 8b7a8978e2 Reduce the size of struct RBreak to reduce memory usage.
The old size of `struct RBreak` was 56 bytes (`MRB_NO_BOXING`)
and it's bigger than other object structures. That increase the
size of `RVALUE` thus increase the total amount of memory consumption.
2017-11-20 18:33:41 +09:00
Yukihiro "Matz" Matsumoto 8f2c62407c Add MRB_METHOD_TABLE_INLINE option.
Now the method tables (in classes/modules and caches) keeps C function
pointers without wrapping in `struct RProc` objects. For the sake of
portability, `mrb_method_t` is represented by the struct and union, but
if the most significant bit of the pointer is not used by the platform,
`mrb_method_t` should be packed in `uintptr_t` to reduce memory usage.

`MRB_METHOD_TABLE_INLINE` is turned on by default for linux.
2017-11-20 18:33:41 +09:00
Yukihiro "Matz" Matsumoto 6c06e77446 Add MRB_METHOD_CACHE description to include/mrbconf.h 2017-11-20 06:04:27 +09:00
Yukihiro "Matz" Matsumoto 6a9efd6849 Invoke mrb_full_gc() before ObjectSpace.count_objects. 2017-11-19 12:19:46 +09:00
Yukihiro "Matz" Matsumoto 9b2454c94d Leave hash->ht to be NULL if initial capacity is zero. 2017-11-19 03:46:58 +09:00
Yukihiro "Matz" Matsumoto 7405821f5a doc/limitaions.md: Remove infinite recursion entry.
It's fixed since 1.3.0
2017-11-18 21:16:22 +09:00
Yukihiro "Matz" Matsumoto 86f9254df0 doc/limitaions.md: Remove Kernel.binding entry.
Since no ISO classes/methods are not provided by mruby, there's
no use mentioning `Kernel.binding` here.
2017-11-18 21:14:19 +09:00
Yukihiro "Matz" Matsumoto 825e93eba4 Assign operands to local variables. 2017-11-18 00:03:59 +09:00
Yukihiro "Matz" Matsumoto 31ce73ddc3 Merge pull request #3853 from ukrainskiysergey/variable_c_cosmetic_changes
Removed useless condition
2017-11-18 00:03:50 +09:00
Ukrainskiy Sergey a2d0ee59c6 Removed useless condition 2017-11-17 22:30:22 +09:00
Yukihiro "Matz" Matsumoto 269f9f2125 Merge pull request #3852 from dabroz/feature-array-transpose
implement Array.transpose
2017-11-17 21:50:34 +09:00
Tomasz Dąbrowski e65fa4d7a2 implement Array.transpose 2017-11-17 12:39:34 +01:00
Yukihiro "Matz" Matsumoto d01003ce3a Merge pull request #3851 from ukrainskiysergey/variable_c_cosmetic_changes
Cosmetic changes in variable.c
2017-11-17 20:04:37 +09:00
Ukrainskiy Sergey ddd32d74e1 Changed the assignment of a variable in variable.c 2017-11-17 19:43:57 +09:00
Ukrainskiy Sergey 74714c8fee Changed numbers to TRUE and FALSE for mrb_bool in variable.c 2017-11-17 19:16:29 +09:00
Yukihiro "Matz" Matsumoto c8da602752 Need to save stack space by number of registers from the current proc,
Not from the execution ensure proc; fix #3849
2017-11-17 01:08:46 +09:00
Yukihiro "Matz" Matsumoto 03a3bd9178 The number of argument should be retrieved by mrb_get_argc; fix #3848
You should not access `mrb->c->ci->argc` directly.
2017-11-13 16:16:38 +09:00
Yukihiro "Matz" Matsumoto c210a8adf9 Fixed wrong stack extend size; fix #3847 2017-11-11 17:55:32 +09:00
Yukihiro "Matz" Matsumoto 181f980b6c Need to clear stack region for local variables in eval; fix #3844 2017-11-10 21:53:12 +09:00
Yukihiro "Matz" Matsumoto 41c8c419cf Use proper target_class to define class/module; fix #3843
The outer class of the class/module definition should be taken from
`MRB_TARGET_CLASS(mrb->c->ci->proc)` not `mrb->c->ci->target_class`
which is the target of constant lookups.
2017-11-09 00:14:21 +09:00
Yukihiro "Matz" Matsumoto f723832ebc Should allocate memory region before updating len; fix #3842
Otherwise half-baked string object will be allocated.
2017-11-08 08:46:55 +09:00
Yukihiro "Matz" Matsumoto 7ae20e0785 Simplify MRB_WITHOUT_FLOAT condtion 2017-11-08 08:45:59 +09:00
Yukihiro "Matz" Matsumoto 37f6e42293 Removed redundant function prototype. 2017-11-04 17:59:00 +09:00
Yukihiro "Matz" Matsumoto d6cb4f9cf2 Merge branch 'pandax381-mrb_without_float' 2017-11-04 12:33:07 +09:00
Yukihiro "Matz" Matsumoto a751f7f196 Make mirb to print warnings; ref #3827 2017-11-04 12:32:34 +09:00
Yukihiro "Matz" Matsumoto fef4b394a7 Avoid compiling fmt_fp.c if MRB_WITHOUT_FLOAT is set; #3827 2017-11-04 12:12:52 +09:00
Yukihiro "Matz" Matsumoto de2363a9f0 Merge branch 'mrb_without_float' of https://github.com/pandax381/mruby into pandax381-mrb_without_float 2017-11-04 11:49:25 +09:00
Yukihiro "Matz" Matsumoto 388d26d770 Reimplement block_given?; ref #3841
Make `block_given?` to search for the top of the scope first.
The top of the scope means either:

* the top method body
* the enclosing class body
* the top-level

The special case is the method defined by `define_method` with a
block as in #3841. In cases like this, the method body (given by
a block) is not considered as the top of the scope. You need to use
`&block` in the block parameter if you want to know if a block is
given to the method.

This commit also changes the behavior of `MRB_PROC_SCOPE` flag.
Now it is only set if the `proc` is either a class body or a method
body defined in Ruby. It is no longer set for a block that given to
`define_method`.
2017-11-04 11:20:04 +09:00
Yukihiro "Matz" Matsumoto ab27abe083 The bidx saved in env may be useless; fix #3841
When `block_given?` is called from a block given to `define_method`
as a method body, the `bidx` may not be within `env` saved closure.
In this case, it causes heap buffer overflow.
2017-11-04 03:01:37 +09:00
YAMAMOTO Masaya 625f9f6fa3 Merge branch 'master' of github.com:mruby/mruby 2017-11-04 01:23:12 +09:00
Yukihiro "Matz" Matsumoto e7fe6ee263 Avoid pointer arithmetic in backtrace.c; #3816 2017-11-04 00:35:50 +09:00
Yukihiro "Matz" Matsumoto 12e38597c8 Always check division-by-zero to avoid undefined behavior; fix #3816
Also removed the code to normalize NaN value for `MRB_NAN_BOXING`.
Tha code was added to fix #1712 but no longer required after 249f05e7d.
2017-11-03 09:35:55 +09:00
Yukihiro "Matz" Matsumoto d489b41c31 Reduce memory leaks from mirb. 2017-11-03 08:24:47 +09:00
Yukihiro "Matz" Matsumoto e4662d77e7 Should not use FSHARED state for string from irep pools; fix #3829
This strings in `irep` pools may be freed forcefully in `mrb_irep_free`.
This commit probably fixes #3817 as well.
2017-11-03 08:24:47 +09:00
Yukihiro "Matz" Matsumoto 13a318b0c7 Merge pull request #3840 from iij/keep-backtrace-rethrown-exc
don't strip away backtrace info when an exception is re-thrown
2017-11-02 21:36:26 +09:00
Tomoyuki Sahara f6896751b4 don't overwrite backtrace info. 2017-11-02 15:44:05 +09:00
Yukihiro "Matz" Matsumoto ddfb24908c Fixed constant (and class variable) reference bug; fix #3839
Unlike method definition, constant reference should start from
`MRB_PROC_TARGET_CLASS(ci->proc)`, not `ci->target_class`.
In addition, `MRB_PROC_TARGET_CLASS(ci->proc)` is always set.
2017-10-31 09:10:08 +09:00
Yukihiro "Matz" Matsumoto 022570ab8d Call stack may not reference the destination proc; fix #3838
The destination `proc` may be an orphan.
2017-10-31 09:10:08 +09:00
Yukihiro "Matz" Matsumoto b6598e052f Need to mark fibers referenced from env; fix #3837
The issue #3837 is a regression of #3819. I was mistakenly removed
a important code to mark fibers from `env`.
2017-10-31 09:10:08 +09:00
Yukihiro "Matz" Matsumoto 77edafb04c Need to check number of argument of Struct#new; fix #3823 2017-10-29 00:25:45 +09:00
Yukihiro "Matz" Matsumoto 59dc7d0763 Removed a debug printf; fix #3834 2017-10-28 23:39:21 +09:00
Yukihiro "Matz" Matsumoto 1b45e034ba Remove one of the lines that did the same thing; fix #3836
The change is suggested by `ukrainskiysergey` in #3836.
I deleted the other line for clarity. I also updated comment lines.
2017-10-28 23:35:01 +09:00
Yukihiro "Matz" Matsumoto 6316e0c75d Should clear ensure stack at OP_RETURN break; #3715
This is a resurrection of d0a7e01, which is accidentally
removed by 93f5f22; Fix #3715
2017-10-28 23:27:07 +09:00
Yukihiro "Matz" Matsumoto 92e24f809b Should check if callinfo stack is popped before updating the stack.
This is a resurrection of 75c374c, which is accidentally removed by
93f5f22; Fix #3507 #3512 #3518 #3521
2017-10-28 23:10:28 +09:00
Yukihiro "Matz" Matsumoto c7c9543bed Fixed UPVAR gotchas; fix #3835
Both `uvenv` function and `env` generation in `create_proc_from_string`
function have bugs to handling enclosed environment objects.
2017-10-28 23:08:31 +09:00
Yukihiro "Matz" Matsumoto 57dad6e3fd Remove a debug variable 2017-10-28 01:37:51 +09:00
Yukihiro "Matz" Matsumoto 23d18bbd62 Add parentheses to pacify a warning. 2017-10-28 01:32:25 +09:00
Yukihiro "Matz" Matsumoto 93f5f22577 Heavily refactored how lexical scope links are implemented; fix #3821
Instead of `irep` links, we added a `upper` link to `struct RProc`.
To make a space for the `upper` link, we moved `target_class` reference.
If a `Proc` does not have `env`, `target_class` is saved in an `union`
shared with `env` (if a `Proc` has env, you can tell it by `MRB_PROC_ENV_P()).
Otherwise `target_class` is referenced from `env->c`. We removed links
in `env` as well.

This change removes 2 members from `mrb_irep` struct, thus saving 2
words per method/proc/block. This also fixes potential memory leaks
due to the circular references caused by a link from `mrb_irep`.
2017-10-28 00:29:30 +09:00
Yukihiro "Matz" Matsumoto 3f9d00ded3 comment out bench build from standard build_config.rb 2017-10-28 00:29:30 +09:00
Yukihiro "Matz" Matsumoto 4614b9d632 remove inline from replacement memcpy&memset 2017-10-28 00:29:30 +09:00
Yukihiro "Matz" Matsumoto 5405b47f41 Update test for Kernel#local_variables 2017-10-28 00:29:30 +09:00
Yukihiro "Matz" Matsumoto 14877469d1 Remove MRB_API from mrb_env_unshare() 2017-10-28 00:29:30 +09:00
Yukihiro "Matz" Matsumoto 07cf7b16f3 Add some peephole optimizations 2017-10-28 00:29:30 +09:00
Yukihiro "Matz" Matsumoto 6c966a1f86 Change the order of "expected" and "actual" in test 2017-10-28 00:29:30 +09:00
Yukihiro "Matz" Matsumoto 0cf5a0ee37 Use alias to implement attr method 2017-10-28 00:29:30 +09:00
Yukihiro "Matz" Matsumoto fda64be996 Flush stdout after every print from tests 2017-10-28 00:29:30 +09:00
Yukihiro "Matz" Matsumoto 71eeb86a99 Format codedump for OP_{LE,LT,GE,GT}. 2017-10-28 00:29:30 +09:00
Yukihiro "Matz" Matsumoto d08205b40d Merge pull request #3833 from bggd/appveyor_winbison_ruby24
Appveyor Improvements
2017-10-25 00:31:44 +09:00
bggd 7f4cc0de51 Turn on method cache for AppVeyor CI 2017-10-24 21:39:05 +09:00
bggd 7a13e89509 Use Ruby 2.4 instead of AppVeyor's Default(Ruby 1.9) 2017-10-24 21:37:36 +09:00
bggd 8a9b6c4352 Use win_bison instead of Cygwin's bison. Use YACC environment variable instead of global PATH 2017-10-24 21:31:37 +09:00
Yukihiro "Matz" Matsumoto 0c3ee0ba66 Add `Array#{permutation,combination}. 2017-10-20 10:38:58 +09:00
Yukihiro "Matz" Matsumoto f2394859e3 Add main.define_method 2017-10-19 10:39:06 +09:00
Tomoyuki Sahara 3c8e1f94c4 Merge pull request #94 from kazuho/kazuho/rename-compatibility
make `rename` behavior consistent with MRI
2017-10-18 13:22:22 +09:00
Yukihiro "Matz" Matsumoto fc930700b7 Add Kernel#itself; CRuby2.2 2017-10-18 10:21:54 +09:00
Yukihiro "Matz" Matsumoto ce916b99b8 Add Hash#to_proc; CRuby2.3 2017-10-18 10:18:43 +09:00
Yukihiro "Matz" Matsumoto b5dfbce767 Add Numeric#{positive?,negative?}; CRuby2.3 2017-10-18 10:10:37 +09:00
Yukihiro "Matz" Matsumoto 44f07045d1 Add Hash#fetch_values; CRuby2.3 2017-10-18 10:05:39 +09:00
Yukihiro "Matz" Matsumoto 913b83d579 Merge branch 'dabroz-fix-get-argc' 2017-10-17 15:24:00 +09:00
Yukihiro "Matz" Matsumoto 3c20c96f84 Use a new function: mrb_get_argc(); ref #3826 2017-10-17 15:23:32 +09:00
Yukihiro "Matz" Matsumoto b890528a18 Remove mrb_vm_get_argc; ref #3826 2017-10-17 15:22:45 +09:00
Yukihiro "Matz" Matsumoto 344a7ce20c Merge branch 'fix-get-argc' of https://github.com/dabroz/mruby into dabroz-fix-get-argc 2017-10-17 15:07:05 +09:00
Yukihiro "Matz" Matsumoto 4122c320bb Add {String,Symbol}#casecmp?; CRuby2.4 2017-10-17 13:26:37 +09:00
Yukihiro "Matz" Matsumoto db8265f428 Add Comparable#uniq; CRuby2.4 2017-10-17 12:46:51 +09:00
Yukihiro "Matz" Matsumoto 4e365156d1 Add Comparable#clamp; CRuby2.4 2017-10-17 11:19:12 +09:00
Yukihiro "Matz" Matsumoto 061d804a59 Add Numeric#{finite?,infinite?}; CRuby2.4 2017-10-17 11:19:12 +09:00
Yukihiro "Matz" Matsumoto 332d8d2a1c Add String#delete_{prefix,suffix}; CRuby2.5 2017-10-17 11:19:12 +09:00
Yukihiro "Matz" Matsumoto 1519616ecb Add Kernel#yield_self; CRuby2.5 2017-10-17 09:10:13 +09:00
Yukihiro "Matz" Matsumoto c96def7c96 Remove top-level constant lookup; CRuby2.5 2017-10-17 08:45:06 +09:00
Yukihiro "Matz" Matsumoto e59ad60327 do/end blocks to work with rescue/ensure/else; CRuby2.5 2017-10-17 08:17:31 +09:00
Yukihiro "Matz" Matsumoto fb85855fa1 Add more checks before accessing struct pointer; ref #3831 2017-10-17 07:43:35 +09:00
Yukihiro "Matz" Matsumoto be2c1592ed Check struct-array pointer before accessing; fix #3831 2017-10-16 22:53:36 +09:00
Yukihiro "Matz" Matsumoto 1988bec23e Need to adjust the stack length of the top-level environment; fix #3819 2017-10-16 22:35:25 +09:00
Yukihiro "Matz" Matsumoto c3710dbb96 Fix a compile error on zero mrbgem case. 2017-10-16 18:46:15 +09:00
Yukihiro "Matz" Matsumoto 6b0c22e395 Merge pull request #3830 from dearblue/fix-alias-for-struct-accessors
fix alias for Struct accessors
2017-10-16 18:45:52 +09:00
YAMAMOTO Masaya b70d69de09 Support MRB_WIHTOUT_FLOAT to mruby-kernel-ext 2017-10-16 18:15:47 +09:00
YAMAMOTO Masaya 9afd376fa4 Support MRB_WIHTOUT_FLOAT to mruby-object-ext 2017-10-16 18:15:25 +09:00
YAMAMOTO Masaya b0cdb93a3a Support MRB_WIHTOUT_FLOAT to mruby-numeric-ext (test only) 2017-10-16 18:14:34 +09:00
YAMAMOTO Masaya 9c1f21aaa1 Support MRB_WIHTOUT_FLOAT to mruby-string-ext 2017-10-16 18:09:56 +09:00
dearblue 44e2c97152 fix alias for Struct accessors 2017-10-15 23:43:55 +09:00
YAMAMOTO Masaya 5d781312ca Support MRB_WIHTOUT_FLOAT to mruby-sprintf 2017-10-13 16:42:35 +09:00
Yukihiro "Matz" Matsumoto fa974a1f6a Merge pull request #3828 from asfluido/master
Correct a small error in parse.y
2017-10-12 20:19:24 +09:00
Carlo Prelz af3d5d6c8a Correct a small error in parse.y, which causes the reading of unassigned memory (triggers an error when address sanitizer is active) 2017-10-12 09:54:02 +02:00
Kazuho Oku 0d92431061 make the behavior consistent with MRI 2017-10-12 15:23:52 +09:00
YAMAMOTO Masaya 81ea81e05c Fix typo 2017-10-11 19:52:21 +09:00
YAMAMOTO Masaya 3eebe81b35 Upadte AUTHORS 2017-10-11 19:44:34 +09:00
YAMAMOTO Masaya dcd5d0ffec Test for MRB_WITHOUT_FLOAT 2017-10-11 17:58:11 +09:00
YAMAMOTO Masaya acdc2d1f24 Add MRB_WITHOUT_FLOAT 2017-10-11 17:58:11 +09:00
YAMAMOTO Masaya 679dfd75a8 Use division expression instead of some floating point literals 2017-10-11 17:58:11 +09:00
Tomasz Dąbrowski be86d8b45f correctly handle *splat arguments in mrb_get_argc, also add mrb_vm_get_argc and mrb_get_argv
Fixes #3825
2017-10-10 18:40:38 +02:00
Yukihiro "Matz" Matsumoto 80e03f3ffb Merge pull request #3824 from nobu/bug/paren_arg
Bug/paren arg
2017-10-09 12:39:13 +09:00
Nobuyoshi Nakada 82983330a3 Fix parse error on TRICK2013/yhara 2017-10-09 08:56:46 +09:00
Nobuyoshi Nakada 1c2a2827b3 Replace lvar_defined with local_var_p 2017-10-09 08:54:25 +09:00
Tomoyuki Sahara f8121953e7 Merge pull request #92 from palkan/master
Handle shared/frozen strings in IO#sysread
2017-10-05 21:27:58 +09:00
Vladimir Dementyev 43795cb1f1 Remove useless mrb_str_modify 2017-10-05 15:22:57 +03:00
Vladimir Dementyev 4c255c7739 Handle shared/frozen strings in IO#sysread
See https://github.com/mruby/mruby/commit/7edbe428caca6814841195a3f2720745cf04353e
2017-10-05 14:40:43 +03:00
Yukihiro "Matz" Matsumoto c3c882f681 Use uint32_t to avoid signed integer overflow warning; #3816 2017-10-01 17:53:10 +09:00
Yukihiro "Matz" Matsumoto 8c408379aa Add cscope.files to .gitignore. 2017-10-01 16:24:43 +09:00
Yukihiro "Matz" Matsumoto 7edbe428ca Add new type of shared string: RSTR_FSHARED.
`RSTR_FSHARED` use frozen strings as shared body instead of
`struct mrb_shared_string`. This reduces allocation from
literal strings.
2017-10-01 16:24:43 +09:00
Yukihiro "Matz" Matsumoto 473b7d0efd Cut links from irep in heaps finalization. 2017-09-29 00:18:55 +09:00
Yukihiro "Matz" Matsumoto 7b01b969f5 codedump to display OP_CALL. 2017-09-29 00:18:55 +09:00
Yukihiro "Matz" Matsumoto 29a9e698e3 Merge pull request #3815 from dabroz/fix-warnings
Fix MSVC 14.0 warnings
2017-09-29 00:18:39 +09:00
Tomasz Dąbrowski 999ce87129 fix: src\vm.c(2631): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 77d6a953ff fix: src\vm.c(1757): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski ebd45b1072 fix: src\vm.c(1744): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 0bff4b6a09 fix: src\vm.c(1702): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 885916c84b fix: src\vm.c(708): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski e88fc10679 fix: src\vm.c(704): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski ec7f478eda fix: src\vm.c(457): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 67ab8406b8 fix: src\vm.c(445): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 23cc698134 fix: src\vm.c(438): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 5ede90cdf4 fix: src\vm.c(438): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 53f934a7ee fix: src\string.c(2219): warning C4244: 'function': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski ef8df492e9 fix: src\string.c(1924): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 027b8d8377 fix: src\string.c(1130): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 46ccabacf0 fix: src\string.c(497): warning C4244: '=': conversion from 'mrb_int' to 'long', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 6cde950017 fix: src\state.c(66): warning C4200: nonstandard extension used: zero-sized array in struct/union 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 0e2976bf93 fix: src\range.c(136): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski b7e71e4cef fix: src\proc.c(96): warning C4244: 'function': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 490de9dbe1 fix: src\print.c(22): warning C4244: 'initializing': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 220c628210 fix: src\pool.c(33): warning C4200: nonstandard extension used: zero-sized array in struct/union 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski f0c1074b07 fix: src\numeric.c(1215): warning C4244: 'function': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 4a0c9c9e31 fix: src\numeric.c(954): warning C4334: '<<': result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?) 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 332a04af73 fix: src\numeric.c(897): warning C4244: 'function': conversion from 'mrb_int' to 'mrb_float', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 971a4f9122 fix: src\kernel.c(874): warning C4244: 'function': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 0e0c96096d fix: src\kernel.c(861): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 7d98055862 fix: src\hash.c(139): warning C4244: 'function': conversion from 'mrb_int' to 'khint_t', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 8cef3f946c fix: src\hash.c(40): warning C4244: '=': conversion from 'mrb_int' to 'khint_t', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski 3e1d60ae0b fix: src\hash.c(27): warning C4244: '=': conversion from 'mrb_int' to 'khint_t', possible loss of data 2017-09-27 22:22:05 +02:00
Tomasz Dąbrowski c7b663f2cf fix: src\gc.c(1425): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski b406e9f795 fix: src\gc.c(1392): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski 1dcf8ba488 fix: src\gc.c(559): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski 7a2391b120 fix: src\error.c(76): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski 4d6b8dbcb9 fix: src\dump.c(710): warning C4244: 'function': conversion from 'mrb_int' to 'uint16_t', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski f4a17dd7b5 fix: src\dump.c(657): warning C4244: 'function': conversion from 'mrb_int' to 'uint16_t', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski 5ed76e381c fix: src\class.c(949): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski 9c5db48d1f fix: src\class.c(949): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski d8b37d0381 fix: src\class.c(583): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski 4146b5c2b5 fix: src\backtrace.c(83): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski 7507d46992 fix: src\array.c(86): warning C4244: '=': conversion from 'mrb_int' to 'uint32_t', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski be81504770 fix: mrbgems\mruby-time\src\time.c(641): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski 0848407ee5 fix: mrbgems\mruby-time\src\time.c(372): warning C4244: 'function': conversion from 'mrb_int' to 'double', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski d713f8d761 fix: mrbgems\mruby-test\driver.c(67): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski 2640896911 fix: mrbgems\mruby-string-ext\src\string.c(49): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski 8d816fa142 fix: mrbgems\mruby-string-ext\src\string.c(30): warning C4244: '=': conversion from 'mrb_int' to 'long', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski d3819620ce fix: mrbgems\mruby-string-ext\src\string.c(38): warning C4244: '=': conversion from 'mrb_int' to 'char', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski a94525d4ea fix: mrbgems\mruby-sprintf\src\sprintf.c(1052): warning C4244: '+=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski 1e2c962fa5 fix: mrbgems\mruby-sprintf\src\sprintf.c(623): warning C4244: 'function': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski 897eabb1bb fix: mrbgems\mruby-sprintf\src\sprintf.c(646): warning C4244: 'function': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski e10b329fa3 fix: mrbgems\mruby-sprintf\src\sprintf.c(618): warning C4244: 'initializing': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski 861077f779 fix: mrbgems\mruby-sprintf\src\sprintf.c(516): warning C4244: 'function': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski 553dbad2c6 fix: mrbgems\mruby-math\src\math.c(660): warning C4244: 'function': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski 49e96a2e19 fix: mrbgems\mruby-math\src\math.c(491): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski 536b95eb48 fix: mrbgems\mruby-kernel-ext\src\kernel.c(114): warning C4244: 'function': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski 9d89f8c00b fix: mrbgems\mruby-fiber\src\fiber.c(215): warning C4244: '=': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski 377d6a47ac fix: mrbgems\mruby-exit\src\mruby-exit.c(10): warning C4244: 'function': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 22:22:04 +02:00
Tomasz Dąbrowski f632baddb1 fix: mrbgems\mruby-eval\src\eval.c(301): warning C4244: 'function': conversion from 'mrb_int' to 'int', possible loss of data 2017-09-27 14:42:27 +02:00
Tomasz Dąbrowski 49db1db81f fix: mrbgems\mruby-eval\src\eval.c(214): warning C4244: '=': conversion from 'mrb_int' to 'short', possible loss of data 2017-09-27 14:42:27 +02:00
Tomasz Dąbrowski 2e239a296e fix: mrbgems\mruby-compiler\core\parse.y(3455): warning C4244: 'function': conversion from 'intptr_t' to 'int', possible loss of data 2017-09-27 14:42:27 +02:00
Tomasz Dąbrowski f1a02dff58 fix: include\mruby/gc.h(43): warning C4200: nonstandard extension used: zero-sized array in struct/union 2017-09-27 14:42:27 +02:00
Yukihiro "Matz" Matsumoto 381850280c The [] special method call should be able to take a block. 2017-09-25 20:44:50 +09:00
Yukihiro "Matz" Matsumoto e98823f189 The lex_state after literals should be EXPR_ENDARG. 2017-09-25 20:44:04 +09:00
Yukihiro "Matz" Matsumoto e01d35ef79 The symbols should not take brace blocks. 2017-09-25 20:22:36 +09:00
Yukihiro "Matz" Matsumoto 298177fd6a Merge pull request #3813 from dabroz/feature-fix-date
Change DISABLE_STDIO to MRB_DISABLE_STDIO in mruby-time/time.c
2017-09-25 20:19:13 +09:00
Tomasz Dabrowski e00b48be4a change DISABLE_STDIO to MRB_DISABLE_STDIO in mruby-time/time.c 2017-09-25 13:11:20 +02:00
Yukihiro "Matz" Matsumoto 7450a774a5 The first instruction was skipped mistakenly in ensure clause; fix #3811 2017-09-23 10:12:04 +09:00
Yukihiro "Matz" Matsumoto 0ceaa0960a OP_EPOP operand may be bigger than mrb->c->eidx; fix #3810 2017-09-22 13:00:58 +09:00
Yukihiro "Matz" Matsumoto 5760226e71 Remove temporary limitation of OP_EPOP.
After f68f5f6, the operand of `OP_EPOP` should have been `1`.
Now we have removed the limitation.
2017-09-12 12:41:02 +09:00
Tomoyuki Sahara ab54185005 receiver variables must be "mrb_int" for mrb_get_args("i").
Otherwise, it can cause a segfault on the platforms where the
size of "int" and "mrb_int" differs.
2017-09-12 12:32:12 +09:00
Tomoyuki Sahara a809d42f5a remove whitespaces at the end of line. 2017-09-12 11:43:21 +09:00
Yukihiro "Matz" Matsumoto d6e41c3e51 The callinfo stack may be reallocated in cipush; fix rest of #3809
fix #3809
2017-09-11 23:13:47 +09:00
Yukihiro "Matz" Matsumoto 3d8c1a7e97 The ensure stack may be empty at OP_EPOP; fix 1st part of #3809 2017-09-11 22:46:34 +09:00
Yukihiro "Matz" Matsumoto 2a1e616e4d Avoid calling mrb_funcall to invoke #initialize from Class.new.
If `#initialize` is implemented in C, we don't need stack consuming
`mrb_funcall`.
2017-09-06 14:35:24 +09:00
Yukihiro "Matz" Matsumoto cbfa2b3588 Avoid recursion from mark_context(). 2017-09-05 21:13:16 +09:00
Yukihiro "Matz" Matsumoto f68f5f6b97 Avoid crossing C function boundary from OP_EPOP; ref #3789 2017-09-05 21:12:36 +09:00
Yukihiro "Matz" Matsumoto 7f4b57bb20 Restrict OP_EPOP operand to 1; ref #3789 2017-09-05 21:11:41 +09:00
Tomoyuki Sahara 15f4bdb529 Merge pull request #37 from udzura/fix-types
Fix type int to mrb_int
2017-09-04 23:55:37 +09:00
Uchio KONDO 5b6e4eda2a Fix type int to mrb_int
- mruby's default int size is changed after: https://github.com/mruby/mruby/commit/f0f4a1088a270e339407a24ffe8be748f4764fc2
- implicit cast causes some errors
2017-09-04 16:33:57 +09:00
Yukihiro "Matz" Matsumoto 3acaa44a70 Restructure irep->outer chain; fix #3804
Instead of `irep -> proc` chain, we use `irep -> irep` chain to
avoid GC bugs like #3804. We added `target_class` reference to
`mrb_irep` struct. That means one more word consumption per `irep`.
2017-09-04 06:51:31 +09:00
Yukihiro "Matz" Matsumoto 8a5d783f2e Call initialize only when it's not empty. 2017-09-04 06:49:05 +09:00
Yukihiro "Matz" Matsumoto 5d7e4957e0 Merge pull request #3806 from flaviommedeiros/master
Trying to make the code more readable
2017-09-03 07:51:12 +09:00
Yukihiro "Matz" Matsumoto da97715e11 Merge pull request #3805 from fl0l0u/patch-1
Update print.c
2017-09-03 07:48:33 +09:00
fl0l0u e03042ec19 Update print.c
Strings not containing a newline are not printed synchronously
ex. bin/mruby -e '["a", "b", "c", "\n", "d", "e", "f", "\n"].each {|e| print e ; usleep 200000}'
2017-09-02 18:26:50 +02:00
Flavio Medeiros 9f677b72db Trying to make the source code more understandable by removing mixing of ternary if statements with attributions. 2017-09-02 13:25:09 -03:00
Yukihiro "Matz" Matsumoto 476af3c647 Merge pull request #3802 from christopheraue/proc_break_tests
Tested local jump errors caused by break in a proc
2017-09-02 22:19:15 +09:00
Yukihiro "Matz" Matsumoto ab99e2c293 Avoid copying over initialized procs using initialize_copy; fix #3803
It may be better to raise exceptions, but CRuby doesn't.
2017-09-01 06:51:59 +09:00
Yukihiro "Matz" Matsumoto 57610091ce Update method cache clearing. 2017-09-01 06:51:59 +09:00
Yukihiro "Matz" Matsumoto f0f4a1088a Make the default integer size to be MRB_INT64 on 64bit systems; close #3800
Unless `MRB_NAN_BOXING` is specified.
2017-09-01 06:51:59 +09:00
Christopher Aue 35deaae776 Tested LocalJumpErrors caused by break in a proc 2017-08-30 12:25:55 +02:00
Yukihiro "Matz" Matsumoto 71357ff1d8 Merge pull request #3801 from christopheraue/assert_raise_refactoring
Allowed to pass multiple exceptions to assert_raise
2017-08-30 18:56:59 +09:00
Christopher Aue bf32265743 Allowed to pass multiple exceptions to assert_raise 2017-08-30 11:03:51 +02:00
Yukihiro "Matz" Matsumoto fe3227cd5c Set the ORPHAN flag in Proc.new; fix #3798 2017-08-30 16:51:40 +09:00
Yukihiro "Matz" Matsumoto 483a038d39 Fixed a critical typo; ref #3798 2017-08-30 16:51:17 +09:00
Yukihiro "Matz" Matsumoto 2c85213298 Need to mark mrb->range_class; fix #3797 2017-08-30 16:12:12 +09:00
Yukihiro "Matz" Matsumoto 79b4f61b02 Merge pull request #3799 from christopheraue/assert_raise_refactoring
Refactored #assert_raise and #assert_nothing_raised
2017-08-30 14:47:12 +09:00
Christopher Aue 4b0b8f7e1a Refactored #assert_raise and #assert_nothing_raised 2017-08-29 23:25:53 +02:00
Yukihiro "Matz" Matsumoto 8976f47e0a Need to update ci after callinfo stack reallocation; fix #3796 2017-08-29 11:06:34 +09:00
Yukihiro "Matz" Matsumoto c082249838 Exclude the top-level closure from each_object; fix #3793 2017-08-29 09:29:14 +09:00
Yukihiro "Matz" Matsumoto 786cbf06c3 Revert "Clear irep->outer when no Proc reference the irep; fix #3793"
This reverts commit 15d48efa4b.
2017-08-29 09:27:45 +09:00
Yukihiro "Matz" Matsumoto 1260d3b68a Add `__ENCODING__' support.
`__ENCODING__' returns the current encoding name (string), unlike
CRuby that returns the encoding object.
2017-08-28 22:42:06 +09:00
Yukihiro "Matz" Matsumoto f1fa5bf1c6 Remove integer type mismatch warnings from parse.y. 2017-08-28 22:31:02 +09:00
Yukihiro "Matz" Matsumoto 15d48efa4b Clear irep->outer when no Proc reference the irep; fix #3793 2017-08-28 10:06:04 +09:00
Yukihiro "Matz" Matsumoto fd927d786e Merge pull request #3795 from christopheraue/array_refactoring
Array refactorings and speed improvements
2017-08-27 08:56:41 +09:00
Christopher Aue c956e17c02 Replaced Array#each with while loop for performance reasons
Example benchmark:
$ time build/bench/bin/mruby -e "Array.new(2_000_000){ |i| i }.index{ |i| i == 1_999_999 }"

Before:
real    0m0.934s
user    0m0.922s
sys     0m0.003s

After:
real    0m0.590s
user    0m0.583s
sys     0m0.007s
2017-08-26 15:57:25 +02:00
Christopher Aue 6c9013e22b Removed unneeded block check in Array#uniq 2017-08-26 15:57:25 +02:00
Christopher Aue f3fb43c729 Reimplemented Array#flatten with #flatten! 2017-08-26 15:57:25 +02:00
Yukihiro "Matz" Matsumoto ccd555421a Merge pull request #3794 from dabroz/fix-flt-epsilon
Fix building with MRB_USE_FLOAT=1
2017-08-26 22:29:00 +09:00
Tomasz Dąbrowski 01b9b71902 fix mrbgems/mruby-range-ext/src/range.c:142:71: error: use of undeclared identifier 'FLT_EPSILON' 2017-08-26 12:11:57 +02:00
Yukihiro "Matz" Matsumoto 85a400e43d Reimplement Array#shift to be faster. 2017-08-26 02:03:21 +09:00
Yukihiro "Matz" Matsumoto cec53ff77e Array#first to treat 1 argument case specially to improve performance. 2017-08-26 02:03:21 +09:00
Yukihiro "Matz" Matsumoto 1b545a6b63 Check for ability to skip optional argument parsing. 2017-08-26 02:03:21 +09:00
Yukihiro "Matz" Matsumoto 60104ce41d Silence compiler warning regarding float condition; fix #3790 2017-08-26 02:02:45 +09:00
Yukihiro "Matz" Matsumoto 43ec918be1 Remove unused mrb_obj_iv_ifnone() from API. 2017-08-26 02:01:50 +09:00
Yukihiro "Matz" Matsumoto 0e10a23d7a Add checks if iv_tbl is NULL. 2017-08-26 02:01:50 +09:00
Yukihiro "Matz" Matsumoto 0c52112dd4 Keep Range class in mrb_state structure for performance. 2017-08-26 02:01:50 +09:00
Yukihiro "Matz" Matsumoto 04dbbff3c1 Use khash for instance variables tables instead of segment list.
For performance reason. Segmented list consumes slightly less memory
but takes a lot of time especially when there are many slots in the
segment lists (e.g. class constants).
2017-08-26 02:01:50 +09:00
Yukihiro "Matz" Matsumoto f2cc1239a5 Turn on method cache for Travis CI. 2017-08-26 02:01:50 +09:00
Yukihiro "Matz" Matsumoto f7f1aca8b5 Merge pull request #3792 from dabroz/fix-test-int16
Fix string test with 16-bit integers
2017-08-26 02:00:30 +09:00
Yukihiro "Matz" Matsumoto 5f2c7e47bb Merge pull request #3791 from dabroz/fix-msvc-warning
Fix MSVC warnings in fmt_fp.c
2017-08-26 01:54:59 +09:00
Tomasz Dąbrowski 17c249780f fix String#% %d test with MRB_INT16 set 2017-08-25 14:36:05 +02:00
Tomasz Dąbrowski 5d9b84ef40 fix fmt_fp.c(329) : warning C4244: 'return' : conversion from 'ptrdiff_t' to 'int', possible loss of data 2017-08-25 14:18:31 +02:00
Tomasz Dąbrowski 78b13b3955 fix fmt_fp.c(251) : warning C4244: '=' : conversion from '__int64' to 'int', possible loss of data 2017-08-25 14:18:05 +02:00
Tomasz Dąbrowski ef6a762d41 fix fmt_fp.c(224) : warning C4244: '=' : conversion from 'ptrdiff_t' to 'int', possible loss of data 2017-08-25 14:14:17 +02:00
Tomasz Dąbrowski bac37a9f1a fix fmt_fp.c(220) : warning C4244: '=' : conversion from '__int64' to 'int', possible loss of data 2017-08-25 14:13:06 +02:00
Tomasz Dąbrowski b2a16d6bf7 fix fmt_fp.c(206) : warning C4244: 'initializing' : conversion from 'ptrdiff_t' to 'int', possible loss of data 2017-08-25 14:12:08 +02:00
Tomasz Dąbrowski c8341dbf7c fix fmt_fp.c(178) : warning C4244: 'return' : conversion from 'ptrdiff_t' to 'int', possible loss of data 2017-08-25 14:10:43 +02:00
Tomasz Dąbrowski 5d099e40e6 fix fmt_fp.c(123) : warning C4244: 'return' : conversion from 'ptrdiff_t' to 'int', possible loss of data 2017-08-25 14:10:24 +02:00
Yukihiro "Matz" Matsumoto 63f10a1ee5 Merge pull request #3788 from christopheraue/fix_codegen_op_send_nregs
Fixed register windows of OP_SENDs generated during codegen
2017-08-24 14:38:03 +09:00
Christopher Aue 3366894a40 Fixed register windows of OP_SENDs generated by NODE_{DREGX,REGX}; ref #3783 2017-08-23 18:16:05 +02:00
Christopher Aue 499498a6a7 Tested register windows of OP_SENDs generated by NODE_{DXSTR,XSTR}; ref #3783 2017-08-23 18:15:54 +02:00
Christopher Aue 84d8ecc1d7 Fixed register windows of OP_SENDs generated by NODE_OP_ASGN; ref #3783 2017-08-23 18:15:44 +02:00
Christopher Aue 4aca9ef98e Refactored code around generation of OP_SEND in NODE_OP_ASGN 2017-08-23 18:15:38 +02:00
Christopher Aue 1221f7676e Fixed register windows of OP_SENDs generated by NODE_{FOR,SYMBOLS}; ref #3783 2017-08-23 18:15:27 +02:00
Christopher Aue c040c8d92b Tested register windows of OP_SENDs generated by NODE_{RESCUE,HASH,ALIAS}; ref #3783 2017-08-23 18:15:08 +02:00
Christopher Aue c6596cf26a Fixed register windows of OP_SENDs generated by NODE_{SCALL,CASE,YIELD,UNDEF}; ref #3783 2017-08-23 18:12:35 +02:00
Christopher Aue 64e5208404 Asserted bidx < ci->nregs for OP_SEND and OP_SUPER 2017-08-23 15:18:06 +02:00
Yukihiro "Matz" Matsumoto 4c9a604877 Added method cache.
To enable method cache, define `MRB_METHOD_CACHE` or
`MRB_METHOD_CACHE_SIZE`. The cache size must be power of 2.
The default cache size is 128.

The measurement:
I measured simple benchmarks found in benchmark/ directory. With
method cache enabled, we gained 6-8% performance improvement, with
97-99% cache hit rate.
2017-08-22 22:17:01 +09:00
Yukihiro "Matz" Matsumoto a65f4dbb32 Remove possible path that leaves a local variable uninitialized. 2017-08-22 15:50:08 +09:00
Yukihiro "Matz" Matsumoto db437b04a4 mrb_obj_respond_to to use mrb_method_search_vm. 2017-08-22 14:23:46 +09:00
Yukihiro "Matz" Matsumoto 0d865a77d5 c (mrbc_context) may be NULL; fix #3787 2017-08-22 09:47:10 +09:00
Yukihiro "Matz" Matsumoto ab3b6dbd2a strlen returns size_t; need to cast before assigning to int. 2017-08-22 08:14:09 +09:00
Yukihiro "Matz" Matsumoto 3f90af6b42 (Try to) fix mixture of int and size_t in UTF-8 conversion.
This only effects VC.
2017-08-22 07:35:51 +09:00
Yukihiro "Matz" Matsumoto a7d611fb23 Reduce signed/unsigned warnings in dump.c 2017-08-19 21:50:36 +09:00
Yukihiro "Matz" Matsumoto 5d0fc7e57a Reduce signed/unsigned warnings in fmt_fp.c 2017-08-19 17:09:30 +09:00
Yukihiro "Matz" Matsumoto 8cea1f8907 Use ptrdiff_t instead of int. 2017-08-19 15:51:08 +09:00
Yukihiro "Matz" Matsumoto a117ec771b Remove mixed signed/unsigned comparison in debug.c. 2017-08-19 14:42:30 +09:00
Yukihiro "Matz" Matsumoto 834523945e Replace stack pop() by push_n(2); pop_n(3); fix #3783
To calculate correct register windows size. The fix was suggested
by Christopher Aue.
2017-08-19 11:56:04 +09:00
Yukihiro "Matz" Matsumoto db098d3e0e Type check before traversing irep->outer; fix #3782 2017-08-19 11:39:42 +09:00
Yukihiro "Matz" Matsumoto 2294ebdd44 Call mrb_full_gc before gc_each_objects; ref #3782
Otherwise dead object may be seen from `#each_object`.
2017-08-19 11:38:11 +09:00
Yukihiro "Matz" Matsumoto 9146d5c34f Zero width unshift should not touch memory; ref #3780 2017-08-19 11:11:26 +09:00
Yukihiro "Matz" Matsumoto 8b3298b2d6 Unshift pointer move size was wrong (not len but alen); fix #3780 2017-08-19 11:08:46 +09:00
Yukihiro "Matz" Matsumoto 29ad0a7964 capacify' for mrb_str_new_capa should not be 0`. 2017-08-18 23:42:34 +09:00
Yukihiro "Matz" Matsumoto a8bd06904d mrb_str_cat: capa should not be zero to avoid infinite loops. 2017-08-18 23:42:34 +09:00
Yukihiro "Matz" Matsumoto a06adb176f mrb_str_cat: capa should be bigger than total. 2017-08-18 23:42:33 +09:00
Yukihiro "Matz" Matsumoto 8b5be554c7 ARY_CAPA handles capacity for embedded arrays by itself. 2017-08-18 23:42:33 +09:00
Yukihiro "Matz" Matsumoto 8fbc4bef55 Reduce signed/unsigned comparison warnings; ref #3785 2017-08-18 22:54:59 +09:00
Yukihiro "Matz" Matsumoto f1767fd079 Separate mrb_str_buf_new and mrb_str_new_capa.
`mrb_str_buf_new` is an old function that ensures capacity size of
`MRB_STR_BUF_MIN_SIZE` minimum. Usually one need to use
`mrb_str_new_capa` instead.
2017-08-18 22:17:48 +09:00
Yukihiro "Matz" Matsumoto 722d123b87 Remove code duplication in mrb_str_concat. 2017-08-18 22:17:48 +09:00
Yukihiro "Matz" Matsumoto 198c898817 Rename mrb_str_concat2 to mrb_str_concat_m.
According to the naming convention a function that implements
a method should be suffixed by `_m`.
2017-08-18 22:17:47 +09:00
Yukihiro "Matz" Matsumoto 4c25738ac7 Merge str_buf_cat and mrb_str_cat. 2017-08-18 22:17:47 +09:00
Yukihiro "Matz" Matsumoto 2adb0c201e Merge pull request #3786 from christopheraue/3784_fix
Reset ci in OP_SUPER after potential realloc
2017-08-18 22:17:33 +09:00
Yukihiro "Matz" Matsumoto 11c3ad999e Merge pull request #3781 from clayton-shopify/fix-hash-compact-bang
Check whether internal khash is initialized in Hash#compact!
2017-08-18 22:13:33 +09:00
Yukihiro "Matz" Matsumoto f229ed917e Merge pull request #3785 from miura1729/original
Improve Array structure
2017-08-18 20:37:31 +09:00
Miura Hideki 75ec86ed00 Improve Array structure 2017-08-18 20:12:00 +09:00
Christopher Aue 6b0860ce61 Reset ci in OP_SUPER after potential realloc 2017-08-18 13:11:08 +02:00
Clayton Smith 5dc688fb12 Check whether internal khash is initialized in Hash#compact! 2017-08-17 12:13:41 -04:00
Yukihiro "Matz" Matsumoto 0789ec71e0 Merge pull request #3779 from christopheraue/vm_refactoring
Some more vm refactorings
2017-08-13 07:11:21 +09:00
Christopher Aue d5ac785b31 Reintroduced not storing converted proc directly in the stack 2017-08-12 23:59:40 +02:00
Christopher Aue 198df61039 Removed unneeded ci->nregs checks in OP_SEND and OP_SUPER
Because of #3504 `ci->nregs = bidx+1` was introduced in b64f08784c.
This led to the follow up error #3551 whose fix introduced the `if (bidx >= ci->nregs)`
check in 071164b799 and the `stack_extend(mrb, ci->nregs)`
in 93d802987e.

Then, the code causing #3504 reappeared again in #3590. The fix for it moved the code
dealing with the block in OP_SUPER from below the `cipush`  to above the `cipush`
in d9fb8b69b0. The `if (bidx >= ci->nregs) { ... }` from
then on works with the original callinfo and not the pushed one. `ci->nregs` needed to
be modified for the pushed one because it is initialized to 0. But for the original ci
it is propertly set and a check is not needed.
2017-08-12 23:27:17 +02:00
Christopher Aue f2d4640998 Extended stack always based on ci->nregs 2017-08-12 14:47:22 +02:00
Christopher Aue 3f591d71c6 Refactored variable usage in OP_SEND and OP_SUPER 2017-08-12 14:31:18 +02:00
Yukihiro "Matz" Matsumoto 8bf492f127 Reduce integer type mismatch warnings in VC. 2017-08-12 09:35:35 +09:00
Yukihiro "Matz" Matsumoto baa5d2e3f7 Remove some empty lines; ref #3778 2017-08-11 22:39:31 +09:00
Yukihiro "Matz" Matsumoto 0828a962c0 Merge pull request #3778 from christopheraue/vm_refactoring
Refactored OP_SEND and OP_SUPER and calculate argc right at the top
2017-08-11 22:38:32 +09:00
Yukihiro "Matz" Matsumoto 42f9af41fb Merge pull request #3777 from christopheraue/super_method_missing_test
Added basic test for calling a missing method through super
2017-08-11 22:35:40 +09:00
Christopher Aue 731dd78aa0 Added basic test for calling a missing method through super 2017-08-11 14:09:22 +02:00
Christopher Aue 58f5115b22 Refactored OP_SEND and OP_SUPER and calculate argc right at the top 2017-08-11 13:42:06 +02:00
Yukihiro "Matz" Matsumoto d077a5f0a6 scan_hex may be used to parse both unicode and hex escape.
The error checks for both usage should be separated; ref #3774
2017-08-11 14:25:02 +09:00
Yukihiro "Matz" Matsumoto 56d4e41d76 Fixed a wrong condition in scan_hex; fix #3774 2017-08-11 14:14:30 +09:00
Yukihiro "Matz" Matsumoto 96d4c2d385 Remove an unused argument from each_backtrace_func. 2017-08-11 13:52:24 +09:00
Yukihiro "Matz" Matsumoto 1d781da8a6 Should not include float.h here. 2017-08-11 13:52:01 +09:00
Yukihiro "Matz" Matsumoto db72cdae28 Merge branch 'christopheraue-super_method_missing_fix' 2017-08-11 13:16:40 +09:00
Yukihiro "Matz" Matsumoto ab39ed4f82 Defer mid update after unshift; ref #3776 2017-08-11 13:15:50 +09:00
Yukihiro "Matz" Matsumoto 9feb069124 Merge branch 'super_method_missing_fix' of https://github.com/christopheraue/mruby into christopheraue-super_method_missing_fix 2017-08-11 13:14:32 +09:00
Yukihiro "Matz" Matsumoto 0ff28c9e60 Silence integer type conversion warnings. 2017-08-11 13:10:31 +09:00
Yukihiro "Matz" Matsumoto ef0b239704 Remove unnecessary inline function ary_elt.
And the function does not conform the naming convention anyway.
2017-08-11 12:57:37 +09:00
Yukihiro "Matz" Matsumoto 67e2dddb82 Remove mrb_ary_len function. Use RARRAY_LEN instead. 2017-08-11 12:52:36 +09:00
Yukihiro "Matz" Matsumoto 8f6b2121d9 Update document comment of array C API functions. 2017-08-11 12:51:45 +09:00
Yukihiro "Matz" Matsumoto 4e2f4f4280 Avoid possible data loss by using ptrdiff_t. 2017-08-11 12:12:11 +09:00
Yukihiro "Matz" Matsumoto ae04005092 The type of ARY_EMBED_LEN should be mrb_int. 2017-08-11 12:09:37 +09:00
Yukihiro "Matz" Matsumoto 3e075a7b6c Should not call to_str in mrb_vformat; fix #3773 2017-08-11 09:21:47 +09:00
Yukihiro "Matz" Matsumoto 68470bef86 Check method existence in `to_enum'; ref #3773 2017-08-11 09:21:09 +09:00
Christopher Aue 2249551c63 Fixed calling missing method through super with 126 args 2017-08-10 23:26:39 +02:00
Yukihiro "Matz" Matsumoto ac42ccc1fc Merge pull request #3772 from vvakame/add2authors
Updated AUTHORS
2017-08-10 09:50:08 +09:00
vvakame a8658b0f2c Updated AUTHORS 2017-08-10 09:21:40 +09:00
Yukihiro "Matz" Matsumoto a7462a7f42 Remove redundant flo_hash function.
`flo_hash` implemented `15.2.8.3.18` but `Kernel#hash` (15.3.1.3.15)
now works for numbers.
2017-08-10 08:47:01 +09:00
Yukihiro "Matz" Matsumoto 3d288ef0d8 Use standard hash functions in mrb_hash_ht_hash_func. 2017-08-10 08:47:01 +09:00
Yukihiro "Matz" Matsumoto 78be0172f7 Normalize float numbers before calculating a hash value. 2017-08-10 08:36:09 +09:00
Yukihiro "Matz" Matsumoto 9826ca54f2 VM stack may be reallocated during mrb_hash_get; fix #3771 2017-08-10 08:21:43 +09:00
Yukihiro "Matz" Matsumoto 9e0c48ddc6 Merge pull request #3770 from christopheraue/tabs_to_spaces
Replaced tabs with spaces
2017-08-10 07:59:49 +09:00
Christopher Aue 2fadddcd20 Replaced tabs with spaces 2017-08-09 21:56:27 +02:00
Yukihiro "Matz" Matsumoto 24c345fe5c Merge branch 'vvakame-add-hash-compact' 2017-08-09 21:21:31 +09:00
Yukihiro "Matz" Matsumoto 6c61a60609 Implement Hash#compact! in C; ref #3769 2017-08-09 21:20:50 +09:00
vvakame 4d46f366ac add method(compact, compact!) and test of Hash to mruby-hash-ext 2017-08-09 19:18:02 +09:00
Yukihiro "Matz" Matsumoto f9c3ebd29d Wrong blkargs pos for vararg; ref #3768 2017-08-09 15:23:20 +09:00
Yukihiro "Matz" Matsumoto 0a61df1c34 The block argument offset saved in the env was wrong; fix #3768
When the method takes variable number of argument (`argc = -1`),
the block argument offset should be `-1` not `0`.
2017-08-09 12:57:55 +09:00
Yukihiro "Matz" Matsumoto 8f62957888 Support break within rescue clauses; fix #3767 ref #3721 2017-08-09 12:25:20 +09:00
Yukihiro "Matz" Matsumoto 66e2928bd4 Float values divided by zero should honor signs; fix #3766
It also fixes unexpected resurrection of #3745 by #3752
2017-08-08 02:13:11 +09:00
Yukihiro "Matz" Matsumoto 8494557006 Set the current pc as the error position in OP_ERR; ref #3765 2017-08-08 01:55:46 +09:00
Yukihiro "Matz" Matsumoto e910cf6169 Check if ptr is NULL before calling memset; fix #3765 2017-08-08 01:54:43 +09:00
Yukihiro "Matz" Matsumoto 1358725738 Merge pull request #3764 from christopheraue/new_hash_perf
Improved speed of creating new hash tables
2017-08-07 01:48:39 +09:00
Christopher Aue ec7475d88b Prevented resizing just created hashes in specific size ranges 2017-08-05 20:59:26 +02:00
Christopher Aue 0e5c3c4ebd Improved speed of creating new hash tables 2017-08-04 22:08:29 +02:00
Yukihiro "Matz" Matsumoto 1b9c4855a3 proc->body.irep may be NULL; fix #3761 2017-08-05 01:28:11 +09:00
Yukihiro "Matz" Matsumoto 006661394d Fixed heap buffer overflow in mrb_ary_unshift_m; fix #3760 2017-08-05 01:18:52 +09:00
Yukihiro "Matz" Matsumoto 36dbfd9bda Change return type of scan_oct from int to int32_t. 2017-08-05 01:06:36 +09:00
Yukihiro "Matz" Matsumoto e86c252a99 Left shift of signed integers is undefined behavior in C; fix #3762 2017-08-05 01:06:36 +09:00
Yukihiro "Matz" Matsumoto 8095754e28 Merge pull request #3763 from mimaki/fix-mrdb-source-path
Fixed a invalid source path name on mruby debugger.
2017-08-04 23:41:14 +09:00
Hiroshi Mimaki 7bdc709da0 Fixed a invalid source path name on mruby debugger. 2017-08-04 17:25:03 +09:00
Yukihiro "Matz" Matsumoto 7b88c1a8e5 Now local_variables works when for closures; fix #3710 2017-08-02 07:44:58 +09:00
Yukihiro "Matz" Matsumoto da24af34b9 Better class name management.
The change removes several internal instance variables used by
class name management. The variables `__classid__` and `__classpath__`
are no longer available. `__outer__` is used only for unnamed outer
classes/modules (and will be removed after they are named).

[Important note]
Along with this change we removed several public functions.

 - mrb_class_outer_module()
 - mrb_class_sym()

We believe no one have used those functions, but if you do, please
ask us for the workaround.
2017-08-01 22:25:49 +09:00
Yukihiro "Matz" Matsumoto 2170fad406 Cosmetic changes (removing spaces before * in return types). 2017-08-01 16:31:18 +09:00
Yukihiro "Matz" Matsumoto 648e9ea51b Move naming unnamed classes/modules
From `mrb_mod_const_set` to `mrb_const_set`.
2017-08-01 16:25:09 +09:00
Yukihiro "Matz" Matsumoto 3f6a098626 Reimplement constant look-up rule to follow lexical scoping.
This update fix CRuby scoping incompatibility; close #600; close #3200
2017-08-01 15:57:32 +09:00
Yukihiro "Matz" Matsumoto 9e10afe1d0 Implements `Module::nesting' (15.2.2.3.2); ref #600, #3200 2017-08-01 15:37:21 +09:00
Yukihiro "Matz" Matsumoto 16aafdd866 Merge pull request #3759 from christopheraue/authors_update
Updated AUTHORS
2017-07-31 07:27:04 +09:00
Yukihiro "Matz" Matsumoto facf5f99d4 Merge pull request #3758 from christopheraue/enumeration_perf
Improved speed of enumeration methods
2017-07-31 07:26:46 +09:00
Christopher Aue a4ff31eaf6 Updated AUTHORS 2017-07-30 16:19:24 +02:00
Christopher Aue 3359b86ec7 Improved speed of enumeration methods 2017-07-30 13:19:31 +02:00
Yukihiro "Matz" Matsumoto c8fdab8725 Merge branch 'udzura-move-task-class-definitions' 2017-07-29 07:15:10 +09:00
Yukihiro "Matz" Matsumoto e821c25d38 Merge branch 'move-task-class-definitions' of https://github.com/udzura/mruby into udzura-move-task-class-definitions 2017-07-29 07:09:53 +09:00
Yukihiro "Matz" Matsumoto b290e98f3b Merge pull request #3757 from christopheraue/module_const_get_class_path
Extended Module#const_get to support class paths
2017-07-29 07:05:37 +09:00
Yukihiro "Matz" Matsumoto cf23a85333 Merge pull request #3755 from christopheraue/array_bsearch_index
Added Array#bsearch_index
2017-07-29 07:01:53 +09:00
Yukihiro "Matz" Matsumoto dda73da640 Merge pull request #3756 from christopheraue/fix_mod_include_ret_val
Fixed return value of Module#include and #prepend
2017-07-29 06:53:06 +09:00
Christopher Aue a3bfd735a0 Added Array#bsearch_index 2017-07-28 23:51:49 +02:00
Christopher Aue 451574f142 Refactored Array#bsearch 2017-07-28 23:51:40 +02:00
Christopher Aue f937af5745 Extended Module#const_get to support class paths 2017-07-28 23:19:49 +02:00
Christopher Aue c7018ea962 Added mrb_str_index to the mrb API 2017-07-28 21:07:20 +02:00
Christopher Aue b499ad6749 Fixed return value of Module#include and #prepend 2017-07-28 17:38:40 +02:00
Christopher Aue 8a6ce74b4d Tested Array#bsearch more thoroughly 2017-07-28 17:15:35 +02:00
Yukihiro "Matz" Matsumoto 4696093673 Rename MRB_SEGMENT_SIZE to MRB_IV_SEGMENT_SIZE. 2017-07-27 16:14:03 +09:00
Yukihiro "Matz" Matsumoto 1e41026b28 Always use MRB_USE_IV_SEGLIST. 2017-07-27 16:14:03 +09:00
Yukihiro "Matz" Matsumoto f26d00d9e8 Embed small size array elements in the heap.
It reduces the memory consumption and sometimes improve the
performance as well.  For example, the consumed memory size
of `bench/bm_ao_render.rb` is reduced from 1.2GB to 1GB, and
its total execution time become 18.795 sec from 22.229 sec.
2017-07-27 16:13:06 +09:00
Yukihiro "Matz" Matsumoto 5d44f8582e Remove loop from OP_POPERR. 2017-07-27 10:30:43 +09:00
Yukihiro "Matz" Matsumoto 7d5cf8749a (0).div(0.0) should be NaN; fix #3754 2017-07-26 15:48:50 +09:00
Yukihiro "Matz" Matsumoto 46ab8fdf07 (0.0).div(0) should not be infinity; fix #3753 2017-07-25 15:28:41 +09:00
Yukihiro "Matz" Matsumoto 9fa3d77114 0/0 should not be infinity; fix #3752 2017-07-25 15:11:31 +09:00
Yukihiro "Matz" Matsumoto 7b8d784040 Reimplement sort method to reduce array copying. 2017-07-25 14:42:38 +09:00
Yukihiro "Matz" Matsumoto 7f9e333647 Should not update @objs from mruby-bin-mruby mrbgem.rake; fix #3751 2017-07-24 16:53:20 +09:00
Yukihiro "Matz" Matsumoto 308341b990 Clear mrb_callinfo struct by zero initializer. 2017-07-24 16:47:11 +09:00
Yukihiro "Matz" Matsumoto 1fc9a3019d Initialize potentially uninitialized local variable. 2017-07-24 16:46:27 +09:00
Yukihiro "Matz" Matsumoto 1c360965e7 Need to unshare env on OP_R_BREAK too. 2017-07-21 10:57:21 +09:00
Yukihiro "Matz" Matsumoto 5fee3f5869 Move NULL check to mrb_env_unshare(); ref #3750 2017-07-21 10:14:15 +09:00
Yukihiro "Matz" Matsumoto e2c9a30571 Should not raise LocalJumpError on funcall'ed frame; fix #3750 2017-07-21 07:17:21 +09:00
Yukihiro "Matz" Matsumoto 04c21d9d6b Merge pull request #3749 from christopheraue/fix_spec_rbfiles
Fixed setting custom rbfiles in gemspec
2017-07-20 23:14:34 +09:00
Yukihiro "Matz" Matsumoto 25a0a6b038 Need to patch OP_GETUPVAR and OP_SETUPVAR; fix #3732 2017-07-20 22:47:20 +09:00
Christopher Aue 5a9eedf541 Fixed setting custom rbfiles in gemspec 2017-07-19 19:46:36 +02:00
Yukihiro "Matz" Matsumoto aa3cb0466e Avoid C undefined behavior of division by zero; close #3745 2017-07-19 09:49:41 +09:00
Yukihiro "Matz" Matsumoto ca2cfc6fe9 Merge pull request #3746 from christopheraue/mod_singleton_class_p
Implemented Module#singleton_class?
2017-07-19 09:08:11 +09:00
Yukihiro "Matz" Matsumoto 645b0fb58c Merge branch 'christopheraue-const_set_mod_to_s' 2017-07-19 09:03:51 +09:00
Yukihiro "Matz" Matsumoto 14a72b0800 Avoid constant-set duplication; ref #3747 2017-07-19 09:03:07 +09:00
Yukihiro "Matz" Matsumoto a8bffdae50 Merge branch 'const_set_mod_to_s' of https://github.com/christopheraue/mruby into christopheraue-const_set_mod_to_s 2017-07-19 08:58:06 +09:00
Christopher Aue 468cc34c93 Fixed Module#to_s and #name for #const_set modules 2017-07-18 22:55:37 +02:00
Christopher Aue dd52b88101 implemented Module#singleton_class? 2017-07-18 20:47:05 +02:00
Yukihiro "Matz" Matsumoto 329938ef15 Simplify mrb_gc_arena_restore() to reduce overhead.
It will no longer shrink arena region. Instead `vm.c` uses
a static function `mrb_gc_arena_shrink()` to shrink.
2017-07-18 23:26:36 +09:00
Yukihiro "Matz" Matsumoto 52aafcd001 Merge pull request #3743 from christopheraue/sprintf_d_tests
added tests for #3736
2017-07-17 09:17:24 +09:00
Yukihiro "Matz" Matsumoto 59eaad9d78 Merge pull request #3742 from christopheraue/iter_exp_tests
added basic tests for while/until/break/next
2017-07-17 09:16:25 +09:00
Christopher Aue 2730231e50 added tests for #3736 2017-07-16 22:34:23 +02:00
Christopher Aue 8fe2a6ce0f added basic tests for while/until/break/next 2017-07-16 22:25:48 +02:00
Yukihiro "Matz" Matsumoto 515a093213 Add Hash#transform_keys! and Hash#transform_values. 2017-07-15 08:51:35 +09:00
Yukihiro "Matz" Matsumoto d7fef24a95 Use keys.each instead of unstable each_keys. 2017-07-15 08:50:52 +09:00
Yukihiro "Matz" Matsumoto 460d628490 Remove duplication in mruby-hash-ext test. 2017-07-14 16:10:26 +09:00
Yukihiro "Matz" Matsumoto 1c02b8558f Avoid duplicated width filling for sprintf %d specifier; fix #3736 2017-07-14 15:21:11 +09:00
Yukihiro "Matz" Matsumoto de3edcc170 Add Hash#transform_{keys,values} to mruby-hash-ext. 2017-07-14 15:13:41 +09:00
Yukihiro "Matz" Matsumoto bad807e7f0 Use floor() to implement round() on WIN32 platform.
This change was suggested by Akira Kakuto.
2017-07-13 20:32:34 +09:00
Yukihiro "Matz" Matsumoto 70e99d6b57 Define round() only on WIN32 platform; fix #3741 2017-07-13 00:09:31 +09:00
Yukihiro "Matz" Matsumoto 7fa9321c18 while|until should have the value from break; fix #3735 2017-07-12 14:56:48 +09:00
Yukihiro "Matz" Matsumoto e5fbe350b3 Avoid float operation to shrink arena buffer size. 2017-07-12 14:52:03 +09:00
Yukihiro "Matz" Matsumoto 9501b18362 Add inline modifier to cipush() and cipop() functions. 2017-07-12 14:50:44 +09:00
Yukihiro "Matz" Matsumoto a18904a4c2 Use "$!" specifier of mrb_get_args. 2017-07-12 14:49:55 +09:00
Yukihiro "Matz" Matsumoto e9b57124a0 Update mrb_get_args() document. 2017-07-12 14:49:06 +09:00
Yukihiro "Matz" Matsumoto adf453a584 Add "*!" argument specifier to avoid stack copying. 2017-07-12 14:48:23 +09:00
Yukihiro "Matz" Matsumoto 059d707e3a Add ary_modify_check() to Array#unshift; ref #3737 2017-07-12 14:44:36 +09:00
Yukihiro "Matz" Matsumoto e1de86134d Merge pull request #3740 from christopheraue/fix_test_output
fixed printing failed assertions
2017-07-12 08:24:02 +09:00
Christopher Aue 495a2e605d fixed printing failed assertions 2017-07-11 12:53:48 +02:00
Yukihiro "Matz" Matsumoto fc666bfe20 POSFIXABLE and NEGFIXABLE should take one argument. 2017-07-11 09:02:24 +09:00
Yukihiro "Matz" Matsumoto 46dee5716f Resurrect POSFIXABLE and NEGFIXABLE; ref 9186828 2017-07-10 09:42:48 +09:00
Yukihiro "Matz" Matsumoto 01fce3dc35 Merge pull request #3739 from ksss/array-shift
Should only check frozen fix #3737
2017-07-09 19:58:11 +09:00
ksss bf48473cf6 Should only check frozen for Array#pop 2017-07-09 18:05:21 +09:00
ksss c76dc33116 Add frozen test for Array#shift 2017-07-09 17:53:12 +09:00
ksss e581f2ed97 Should only check frozen fix #3737 2017-07-09 17:47:10 +09:00
Yukihiro "Matz" Matsumoto ce6c05600a Add fallback definitions of DBL_EPSILPN and LDBL_EPSILON; fix #3733
This is a workaround for mingw-w64 (5.3.1) bug.
2017-07-07 22:47:49 +09:00
Yukihiro "Matz" Matsumoto 718a9ceb6e Reduce allocation size of backtrace arrays. 2017-07-06 09:33:53 +09:00
Yukihiro "Matz" Matsumoto 542f0f7b16 Avoid out-of-bounds access of the backtrace array. 2017-07-06 09:32:28 +09:00
Yukihiro "Matz" Matsumoto 91868286be FIXABLE_FLOAT() fails sometimes in MRB_INT64 environment. 2017-07-06 09:05:46 +09:00
Yukihiro "Matz" Matsumoto cc04f03393 print("%d", 0) should not print -0; fix #3731 2017-07-05 23:31:50 +09:00
Yukihiro "Matz" Matsumoto 2ef5d22b60 Put a space between error position and error message.
For readability's sake.
2017-07-05 18:34:27 +09:00
Yukihiro "Matz" Matsumoto b68e7a605c Negation was not a good way to handle negative integers; fix #3729
There's a number that negation does not work (-2147483648 in 32bit
environment).
2017-07-05 18:13:37 +09:00
Yukihiro "Matz" Matsumoto b643a1a8bc In Ruby, sprintf specifier %u should behave as %d; fix #3730
Since there's no unsigned integer in Ruby. Binary, octal and
hexadecimal negative numbers can be represented by using 2's
compliment. But decimal (not being power of 2) cannot be use
that kind of format.
2017-07-05 17:48:40 +09:00
Yukihiro "Matz" Matsumoto bd66c5d716 Check stack size before accessing env stack; fix #3727 2017-07-05 09:19:06 +09:00
Yukihiro "Matz" Matsumoto cc01dedc65 Avoid undefined behavior of left shifting negative integer; #3728 2017-07-05 03:11:39 +09:00
Yukihiro "Matz" Matsumoto c377d504f6 Avoid undefined behavior of signed integer overflow; fix #3728 2017-07-05 03:11:39 +09:00
Yukihiro "Matz" Matsumoto c6bd8ceab7 Merge pull request #3726 from mruby/stable
mruby-1.3.0
2017-07-04 15:46:38 +09:00
Yukihiro "Matz" Matsumoto e9cdc88008 Refactor sprintf() code. 2017-07-04 08:50:39 +09:00
Yukihiro "Matz" Matsumoto 31bc2b0009 Initialize flags for each loop. 2017-07-04 08:46:33 +09:00
Yukihiro "Matz" Matsumoto 9b8956cdd0 break should not cross fiber-context boundary; fix #3724 2017-07-01 12:45:27 +09:00
Yukihiro "Matz" Matsumoto 7d99830211 super may be called from a block; fix #3723 2017-07-01 12:45:27 +09:00
Yukihiro "Matz" Matsumoto 466a18b0d3 Remove redundant use of Object#to_s in interpolation. 2017-06-28 23:28:24 +09:00
Yukihiro "Matz" Matsumoto aee1476ebd Provide better way to check compile errors.
Now you can just call `mrb_load_*` functions then check
`context->parser_nerr > 0` if the return value is `undef`,
instead of calling `mrb_parse_*` functions independently.
ref #3248 #3331
2017-06-28 16:04:40 +09:00
Yukihiro "Matz" Matsumoto 15945e14b9 Revert "Make mrb_load_exec a static function."
This reverts commit 7944d9a6d4.
Because it voids #3248 and #3331. But we should add better way
to check whether compile errors occur without duplicated callings.
2017-06-28 16:00:59 +09:00
Yukihiro "Matz" Matsumoto f0abd4241f Avoid mrb_funcall() unless absolutely necessary; ref #3722
As a result, `#chr` is not called for ch < 0x80, so we need to
update the "invalid chr" test.
2017-06-28 12:03:53 +09:00
Yukihiro "Matz" Matsumoto 3554a41a54 Remove unnecessary initialization of a local variable. 2017-06-27 22:48:06 +09:00
Yukihiro "Matz" Matsumoto 877e16501c No longer need to copy argv from mrb_get_args; ref #3722 2017-06-27 22:47:26 +09:00
Yukihiro "Matz" Matsumoto 1a3b32343e Copy argv from VM stack to avoid use-after-free; fix #3722 2017-06-27 22:43:37 +09:00
Yukihiro "Matz" Matsumoto b30eba6a13 Make LocalJumpError a subclass of ScriptError.
It's incompatible with CRuby, but it is required for mruby because
it cannot detect `break` outside of loops in the parsing time, but
in the code generation time where it cannot raise `SyntaxError`.
2017-06-23 18:08:38 +09:00
Yukihiro "Matz" Matsumoto d0717efda6 Should raise an exception if break called in ensure; fix #3721 2017-06-23 18:08:04 +09:00
Yukihiro "Matz" Matsumoto 7944d9a6d4 Make mrb_load_exec a static function. 2017-06-23 17:56:12 +09:00
Yukihiro "Matz" Matsumoto 9a59cd7af8 Silence mrbmemcpy and mrbmemset warnings. 2017-06-23 17:54:02 +09:00
Yukihiro "Matz" Matsumoto b200c7475a No need to mark stacks of terminated fibers; fix #3720 2017-06-22 02:05:14 +09:00
Yukihiro "Matz" Matsumoto c41e262667 Add write barrier to protect singleton class from GC; fix #3717 2017-06-22 01:20:22 +09:00
Yukihiro "Matz" Matsumoto af0bef6dd8 Silence rubocop warnings. 2017-06-22 00:27:17 +09:00
Yukihiro "Matz" Matsumoto e8a4e4262a Add write barrier to protect proc reference from fiber; fix #3719 2017-06-21 17:59:14 +09:00
Yukihiro "Matz" Matsumoto 464d3fc0a3 Use alias enum_for to_enum instead of alias :enum_for :to_enum. 2017-06-21 11:13:43 +09:00
Yukihiro "Matz" Matsumoto 057be5ffb5 use unless instead of if not. 2017-06-21 11:13:33 +09:00
Yukihiro "Matz" Matsumoto d0a7e01d9c Should call ecall() before callinfo adjustment; fix #3715 2017-06-21 02:51:55 +09:00
Yukihiro "Matz" Matsumoto bf1cb87b34 Array size can be cause integer overflow; fix #3710 2017-06-20 20:19:37 +09:00
Yukihiro "Matz" Matsumoto 39779b339e Merge pull request #3718 from miura1729/original
#3711 fix
2017-06-20 16:18:07 +09:00
Miura Hideki 0fa94f9ead #3711 fix 2017-06-20 12:50:00 +09:00
Yukihiro "Matz" Matsumoto 615e7e44e3 Avoid using snprintf(3) in case MRB_DISABLE_STDIO; fix #3714 2017-06-20 09:39:33 +09:00
Yukihiro "Matz" Matsumoto 455f3954dc Merge pull request #3713 from Asmod4n/patch-2
Save gc_arena after buffer got allocated
2017-06-20 09:16:38 +09:00
Asmod4n abca63c73b Save gc_arena after buffer got allocated
Latest fix was freeing the buffer while it was still in use.
Fixes #3712
2017-06-19 20:27:38 +02:00
Tomoyuki Sahara 04774e5bf2 remove unused exception variables. 2017-06-15 11:00:26 +09:00
Tomoyuki Sahara 7c62d89348 Merge pull request #88 from christopheraue/master
Fix for IO#read(n) with n > IO::BUF_SIZE
2017-06-15 10:53:01 +09:00
Christopher Aue 3642fe4013 fixed #87: IO#read(n) with n > IO::BUF_SIZE 2017-06-13 21:40:36 +02:00
Tomoyuki Sahara 81a0dcdb7a sizeof(optval) must be 1 for IP_MULTICAST_TTL & IP_MULTICAST_LOOP. fixes #34. 2017-06-13 12:13:04 +09:00
Tomoyuki Sahara fe99819bc9 Merge pull request #85 from ksss/read
Support outbuf argument for IO#read
2017-06-12 16:17:53 +09:00
Tomoyuki Sahara c279f00109 Merge pull request #86 from ksss/write
Reseek when write
2017-06-12 16:15:31 +09:00
Tomoyuki Sahara 0b41066e83 Merge pull request #84 from ksss/pos
To accurate `pos`
2017-06-12 15:43:44 +09:00
ksss 051d7bc8db Reseek when write 2017-06-12 09:57:18 +09:00
ksss 1ebe1c8b1f Support outbuf argument for IO#read 2017-06-12 09:43:02 +09:00
ksss 27f422880f To accurate pos
pos shouldn't cache because it's not controllable
2017-06-11 23:22:04 +09:00
Tomoyuki Sahara 3a73a58493 mruby 1.2.0 assumes test blocks return their results. master does not. 2017-06-07 11:36:37 +09:00
Tomoyuki Sahara 383a9c79e1 Merge pull request #13 from ksss/unpack-utf8
Support unpack template "U"
2017-06-07 11:09:43 +09:00
Tomoyuki Sahara dab87cf960 Merge pull request #80 from ksss/sysread
IO#sysread Check for readable
2017-06-05 16:21:30 +09:00
ksss a3a4f4d061 IO#sysread Check for readable 2017-05-27 13:34:11 +09:00
Tomoyuki Sahara 0c0b34136e Merge pull request #78 from ksss/syswrite
Should raise SyscallError on IO#syswrite
2017-05-23 15:09:04 +09:00
Tomoyuki Sahara 87771ecf92 Merge pull request #79 from ksss/ioerror
Fix some spec for IO#sysread
2017-05-23 15:06:15 +09:00
ksss 0bbd60b523 IO#sysread should raise error when invalid pos 2017-05-22 11:47:45 +09:00
ksss 86edc9ab85 IO#sysread should raise IOError when closed 2017-05-21 22:54:46 +09:00
ksss 844b2c368f IO#sysread with 0 always return empty string 2017-05-21 22:54:12 +09:00
ksss c43795c664 Should raise SyscallError on IO#syswrite
instead of IOError
2017-05-21 17:10:15 +09:00
Tomoyuki Sahara 6836f424c5 "open" error message should include pathname. fixes #77. 2017-05-19 17:14:43 +09:00
Tomoyuki Sahara 728d313b2c Merge pull request #76 from yyamano/issue-75
Make backquote work with the latest mruby. Fixed #75
2017-04-25 11:19:07 +09:00
Yuji Yamano 311f4a230f Make backquote work with the latest mruby. Fixed #75 2017-04-24 02:40:01 -04:00
Tomoyuki Sahara 7e014efe45 Merge pull request #14 from ksss/to_int
Should use `to_int` instead of `to_i`
2017-04-06 10:25:06 +09:00
Uchio KONDO 38db5e550f Some adjustments 2017-04-04 12:16:53 +09:00
Uchio KONDO 9c2db2e134 Move class/module definitions to normal .rb files 2017-04-04 12:03:43 +09:00
Uchio KONDO 86b69d7c5d Initial skelton for class/module def 2017-04-04 11:57:17 +09:00
ksss d83e15e866 Should use to_int instead of to_i
For CRuby compatibility
2017-04-04 11:19:43 +09:00
ksss 0dbd1d5992 Add "U" template to doc 2017-04-04 11:07:15 +09:00
ksss f691a73c26 Should raise RangeError 2017-04-04 11:07:14 +09:00
ksss a80a745b69 Support unpack template "U" 2017-04-04 10:06:30 +09:00
Tomoyuki Sahara f8a3af8086 Merge pull request #74 from iij/run-test-outside-source-tree
run mrbtest outside of source tree.
2017-02-28 12:34:15 +09:00
Tomoyuki Sahara 3ae5fea2b8 run mrbtest outside of source tree. 2017-02-28 12:10:51 +09:00
Tomoyuki Sahara 74fe87c289 Add a travis-ci badge. 2017-02-17 10:33:11 +09:00
Tomoyuki Sahara 86d58a2d37 File class does not have to include Enumerable.
Because IO class, which is the superclass of File class, includes it.
2017-02-10 11:22:52 +09:00
Tomoyuki Sahara 88a7fedea4 support "x". 2017-02-09 11:07:55 +09:00
Tomoyuki Sahara 3dad125a1c TCPSocket.new supports "local_host" and "local_service". 2017-02-08 19:04:11 +09:00
Tomoyuki Sahara caab1c203c define IO#hash to override Enumerable#hash. fixes #73.
Current implementation of Enumerable#hash calls #each to collect
hash values of enumerated objects (then calculates the hash value
of the Enumerable object).  But IO#each is a method to read lines.
It is not expected that IO#hash reads all lines from the IO object.
Or even worse, program waits for the IO object to be readable if
it is a socket or something cannot be read immediately.
2017-02-08 18:31:50 +09:00
Tomoyuki Sahara 69623078a8 Merge pull request #72 from masahino/add_pointer_casting
Add pointer casting
2016-12-26 09:12:19 +09:00
masahino 1fac605e3f Add pointer casting 2016-12-24 23:32:44 +09:00
Tomoyuki Sahara 458b517c6f Merge pull request #71 from eagletmt/readlink
Add File.readlink
2016-12-19 09:03:13 +09:00
Kohei Suzuki b31b8022db Fix memory leak in error case 2016-12-17 16:48:02 +09:00
Kohei Suzuki d1c48192cb Add File.readlink 2016-12-17 15:03:52 +09:00
Tomoyuki Sahara 7e89736291 Merge pull request #70 from eagletmt/chmod
Add File.chmod
2016-12-16 22:54:20 +09:00
Kohei Suzuki 698378f076 Add File.chmod 2016-12-16 01:20:08 +09:00
Tomoyuki Sahara f2d4880098 Merge pull request #11 from masahino/add_casting
Add pointer casting
2016-12-12 06:51:03 +09:00
masahino 906b516cfa Add pointer casting 2016-12-09 21:57:06 +09:00
Tomoyuki Sahara 0eafb089c9 Merge pull request #69 from eagletmt/explicit-cast
Add explicit cast from void* to struct mrb_io*
2016-11-27 13:53:50 +09:00
Kohei Suzuki 905203ef5e Add explicit cast from void* to struct mrb_io*
For compatibility with C++.
2016-11-26 14:18:28 +09:00
Tomoyuki Sahara b5e2dc9097 raise an exception when we cannot close "fd" but can close "fd2". 2016-10-13 16:57:38 +09:00
Tomoyuki Sahara f6a82772e6 eof? should raise an IOError if it is not opened for reading. 2016-09-30 17:10:55 +09:00
Tomoyuki Sahara 2229a2aa0f reimplement #eof. fixes #66. 2016-09-30 16:27:11 +09:00
Tomoyuki Sahara 51cf6b6048 Merge pull request #65 from ksss/join
Support Array argument
2016-09-13 09:57:05 +09:00
ksss ff845be72c Support Array argument 2016-09-11 22:01:45 +09:00
ksss 7c9d941003 Show value of expect and actual each assertion 2016-09-11 17:00:19 +09:00
Tomoyuki Sahara d8189c2b19 Merge pull request #64 from asfluido/master
Apparently, in mruby-process gem, Process is now a Module, not a Class
2016-08-10 09:12:44 +09:00
Carlo - PERI 024b09de0c Apparently, in mruby-process gem, Process is now a Module, not a Class 2016-08-09 11:23:49 +02:00
Tomoyuki Sahara b341ee7c12 Merge pull request #63 from ksss/opt
Enable option :in, :out, :err to IO.popen
2016-08-08 10:12:20 +09:00
Tomoyuki Sahara 9ccf03e5ae Merge pull request #62 from ksss/global
Should use global variable
2016-08-08 09:38:22 +09:00
ksss d2c1f4d10b Enable Fixnum option 2016-08-07 22:19:21 +09:00
ksss b462ef4506 Enable option :in, :out, :err 2016-08-07 21:21:01 +09:00
ksss 4cac5e9c70 Should use global variable 2016-08-06 23:11:31 +09:00
Tomoyuki Sahara cc66bf94d1 Merge pull request #9 from ksss/pointer-sign
Suppress compiler warning [-Wpointer-sign]
2016-07-19 09:45:32 +09:00
Tomoyuki Sahara 13650747e7 Merge pull request #10 from dabroz/master
Added 'U' pack support.
2016-07-19 09:44:14 +09:00
Tomasz Dąbrowski 26c1dedcab Added 'U' pack support. 2016-07-18 16:06:01 +02:00
ksss b9f7daf5b6 Suppress compiler warning [-Wpointer-sign] 2016-07-01 22:27:02 +09:00
Tomoyuki Sahara 93d481d4b4 update $? when IO object is closed. closes #58. 2016-06-22 10:29:49 +09:00
Tomoyuki Sahara e90ecff671 Merge pull request #60 from drbrain/test_io_setup_failure
Test io setup failure
2016-06-21 09:52:30 +09:00
Tomoyuki Sahara 2af2a4fff8 add IO#isatty and IO#tty? 2016-06-21 09:49:34 +09:00
Tomoyuki Sahara b2a0c9c6bf Merge pull request #30 from rhykw/tcpserver-reuseaddr
Use TCPServer SO_REUSEADDR
2016-05-30 10:42:30 +09:00
rhykw 4f6703203b TCPServer use SO_REUSEADDR if possible 2016-05-28 09:33:53 +09:00
rhykw 2a80cccf30 TCPServer use SO_REUSEADDR 2016-05-23 21:44:34 +09:00
Eric Hodel 11961b42ac Create socket in /tmp for security
Some systems do not allow UNIX sockets from arbitrary directories.
Instead of trying to `#define SOCKET_PATH` correctly I assume the /tmp/
directory is accessible and use it.
2016-05-12 17:55:14 -07:00
Eric Hodel 777cf70cc5 Include reason in test failure message
I am seeing this test fail in some environments but can't determine why.
The extra information will help me determine the reason bind(2) is
failing.
2016-05-12 16:02:09 -07:00
Tomoyuki Sahara 18f7b45ad1 Merge pull request #29 from rmalizia44/patch-1
Add _WIN32_WINNT definition to Avoid Windows Compilation Errors
2016-01-30 22:39:20 +09:00
rmalizia44 be2ec608e2 Add _WIN32_WINNT definition to Avoid Windows Compilation Errors
the line #define _WIN32_WINNT 0x0501 will cause ws2tcpip.h to implement the missing functions freeaddrinfo, getaddrinfo and getnameinfo on windows
2016-01-28 03:28:05 -02:00
Tomoyuki Sahara 1c4428880b Merge pull request #57 from MaximAbramchuck/patch-1
Add installation instructions
2016-01-21 22:09:17 +09:00
Maxim Abramchuk 7d6f2beaaa Add installation instructions 2016-01-20 13:40:30 +03:00
Tomoyuki Sahara c165e50193 Merge pull request #28 from zzak/port-ntop-pton-win32
Port inet_ntop and inet_pton for WIN32
2016-01-18 16:12:35 +09:00
Tomoyuki Sahara a25ec0a749 Merge pull request #27 from zzak/fix-udpsock-warning
Fix warning: variable 'udpsock' set but not used
2016-01-18 16:09:55 +09:00
Zachary Scott bdc118304c Port inet_ntop and inet_pton for WIN32
Without these functions, compilation fails on MinGW
2016-01-18 15:34:26 +09:00
Zachary Scott c8a2c636e0 Fix warning: variable 'udpsock' set but not used 2016-01-18 15:27:32 +09:00
Tomoyuki Sahara 99e10b8dc4 File::ALT_SEPARATOR is always defined (some string or nil). 2015-12-08 16:44:13 +09:00
Tomoyuki Sahara 4acfd1c7d2 Merge pull request #56 from takahashim/fix-flock
Fix for windows(mingw)
2015-12-08 12:55:38 +09:00
takahashim dd754220ce Fix for windows(mingw)
* File.expand_path: support drive letter and ALT_SEPARATOR

* File.dirname: support ALT_SEPARATOR
* File.basename: ditto.

* IO.popen: raise NotImplementedError
* IO.pipe: ditto.
* `cmd`:  ditto.
* File#flock: ditto.
* FileTest.pipe?: ditto.
* FileTest.symlink?: ditto.
* FileTest.socket?: ditto.
2015-12-08 00:29:42 +09:00
Tomoyuki Sahara 68de1e4fc5 Merge pull request #55 from takahashim/separator
fix file separator
2015-12-07 16:00:46 +09:00
takahashim 0f5b8b66b0 fix file separator
* File::SEPARATOR should be "/"
* File::ALT_SEPARATOR should be "\\" or nil.
2015-12-04 15:36:41 +09:00
Tomoyuki Sahara 6c67120ed4 Merge pull request #54 from takahashim/win-crlf
fix tests for Win: use binary mode
2015-12-03 12:22:59 +09:00
takahashim b19c315148 fix tests for Win: use binary mode 2015-12-02 21:47:46 +09:00
Tomoyuki Sahara 7337bfa497 Merge pull request #53 from takahashim/build-win32
build on Win32
2015-12-02 10:13:15 +09:00
takahashim 07ceb138fa build on Win32 2015-12-02 00:10:43 +09:00
Tomoyuki Sahara 07f1ebd26d symlink(2) returns -1 when it fails. 2015-11-24 17:09:00 +09:00
Tomoyuki Sahara 11ffb93852 assert_nothing_raised is not available on mruby 1.0.0. 2015-11-24 17:00:12 +09:00
Tomoyuki Sahara ca495944b6 Merge pull request #51 from ksss/io-pipe
Implement IO.pipe
2015-11-24 16:49:34 +09:00
ksss a55accd736 Implement IO.pipe 2015-11-24 14:24:24 +09:00
Tomoyuki Sahara c9a4091b83 arguments can be shared strings. 2015-11-24 09:54:03 +09:00
Tomoyuki Sahara 1f4bd9fd9f Merge pull request #50 from takahashim/file-symlink
add File.symlink
2015-11-24 09:47:09 +09:00
takahashim 2cc674e58e add File.symlink 2015-11-22 13:13:52 +09:00
Tomoyuki Sahara 14cdff075d Merge pull request #48 from takahashim/file-path
add File.path
2015-11-22 07:12:23 +09:00
takahashim 44473fecdd add File.path 2015-11-21 22:03:40 +09:00
Tomoyuki Sahara 828551f86c off_t can be larger than mrb_int. 2015-10-20 16:03:02 +09:00
Tomoyuki Sahara db7d829679 raise a SystemCallError when lseek(2) fails. 2015-10-20 15:40:25 +09:00
Tomoyuki Sahara 21963f8fa1 UT for IO#sysseek. 2015-10-20 15:37:05 +09:00
Tomoyuki Sahara cac0035348 fix typo. 2015-10-20 15:16:46 +09:00
Tomoyuki Sahara 78fe65aec4 Merge branch 'master' of github.com:iij/mruby-io 2015-10-20 15:13:28 +09:00
Tomoyuki Sahara 71197d2737 Merge pull request #47 from matsumoto-r/patch-1
Fix buffer overflow of `pos` when file-size is too big
2015-10-19 19:33:09 +09:00
MATSUMOTO, Ryosuke 238704592a Fix buffer overflow of pos when file-size is too big 2015-10-19 19:24:39 +09:00
Tomoyuki Sahara e724c5af98 Merge pull request #45 from takahashim/enable-test
enable test
2015-09-28 12:25:33 +09:00
Tomoyuki Sahara 1f217ea82e Merge pull request #46 from takahashim/add-rewind
support IO#rewind
2015-09-28 12:24:51 +09:00
takahashim 9bbfc38bb4 add IO#rewind 2015-09-27 21:25:06 +09:00
Tomoyuki Sahara 1d6b7f9bba Merge pull request #44 from takahashim/io-addstr
support IO#<<
2015-09-27 21:15:54 +09:00
takahashim f5560e8f17 enable test 2015-09-27 01:39:11 +09:00
takahashim c26f998ed5 support IO#<< 2015-09-27 00:29:17 +09:00
Tomoyuki Sahara 625995424c To run test, we need "conf.enable_test" in build_config.rb. 2015-09-08 13:25:05 +09:00
Tomoyuki Sahara f3016752bd build in container-based environment. 2015-09-08 13:23:46 +09:00
Tomoyuki Sahara ecd7ef5924 Revert "try to fix failure on travis."
This reverts commit 02daa2509d.
2015-09-08 11:57:08 +09:00
Tomoyuki Sahara 02daa2509d try to fix failure on travis. 2015-09-08 10:44:08 +09:00
Tomoyuki Sahara 5fa3c39145 variables are not used on the platforms lack FD_CLOEXEC. 2015-08-27 09:56:17 +09:00
Tomoyuki Sahara 6c4d39412f Merge pull request #30 from ksss/cloexec
Opened fd should be set FD_CLOEXEC by default
2015-08-26 17:37:21 +09:00
Tomoyuki Sahara 042e4a4313 Merge pull request #43 from jkutner/master
Made FILE_SEPERATOR platform dependent
2015-08-21 09:20:32 +09:00
Joe Kutner 2467332c93 Made FILE_SEPERATOR platform dependent 2015-08-20 07:22:48 -05:00
Tomoyuki Sahara efaf74672e Merge pull request #42 from hone/path_separator
define PATH_SEPARATOR
2015-08-12 09:06:34 +09:00
Tomoyuki Sahara 5323498033 Merge pull request #23 from expeditiousRubyist/master
Changed Windows IO overrides to use sysread and syswrite instead
2015-08-10 10:36:14 +09:00
Tomoyuki Sahara e8efd10bd9 make pack_l simpler. 2015-08-07 11:51:01 +09:00
Tomoyuki Sahara 4603047eb1 update installation procedure. 2015-08-07 11:49:56 +09:00
Tomoyuki Sahara 359d2ae6fd support "q" and "Q". closes #7. 2015-08-07 11:48:45 +09:00
Tomoyuki Sahara d34db58797 implicit type conversion caused unexpected result. fixes #8. 2015-08-06 15:38:35 +09:00
unknown c43a08314e Changed IO overrides to use sysread and syswrite instead of read and write 2015-08-03 04:12:10 -07:00
Terence Lee ec4982b2d3 define PATH_SEPARATOR 2015-08-02 17:35:07 +02:00
Tomoyuki Sahara 8527c78fb5 Merge pull request #22 from Asmod4n/master
added SO_NOSIGPIPE
2015-07-28 09:00:31 +09:00
Asmod4n 2929c629d4 added SO_NOSIGPIPE 2015-07-27 18:42:22 +02:00
Tomoyuki Sahara de60400c64 Merge pull request #21 from expeditiousRubyist/master
Added functioning read for Win32
2015-07-25 20:09:20 +09:00
Rubyist f80a4fd0e8 Added functioning read for Win32 2015-07-25 00:24:31 -07:00
Tomoyuki Sahara 2d1134e9ea Merge pull request #41 from hone/cross_compile_windows
support for crossbuild for windows (32 bit and 64 bit) using mingw
2015-07-24 09:19:56 +09:00
Terence Lee fe7784efb0 support for crossbuild for windows (32 bit and 64 bit) using mingw 2015-07-23 12:39:05 -05:00
Tomoyuki Sahara bfb9cf7922 Merge pull request #20 from expeditiousRubyist/master
Win32 Port
2015-07-22 09:35:39 +09:00
Rubyist 4ab922044d Removed unnecessary/incorrect use of sizeof(int) and corrected more
improper usages of mrb_sys_fail
2015-07-21 15:56:27 -07:00
Rubyist 7ee9ab89f9 Changed some uses of mrb_sys_fail to instead use mrb_raise where
appropriate
2015-07-21 03:37:28 -07:00
Rubyist a426f0e2b5 Overrided close and write to work on Win32 platforms 2015-07-18 23:22:57 -07:00
Rubyist 752f7c1526 Minimal semi-working compile on Windows platforms. 2015-07-17 23:45:02 -07:00
Rubyist 7d8cbf1a9c Added Winsock 2 to list of libraries to use when building for Windows
targets
2015-07-17 23:03:34 -07:00
Tomoyuki Sahara 1b5c68567e Merge pull request #40 from archSeer/patch-1
Remove mrb_io_s_select typo.
2015-07-03 09:36:49 +09:00
Blaž Hrastnik 8da787be72 Remove mrb_io_s_select typo.
Uncovered with a Coverity scan of our project using mruby-io. https://scan8.coverity.com/reports.htm#v26153/p11375/fileInstanceId=6844382&defectInstanceId=2515905&mergedDefectId=121921
2015-07-02 21:02:56 +02:00
Tomoyuki Sahara b913e7eefd test suite for pack/unpack. 2015-05-22 11:38:56 +09:00
Tomoyuki Sahara 2ba4933158 refactor "AaZ". fixes #6. 2015-05-22 11:38:39 +09:00
Tomoyuki Sahara 15de80a7cd style. 2015-05-22 09:41:39 +09:00
Tomoyuki Sahara dacb8b626b failed to remove temporary files! 2015-05-20 11:38:03 +09:00
Tomoyuki Sahara ae4fc77675 Merge pull request #39 from jbreeden/master
Correct File::NULL for Windows
2015-04-18 06:50:32 +09:00
Jared Breeden 6d6be18d4e Removing redundant platform check 2015-04-17 15:45:14 -04:00
Jared Breeden 7f8324a2ed Merge branch 'master' of https://github.com/iij/mruby-io 2015-04-17 15:40:35 -04:00
Jared Breeden 36343cf098 Correct File::NULL for Windows 2015-04-17 15:39:11 -04:00
Jared Breeden c0738a74c6 Excluding wait call for windows 2015-04-05 17:21:02 -04:00
Tomoyuki Sahara cfbc8a8995 Merge pull request #38 from jbreeden/master
Excluding wait call for windows
2015-04-05 09:23:29 +09:00
Tomoyuki Sahara e92fd76248 wait for child processes when we close pipes. fixes #37. 2015-04-03 10:05:09 +09:00
Tomoyuki Sahara 1629e86063 add IPv6 constants defined in RFC3493. 2015-02-13 11:35:36 +09:00
Tomoyuki Sahara e4006cb53a Socket::Option requires iij/mruby-pack. 2014-12-26 16:12:41 +09:00
Tomoyuki Sahara 0d05a22602 don't call undefined method. fixes #15. 2014-12-26 16:00:50 +09:00
Tomoyuki Sahara 7b17158f88 remove unused variables. 2014-12-26 13:36:11 +09:00
Tomoyuki Sahara a09858af61 syscalls may return sockaddr shorter than sizeof(struct sockaddr) on Linux. 2014-12-26 13:27:39 +09:00
Tomoyuki Sahara a960a6f931 failed to add... 2014-12-26 11:19:53 +09:00
Tomoyuki Sahara 3a22166c67 debug UNIXSocket and UNIXServer. 2014-12-26 11:16:03 +09:00
Tomoyuki Sahara 3a97a453c4 rewrite IO.for_fd.
IO.for_fd should call IO#initialize to initialize the created object
properly.  It cannot be implemented in Ruby.
2014-12-26 11:09:07 +09:00
Tomoyuki Sahara c455544ee2 better error message. 2014-12-26 11:08:18 +09:00
Tomoyuki Sahara 1d1f273ca9 Merge pull request #35 from tmtm/fix-read-create-many-objects
FIX: IO#read create a large number of objects.
2014-12-18 11:33:06 +09:00
TOMITA Masahiro 42752bffce FIX: IO#read create a large number of objects. 2014-12-18 00:41:59 +09:00
Tomoyuki Sahara e7dbe6e87a Merge pull request #33 from iij/revert-32-fix-read-create-many-objects
Revert "FIX: IO#read create a large number of objects."
2014-12-17 13:39:59 +09:00
Tomoyuki Sahara e82c1d3f38 Revert "FIX: IO#read create a large number of objects." 2014-12-17 13:37:15 +09:00
Tomoyuki Sahara 50721e9bf8 Merge pull request #32 from tmtm/fix-read-create-many-objects
FIX: IO#read create a large number of objects.
2014-12-17 13:35:34 +09:00
TOMITA Masahiro 9b13a59a55 FIX: IO#read create a large number of objects. 2014-12-17 01:46:23 +09:00
Tomoyuki Sahara ee347f3417 Merge pull request #31 from tmtm/fix-sysread-segv
FIX: IO#sysread occurs SEGV
2014-12-16 09:07:45 +09:00
TOMITA Masahiro be9e203563 FIX: IO#sysread occurs SEGV 2014-12-15 20:24:01 +09:00
Tomoyuki Sahara 723db886e1 add Socket::Option#inspect
without this, mirb dies.
https://github.com/mruby/mruby/pull/2666
2014-12-12 12:38:43 +09:00
Tomoyuki Sahara 121475638d add "I" and "i". 2014-12-12 12:12:41 +09:00
Tomoyuki Sahara 2103bc99ba style 2014-12-12 12:12:19 +09:00
Tomoyuki Sahara 669fe705cc "i" and "I". 2014-12-12 12:01:58 +09:00
ksss e61c469724 IO.popen fd set close_on_exec flag by default 2014-12-04 10:25:03 +09:00
ksss 9439b981d8 Opened fd should be set FD_CLOEXEC by default 2014-12-04 10:25:03 +09:00
Tomoyuki Sahara d1fee5892a IO.sysopen does retry. closes #26. 2014-11-25 16:26:34 +09:00
Tomoyuki Sahara e7cd024498 Merge pull request #29 from sdottaka/fix-for-msvc
Fix broken build for Visual C++
2014-11-25 10:29:07 +09:00
sdottaka 24007b80b4 Fix broken build for Visual C++ 2014-11-22 17:48:59 +09:00
Tomoyuki Sahara a2f45bf8d1 Merge pull request #28 from ksss/file-size
Implement FileTest.size
2014-11-18 10:35:12 +09:00
ksss a44ada616e Implement FileTest.size
- File.size delegate to FileTest.size
- File.size more faster by reading i-node value
2014-11-16 14:55:45 +09:00
Tomoyuki Sahara 379c5a6d88 Merge pull request #25 from matz/gc_on_enfile
garbage collect when open(2) fails with ENFILE or EMFILE
2014-11-13 09:27:11 +09:00
Yukihiro "Matz" Matsumoto b50093ad28 garbage collect when open(2) fails with ENFILE or EMFILE 2014-11-13 01:50:46 +09:00
Tomoyuki Sahara 190264b3c8 Merge pull request #23 from jbreeden/master
Correcting E_NOTIMP_ERROR reference
2014-08-08 21:34:15 +09:00
Akito Mochizuki 0761b17245 update implemented methods table 2014-08-05 11:51:05 +09:00
jbreeden 9a2cbc4122 Correcting E_NOTIMP_ERROR reference 2014-08-03 16:45:46 -04:00
Tomoyuki Sahara e60951a305 add IO#sync and IO#sync= 2014-07-29 10:55:02 +09:00
Tomoyuki Sahara 1768ee02e5 remove extra ';'. 2014-07-22 23:55:25 +09:00
Tomoyuki Sahara 8c34a8d561 Merge pull request #22 from take-cheeze/fix_arg
Fix type of argument passed to mrb_get_args.
2014-07-22 15:30:57 +09:00
take_cheeze 689541d0fb Fix type of argument passed to mrb_get_args. 2014-07-19 21:37:13 +09:00
Tomoyuki Sahara 093f4e2cff mrb_voidp (and other macros) has gone. 2014-07-09 12:24:50 +09:00
Tomoyuki Sahara fa39825b1b refactor. 2014-07-09 10:01:33 +09:00
Tomoyuki Sahara 66a92240de Merge pull request #21 from dreamedge/add_close_on_exec
Add close on exec
2014-07-09 09:34:12 +09:00
dreamedge 78f5f98710 delete debug messages 2014-07-09 05:29:20 +09:00
dreamedge 7e689e8680 Add IO#close_on_exec=
and a test on test/io.rb
2014-07-08 15:56:56 +09:00
dreamedge 59b7c4eaf0 add IO.close_on_exec? 2014-07-07 12:47:53 +09:00
Tomoyuki Sahara 91c285fcfe regen. 2014-07-02 09:12:27 +09:00
Tomoyuki Sahara 04097348e8 more TCP options (for NetBSD). 2014-07-02 09:12:04 +09:00
Tomoyuki Sahara baa40ef2b1 sort. 2014-07-02 09:09:58 +09:00
Tomoyuki Sahara 9c3c267bef Merge pull request #14 from dreamedge/add_tcp_constants
Add TCP_* constants included in "netinet/tcp.h".
2014-07-02 09:08:47 +09:00
dreamedge f3c71cf5da Add TCP_* constants included in "netinet/tcp.h".
ex: TCP_NODELAY, TCP_CORK, ...
2014-07-02 00:30:10 +09:00
Tomoyuki Sahara ddfc4eb5ef IO#read(0) should return "" immediately. fixes iij/mruby-socket#13. 2014-06-19 09:57:08 +09:00
Tomoyuki Sahara 376af5bac3 re-implement TCPServer.accept. fixes #12. 2014-06-17 15:41:42 +09:00
Tomoyuki Sahara 5b65ca3ebb Merge pull request #5 from take-cheeze/float
Add full support of float templates.
2014-06-15 19:54:08 +09:00
take_cheeze 7b2611ea28 Update supported template list. 2014-06-14 13:25:00 +09:00
take_cheeze 8f4b7ac15c Support float/double unpacking. 2014-06-14 13:25:00 +09:00
take_cheeze 514450e891 Use PACK_FLAG_LITTLEENDIAN. 2014-06-14 13:25:00 +09:00
take_cheeze 7dc2b4f59f Implement g/f/F/G/d/D packing. 2014-06-14 13:24:59 +09:00
take_cheeze f4f968241b Add support of little endian float. 2014-06-14 13:24:49 +09:00
Tomoyuki Sahara a0c4ca2406 Merge pull request #4 from take-cheeze/raise_fix
Fix invalid raise format found with mruby-clang-plugin.
2014-06-14 07:51:42 +09:00
take_cheeze 1997420a7f Fix raise format found with mruby-clang-plugin. 2014-06-13 17:42:43 +09:00
Tomoyuki Sahara d894de86f4 fd2 is valid if fd2 >= 0. fixes #18. 2014-06-10 10:22:50 +09:00
Tomoyuki Sahara cb84ce30e7 no longer used. 2014-06-10 09:54:23 +09:00
Tomoyuki Sahara 9ee9c271d1 Merge pull request #20 from windwiny/patch-1
compatible 32 bit windows
2014-05-09 02:33:00 +09:00
windwiny dc61ef1c65 compatible 32 bit windows 2014-05-07 20:33:12 +08:00
Tomoyuki Sahara 077f39bd38 Merge pull request #19 from schmurfy/solaris_flock
raise an error for flock on solaris
2014-04-29 00:45:08 +09:00
Julien Ammous 9a1b25bdd8 raise an error for flock on solaris 2014-04-28 15:40:04 +02:00
Tomoyuki Sahara 5aeb99ad49 fix mrb_raisef usage. 2014-04-21 11:14:40 +09:00
Tomoyuki Sahara 9c00de59ce IO.for_fd can be written in Ruby. 2014-04-21 10:24:59 +09:00
Tomoyuki Sahara c46cb1b5eb more tests. 2014-04-21 10:02:25 +09:00
Tomoyuki Sahara e5f30f83ce IO#flush should raise an exception if it is closed. 2014-04-21 10:01:49 +09:00
Tomoyuki Sahara 99c67749ff remove return statements after mrb_raise(). 2014-04-21 09:06:46 +09:00
Tomoyuki Sahara 7d7a549a4f remove io_open(). 2014-04-18 11:32:38 +09:00
Tomoyuki Sahara 36045ea96f IO#syswrite should raise an error if it's not opened for writing. 2014-04-18 11:20:55 +09:00
Tomoyuki Sahara 1c4f46f324 remove standard header files from io.h. 2014-04-17 16:29:27 +09:00
Tomoyuki Sahara a11780f4f1 file.c depends on mruby/ext/io.h now. 2014-04-17 16:18:26 +09:00
Tomoyuki Sahara a3e1e535dc function declarations should be in a header file. 2014-04-17 16:13:18 +09:00
Tomoyuki Sahara 9f5ff9ddec remove unused constants. 2014-04-17 16:12:51 +09:00
Tomoyuki Sahara ba9cb1f757 "struct mrb_io_type" is not used at all. 2014-04-17 16:07:12 +09:00
Tomoyuki Sahara 10be4cbb2c file.c does not depend on mruby/ext/io.h. 2014-04-17 15:56:11 +09:00
Tomoyuki Sahara 87ce12dfe3 io.write("") -> 0 2014-04-17 15:53:51 +09:00
Tomoyuki Sahara 810e37b1c3 return value of syswrite may be less than length of given string. 2014-04-17 15:45:31 +09:00
Tomoyuki Sahara d5cf1de1ae Merge pull request #16 from schmurfy/solaris
solaris does not have flock
2014-04-11 06:53:34 +09:00
Tomoyuki Sahara 1d987d2fcd Merge pull request #9 from schmurfy/solaris
OpenSolaris/Illumos defines a "sun" constant...
2014-04-11 05:50:18 +09:00
Julien Ammous 9850e6a9d0 OpenSolaris/Illumos defines a "sun" constant... 2014-04-10 19:32:05 +02:00
Julien Ammous cd168c6f32 solaris does not have flock 2014-04-10 19:26:55 +02:00
Tomoyuki Sahara 28e00d82fb suppress compiler warnings. 2014-04-07 13:15:54 +09:00
Tomoyuki Sahara a6ab2c54f3 Merge pull request #15 from monami-ya-mrb/pr-add-error-check-in-test
Don't ignore the return value of symlink().
2014-04-05 11:55:51 +09:00
Masaki Muranaka 706ef1337a Don't ignore the return value of symlink(). 2014-04-05 10:44:47 +09:00
Akira Yumiyama 572b404935 Update .travis.yml 2014-04-04 11:32:42 +09:00
Akira Yumiyama 2bf49c9232 Update .travis.yml 2014-04-04 11:31:45 +09:00
Akira Yumiyama 083cd9ca8c Update .travis.yml 2014-04-04 11:31:33 +09:00
Akira Yumiyama 355723ebca Create .travis.yml 2014-04-04 11:27:56 +09:00
Akira Yumiyama 80e01e3659 Create .travis.yml 2014-04-04 11:27:14 +09:00
Akira Yumiyama 1094bbfff8 Create .travis.yml 2014-04-04 11:25:04 +09:00
Akira Yumiyama eda9d1a8fc nonexistent test fixes (for travis-ci) 2014-03-26 22:09:10 +09:00
Tomoyuki Sahara ab9dcc766e IO.close should be IO._sysclose. closes #13. 2014-03-26 17:22:57 +09:00
Tomoyuki Sahara 719452b8d2 remove unsed. 2014-03-14 10:47:54 +09:00
Tomoyuki Sahara 14031bdf44 Merge pull request #11 from pbosetti/master
Can build on VisualStudio, revised.
2014-03-14 10:41:56 +09:00
Tomoyuki Sahara 279587c138 split. 2014-03-12 09:44:34 +09:00
Tomoyuki Sahara a8558512ec mruby-mtest is not required to build (but to test). 2014-03-12 09:41:23 +09:00
Tomoyuki Sahara e345d4c68f Merge pull request #7 from monami-ya-mrb/pr-fix-connect-failed
Call Socket._connect() in Socket.connect() .
2014-03-11 23:25:29 +09:00
Masaki Muranaka 11b47459e7 Call Socket._connect() in Socket.connect() . 2014-03-11 21:18:05 +09:00
Paolo Bosetti 39bd240116 Fixed bug in File.expand_path() on Windows (forever recursive loop) 2014-03-07 16:47:18 +01:00
Paolo Bosetti 7ff049457f Added File.foreach method.
Improved error management in File.new (Errno can be undefined)
2014-03-04 10:43:46 +01:00
Paolo Bosetti d9f3fd868a Merge branch 'master' of https://github.com/iij/mruby-io into test
Conflicts:
	src/io.c
2014-03-03 13:15:57 +01:00
Tomoyuki Sahara f7c054bd39 quiet compiler. 2014-02-25 12:28:34 +09:00
Tomoyuki Sahara e8706d4ee7 remove unused. 2014-02-25 12:23:15 +09:00
Tomoyuki Sahara b9dff44582 Merge branch 'master' of github.com:iij/mruby-io 2014-02-25 12:20:52 +09:00
Tomoyuki Sahara 56a8c592dd add IO.read 2014-02-25 12:19:52 +09:00
Tomoyuki Sahara a90d8b8a73 add Socket.getaddrinfo. 2014-02-24 11:21:49 +09:00
Akira Yumiyama d28f042118 compatibility support (mruby/mruby, iij/mruby and 1.0.0)
- refs https://github.com/mruby/mruby/commit/36e234aa377d50d8ee425c7868e0651cf78e85cf
2014-02-22 20:45:07 +09:00
Tomoyuki Sahara 7fd585bae1 support older version. 2014-02-14 10:36:37 +09:00
Tomoyuki Sahara daa65c15de add dummy IO#flush for better compatibility with CRuby. 2014-02-12 16:33:34 +09:00
Tomoyuki Sahara 40c52f58d0 Merge pull request #9 from matsumoto-r/support_mrb_get_module
Support mrb_module_get
2014-02-12 10:57:58 +09:00
Paolo Bosetti ee2859de6e Updated mrb_include_module call after mruby 1.0.0 2014-02-11 14:54:30 +01:00
Tomoyuki Sahara b3c6075dc5 IO._bless has gone.
https://github.com/iij/mruby-io/commit/b74458a486042f4863fa6362057e25f0997694f5
2014-02-10 09:51:24 +09:00
Tomoyuki Sahara b74458a486 remove _bless trick. closes #8. 2014-02-10 09:49:37 +09:00
MATSUMOTO Ryosuke 526608c8a2 Support mrb_module_ge 2014-02-08 17:38:41 +09:00
Tomoyuki Sahara f10b73efa7 move license terms to the bottom. 2014-02-03 12:35:02 +09:00
Paolo Bosetti a2af349959 Now the drive letter is returned as leading path element by File#dirname on Windows 2014-01-13 17:29:57 +01:00
Tomoyuki Sahara b744097511 Merge pull request #6 from schmurfy/testless
removed mtest dependency
2014-01-09 16:09:50 -08:00
Paolo Bosetti a613bce3f2 Merge branch 'master' of https://github.com/iij/mruby-io 2014-01-07 13:51:38 +01:00
Tomoyuki Sahara 8cee36b1b5 Catch Errno::ENFILE too.
When system file descriptor table is full, errno is set to
ENFILE instead of EMFILE.  They are similar but different.
2013-12-13 15:49:32 +09:00
Paolo Bosetti 23afaf02dc Made compatible with VisualStudio 2013-12-10 14:34:26 +01:00
Julien Ammous a26ce35c64 removed mtest dependency 2013-12-04 20:51:27 +01:00
Tomoyuki Sahara d12f436bdb mrb_intern API change. 2013-12-03 10:07:29 +09:00
Paolo Bosetti 5a59fd3a5c Fix for compilation under Win/MinGW 2013-12-02 12:14:04 +01:00
Tomoyuki Sahara e641e9a380 suppress a compiler warning. 2013-11-20 12:14:54 +09:00
Tomoyuki Sahara 2245818f91 make it more portable. 2013-11-20 12:13:34 +09:00
Tomoyuki Sahara 78d2d909cf style 2013-11-20 10:26:13 +09:00
Tomoyuki Sahara 87d878292d Try GC when Too many open files (revert a part of 1e8097a). 2013-11-16 16:04:31 +09:00
Tomoyuki Sahara e44da8a6cc test for #6. 2013-11-16 05:44:04 +09:00
Tomoyuki Sahara 1e8097a4b8 IO.sysopen raises an exception when open(2) fails. closes #6. 2013-11-16 05:14:07 +09:00
Tomoyuki Sahara e96cdeb2af Merge pull request #3 from h2so5/patch-1
avoid declaration error on VC++
2013-11-05 18:31:15 -08:00
h2so5 db14b8e7d4 avoid declaration error on VC++ 2013-11-06 11:25:33 +09:00
Tomoyuki Sahara d8e5e7df3f Merge pull request #3 from murasesyuka/feature/add_dependencies_gem
add mruby-socket dependency gems
2013-11-03 00:41:21 -07:00
murase_syuka 78ebe1b427 add mruby-socket dependency gems 2013-11-02 14:30:42 +09:00
Tomoyuki Sahara 823df14ff4 remove unused code and irrelevant comment. 2013-10-15 10:43:48 +09:00
Tomoyuki Sahara ec443d45db more IPPROTO_* related to IPv6. 2013-10-10 10:24:02 +09:00
Tomoyuki Sahara 93edd26b3e fix typo... 2013-10-09 00:35:22 +09:00
Tomoyuki Sahara 005f01f2fc fix RSTRING_PTR usage. 2013-10-03 12:18:39 +09:00
Tomoyuki Sahara bf4c226232 Merge pull request #4 from pbosetti/master
Truncate the file to zero length on opening when "w" mode is set
2013-10-02 17:08:24 -07:00
Paolo Bosetti c608c26ab4 Merge branch 'master' of https://github.com/iij/mruby-io 2013-10-02 13:05:12 +02:00
Paolo Bosetti 49494a7367 Truncate file on File.open(file, "w") 2013-10-02 13:01:56 +02:00
Tomoyuki Sahara 8b48e2b4a4 syswrite must write to fd2 if it is properly set.
closes #3.
2013-09-30 11:56:15 +09:00
Tomoyuki Sahara 97899a6922 style 2013-09-30 11:18:22 +09:00
Tomoyuki Sahara adb3bd6698 don't retry when we cannot fork(2).
EAGAIN indicates the system is under heavy load.
Retrying make things worse.
2013-09-30 10:55:09 +09:00
Tomoyuki Sahara d75d23294d fix descriptor leakage. 2013-09-30 10:36:29 +09:00
Tomoyuki Sahara b4f0a68fba add File#flock. 2013-09-30 10:17:21 +09:00
Tomoyuki Sahara 140da1c6ca remove duplicated white spaces. 2013-09-26 18:31:02 +09:00
Tomoyuki Sahara e27fb544df suppress a warning and fix a possible segv. 2013-09-26 10:59:40 +09:00
Tomoyuki Sahara e2b0606752 Merge pull request #2 from pbosetti/master
Catch up with API changes on mrb_intern() -> mrb_intern_cstr()
2013-09-25 18:21:27 -07:00
Paolo Bosetti c4e3c46e86 Catch up with API changes on mrb_intern() -> mrb_intern_cstr() 2013-09-25 13:26:49 +02:00
Tomoyuki Sahara 47a610e688 use array parameter on IO.open. 2013-08-30 19:09:36 +09:00
Tomoyuki Sahara 713aa48cf9 STDERR's file descriptor is 2.
closes #1
2013-08-30 17:04:40 +09:00
Tomoyuki Sahara 9dc875f246 add cmd (command output expression). 2013-08-23 16:00:08 +09:00
Tomoyuki Sahara 40adffc676 ARGS_XXX -> MRB_ARGS_XXX 2013-08-21 09:29:38 +09:00
Tomoyuki Sahara 0345215465 fix a possible address family mismatch. 2013-08-14 11:51:53 +09:00
Tomoyuki Sahara a9593e1f57 v4/v6 fallback for TCP. 2013-08-14 09:34:22 +09:00
Tomoyuki Sahara 5e8021bedb tests for File.socket? and File.symlink? 2013-08-08 14:00:02 +09:00
Tomoyuki Sahara c49541058c use lstat(2) to check if it's a symlink 2013-08-08 13:58:47 +09:00
Tomoyuki Sahara 76e1017f48 hints.ai_socktype must be set if servname is not NULL on NetBSD3.
Closes #1
2013-07-25 15:04:59 +09:00
Tomoyuki Sahara a341b8e0ff more socket options (for multicast). 2013-07-25 11:58:05 +09:00
Tomoyuki Sahara cf827ab0e7 fix Addrinfo.getaddrinfo("127.0.0.1", nil).
Closes #2
2013-07-25 11:54:53 +09:00
Takashi Sogabe 4f3a749da1 Fix incorrect condition for pendig-IO 2013-06-26 15:24:23 +09:00
Tomoyuki Sahara 216e32751e Socket.gethostname always fails. 2013-06-21 09:14:53 +09:00
Akira Yumiyama 5625e44371 add method: IO#select 2013-06-02 15:25:14 +09:00
Akira Yumiyama 1272df7cb6 fix IO#eof? method (consider the read buffer) 2013-06-02 13:24:34 +09:00
Akito Mochizuki 35defaf1c9 fix mrb_voidp_value function call 2013-05-28 10:15:25 +09:00
Tomoyuki Sahara f4aa3e7ae7 getaddrinfo("localhost") returns "fe80::1%lo0" on MacOS! 2013-05-21 14:48:42 +09:00
Tomoyuki Sahara 1411d5b974 using mruby-mtest on test/socket.rb. 2013-05-21 14:23:35 +09:00
Tomoyuki Sahara 12144b9ad2 getaddrinfo("localhost") may return 2 or more. 2013-05-21 14:23:07 +09:00
Tomoyuki Sahara 0f2d7e8a99 fix reading wrong variable. 2013-05-21 14:15:15 +09:00
Tomoyuki Sahara b8912c3508 Linux does not have getpeereid(2). 2013-05-21 14:13:15 +09:00
Tomoyuki Sahara 4bebd4d70f mrb_sys_fail() is declared in src/error.h 2013-05-21 14:03:10 +09:00
Tomoyuki Sahara cfe18142cb test runner. 2013-05-21 13:53:27 +09:00
Tomoyuki Sahara 89147066f8 mruby-socket depends on mruby-io. 2013-05-21 13:48:33 +09:00
Tomoyuki Sahara bc5feb39a1 short description, example, requirement, todo, license. 2013-05-21 13:40:14 +09:00
Tomoyuki Sahara e459ecc934 Merge branch 'master' of github.com:iij/mruby-socket 2013-05-21 13:19:32 +09:00
Tomoyuki Sahara 49e53bca5d Socket library for mruby. 2013-05-21 13:17:34 +09:00
Tomoyuki Sahara 06f1c82f64 Initial commit 2013-05-20 21:15:50 -07:00
Akira Yumiyama 0a21d9ec92 bufix of mrb_file__gethome() 2013-05-12 14:58:12 +09:00
Akira Yumiyama e277079616 update run_test.rb 2013-05-12 14:50:31 +09:00
Akira Yumiyama 55b6ef43c5 add return value check of fseek 2013-05-12 14:23:48 +09:00
Akira Yumiyama 14e1992ed0 add null check 2013-05-12 14:15:00 +09:00
Akira Yumiyama d39a05e68e remove unused variable. 2013-05-12 14:14:48 +09:00
Akira Yumiyama 49cc9c7cfa Use strncpy instead of strcpy. 2013-05-12 14:01:53 +09:00
Akira Yumiyama c25d386c41 Use mkstemp instead of mktemp. 2013-05-12 13:15:11 +09:00
Akira Yumiyama acc8995060 update run_test.rb 2013-05-12 12:54:35 +09:00
Akira Yumiyama df529a83d6 add $stdin $stdout $stderr STDIN STDOUT STDERR 2013-05-08 20:22:29 +09:00
Akira Yumiyama 7a94d02e8d add IO#print 2013-05-08 20:22:14 +09:00
Tomoyuki Sahara 38f4086a52 Merge pull request #2 from schmurfy/double
added support for E in pack
2013-05-08 01:53:56 -07:00
Julien Ammous dce09fb7fd removed unused variables 2013-05-08 10:26:15 +02:00
Julien Ammous c869bdedc0 added support for E in pack (double) 2013-05-08 10:26:15 +02:00
Tomoyuki Sahara 8c5cb5e782 cannot pack objects other than the first one. closes #1. 2013-05-08 09:40:24 +09:00
Akira Yumiyama f89ee88a6c rename mrb_class_obj_get -> mrb_class_get 2013-05-02 23:52:57 +09:00
Akira Yumiyama 7618ca6bb3 remove unused Makefile 2013-05-02 23:45:47 +09:00
Akira Yumiyama 8bfbca234f update run_test.rb 2013-05-02 23:44:40 +09:00
Akira Yumiyama 62e1823187 update run_test.rb 2013-05-02 23:36:20 +09:00
Akira Yumiyama 814f3305ca put MRB_ prefix before ARGS_XXX macros 2013-04-27 10:09:05 +09:00
Akira Yumiyama d5982b43c5 put MRB_ prefix before ARGS_XXX macros 2013-04-27 09:47:05 +09:00
Akira Yumiyama da557fbc82 add File.expand_path 2013-04-07 01:55:18 +09:00
Akira Yumiyama cc40f93ac8 Kernel#open block support 2013-04-02 15:51:36 +09:00
Akira Yumiyama 911003987b add Kernel#open 2013-04-02 15:32:01 +09:00
Akira Yumiyama 5a425f598b Update README.md 2013-04-01 10:17:18 +09:00
Akira Yumiyama b8a23e6be8 update README.md 2013-04-01 09:21:12 +09:00
Akira Yumiyama e8ca5e5169 initial commit 2013-04-01 09:12:01 +09:00
Tomoyuki Sahara 858d67c154 add "v" and "V". 2013-02-15 10:54:36 +09:00
Tomoyuki Sahara fc43022c95 support "V" and "v". 2013-02-15 10:52:37 +09:00
Tomoyuki Sahara abe9ccfe4b Merge branch 'master' of https://github.com/iij/mruby-pack 2013-02-15 10:46:21 +09:00
Tomoyuki Sahara 88fa5851f4 fix an issue large/negative integer may not be packed/unpacked correctly. 2013-02-15 10:45:30 +09:00
Tomoyuki Sahara a0c62dd4b8 fix an issue negative integer may not be packed/unpacked correctly. 2013-02-15 10:39:04 +09:00
Akira Yumiyama 53ff8bab17 update README.md 2013-01-30 17:03:42 +09:00
Akira Yumiyama aadcbb1690 add mrbgem test runner 2013-01-30 15:20:41 +09:00
Akira Yumiyama 0786e37ed6 update mrbgem.rake 2013-01-30 15:20:10 +09:00
Akira Yumiyama a0161d69a8 typo fix on mrbgem.rake 2013-01-24 10:12:02 +09:00
Akira Yumiyama f70a45ad3a update mrbgem.rake 2013-01-24 10:09:15 +09:00
Akira Yumiyama 558f6fc090 update mrbgem.rake 2013-01-24 09:00:55 +09:00
Akira Yumiyama e734ab3f95 add mrb_mruby_pack_gem_final 2013-01-24 09:00:40 +09:00
Akira Yumiyama 209ad3171d add mrbgem.rake 2013-01-04 00:04:02 +09:00
Akira Yumiyama fb79282a5b add README.md 2012-12-31 13:15:30 +09:00
Akira Yumiyama e205905d02 mruby-pack 2012-12-31 11:38:22 +09:00
209 changed files with 14720 additions and 2888 deletions
+1
View File
@@ -16,6 +16,7 @@
.ccmalloc
.svn
/.git
cscope.files
cscope.out
tags
/src/y.tab.c
+2
View File
@@ -14,5 +14,7 @@ addons:
packages:
- gperf
env:
MRUBY_CONFIG=travis_config.rb
env: MRUBY_CONFIG=travis_config.rb
script: "./minirake all test"
+3
View File
@@ -35,3 +35,6 @@ Original Authors "mruby developers" are:
Terence Lee
Zachary Scott
Tomasz Dąbrowski
Christopher Aue
Masahiro Wakame
YAMAMOTO Masaya
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2017 mruby developers
Copyright (c) 2018 mruby developers
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
+1 -1
View File
@@ -17,7 +17,7 @@ of the Ministry of Economy, Trade and Industry of Japan.
## How to get mruby
The stable version 1.3.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/1.3.0.zip](https://github.com/mruby/mruby/archive/1.3.0.zip)
The stable version 1.4.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/1.4.0.zip](https://github.com/mruby/mruby/archive/1.4.0.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)
+5 -3
View File
@@ -5,10 +5,12 @@ MRUBY_ROOT = File.dirname(File.expand_path(__FILE__))
MRUBY_BUILD_HOST_IS_CYGWIN = RUBY_PLATFORM.include?('cygwin')
MRUBY_BUILD_HOST_IS_OPENBSD = RUBY_PLATFORM.include?('openbsd')
$LOAD_PATH << File.join(MRUBY_ROOT, "lib")
# load build systems
load "#{MRUBY_ROOT}/tasks/ruby_ext.rake"
load "#{MRUBY_ROOT}/tasks/mruby_build.rake"
load "#{MRUBY_ROOT}/tasks/mrbgem_spec.rake"
require "mruby-core-ext"
require "mruby/build"
require "mruby/gem"
# load configuration file
MRUBY_CONFIG = (ENV['MRUBY_CONFIG'] && ENV['MRUBY_CONFIG'] != '') ? ENV['MRUBY_CONFIG'] : "#{MRUBY_ROOT}/build_config.rb"
+14 -3
View File
@@ -5,6 +5,10 @@ os: Visual Studio 2015
clone_depth: 50
cache:
- win_flex_bison-2.5.10.zip
environment:
matrix:
# Visual Studio 2015 64bit
@@ -18,10 +22,17 @@ environment:
init:
- call "%visualcpp%" %machine%
# For using bison.exe
- set PATH=%PATH%;C:\cygwin\bin;
# For using Rubyinstaller's Ruby 2.4 64bit
- set PATH=C:\Ruby24-x64\bin;%PATH%
- ruby --version
install:
- if not exist win_flex_bison-2.5.10.zip 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 > nul
build_script:
- set YACC=.\win_flex_bison\win_bison.exe
- set MRUBY_CONFIG=appveyor_config.rb
- ruby .\minirake test
- ruby .\minirake test all
+1 -1
View File
@@ -5,7 +5,7 @@ MRuby::Build.new('debug') do |conf|
# include all core GEMs
conf.gembox 'full-core'
conf.compilers.each do |c|
c.defines += %w(MRB_GC_STRESS MRB_GC_FIXED_ARENA)
c.defines += %w(MRB_GC_STRESS MRB_GC_FIXED_ARENA MRB_METHOD_CACHE)
end
build_mrbc_exec
+15 -15
View File
@@ -68,7 +68,7 @@ class Vec
def vnormalize
len = vlength
v = Vec.new(@x, @y, @z)
if len > 1.0e-17 then
if len > 1.0e-17
v.x = v.x / len
v.y = v.y / len
v.z = v.z / len
@@ -92,10 +92,10 @@ class Sphere
b = rs.vdot(ray.dir)
c = rs.vdot(rs) - (@radius * @radius)
d = b * b - c
if d > 0.0 then
if d > 0.0
t = - b - Math.sqrt(d)
if t > 0.0 and t < isect.t then
if t > 0.0 and t < isect.t
isect.t = t
isect.hit = true
isect.pl = Vec.new(ray.org.x + ray.dir.x * t,
@@ -118,16 +118,16 @@ class Plane
d = -@p.vdot(@n)
v = ray.dir.vdot(@n)
v0 = v
if v < 0.0 then
if v < 0.0
v0 = -v
end
if v0 < 1.0e-17 then
if v0 < 1.0e-17
return
end
t = -(ray.org.vdot(@n) + d) / v
if t > 0.0 and t < isect.t then
if t > 0.0 and t < isect.t
isect.hit = true
isect.t = t
isect.n = @n
@@ -170,10 +170,10 @@ end
def clamp(f)
i = f * 255.5
if i > 255.0 then
if i > 255.0
i = 255.0
end
if i < 0.0 then
if i < 0.0
i = 0.0
end
i.to_i
@@ -183,11 +183,11 @@ def otherBasis(basis, n)
basis[2] = Vec.new(n.x, n.y, n.z)
basis[1] = Vec.new(0.0, 0.0, 0.0)
if n.x < 0.6 and n.x > -0.6 then
if n.x < 0.6 and n.x > -0.6
basis[1].x = 1.0
elsif n.y < 0.6 and n.y > -0.6 then
elsif n.y < 0.6 and n.y > -0.6
basis[1].y = 1.0
elsif n.z < 0.6 and n.z > -0.6 then
elsif n.z < 0.6 and n.z > -0.6
basis[1].z = 1.0
else
basis[1].x = 1.0
@@ -221,8 +221,8 @@ class Scene
p0 = Vec.new(isect.pl.x + eps * isect.n.x,
isect.pl.y + eps * isect.n.y,
isect.pl.z + eps * isect.n.z)
nphi.times do |j|
ntheta.times do |i|
nphi.times do
ntheta.times do
r = Rand::rand
phi = 2.0 * 3.14159265 * Rand::rand
x = Math.cos(phi) * Math.sqrt(1.0 - r)
@@ -241,7 +241,7 @@ class Scene
@spheres[1].intersect(ray, occisect)
@spheres[2].intersect(ray, occisect)
@plane.intersect(ray, occisect)
if occisect.hit then
if occisect.hit
occlusion = occlusion + 1.0
else
0.0
@@ -283,7 +283,7 @@ class Scene
@spheres[1].intersect(ray, isect)
@spheres[2].intersect(ray, isect)
@plane.intersect(ray, isect)
if isect.hit then
if isect.hit
col = ambient_occlusion(isect)
rad.x = rad.x + col.x
rad.y = rad.y + col.y
+3 -3
View File
@@ -17,19 +17,19 @@ def test_lists()
# li2 must now be empty
# remove each individual item from right side of li3 and
# append to right side of li2 (reversing list)
while (not li3.empty?)
until li3.empty?
li2.push(li3.pop)
end
# li3 must now be empty
# reverse li1 in place
li1.reverse!
# check that first item is now SIZE
if li1[0] != SIZE then
if li1[0] != SIZE
p "not SIZE"
0
else
# compare li1 and li2 for equality
if li1 != li2 then
if li1 != li2
return(0)
else
# return the length of the list
+11 -12
View File
@@ -124,17 +124,17 @@ MRuby::Build.new('test') do |conf|
conf.gembox 'default'
end
MRuby::Build.new('bench') do |conf|
# Gets set by the VS command prompts.
if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
toolchain :visualcpp
else
toolchain :gcc
conf.cc.flags << '-O3'
end
conf.gembox 'default'
end
#MRuby::Build.new('bench') do |conf|
# # Gets set by the VS command prompts.
# if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
# toolchain :visualcpp
# else
# toolchain :gcc
# conf.cc.flags << '-O3'
# end
#
# conf.gembox 'default'
#end
# Define cross build settings
# MRuby::CrossBuild.new('32bit') do |conf|
@@ -148,5 +148,4 @@ end
# conf.gem 'examples/mrbgems/c_and_ruby_extension_example'
#
# conf.test_runner.command = 'env'
#
# end
+1 -1
View File
@@ -38,7 +38,7 @@ To confirm mrdb was installed properly, run mrdb with the `--version` option:
```bash
$ mrdb --version
mruby 1.3.0 (2017-7-4)
mruby 1.4.0 (2018-1-16)
```
## 2.2 Basic Operation
+5 -5
View File
@@ -114,14 +114,14 @@ inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list)
mrb_ary_push(mrb, list, ary);
arystr = mrb_str_buf_new(mrb, 64);
mrb_str_buf_cat(mrb, arystr, head, sizeof(head));
arystr = mrb_str_new_capa(mrb, 64);
mrb_str_cat(mrb, arystr, head, sizeof(head));
for(i=0; i<RARRAY_LEN(ary); i++) {
int ai = mrb_gc_arena_save(mrb);
if (i > 0) {
mrb_str_buf_cat(mrb, arystr, sep, sizeof(sep));
mrb_str_cat(mrb, arystr, sep, sizeof(sep));
}
if (mrb_array_p(RARRAY_PTR(ary)[i])) {
s = inspect_ary(mrb, RARRAY_PTR(ary)[i], list);
@@ -129,11 +129,11 @@ inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list)
else {
s = mrb_inspect(mrb, RARRAY_PTR(ary)[i]);
}
mrb_str_buf_cat(mrb, arystr, RSTRING_PTR(s), RSTRING_LEN(s));
mrb_str_cat(mrb, arystr, RSTRING_PTR(s), RSTRING_LEN(s));
mrb_gc_arena_restore(mrb, ai);
}
mrb_str_buf_cat(mrb, arystr, tail, sizeof(tail));
mrb_str_cat(mrb, arystr, tail, sizeof(tail));
mrb_ary_pop(mrb, list);
return arystr;
+1 -12
View File
@@ -122,20 +122,9 @@ largest value of required alignment.
* If defined `Float` will be a mruby object with `RBasic`.
## Instance variable configuration.
`MRB_USE_IV_SEGLIST`
* If defined enable segmented list in instance variable table instead of khash.
* Segmented list is a linked list of key and value segments.
* It will linear search instead of hash search.
`MRB_SEGMENT_SIZE`
`MRB_IV_SEGMENT_SIZE`
* Default value is `4`.
* Specifies size of each segment in segment list.
* Ignored when `MRB_USE_IV_SEGLIST` isn't defined.
`MRB_IVHASH_INIT_SIZE`
* Default value is `8`.
* Specifies initial size for instance variable table.
* Ignored when `MRB_USE_IV_SEGLIST` is defined.
## Other configuration.
`MRB_UTF8_STRING`
+7 -28
View File
@@ -38,7 +38,7 @@ puts [1,2,3]
3
```
#### mruby [1.3.0 (2017-7-4)]
#### mruby [1.4.0 (2018-1-16)]
```
[1, 2, 3]
@@ -61,26 +61,10 @@ end
```ZeroDivisionError``` is raised.
#### mruby [1.3.0 (2017-7-4)]
#### mruby [1.4.0 (2018-1-16)]
No exception is raised.
## Check of infinite recursion
mruby does not check infinite recursion across C extensions.
```ruby
def test; eval 'test'; end; test
```
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
```SystemStackError``` is raised.
#### mruby [1.3.0 (2017-7-4)]
Segmentation fault.
## Fiber execution can't cross C function boundary
mruby's ```Fiber``` is implemented in a similar way to Lua's co-routine. This
@@ -105,7 +89,7 @@ p Liste.new "foobar"
``` [] ```
#### mruby [1.3.0 (2017-7-4)]
#### mruby [1.4.0 (2018-1-16)]
```ArgumentError``` is raised.
@@ -135,7 +119,7 @@ false
true
```
#### mruby [1.3.0 (2017-7-4)]
#### mruby [1.4.0 (2018-1-16)]
```
true
@@ -158,7 +142,7 @@ defined?(Foo)
nil
```
#### mruby [1.3.0 (2017-7-4)]
#### mruby [1.4.0 (2018-1-16)]
```NameError``` is raised.
@@ -175,7 +159,7 @@ alias $a $__a__
``` nil ```
#### mruby [1.3.0 (2017-7-4)]
#### mruby [1.4.0 (2018-1-16)]
Syntax error
@@ -197,12 +181,7 @@ end
```ArgumentError``` is raised.
The re-defined ```+``` operator does not accept any arguments.
#### mruby [1.3.0 (2017-7-4)]
#### mruby [1.4.0 (2018-1-16)]
``` 'ab' ```
Behavior of the operator wasn't changed.
## ```Kernel.binding``` missing
```Kernel.binding``` is not implemented as it is not in the
ISO standard.
@@ -46,7 +46,6 @@ MRuby::CrossBuild.new("ArduinoDue") do |conf|
#configuration for low memory environment
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
cc.defines << %w(MRB_USE_IV_SEGLIST)
cc.defines << %w(KHASH_DEFAULT_SIZE=8)
cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20)
cc.defines << %w(MRB_GC_STRESS)
-1
View File
@@ -32,7 +32,6 @@ MRuby::CrossBuild.new("RX630") do |conf|
#configuration for low memory environment
cc.defines << %w(MRB_USE_FLOAT)
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
cc.defines << %w(MRB_USE_IV_SEGLIST)
cc.defines << %w(KHASH_DEFAULT_SIZE=8)
cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20)
cc.defines << %w(MRB_GC_STRESS)
@@ -43,7 +43,6 @@ MRuby::CrossBuild.new("chipKITMax32") do |conf|
#configuration for low memory environment
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
cc.defines << %w(MRB_USE_IV_SEGLIST)
cc.defines << %w(KHASH_DEFAULT_SIZE=8)
cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20)
cc.defines << %w(MRB_GC_STRESS)
+29 -9
View File
@@ -28,13 +28,39 @@
/* add -DMRB_USE_FLOAT to use float instead of double for floating point numbers */
//#define MRB_USE_FLOAT
/* exclude floating point numbers */
//#define MRB_WITHOUT_FLOAT
/* add -DMRB_METHOD_CACHE to use method cache to improve performance */
//#define MRB_METHOD_CACHE
/* size of the method cache (need to be the power of 2) */
//#define MRB_METHOD_CACHE_SIZE (1<<7)
/* add -DMRB_METHOD_TABLE_INLINE unless platform uses MSB of pointers */
//#define MRB_METHOD_TABLE_INLINE
/* turn MRB_METHOD_TABLE_INLINE on for linux by default */
#if !defined(MRB_METHOD_TABLE_INLINE) && defined(__linux__)
# define MRB_METHOD_TABLE_INLINE
#endif
/* add -DMRB_INT16 to use 16bit integer for mrb_int; conflict with MRB_INT64 */
//#define MRB_INT16
/* add -DMRB_INT64 to use 64bit integer for mrb_int; conflict with MRB_INT16 */
//#define MRB_INT64
/* represent mrb_value in boxed double; conflict with MRB_USE_FLOAT */
/* if no specific integer type is chosen */
#if !defined(MRB_INT16) && !defined(MRB_INT32) && !defined(MRB_INT64)
# if defined(MRB_64BIT) && !defined(MRB_NAN_BOXING)
/* Use 64bit integers on 64bit architecture (without MRB_NAN_BOXING) */
# define MRB_INT64
# else
/* Otherwise use 32bit integers */
# define MRB_INT32
# endif
#endif
/* represent mrb_value in boxed double; conflict with MRB_USE_FLOAT and MRB_WITHOUT_FLOAT */
//#define MRB_NAN_BOXING
/* define on big endian machines; used by MRB_NAN_BOXING */
@@ -52,12 +78,6 @@
/* number of object per heap page */
//#define MRB_HEAP_PAGE_SIZE 1024
/* use segmented list for IV table */
//#define MRB_USE_IV_SEGLIST
/* initial size for IV khash; ignored when MRB_USE_IV_SEGLIST is set */
//#define MRB_IVHASH_INIT_SIZE 8
/* if _etext and _edata available, mruby can reduce memory used by symbols */
//#define MRB_USE_ETEXT_EDATA
@@ -93,10 +113,10 @@
//#define MRB_FIXED_STATE_ATEXIT_STACK
/* -DMRB_DISABLE_XXXX to drop following features */
//#define MRB_DISABLE_STDIO /* use of stdio */
//#define MRB_DISABLE_STDIO /* use of stdio */
/* -DMRB_ENABLE_XXXX to enable following features */
//#define MRB_ENABLE_DEBUG_HOOK /* hooks for debugger */
//#define MRB_ENABLE_DEBUG_HOOK /* hooks for debugger */
/* end of configuration */
+91 -21
View File
@@ -1,7 +1,7 @@
/*
** mruby - An embeddable Ruby implementation
**
** Copyright (c) mruby developers 2010-2017
** Copyright (c) mruby developers 2010-2018
**
** Permission is hereby granted, free of charge, to any person obtaining
** a copy of this software and associated documentation files (the
@@ -65,11 +65,23 @@
#include "mrbconf.h"
#ifndef MRB_WITHOUT_FLOAT
#ifndef FLT_EPSILON
#define FLT_EPSILON (1.19209290e-07f)
#endif
#ifndef DBL_EPSILON
#define DBL_EPSILON ((double)2.22044604925031308085e-16L)
#endif
#ifndef LDBL_EPSILON
#define LDBL_EPSILON (1.08420217248550443401e-19L)
#endif
#ifdef MRB_USE_FLOAT
#define MRB_FLOAT_EPSILON FLT_EPSILON
#else
#define MRB_FLOAT_EPSILON DBL_EPSILON
#endif
#endif
#include "mruby/common.h"
#include <mruby/value.h>
@@ -150,6 +162,36 @@ struct mrb_context {
struct RFiber *fib;
};
#ifdef MRB_METHOD_CACHE_SIZE
# define MRB_METHOD_CACHE
#else
/* default method cache size: 128 */
/* cache size needs to be power of 2 */
# define MRB_METHOD_CACHE_SIZE (1<<7)
#endif
typedef mrb_value (*mrb_func_t)(struct mrb_state *mrb, mrb_value);
#ifdef MRB_METHOD_TABLE_INLINE
typedef uintptr_t mrb_method_t;
#else
typedef struct {
mrb_bool func_p;
union {
struct RProc *proc;
mrb_func_t func;
};
} mrb_method_t;
#endif
#ifdef MRB_METHOD_CACHE
struct mrb_cache_entry {
struct RClass *c, *c0;
mrb_sym mid;
mrb_method_t m;
};
#endif
struct mrb_jmpbuf;
typedef void (*mrb_atexit_func)(struct mrb_state*);
@@ -178,8 +220,11 @@ typedef struct mrb_state {
struct RClass *string_class;
struct RClass *array_class;
struct RClass *hash_class;
struct RClass *range_class;
#ifndef MRB_WITHOUT_FLOAT
struct RClass *float_class;
#endif
struct RClass *fixnum_class;
struct RClass *true_class;
struct RClass *false_class;
@@ -190,6 +235,10 @@ typedef struct mrb_state {
struct alloca_header *mems;
mrb_gc gc;
#ifdef MRB_METHOD_CACHE
struct mrb_cache_entry cache[MRB_METHOD_CACHE_SIZE];
#endif
mrb_sym symidx;
struct kh_n2s *name2sym; /* symbol hash */
struct symbol_name *symtbl; /* symbol table */
@@ -222,9 +271,6 @@ typedef struct mrb_state {
mrb_int atexit_stack_len;
} mrb_state;
typedef mrb_value (*mrb_func_t)(mrb_state *mrb, mrb_value);
/**
* Defines a new class.
*
@@ -827,11 +873,14 @@ mrb_get_mid(mrb_state *mrb) /* get method symbol */
return mrb->c->ci->mid;
}
static inline int
mrb_get_argc(mrb_state *mrb) /* get argc */
{
return mrb->c->ci->argc;
}
/**
* Retrieve number of arguments from mrb_state.
*
* Correctly handles *splat arguments.
*/
MRB_API mrb_int mrb_get_argc(mrb_state *mrb);
MRB_API mrb_value* mrb_get_argv(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.
@@ -945,13 +994,13 @@ MRB_API mrb_value mrb_str_new_static(mrb_state *mrb, const char *p, size_t len);
#define mrb_str_new_lit(mrb, lit) mrb_str_new_static(mrb, (lit), mrb_strlen_lit(lit))
#ifdef _WIN32
char* mrb_utf8_from_locale(const char *p, size_t len);
char* mrb_locale_from_utf8(const char *p, size_t len);
char* mrb_utf8_from_locale(const char *p, int len);
char* mrb_locale_from_utf8(const char *p, int len);
#define mrb_locale_free(p) free(p)
#define mrb_utf8_free(p) free(p)
#else
#define mrb_utf8_from_locale(p, l) (p)
#define mrb_locale_from_utf8(p, l) (p)
#define mrb_utf8_from_locale(p, l) ((char*)p)
#define mrb_locale_from_utf8(p, l) ((char*)p)
#define mrb_locale_free(p)
#define mrb_utf8_free(p)
#endif
@@ -1023,17 +1072,35 @@ MRB_API mrb_sym mrb_obj_to_sym(mrb_state *mrb, mrb_value name);
MRB_API mrb_bool mrb_obj_eq(mrb_state*, mrb_value, mrb_value);
MRB_API mrb_bool mrb_obj_equal(mrb_state*, mrb_value, mrb_value);
MRB_API mrb_bool mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2);
MRB_API mrb_value mrb_convert_to_integer(mrb_state *mrb, mrb_value val, int base);
MRB_API mrb_value mrb_convert_to_integer(mrb_state *mrb, mrb_value val, mrb_int base);
MRB_API mrb_value mrb_Integer(mrb_state *mrb, mrb_value val);
#ifndef MRB_WITHOUT_FLOAT
MRB_API mrb_value mrb_Float(mrb_state *mrb, mrb_value val);
#endif
MRB_API mrb_value mrb_inspect(mrb_state *mrb, mrb_value obj);
MRB_API mrb_bool mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2);
static inline int mrb_gc_arena_save(mrb_state*);
static inline void mrb_gc_arena_restore(mrb_state*,int);
static inline int
mrb_gc_arena_save(mrb_state *mrb)
{
return mrb->gc.arena_idx;
}
static inline void
mrb_gc_arena_restore(mrb_state *mrb, int idx)
{
mrb->gc.arena_idx = idx;
}
MRB_API int mrb_gc_arena_save(mrb_state*);
MRB_API void mrb_gc_arena_restore(mrb_state*,int);
MRB_API void mrb_garbage_collect(mrb_state*);
MRB_API void mrb_full_gc(mrb_state*);
MRB_API void mrb_incremental_gc(mrb_state *);
MRB_API int mrb_gc_arena_save(mrb_state*);
MRB_API void mrb_gc_arena_restore(mrb_state*,int);
MRB_API void mrb_gc_mark(mrb_state*,struct RBasic*);
#define mrb_gc_mark_value(mrb,val) do {\
if (!mrb_immediate_p(val)) mrb_gc_mark((mrb), mrb_basic_ptr(val)); \
@@ -1097,9 +1164,12 @@ MRB_API void mrb_print_error(mrb_state *mrb);
#define E_SYNTAX_ERROR (mrb_exc_get(mrb, "SyntaxError"))
#define E_LOCALJUMP_ERROR (mrb_exc_get(mrb, "LocalJumpError"))
#define E_REGEXP_ERROR (mrb_exc_get(mrb, "RegexpError"))
#define E_FROZEN_ERROR (mrb_exc_get(mrb, "FrozenError"))
#define E_NOTIMP_ERROR (mrb_exc_get(mrb, "NotImplementedError"))
#ifndef MRB_WITHOUT_FLOAT
#define E_FLOATDOMAIN_ERROR (mrb_exc_get(mrb, "FloatDomainError"))
#endif
#define E_KEY_ERROR (mrb_exc_get(mrb, "KeyError"))
@@ -1183,21 +1253,21 @@ MRB_API mrb_value mrb_format(mrb_state *mrb, const char *format, ...);
/* use naive memcpy and memset instead */
#undef memcpy
#undef memset
static inline void*
static void*
mrbmemcpy(void *dst, const void *src, size_t n)
{
char *d = dst;
const char *s = src;
char *d = (char*)dst;
const char *s = (const char*)src;
while (n--)
*d++ = *s++;
return d;
}
#define memcpy(a,b,c) mrbmemcpy(a,b,c)
static inline void*
static void*
mrbmemset(void *s, int c, size_t n)
{
char *t = s;
char *t = (char*)s;
while (n--)
*t++ = c;
return s;
+44 -26
View File
@@ -21,22 +21,46 @@ typedef struct mrb_shared_array {
mrb_value *ptr;
} mrb_shared_array;
#define MRB_ARY_EMBED_LEN_MAX ((mrb_int)(sizeof(void*)*3/sizeof(mrb_value)))
struct RArray {
MRB_OBJECT_HEADER;
mrb_int len;
union {
mrb_int capa;
mrb_shared_array *shared;
} aux;
mrb_value *ptr;
struct {
mrb_int len;
union {
mrb_int capa;
mrb_shared_array *shared;
} aux;
mrb_value *ptr;
} heap;
mrb_value embed[MRB_ARY_EMBED_LEN_MAX];
} as;
};
#define mrb_ary_ptr(v) ((struct RArray*)(mrb_ptr(v)))
#define mrb_ary_value(p) mrb_obj_value((void*)(p))
#define RARRAY(v) ((struct RArray*)(mrb_ptr(v)))
#define RARRAY_LEN(a) (RARRAY(a)->len)
#define RARRAY_PTR(a) ((const mrb_value*)RARRAY(a)->ptr)
#define MRB_ARY_EMBED_MASK 7
#define ARY_EMBED_P(a) ((a)->flags & MRB_ARY_EMBED_MASK)
#define ARY_UNSET_EMBED_FLAG(a) ((a)->flags &= ~(MRB_ARY_EMBED_MASK))
#define ARY_EMBED_LEN(a) ((mrb_int)(((a)->flags & MRB_ARY_EMBED_MASK) - 1))
#define ARY_SET_EMBED_LEN(a,len) ((a)->flags = ((a)->flags&~MRB_ARY_EMBED_MASK) | ((uint32_t)(len) + 1))
#define ARY_EMBED_PTR(a) (&((a)->as.embed[0]))
#define ARY_LEN(a) (ARY_EMBED_P(a)?ARY_EMBED_LEN(a):(a)->as.heap.len)
#define ARY_PTR(a) (ARY_EMBED_P(a)?ARY_EMBED_PTR(a):(a)->as.heap.ptr)
#define RARRAY_LEN(a) ARY_LEN(RARRAY(a))
#define RARRAY_PTR(a) ARY_PTR(RARRAY(a))
#define ARY_SET_LEN(a,n) do {\
if (ARY_EMBED_P(a)) {\
mrb_assert((n) <= MRB_ARY_EMBED_LEN_MAX); \
ARY_SET_EMBED_LEN(a,n);\
}\
else\
(a)->as.heap.len = (n);\
} while (0)
#define ARY_CAPA(a) (ARY_EMBED_P(a)?MRB_ARY_EMBED_LEN_MAX:(a)->as.heap.aux.capa)
#define MRB_ARY_SHARED 256
#define ARY_SHARED_P(a) ((a)->flags & MRB_ARY_SHARED)
#define ARY_SET_SHARED_FLAG(a) ((a)->flags |= MRB_ARY_SHARED)
@@ -178,7 +202,7 @@ MRB_API void mrb_ary_replace(mrb_state *mrb, mrb_value self, mrb_value other);
MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self);
/*
* Unshift an element into an array
* Unshift an element into the array
*
* Equivalent to:
*
@@ -189,6 +213,17 @@ MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self);
* @param item The item to unshift.
*/
MRB_API mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item);
/*
* Get nth element in the array
*
* Equivalent to:
*
* ary[offset]
*
* @param ary The target array.
* @param offset The element position (negative counts from the tail).
*/
MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset);
/*
@@ -205,7 +240,7 @@ MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset);
MRB_API mrb_value mrb_ary_shift(mrb_state *mrb, mrb_value self);
/*
* Removes all elements from this array
* Removes all elements from the array
*
* Equivalent to:
*
@@ -239,23 +274,6 @@ 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);
static inline mrb_int
mrb_ary_len(mrb_state *mrb, mrb_value ary)
{
(void)mrb;
mrb_assert(mrb_array_p(ary));
return RARRAY_LEN(ary);
}
static inline mrb_value
ary_elt(mrb_value ary, mrb_int offset)
{
if (offset < 0 || RARRAY_LEN(ary) <= offset) {
return mrb_nil_value();
}
return RARRAY_PTR(ary)[offset];
}
MRB_END_DECL
#endif /* MRUBY_ARRAY_H */
+4
View File
@@ -11,6 +11,10 @@
# error ---->> MRB_NAN_BOXING and MRB_USE_FLOAT conflict <<----
#endif
#ifdef MRB_WITHOUT_FLOAT
# error ---->> MRB_NAN_BOXING and MRB_WITHOUT_FLOAT conflict <<----
#endif
#ifdef MRB_INT64
# error ---->> MRB_NAN_BOXING and MRB_INT64 conflict <<----
#endif
+8
View File
@@ -12,7 +12,9 @@
typedef struct mrb_value {
union {
#ifndef MRB_WITHOUT_FLOAT
mrb_float f;
#endif
void *p;
mrb_int i;
mrb_sym sym;
@@ -20,11 +22,15 @@ typedef struct mrb_value {
enum mrb_vtype tt;
} mrb_value;
#ifndef MRB_WITHOUT_FLOAT
#define mrb_float_pool(mrb,f) mrb_float_value(mrb,f)
#endif
#define mrb_ptr(o) (o).value.p
#define mrb_cptr(o) mrb_ptr(o)
#ifndef MRB_WITHOUT_FLOAT
#define mrb_float(o) (o).value.f
#endif
#define mrb_fixnum(o) (o).value.i
#define mrb_symbol(o) (o).value.sym
#define mrb_type(o) (o).tt
@@ -39,7 +45,9 @@ typedef struct mrb_value {
#define SET_TRUE_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_TRUE, value.i, 1)
#define SET_BOOL_VALUE(r,b) BOXNIX_SET_VALUE(r, b ? MRB_TT_TRUE : MRB_TT_FALSE, value.i, 1)
#define SET_INT_VALUE(r,n) BOXNIX_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n))
#ifndef MRB_WITHOUT_FLOAT
#define SET_FLOAT_VALUE(mrb,r,v) BOXNIX_SET_VALUE(r, MRB_TT_FLOAT, value.f, (v))
#endif
#define SET_SYM_VALUE(r,v) BOXNIX_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v))
#define SET_OBJ_VALUE(r,v) BOXNIX_SET_VALUE(r, (((struct RObject*)(v))->tt), value.p, (v))
#define SET_CPTR_VALUE(mrb,r,v) BOXNIX_SET_VALUE(r, MRB_TT_CPTR, value.p, v)
+16
View File
@@ -15,10 +15,12 @@
#error MRB_INT64 cannot be used with MRB_WORD_BOXING in 32-bit mode.
#endif
#ifndef MRB_WITHOUT_FLOAT
struct RFloat {
MRB_OBJECT_HEADER;
mrb_float f;
};
#endif
struct RCptr {
MRB_OBJECT_HEADER;
@@ -26,7 +28,11 @@ struct RCptr {
};
#define MRB_FIXNUM_SHIFT 1
#ifdef MRB_WITHOUT_FLOAT
#define MRB_TT_HAS_BASIC MRB_TT_CPTR
#else
#define MRB_TT_HAS_BASIC MRB_TT_FLOAT
#endif
enum mrb_special_consts {
MRB_Qnil = 0,
@@ -51,21 +57,29 @@ typedef union mrb_value {
mrb_sym sym : (sizeof(mrb_sym) * CHAR_BIT);
};
struct RBasic *bp;
#ifndef MRB_WITHOUT_FLOAT
struct RFloat *fp;
#endif
struct RCptr *vp;
} value;
unsigned long w;
} mrb_value;
MRB_API mrb_value mrb_word_boxing_cptr_value(struct mrb_state*, void*);
#ifndef MRB_WITHOUT_FLOAT
MRB_API mrb_value mrb_word_boxing_float_value(struct mrb_state*, mrb_float);
MRB_API mrb_value mrb_word_boxing_float_pool(struct mrb_state*, mrb_float);
#endif
#ifndef MRB_WITHOUT_FLOAT
#define mrb_float_pool(mrb,f) mrb_word_boxing_float_pool(mrb,f)
#endif
#define mrb_ptr(o) (o).value.p
#define mrb_cptr(o) (o).value.vp->p
#ifndef MRB_WITHOUT_FLOAT
#define mrb_float(o) (o).value.fp->f
#endif
#define mrb_fixnum(o) ((mrb_int)(o).value.i)
#define mrb_symbol(o) (o).value.sym
@@ -106,7 +120,9 @@ mrb_type(mrb_value o)
}\
} while (0)
#ifndef MRB_WITHOUT_FLOAT
#define SET_FLOAT_VALUE(mrb,r,v) r = mrb_word_boxing_float_value(mrb, v)
#endif
#define SET_CPTR_VALUE(mrb,r,v) r = mrb_word_boxing_cptr_value(mrb, v)
#define SET_NIL_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_FALSE, value.i, 0)
#define SET_FALSE_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_FALSE, value.i, 1)
+9 -5
View File
@@ -40,8 +40,10 @@ mrb_class(mrb_state *mrb, mrb_value v)
return mrb->symbol_class;
case MRB_TT_FIXNUM:
return mrb->fixnum_class;
#ifndef MRB_WITHOUT_FLOAT
case MRB_TT_FLOAT:
return mrb->float_class;
#endif
case MRB_TT_CPTR:
return mrb->object_class;
case MRB_TT_ENV:
@@ -52,7 +54,7 @@ mrb_class(mrb_state *mrb, mrb_value v)
}
/* TODO: figure out where to put user flags */
#define MRB_FLAG_IS_FROZEN (1 << 18)
/* flags bits >= 18 is reserved */
#define MRB_FLAG_IS_PREPENDED (1 << 19)
#define MRB_FLAG_IS_ORIGIN (1 << 20)
#define MRB_CLASS_ORIGIN(c) do {\
@@ -63,6 +65,7 @@ mrb_class(mrb_state *mrb, mrb_value v)
}\
}\
} while (0)
#define MRB_FLAG_IS_INHERITED (1 << 21)
#define MRB_INSTANCE_TT_MASK (0xFF)
#define MRB_SET_INSTANCE_TT(c, tt) c->flags = ((c->flags & ~MRB_INSTANCE_TT_MASK) | (char)tt)
#define MRB_INSTANCE_TT(c) (enum mrb_vtype)(c->flags & MRB_INSTANCE_TT_MASK)
@@ -71,16 +74,17 @@ MRB_API struct RClass* mrb_define_class_id(mrb_state*, mrb_sym, struct RClass*);
MRB_API struct RClass* mrb_define_module_id(mrb_state*, mrb_sym);
MRB_API struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb_sym);
MRB_API struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym);
MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, struct RProc *);
MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, mrb_method_t);
MRB_API void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec);
MRB_API void mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b);
MRB_API struct RClass *mrb_class_outer_module(mrb_state*, struct RClass *);
MRB_API struct RProc *mrb_method_search_vm(mrb_state*, struct RClass**, mrb_sym);
MRB_API struct RProc *mrb_method_search(mrb_state*, struct RClass*, mrb_sym);
MRB_API mrb_method_t mrb_method_search_vm(mrb_state*, struct RClass**, mrb_sym);
MRB_API mrb_method_t mrb_method_search(mrb_state*, struct RClass*, mrb_sym);
MRB_API struct RClass* mrb_class_real(struct RClass* cl);
void mrb_class_name_class(mrb_state*, struct RClass*, struct RClass*, mrb_sym);
mrb_value mrb_class_find_path(mrb_state*, struct RClass*);
void mrb_gc_mark_mt(mrb_state*, struct RClass*);
size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*);
void mrb_gc_free_mt(mrb_state*, struct RClass*);
+1 -1
View File
@@ -14,7 +14,7 @@
#define MRB_END_DECL
#else
# define MRB_BEGIN_DECL extern "C" {
# define MRB_END_DECL }
# define MRB_END_DECL }
#endif
#else
/** Start declarations in C mode */
+6 -5
View File
@@ -33,6 +33,8 @@ typedef struct mrbc_context {
mrb_bool no_exec:1;
mrb_bool keep_lv:1;
mrb_bool no_optimize:1;
size_t parser_nerr;
} mrbc_context;
MRB_API mrbc_context* mrbc_context_new(mrb_state *mrb);
@@ -136,7 +138,7 @@ struct mrb_parser_state {
int tidx;
int tsiz;
mrb_ast_node *all_heredocs; /* list of mrb_parser_heredoc_info* */
mrb_ast_node *all_heredocs; /* list of mrb_parser_heredoc_info* */
mrb_ast_node *heredocs_from_nextline;
mrb_ast_node *parsing_heredoc;
mrb_ast_node *lex_strterm_before_heredoc;
@@ -163,7 +165,6 @@ struct mrb_parser_state {
MRB_API struct mrb_parser_state* mrb_parser_new(mrb_state*);
MRB_API void mrb_parser_free(struct mrb_parser_state*);
MRB_API void mrb_parser_parse(struct mrb_parser_state*,mrbc_context*);
MRB_API double mrb_float_read(const char*, char**);
MRB_API void mrb_parser_set_filename(struct mrb_parser_state*, char const*);
MRB_API char const* mrb_parser_get_filename(struct mrb_parser_state*, uint16_t idx);
@@ -173,7 +174,7 @@ MRB_API char const* mrb_parser_get_filename(struct mrb_parser_state*, uint16_t i
MRB_API struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*);
#endif
MRB_API struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*,mrbc_context*);
MRB_API struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,int,mrbc_context*);
MRB_API struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,size_t,mrbc_context*);
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);
@@ -183,9 +184,9 @@ MRB_API mrb_value mrb_load_file(mrb_state*,FILE*);
MRB_API mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrbc_context *cxt);
#endif
MRB_API mrb_value mrb_load_string(mrb_state *mrb, const char *s);
MRB_API mrb_value mrb_load_nstring(mrb_state *mrb, const char *s, int len);
MRB_API mrb_value mrb_load_nstring(mrb_state *mrb, const char *s, size_t len);
MRB_API mrb_value mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *cxt);
MRB_API mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *cxt);
MRB_API mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *s, size_t len, mrbc_context *cxt);
/** @} */
MRB_END_DECL
+2 -2
View File
@@ -47,13 +47,13 @@ typedef struct mrb_irep_debug_info {
* get line from irep's debug info and program counter
* @return returns NULL if not found
*/
MRB_API const char *mrb_debug_get_filename(mrb_irep *irep, uint32_t pc);
MRB_API const char *mrb_debug_get_filename(mrb_irep *irep, ptrdiff_t pc);
/*
* get line from irep's debug info and program counter
* @return returns -1 if not found
*/
MRB_API int32_t mrb_debug_get_line(mrb_irep *irep, uint32_t pc);
MRB_API int32_t mrb_debug_get_line(mrb_irep *irep, ptrdiff_t pc);
MRB_API mrb_irep_debug_info_file *mrb_debug_info_append_file(
mrb_state *mrb, mrb_irep *irep,
+1 -2
View File
@@ -24,7 +24,7 @@ struct RException {
MRB_API void mrb_sys_fail(mrb_state *mrb, const char *mesg);
MRB_API mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str);
#define mrb_exc_new_str_lit(mrb, c, lit) mrb_exc_new_str(mrb, c, mrb_str_new_lit(mrb, lit))
MRB_API mrb_value mrb_make_exception(mrb_state *mrb, int argc, const mrb_value *argv);
MRB_API mrb_value mrb_make_exception(mrb_state *mrb, mrb_int argc, const mrb_value *argv);
MRB_API mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc);
MRB_API mrb_value mrb_get_backtrace(mrb_state *mrb);
MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, const char *fmt, ...);
@@ -34,7 +34,6 @@ MRB_API mrb_value mrb_f_raise(mrb_state*, mrb_value);
struct RBreak {
MRB_OBJECT_HEADER;
struct iv_tbl *iv;
struct RProc *proc;
mrb_value val;
};
+11
View File
@@ -33,6 +33,13 @@ typedef enum {
MRB_GC_STATE_SWEEP
} mrb_gc_state;
/* Disable MSVC warning "C4200: nonstandard extension used: zero-sized array
* in struct/union" when in C++ mode */
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4200)
#endif
typedef struct mrb_heap_page {
struct RBasic *freelist;
struct mrb_heap_page *prev;
@@ -43,6 +50,10 @@ typedef struct mrb_heap_page {
void *objects[];
} mrb_heap_page;
#ifdef _MSC_VER
#pragma warning(pop)
#endif
typedef struct mrb_gc {
mrb_heap_page *heaps; /* heaps for GC */
mrb_heap_page *sweeps;
+2 -1
View File
@@ -44,7 +44,7 @@ typedef struct mrb_irep {
uint16_t *lines;
struct mrb_irep_debug_info* debug_info;
size_t ilen, plen, slen, rlen, refcnt;
int ilen, plen, slen, rlen, refcnt;
} mrb_irep;
#define MRB_ISEQ_NO_FREE 1
@@ -55,6 +55,7 @@ MRB_API mrb_value mrb_load_irep_cxt(mrb_state*, const uint8_t*, mrbc_context*);
void mrb_irep_free(mrb_state*, struct mrb_irep*);
void mrb_irep_incref(mrb_state*, struct mrb_irep*);
void mrb_irep_decref(mrb_state*, struct mrb_irep*);
void mrb_irep_cutref(mrb_state*, struct mrb_irep*);
MRB_END_DECL
+13 -9
View File
@@ -16,21 +16,25 @@
*/
MRB_BEGIN_DECL
#define POSFIXABLE(f) ((f) <= MRB_INT_MAX)
#define NEGFIXABLE(f) ((f) >= MRB_INT_MIN)
#define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f))
#ifdef MRB_INT64
#define FIXABLE_FLOAT(f) FIXABLE((mrb_int)(f))
#else
#define FIXABLE_FLOAT(f) FIXABLE(f)
#define TYPED_POSFIXABLE(f,t) ((f) <= (t)MRB_INT_MAX)
#define TYPED_NEGFIXABLE(f,t) ((f) >= (t)MRB_INT_MIN)
#define TYPED_FIXABLE(f,t) (TYPED_POSFIXABLE(f,t) && TYPED_NEGFIXABLE(f,t))
#define POSFIXABLE(f) TYPED_POSFIXABLE(f,mrb_int)
#define NEGFIXABLE(f) TYPED_NEGFIXABLE(f,mrb_int)
#define FIXABLE(f) TYPED_FIXABLE(f,mrb_int)
#ifndef MRB_WITHOUT_FLOAT
#define FIXABLE_FLOAT(f) TYPED_FIXABLE(f,double)
#endif
#ifndef MRB_WITHOUT_FLOAT
MRB_API mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val);
MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base);
#endif
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 mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x);
#endif
mrb_value mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y);
mrb_value mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y);
+2
View File
@@ -22,6 +22,8 @@ struct RBasic {
};
#define mrb_basic_ptr(v) ((struct RBasic*)(mrb_ptr(v)))
/* flags bits >= 18 is reserved */
#define MRB_FLAG_IS_FROZEN (1 << 18)
#define MRB_FROZEN_P(o) ((o)->flags & MRB_FLAG_IS_FROZEN)
#define MRB_SET_FROZEN_FLAG(o) ((o)->flags |= MRB_FLAG_IS_FROZEN)
#define MRB_UNSET_FROZEN_FLAG(o) ((o)->flags &= ~MRB_FLAG_IS_FROZEN)
+63 -15
View File
@@ -18,19 +18,20 @@ MRB_BEGIN_DECL
struct REnv {
MRB_OBJECT_HEADER;
mrb_value *stack;
ptrdiff_t cioff;
union {
mrb_sym mid;
struct mrb_context *c;
} cxt;
struct mrb_context *cxt;
mrb_sym mid;
};
#define MRB_SET_ENV_STACK_LEN(e,len) (e)->flags = (unsigned int)(len)
#define MRB_ENV_STACK_LEN(e) ((mrb_int)(e)->flags)
#define MRB_ENV_UNSHARE_STACK(e) ((e)->cioff = -1)
#define MRB_ENV_STACK_SHARED_P(e) ((e)->cioff >= 0)
/* 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)
MRB_API void mrb_env_unshare(mrb_state*, struct REnv*);
void mrb_env_unshare(mrb_state*, struct REnv*);
struct RProc {
MRB_OBJECT_HEADER;
@@ -38,8 +39,11 @@ struct RProc {
mrb_irep *irep;
mrb_func_t func;
} body;
struct RClass *target_class;
struct REnv *env;
struct RProc *upper;
union {
struct RClass *target_class;
struct REnv *env;
} e;
};
/* aspec access */
@@ -51,12 +55,29 @@ struct RProc {
#define MRB_ASPEC_KDICT(a) ((a) & (1<<1))
#define MRB_ASPEC_BLOCK(a) ((a) & 1)
#define MRB_PROC_CFUNC 128
#define MRB_PROC_CFUNC_P(p) (((p)->flags & MRB_PROC_CFUNC) != 0)
#define MRB_PROC_CFUNC_FL 128
#define MRB_PROC_CFUNC_P(p) (((p)->flags & MRB_PROC_CFUNC_FL) != 0)
#define MRB_PROC_CFUNC(p) (p)->body.func
#define MRB_PROC_STRICT 256
#define MRB_PROC_STRICT_P(p) (((p)->flags & MRB_PROC_STRICT) != 0)
#define MRB_PROC_ORPHAN 512
#define MRB_PROC_ORPHAN_P(p) (((p)->flags & MRB_PROC_ORPHAN) != 0)
#define MRB_PROC_ENVSET 1024
#define MRB_PROC_ENV_P(p) (((p)->flags & MRB_PROC_ENVSET) != 0)
#define MRB_PROC_ENV(p) (MRB_PROC_ENV_P(p) ? (p)->e.env : NULL)
#define MRB_PROC_TARGET_CLASS(p) (MRB_PROC_ENV_P(p) ? (p)->e.env->c : (p)->e.target_class)
#define MRB_PROC_SET_TARGET_CLASS(p,tc) do {\
if (MRB_PROC_ENV_P(p)) {\
(p)->e.env->c = (tc);\
mrb_field_write_barrier(mrb, (struct RBasic*)(p)->e.env, (struct RBasic*)tc);\
}\
else {\
(p)->e.target_class = (tc);\
mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)tc);\
}\
} while (0)
#define MRB_PROC_SCOPE 2048
#define MRB_PROC_SCOPE_P(p) (((p)->flags & MRB_PROC_SCOPE) != 0)
#define mrb_proc_ptr(v) ((struct RProc*)(mrb_ptr(v)))
@@ -75,8 +96,35 @@ MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state*, mrb_int);
/* old name */
#define mrb_cfunc_env_get(mrb, idx) mrb_proc_cfunc_env_get(mrb, idx)
#ifdef MRB_METHOD_TABLE_INLINE
#define MRB_METHOD_FUNC_FL ((uintptr_t)1U<<(sizeof(uintptr_t)*8-1))
#define MRB_METHOD_FUNC_P(m) ((uintptr_t)(m)&MRB_METHOD_FUNC_FL)
#define MRB_METHOD_FUNC(m) ((mrb_func_t)((uintptr_t)(m)&(~MRB_METHOD_FUNC_FL)))
#define MRB_METHOD_FROM_FUNC(m,fn) m=(mrb_method_t)((struct RProc*)((uintptr_t)(fn)|MRB_METHOD_FUNC_FL))
#define MRB_METHOD_FROM_PROC(m,pr) m=(mrb_method_t)(struct RProc*)(pr)
#define MRB_METHOD_PROC_P(m) (!MRB_METHOD_FUNC_P(m))
#define MRB_METHOD_PROC(m) ((struct RProc*)(m))
#define MRB_METHOD_UNDEF_P(m) ((m)==0)
#else
#define MRB_METHOD_FUNC_P(m) ((m).func_p)
#define MRB_METHOD_FUNC(m) ((m).func)
#define MRB_METHOD_FROM_FUNC(m,fn) do{(m).func_p=TRUE;(m).func=(fn);}while(0)
#define MRB_METHOD_FROM_PROC(m,pr) do{(m).func_p=FALSE;(m).proc=(pr);}while(0)
#define MRB_METHOD_PROC_P(m) (!MRB_METHOD_FUNC_P(m))
#define MRB_METHOD_PROC(m) ((m).proc)
#define MRB_METHOD_UNDEF_P(m) ((m).proc==NULL)
#endif /* MRB_METHOD_TABLE_INLINE */
#define MRB_METHOD_CFUNC_P(m) (MRB_METHOD_FUNC_P(m)?TRUE:(MRB_METHOD_PROC(m)?(MRB_PROC_CFUNC_P(MRB_METHOD_PROC(m))):FALSE))
#define MRB_METHOD_CFUNC(m) (MRB_METHOD_FUNC_P(m)?MRB_METHOD_FUNC(m):((MRB_METHOD_PROC(m)&&MRB_PROC_CFUNC_P(MRB_METHOD_PROC(m)))?MRB_PROC_CFUNC(MRB_METHOD_PROC(m)):NULL))
#include <mruby/khash.h>
KHASH_DECLARE(mt, mrb_sym, struct RProc*, TRUE)
KHASH_DECLARE(mt, mrb_sym, mrb_method_t, TRUE)
MRB_END_DECL
+24 -6
View File
@@ -26,6 +26,7 @@ struct RString {
union {
mrb_int capa;
struct mrb_shared_string *shared;
struct RString *fshared;
} aux;
char *ptr;
} heap;
@@ -59,10 +60,17 @@ struct RString {
#define RSTR_SET_SHARED_FLAG(s) ((s)->flags |= MRB_STR_SHARED)
#define RSTR_UNSET_SHARED_FLAG(s) ((s)->flags &= ~MRB_STR_SHARED)
#define RSTR_FSHARED_P(s) ((s)->flags & MRB_STR_FSHARED)
#define RSTR_SET_FSHARED_FLAG(s) ((s)->flags |= MRB_STR_FSHARED)
#define RSTR_UNSET_FSHARED_FLAG(s) ((s)->flags &= ~MRB_STR_FSHARED)
#define RSTR_NOFREE_P(s) ((s)->flags & MRB_STR_NOFREE)
#define RSTR_SET_NOFREE_FLAG(s) ((s)->flags |= MRB_STR_NOFREE)
#define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE)
#define RSTR_POOL_P(s) ((s)->flags & MRB_STR_POOL)
#define RSTR_SET_POOL_FLAG(s) ((s)->flags |= MRB_STR_POOL)
/*
* Returns a pointer from a Ruby string
*/
@@ -76,14 +84,23 @@ struct RString {
MRB_API mrb_int mrb_str_strlen(mrb_state*, struct RString*);
#define MRB_STR_SHARED 1
#define MRB_STR_NOFREE 2
#define MRB_STR_NO_UTF 8
#define MRB_STR_EMBED 16
#define MRB_STR_EMBED_LEN_MASK 0x3e0
#define MRB_STR_EMBED_LEN_SHIFT 5
#define MRB_STR_FSHARED 2
#define MRB_STR_NOFREE 4
#define MRB_STR_POOL 8
#define MRB_STR_NO_UTF 16
#define MRB_STR_EMBED 32
#define MRB_STR_EMBED_LEN_MASK 0x7c0
#define MRB_STR_EMBED_LEN_SHIFT 6
void mrb_gc_free_str(mrb_state*, struct RString*);
MRB_API void mrb_str_modify(mrb_state*, struct RString*);
/*
* Finds the index of a substring in a string
*/
MRB_API mrb_int mrb_str_index(mrb_state*, mrb_value, const char*, mrb_int, mrb_int);
#define mrb_str_index_lit(mrb, str, lit, off) mrb_str_index(mrb, str, lit, mrb_strlen_lit(lit), off);
/*
* Appends self to other. Returns self as a concatnated string.
*
@@ -297,6 +314,7 @@ MRB_API mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb
MRB_API mrb_value mrb_string_type(mrb_state *mrb, mrb_value str);
MRB_API mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str);
MRB_API mrb_value mrb_str_new_capa(mrb_state *mrb, size_t capa);
MRB_API mrb_value mrb_str_buf_new(mrb_state *mrb, size_t capa);
MRB_API const char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr);
@@ -401,7 +419,7 @@ MRB_API int mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2);
MRB_API char *mrb_str_to_cstr(mrb_state *mrb, mrb_value str);
mrb_value mrb_str_pool(mrb_state *mrb, mrb_value str);
mrb_int mrb_str_hash(mrb_state *mrb, mrb_value str);
uint32_t mrb_str_hash(mrb_state *mrb, mrb_value str);
mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str);
/*
+7 -1
View File
@@ -63,12 +63,14 @@ struct mrb_state;
#endif
#ifndef MRB_WITHOUT_FLOAT
MRB_API double mrb_float_read(const char*, char**);
#ifdef MRB_USE_FLOAT
typedef float mrb_float;
#else
typedef double mrb_float;
#endif
#endif
#if defined _MSC_VER && _MSC_VER < 1900
# ifndef __cplusplus
@@ -79,7 +81,7 @@ MRB_API int mrb_msvc_vsnprintf(char *s, size_t n, const char *format, va_list ar
MRB_API int mrb_msvc_snprintf(char *s, size_t n, const char *format, ...);
# define vsnprintf(s, n, format, arg) mrb_msvc_vsnprintf(s, n, format, arg)
# define snprintf(s, n, format, ...) mrb_msvc_snprintf(s, n, format, __VA_ARGS__)
# if _MSC_VER < 1800
# if _MSC_VER < 1800 && !defined MRB_WITHOUT_FLOAT
# include <float.h>
# define isfinite(n) _finite(n)
# define isnan _isnan
@@ -158,7 +160,9 @@ typedef void mrb_value;
#ifndef mrb_bool
#define mrb_bool(o) (mrb_type(o) != MRB_TT_FALSE)
#endif
#ifndef MRB_WITHOUT_FLOAT
#define mrb_float_p(o) (mrb_type(o) == MRB_TT_FLOAT)
#endif
#define mrb_symbol_p(o) (mrb_type(o) == MRB_TT_SYMBOL)
#define mrb_array_p(o) (mrb_type(o) == MRB_TT_ARRAY)
#define mrb_string_p(o) (mrb_type(o) == MRB_TT_STRING)
@@ -171,6 +175,7 @@ MRB_API mrb_bool mrb_regexp_p(struct mrb_state*, mrb_value);
/*
* Returns a float in Ruby.
*/
#ifndef MRB_WITHOUT_FLOAT
MRB_INLINE mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f)
{
mrb_value v;
@@ -178,6 +183,7 @@ MRB_INLINE mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f)
SET_FLOAT_VALUE(mrb, v, f);
return v;
}
#endif
static inline mrb_value
mrb_cptr_value(struct mrb_state *mrb, void *p)
-2
View File
@@ -47,7 +47,6 @@ MRB_API void mrb_iv_check(mrb_state *mrb, mrb_sym sym);
MRB_API mrb_value mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
MRB_API void mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
MRB_API mrb_bool mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
MRB_API void mrb_obj_iv_ifnone(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
MRB_API mrb_value mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym);
MRB_API void mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v);
MRB_API mrb_bool mrb_iv_defined(mrb_state*, mrb_value, mrb_sym);
@@ -126,7 +125,6 @@ mrb_value mrb_obj_instance_variables(mrb_state*, mrb_value);
mrb_value mrb_mod_class_variables(mrb_state*, mrb_value);
mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym);
mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym);
mrb_sym mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer);
/* GC functions */
void mrb_gc_mark_gv(mrb_state*);
+4 -4
View File
@@ -42,7 +42,7 @@ MRB_BEGIN_DECL
/*
* Minor release version number.
*/
#define MRUBY_RELEASE_MINOR 3
#define MRUBY_RELEASE_MINOR 4
/*
* Tiny release version number.
@@ -62,17 +62,17 @@ MRB_BEGIN_DECL
/*
* Release year.
*/
#define MRUBY_RELEASE_YEAR 2017
#define MRUBY_RELEASE_YEAR 2018
/*
* Release month.
*/
#define MRUBY_RELEASE_MONTH 7
#define MRUBY_RELEASE_MONTH 1
/*
* Release day.
*/
#define MRUBY_RELEASE_DAY 4
#define MRUBY_RELEASE_DAY 16
/*
* Release date as a string.
@@ -1,5 +1,5 @@
load "#{MRUBY_ROOT}/tasks/mruby_build_gem.rake"
load "#{MRUBY_ROOT}/tasks/mruby_build_commands.rake"
require "mruby/build/load_gems"
require "mruby/build/command"
module MRuby
class << self
@@ -241,7 +241,7 @@ EOS
else
compiler.defines += %w(DISABLE_GEMS)
end
compiler.define_rules build_dir, File.expand_path(File.join(File.dirname(__FILE__), '..'))
compiler.define_rules build_dir, File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
end
end
+3 -3
View File
@@ -63,9 +63,6 @@ module MRuby
objfile(f.relative_path_from(@dir).to_s.pathmap("#{build_dir}/%X"))
end
@generate_functions = !(@rbfiles.empty? && @objs.empty?)
@objs << objfile("#{build_dir}/gem_init") if @generate_functions
@test_rbfiles = Dir.glob("#{dir}/test/**/*.rb")
@test_objs = Dir.glob("#{dir}/test/*.{c,cpp,cxx,cc,m,asm,s,S}").map do |f|
objfile(f.relative_path_from(dir).to_s.pathmap("#{build_dir}/%X"))
@@ -83,6 +80,9 @@ module MRuby
instance_eval(&@initializer)
@generate_functions = !(@rbfiles.empty? && @objs.empty?)
@objs << objfile("#{build_dir}/gem_init") if @generate_functions
if !name || !licenses || !authors
fail "#{name || dir} required to set name, license(s) and author(s)"
end
+3
View File
@@ -14,6 +14,9 @@ MRuby::GemBox.new do |conf|
# Use standard Struct class
conf.gem :core => "mruby-struct"
# Use Comparable module extension
conf.gem :core => "mruby-compar-ext"
# Use Enumerable module extension
conf.gem :core => "mruby-enum-ext"
+1
View File
@@ -2,4 +2,5 @@ MRuby::Gem::Specification.new('mruby-array-ext') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'Array class extension'
spec.add_test_dependency 'mruby-enumerator', core: 'mruby-enumerator'
end
+216 -46
View File
@@ -81,11 +81,7 @@ class Array
#
def uniq(&block)
ary = self.dup
if block
ary.uniq!(&block)
else
ary.uniq!
end
ary.uniq!(&block)
ary
end
@@ -105,8 +101,19 @@ class Array
hash = {}
array = []
elem.each { |x| hash[x] = true }
self.each { |x| array << x unless hash[x] }
idx = 0
len = elem.size
while idx < len
hash[elem[idx]] = true
idx += 1
end
idx = 0
len = size
while idx < len
v = self[idx]
array << v unless hash[v]
idx += 1
end
array
end
@@ -141,12 +148,21 @@ class Array
hash = {}
array = []
elem.each{|v| hash[v] = true }
self.each do |v|
idx = 0
len = elem.size
while idx < len
hash[elem[idx]] = true
idx += 1
end
idx = 0
len = size
while idx < len
v = self[idx]
if hash[v]
array << v
hash.delete v
end
idx += 1
end
array
end
@@ -169,15 +185,9 @@ class Array
# a.flatten(1) #=> [1, 2, 3, [4, 5]]
#
def flatten(depth=nil)
ar = []
self.each do |e|
if e.is_a?(Array) && (depth.nil? || depth > 0)
ar += e.flatten(depth.nil? ? nil : depth - 1)
else
ar << e
end
end
ar
res = dup
res.flatten! depth
res
end
##
@@ -200,13 +210,17 @@ class Array
def flatten!(depth=nil)
modified = false
ar = []
self.each do |e|
idx = 0
len = size
while idx < len
e = self[idx]
if e.is_a?(Array) && (depth.nil? || depth > 0)
ar += e.flatten(depth.nil? ? nil : depth - 1)
modified = true
else
ar << e
end
idx += 1
end
if modified
self.replace(ar)
@@ -252,7 +266,7 @@ class Array
# for efficiency
def reverse_each(&block)
return to_enum :reverse_each unless block_given?
return to_enum :reverse_each unless block
i = self.size - 1
while i>=0
@@ -474,7 +488,7 @@ class Array
# scores.delete_if {|score| score < 80 } #=> [97]
def delete_if(&block)
return to_enum :delete_if unless block_given?
return to_enum :delete_if unless block
idx = 0
while idx < self.size do
@@ -503,7 +517,7 @@ class Array
# If no block is given, an Enumerator is returned instead.
def reject!(&block)
return to_enum :reject! unless block_given?
return to_enum :reject! unless block
len = self.size
idx = 0
@@ -593,33 +607,60 @@ class Array
# undefined which value is actually picked up at each iteration.
def bsearch(&block)
return to_enum :bsearch unless block_given?
return to_enum :bsearch unless block
if idx = bsearch_index(&block)
self[idx]
else
nil
end
end
##
# call-seq:
# ary.bsearch_index {|x| block } -> int or nil
#
# By using binary search, finds an index of a value from this array which
# meets the given condition in O(log n) where n is the size of the array.
#
# It supports two modes, depending on the nature of the block and they are
# exactly the same as in the case of #bsearch method with the only difference
# being that this method returns the index of the element instead of the
# element itself. For more details consult the documentation for #bsearch.
def bsearch_index(&block)
return to_enum :bsearch_index unless block
low = 0
high = self.size
high = size
satisfied = false
while low < high
mid = low + ((high - low) / 2).truncate
val = self[mid]
v = block.call(val)
if v.is_a?(Integer)
return val if v == 0
smaller = v < 0
elsif v == true
mid = ((low+high)/2).truncate
res = block.call self[mid]
case res
when 0 # find-any mode: Found!
return mid
when Numeric # find-any mode: Continue...
in_lower_half = res < 0
when true # find-min mode
in_lower_half = true
satisfied = true
smaller = true
elsif v == false || v.nil?
smaller = false
when false, nil # find-min mode
in_lower_half = false
else
raise TypeError, 'invalid block result (must be numeric, true, false or nil)'
end
if smaller
if in_lower_half
high = mid
else
low = mid + 1
end
end
return nil if low == self.size
return nil unless satisfied
self[low]
satisfied ? low : nil
end
##
@@ -640,7 +681,7 @@ class Array
# scores.delete_if {|score| score < 80 } #=> [97]
def delete_if(&block)
return to_enum :delete_if unless block_given?
return to_enum :delete_if unless block
idx = 0
while idx < self.size do
@@ -669,7 +710,7 @@ class Array
# a.keep_if { |val| val > 3 } #=> [4, 5]
def keep_if(&block)
return to_enum :keep_if unless block_given?
return to_enum :keep_if unless block
idx = 0
len = self.size
@@ -698,13 +739,17 @@ class Array
# If no block is given, an Enumerator is returned instead.
def select!(&block)
return to_enum :select! unless block_given?
return to_enum :select! unless block
result = []
self.each do |x|
result << x if block.call(x)
idx = 0
len = size
while idx < len
elem = self[idx]
result << elem if block.call(elem)
idx += 1
end
return nil if self.size == result.size
return nil if len == result.size
self.replace(result)
end
@@ -726,8 +771,9 @@ class Array
if block
idx = 0
self.each do |*e|
return idx if block.call(*e)
len = size
while idx < len
return idx if block.call self[idx]
idx += 1
end
else
@@ -762,4 +808,128 @@ class Array
n
end
end
##
# call-seq:
# ary.permutation { |p| block } -> ary
# ary.permutation -> Enumerator
# ary.permutation(n) { |p| block } -> ary
# ary.permutation(n) -> Enumerator
#
# When invoked with a block, yield all permutations of length +n+ of the
# elements of the array, then return the array itself.
#
# If +n+ is not specified, yield all permutations of all elements.
#
# The implementation makes no guarantees about the order in which the
# permutations are yielded.
#
# If no block is given, an Enumerator is returned instead.
#
# Examples:
#
# a = [1, 2, 3]
# a.permutation.to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
# a.permutation(1).to_a #=> [[1],[2],[3]]
# a.permutation(2).to_a #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
# a.permutation(3).to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
# a.permutation(0).to_a #=> [[]] # one permutation of length 0
# a.permutation(4).to_a #=> [] # no permutations of length 4
def permutation(n=self.size, &block)
size = self.size
return to_enum(:permutation, n) unless block
return if n > size
if n == 0
yield []
else
i = 0
while i<size
result = [self[i]]
if n-1 > 0
ary = self[0...i] + self[i+1..-1]
ary.permutation(n-1) do |c|
yield result + c
end
else
yield result
end
i += 1
end
end
end
##
# call-seq:
# ary.combination(n) { |c| block } -> ary
# ary.combination(n) -> Enumerator
#
# When invoked with a block, yields all combinations of length +n+ of elements
# from the array and then returns the array itself.
#
# The implementation makes no guarantees about the order in which the
# combinations are yielded.
#
# If no block is given, an Enumerator is returned instead.
#
# Examples:
#
# a = [1, 2, 3, 4]
# a.combination(1).to_a #=> [[1],[2],[3],[4]]
# a.combination(2).to_a #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
# a.combination(3).to_a #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
# a.combination(4).to_a #=> [[1,2,3,4]]
# a.combination(0).to_a #=> [[]] # one combination of length 0
# a.combination(5).to_a #=> [] # no combinations of length 5
def combination(n, &block)
size = self.size
return to_enum(:combination, n) unless block
return if n > size
if n == 0
yield []
elsif n == 1
i = 0
while i<size
yield [self[i]]
i += 1
end
else
i = 0
while i<size
result = [self[i]]
self[i+1..-1].combination(n-1) do |c|
yield result + c
end
i += 1
end
end
end
##
# call-seq:
# ary.transpose -> new_ary
#
# Assumes that self is an array of arrays and transposes the rows and columns.
#
# If the length of the subarrays dont match, an IndexError is raised.
#
# Examples:
#
# a = [[1,2], [3,4], [5,6]]
# a.transpose #=> [[1, 3, 5], [2, 4, 6]]
def transpose
return [] if empty?
column_count = nil
self.each do |row|
raise TypeError unless row.is_a?(Array)
column_count ||= row.count
raise IndexError, 'element size differs' unless column_count == row.count
end
Array.new(column_count) do |column_index|
self.map { |row| row[column_index] }
end
end
end
+22 -19
View File
@@ -127,19 +127,20 @@ mrb_ary_to_h(mrb_state *mrb, mrb_value ary)
hash = mrb_hash_new_capa(mrb, 0);
for (i = 0; i < RARRAY_LEN(ary); ++i) {
v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]);
mrb_value elt = RARRAY_PTR(ary)[i];
v = mrb_check_array_type(mrb, elt);
if (mrb_nil_p(v)) {
mrb_raisef(mrb, E_TYPE_ERROR, "wrong element type %S at %S (expected array)",
mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, ary_elt(ary, i))),
mrb_fixnum_value(i)
mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, elt)),
mrb_fixnum_value(i)
);
}
if (RARRAY_LEN(v) != 2) {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong array length at %S (expected 2, was %S)",
mrb_fixnum_value(i),
mrb_fixnum_value(RARRAY_LEN(v))
mrb_fixnum_value(i),
mrb_fixnum_value(RARRAY_LEN(v))
);
}
@@ -174,18 +175,20 @@ static mrb_value
mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
{
struct RArray *a = mrb_ary_ptr(self);
mrb_int i, j, k, len;
mrb_value index;
mrb_int i, j, k, len, alen = ARY_LEN(a);
mrb_value val;
mrb_value *ptr;
mrb_value ary;
mrb_ary_modify(mrb, a);
if (mrb_get_args(mrb, "o|i", &index, &len) == 1) {
if (mrb_get_argc(mrb) == 1) {
mrb_value index;
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, a->len, TRUE) == 1) {
if (mrb_range_beg_len(mrb, index, &i, &len, alen, TRUE) == 1) {
goto delete_pos_len;
}
else {
@@ -200,27 +203,27 @@ mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
}
}
i = mrb_fixnum(index);
mrb_get_args(mrb, "ii", &i, &len);
delete_pos_len:
if (i < 0) i += a->len;
if (i < 0 || a->len < i) return mrb_nil_value();
if (i < 0) i += alen;
if (i < 0 || alen < i) return mrb_nil_value();
if (len < 0) return mrb_nil_value();
if (a->len == i) return mrb_ary_new(mrb);
if (len > a->len - i) len = a->len - i;
if (alen == i) return mrb_ary_new(mrb);
if (len > alen - i) len = alen - i;
ary = mrb_ary_new_capa(mrb, len);
ptr = ARY_PTR(a);
for (j = i, k = 0; k < len; ++j, ++k) {
mrb_ary_push(mrb, ary, a->ptr[j]);
mrb_ary_push(mrb, ary, ptr[j]);
}
ptr = a->ptr + i;
for (j = i; j < a->len - len; ++j) {
ptr += i;
for (j = i; j < alen - len; ++j) {
*ptr = *(ptr+len);
++ptr;
}
mrb_ary_resize(mrb, self, a->len - len);
mrb_ary_resize(mrb, self, alen - len);
return ary;
}
+78 -10
View File
@@ -228,18 +228,47 @@ end
assert("Array#bsearch") do
# Find minimum mode
a = [0, 4, 7, 10, 12]
assert_include [4, 7], a.bsearch {|x| x >= 4 }
assert_equal 7, a.bsearch {|x| x >= 6 }
assert_equal 0, a.bsearch {|x| x >= -1 }
assert_nil a.bsearch {|x| x >= 100 }
a = [0, 2, 4]
assert_equal 0, a.bsearch{ |x| x >= -1 }
assert_equal 0, a.bsearch{ |x| x >= 0 }
assert_equal 2, a.bsearch{ |x| x >= 1 }
assert_equal 2, a.bsearch{ |x| x >= 2 }
assert_equal 4, a.bsearch{ |x| x >= 3 }
assert_equal 4, a.bsearch{ |x| x >= 4 }
assert_nil a.bsearch{ |x| x >= 5 }
# Find any mode
a = [0, 4, 7, 10, 12]
assert_include [4, 7], a.bsearch {|x| 1 - (x / 4).truncate }
assert_nil a.bsearch {|x| 4 - (x / 2).truncate }
assert_equal(nil, a.bsearch {|x| 1 })
assert_equal(nil, a.bsearch {|x| -1 })
a = [0, 4, 8]
def between(lo, x, hi)
if x < lo
1
elsif x > hi
-1
else
0
end
end
assert_nil a.bsearch{ |x| between(-3, x, -1) }
assert_equal 0, a.bsearch{ |x| between(-1, x, 1) }
assert_nil a.bsearch{ |x| between( 1, x, 3) }
assert_equal 4, a.bsearch{ |x| between( 3, x, 5) }
assert_nil a.bsearch{ |x| between( 5, x, 7) }
assert_equal 8, a.bsearch{ |x| between( 7, x, 9) }
assert_nil a.bsearch{ |x| between( 9, x, 11) }
assert_equal 0, a.bsearch{ |x| between( 0, x, 3) }
assert_equal 4, a.bsearch{ |x| between( 0, x, 4) }
assert_equal 4, a.bsearch{ |x| between( 4, x, 8) }
assert_equal 8, a.bsearch{ |x| between( 5, x, 8) }
# Invalid block result
assert_raise TypeError, 'invalid block result (must be numeric, true, false or nil)' do
a.bsearch{ 'I like to watch the world burn' }
end
end
assert("Array#bsearch_index") do
# tested through Array#bsearch
end
assert("Array#delete_if") do
@@ -352,3 +381,42 @@ assert("Array#slice!") do
assert_equal(i, [1, 2, 3])
assert_equal(j, nil)
end
assert("Array#permutation") do
a = [1, 2, 3]
assert_equal([[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]],
a.permutation.to_a)
assert_equal([[1],[2],[3]],
a.permutation(1).to_a)
assert_equal([[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]],
a.permutation(2).to_a)
assert_equal([[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]],
a.permutation(3).to_a)
assert_equal([[]], a.permutation(0).to_a)
assert_equal([], a.permutation(4).to_a)
end
assert("Array#combination") do
a = [1, 2, 3, 4]
assert_equal([[1],[2],[3],[4]],
a.combination(1).to_a)
assert_equal([[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]],
a.combination(2).to_a)
assert_equal([[1,2,3],[1,2,4],[1,3,4],[2,3,4]],
a.combination(3).to_a)
assert_equal([[1,2,3,4]],
a.combination(4).to_a)
assert_equal([[]], a.combination(0).to_a)
assert_equal([], a.combination(5).to_a)
end
assert('Array#transpose') do
assert_equal([].transpose, [])
assert_equal([[]].transpose, [])
assert_equal([[1]].transpose, [[1]])
assert_equal([[1,2,3]].transpose, [[1], [2], [3]])
assert_equal([[1], [2], [3]].transpose, [[1,2,3]])
assert_equal([[1,2], [3,4], [5,6]].transpose, [[1,3,5], [2,4,6]])
assert_raise(TypeError) { [1].transpose }
assert_raise(IndexError) { [[1], [2,3,4]].transpose }
end
+2 -2
View File
@@ -341,8 +341,8 @@ assert('mruby-bin-debugger(print) Literal:Numeric') do
tc << {:cmd=>"p +0100", :exp=>'$3 = 64'}
tc << {:cmd=>"p 0x100", :exp=>'$4 = 256'}
tc << {:cmd=>"p 1_234", :exp=>'$5 = 1234'}
tc << {:cmd=>"p 0b1000_0000", :exp=>"$6 = #{0b1000_0000.to_s}"}
tc << {:cmd=>"p 0x1000_0000", :exp=>"$7 = #{0x1000_0000.to_s}"}
tc << {:cmd=>"p 0b1000_0000", :exp=>"$6 = #{0b1000_0000}"}
tc << {:cmd=>"p 0x1000_0000", :exp=>"$7 = #{0x1000_0000}"}
tc << {:cmd=>"p 3.14", :exp=>'$8 = 3.14'}
tc << {:cmd=>"p -12.3", :exp=>'$9 = -12.3'}
@@ -112,23 +112,12 @@ check_file_lineno(struct mrb_irep *irep, const char *file, uint16_t lineno)
return result;
}
static const char*
get_class_name(mrb_state *mrb, struct RClass *class_obj)
{
struct RClass *outer;
mrb_sym class_sym;
outer = mrb_class_outer_module(mrb, class_obj);
class_sym = mrb_class_sym(mrb, class_obj, outer);
return mrb_sym2name(mrb, class_sym);
}
static int32_t
compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *class_obj, mrb_sym method_sym, mrb_bool* isCfunc)
{
const char* class_name;
const char* method_name;
struct RProc* m;
mrb_method_t m;
struct RClass* sc;
const char* sn;
mrb_sym ssym;
@@ -139,7 +128,7 @@ compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *cl
method_p = &bp->point.methodpoint;
if (strcmp(method_p->method_name, method_name) == 0) {
class_name = get_class_name(mrb, class_obj);
class_name = mrb_class_name(mrb, class_obj);
if (class_name == NULL) {
if (method_p->class_name == NULL) {
return bp->bpno;
@@ -147,10 +136,10 @@ compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *cl
}
else if (method_p->class_name != NULL) {
m = mrb_method_search_vm(mrb, &class_obj, method_sym);
if (m == NULL) {
if (MRB_METHOD_UNDEF_P(m)) {
return MRB_DEBUG_OK;
}
if (MRB_PROC_CFUNC_P(m)) {
if (MRB_METHOD_CFUNC_P(m)) {
*isCfunc = TRUE;
}
@@ -162,12 +151,12 @@ compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *cl
sc = mrb_class_get(mrb, method_p->class_name);
ssym = mrb_symbol(mrb_check_intern_cstr(mrb, method_p->method_name));
m = mrb_method_search_vm(mrb, &sc, ssym);
if (m == NULL) {
if (MRB_METHOD_UNDEF_P(m)) {
return MRB_DEBUG_OK;
}
class_name = get_class_name(mrb, class_obj);
sn = get_class_name(mrb, sc);
class_name = mrb_class_name(mrb, class_obj);
sn = mrb_class_name(mrb, sc);
if (strcmp(sn, class_name) == 0) {
return bp->bpno;
}
@@ -204,7 +193,7 @@ mrb_debug_set_break_line(mrb_state *mrb, mrb_debug_context *dbg, const char *fil
return MRB_DEBUG_BREAK_INVALID_LINENO;
}
set_file = mrb_malloc(mrb, strlen(file) + 1);
set_file = (char*)mrb_malloc(mrb, strlen(file) + 1);
index = dbg->bpnum;
dbg->bp[index].bpno = dbg->next_bpno;
@@ -241,14 +230,14 @@ mrb_debug_set_break_method(mrb_state *mrb, mrb_debug_context *dbg, const char *c
}
if (class_name != NULL) {
set_class = mrb_malloc(mrb, strlen(class_name) + 1);
set_class = (char*)mrb_malloc(mrb, strlen(class_name) + 1);
strncpy(set_class, class_name, strlen(class_name) + 1);
}
else {
set_class = NULL;
}
set_method = mrb_malloc(mrb, strlen(method_name) + 1);
set_method = (char*)mrb_malloc(mrb, strlen(method_name) + 1);
strncpy(set_method, method_name, strlen(method_name) + 1);
@@ -440,7 +429,7 @@ static mrb_bool
check_start_pc_for_line(mrb_irep *irep, mrb_code *pc, uint16_t line)
{
if (pc > irep->iseq) {
if (line == mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq - 1))) {
if (line == mrb_debug_get_line(irep, pc - irep->iseq - 1)) {
return FALSE;
}
}
@@ -514,5 +503,3 @@ mrb_debug_check_breakpoint_method(mrb_state *mrb, mrb_debug_context *dbg, struct
return 0;
}
@@ -48,7 +48,7 @@ build_path(mrb_state *mrb, const char *dir, const char *base)
len += strlen(dir) + sizeof("/") - 1;
}
path = mrb_malloc(mrb, len);
path = (char*)mrb_malloc(mrb, len);
memset(path, 0, len);
if (strcmp(dir, ".")) {
@@ -64,7 +64,8 @@ static char*
dirname(mrb_state *mrb, const char *path)
{
size_t len;
char *p, *dir;
const char *p;
char *dir;
if (path == NULL) {
return NULL;
@@ -73,7 +74,7 @@ dirname(mrb_state *mrb, const char *path)
p = strrchr(path, '/');
len = p != NULL ? (size_t)(p - path) : strlen(path);
dir = mrb_malloc(mrb, len + 1);
dir = (char*)mrb_malloc(mrb, len + 1);
strncpy(dir, path, len);
dir[len] = '\0';
@@ -83,9 +84,9 @@ dirname(mrb_state *mrb, const char *path)
static source_file*
source_file_new(mrb_state *mrb, mrb_debug_context *dbg, char *filename)
{
source_file *file = NULL;
source_file *file;
file = mrb_malloc(mrb, sizeof(source_file));
file = (source_file*)mrb_malloc(mrb, sizeof(source_file));
memset(file, '\0', sizeof(source_file));
file->fp = fopen(filename, "rb");
@@ -96,7 +97,7 @@ source_file_new(mrb_state *mrb, mrb_debug_context *dbg, char *filename)
}
file->lineno = 1;
file->path = mrb_malloc(mrb, strlen(filename) + 1);
file->path = (char*)mrb_malloc(mrb, strlen(filename) + 1);
strcpy(file->path, filename);
return file;
}
@@ -174,9 +175,13 @@ mrb_debug_get_source(mrb_state *mrb, mrdb_state *mrdb, const char *srcpath, cons
FILE *fp;
const char *search_path[3];
char *path = NULL;
const char *srcname = strrchr(filename, '/');
if (srcname) srcname++;
else srcname = filename;
search_path[0] = srcpath;
search_path[1] = dirname(mrb, mrb_debug_get_filename(mrdb->dbg->root_irep, 0));
search_path[1] = dirname(mrb, mrb_debug_get_filename(mrdb->dbg->irep, 0));
search_path[2] = ".";
for (i = 0; i < 3; i++) {
@@ -184,7 +189,7 @@ mrb_debug_get_source(mrb_state *mrb, mrdb_state *mrdb, const char *srcpath, cons
continue;
}
if ((path = build_path(mrb, search_path[i], filename)) == NULL) {
if ((path = build_path(mrb, search_path[i], srcname)) == NULL) {
continue;
}
@@ -274,7 +274,7 @@ parse_breakcommand(mrdb_state *mrdb, const char **file, uint32_t *line, char **c
STRTOUL(l, body);
if (l <= 65535) {
*line = l;
*file = (body == args)? mrb_debug_get_filename(dbg->irep, (uint32_t)(dbg->pc - dbg->irep->iseq)): args;
*file = (body == args)? mrb_debug_get_filename(dbg->irep, dbg->pc - dbg->irep->iseq): args;
}
else {
puts(BREAK_ERR_MSG_RANGEOVER);
@@ -133,7 +133,7 @@ typedef struct listcmd_parser_state {
static listcmd_parser_state*
listcmd_parser_state_new(mrb_state *mrb)
{
listcmd_parser_state *st = mrb_malloc(mrb, sizeof(listcmd_parser_state));
listcmd_parser_state *st = (listcmd_parser_state*)mrb_malloc(mrb, sizeof(listcmd_parser_state));
memset(st, 0, sizeof(listcmd_parser_state));
return st;
}
@@ -227,7 +227,7 @@ parse_filename(mrb_state *mrb, char **sp, listcmd_parser_state *st)
}
if (len > 0) {
st->filename = mrb_malloc(mrb, len + 1);
st->filename = (char*)mrb_malloc(mrb, len + 1);
strncpy(st->filename, *sp, len);
st->filename[len] = '\0';
*sp += len;
@@ -242,7 +242,8 @@ char*
replace_ext(mrb_state *mrb, const char *filename, const char *ext)
{
size_t len;
char *p, *s;
const char *p;
char *s;
if (filename == NULL) {
return NULL;
@@ -255,7 +256,7 @@ replace_ext(mrb_state *mrb, const char *filename, const char *ext)
len = strlen(filename);
}
s = mrb_malloc(mrb, len + strlen(ext) + 1);
s = (char*)mrb_malloc(mrb, len + strlen(ext) + 1);
memset(s, '\0', len + strlen(ext) + 1);
strncpy(s, filename, len);
strcat(s, ext);
@@ -325,7 +326,7 @@ parse_listcmd_args(mrb_state *mrb, mrdb_state *mrdb, listcmd_parser_state *st)
static mrb_bool
check_cmd_pattern(const char *pattern, const char *cmd)
{
char *lbracket, *rbracket, *p, *q;
const char *lbracket, *rbracket, *p, *q;
if (pattern == NULL && cmd == NULL) {
return TRUE;
+5 -5
View File
@@ -184,7 +184,7 @@ cleanup(mrb_state *mrb, struct _args *args)
static mrb_debug_context*
mrb_debug_context_new(mrb_state *mrb)
{
mrb_debug_context *dbg = mrb_malloc(mrb, sizeof(mrb_debug_context));
mrb_debug_context *dbg = (mrb_debug_context*)mrb_malloc(mrb, sizeof(mrb_debug_context));
memset(dbg, 0, sizeof(mrb_debug_context));
@@ -223,12 +223,12 @@ mrb_debug_context_free(mrb_state *mrb)
static mrdb_state*
mrdb_state_new(mrb_state *mrb)
{
mrdb_state *mrdb = mrb_malloc(mrb, sizeof(mrdb_state));
mrdb_state *mrdb = (mrdb_state*)mrb_malloc(mrb, sizeof(mrdb_state));
memset(mrdb, 0, sizeof(mrdb_state));
mrdb->dbg = mrb_debug_context_get(mrb);
mrdb->command = mrb_malloc(mrb, MAX_COMMAND_LINE+1);
mrdb->command = (char*)mrb_malloc(mrb, MAX_COMMAND_LINE+1);
mrdb->print_no = 1;
return mrdb;
@@ -566,8 +566,8 @@ mrb_code_fetch_hook(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *reg
dbg->xphase = DBG_PHASE_RUNNING;
}
file = mrb_debug_get_filename(irep, (uint32_t)(pc - irep->iseq));
line = mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq));
file = mrb_debug_get_filename(irep, pc - irep->iseq);
line = mrb_debug_get_line(irep, pc - irep->iseq);
switch (dbg->xm) {
case DBG_STEP:
+30 -3
View File
@@ -19,6 +19,12 @@
#include <readline/history.h>
#define MIRB_ADD_HISTORY(line) add_history(line)
#define MIRB_READLINE(ch) readline(ch)
#if !defined(RL_READLINE_VERSION) || RL_READLINE_VERSION < 0x600
/* libedit & older readline do not have rl_free() */
#define MIRB_LINE_FREE(line) free(line)
#else
#define MIRB_LINE_FREE(line) rl_free(line)
#endif
#define MIRB_WRITE_HISTORY(path) write_history(path)
#define MIRB_READ_HISTORY(path) read_history(path)
#define MIRB_USING_HISTORY() using_history()
@@ -27,6 +33,7 @@
#include <linenoise.h>
#define MIRB_ADD_HISTORY(line) linenoiseHistoryAdd(line)
#define MIRB_READLINE(ch) linenoise(ch)
#define MIRB_LINE_FREE(line) linenoiseFree(line)
#define MIRB_WRITE_HISTORY(path) linenoiseHistorySave(path)
#define MIRB_READ_HISTORY(path) linenoiseHistoryLoad(history_path)
#define MIRB_USING_HISTORY()
@@ -88,6 +95,7 @@ static void
p(mrb_state *mrb, mrb_value obj, int prompt)
{
mrb_value val;
char* msg;
val = mrb_funcall(mrb, obj, "inspect", 0);
if (prompt) {
@@ -101,7 +109,9 @@ p(mrb_state *mrb, mrb_value obj, int prompt)
if (!mrb_string_p(val)) {
val = mrb_obj_as_string(mrb, obj);
}
fwrite(RSTRING_PTR(val), RSTRING_LEN(val), 1, stdout);
msg = mrb_locale_from_utf8(RSTRING_PTR(val), RSTRING_LEN(val));
fwrite(msg, strlen(msg), 1, stdout);
mrb_locale_free(msg);
putc('\n', stdout);
}
@@ -489,7 +499,7 @@ main(int argc, char **argv)
strcpy(last_code_line, line);
strcat(last_code_line, "\n");
MIRB_ADD_HISTORY(line);
free(line);
MIRB_LINE_FREE(line);
#endif
done:
@@ -528,9 +538,17 @@ done:
/* no evaluation of code */
}
else {
if (0 < parser->nwarn) {
/* warning */
char* msg = mrb_locale_from_utf8(parser->warn_buffer[0].message, -1);
printf("line %d: %s\n", parser->warn_buffer[0].lineno, msg);
mrb_utf8_free(msg);
}
if (0 < parser->nerr) {
/* syntax error */
printf("line %d: %s\n", parser->error_buffer[0].lineno, parser->error_buffer[0].message);
char* msg = mrb_locale_from_utf8(parser->error_buffer[0].message, -1);
printf("line %d: %s\n", parser->error_buffer[0].lineno, msg);
mrb_utf8_free(msg);
}
else {
/* generate bytecode */
@@ -544,6 +562,13 @@ done:
if (args.verbose) {
mrb_codedump_all(mrb, proc);
}
/* 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);
}
}
/* pass a proc for evaluation */
/* evaluate the bytecode */
result = mrb_vm_run(mrb,
@@ -577,6 +602,8 @@ done:
mrb_free(mrb, history_path);
#endif
if (args.rfp) fclose(args.rfp);
mrb_free(mrb, args.argv);
mrbc_context_free(mrb, cxt);
mrb_close(mrb);
+1 -2
View File
@@ -7,7 +7,6 @@ MRuby::Gem::Specification.new('mruby-bin-mruby') do |spec|
spec.add_dependency('mruby-error', :core => 'mruby-error')
if build.cxx_exception_enabled?
@objs << build.compile_as_cxx("#{spec.dir}/tools/mruby/mruby.c", "#{spec.build_dir}/tools/mruby/mruby.cxx")
@objs.delete_if { |v| v == objfile("#{spec.build_dir}/tools/mruby/mruby") }
build.compile_as_cxx("#{spec.dir}/tools/mruby/mruby.c", "#{spec.build_dir}/tools/mruby/mruby.cxx")
end
end
@@ -16,7 +16,7 @@ struct strip_args {
static void
irep_remove_lv(mrb_state *mrb, mrb_irep *irep)
{
size_t i;
int i;
if (irep->lv) {
mrb_free(mrb, irep->lv);
+45
View File
@@ -9,12 +9,57 @@ mrb_mod_name(mrb_state *mrb, mrb_value self)
return mrb_nil_p(name)? name : mrb_str_dup(mrb, name);
}
static mrb_value
mrb_mod_singleton_class_p(mrb_state *mrb, mrb_value self)
{
return mrb_bool_value(mrb_type(self) == MRB_TT_SCLASS);
}
/*
* call-seq:
* module_exec(arg...) {|var...| block } -> obj
* class_exec(arg...) {|var...| block } -> obj
*
* Evaluates the given block in the context of the
* class/module. The method defined in the block will belong
* to the receiver. Any arguments passed to the method will be
* passed to the block. This can be used if the block needs to
* access instance variables.
*
* class Thing
* end
* Thing.class_exec{
* def hello() "Hello there!" end
* }
* puts Thing.new.hello()
*/
static mrb_value
mrb_mod_module_exec(mrb_state *mrb, mrb_value self)
{
const mrb_value *argv;
mrb_int argc;
mrb_value blk;
mrb_get_args(mrb, "*&", &argv, &argc, &blk);
if (mrb_nil_p(blk)) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
}
mrb->c->ci->target_class = mrb_class_ptr(self);
return mrb_yield_cont(mrb, blk, self, argc, argv);
}
void
mrb_mruby_class_ext_gem_init(mrb_state *mrb)
{
struct RClass *mod = mrb->module_class;
mrb_define_method(mrb, mod, "name", mrb_mod_name, MRB_ARGS_NONE());
mrb_define_method(mrb, mod, "singleton_class?", mrb_mod_singleton_class_p, MRB_ARGS_NONE());
mrb_define_method(mrb, mod, "module_exec", mrb_mod_module_exec, MRB_ARGS_ANY()|MRB_ARGS_BLOCK());
mrb_define_method(mrb, mod, "class_exec", mrb_mod_module_exec, MRB_ARGS_ANY()|MRB_ARGS_BLOCK());
}
void
+51 -6
View File
@@ -1,10 +1,55 @@
assert 'Module#name' do
module A
class B
end
module Outer
class Inner; end
const_set :SetInner, Class.new
end
assert_nil A::B.singleton_class.name
assert_equal 'Fixnum', Fixnum.name
assert_equal 'A::B', A::B.name
assert_equal 'Outer', Outer.name
assert_equal 'Outer::Inner', Outer::Inner.name
assert_equal 'Outer::SetInner', Outer::SetInner.name
outer = Module.new do
const_set :SetInner, Class.new
end
Object.const_set :SetOuter, outer
assert_equal 'SetOuter', SetOuter.name
assert_equal 'SetOuter::SetInner', SetOuter::SetInner.name
mod = Module.new
cls = Class.new
assert_nil mod.name
assert_nil cls.name
end
assert 'Module#singleton_class?' do
mod = Module.new
cls = Class.new
scl = cls.singleton_class
assert_false mod.singleton_class?
assert_false cls.singleton_class?
assert_true scl.singleton_class?
end
assert 'Module#module_eval' do
mod = Module.new
mod.class_exec(1,2,3) do |a,b,c|
assert_equal([1,2,3], [a,b,c])
def hi
"hi"
end
end
cls = Class.new
cls.class_exec(42) do |x|
assert_equal(42, x)
include mod
def hello
"hello"
end
end
obj = cls.new
assert_equal("hi", obj.hi)
assert_equal("hello", obj.hello)
end
+5
View File
@@ -0,0 +1,5 @@
MRuby::Gem::Specification.new('mruby-compar-ext') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'Enumerable module extension'
end
+31
View File
@@ -0,0 +1,31 @@
module Comparable
##
# Returns <i>min</i> if <i>obj</i> <code><=></code> <i>min</i> is less
# than zero, <i>max</i> if <i>obj</i> <code><=></code> <i>max</i> is
# greater than zero and <i>obj</i> otherwise.
#
# 12.clamp(0, 100) #=> 12
# 523.clamp(0, 100) #=> 100
# -3.123.clamp(0, 100) #=> 0
#
# 'd'.clamp('a', 'f') #=> 'd'
# 'z'.clamp('a', 'f') #=> 'f'
#
def clamp(min, max)
if (min <=> max) > 0
raise ArgumentError, "min argument must be smaller than max argument"
end
c = self <=> min
if c == 0
return self
elsif c < 0
return min
end
c = self <=> max
if c > 0
return max
else
return self
end
end
end
+190 -131
View File
@@ -66,9 +66,7 @@ typedef struct scope {
int icapa;
mrb_irep *irep;
size_t pcapa;
size_t scapa;
size_t rcapa;
int pcapa, scapa, rcapa;
uint16_t nlocals;
uint16_t nregs;
@@ -280,6 +278,19 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
}
}
break;
case OP_GETUPVAR:
if (c0 == OP_SETUPVAR) {
if (GETARG_B(i) == GETARG_B(i0) && GETARG_C(i) == GETARG_C(i0)) {
if (GETARG_A(i) == GETARG_A(i0)) {
/* just skip OP_SETUPVAR */
return 0;
}
else {
return genop(s, MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_A(i0)));
}
}
}
break;
case OP_EPOP:
if (c0 == OP_EPOP) {
s->iseq[s->pc-1] = MKOP_A(OP_EPOP, GETARG_A(i0)+GETARG_A(i));
@@ -337,6 +348,14 @@ genop_peep(codegen_scope *s, mrb_code i, int val)
s->iseq[s->pc-1] = MKOP_ABC(OP_SUBI, GETARG_A(i), GETARG_B(i), -c);
return 0;
}
break;
case OP_ARYCAT:
case OP_ARYPUSH:
if (c0 == OP_MOVE && GETARG_A(i0) >= s->nlocals) {
s->iseq[s->pc-1] = MKOP_AB(c1, GETARG_A(i), GETARG_B(i0));
return 0;
}
break;
case OP_STRCAT:
if (c0 == OP_STRING) {
mrb_value v = s->irep->pool[GETARG_Bx(i0)];
@@ -373,6 +392,14 @@ scope_error(codegen_scope *s)
exit(EXIT_FAILURE);
}
static void
distcheck(codegen_scope *s, int diff)
{
if (diff > MAXARG_sBx || diff < -MAXARG_sBx) {
codegen_error(s, "too distant jump address");
}
}
static inline void
dispatch(codegen_scope *s, int pc)
{
@@ -394,9 +421,7 @@ dispatch(codegen_scope *s, int pc)
scope_error(s);
break;
}
if (diff > MAXARG_sBx) {
codegen_error(s, "too distant jump address");
}
distcheck(s, diff);
s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff);
}
@@ -428,7 +453,7 @@ push_(codegen_scope *s)
}
static void
push_n_(codegen_scope *s, size_t n)
push_n_(codegen_scope *s, int n)
{
if (s->sp+n > 511) {
codegen_error(s, "too complex expression");
@@ -447,7 +472,7 @@ push_n_(codegen_scope *s, size_t n)
static inline int
new_lit(codegen_scope *s, mrb_value val)
{
size_t i;
int i;
mrb_value *pv;
switch (mrb_type(val)) {
@@ -462,6 +487,7 @@ new_lit(codegen_scope *s, mrb_value val)
return i;
}
break;
#ifndef MRB_WITHOUT_FLOAT
case MRB_TT_FLOAT:
for (i=0; i<s->irep->plen; i++) {
pv = &s->irep->pool[i];
@@ -469,6 +495,7 @@ new_lit(codegen_scope *s, mrb_value val)
if (mrb_float(*pv) == mrb_float(val)) return i;
}
break;
#endif
case MRB_TT_FIXNUM:
for (i=0; i<s->irep->plen; i++) {
pv = &s->irep->pool[i];
@@ -494,10 +521,12 @@ new_lit(codegen_scope *s, mrb_value val)
*pv = mrb_str_pool(s->mrb, val);
break;
#ifndef MRB_WITHOUT_FLOAT
case MRB_TT_FLOAT:
#ifdef MRB_WORD_BOXING
*pv = mrb_float_pool(s->mrb, mrb_float(val));
break;
#endif
#endif
case MRB_TT_FIXNUM:
*pv = val;
@@ -518,7 +547,7 @@ new_lit(codegen_scope *s, mrb_value val)
static int
new_msym(codegen_scope *s, mrb_sym sym)
{
size_t i, len;
int i, len;
mrb_assert(s->irep);
@@ -539,7 +568,7 @@ new_msym(codegen_scope *s, mrb_sym sym)
static int
new_sym(codegen_scope *s, mrb_sym sym)
{
size_t i;
int i;
for (i=0; i<s->irep->slen; i++) {
if (s->irep->syms[i] == sym) return i;
@@ -573,8 +602,8 @@ node_len(node *tree)
return n;
}
#define sym(x) ((mrb_sym)(intptr_t)(x))
#define lv_name(lv) sym((lv)->car)
#define nsym(x) ((mrb_sym)(intptr_t)(x))
#define lv_name(lv) nsym((lv)->car)
static int
lv_idx(codegen_scope *s, mrb_sym id)
{
@@ -633,6 +662,7 @@ for_body(codegen_scope *s, node *tree)
scope_finish(s);
s = prev;
genop(s, MKOP_Abc(OP_LAMBDA, cursp(), s->irep->rlen-1, OP_L_BLOCK));
push();pop(); /* space for a block */
pop();
idx = new_msym(s, mrb_intern_lit(s->mrb, "each"));
genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0));
@@ -701,7 +731,7 @@ lambda_body(codegen_scope *s, node *tree, int blk)
dispatch(s, pos+i);
codegen(s, opt->car->cdr, VAL);
idx = lv_idx(s, (mrb_sym)(intptr_t)opt->car->car);
idx = lv_idx(s, nsym(opt->car->car));
pop();
genop_peep(s, MKOP_AB(OP_MOVE, idx, cursp()), NOVAL);
i++;
@@ -764,11 +794,14 @@ scope_body(codegen_scope *s, node *tree, int val)
return s->irep->rlen - 1;
}
#define nint(x) ((int)(intptr_t)(x))
#define nchar(x) ((char)(intptr_t)(x))
static mrb_bool
nosplat(node *t)
{
while (t) {
if ((intptr_t)t->car->car == NODE_SPLAT) return FALSE;
if (nint(t->car->car) == NODE_SPLAT) return FALSE;
t = t->cdr;
}
return TRUE;
@@ -804,12 +837,12 @@ gen_values(codegen_scope *s, node *t, int val, int extra)
int is_splat;
while (t) {
is_splat = (intptr_t)t->car->car == NODE_SPLAT; /* splat mode */
is_splat = nint(t->car->car) == NODE_SPLAT; /* splat mode */
if (
n+extra >= CALL_MAXARGS - 1 /* need to subtract one because vm.c expects an array if n == CALL_MAXARGS */
|| is_splat) {
if (val) {
if (is_splat && n == 0 && (intptr_t)t->car->cdr->car == NODE_ARRAY) {
if (is_splat && n == 0 && nint(t->car->cdr->car) == NODE_ARRAY) {
codegen(s, t->car->cdr, VAL);
pop();
}
@@ -820,10 +853,10 @@ gen_values(codegen_scope *s, node *t, int val, int extra)
codegen(s, t->car, VAL);
pop(); pop();
if (is_splat) {
genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
genop_peep(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1), NOVAL);
}
else {
genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
genop_peep(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1), NOVAL);
}
}
t = t->cdr;
@@ -831,11 +864,11 @@ gen_values(codegen_scope *s, node *t, int val, int extra)
push();
codegen(s, t->car, VAL);
pop(); pop();
if ((intptr_t)t->car->car == NODE_SPLAT) {
genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
if (nint(t->car->car) == NODE_SPLAT) {
genop_peep(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1), NOVAL);
}
else {
genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
genop_peep(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1), NOVAL);
}
t = t->cdr;
}
@@ -859,7 +892,7 @@ gen_values(codegen_scope *s, node *t, int val, int extra)
static void
gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
{
mrb_sym sym = name ? name : sym(tree->cdr->car);
mrb_sym sym = name ? name : nsym(tree->cdr->car);
int idx, skip = 0;
int n = 0, noop = 0, sendv = 0, blk = 0;
@@ -869,7 +902,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
genop(s, MKOP_A(OP_LOADNIL, cursp()));
push();
genop(s, MKOP_AB(OP_MOVE, cursp(), recv));
push(); pop(); /* space for a block */
push_n(2); pop_n(2); /* space for one arg and a block */
pop();
idx = new_msym(s, mrb_intern_lit(s->mrb, "=="));
genop(s, MKOP_ABC(OP_EQ, cursp(), idx, 1));
@@ -959,16 +992,16 @@ static void
gen_assignment(codegen_scope *s, node *tree, int sp, int val)
{
int idx;
int type = (intptr_t)tree->car;
int type = nint(tree->car);
tree = tree->cdr;
switch (type) {
case NODE_GVAR:
idx = new_sym(s, sym(tree));
idx = new_sym(s, nsym(tree));
genop_peep(s, MKOP_ABx(OP_SETGLOBAL, sp, idx), val);
break;
case NODE_LVAR:
idx = lv_idx(s, sym(tree));
idx = lv_idx(s, nsym(tree));
if (idx > 0) {
if (idx != sp) {
genop_peep(s, MKOP_AB(OP_MOVE, idx, sp), val);
@@ -980,7 +1013,7 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
codegen_scope *up = s->prev;
while (up) {
idx = lv_idx(up, sym(tree));
idx = lv_idx(up, nsym(tree));
if (idx > 0) {
genop_peep(s, MKOP_ABC(OP_SETUPVAR, sp, idx, lv), val);
break;
@@ -991,19 +1024,19 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
}
break;
case NODE_IVAR:
idx = new_sym(s, sym(tree));
idx = new_sym(s, nsym(tree));
genop_peep(s, MKOP_ABx(OP_SETIV, sp, idx), val);
break;
case NODE_CVAR:
idx = new_sym(s, sym(tree));
idx = new_sym(s, nsym(tree));
genop_peep(s, MKOP_ABx(OP_SETCV, sp, idx), val);
break;
case NODE_CONST:
idx = new_sym(s, sym(tree));
idx = new_sym(s, nsym(tree));
genop_peep(s, MKOP_ABx(OP_SETCONST, sp, idx), val);
break;
case NODE_COLON2:
idx = new_sym(s, sym(tree->cdr));
idx = new_sym(s, nsym(tree->cdr));
genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), NOVAL);
push();
codegen(s, tree->car, VAL);
@@ -1014,7 +1047,7 @@ gen_assignment(codegen_scope *s, node *tree, int sp, int val)
case NODE_CALL:
case NODE_SCALL:
push();
gen_call(s, tree, attrsym(s, sym(tree->cdr->car)), sp, NOVAL,
gen_call(s, tree, attrsym(s, nsym(tree->cdr->car)), sp, NOVAL,
type == NODE_SCALL);
pop();
if (val) {
@@ -1094,6 +1127,7 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
static void
gen_send_intern(codegen_scope *s)
{
push();pop(); /* space for a block */
pop();
genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "intern")), 0));
push();
@@ -1105,9 +1139,9 @@ gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
int i = 0, j = 0;
while (tree) {
switch ((intptr_t)tree->car->car) {
switch (nint(tree->car->car)) {
case NODE_STR:
if ((tree->cdr == NULL) && ((intptr_t)tree->car->cdr->cdr == 0))
if ((tree->cdr == NULL) && (nint(tree->car->cdr->cdr) == 0))
break;
/* fall through */
case NODE_BEGIN:
@@ -1143,7 +1177,7 @@ gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
}
else {
while (tree) {
switch ((intptr_t)tree->car->car) {
switch (nint(tree->car->car)) {
case NODE_BEGIN: case NODE_BLOCK:
codegen(s, tree->car, NOVAL);
}
@@ -1160,6 +1194,7 @@ raise_error(codegen_scope *s, const char *msg)
genop(s, MKOP_ABx(OP_ERR, 1, idx));
}
#ifndef MRB_WITHOUT_FLOAT
static double
readint_float(codegen_scope *s, const char *p, int base)
{
@@ -1185,6 +1220,7 @@ readint_float(codegen_scope *s, const char *p, int base)
}
return f;
}
#endif
static mrb_int
readint_mrb_int(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_bool *overflow)
@@ -1232,7 +1268,7 @@ readint_mrb_int(codegen_scope *s, const char *p, int base, mrb_bool neg, mrb_boo
static void
gen_retval(codegen_scope *s, node *tree)
{
if ((intptr_t)tree->car == NODE_SPLAT) {
if (nint(tree->car) == NODE_SPLAT) {
genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), 0));
push();
codegen(s, tree, VAL);
@@ -1271,7 +1307,7 @@ codegen(codegen_scope *s, node *tree, int val)
s->filename = mrb_parser_get_filename(s->parser, tree->filename_index);
}
nt = (intptr_t)tree->car;
nt = nint(tree->car);
s->lineno = tree->lineno;
tree = tree->cdr;
switch (nt) {
@@ -1316,9 +1352,10 @@ codegen(codegen_scope *s, node *tree, int val)
if (pos1) dispatch(s, pos1);
pos2 = 0;
do {
if (n4 && n4->car && (intptr_t)n4->car->car == NODE_SPLAT) {
if (n4 && n4->car && nint(n4->car->car) == NODE_SPLAT) {
codegen(s, n4->car, VAL);
genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
push_n(2); pop_n(2); /* space for one arg and a block */
pop();
genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
}
@@ -1333,6 +1370,7 @@ codegen(codegen_scope *s, node *tree, int val)
pop();
genop(s, MKOP_ABC(OP_RESCUE, exc, cursp(), 1));
}
distcheck(s, pos2);
tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
pos2 = tmp;
if (n4) {
@@ -1350,6 +1388,7 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, n3->cdr->cdr->car, val);
if (val) pop();
}
distcheck(s, exend);
tmp = genop(s, MKOP_sBx(OP_JMP, exend));
exend = tmp;
n2 = n2->cdr;
@@ -1377,7 +1416,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_ENSURE:
if (!tree->cdr || !tree->cdr->cdr ||
((intptr_t)tree->cdr->cdr->car == NODE_BEGIN &&
(nint(tree->cdr->cdr->car) == NODE_BEGIN &&
tree->cdr->cdr->cdr)) {
int idx;
int epush = s->pc;
@@ -1422,7 +1461,7 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, e, val);
goto exit;
}
switch ((intptr_t)tree->car->car) {
switch (nint(tree->car->car)) {
case NODE_TRUE:
case NODE_INT:
case NODE_STR:
@@ -1495,6 +1534,7 @@ codegen(codegen_scope *s, node *tree, int val)
dispatch(s, lp->pc1);
codegen(s, tree->car, VAL);
pop();
distcheck(s, lp->pc2 - s->pc);
genop(s, MKOP_AsBx(OP_JMPIF, cursp(), lp->pc2 - s->pc));
loop_pop(s, val);
@@ -1511,6 +1551,7 @@ codegen(codegen_scope *s, node *tree, int val)
dispatch(s, lp->pc1);
codegen(s, tree->car, VAL);
pop();
distcheck(s, lp->pc2 - s->pc);
genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), lp->pc2 - s->pc));
loop_pop(s, val);
@@ -1541,8 +1582,9 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, n->car, VAL);
if (head) {
genop(s, MKOP_AB(OP_MOVE, cursp(), head));
push_n(2); pop_n(2); /* space for one arg and a block */
pop();
if ((intptr_t)n->car->car == NODE_SPLAT) {
if (nint(n->car->car) == NODE_SPLAT) {
genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
}
else {
@@ -1552,6 +1594,7 @@ codegen(codegen_scope *s, node *tree, int val)
else {
pop();
}
distcheck(s, pos2);
tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
pos2 = tmp;
n = n->cdr;
@@ -1562,6 +1605,7 @@ codegen(codegen_scope *s, node *tree, int val)
}
codegen(s, tree->car->cdr, val);
if (val) pop();
distcheck(s, pos3);
tmp = genop(s, MKOP_sBx(OP_JMP, pos3));
pos3 = tmp;
if (pos1) dispatch(s, pos1);
@@ -1622,7 +1666,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_COLON2:
{
int sym = new_sym(s, sym(tree->cdr));
int sym = new_sym(s, nsym(tree->cdr));
codegen(s, tree->car, VAL);
pop();
@@ -1633,7 +1677,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_COLON3:
{
int sym = new_sym(s, sym(tree));
int sym = new_sym(s, nsym(tree));
genop(s, MKOP_A(OP_OCLASS, cursp()));
genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
@@ -1709,7 +1753,7 @@ codegen(codegen_scope *s, node *tree, int val)
node *t = tree->cdr, *p;
int rhs = cursp();
if ((intptr_t)t->car == NODE_ARRAY && t->cdr && nosplat(t->cdr)) {
if (nint(t->car) == NODE_ARRAY && t->cdr && nosplat(t->cdr)) {
/* fixed rhs */
t = t->cdr;
while (t) {
@@ -1783,14 +1827,14 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_OP_ASGN:
{
mrb_sym sym = sym(tree->cdr->car);
mrb_sym sym = nsym(tree->cdr->car);
mrb_int len;
const char *name = mrb_sym2name_len(s->mrb, sym, &len);
int idx, callargs = -1, vsp = -1;
if ((len == 2 && name[0] == '|' && name[1] == '|') &&
((intptr_t)tree->car->car == NODE_CONST ||
(intptr_t)tree->car->car == NODE_CVAR)) {
(nint(tree->car->car) == NODE_CONST ||
nint(tree->car->car) == NODE_CVAR)) {
int onerr, noexc, exc;
struct loopinfo *lp;
@@ -1808,45 +1852,36 @@ codegen(codegen_scope *s, node *tree, int val)
dispatch(s, noexc);
loop_pop(s, NOVAL);
}
else if ((intptr_t)tree->car->car == NODE_CALL) {
else if (nint(tree->car->car) == NODE_CALL) {
node *n = tree->car->cdr;
int base, i, nargs = 0;
callargs = 0;
if (val) {
vsp = cursp();
push();
}
codegen(s, n->car, VAL); /* receiver */
idx = new_msym(s, sym(n->cdr->car));
idx = new_msym(s, nsym(n->cdr->car));
base = cursp()-1;
if (n->cdr->cdr->car) {
int base = cursp()-1;
int nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 1);
/* copy receiver and arguments */
nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 1);
if (nargs >= 0) {
int i;
genop(s, MKOP_AB(OP_MOVE, cursp(), base));
for (i=0; i<nargs; i++) {
genop(s, MKOP_AB(OP_MOVE, cursp()+i+1, base+i+1));
}
push_n(nargs+1);
pop_n(nargs+1);
callargs = nargs;
}
else {
/* varargs */
else { /* varargs */
push();
genop(s, MKOP_AB(OP_MOVE, cursp(), base));
genop(s, MKOP_AB(OP_MOVE, cursp()+1, base+1));
nargs = 1;
callargs = CALL_MAXARGS;
}
genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
}
else {
genop(s, MKOP_AB(OP_MOVE, cursp(), cursp()-1));
genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 0));
callargs = 0;
/* copy receiver and arguments */
genop(s, MKOP_AB(OP_MOVE, cursp(), base));
for (i=0; i<nargs; i++) {
genop(s, MKOP_AB(OP_MOVE, cursp()+i+1, base+i+1));
}
push_n(nargs+2);pop_n(nargs+2); /* space for receiver, arguments and a block */
genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
push();
}
else {
@@ -1872,21 +1907,18 @@ codegen(codegen_scope *s, node *tree, int val)
if (val && vsp >= 0) {
genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
}
if ((intptr_t)tree->car->car == NODE_CALL) {
mrb_sym m = sym(tree->car->cdr->cdr->car);
mrb_sym m2 = attrsym(s, m);
idx = new_msym(s, m2);
pop();
if (nint(tree->car->car) == NODE_CALL) {
if (callargs == CALL_MAXARGS) {
genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
pop();
genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
}
else {
pop_n(callargs);
genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs+1));
callargs++;
}
pop();
idx = new_msym(s, attrsym(s, nsym(tree->car->cdr->cdr->car)));
genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
}
else {
gen_assignment(s, tree->car, cursp(), val);
@@ -1942,7 +1974,7 @@ codegen(codegen_scope *s, node *tree, int val)
callargs++;
}
pop();
idx = new_msym(s, attrsym(s,sym(tree->car->cdr->cdr->car)));
idx = new_msym(s, attrsym(s,nsym(tree->car->cdr->cdr->car)));
genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
}
}
@@ -2048,6 +2080,7 @@ codegen(codegen_scope *s, node *tree, int val)
push();
}
}
push();pop(); /* space for a block */
pop_n(n+1);
genop(s, MKOP_ABx(OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf)));
if (sendv) n = CALL_MAXARGS;
@@ -2070,6 +2103,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
}
codegen(s, tree, NOVAL);
distcheck(s, s->loop->pc1 - s->pc);
genop(s, MKOP_sBx(OP_JMP, s->loop->pc1 - s->pc));
}
else {
@@ -2093,6 +2127,7 @@ codegen(codegen_scope *s, node *tree, int val)
if (s->ensure_level > s->loop->ensure_level) {
genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
}
distcheck(s, s->loop->pc2 - s->pc);
genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc));
}
if (val) push();
@@ -2120,13 +2155,12 @@ codegen(codegen_scope *s, node *tree, int val)
}
else {
if (n > 0) {
while (n--) {
genop_peep(s, MKOP_A(OP_POPERR, 1), NOVAL);
}
genop_peep(s, MKOP_A(OP_POPERR, n), NOVAL);
}
if (s->ensure_level > lp->ensure_level) {
genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - lp->ensure_level), NOVAL);
}
distcheck(s, s->loop->pc1 - s->pc);
genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc));
}
}
@@ -2136,7 +2170,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_LVAR:
if (val) {
int idx = lv_idx(s, sym(tree));
int idx = lv_idx(s, nsym(tree));
if (idx > 0) {
genop_peep(s, MKOP_AB(OP_MOVE, cursp(), idx), NOVAL);
@@ -2146,9 +2180,9 @@ codegen(codegen_scope *s, node *tree, int val)
codegen_scope *up = s->prev;
while (up) {
idx = lv_idx(up, sym(tree));
idx = lv_idx(up, nsym(tree));
if (idx > 0) {
genop(s, MKOP_ABC(OP_GETUPVAR, cursp(), idx, lv));
genop_peep(s, MKOP_ABC(OP_GETUPVAR, cursp(), idx, lv), VAL);
break;
}
lv++;
@@ -2161,7 +2195,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_GVAR:
if (val) {
int sym = new_sym(s, sym(tree));
int sym = new_sym(s, nsym(tree));
genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
push();
@@ -2170,7 +2204,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_IVAR:
if (val) {
int sym = new_sym(s, sym(tree));
int sym = new_sym(s, nsym(tree));
genop(s, MKOP_ABx(OP_GETIV, cursp(), sym));
push();
@@ -2179,7 +2213,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_CVAR:
if (val) {
int sym = new_sym(s, sym(tree));
int sym = new_sym(s, nsym(tree));
genop(s, MKOP_ABx(OP_GETCV, cursp(), sym));
push();
@@ -2188,7 +2222,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_CONST:
{
int sym = new_sym(s, sym(tree));
int sym = new_sym(s, nsym(tree));
genop(s, MKOP_ABx(OP_GETCONST, cursp(), sym));
if (val) {
@@ -2207,7 +2241,7 @@ codegen(codegen_scope *s, node *tree, int val)
int sym;
buf[0] = '$';
buf[1] = (char)(intptr_t)tree;
buf[1] = nchar(tree);
buf[2] = 0;
sym = new_sym(s, mrb_intern_cstr(s->mrb, buf));
genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
@@ -2221,7 +2255,7 @@ codegen(codegen_scope *s, node *tree, int val)
mrb_value str;
int sym;
str = mrb_format(mrb, "$%S", mrb_fixnum_value((mrb_int)(intptr_t)tree));
str = mrb_format(mrb, "$%S", mrb_fixnum_value(nint(tree)));
sym = new_sym(s, mrb_intern_str(mrb, str));
genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
push();
@@ -2239,19 +2273,22 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_INT:
if (val) {
char *p = (char*)tree->car;
int base = (intptr_t)tree->cdr->car;
int base = nint(tree->cdr->car);
mrb_int i;
mrb_code co;
mrb_bool overflow;
i = readint_mrb_int(s, p, base, FALSE, &overflow);
#ifndef MRB_WITHOUT_FLOAT
if (overflow) {
double f = readint_float(s, p, base);
int off = new_lit(s, mrb_float_value(s->mrb, f));
genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
}
else {
else
#endif
{
if (i < MAXARG_sBx && i > -MAXARG_sBx) {
co = MKOP_AsBx(OP_LOADI, cursp(), i);
}
@@ -2265,6 +2302,7 @@ codegen(codegen_scope *s, node *tree, int val)
}
break;
#ifndef MRB_WITHOUT_FLOAT
case NODE_FLOAT:
if (val) {
char *p = (char*)tree;
@@ -2275,12 +2313,14 @@ codegen(codegen_scope *s, node *tree, int val)
push();
}
break;
#endif
case NODE_NEGATE:
{
nt = (intptr_t)tree->car;
nt = nint(tree->car);
tree = tree->cdr;
switch (nt) {
#ifndef MRB_WITHOUT_FLOAT
case NODE_FLOAT:
if (val) {
char *p = (char*)tree;
@@ -2291,16 +2331,18 @@ codegen(codegen_scope *s, node *tree, int val)
push();
}
break;
#endif
case NODE_INT:
if (val) {
char *p = (char*)tree->car;
int base = (intptr_t)tree->cdr->car;
int base = nint(tree->cdr->car);
mrb_int i;
mrb_code co;
mrb_bool overflow;
i = readint_mrb_int(s, p, base, TRUE, &overflow);
#ifndef MRB_WITHOUT_FLOAT
if (overflow) {
double f = readint_float(s, p, base);
int off = new_lit(s, mrb_float_value(s->mrb, -f));
@@ -2308,6 +2350,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
}
else {
#endif
if (i < MAXARG_sBx && i > -MAXARG_sBx) {
co = MKOP_AsBx(OP_LOADI, cursp(), i);
}
@@ -2316,7 +2359,9 @@ codegen(codegen_scope *s, node *tree, int val)
co = MKOP_ABx(OP_LOADL, cursp(), off);
}
genop(s, co);
#ifndef MRB_WITHOUT_FLOAT
}
#endif
push();
}
break;
@@ -2378,7 +2423,7 @@ codegen(codegen_scope *s, node *tree, int val)
node *n = tree;
while (n) {
if ((intptr_t)n->car->car != NODE_STR) {
if (nint(n->car->car) != NODE_STR) {
codegen(s, n->car, NOVAL);
}
n = n->cdr;
@@ -2405,7 +2450,7 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, tree->car, VAL);
n = tree->cdr;
while (n) {
if ((intptr_t)n->car->car == NODE_XSTR) {
if (nint(n->car->car) == NODE_XSTR) {
n->car->car = (struct mrb_ast_node*)(intptr_t)NODE_STR;
mrb_assert(!n->cdr); /* must be the end */
}
@@ -2458,26 +2503,26 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
push();
genop(s, MKOP_ABx(OP_STRING, cursp(), off));
push();
if (p2 || p3) {
push();
if (p2) {
if (p2) { /* opt */
off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
genop(s, MKOP_ABx(OP_STRING, cursp(), off));
}
else {
genop(s, MKOP_A(OP_LOADNIL, cursp()));
}
push();
argc++;
if (p3) {
push();
if (p3) { /* enc */
off = new_lit(s, mrb_str_new(s->mrb, p3, 1));
genop(s, MKOP_ABx(OP_STRING, cursp(), off));
push();
argc++;
pop();
}
pop();
}
pop();
push(); /* space for a block */
pop_n(argc+2);
sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
mrb_gc_arena_restore(s->mrb, ai);
@@ -2507,31 +2552,31 @@ codegen(codegen_scope *s, node *tree, int val)
n = n->cdr;
}
n = tree->cdr->cdr;
if (n->car) {
if (n->car) { /* tail */
p = (char*)n->car;
off = new_lit(s, mrb_str_new_cstr(s->mrb, p));
codegen(s, tree->car, VAL);
genop(s, MKOP_ABx(OP_STRING, cursp(), off));
pop();
genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
push();
}
if (n->cdr->car) {
if (n->cdr->car) { /* opt */
char *p2 = (char*)n->cdr->car;
push();
off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
genop(s, MKOP_ABx(OP_STRING, cursp(), off));
push();
argc++;
}
if (n->cdr->cdr) {
if (n->cdr->cdr) { /* enc */
char *p2 = (char*)n->cdr->cdr;
push();
off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
genop(s, MKOP_ABx(OP_STRING, cursp(), off));
push();
argc++;
}
pop_n(argc);
push(); /* space for a block */
pop_n(argc+2);
sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
mrb_gc_arena_restore(s->mrb, ai);
@@ -2541,7 +2586,7 @@ codegen(codegen_scope *s, node *tree, int val)
node *n = tree->car;
while (n) {
if ((intptr_t)n->car->car != NODE_STR) {
if (nint(n->car->car) != NODE_STR) {
codegen(s, n->car, NOVAL);
}
n = n->cdr;
@@ -2551,7 +2596,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_SYM:
if (val) {
int sym = new_sym(s, sym(tree));
int sym = new_sym(s, nsym(tree));
genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
push();
@@ -2595,8 +2640,8 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_ALIAS:
{
int a = new_msym(s, sym(tree->car));
int b = new_msym(s, sym(tree->cdr));
int a = new_msym(s, nsym(tree->car));
int b = new_msym(s, nsym(tree->cdr));
int c = new_msym(s, mrb_intern_lit(s->mrb, "alias_method"));
genop(s, MKOP_A(OP_TCLASS, cursp()));
@@ -2606,7 +2651,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_ABx(OP_LOADSYM, cursp(), b));
push();
genop(s, MKOP_A(OP_LOADNIL, cursp()));
push();
push(); /* space for a block */
pop_n(4);
genop(s, MKOP_ABC(OP_SEND, cursp(), c, 2));
if (val) {
@@ -2629,7 +2674,7 @@ codegen(codegen_scope *s, node *tree, int val)
pop_n(num);
genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), num));
while (t) {
symbol = new_msym(s, sym(t->car));
symbol = new_msym(s, nsym(t->car));
push();
genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
pop();
@@ -2639,12 +2684,13 @@ codegen(codegen_scope *s, node *tree, int val)
num = CALL_MAXARGS;
break;
}
symbol = new_msym(s, sym(t->car));
symbol = new_msym(s, nsym(t->car));
genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
push();
t = t->cdr;
num++;
}
push();pop(); /* space for a block */
pop();
if (num < CALL_MAXARGS) {
pop_n(num);
@@ -2679,7 +2725,7 @@ codegen(codegen_scope *s, node *tree, int val)
push();
}
pop(); pop();
idx = new_msym(s, sym(tree->car->cdr));
idx = new_msym(s, nsym(tree->car->cdr));
genop(s, MKOP_AB(OP_CLASS, cursp(), idx));
idx = scope_body(s, tree->cdr->cdr->car, val);
genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
@@ -2705,7 +2751,7 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, tree->car->car, VAL);
}
pop();
idx = new_msym(s, sym(tree->car->cdr));
idx = new_msym(s, nsym(tree->car->cdr));
genop(s, MKOP_AB(OP_MODULE, cursp(), idx));
idx = scope_body(s, tree->cdr->car, val);
genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
@@ -2732,7 +2778,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_DEF:
{
int sym = new_msym(s, sym(tree->car));
int sym = new_msym(s, nsym(tree->car));
int idx = lambda_body(s, tree->cdr, 0);
genop(s, MKOP_A(OP_TCLASS, cursp()));
@@ -2751,7 +2797,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_SDEF:
{
node *recv = tree->car;
int sym = new_msym(s, sym(tree->cdr->car));
int sym = new_msym(s, nsym(tree->cdr->car));
int idx = lambda_body(s, tree->cdr->cdr, 0);
codegen(s, recv, VAL);
@@ -2938,23 +2984,32 @@ loop_break(codegen_scope *s, node *tree)
}
else {
struct loopinfo *loop;
int n = 0;
if (tree) {
gen_retval(s, tree);
}
loop = s->loop;
while (loop && loop->type == LOOP_BEGIN) {
genop_peep(s, MKOP_A(OP_POPERR, 1), NOVAL);
loop = loop->prev;
}
while (loop && loop->type == LOOP_RESCUE) {
loop = loop->prev;
while (loop) {
if (loop->type == LOOP_BEGIN) {
n++;
loop = loop->prev;
}
else if (loop->type == LOOP_RESCUE) {
loop = loop->prev;
}
else{
break;
}
}
if (!loop) {
raise_error(s, "unexpected break");
return;
}
if (n > 0) {
genop_peep(s, MKOP_A(OP_POPERR, n), NOVAL);
}
if (loop->type == LOOP_NORMAL) {
int tmp;
@@ -2965,6 +3020,7 @@ loop_break(codegen_scope *s, node *tree)
if (tree) {
genop_peep(s, MKOP_AB(OP_MOVE, loop->acc, cursp()), NOVAL);
}
distcheck(s, s->loop->pc3);
tmp = genop(s, MKOP_sBx(OP_JMP, loop->pc3));
loop->pc3 = tmp;
}
@@ -2980,10 +3036,10 @@ loop_break(codegen_scope *s, node *tree)
static void
loop_pop(codegen_scope *s, int val)
{
dispatch_linked(s, s->loop->pc3);
if (val) {
genop(s, MKOP_A(OP_LOADNIL, cursp()));
}
dispatch_linked(s, s->loop->pc3);
s->loop = s->loop->prev;
if (val) push();
}
@@ -3011,6 +3067,9 @@ mrb_generate_code(mrb_state *mrb, parser_state *p)
mrb_irep_decref(mrb, scope->irep);
mrb_pool_close(scope->mpool);
proc->c = NULL;
if (mrb->c->cibase && mrb->c->cibase->proc == proc->upper) {
proc->upper = NULL;
}
mrb->jmp = prev_jmp;
return proc;
}
+5 -6
View File
@@ -52,7 +52,7 @@ inline
#endif
#endif
static unsigned int
hash (register const char *str, register unsigned int len)
hash (const char *str, unsigned int len)
{
static const unsigned char asso_values[] =
{
@@ -83,7 +83,7 @@ hash (register const char *str, register unsigned int len)
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
51, 51, 51, 51, 51, 51
};
register int hval = len;
int hval = len;
switch (hval)
{
@@ -105,7 +105,7 @@ __attribute__ ((__gnu_inline__))
#endif
#endif
const struct kwtable *
mrb_reserved_word (register const char *str, register unsigned int len)
mrb_reserved_word (const char *str, unsigned int len)
{
static const struct kwtable wordlist[] =
{
@@ -196,11 +196,11 @@ mrb_reserved_word (register const char *str, register unsigned int len)
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
{
register int key = hash (str, len);
int key = hash (str, len);
if (key <= MAX_HASH_VALUE && key >= 0)
{
register const char *s = wordlist[key].name;
const char *s = wordlist[key].name;
if (*str == *s && !strcmp (str + 1, s + 1))
return &wordlist[key];
@@ -209,4 +209,3 @@ mrb_reserved_word (register const char *str, register unsigned int len)
return 0;
}
#line 50 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
+69 -52
View File
@@ -740,16 +740,18 @@ new_int(parser_state *p, const char *s, int base)
return list3((node*)NODE_INT, (node*)strdup(s), nint(base));
}
#ifndef MRB_WITHOUT_FLOAT
/* (:float . i) */
static node*
new_float(parser_state *p, const char *s)
{
return cons((node*)NODE_FLOAT, (node*)strdup(s));
}
#endif
/* (:str . (s . len)) */
static node*
new_str(parser_state *p, const char *s, int len)
new_str(parser_state *p, const char *s, size_t len)
{
return cons((node*)NODE_STR, cons((node*)strndup(s, len), nint(len)));
}
@@ -1384,7 +1386,7 @@ command_asgn : lhs '=' command_rhs
backref_error(p, $1);
$$ = new_begin(p, 0);
}
;
;
command_rhs : command_call %prec tOP_ASGN
| command_call modifier_rescue stmt
@@ -2577,7 +2579,7 @@ do_block : keyword_do_block
local_nest(p);
}
opt_block_param
compstmt
bodystmt
keyword_end
{
$$ = new_block(p,$3,$4);
@@ -2667,7 +2669,7 @@ brace_block : '{'
$<num>$ = p->lineno;
}
opt_block_param
compstmt keyword_end
bodystmt keyword_end
{
$$ = new_block(p,$3,$4);
SET_LINENO($$, $<num>2);
@@ -2853,18 +2855,18 @@ words : tWORDS_BEG tSTRING
symbol : basic_symbol
{
p->lstate = EXPR_ENDARG;
$$ = new_sym(p, $1);
}
| tSYMBEG tSTRING_BEG string_rep tSTRING
{
p->lstate = EXPR_END;
p->lstate = EXPR_ENDARG;
$$ = new_dsym(p, push($3, $4));
}
;
basic_symbol : tSYMBEG sym
{
p->lstate = EXPR_END;
$$ = $2;
}
;
@@ -2968,6 +2970,15 @@ var_ref : variable
snprintf(buf, sizeof(buf), "%d", p->lineno);
$$ = new_int(p, buf, 10);
}
| keyword__ENCODING__
{
#ifdef MRB_UTF8_STRING
const char *enc = "UTF-8";
#else
const char *enc = "ASCII-8BIT";
#endif
$$ = new_str(p, enc, strlen(enc));
}
;
backref : tNTH_REF
@@ -3361,7 +3372,7 @@ static void
yyerror(parser_state *p, const char *s)
{
char* c;
int n;
size_t n;
if (! p->capture_errors) {
#ifndef MRB_DISABLE_STDIO
@@ -3397,7 +3408,7 @@ static void
yywarn(parser_state *p, const char *s)
{
char* c;
int n;
size_t n;
if (! p->capture_errors) {
#ifndef MRB_DISABLE_STDIO
@@ -3443,7 +3454,7 @@ backref_error(parser_state *p, node *n)
c = (int)(intptr_t)n->car;
if (c == NODE_NTH_REF) {
yyerror_i(p, "can't set variable $%" MRB_PRId, (mrb_int)(intptr_t)n->cdr);
yyerror_i(p, "can't set variable $%" MRB_PRId, (int)(intptr_t)n->cdr);
}
else if (c == NODE_BACK_REF) {
yyerror_i(p, "can't set variable $%c", (int)(intptr_t)n->cdr);
@@ -3593,7 +3604,7 @@ peek_n(parser_state *p, int c, int n)
static mrb_bool
peeks(parser_state *p, const char *s)
{
int len = strlen(s);
size_t len = strlen(s);
#ifndef MRB_DISABLE_STDIO
if (p->f) {
@@ -3629,7 +3640,7 @@ skips(parser_state *p, const char *s)
}
s++;
if (peeks(p, s)) {
int len = strlen(s);
size_t len = strlen(s);
while (len--) {
if (nextc(p) == '\n') {
@@ -3751,28 +3762,28 @@ toklen(parser_state *p)
#define IS_LABEL_POSSIBLE() ((p->lstate == EXPR_BEG && !cmd_state) || IS_ARG())
#define IS_LABEL_SUFFIX(n) (peek_n(p, ':',(n)) && !peek_n(p, ':', (n)+1))
static int
static int32_t
scan_oct(const int *start, int len, int *retlen)
{
const int *s = start;
int retval = 0;
int32_t retval = 0;
/* mrb_assert(len <= 3) */
while (len-- && *s >= '0' && *s <= '7') {
retval <<= 3;
retval |= *s++ - '0';
}
*retlen = s - start;
*retlen = (int)(s - start);
return retval;
}
static int32_t
scan_hex(const int *start, int len, int *retlen)
scan_hex(parser_state *p, const int *start, int len, int *retlen)
{
static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
const int *s = start;
int32_t retval = 0;
uint32_t retval = 0;
char *tmp;
/* mrb_assert(len <= 8) */
@@ -3781,22 +3792,26 @@ scan_hex(const int *start, int len, int *retlen)
retval |= (tmp - hexdigit) & 15;
s++;
}
*retlen = s - start;
*retlen = (int)(s - start);
return retval;
return (int32_t)retval;
}
static int32_t
read_escape_unicode(parser_state *p, int limit)
{
int32_t c;
int buf[9];
int i;
int32_t hex;
/* Look for opening brace */
i = 0;
buf[0] = nextc(p);
if (buf[0] < 0) goto eof;
if (buf[0] < 0) {
eof:
yyerror(p, "invalid escape character syntax");
return -1;
}
if (ISXDIGIT(buf[0])) {
/* \uxxxx form */
for (i=1; i<limit; i++) {
@@ -3811,17 +3826,12 @@ read_escape_unicode(parser_state *p, int limit)
else {
pushback(p, buf[0]);
}
c = scan_hex(buf, i, &i);
if (i == 0) {
eof:
yyerror(p, "Invalid escape character syntax");
hex = scan_hex(p, buf, i, &i);
if (i == 0 || hex > 0x10FFFF || (hex & 0xFFFFF800) == 0xD800) {
yyerror(p, "invalid Unicode code point");
return -1;
}
if (c < 0 || c > 0x10FFFF || (c & 0xFFFFF800) == 0xD800) {
yyerror(p, "Invalid Unicode code point");
return -1;
}
return c;
return hex;
}
/* Return negative to indicate Unicode code point */
@@ -3887,13 +3897,12 @@ read_escape(parser_state *p)
break;
}
}
c = scan_hex(buf, i, &i);
if (i == 0) {
yyerror(p, "Invalid escape character syntax");
return 0;
yyerror(p, "invalid hex escape");
return -1;
}
return scan_hex(p, buf, i, &i);
}
return c;
case 'u': /* Unicode */
if (peek(p, '{')) {
@@ -3960,9 +3969,9 @@ parse_string(parser_state *p)
{
int c;
string_type type = (string_type)(intptr_t)p->lex_strterm->car;
int nest_level = (intptr_t)p->lex_strterm->cdr->car;
int beg = (intptr_t)p->lex_strterm->cdr->cdr->car;
int end = (intptr_t)p->lex_strterm->cdr->cdr->cdr;
int nest_level = intn(p->lex_strterm->cdr->car);
int beg = intn(p->lex_strterm->cdr->cdr->car);
int end = intn(p->lex_strterm->cdr->cdr->cdr);
parser_heredoc_info *hinf = (type & STR_FUNC_HEREDOC) ? parsing_heredoc_inf(p) : NULL;
int cmd_state = p->cmd_start;
@@ -4118,7 +4127,7 @@ parse_string(parser_state *p)
}
tokfix(p);
p->lstate = EXPR_END;
p->lstate = EXPR_ENDARG;
end_strterm(p);
if (type & STR_FUNC_XQUOTE) {
@@ -4605,7 +4614,7 @@ parser_yylex(parser_state *p)
}
tokfix(p);
pylval.nd = new_str(p, tok(p), toklen(p));
p->lstate = EXPR_END;
p->lstate = EXPR_ENDARG;
return tCHAR;
case '&':
@@ -4754,7 +4763,7 @@ parser_yylex(parser_state *p)
int is_float, seen_point, seen_e, nondigit;
is_float = seen_point = seen_e = nondigit = 0;
p->lstate = EXPR_END;
p->lstate = EXPR_ENDARG;
newtok(p);
if (c == '-' || c == '+') {
tokadd(p, c);
@@ -4955,6 +4964,11 @@ parser_yylex(parser_state *p)
}
tokfix(p);
if (is_float) {
#ifdef MRB_WITHOUT_FLOAT
yywarning_s(p, "floating point numbers are not supported", tok(p));
pylval.nd = new_int(p, "0", 10);
return tINTEGER;
#else
double d;
char *endp;
@@ -4969,6 +4983,7 @@ parser_yylex(parser_state *p)
}
pylval.nd = new_float(p, tok(p));
return tFLOAT;
#endif
}
pylval.nd = new_int(p, tok(p), 10);
return tINTEGER;
@@ -4984,7 +4999,7 @@ parser_yylex(parser_state *p)
if (c == ')')
p->lstate = EXPR_ENDFN;
else
p->lstate = EXPR_ENDARG;
p->lstate = EXPR_END;
return c;
case ':':
@@ -5071,6 +5086,9 @@ parser_yylex(parser_state *p)
else if (IS_SPCARG(-1)) {
c = tLPAREN_ARG;
}
else if (p->lstate == EXPR_END && space_seen) {
c = tLPAREN_ARG;
}
p->paren_nest++;
COND_PUSH(0);
CMDARG_PUSH(0);
@@ -5490,11 +5508,9 @@ parser_yylex(parser_state *p)
mrb_sym ident = intern_cstr(tok(p));
pylval.id = ident;
#if 0
if (last_state != EXPR_DOT && islower(tok(p)[0]) && lvar_defined(ident)) {
if (last_state != EXPR_DOT && islower(tok(p)[0]) && local_var_p(p, ident)) {
p->lstate = EXPR_END;
}
#endif
}
return result;
}
@@ -5558,7 +5574,7 @@ mrb_parser_parse(parser_state *p, mrbc_context *c)
p->jmp = &buf1;
MRB_TRY(p->jmp) {
int n;
int n = 1;
p->cmd_start = TRUE;
p->in_def = p->in_single = 0;
@@ -5674,7 +5690,7 @@ MRB_API const char*
mrbc_filename(mrb_state *mrb, mrbc_context *c, const char *s)
{
if (s) {
int len = strlen(s);
size_t len = strlen(s);
char *p = (char *)mrb_malloc(mrb, len + 1);
memcpy(p, s, len + 1);
@@ -5706,16 +5722,16 @@ mrb_parser_set_filename(struct mrb_parser_state *p, const char *f)
for (i = 0; i < p->filename_table_length; ++i) {
if (p->filename_table[i] == sym) {
p->current_filename_index = i;
p->current_filename_index = (int)i;
return;
}
}
p->current_filename_index = p->filename_table_length++;
p->current_filename_index = (int)p->filename_table_length++;
new_table = (mrb_sym*)parser_palloc(p, sizeof(mrb_sym) * p->filename_table_length);
if (p->filename_table) {
memmove(new_table, p->filename_table, sizeof(mrb_sym) * p->filename_table_length);
memmove(new_table, p->filename_table, sizeof(mrb_sym) * p->current_filename_index);
}
p->filename_table = new_table;
p->filename_table[p->filename_table_length - 1] = sym;
@@ -5746,7 +5762,7 @@ mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c)
#endif
MRB_API parser_state*
mrb_parse_nstring(mrb_state *mrb, const char *s, int len, mrbc_context *c)
mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len, mrbc_context *c)
{
parser_state *p;
@@ -5777,6 +5793,7 @@ mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c)
return mrb_undef_value();
}
if (!p->tree || p->nerr) {
if (c) c->parser_nerr = p->nerr;
if (p->capture_errors) {
char buf[256];
int n;
@@ -5816,7 +5833,7 @@ mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c)
c->keep_lv = TRUE;
}
}
proc->target_class = target;
MRB_PROC_SET_TARGET_CLASS(proc, target);
if (mrb->c->ci) {
mrb->c->ci->target_class = target;
}
@@ -5840,13 +5857,13 @@ mrb_load_file(mrb_state *mrb, FILE *f)
#endif
MRB_API mrb_value
mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *c)
mrb_load_nstring_cxt(mrb_state *mrb, const char *s, size_t len, mrbc_context *c)
{
return mrb_load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c);
}
MRB_API mrb_value
mrb_load_nstring(mrb_state *mrb, const char *s, int len)
mrb_load_nstring(mrb_state *mrb, const char *s, size_t len)
{
return mrb_load_nstring_cxt(mrb, s, len, NULL);
}
+108 -6
View File
@@ -201,7 +201,7 @@ module Enumerable
ary.push([block.call(e), i])
}
if ary.size > 1
__sort_sub__(ary, ::Array.new(ary.size), 0, 0, ary.size - 1) do |a,b|
__sort_sub__(ary, 0, ary.size - 1) do |a,b|
a <=> b
end
end
@@ -451,20 +451,30 @@ module Enumerable
##
# call-seq:
# enum.none? [{ |obj| block }] -> true or false
# enum.none?(pattern) -> true or false
#
# Passes each element of the collection to the given block. The method
# returns <code>true</code> if the block never returns <code>true</code>
# for all elements. If the block is not given, <code>none?</code> will return
# <code>true</code> only if none of the collection members is true.
#
# If a pattern is supplied instead, the method returns whether
# <code>pattern === element</code> for none of the collection members.
#
# %w(ant bear cat).none? { |word| word.length == 5 } #=> true
# %w(ant bear cat).none? { |word| word.length >= 4 } #=> false
# %w{ant bear cat}.none?(/d/) #=> true
# [1, 3.14, 42].none?(Float) #=> false
# [].none? #=> true
# [nil, false].none? #=> true
# [nil, true].none? #=> false
def none?(&block)
if block
def none?(pat=NONE, &block)
if pat != NONE
self.each do |*val|
return false if pat === val.__svalue
end
elsif block
self.each do |*val|
return false if block.call(*val)
end
@@ -479,6 +489,7 @@ module Enumerable
##
# call-seq:
# enum.one? [{ |obj| block }] -> true or false
# enum.one?(pattern) -> true or false
#
# Passes each element of the collection to the given block. The method
# returns <code>true</code> if the block returns <code>true</code>
@@ -486,16 +497,26 @@ module Enumerable
# <code>true</code> only if exactly one of the collection members is
# true.
#
# If a pattern is supplied instead, the method returns whether
# <code>pattern === element</code> for exactly one collection member.
#
# %w(ant bear cat).one? { |word| word.length == 4 } #=> true
# %w(ant bear cat).one? { |word| word.length > 4 } #=> false
# %w(ant bear cat).one? { |word| word.length < 4 } #=> false
# %w{ant bear cat}.one?(/t/) #=> false
# [nil, true, 99].one? #=> false
# [nil, true, false].one? #=> true
#
# [ nil, true, 99 ].one?(Integer) #=> true
# [].one? #=> false
def one?(&block)
def one?(pat=NONE, &block)
count = 0
if block
if pat!=NONE
self.each do |*val|
count += 1 if pat === val.__svalue
return false if count > 1
end
elsif block
self.each do |*val|
count += 1 if block.call(*val)
return false if count > 1
@@ -510,6 +531,71 @@ module Enumerable
count == 1 ? true : false
end
# ISO 15.3.2.2.1
# call-seq:
# enum.all? [{ |obj| block } ] -> true or false
# enum.all?(pattern) -> true or false
#
# Passes each element of the collection to the given block. The method
# returns <code>true</code> if the block never returns
# <code>false</code> or <code>nil</code>. If the block is not given,
# Ruby adds an implicit block of <code>{ |obj| obj }</code> which will
# cause #all? to return +true+ when none of the collection members are
# +false+ or +nil+.
#
# If a pattern is supplied instead, the method returns whether
# <code>pattern === element</code> for every collection member.
#
# %w[ant bear cat].all? { |word| word.length >= 3 } #=> true
# %w[ant bear cat].all? { |word| word.length >= 4 } #=> false
# %w[ant bear cat].all?(/t/) #=> false
# [1, 2i, 3.14].all?(Numeric) #=> true
# [nil, true, 99].all? #=> false
#
def all?(pat=NONE, &block)
if pat != NONE
self.each{|*val| return false unless pat === val.__svalue}
elsif block
self.each{|*val| return false unless block.call(*val)}
else
self.each{|*val| return false unless val.__svalue}
end
true
end
# ISO 15.3.2.2.2
# call-seq:
# enum.any? [{ |obj| block }] -> true or false
# enum.any?(pattern) -> true or false
#
# Passes each element of the collection to the given block. The method
# returns <code>true</code> if the block ever returns a value other
# than <code>false</code> or <code>nil</code>. If the block is not
# given, Ruby adds an implicit block of <code>{ |obj| obj }</code> that
# will cause #any? to return +true+ if at least one of the collection
# members is not +false+ or +nil+.
#
# If a pattern is supplied instead, the method returns whether
# <code>pattern === element</code> for any collection member.
#
# %w[ant bear cat].any? { |word| word.length >= 3 } #=> true
# %w[ant bear cat].any? { |word| word.length >= 4 } #=> true
# %w[ant bear cat].any?(/d/) #=> false
# [nil, true, 99].any?(Integer) #=> true
# [nil, true, 99].any? #=> true
# [].any? #=> false
#
def any?(pat=NONE, &block)
if pat != NONE
self.each{|*val| return true if pat === val.__svalue}
elsif block
self.each{|*val| return true if block.call(*val)}
else
self.each{|*val| return true if val.__svalue}
end
false
end
##
# call-seq:
# enum.each_with_object(obj) { |(*args), memo_obj| ... } -> obj
@@ -708,4 +794,20 @@ module Enumerable
def nil.to_h
{}
end
def uniq(&block)
hash = {}
if block
self.each do|*v|
v = v.__svalue
hash[block.call(v)] ||= v
end
else
self.each do|*v|
v = v.__svalue
hash[v] ||= v
end
end
hash.values
end
end
+14
View File
@@ -100,6 +100,7 @@ end
assert("Enumerable#none?") do
assert_true %w(ant bear cat).none? { |word| word.length == 5 }
assert_false %w(ant bear cat).none? { |word| word.length >= 4 }
assert_false [1, 3.14, 42].none?(Float)
assert_true [].none?
assert_true [nil, false].none?
assert_false [nil, true].none?
@@ -109,8 +110,21 @@ assert("Enumerable#one?") do
assert_true %w(ant bear cat).one? { |word| word.length == 4 }
assert_false %w(ant bear cat).one? { |word| word.length > 4 }
assert_false %w(ant bear cat).one? { |word| word.length < 4 }
assert_true [1, 3.14, 42].one?(Float)
assert_false [nil, true, 99].one?
assert_true [nil, true, false].one?
assert_true [ nil, true, 99 ].one?(Integer)
assert_false [].one?
end
assert("Enumerable#all? (enhancement)") do
assert_false [1, 2, 3.14].all?(Integer)
assert_true [1, 2, 3.14].all?(Numeric)
end
assert("Enumerable#any? (enhancement)") do
assert_false [1, 2, 3].all?(Float)
assert_true [nil, true, 99].any?(Integer)
end
assert("Enumerable#each_with_object") do
+19 -1
View File
@@ -43,6 +43,9 @@ class Enumerator
end
def to_enum(meth=:each, *args, &block)
unless self.respond_to?(meth)
raise NoMethodError, "undefined method #{meth}"
end
lz = Lazy.new(self, &block)
lz.obj = self
lz.meth = meth
@@ -69,7 +72,7 @@ class Enumerator
def reject(&block)
Lazy.new(self){|yielder, val|
if not block.call(val)
unless block.call(val)
yielder << val
end
}
@@ -155,6 +158,21 @@ class Enumerator
}
end
def uniq(&block)
hash = {}
Lazy.new(self){|yielder, val|
if block
v = block.call(val)
else
v = val
end
unless hash.include?(v)
yielder << val
hash[v] = val
end
}
end
alias force to_a
end
end
+14 -10
View File
@@ -110,11 +110,14 @@ class Enumerator
# p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
#
def initialize(obj=nil, meth=:each, *args, &block)
if block_given?
if block
obj = Generator.new(&block)
else
raise ArgumentError unless obj
end
if @obj and !self.respond_to?(meth)
raise NoMethodError, "undefined method #{meth}"
end
@obj = obj
@meth = meth
@@ -151,8 +154,9 @@ class Enumerator
#
# +offset+:: the starting index to use
#
def with_index(offset=0)
return to_enum :with_index, offset unless block_given?
def with_index(offset=0, &block)
return to_enum :with_index, offset unless block
offset = if offset.nil?
0
elsif offset.respond_to?(:to_int)
@@ -164,7 +168,7 @@ class Enumerator
n = offset - 1
enumerator_block_call do |*i|
n += 1
yield i.__svalue, n
block.call i.__svalue, n
end
end
@@ -209,11 +213,11 @@ class Enumerator
# # => foo:1
# # => foo:2
#
def with_object(object)
return to_enum(:with_object, object) unless block_given?
def with_object(object, &block)
return to_enum(:with_object, object) unless block
enumerator_block_call do |i|
yield [i,object]
block.call [i,object]
end
object
end
@@ -277,7 +281,7 @@ class Enumerator
end
obj.args = args
end
return obj unless block_given?
return obj unless block
enumerator_block_call(&block)
end
@@ -538,7 +542,7 @@ class Enumerator
# just for internal
class Yielder
def initialize(&block)
raise LocalJumpError, "no block given" unless block_given?
raise LocalJumpError, "no block given" unless block
@proc = block
end
@@ -612,7 +616,7 @@ module Kernel
def to_enum(meth=:each, *args)
Enumerator.new self, meth, *args
end
alias :enum_for :to_enum
alias enum_for to_enum
end
module Enumerable
+5 -5
View File
@@ -33,7 +33,7 @@ assert 'Enumerator.new' do
a, b = b, a + b
end
end
assert_equal fib.take(10), [1,1,2,3,5,8,13,21,34,55]
assert_equal [1,1,2,3,5,8,13,21,34,55], fib.take(10)
end
assert 'Enumerator#initialize_copy' do
@@ -509,28 +509,28 @@ end
assert 'Hash#select' do
h = {1=>2,3=>4,5=>6}
hret = h.select.with_index {|a,b| a[1] == 4}
hret = h.select.with_index {|a,_b| a[1] == 4}
assert_equal({3=>4}, hret)
assert_equal({1=>2,3=>4,5=>6}, h)
end
assert 'Hash#select!' do
h = {1=>2,3=>4,5=>6}
hret = h.select!.with_index {|a,b| a[1] == 4}
hret = h.select!.with_index {|a,_b| a[1] == 4}
assert_equal h, hret
assert_equal({3=>4}, h)
end
assert 'Hash#reject' do
h = {1=>2,3=>4,5=>6}
hret = h.reject.with_index {|a,b| a[1] == 4}
hret = h.reject.with_index {|a,_b| a[1] == 4}
assert_equal({1=>2,5=>6}, hret)
assert_equal({1=>2,3=>4,5=>6}, h)
end
assert 'Hash#reject!' do
h = {1=>2,3=>4,5=>6}
hret = h.reject!.with_index {|a,b| a[1] == 4}
hret = h.reject!.with_index {|a,_b| a[1] == 4}
assert_equal h, hret
assert_equal({1=>2,5=>6}, h)
end
+110 -56
View File
@@ -12,34 +12,38 @@ 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 mrb_context *c = mrb->c;
struct REnv *e = c->ci[-1].proc->env;
struct RProc *proc;
struct RProc *proc = mrb->c->ci[-1].proc;
if (level == 0) {
proc = c->ci[-1].proc;
if (MRB_PROC_CFUNC_P(proc)) {
return NULL;
}
return proc->body.irep;
while (level--) {
if (!proc) return NULL;
proc = proc->upper;
}
while (--level) {
e = (struct REnv*)e->c;
if (!e) return NULL;
}
if (!e) return NULL;
if (!MRB_ENV_STACK_SHARED_P(e)) return NULL;
c = e->cxt.c;
proc = c->cibase[e->cioff].proc;
if (!proc || MRB_PROC_CFUNC_P(proc)) {
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 inline mrb_code
search_variable(mrb_state *mrb, mrb_sym vsym, int bnest)
{
@@ -48,7 +52,7 @@ search_variable(mrb_state *mrb, mrb_sym vsym, int bnest)
int pos;
for (level = 0; (virep = get_closure_irep(mrb, level)); level++) {
if (!virep || virep->lv == NULL) {
if (virep->lv == NULL) {
continue;
}
for (pos = 0; pos < virep->nlocals - 1; pos++) {
@@ -61,6 +65,20 @@ search_variable(mrb_state *mrb, mrb_sym vsym, int bnest)
return 0;
}
static int
irep_argc(mrb_irep *irep)
{
mrb_code c;
c = irep->iseq[0];
if (GET_OPCODE(c) == OP_ENTER) {
mrb_aspec ax = GETARG_Ax(c);
/* 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)
{
@@ -71,32 +89,24 @@ potential_upvar_p(struct mrb_locals *lv, uint16_t v, int argc, uint16_t nlocals)
}
static void
patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest)
patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
{
size_t i;
int i;
mrb_code c;
int argc = 0;
int argc = irep_argc(irep);
for (i = 0; i < irep->ilen; i++) {
c = irep->iseq[i];
switch(GET_OPCODE(c)){
case OP_ENTER:
{
mrb_aspec ax = GETARG_Ax(c);
/* extra 1 means a slot for block */
argc = MRB_ASPEC_REQ(ax)+MRB_ASPEC_OPT(ax)+MRB_ASPEC_REST(ax)+MRB_ASPEC_POST(ax)+1;
}
break;
case OP_EPUSH:
patch_irep(mrb, irep->reps[GETARG_Bx(c)], bnest + 1);
patch_irep(mrb, irep->reps[GETARG_Bx(c)], bnest + 1, top);
break;
case OP_LAMBDA:
{
int arg_c = GETARG_c(c);
if (arg_c & OP_L_CAPTURE) {
patch_irep(mrb, irep->reps[GETARG_b(c)], bnest + 1);
patch_irep(mrb, irep->reps[GETARG_b(c)], bnest + 1, top);
}
}
break;
@@ -105,7 +115,7 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest)
if (GETARG_C(c) != 0) {
break;
}
{
else {
mrb_code arg = search_variable(mrb, irep->syms[GETARG_B(c)], bnest);
if (arg != 0) {
/* must replace */
@@ -133,6 +143,34 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest)
}
break;
case OP_GETUPVAR:
{
int lev = GETARG_C(c)+1;
mrb_irep *tmp = search_irep(top, bnest, lev, irep);
if (potential_upvar_p(tmp->lv, GETARG_B(c), irep_argc(tmp), tmp->nlocals)) {
mrb_code arg = search_variable(mrb, tmp->lv[GETARG_B(c)-1].name, bnest);
if (arg != 0) {
/* must replace */
irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
}
}
}
break;
case OP_SETUPVAR:
{
int lev = GETARG_C(c)+1;
mrb_irep *tmp = search_irep(top, bnest, lev, irep);
if (potential_upvar_p(tmp->lv, GETARG_B(c), irep_argc(tmp), tmp->nlocals)) {
mrb_code arg = search_variable(mrb, tmp->lv[GETARG_B(c)-1].name, bnest);
if (arg != 0) {
/* must replace */
irep->iseq[i] = MKOPCODE(OP_SETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
}
}
}
break;
case OP_STOP:
if (mrb->c->ci->acc >= 0) {
irep->iseq[i] = MKOP_AB(OP_RETURN, irep->nlocals, OP_R_NORMAL);
@@ -145,20 +183,22 @@ patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest)
void mrb_codedump_all(mrb_state*, struct RProc*);
static struct RProc*
create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, const char *file, mrb_int line)
create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding, const char *file, mrb_int line)
{
mrbc_context *cxt;
struct mrb_parser_state *p;
struct RProc *proc;
struct REnv *e;
struct mrb_context *c = mrb->c;
mrb_callinfo *ci = &mrb->c->ci[-1]; /* callinfo of eval caller */
struct RClass *target_class = NULL;
int bidx;
if (!mrb_nil_p(binding)) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "Binding of eval must be nil.");
}
cxt = mrbc_context_new(mrb);
cxt->lineno = line;
cxt->lineno = (short)line;
mrbc_filename(mrb, cxt, file ? file : "(eval)");
cxt->capture_errors = TRUE;
@@ -198,20 +238,31 @@ create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, con
mrbc_context_free(mrb, cxt);
mrb_raise(mrb, E_SCRIPT_ERROR, "codegen error");
}
if (c->ci[-1].proc->target_class) {
proc->target_class = c->ci[-1].proc->target_class;
target_class = MRB_PROC_TARGET_CLASS(ci->proc);
if (!MRB_PROC_CFUNC_P(ci->proc)) {
if (ci->env) {
e = ci->env;
}
else {
e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV,
(struct RClass*)target_class);
e->mid = ci->mid;
e->stack = ci[1].stackent;
e->cxt = mrb->c;
MRB_ENV_SET_STACK_LEN(e, ci->proc->body.irep->nlocals);
bidx = ci->argc;
if (ci->argc < 0) bidx = 2;
else bidx += 1;
MRB_ENV_SET_BIDX(e, bidx);
}
proc->e.env = e;
proc->flags |= MRB_PROC_ENVSET;
mrb_field_write_barrier(mrb, (struct RBasic*)proc, (struct RBasic*)e);
}
e = c->ci[-1].proc->env;
if (!e) e = c->ci[-1].env;
e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)e);
e->cxt.c = c;
e->cioff = c->ci - c->cibase;
e->stack = c->ci->stackent;
MRB_SET_ENV_STACK_LEN(e, c->ci->proc->body.irep->nlocals);
c->ci->target_class = proc->target_class;
c->ci->env = 0;
proc->env = e;
patch_irep(mrb, proc->body.irep, 0);
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);
mrbc_context_free(mrb, cxt);
@@ -222,13 +273,17 @@ create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, con
static mrb_value
exec_irep(mrb_state *mrb, mrb_value self, struct RProc *proc)
{
/* no argument passed from eval() */
mrb->c->ci->argc = 0;
if (mrb->c->ci->acc < 0) {
mrb_value ret = mrb_top_run(mrb, proc, mrb->c->stack[0], 0);
mrb_value ret = mrb_top_run(mrb, proc, self, 0);
if (mrb->exc) {
mrb_exc_raise(mrb, mrb_obj_value(mrb->exc));
}
return ret;
}
/* clear block */
mrb->c->stack[1] = mrb_nil_value();
return mrb_exec_irep(mrb, self, proc);
}
@@ -255,7 +310,7 @@ f_instance_eval(mrb_state *mrb, mrb_value self)
mrb_value b;
mrb_int argc; mrb_value *argv;
mrb_get_args(mrb, "*&", &argv, &argc, &b);
mrb_get_args(mrb, "*!&", &argv, &argc, &b);
if (mrb_nil_p(b)) {
char *s;
@@ -268,8 +323,7 @@ f_instance_eval(mrb_state *mrb, mrb_value self)
mrb_get_args(mrb, "s|zi", &s, &len, &file, &line);
cv = mrb_singleton_class(mrb, self);
proc = create_proc_from_string(mrb, s, len, mrb_nil_value(), file, line);
proc->target_class = mrb_class_ptr(cv);
mrb->c->ci->env = NULL;
MRB_PROC_SET_TARGET_CLASS(proc, mrb_class_ptr(cv));
mrb_assert(!MRB_PROC_CFUNC_P(proc));
return exec_irep(mrb, self, proc);
}
+1 -1
View File
@@ -7,7 +7,7 @@ f_exit(mrb_state *mrb, mrb_value self)
mrb_int i = EXIT_SUCCESS;
mrb_get_args(mrb, "|i", &i);
exit(i);
exit((int)i);
/* not reached */
return mrb_nil_value();
}
+7 -6
View File
@@ -123,8 +123,9 @@ fiber_init(mrb_state *mrb, mrb_value self)
/* adjust return callinfo */
ci = c->ci;
ci->target_class = p->target_class;
ci->target_class = MRB_PROC_TARGET_CLASS(p);
ci->proc = p;
mrb_field_write_barrier(mrb, (struct RBasic*)mrb_obj_ptr(self), (struct RBasic*)p);
ci->pc = p->body.irep->iseq;
ci->nregs = p->body.irep->nregs;
ci[1] = ci[0];
@@ -211,8 +212,8 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr
while (b<e) {
*b++ = *a++;
}
c->cibase->argc = len;
value = c->stack[0] = c->ci->proc->env->stack[0];
c->cibase->argc = (int)len;
value = c->stack[0] = MRB_PROC_ENV(c->ci->proc)->stack[0];
}
else {
value = fiber_result(mrb, a, len);
@@ -252,7 +253,7 @@ fiber_resume(mrb_state *mrb, mrb_value self)
mrb_int len;
mrb_bool vmexec = FALSE;
mrb_get_args(mrb, "*", &a, &len);
mrb_get_args(mrb, "*!", &a, &len);
if (mrb->c->ci->acc < 0) {
vmexec = TRUE;
}
@@ -312,7 +313,7 @@ fiber_transfer(mrb_state *mrb, mrb_value self)
mrb_int len;
fiber_check_cfunc(mrb, mrb->c);
mrb_get_args(mrb, "*", &a, &len);
mrb_get_args(mrb, "*!", &a, &len);
if (c == mrb->root_c) {
mrb->c->status = MRB_FIBER_TRANSFERRED;
@@ -370,7 +371,7 @@ fiber_yield(mrb_state *mrb, mrb_value self)
mrb_value *a;
mrb_int len;
mrb_get_args(mrb, "*", &a, &len);
mrb_get_args(mrb, "*!", &a, &len);
return mrb_fiber_yield(mrb, len, a);
}
+3 -2
View File
@@ -2,6 +2,7 @@ MRuby::Gem::Specification.new('mruby-hash-ext') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'Hash class extension'
spec.add_dependency 'mruby-enum-ext', :core => 'mruby-enum-ext'
spec.add_dependency 'mruby-array-ext', :core => 'mruby-array-ext'
spec.add_dependency 'mruby-enum-ext', core: 'mruby-enum-ext'
spec.add_dependency 'mruby-array-ext', core: 'mruby-array-ext'
spec.add_test_dependency 'mruby-enumerator', core: 'mruby-enumerator'
end
+120 -3
View File
@@ -114,6 +114,22 @@ class Hash
alias update merge!
##
# call-seq:
# hsh.compact -> new_hsh
#
# Returns a new hash with the nil values/key pairs removed
#
# h = { a: 1, b: false, c: nil }
# h.compact #=> { a: 1, b: false }
# h #=> { a: 1, b: false, c: nil }
#
def compact
result = self.dup
result.compact!
result
end
##
# call-seq:
# hsh.fetch(key [, default] ) -> obj
@@ -149,7 +165,7 @@ class Hash
elsif none != NONE
none
else
raise KeyError, "Key not found: #{key}"
raise KeyError, "Key not found: #{key.inspect}"
end
else
self[key]
@@ -171,7 +187,7 @@ class Hash
#
def delete_if(&block)
return to_enum :delete_if unless block_given?
return to_enum :delete_if unless block
self.each do |k, v|
self.delete(k) if block.call(k, v)
@@ -228,7 +244,7 @@ class Hash
#
def keep_if(&block)
return to_enum :keep_if unless block_given?
return to_enum :keep_if unless block
keys = []
self.each do |k, v|
@@ -382,4 +398,105 @@ class Hash
n
end
end
##
# call-seq:
# hsh.transform_keys {|key| block } -> new_hash
# hsh.transform_keys -> an_enumerator
#
# Returns a new hash, with the keys computed from running the block
# once for each key in the hash, and the values unchanged.
#
# If no block is given, an enumerator is returned instead.
#
def transform_keys(&block)
return to_enum :transform_keys unless block
hash = {}
self.keys.each do |k|
new_key = block.call(k)
hash[new_key] = self[k]
end
hash
end
##
# call-seq:
# hsh.transform_keys! {|key| block } -> hsh
# hsh.transform_keys! -> an_enumerator
#
# Invokes the given block once for each key in <i>hsh</i>, replacing it
# with the new key returned by the block, and then returns <i>hsh</i>.
#
# If no block is given, an enumerator is returned instead.
#
def transform_keys!(&block)
return to_enum :transform_keys! unless block
self.keys.each do |k|
value = self[k]
new_key = block.call(k)
self.__delete(k)
self[new_key] = value
end
self
end
##
# call-seq:
# hsh.transform_values {|value| block } -> new_hash
# hsh.transform_values -> an_enumerator
#
# Returns a new hash with the results of running the block once for
# every value.
# This method does not change the keys.
#
# If no block is given, an enumerator is returned instead.
#
def transform_values(&b)
return to_enum :transform_values unless block_given?
hash = {}
self.keys.each do |k|
hash[k] = yield(self[k])
end
hash
end
##
# call-seq:
# hsh.transform_values! {|key| block } -> hsh
# hsh.transform_values! -> an_enumerator
#
# Invokes the given block once for each value in the hash, replacing
# with the new value returned by the block, and then returns <i>hsh</i>.
#
# If no block is given, an enumerator is returned instead.
#
def transform_values!(&b)
return to_enum :transform_values! unless block_given?
self.keys.each do |k|
self[k] = yield(self[k])
end
self
end
def to_proc
->x{self[x]}
end
##
# call-seq:
# hsh.fetch_values(key, ...) -> array
# hsh.fetch_values(key, ...) { |key| block } -> array
#
# Returns an array containing the values associated with the given keys
# but also raises <code>KeyError</code> when one of keys can't be found.
# Also see <code>Hash#values_at</code> and <code>Hash#fetch</code>.
#
# h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
#
# h.fetch_values("cow", "cat") #=> ["bovine", "feline"]
# h.fetch_values("cow", "bird") # raises KeyError
# h.fetch_values("cow", "bird") { |k| k.upcase } #=> ["bovine", "BIRD"]
#
def fetch_values(*keys, &block)
keys.map do |k|
self.fetch(k, &block)
end
end
end
+77
View File
@@ -36,6 +36,81 @@ hash_values_at(mrb_state *mrb, mrb_value hash)
return result;
}
/*
* call-seq:
* hsh.compact! -> hsh
*
* Removes all nil values from the hash. Returns the hash.
*
* h = { a: 1, b: false, c: nil }
* h.compact! #=> { a: 1, b: false }
*/
static mrb_value
hash_compact_bang(mrb_state *mrb, mrb_value hash)
{
khiter_t k;
khash_t(ht) *h = RHASH_TBL(hash);
mrb_int n = -1;
if (!h) return mrb_nil_value();
for (k = kh_begin(h); k != kh_end(h); k++) {
if (kh_exist(h, k)) {
mrb_value val = kh_value(h, k).v;
khiter_t k2;
if (mrb_nil_p(val)) {
kh_del(ht, mrb, h, k);
n = kh_value(h, k).n;
for (k2 = kh_begin(h); k2 != kh_end(h); k2++) {
if (!kh_exist(h, k2)) continue;
if (kh_value(h, k2).n > n) kh_value(h, k2).n--;
}
}
}
}
if (n < 0) return mrb_nil_value();
return hash;
}
/*
* call-seq:
* hsh.slice(*keys) -> a_hash
*
* Returns a hash containing only the given keys and their values.
*
* h = { a: 100, b: 200, c: 300 }
* h.slice(:a) #=> {:a=>100}
* h.slice(:b, :c, :d) #=> {:b=>200, :c=>300}
*/
static mrb_value
hash_slice(mrb_state *mrb, mrb_value hash)
{
khash_t(ht) *h = RHASH_TBL(hash);
mrb_value *argv, result;
mrb_int argc, i;
khiter_t k;
int ai;
mrb_get_args(mrb, "*", &argv, &argc);
if (argc == 0 || h == NULL) {
return mrb_hash_new_capa(mrb, argc);
}
result = mrb_hash_new_capa(mrb, argc);
ai = mrb_gc_arena_save(mrb);
for (i = 0; i < argc; i++) {
mrb_value key = argv[i];
k = kh_get(ht, mrb, h, key);
if (k != kh_end(h)) {
mrb_value val = kh_value(h, k).v;
mrb_hash_set(mrb, result, key, val);
}
mrb_gc_arena_restore(mrb, ai);
}
return result;
}
void
mrb_mruby_hash_ext_gem_init(mrb_state *mrb)
{
@@ -43,6 +118,8 @@ mrb_mruby_hash_ext_gem_init(mrb_state *mrb)
h = mrb->hash_class;
mrb_define_method(mrb, h, "values_at", hash_values_at, MRB_ARGS_ANY());
mrb_define_method(mrb, h, "compact!", hash_compact_bang, MRB_ARGS_NONE());
mrb_define_method(mrb, h, "slice", hash_slice, MRB_ARGS_ANY());
}
void
+44
View File
@@ -82,6 +82,20 @@ assert('Hash#values_at') do
assert_equal keys, h.values_at(*keys)
end
assert('Hash#compact') do
h = { "cat" => "feline", "dog" => nil, "cow" => false }
assert_equal({ "cat" => "feline", "cow" => false }, h.compact)
assert_equal({ "cat" => "feline", "dog" => nil, "cow" => false }, h)
end
assert('Hash#compact!') do
h = { "cat" => "feline", "dog" => nil, "cow" => false }
h.compact!
assert_equal({ "cat" => "feline", "cow" => false }, h)
end
assert('Hash#fetch') do
h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
assert_equal "feline", h.fetch("cat")
@@ -254,3 +268,33 @@ assert("Hash#dig") do
assert_equal(1, h.dig(:a, :b, :c))
assert_nil(h.dig(:d))
end
assert("Hash#transform_keys") do
h = {"1" => 100, "2" => 200}
assert_equal({"1!" => 100, "2!" => 200},
h.transform_keys{|k| k+"!"})
assert_equal({1 => 100, 2 => 200},
h.transform_keys{|k|k.to_i})
assert_equal({"1.0" => 100, "2.1" => 200},
h.transform_keys.with_index{|k, i| "#{k}.#{i}"})
assert_equal(h, h.transform_keys!{|k|k.to_i})
assert_equal(h, {1 => 100, 2 => 200})
end
assert("Hash#transform_values") do
h = {a: 1, b: 2, c: 3}
assert_equal({a: 2, b: 5, c: 10},
h.transform_values{|v| v * v + 1})
assert_equal({a: "1", b: "2", c: "3"},
h.transform_values{|v|v.to_s})
assert_equal({a: "1.0", b: "2.1", c: "3.2"},
h.transform_values.with_index{|v, i| "#{v}.#{i}"})
assert_equal(h, h.transform_values!{|v|v.to_s})
assert_equal({a: "1", b: "2", c: "3"}, h)
end
assert("Hash#slice") do
h = { a: 100, b: 200, c: 300 }
assert_equal({:a=>100}, h.slice(:a))
assert_equal({:b=>200, :c=>300}, h.slice(:b, :c, :d))
end
+1
View File
@@ -0,0 +1 @@
/tmp
+2
View File
@@ -0,0 +1,2 @@
script:
- "ruby run_test.rb all test"
+193
View File
@@ -0,0 +1,193 @@
mruby-io
========
[![Build Status](https://travis-ci.org/iij/mruby-io.svg?branch=master)](https://travis-ci.org/iij/mruby-io)
`IO` and `File` classes for mruby
## Installation
Add the line below to your `build_config.rb`:
```
conf.gem :github => 'iij/mruby-io'
```
## Implemented methods
### IO
- http://doc.ruby-lang.org/ja/1.9.3/class/IO.html
| method | mruby-io | memo |
| ------------------------- | -------- | ---- |
| IO.binread | | |
| IO.binwrite | | |
| IO.copy_stream | | |
| IO.new, IO.for_fd, IO.open | o | |
| IO.foreach | | |
| IO.pipe | o | |
| IO.popen | o | |
| IO.read | o | |
| IO.readlines | | |
| IO.select | o | |
| IO.sysopen | o | |
| IO.try_convert | | |
| IO.write | | |
| IO#<< | | |
| IO#advise | | |
| IO#autoclose= | | |
| IO#autoclose? | | |
| IO#binmode | | |
| IO#binmode? | | |
| IO#bytes | | obsolete |
| IO#chars | | obsolete |
| IO#clone, IO#dup | o | |
| IO#close | o | |
| IO#close_on_exec= | o | |
| IO#close_on_exec? | o | |
| IO#close_read | | |
| IO#close_write | | |
| IO#closed? | o | |
| IO#codepoints | | obsolete |
| IO#each_byte | o | |
| IO#each_char | o | |
| IO#each_codepoint | | |
| IO#each_line | o | |
| IO#eof, IO#eof? | o | |
| IO#external_encoding | | |
| IO#fcntl | | |
| IO#fdatasync | | |
| IO#fileno, IO#to_i | o | |
| IO#flush | o | |
| IO#fsync | | |
| IO#getbyte | | |
| IO#getc | o | |
| IO#gets | o | |
| IO#internal_encoding | | |
| IO#ioctl | | |
| IO#isatty, IO#tty? | o | |
| IO#lineno | | |
| IO#lineno= | | |
| IO#lines | | obsolete |
| IO#pid | o | |
| IO#pos, IO#tell | o | |
| IO#pos= | o | |
| IO#print | o | |
| IO#printf | o | |
| IO#putc | | |
| IO#puts | o | |
| IO#read | o | |
| IO#read_nonblock | | |
| IO#readbyte | | |
| IO#readchar | o | |
| IO#readline | o | |
| IO#readlines | o | |
| IO#readpartial | | |
| IO#reopen | | |
| IO#rewind | | |
| IO#seek | o | |
| IO#set_encoding | | |
| IO#stat | | |
| IO#sync | o | |
| IO#sync= | o | |
| IO#sysread | o | |
| IO#sysseek | o | |
| IO#syswrite | o | |
| IO#to_io | | |
| IO#ungetbyte | | |
| IO#ungetc | o | |
| IO#write | o | |
| IO#write_nonblock | | |
### File
- http://doc.ruby-lang.org/ja/1.9.3/class/File.html
| method | mruby-io | memo |
| --------------------------- | -------- | ---- |
| File.absolute_path | | |
| File.atime | | |
| File.basename | o | |
| File.blockdev? | | FileTest |
| File.chardev? | | FileTest |
| File.chmod | o | |
| File.chown | | |
| File.ctime | | |
| File.delete, File.unlink | o | |
| File.directory? | o | FileTest |
| File.dirname | o | |
| File.executable? | | FileTest |
| File.executable_real? | | FileTest |
| File.exist?, exists? | o | FileTest |
| File.expand_path | o | |
| File.extname | o | |
| File.file? | o | FileTest |
| File.fnmatch, File.fnmatch? | | |
| File.ftype | | |
| File.grpowned? | | FileTest |
| File.identical? | | FileTest |
| File.join | o | |
| File.lchmod | | |
| File.lchown | | |
| File.link | | |
| File.lstat | | |
| File.mtime | | |
| File.new, File.open | o | |
| File.owned? | | FileTest |
| File.path | | |
| File.pipe? | o | FileTest |
| File.readable? | | FileTest |
| File.readable_real? | | FileTest |
| File.readlink | o | |
| File.realdirpath | | |
| File.realpath | o | |
| File.rename | o | |
| File.setgid? | | FileTest |
| File.setuid? | | FileTest |
| File.size | o | |
| File.size? | o | FileTest |
| File.socket? | o | FileTest |
| File.split | | |
| File.stat | | |
| File.sticky? | | FileTest |
| File.symlink | | |
| File.symlink? | o | FileTest |
| File.truncate | | |
| File.umask | o | |
| File.utime | | |
| File.world_readable? | | |
| File.world_writable? | | |
| File.writable? | | FileTest |
| File.writable_real? | | FileTest |
| File.zero? | o | FileTest |
| File#atime | | |
| File#chmod | | |
| File#chown | | |
| File#ctime | | |
| File#flock | o | |
| File#lstat | | |
| File#mtime | | |
| File#path, File#to_path | o | |
| File#size | | |
| File#truncate | | |
## License
Copyright (c) 2013 Internet Initiative Japan Inc.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
+38
View File
@@ -0,0 +1,38 @@
/*
** io.h - IO class
*/
#ifndef MRUBY_IO_H
#define MRUBY_IO_H
#if defined(__cplusplus)
extern "C" {
#endif
struct mrb_io {
int fd; /* file descriptor, or -1 */
int fd2; /* file descriptor to write if it's different from fd, or -1 */
int pid; /* child's pid (for pipes) */
unsigned int readable:1,
writable:1,
sync:1,
is_socket:1;
};
#define FMODE_READABLE 0x00000001
#define FMODE_WRITABLE 0x00000002
#define FMODE_READWRITE (FMODE_READABLE|FMODE_WRITABLE)
#define FMODE_BINMODE 0x00000004
#define FMODE_APPEND 0x00000040
#define FMODE_CREATE 0x00000080
#define FMODE_TRUNC 0x00000800
#define E_IO_ERROR (mrb_class_get(mrb, "IOError"))
#define E_EOF_ERROR (mrb_class_get(mrb, "EOFError"))
mrb_value mrb_io_fileno(mrb_state *mrb, mrb_value io);
#if defined(__cplusplus)
} /* extern "C" { */
#endif
#endif /* MRUBY_IO_H */
+17
View File
@@ -0,0 +1,17 @@
MRuby::Gem::Specification.new('mruby-io') do |spec|
spec.license = 'MIT'
spec.authors = 'Internet Initiative Japan Inc.'
spec.summary = 'IO and File class'
spec.cc.include_paths << "#{build.root}/src"
case RUBY_PLATFORM
when /mingw|mswin/
spec.linker.libraries += ['Ws2_32']
#spec.cc.include_paths += ["C:/Windows/system/include"]
spec.linker.library_paths += ["C:/Windows/system"]
end
if build.kind_of?(MRuby::CrossBuild) && %w(x86_64-w64-mingw32 i686-w64-mingw32).include?(build.host_target)
spec.linker.libraries += ['ws2_32']
end
end
+208
View File
@@ -0,0 +1,208 @@
class File < IO
class FileError < Exception; end
class NoFileError < FileError; end
class UnableToStat < FileError; end
class PermissionError < FileError; end
attr_accessor :path
def initialize(fd_or_path, mode = "r", perm = 0666)
if fd_or_path.kind_of? Fixnum
super(fd_or_path, mode)
else
@path = fd_or_path
fd = IO.sysopen(@path, mode, perm)
super(fd, mode)
end
end
def self.join(*names)
return "" if names.empty?
names.map! do |name|
case name
when String
name
when Array
if names == name
raise ArgumentError, "recursive array"
end
join(*name)
else
raise TypeError, "no implicit conversion of #{name.class} into String"
end
end
return names[0] if names.size == 1
if names[0][-1] == File::SEPARATOR
s = names[0][0..-2]
else
s = names[0].dup
end
(1..names.size-2).each { |i|
t = names[i]
if t[0] == File::SEPARATOR and t[-1] == File::SEPARATOR
t = t[1..-2]
elsif t[0] == File::SEPARATOR
t = t[1..-1]
elsif t[-1] == File::SEPARATOR
t = t[0..-2]
end
s += File::SEPARATOR + t if t != ""
}
if names[-1][0] == File::SEPARATOR
s += File::SEPARATOR + names[-1][1..-1]
else
s += File::SEPARATOR + names[-1]
end
s
end
def self.expand_path(path, default_dir = '.')
def concat_path(path, base_path)
if path[0] == "/" || path[1] == ':' # Windows root!
expanded_path = path
elsif path[0] == "~"
if (path[1] == "/" || path[1] == nil)
dir = path[1, path.size]
home_dir = _gethome
unless home_dir
raise ArgumentError, "couldn't find HOME environment -- expanding '~'"
end
expanded_path = home_dir
expanded_path += dir if dir
expanded_path += "/"
else
splitted_path = path.split("/")
user = splitted_path[0][1, splitted_path[0].size]
dir = "/" + splitted_path[1, splitted_path.size].join("/")
home_dir = _gethome(user)
unless home_dir
raise ArgumentError, "user #{user} doesn't exist"
end
expanded_path = home_dir
expanded_path += dir if dir
expanded_path += "/"
end
else
expanded_path = concat_path(base_path, _getwd)
expanded_path += "/" + path
end
expanded_path
end
expanded_path = concat_path(path, default_dir)
drive_prefix = ""
if File::ALT_SEPARATOR && expanded_path.size > 2 &&
("A".."Z").include?(expanded_path[0].upcase) && expanded_path[1] == ":"
drive_prefix = expanded_path[0, 2]
expanded_path = expanded_path[2, expanded_path.size]
end
expand_path_array = []
if File::ALT_SEPARATOR && expanded_path.include?(File::ALT_SEPARATOR)
expanded_path.gsub!(File::ALT_SEPARATOR, '/')
end
while expanded_path.include?('//')
expanded_path = expanded_path.gsub('//', '/')
end
if expanded_path != "/"
expanded_path.split('/').each do |path_token|
if path_token == '..'
if expand_path_array.size > 1
expand_path_array.pop
end
elsif path_token == '.'
# nothing to do.
else
expand_path_array << path_token
end
end
expanded_path = expand_path_array.join("/")
if expanded_path.empty?
expanded_path = '/'
end
end
if drive_prefix.empty?
expanded_path
else
drive_prefix + expanded_path.gsub("/", File::ALT_SEPARATOR)
end
end
def self.foreach(file)
if block_given?
self.open(file) do |f|
f.each {|l| yield l}
end
else
return self.new(file)
end
end
def self.directory?(file)
FileTest.directory?(file)
end
def self.exist?(file)
FileTest.exist?(file)
end
def self.exists?(file)
FileTest.exists?(file)
end
def self.file?(file)
FileTest.file?(file)
end
def self.pipe?(file)
FileTest.pipe?(file)
end
def self.size(file)
FileTest.size(file)
end
def self.size?(file)
FileTest.size?(file)
end
def self.socket?(file)
FileTest.socket?(file)
end
def self.symlink?(file)
FileTest.symlink?(file)
end
def self.zero?(file)
FileTest.zero?(file)
end
def self.extname(filename)
fname = self.basename(filename)
return '' if fname[0] == '.' || fname.index('.').nil?
ext = fname.split('.').last
ext.empty? ? '' : ".#{ext}"
end
def self.path(filename)
if filename.kind_of?(String)
filename
elsif filename.respond_to?(:to_path)
filename.to_path
else
raise TypeError, "no implicit conversion of #{filename.class} into String"
end
end
end
+29
View File
@@ -0,0 +1,29 @@
class File
module Constants
RDONLY = 0
WRONLY = 1
RDWR = 2
NONBLOCK = 4
APPEND = 8
BINARY = 0
SYNC = 128
NOFOLLOW = 256
CREAT = 512
TRUNC = 1024
EXCL = 2048
NOCTTY = 131072
DSYNC = 4194304
FNM_SYSCASE = 0
FNM_NOESCAPE = 1
FNM_PATHNAME = 2
FNM_DOTMATCH = 4
FNM_CASEFOLD = 8
end
end
class File
include File::Constants
end
+387
View File
@@ -0,0 +1,387 @@
##
# IO
class IOError < StandardError; end
class EOFError < IOError; end
class IO
SEEK_SET = 0
SEEK_CUR = 1
SEEK_END = 2
BUF_SIZE = 4096
def self.open(*args, &block)
io = self.new(*args)
return io unless block
begin
yield io
ensure
begin
io.close unless io.closed?
rescue StandardError
end
end
end
def self.popen(command, mode = 'r', opts={}, &block)
if !self.respond_to?(:_popen)
raise NotImplementedError, "popen is not supported on this platform"
end
io = self._popen(command, mode, opts)
return io unless block
begin
yield io
ensure
begin
io.close unless io.closed?
rescue IOError
# nothing
end
end
end
def self.pipe(&block)
if !self.respond_to?(:_pipe)
raise NotImplementedError, "pipe is not supported on this platform"
end
if block
begin
r, w = IO._pipe
yield r, w
ensure
r.close unless r.closed?
w.close unless w.closed?
end
else
IO._pipe
end
end
def self.read(path, length=nil, offset=nil, opt=nil)
if not opt.nil? # 4 arguments
offset ||= 0
elsif not offset.nil? # 3 arguments
if offset.is_a? Hash
opt = offset
offset = 0
else
opt = {}
end
elsif not length.nil? # 2 arguments
if length.is_a? Hash
opt = length
offset = 0
length = nil
else
offset = 0
opt = {}
end
else # only 1 argument
opt = {}
offset = 0
length = nil
end
str = ""
fd = -1
io = nil
begin
if path[0] == "|"
io = IO.popen(path[1..-1], (opt[:mode] || "r"))
else
fd = IO.sysopen(path)
io = IO.open(fd, opt[:mode] || "r")
end
io.seek(offset) if offset > 0
str = io.read(length)
ensure
if io
io.close
elsif fd != -1
IO._sysclose(fd)
end
end
str
end
def flush
# mruby-io always writes immediately (no output buffer).
raise IOError, "closed stream" if self.closed?
self
end
def hash
# We must define IO#hash here because IO includes Enumerable and
# Enumerable#hash will call IO#read...
self.__id__
end
def write(string)
str = string.is_a?(String) ? string : string.to_s
return str.size unless str.size > 0
if 0 < @buf.length
# reset real pos ignore buf
seek(pos, SEEK_SET)
end
len = syswrite(str)
len
end
def <<(str)
write(str)
self
end
def eof?
_check_readable
begin
buf = _read_buf
return buf.size == 0
rescue EOFError
return true
end
end
alias_method :eof, :eof?
def pos
raise IOError if closed?
sysseek(0, SEEK_CUR) - @buf.length
end
alias_method :tell, :pos
def pos=(i)
seek(i, SEEK_SET)
end
def rewind
seek(0, SEEK_SET)
end
def seek(i, whence = SEEK_SET)
raise IOError if closed?
sysseek(i, whence)
@buf = ''
0
end
def _read_buf
return @buf if @buf && @buf.size > 0
@buf = sysread(BUF_SIZE)
end
def ungetc(substr)
raise TypeError.new "expect String, got #{substr.class}" unless substr.is_a?(String)
if @buf.empty?
@buf = substr.dup
else
@buf = substr + @buf
end
nil
end
def read(length = nil, outbuf = "")
unless length.nil?
unless length.is_a? Fixnum
raise TypeError.new "can't convert #{length.class} into Integer"
end
if length < 0
raise ArgumentError.new "negative length: #{length} given"
end
if length == 0
return "" # easy case
end
end
array = []
while 1
begin
_read_buf
rescue EOFError
array = nil if array.empty? and (not length.nil?) and length != 0
break
end
if length
consume = (length <= @buf.size) ? length : @buf.size
array.push @buf[0, consume]
@buf = @buf[consume, @buf.size - consume]
length -= consume
break if length == 0
else
array.push @buf
@buf = ''
end
end
if array.nil?
outbuf.replace("")
nil
else
outbuf.replace(array.join)
end
end
def readline(arg = $/, limit = nil)
case arg
when String
rs = arg
when Fixnum
rs = $/
limit = arg
else
raise ArgumentError
end
if rs.nil?
return read
end
if rs == ""
rs = $/ + $/
end
array = []
while 1
begin
_read_buf
rescue EOFError
array = nil if array.empty?
break
end
if limit && limit <= @buf.size
array.push @buf[0, limit]
@buf = @buf[limit, @buf.size - limit]
break
elsif idx = @buf.index(rs)
len = idx + rs.size
array.push @buf[0, len]
@buf = @buf[len, @buf.size - len]
break
else
array.push @buf
@buf = ''
end
end
raise EOFError.new "end of file reached" if array.nil?
array.join
end
def gets(*args)
begin
readline(*args)
rescue EOFError
nil
end
end
def readchar
_read_buf
c = @buf[0]
@buf = @buf[1, @buf.size]
c
end
def getc
begin
readchar
rescue EOFError
nil
end
end
# 15.2.20.5.3
def each(&block)
while line = self.gets
block.call(line)
end
self
end
# 15.2.20.5.4
def each_byte(&block)
while char = self.getc
block.call(char)
end
self
end
# 15.2.20.5.5
alias each_line each
alias each_char each_byte
def readlines
ary = []
while (line = gets)
ary << line
end
ary
end
def puts(*args)
i = 0
len = args.size
while i < len
s = args[i].to_s
write s
write "\n" if (s[-1] != "\n")
i += 1
end
write "\n" if len == 0
nil
end
def print(*args)
i = 0
len = args.size
while i < len
write args[i].to_s
i += 1
end
end
def printf(*args)
write sprintf(*args)
nil
end
alias_method :to_i, :fileno
alias_method :tty?, :isatty
end
STDIN = IO.open(0, "r")
STDOUT = IO.open(1, "w")
STDERR = IO.open(2, "w")
$stdin = STDIN
$stdout = STDOUT
$stderr = STDERR
module Kernel
def print(*args)
$stdout.print(*args)
end
def puts(*args)
$stdout.puts(*args)
end
def printf(*args)
$stdout.printf(*args)
end
def gets(*args)
$stdin.gets(*args)
end
def getc(*args)
$stdin.getc(*args)
end
end
+15
View File
@@ -0,0 +1,15 @@
module Kernel
def `(cmd)
IO.popen(cmd) { |io| io.read }
end
def open(file, *rest, &block)
raise ArgumentError unless file.is_a?(String)
if file[0] == "|"
IO.popen(file[1..-1], *rest, &block)
else
File.open(file, *rest, &block)
end
end
end
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env ruby
#
# mrbgems test runner
#
if __FILE__ == $0
repository, dir = 'https://github.com/mruby/mruby.git', 'tmp/mruby'
build_args = ARGV
Dir.mkdir 'tmp' unless File.exist?('tmp')
unless File.exist?(dir)
system "git clone #{repository} #{dir}"
end
exit system(%Q[cd #{dir}; MRUBY_CONFIG=#{File.expand_path __FILE__} ruby minirake #{build_args.join(' ')}])
end
MRuby::Build.new do |conf|
toolchain :gcc
conf.gembox 'default'
conf.gem :git => 'https://github.com/iij/mruby-env.git'
conf.enable_test
conf.gem File.expand_path(File.dirname(__FILE__))
end
+489
View File
@@ -0,0 +1,489 @@
/*
** file.c - File class
*/
#include "mruby.h"
#include "mruby/class.h"
#include "mruby/data.h"
#include "mruby/string.h"
#include "mruby/ext/io.h"
#if MRUBY_RELEASE_NO < 10000
#include "error.h"
#else
#include "mruby/error.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#include <io.h>
#define NULL_FILE "NUL"
#define UNLINK _unlink
#define GETCWD _getcwd
#define CHMOD(a, b) 0
#define MAXPATHLEN 1024
#if !defined(PATH_MAX)
#define PATH_MAX _MAX_PATH
#endif
#define realpath(N,R) _fullpath((R),(N),_MAX_PATH)
#include <direct.h>
#else
#define NULL_FILE "/dev/null"
#include <unistd.h>
#define UNLINK unlink
#define GETCWD getcwd
#define CHMOD(a, b) chmod(a,b)
#include <sys/file.h>
#include <libgen.h>
#include <sys/param.h>
#include <pwd.h>
#endif
#define FILE_SEPARATOR "/"
#if defined(_WIN32) || defined(_WIN64)
#define PATH_SEPARATOR ";"
#define FILE_ALT_SEPARATOR "\\"
#else
#define PATH_SEPARATOR ":"
#endif
#ifndef LOCK_SH
#define LOCK_SH 1
#endif
#ifndef LOCK_EX
#define LOCK_EX 2
#endif
#ifndef LOCK_NB
#define LOCK_NB 4
#endif
#ifndef LOCK_UN
#define LOCK_UN 8
#endif
#define STAT(p, s) stat(p, s)
#ifdef _WIN32
static int
flock(int fd, int operation) {
OVERLAPPED ov;
HANDLE h = (HANDLE)_get_osfhandle(fd);
DWORD flags;
flags = ((operation & LOCK_NB) ? LOCKFILE_FAIL_IMMEDIATELY : 0)
| ((operation & LOCK_SH) ? LOCKFILE_EXCLUSIVE_LOCK : 0);
memset(&ov, 0, sizeof(ov));
return LockFileEx(h, flags, 0, 0xffffffff, 0xffffffff, &ov) ? 0 : -1;
}
#endif
mrb_value
mrb_file_s_umask(mrb_state *mrb, mrb_value klass)
{
#if defined(_WIN32) || defined(_WIN64)
/* nothing to do on windows */
return mrb_fixnum_value(0);
#else
mrb_int mask, omask;
if (mrb_get_args(mrb, "|i", &mask) == 0) {
omask = umask(0);
umask(omask);
} else {
omask = umask(mask);
}
return mrb_fixnum_value(omask);
#endif
}
static mrb_value
mrb_file_s_unlink(mrb_state *mrb, mrb_value obj)
{
mrb_value *argv;
mrb_value pathv;
mrb_int argc, i;
char *path;
mrb_get_args(mrb, "*", &argv, &argc);
for (i = 0; i < argc; i++) {
pathv = mrb_convert_type(mrb, argv[i], MRB_TT_STRING, "String", "to_str");
path = mrb_locale_from_utf8(mrb_string_value_cstr(mrb, &pathv), -1);
if (UNLINK(path) < 0) {
mrb_locale_free(path);
mrb_sys_fail(mrb, path);
}
mrb_locale_free(path);
}
return mrb_fixnum_value(argc);
}
static mrb_value
mrb_file_s_rename(mrb_state *mrb, mrb_value obj)
{
mrb_value from, to;
char *src, *dst;
mrb_get_args(mrb, "SS", &from, &to);
src = mrb_locale_from_utf8(mrb_string_value_cstr(mrb, &from), -1);
dst = mrb_locale_from_utf8(mrb_string_value_cstr(mrb, &to), -1);
if (rename(src, dst) < 0) {
#if defined(_WIN32) || defined(_WIN64)
if (CHMOD(dst, 0666) == 0 && UNLINK(dst) == 0 && rename(src, dst) == 0) {
mrb_locale_free(src);
mrb_locale_free(dst);
return mrb_fixnum_value(0);
}
#endif
mrb_locale_free(src);
mrb_locale_free(dst);
mrb_sys_fail(mrb, mrb_str_to_cstr(mrb, mrb_format(mrb, "(%S, %S)", from, to)));
}
mrb_locale_free(src);
mrb_locale_free(dst);
return mrb_fixnum_value(0);
}
static mrb_value
mrb_file_dirname(mrb_state *mrb, mrb_value klass)
{
#if defined(_WIN32) || defined(_WIN64)
char dname[_MAX_DIR], vname[_MAX_DRIVE];
char buffer[_MAX_DRIVE + _MAX_DIR];
char *path;
size_t ridx;
mrb_value s;
mrb_get_args(mrb, "S", &s);
path = mrb_locale_from_utf8(mrb_str_to_cstr(mrb, s), -1);
_splitpath((const char*)path, vname, dname, NULL, NULL);
snprintf(buffer, _MAX_DRIVE + _MAX_DIR, "%s%s", vname, dname);
mrb_locale_free(path);
ridx = strlen(buffer);
if (ridx == 0) {
strncpy(buffer, ".", 2); /* null terminated */
} else if (ridx > 1) {
ridx--;
while (ridx > 0 && (buffer[ridx] == '/' || buffer[ridx] == '\\')) {
buffer[ridx] = '\0'; /* remove last char */
ridx--;
}
}
return mrb_str_new_cstr(mrb, buffer);
#else
char *dname, *path;
mrb_value s;
mrb_get_args(mrb, "S", &s);
path = mrb_locale_from_utf8(mrb_str_to_cstr(mrb, s), -1);
if ((dname = dirname(path)) == NULL) {
mrb_locale_free(path);
mrb_sys_fail(mrb, "dirname");
}
mrb_locale_free(path);
return mrb_str_new_cstr(mrb, dname);
#endif
}
static mrb_value
mrb_file_basename(mrb_state *mrb, mrb_value klass)
{
// NOTE: Do not use mrb_locale_from_utf8 here
#if defined(_WIN32) || defined(_WIN64)
char bname[_MAX_DIR];
char extname[_MAX_EXT];
char *path;
size_t ridx;
char buffer[_MAX_DIR + _MAX_EXT];
mrb_value s;
mrb_get_args(mrb, "S", &s);
path = mrb_str_to_cstr(mrb, s);
ridx = strlen(path);
if (ridx > 0) {
ridx--;
while (ridx > 0 && (path[ridx] == '/' || path[ridx] == '\\')) {
path[ridx] = '\0';
ridx--;
}
if (strncmp(path, "/", 2) == 0) {
return mrb_str_new_cstr(mrb, path);
}
}
_splitpath((const char*)path, NULL, NULL, bname, extname);
snprintf(buffer, _MAX_DIR + _MAX_EXT, "%s%s", bname, extname);
return mrb_str_new_cstr(mrb, buffer);
#else
char *bname, *path;
mrb_value s;
mrb_get_args(mrb, "S", &s);
path = mrb_str_to_cstr(mrb, s);
if ((bname = basename(path)) == NULL) {
mrb_sys_fail(mrb, "basename");
}
if (strncmp(bname, "//", 3) == 0) bname[1] = '\0'; /* patch for Cygwin */
return mrb_str_new_cstr(mrb, bname);
#endif
}
static mrb_value
mrb_file_realpath(mrb_state *mrb, mrb_value klass)
{
mrb_value pathname, dir_string, s, result;
mrb_int argc;
char *cpath;
argc = mrb_get_args(mrb, "S|S", &pathname, &dir_string);
if (argc == 2) {
s = mrb_str_dup(mrb, dir_string);
s = mrb_str_append(mrb, s, mrb_str_new_cstr(mrb, FILE_SEPARATOR));
s = mrb_str_append(mrb, s, pathname);
pathname = s;
}
cpath = mrb_locale_from_utf8(mrb_str_to_cstr(mrb, pathname), -1);
result = mrb_str_buf_new(mrb, PATH_MAX);
if (realpath(cpath, RSTRING_PTR(result)) == NULL) {
mrb_locale_free(cpath);
mrb_sys_fail(mrb, cpath);
}
mrb_locale_free(cpath);
mrb_str_resize(mrb, result, strlen(RSTRING_PTR(result)));
return result;
}
mrb_value
mrb_file__getwd(mrb_state *mrb, mrb_value klass)
{
mrb_value path;
char buf[MAXPATHLEN], *utf8;
if (GETCWD(buf, MAXPATHLEN) == NULL) {
mrb_sys_fail(mrb, "getcwd(2)");
}
utf8 = mrb_utf8_from_locale(buf, -1);
path = mrb_str_new_cstr(mrb, utf8);
mrb_utf8_free(utf8);
return path;
}
static int
mrb_file_is_absolute_path(const char *path)
{
return (path[0] == '/');
}
static mrb_value
mrb_file__gethome(mrb_state *mrb, mrb_value klass)
{
mrb_int argc;
char *home;
mrb_value path;
#ifndef _WIN32
mrb_value username;
argc = mrb_get_args(mrb, "|S", &username);
if (argc == 0) {
home = getenv("HOME");
if (home == NULL) {
return mrb_nil_value();
}
if (!mrb_file_is_absolute_path(home)) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "non-absolute home");
}
} else {
const char *cuser = mrb_str_to_cstr(mrb, username);
struct passwd *pwd = getpwnam(cuser);
if (pwd == NULL) {
return mrb_nil_value();
}
home = pwd->pw_dir;
if (!mrb_file_is_absolute_path(home)) {
mrb_raisef(mrb, E_ARGUMENT_ERROR, "non-absolute home of ~%S", username);
}
}
home = mrb_locale_from_utf8(home, -1);
path = mrb_str_new_cstr(mrb, home);
mrb_utf8_free(home);
return path;
#else
argc = mrb_get_argc(mrb);
if (argc == 0) {
home = getenv("USERPROFILE");
if (home == NULL) {
return mrb_nil_value();
}
if (!mrb_file_is_absolute_path(home)) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "non-absolute home");
}
} else {
return mrb_nil_value();
}
home = mrb_locale_from_utf8(home, -1);
path = mrb_str_new_cstr(mrb, home);
mrb_utf8_free(home);
return path;
#endif
}
mrb_value
mrb_file_flock(mrb_state *mrb, mrb_value self)
{
#if defined(sun)
mrb_raise(mrb, E_NOTIMP_ERROR, "flock is not supported on Illumos/Solaris/Windows");
#else
mrb_int operation;
int fd;
mrb_get_args(mrb, "i", &operation);
fd = (int)mrb_fixnum(mrb_io_fileno(mrb, self));
while (flock(fd, (int)operation) == -1) {
switch (errno) {
case EINTR:
/* retry */
break;
case EAGAIN: /* NetBSD */
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
case EWOULDBLOCK: /* FreeBSD OpenBSD Linux */
#endif
if (operation & LOCK_NB) {
return mrb_false_value();
}
/* FALLTHRU - should not happen */
default:
mrb_sys_fail(mrb, "flock failed");
break;
}
}
#endif
return mrb_fixnum_value(0);
}
static mrb_value
mrb_file_s_symlink(mrb_state *mrb, mrb_value klass)
{
#if defined(_WIN32) || defined(_WIN64)
mrb_raise(mrb, E_NOTIMP_ERROR, "symlink is not supported on this platform");
#else
mrb_value from, to;
const char *src, *dst;
int ai = mrb_gc_arena_save(mrb);
mrb_get_args(mrb, "SS", &from, &to);
src = mrb_locale_from_utf8(mrb_str_to_cstr(mrb, from), -1);
dst = mrb_locale_from_utf8(mrb_str_to_cstr(mrb, to), -1);
if (symlink(src, dst) == -1) {
mrb_locale_free(src);
mrb_locale_free(dst);
mrb_sys_fail(mrb, mrb_str_to_cstr(mrb, mrb_format(mrb, "(%S, %S)", from, to)));
}
mrb_locale_free(src);
mrb_locale_free(dst);
mrb_gc_arena_restore(mrb, ai);
#endif
return mrb_fixnum_value(0);
}
static mrb_value
mrb_file_s_chmod(mrb_state *mrb, mrb_value klass) {
mrb_int mode;
mrb_int argc, i;
mrb_value *filenames;
int ai = mrb_gc_arena_save(mrb);
mrb_get_args(mrb, "i*", &mode, &filenames, &argc);
for (i = 0; i < argc; i++) {
char *path = mrb_locale_from_utf8(mrb_str_to_cstr(mrb, filenames[i]), -1);
if (CHMOD(path, mode) == -1) {
mrb_locale_free(path);
mrb_sys_fail(mrb, path);
}
mrb_locale_free(path);
}
mrb_gc_arena_restore(mrb, ai);
return mrb_fixnum_value(argc);
}
static mrb_value
mrb_file_s_readlink(mrb_state *mrb, mrb_value klass) {
#if defined(_WIN32) || defined(_WIN64)
mrb_raise(mrb, E_NOTIMP_ERROR, "readlink is not supported on this platform");
return mrb_nil_value(); // unreachable
#else
char *path, *buf, *tmp;
size_t bufsize = 100;
ssize_t rc;
mrb_value ret;
int ai = mrb_gc_arena_save(mrb);
mrb_get_args(mrb, "z", &path);
tmp = mrb_locale_from_utf8(path, -1);
buf = (char *)mrb_malloc(mrb, bufsize);
while ((rc = readlink(tmp, buf, bufsize)) == (ssize_t)bufsize && rc != -1) {
bufsize *= 2;
buf = (char *)mrb_realloc(mrb, buf, bufsize);
}
mrb_locale_free(tmp);
if (rc == -1) {
mrb_free(mrb, buf);
mrb_sys_fail(mrb, path);
}
tmp = mrb_utf8_from_locale(buf, -1);
ret = mrb_str_new(mrb, tmp, rc);
mrb_locale_free(tmp);
mrb_free(mrb, buf);
mrb_gc_arena_restore(mrb, ai);
return ret;
#endif
}
void
mrb_init_file(mrb_state *mrb)
{
struct RClass *io, *file, *cnst;
io = mrb_class_get(mrb, "IO");
file = mrb_define_class(mrb, "File", io);
MRB_SET_INSTANCE_TT(file, MRB_TT_DATA);
mrb_define_class_method(mrb, file, "umask", mrb_file_s_umask, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, file, "delete", mrb_file_s_unlink, MRB_ARGS_ANY());
mrb_define_class_method(mrb, file, "unlink", mrb_file_s_unlink, MRB_ARGS_ANY());
mrb_define_class_method(mrb, file, "rename", mrb_file_s_rename, MRB_ARGS_REQ(2));
mrb_define_class_method(mrb, file, "symlink", mrb_file_s_symlink, MRB_ARGS_REQ(2));
mrb_define_class_method(mrb, file, "chmod", mrb_file_s_chmod, MRB_ARGS_REQ(1) | MRB_ARGS_REST());
mrb_define_class_method(mrb, file, "readlink", mrb_file_s_readlink, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, file, "dirname", mrb_file_dirname, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, file, "basename", mrb_file_basename, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, file, "realpath", mrb_file_realpath, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
mrb_define_class_method(mrb, file, "_getwd", mrb_file__getwd, MRB_ARGS_NONE());
mrb_define_class_method(mrb, file, "_gethome", mrb_file__gethome, MRB_ARGS_OPT(1));
mrb_define_method(mrb, file, "flock", mrb_file_flock, MRB_ARGS_REQ(1));
cnst = mrb_define_module_under(mrb, file, "Constants");
mrb_define_const(mrb, cnst, "LOCK_SH", mrb_fixnum_value(LOCK_SH));
mrb_define_const(mrb, cnst, "LOCK_EX", mrb_fixnum_value(LOCK_EX));
mrb_define_const(mrb, cnst, "LOCK_UN", mrb_fixnum_value(LOCK_UN));
mrb_define_const(mrb, cnst, "LOCK_NB", mrb_fixnum_value(LOCK_NB));
mrb_define_const(mrb, cnst, "SEPARATOR", mrb_str_new_cstr(mrb, FILE_SEPARATOR));
mrb_define_const(mrb, cnst, "PATH_SEPARATOR", mrb_str_new_cstr(mrb, PATH_SEPARATOR));
#if defined(_WIN32) || defined(_WIN64)
mrb_define_const(mrb, cnst, "ALT_SEPARATOR", mrb_str_new_cstr(mrb, FILE_ALT_SEPARATOR));
#else
mrb_define_const(mrb, cnst, "ALT_SEPARATOR", mrb_nil_value());
#endif
mrb_define_const(mrb, cnst, "NULL", mrb_str_new_cstr(mrb, NULL_FILE));
}
+381
View File
@@ -0,0 +1,381 @@
/*
** file.c - File class
*/
#include "mruby.h"
#include "mruby/class.h"
#include "mruby/data.h"
#include "mruby/string.h"
#include "mruby/ext/io.h"
#if MRUBY_RELEASE_NO < 10000
#include "error.h"
#else
#include "mruby/error.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>
#if defined(_WIN32) || defined(_WIN64)
#define LSTAT stat
#include <winsock.h>
#else
#define LSTAT lstat
#include <sys/file.h>
#include <sys/param.h>
#include <sys/wait.h>
#include <libgen.h>
#include <pwd.h>
#include <unistd.h>
#endif
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern struct mrb_data_type mrb_io_type;
static int
mrb_stat0(mrb_state *mrb, mrb_value obj, struct stat *st, int do_lstat)
{
mrb_value tmp;
mrb_value io_klass, str_klass;
io_klass = mrb_obj_value(mrb_class_get(mrb, "IO"));
str_klass = mrb_obj_value(mrb_class_get(mrb, "String"));
tmp = mrb_funcall(mrb, obj, "is_a?", 1, io_klass);
if (mrb_test(tmp)) {
struct mrb_io *fptr;
fptr = (struct mrb_io *)mrb_get_datatype(mrb, obj, &mrb_io_type);
if (fptr && fptr->fd >= 0) {
return fstat(fptr->fd, st);
}
mrb_raise(mrb, E_IO_ERROR, "closed stream");
return -1;
}
tmp = mrb_funcall(mrb, obj, "is_a?", 1, str_klass);
if (mrb_test(tmp)) {
char *path = mrb_locale_from_utf8(mrb_str_to_cstr(mrb, obj), -1);
int ret;
if (do_lstat) {
ret = LSTAT(path, st);
} else {
ret = stat(path, st);
}
mrb_locale_free(path);
return ret;
}
return -1;
}
static int
mrb_stat(mrb_state *mrb, mrb_value obj, struct stat *st)
{
return mrb_stat0(mrb, obj, st, 0);
}
static int
mrb_lstat(mrb_state *mrb, mrb_value obj, struct stat *st)
{
return mrb_stat0(mrb, obj, st, 1);
}
/*
* Document-method: directory?
*
* call-seq:
* File.directory?(file_name) -> true or false
*
* Returns <code>true</code> if the named file is a directory,
* or a symlink that points at a directory, and <code>false</code>
* otherwise.
*
* File.directory?(".")
*/
mrb_value
mrb_filetest_s_directory_p(mrb_state *mrb, mrb_value klass)
{
#ifndef S_ISDIR
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
struct stat st;
mrb_value obj;
mrb_get_args(mrb, "o", &obj);
if (mrb_stat(mrb, obj, &st) < 0)
return mrb_false_value();
if (S_ISDIR(st.st_mode))
return mrb_true_value();
return mrb_false_value();
}
/*
* call-seq:
* File.pipe?(file_name) -> true or false
*
* Returns <code>true</code> if the named file is a pipe.
*/
mrb_value
mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
{
#if defined(_WIN32) || defined(_WIN64)
mrb_raise(mrb, E_NOTIMP_ERROR, "pipe is not supported on this platform");
#else
#ifdef S_IFIFO
# ifndef S_ISFIFO
# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
# endif
struct stat st;
mrb_value obj;
mrb_get_args(mrb, "o", &obj);
if (mrb_stat(mrb, obj, &st) < 0)
return mrb_false_value();
if (S_ISFIFO(st.st_mode))
return mrb_true_value();
#endif
return mrb_false_value();
#endif
}
/*
* call-seq:
* File.symlink?(file_name) -> true or false
*
* Returns <code>true</code> if the named file is a symbolic link.
*/
mrb_value
mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
{
#if defined(_WIN32) || defined(_WIN64)
mrb_raise(mrb, E_NOTIMP_ERROR, "symlink is not supported on this platform");
#else
#ifndef S_ISLNK
# ifdef _S_ISLNK
# define S_ISLNK(m) _S_ISLNK(m)
# else
# ifdef _S_IFLNK
# define S_ISLNK(m) (((m) & S_IFMT) == _S_IFLNK)
# else
# ifdef S_IFLNK
# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
# endif
# endif
# endif
#endif
#ifdef S_ISLNK
struct stat st;
mrb_value obj;
mrb_get_args(mrb, "o", &obj);
if (mrb_lstat(mrb, obj, &st) == -1)
return mrb_false_value();
if (S_ISLNK(st.st_mode))
return mrb_true_value();
#endif
return mrb_false_value();
#endif
}
/*
* call-seq:
* File.socket?(file_name) -> true or false
*
* Returns <code>true</code> if the named file is a socket.
*/
mrb_value
mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass)
{
#if defined(_WIN32) || defined(_WIN64)
mrb_raise(mrb, E_NOTIMP_ERROR, "socket is not supported on this platform");
#else
#ifndef S_ISSOCK
# ifdef _S_ISSOCK
# define S_ISSOCK(m) _S_ISSOCK(m)
# else
# ifdef _S_IFSOCK
# define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
# else
# ifdef S_IFSOCK
# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
# endif
# endif
# endif
#endif
#ifdef S_ISSOCK
struct stat st;
mrb_value obj;
mrb_get_args(mrb, "o", &obj);
if (mrb_stat(mrb, obj, &st) < 0)
return mrb_false_value();
if (S_ISSOCK(st.st_mode))
return mrb_true_value();
#endif
return mrb_false_value();
#endif
}
/*
* call-seq:
* File.exist?(file_name) -> true or false
* File.exists?(file_name) -> true or false
*
* Return <code>true</code> if the named file exists.
*/
mrb_value
mrb_filetest_s_exist_p(mrb_state *mrb, mrb_value klass)
{
struct stat st;
mrb_value obj;
mrb_get_args(mrb, "o", &obj);
if (mrb_stat(mrb, obj, &st) < 0)
return mrb_false_value();
return mrb_true_value();
}
/*
* call-seq:
* File.file?(file_name) -> true or false
*
* Returns <code>true</code> if the named file exists and is a
* regular file.
*/
mrb_value
mrb_filetest_s_file_p(mrb_state *mrb, mrb_value klass)
{
#ifndef S_ISREG
# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
struct stat st;
mrb_value obj;
mrb_get_args(mrb, "o", &obj);
if (mrb_stat(mrb, obj, &st) < 0)
return mrb_false_value();
if (S_ISREG(st.st_mode))
return mrb_true_value();
return mrb_false_value();
}
/*
* call-seq:
* File.zero?(file_name) -> true or false
*
* Returns <code>true</code> if the named file exists and has
* a zero size.
*/
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);
if (mrb_stat(mrb, obj, &st) < 0)
return mrb_false_value();
if (st.st_size == 0)
return mrb_true_value();
return mrb_false_value();
}
/*
* call-seq:
* File.size(file_name) -> integer
*
* Returns the size of <code>file_name</code>.
*
* _file_name_ can be an IO object.
*/
mrb_value
mrb_filetest_s_size(mrb_state *mrb, mrb_value klass)
{
struct stat st;
mrb_value obj;
mrb_get_args(mrb, "o", &obj);
if (mrb_stat(mrb, obj, &st) < 0)
mrb_sys_fail(mrb, "mrb_stat");
return mrb_fixnum_value(st.st_size);
}
/*
* call-seq:
* File.size?(file_name) -> Integer or nil
*
* Returns +nil+ if +file_name+ doesn't exist or has zero size, the size of the
* file otherwise.
*/
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);
if (mrb_stat(mrb, obj, &st) < 0)
return mrb_nil_value();
if (st.st_size == 0)
return mrb_nil_value();
return mrb_fixnum_value(st.st_size);
}
void
mrb_init_file_test(mrb_state *mrb)
{
struct RClass *f;
f = mrb_define_class(mrb, "FileTest", mrb->object_class);
mrb_define_class_method(mrb, f, "directory?", mrb_filetest_s_directory_p, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, f, "exist?", mrb_filetest_s_exist_p, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, f, "exists?", mrb_filetest_s_exist_p, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, f, "file?", mrb_filetest_s_file_p, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, f, "pipe?", mrb_filetest_s_pipe_p, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, f, "size", mrb_filetest_s_size, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, f, "size?", mrb_filetest_s_size_p, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, f, "socket?", mrb_filetest_s_socket_p, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, f, "symlink?", mrb_filetest_s_symlink_p, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, f, "zero?", mrb_filetest_s_zero_p, MRB_ARGS_REQ(1));
}
File diff suppressed because it is too large Load Diff
+20
View File
@@ -0,0 +1,20 @@
#include "mruby.h"
void mrb_init_io(mrb_state *mrb);
void mrb_init_file(mrb_state *mrb);
void mrb_init_file_test(mrb_state *mrb);
#define DONE mrb_gc_arena_restore(mrb, 0)
void
mrb_mruby_io_gem_init(mrb_state* mrb)
{
mrb_init_io(mrb); DONE;
mrb_init_file(mrb); DONE;
mrb_init_file_test(mrb); DONE;
}
void
mrb_mruby_io_gem_final(mrb_state* mrb)
{
}
+197
View File
@@ -0,0 +1,197 @@
##
# IO Test
assert('File', '15.2.21') do
File.class == Class
end
assert('File', '15.2.21.2') do
File.superclass == IO
end
assert('File TEST SETUP') do
MRubyIOTestUtil.io_test_setup
end
assert('File#initialize', '15.2.21.4.1') do
io = File.open($mrbtest_io_rfname, "r")
assert_nil io.close
assert_raise IOError do
io.close
end
end
assert('File#path', '15.2.21.4.2') do
io = File.open($mrbtest_io_rfname, "r")
assert_equal $mrbtest_io_msg, io.read
assert_equal $mrbtest_io_rfname, io.path
io.close
assert_equal $mrbtest_io_rfname, io.path
io.closed?
end
assert('File.basename') do
assert_equal '/', File.basename('//')
assert_equal 'a', File.basename('/a/')
assert_equal 'b', File.basename('/a/b')
assert_equal 'b', File.basename('../a/b')
end
assert('File.dirname') do
assert_equal '.', File.dirname('')
assert_equal '.', File.dirname('a')
assert_equal '/', File.dirname('/a')
assert_equal 'a', File.dirname('a/b')
assert_equal '/a', File.dirname('/a/b')
end
assert('File.extname') do
assert_equal '.txt', File.extname('foo/foo.txt')
assert_equal '.gz', File.extname('foo/foo.tar.gz')
assert_equal '', File.extname('foo/bar')
assert_equal '', File.extname('foo/.bar')
assert_equal '', File.extname('foo.txt/bar')
assert_equal '', File.extname('.foo')
end
assert('IO#flock') do
f = File.open $mrbtest_io_rfname
begin
assert_equal(f.flock(File::LOCK_SH), 0)
assert_equal(f.flock(File::LOCK_UN), 0)
assert_equal(f.flock(File::LOCK_EX | File::LOCK_NB), 0)
assert_equal(f.flock(File::LOCK_UN), 0)
rescue NotImplementedError => e
skip e.message
ensure
f.close
end
end
assert('File.join') do
assert_equal "", File.join()
assert_equal "a", File.join("a")
assert_equal "/a", File.join("/a")
assert_equal "a/", File.join("a/")
assert_equal "a/b/c", File.join("a", "b", "c")
assert_equal "/a/b/c", File.join("/a", "b", "c")
assert_equal "a/b/c/", File.join("a", "b", "c/")
assert_equal "a/b/c", File.join("a/", "/b/", "/c")
assert_equal "a/b/c", File.join(["a", "b", "c"])
assert_equal "a/b/c", File.join("a", ["b", ["c"]])
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
end
end
end
assert("File.readlink") do
begin
assert_equal $mrbtest_io_rfname, File.readlink($mrbtest_io_symlinkname)
rescue NotImplementedError => e
skip e.message
end
end
assert("File.readlink fails with non-symlink") do
skip "readlink is not supported on this platform" if MRubyIOTestUtil.win?
begin
e2 = nil
assert_raise(RuntimeError) {
begin
File.readlink($mrbtest_io_rfname)
rescue => e
if Object.const_defined?(:SystemCallError) and e.kind_of?(SystemCallError)
raise RuntimeError, "SystemCallError converted to RuntimeError"
end
raise e
rescue NotImplementedError => e
e2 = e
end
}
raise e2 if e2
rescue NotImplementedError => e
skip e.message
end
end
assert('File.expand_path') do
assert_equal "/", File.expand_path("..", "/tmp"), "parent path with base_dir (1)"
assert_equal "/tmp", File.expand_path("..", "/tmp/mruby"), "parent path with base_dir (2)"
assert_equal "/home", File.expand_path("/home"), "absolute"
assert_equal "/home", File.expand_path("/home", "."), "absolute with base_dir"
assert_equal "/hoge", File.expand_path("/tmp/..//hoge")
assert_equal "/hoge", File.expand_path("////tmp/..///////hoge")
assert_equal "/", File.expand_path("../../../..", "/")
if File._getwd[1] == ":"
drive_letter = File._getwd[0]
assert_equal drive_letter + ":\\", File.expand_path(([".."] * 100).join("/"))
else
assert_equal "/", File.expand_path(([".."] * 100).join("/"))
end
end
assert('File.expand_path (with ENV)') do
skip unless Object.const_defined?(:ENV) && ENV['HOME']
assert_equal ENV['HOME'], File.expand_path("~/"), "home"
assert_equal ENV['HOME'], File.expand_path("~/", "/"), "home with base_dir"
assert_equal "#{ENV['HOME']}/user", File.expand_path("user", ENV['HOME']), "relative with base_dir"
end
assert('File.path') do
assert_equal "", File.path("")
assert_equal "a/b/c", File.path("a/b/c")
assert_equal "a/../b/./c", File.path("a/../b/./c")
assert_raise(TypeError) { File.path(nil) }
assert_raise(TypeError) { File.path(123) }
end
assert('File.symlink') do
target_name = "/usr/bin"
symlink_name = "test-bin-dummy"
if !File.exist?(target_name)
skip("target directory of File.symlink is not found")
else
begin
assert_equal 0, File.symlink(target_name, symlink_name)
begin
assert_equal true, File.symlink?(symlink_name)
ensure
File.delete symlink_name
end
rescue NotImplementedError => e
skip e.message
end
end
end
assert('File.chmod') do
File.open('chmod-test', 'w') {}
begin
assert_equal 1, File.chmod(0400, 'chmod-test')
ensure
File.delete('chmod-test')
end
end
assert('File TEST CLEANUP') do
assert_nil MRubyIOTestUtil.io_test_cleanup
end
+117
View File
@@ -0,0 +1,117 @@
##
# FileTest
assert('FileTest TEST SETUP') do
MRubyIOTestUtil.io_test_setup
end
assert("FileTest.directory?") do
dir = MRubyIOTestUtil.mkdtemp("mruby-io-test.XXXXXX")
begin
assert_true FileTest.directory?(dir)
assert_false FileTest.directory?($mrbtest_io_rfname)
ensure
MRubyIOTestUtil.rmdir dir
end
end
assert("FileTest.exist?") do
assert_equal true, FileTest.exist?($mrbtest_io_rfname), "filename - exist"
assert_equal false, FileTest.exist?($mrbtest_io_rfname + "-"), "filename - not exist"
io = IO.new(IO.sysopen($mrbtest_io_rfname))
assert_equal true, FileTest.exist?(io), "io obj - exist"
io.close
assert_equal true, io.closed?
assert_raise IOError do
FileTest.exist?(io)
end
end
assert("FileTest.file?") do
dir = MRubyIOTestUtil.mkdtemp("mruby-io-test.XXXXXX")
begin
assert_true FileTest.file?($mrbtest_io_rfname)
assert_false FileTest.file?(dir)
ensure
MRubyIOTestUtil.rmdir dir
end
end
assert("FileTest.pipe?") do
begin
assert_equal false, FileTest.pipe?("/tmp")
io = IO.popen("ls")
assert_equal true, FileTest.pipe?(io)
rescue NotImplementedError => e
skip e.message
end
end
assert('FileTest.size') do
assert_equal FileTest.size($mrbtest_io_rfname), $mrbtest_io_msg.size
assert_equal FileTest.size($mrbtest_io_wfname), 0
end
assert("FileTest.size?") do
assert_equal $mrbtest_io_msg.size, FileTest.size?($mrbtest_io_rfname)
assert_equal nil, FileTest.size?($mrbtest_io_wfname)
assert_equal nil, FileTest.size?("not-exist-test-target-file")
fp1 = File.open($mrbtest_io_rfname)
fp2 = File.open($mrbtest_io_wfname)
assert_equal $mrbtest_io_msg.size, FileTest.size?(fp1)
assert_equal nil, FileTest.size?(fp2)
fp1.close
fp2.close
assert_raise IOError do
FileTest.size?(fp1)
end
assert_raise IOError do
FileTest.size?(fp2)
end
fp1.closed? && fp2.closed?
end
assert("FileTest.socket?") do
begin
assert_true FileTest.socket?($mrbtest_io_socketname)
rescue NotImplementedError => e
skip e.message
end
end
assert("FileTest.symlink?") do
begin
assert_true FileTest.symlink?($mrbtest_io_symlinkname)
rescue NotImplementedError => e
skip e.message
end
end
assert("FileTest.zero?") do
assert_equal false, FileTest.zero?($mrbtest_io_rfname)
assert_equal true, FileTest.zero?($mrbtest_io_wfname)
assert_equal false, FileTest.zero?("not-exist-test-target-file")
fp1 = File.open($mrbtest_io_rfname)
fp2 = File.open($mrbtest_io_wfname)
assert_equal false, FileTest.zero?(fp1)
assert_equal true, FileTest.zero?(fp2)
fp1.close
fp2.close
assert_raise IOError do
FileTest.zero?(fp1)
end
assert_raise IOError do
FileTest.zero?(fp2)
end
fp1.closed? && fp2.closed?
end
assert('FileTest TEST CLEANUP') do
assert_nil MRubyIOTestUtil.io_test_cleanup
end
+4
View File
@@ -0,0 +1,4 @@
#!/bin/sh
ulimit -n 20
mruby -e '100.times { File.open "'$0'" }'
+642
View File
@@ -0,0 +1,642 @@
##
# IO Test
unless Object.respond_to? :assert_nothing_raised
def assert_nothing_raised(*exp)
ret = true
if $mrbtest_assert
$mrbtest_assert_idx += 1
msg = exp.last.class == String ? exp.pop : ""
begin
yield
rescue Exception => e
msg = "#{msg} exception raised."
diff = " Class: <#{e.class}>\n" +
" Message: #{e.message}"
$mrbtest_assert.push([$mrbtest_assert_idx, msg, diff])
ret = false
end
end
ret
end
end
assert('IO TEST SETUP') do
MRubyIOTestUtil.io_test_setup
$cr = MRubyIOTestUtil.win? ? 1 : 0 # "\n" include CR or not
end
assert('IO', '15.2.20') do
assert_equal(Class, IO.class)
end
assert('IO', '15.2.20.2') do
assert_equal(Object, IO.superclass)
end
assert('IO', '15.2.20.3') do
assert_include(IO.included_modules, Enumerable)
end
assert('IO.open', '15.2.20.4.1') do
fd = IO.sysopen $mrbtest_io_rfname
assert_equal Fixnum, fd.class
io = IO.open fd
assert_equal IO, io.class
assert_equal $mrbtest_io_msg, io.read
io.close
fd = IO.sysopen $mrbtest_io_rfname
IO.open(fd) do |io|
assert_equal $mrbtest_io_msg, io.read
end
true
end
assert('IO#close', '15.2.20.5.1') do
io = IO.new(IO.sysopen($mrbtest_io_rfname))
assert_nil io.close
end
assert('IO#closed?', '15.2.20.5.2') do
io = IO.new(IO.sysopen($mrbtest_io_rfname))
assert_false io.closed?
io.close
assert_true io.closed?
end
#assert('IO#each', '15.2.20.5.3') do
#assert('IO#each_byte', '15.2.20.5.4') do
#assert('IO#each_line', '15.2.20.5.5') do
assert('IO#eof?', '15.2.20.5.6') do
io = IO.new(IO.sysopen($mrbtest_io_wfname, 'w'), 'w')
assert_raise(IOError) do
io.eof?
end
io.close
# empty file
io = IO.open(IO.sysopen($mrbtest_io_wfname, 'w'), 'w')
io.close
io = IO.open(IO.sysopen($mrbtest_io_wfname, 'r'), 'r')
assert_true io.eof?
io.close
# nonempty file
io = IO.new(IO.sysopen($mrbtest_io_rfname))
assert_false io.eof?
io.readchar
assert_false io.eof?
io.read
assert_true io.eof?
io.close
true
end
assert('IO#flush', '15.2.20.5.7') do
# Note: mruby-io does not have any buffer to be flushed now.
io = IO.new(IO.sysopen($mrbtest_io_wfname))
assert_equal io, io.flush
io.close
assert_raise(IOError) do
io.flush
end
end
assert('IO#getc', '15.2.20.5.8') do
io = IO.new(IO.sysopen($mrbtest_io_rfname))
$mrbtest_io_msg.each_char { |ch|
assert_equal ch, io.getc
}
assert_equal nil, io.getc
io.close
true
end
#assert('IO#gets', '15.2.20.5.9') do
#assert('IO#initialize_copy', '15.2.20.5.10') do
#assert('IO#print', '15.2.20.5.11') do
#assert('IO#putc', '15.2.20.5.12') do
#assert('IO#puts', '15.2.20.5.13') do
assert('IO#read', '15.2.20.5.14') do
IO.open(IO.sysopen($mrbtest_io_rfname)) do |io|
assert_raise(ArgumentError) { io.read(-5) }
assert_raise(TypeError) { io.read("str") }
len = $mrbtest_io_msg.length
assert_equal '', io.read(0)
assert_equal 'mruby', io.read(5)
assert_equal $mrbtest_io_msg[5,len], io.read(len)
assert_equal "", io.read
assert_nil io.read(1)
end
IO.open(IO.sysopen($mrbtest_io_rfname)) do |io|
assert_equal $mrbtest_io_msg, io.read
end
end
assert "IO#read(n) with n > IO::BUF_SIZE" do
skip "pipe is not supported on this platform" if MRubyIOTestUtil.win?
r,w = IO.pipe
n = IO::BUF_SIZE+1
w.write 'a'*n
assert_equal r.read(n), 'a'*n
end
assert('IO#readchar', '15.2.20.5.15') do
# almost same as IO#getc
IO.open(IO.sysopen($mrbtest_io_rfname)) do |io|
$mrbtest_io_msg.each_char { |ch|
assert_equal ch, io.readchar
}
assert_raise(EOFError) do
io.readchar
end
end
end
#assert('IO#readline', '15.2.20.5.16') do
#assert('IO#readlines', '15.2.20.5.17') do
assert('IO#sync', '15.2.20.5.18') do
io = IO.new(IO.sysopen($mrbtest_io_rfname))
s = io.sync
assert_true(s == true || s == false)
io.close
assert_raise(IOError) do
io.sync
end
end
assert('IO#sync=', '15.2.20.5.19') do
io = IO.new(IO.sysopen($mrbtest_io_rfname))
io.sync = true
assert_true io.sync
io.sync = false
assert_false io.sync
io.close
assert_raise(IOError) do
io.sync = true
end
end
assert('IO#write', '15.2.20.5.20') do
io = IO.open(IO.sysopen($mrbtest_io_wfname))
assert_equal 0, io.write("")
io.close
io = IO.open(IO.sysopen($mrbtest_io_wfname, "r+"), "r+")
assert_equal 7, io.write("abcdefg")
io.rewind
assert_equal "ab", io.read(2)
assert_equal 3, io.write("123")
io.rewind
assert_equal "ab123fg", io.read
io.close
true
end
assert('IO#<<') do
io = IO.open(IO.sysopen($mrbtest_io_wfname))
io << "" << ""
assert_equal 0, io.pos
io.close
true
end
assert('IO#dup for readable') do
io = IO.new(IO.sysopen($mrbtest_io_rfname))
dup = io.dup
assert_true io != dup
assert_true io.fileno != dup.fileno
assert_equal 'm', dup.sysread(1)
assert_equal 'r', io.sysread(1)
assert_equal 'u', dup.sysread(1)
assert_equal 'b', io.sysread(1)
assert_equal 'y', dup.sysread(1)
dup.close
assert_false io.closed?
io.close
true
end
assert('IO#dup for writable') do
io = IO.open(IO.sysopen($mrbtest_io_wfname, 'w+'), 'w+')
dup = io.dup
io.syswrite "mruby"
assert_equal 5, dup.sysseek(0, IO::SEEK_CUR)
io.sysseek 0, IO::SEEK_SET
assert_equal 0, dup.sysseek(0, IO::SEEK_CUR)
assert_equal "mruby", dup.sysread(5)
dup.close
io.close
true
end
assert('IO.for_fd') do
fd = IO.sysopen($mrbtest_io_rfname)
io = IO.for_fd(fd)
assert_equal $mrbtest_io_msg, io.read
io.close
true
end
assert('IO.new') do
io = IO.new(0)
io.close
true
end
assert('IO gc check') do
100.times { IO.new(0) }
end
assert('IO.sysopen("./nonexistent")') do
if Object.const_defined? :Errno
eclass = Errno::ENOENT
else
eclass = RuntimeError
end
assert_raise eclass do
fd = IO.sysopen "./nonexistent"
IO._sysclose fd
end
end
assert('IO.sysopen, IO#sysread') do
fd = IO.sysopen $mrbtest_io_rfname
io = IO.new fd
str1 = " "
str2 = io.sysread(5, str1)
assert_equal $mrbtest_io_msg[0,5], str1
assert_equal $mrbtest_io_msg[0,5], str2
assert_raise EOFError do
io.sysread(10000)
io.sysread(10000)
end
assert_raise RuntimeError do
io.sysread(5, "abcde".freeze)
end
io.close
assert_equal "", io.sysread(0)
assert_raise(IOError) { io.sysread(1) }
assert_raise(ArgumentError) { io.sysread(-1) }
io.closed?
fd = IO.sysopen $mrbtest_io_wfname, "w"
io = IO.new fd, "w"
assert_raise(IOError) { io.sysread(1) }
io.close
true
end
assert('IO.sysopen, IO#syswrite') do
fd = IO.sysopen $mrbtest_io_wfname, "w"
io = IO.new fd, "w"
str = "abcdefg"
len = io.syswrite(str)
assert_equal str.size, len
io.close
io = IO.new(IO.sysopen($mrbtest_io_rfname), "r")
assert_raise(IOError) { io.syswrite("a") }
io.close
true
end
assert('IO#_read_buf') do
fd = IO.sysopen $mrbtest_io_rfname
io = IO.new fd
def io._buf
@buf
end
msg_len = $mrbtest_io_msg.size
assert_equal '', io._buf
assert_equal $mrbtest_io_msg, io._read_buf
assert_equal $mrbtest_io_msg, io._buf
assert_equal 'mruby', io.read(5)
assert_equal 5, io.pos
assert_equal msg_len - 5, io._buf.size
assert_equal $mrbtest_io_msg[5,100], io.read
assert_equal 0, io._buf.size
assert_raise EOFError do
io._read_buf
end
assert_equal true, io.eof
assert_equal true, io.eof?
io.close
io.closed?
end
assert('IO#isatty') do
skip "isatty is not supported on this platform" if MRubyIOTestUtil.win?
f1 = File.open("/dev/tty")
f2 = File.open($mrbtest_io_rfname)
assert_true f1.isatty
assert_false f2.isatty
f1.close
f2.close
true
end
assert('IO#pos=, IO#seek') do
fd = IO.sysopen $mrbtest_io_rfname
io = IO.new fd
def io._buf
@buf
end
assert_equal 'm', io.getc
assert_equal 1, io.pos
assert_equal 0, io.seek(0)
assert_equal 0, io.pos
io.close
io.closed?
end
assert('IO#rewind') do
fd = IO.sysopen $mrbtest_io_rfname
io = IO.new fd
assert_equal 'm', io.getc
assert_equal 1, io.pos
assert_equal 0, io.rewind
assert_equal 0, io.pos
io.close
io.closed?
end
assert('IO#gets') do
fd = IO.sysopen $mrbtest_io_rfname
io = IO.new fd
# gets without arguments
assert_equal $mrbtest_io_msg, io.gets, "gets without arguments"
assert_equal nil, io.gets, "gets returns nil, when EOF"
# gets with limit
io.pos = 0
assert_equal $mrbtest_io_msg[0, 5], io.gets(5), "gets with limit"
# gets with rs
io.pos = 0
assert_equal $mrbtest_io_msg[0, 6], io.gets(' '), "gets with rs"
# gets with rs, limit
io.pos = 0
assert_equal $mrbtest_io_msg[0, 5], io.gets(' ', 5), "gets with rs, limit"
io.close
assert_equal true, io.closed?, "close success"
# reading many-lines file.
fd = IO.sysopen $mrbtest_io_wfname, "w"
io = IO.new fd, "w"
io.write "0123456789" * 2 + "\na"
assert_equal 22 + $cr, io.pos
io.close
assert_equal true, io.closed?
fd = IO.sysopen $mrbtest_io_wfname
io = IO.new fd
line = io.gets
# gets first line
assert_equal "0123456789" * 2 + "\n", line, "gets first line"
assert_equal 21, line.size
assert_equal 21 + $cr, io.pos
# gets second line
assert_equal "a", io.gets, "gets second line"
# gets third line
assert_equal nil, io.gets, "gets third line; returns nil"
io.close
io.closed?
end
assert('IO#gets - paragraph mode') do
fd = IO.sysopen $mrbtest_io_wfname, "w"
io = IO.new fd, "w"
io.write "0" * 10 + "\n"
io.write "1" * 10 + "\n\n"
io.write "2" * 10 + "\n"
assert_equal 34 + $cr * 4, io.pos
io.close
assert_equal true, io.closed?
fd = IO.sysopen $mrbtest_io_wfname
io = IO.new fd
para1 = "#{'0' * 10}\n#{'1' * 10}\n\n"
text1 = io.gets("")
assert_equal para1, text1
para2 = "#{'2' * 10}\n"
text2 = io.gets("")
assert_equal para2, text2
io.close
io.closed?
end
assert('IO.popen') do
begin
$? = nil
io = IO.popen("echo mruby-io")
assert_true io.close_on_exec?
assert_equal Fixnum, io.pid.class
out = io.read
assert_equal out.class, String
assert_include out, 'mruby-io'
io.close
if Object.const_defined? :Process
assert_true $?.success?
else
assert_equal 0, $?
end
assert_true io.closed?
rescue NotImplementedError => e
skip e.message
end
end
assert('IO.popen with in option') do
begin
IO.pipe do |r, w|
w.write 'hello'
w.close
assert_equal "hello", IO.popen("cat", "r", in: r) { |i| i.read }
assert_equal "", r.read
end
assert_raise(ArgumentError) { IO.popen("hello", "r", in: Object.new) }
rescue NotImplementedError => e
skip e.message
end
end
assert('IO.popen with out option') do
begin
IO.pipe do |r, w|
IO.popen("echo 'hello'", "w", out: w) {}
w.close
assert_equal "hello\n", r.read
end
rescue NotImplementedError => e
skip e.message
end
end
assert('IO.popen with err option') do
begin
IO.pipe do |r, w|
assert_equal "", IO.popen("echo 'hello' 1>&2", "r", err: w) { |i| i.read }
w.close
assert_equal "hello\n", r.read
end
rescue NotImplementedError => e
skip e.message
end
end
assert('IO.read') do
# empty file
fd = IO.sysopen $mrbtest_io_wfname, "w"
io = IO.new fd, "w"
io.close
assert_equal "", IO.read($mrbtest_io_wfname)
assert_equal nil, IO.read($mrbtest_io_wfname, 1)
# one byte file
fd = IO.sysopen $mrbtest_io_wfname, "w"
io = IO.new fd, "w"
io.write "123"
io.close
assert_equal "123", IO.read($mrbtest_io_wfname)
assert_equal "", IO.read($mrbtest_io_wfname, 0)
assert_equal "1", IO.read($mrbtest_io_wfname, 1)
assert_equal "", IO.read($mrbtest_io_wfname, 0, 10)
assert_equal "23", IO.read($mrbtest_io_wfname, 2, 1)
assert_equal "23", IO.read($mrbtest_io_wfname, 10, 1)
assert_equal "", IO.read($mrbtest_io_wfname, nil, 10)
assert_equal nil, IO.read($mrbtest_io_wfname, 1, 10)
end
assert('IO#fileno') do
fd = IO.sysopen $mrbtest_io_rfname
io = IO.new fd
assert_equal io.fileno, fd
assert_equal io.to_i, fd
io.close
io.closed?
end
assert('IO#close_on_exec') do
fd = IO.sysopen $mrbtest_io_wfname, "w"
io = IO.new fd, "w"
begin
# IO.sysopen opens a file descripter with O_CLOEXEC flag.
assert_true io.close_on_exec?
rescue ScriptError
io.close
skip "IO\#close_on_exec is not implemented."
end
io.close_on_exec = false
assert_equal(false, io.close_on_exec?)
io.close_on_exec = true
assert_equal(true, io.close_on_exec?)
io.close_on_exec = false
assert_equal(false, io.close_on_exec?)
io.close
io.closed?
begin
r, w = IO.pipe
assert_equal(true, r.close_on_exec?)
r.close_on_exec = false
assert_equal(false, r.close_on_exec?)
r.close_on_exec = true
assert_equal(true, r.close_on_exec?)
assert_equal(true, w.close_on_exec?)
w.close_on_exec = false
assert_equal(false, w.close_on_exec?)
w.close_on_exec = true
assert_equal(true, w.close_on_exec?)
ensure
r.close unless r.closed?
w.close unless w.closed?
end
end
assert('IO#sysseek') do
IO.open(IO.sysopen($mrbtest_io_rfname)) do |io|
assert_equal 2, io.sysseek(2)
assert_equal 5, io.sysseek(3, IO::SEEK_CUR) # 2 + 3 => 5
assert_equal $mrbtest_io_msg.size - 4, io.sysseek(-4, IO::SEEK_END)
end
end
assert('IO.pipe') do
begin
called = false
IO.pipe do |r, w|
assert_true r.kind_of?(IO)
assert_true w.kind_of?(IO)
assert_false r.closed?
assert_false w.closed?
assert_true FileTest.pipe?(r)
assert_true FileTest.pipe?(w)
assert_nil r.pid
assert_nil w.pid
assert_true 2 < r.fileno
assert_true 2 < w.fileno
assert_true r.fileno != w.fileno
assert_false r.sync
assert_true w.sync
assert_equal 8, w.write('test for')
assert_equal 'test', r.read(4)
assert_equal ' for', r.read(4)
assert_equal 5, w.write(' pipe')
assert_equal nil, w.close
assert_equal ' pipe', r.read
called = true
assert_raise(IOError) { r.write 'test' }
# TODO:
# This assert expect raise IOError but got RuntimeError
# Because mruby-io not have flag for I/O readable
# assert_raise(IOError) { w.read }
end
assert_true called
assert_nothing_raised do
IO.pipe { |r, w| r.close; w.close }
end
rescue NotImplementedError => e
skip e.message
end
end
assert('`cmd`') do
begin
assert_equal `echo foo`, "foo\n"
rescue NotImplementedError => e
skip e.message
end
end
assert('IO TEST CLEANUP') do
assert_nil MRubyIOTestUtil.io_test_cleanup
end
+256
View File
@@ -0,0 +1,256 @@
#include <sys/types.h>
#include <errno.h>
#if defined(_WIN32) || defined(_WIN64)
#include <winsock.h>
#include <io.h>
#include <fcntl.h>
#include <direct.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#if (!defined __MINGW64__) && (!defined __MINGW32__)
typedef int mode_t;
#endif
#define open _open
#define close _close
#ifdef _MSC_VER
#include <sys/stat.h>
static int
mkstemp(char *p)
{
int fd;
char* fname = _mktemp(p);
if (fname == NULL)
return -1;
fd = open(fname, O_RDWR | O_CREAT | O_EXCL, _S_IREAD | _S_IWRITE);
if (fd >= 0)
return fd;
return -1;
}
#endif
static char*
mkdtemp(char *temp)
{
char *path = _mktemp(temp);
if (path[0] == 0) return NULL;
if (_mkdir(path) < 0) return NULL;
return path;
}
#define umask(mode) _umask(mode)
#define rmdir(path) _rmdir(path)
#else
#include <sys/socket.h>
#include <unistd.h>
#include <sys/un.h>
#endif
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include "mruby.h"
#include "mruby/array.h"
#include "mruby/error.h"
#include "mruby/string.h"
#include "mruby/variable.h"
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";
char msg[] = "mruby io test\n";
mode_t mask;
int fd0, fd1;
FILE *fp;
#if !defined(_WIN32) && !defined(_WIN64)
int fd2, fd3;
struct sockaddr_un sun0;
#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");
if (fp == NULL) {
mrb_raise(mrb, E_RUNTIME_ERROR, "can't open temporary file");
return mrb_nil_value();
}
fputs(msg, fp);
fclose(fp);
fp = fopen(wfname, "wb");
if (fp == NULL) {
mrb_raise(mrb, E_RUNTIME_ERROR, "can't open temporary file");
return mrb_nil_value();
}
fclose(fp);
#if !defined(_WIN32) && !defined(_WIN64)
unlink(symlinkname);
close(fd2);
if (symlink(rfname, symlinkname) == -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) {
mrb_raise(mrb, E_RUNTIME_ERROR, "can't make a socket");
}
sun0.sun_family = AF_UNIX;
snprintf(sun0.sun_path, sizeof(sun0.sun_path), "%s", socketname);
if (bind(fd3, (struct sockaddr *)&sun0, sizeof(sun0)) == -1) {
mrb_raisef(mrb, E_RUNTIME_ERROR, "can't bind AF_UNIX socket to %S: %S",
mrb_str_new_cstr(mrb, sun0.sun_path),
mrb_fixnum_value(errno));
}
close(fd3);
#endif
return mrb_true_value();
}
static mrb_value
mrb_io_test_io_cleanup(mrb_state *mrb, mrb_value self)
{
mrb_value rfname = mrb_gv_get(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_rfname"));
mrb_value wfname = mrb_gv_get(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_wfname"));
mrb_value symlinkname = mrb_gv_get(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_symlinkname"));
mrb_value socketname = mrb_gv_get(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_socketname"));
if (mrb_type(rfname) == MRB_TT_STRING) {
remove(RSTRING_PTR(rfname));
}
if (mrb_type(wfname) == MRB_TT_STRING) {
remove(RSTRING_PTR(wfname));
}
if (mrb_type(symlinkname) == MRB_TT_STRING) {
remove(RSTRING_PTR(symlinkname));
}
if (mrb_type(socketname) == MRB_TT_STRING) {
remove(RSTRING_PTR(socketname));
}
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_rfname"), mrb_nil_value());
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_wfname"), mrb_nil_value());
mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$mrbtest_io_symlinkname"), mrb_nil_value());
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());
return mrb_nil_value();
}
static mrb_value
mrb_io_test_file_setup(mrb_state *mrb, mrb_value self)
{
mrb_value ary = mrb_io_test_io_setup(mrb, self);
#if !defined(_WIN32) && !defined(_WIN64)
if (symlink("/usr/bin", "test-bin") == -1) {
mrb_raise(mrb, E_RUNTIME_ERROR, "can't make a symbolic link");
}
#endif
return ary;
}
static mrb_value
mrb_io_test_file_cleanup(mrb_state *mrb, mrb_value self)
{
mrb_io_test_io_cleanup(mrb, self);
remove("test-bin");
return mrb_nil_value();
}
static mrb_value
mrb_io_test_mkdtemp(mrb_state *mrb, mrb_value klass)
{
mrb_value str;
char *cp;
mrb_get_args(mrb, "S", &str);
cp = mrb_str_to_cstr(mrb, str);
if (mkdtemp(cp) == NULL) {
mrb_sys_fail(mrb, "mkdtemp");
}
return mrb_str_new_cstr(mrb, cp);
}
static mrb_value
mrb_io_test_rmdir(mrb_state *mrb, mrb_value klass)
{
mrb_value str;
char *cp;
mrb_get_args(mrb, "S", &str);
cp = mrb_str_to_cstr(mrb, str);
if (rmdir(cp) == -1) {
mrb_sys_fail(mrb, "rmdir");
}
return mrb_true_value();
}
mrb_value
mrb_io_win_p(mrb_state *mrb, mrb_value klass)
{
#if defined(_WIN32) || defined(_WIN64)
# if defined(__CYGWIN__) || defined(__CYGWIN32__)
return mrb_false_value();
# else
return mrb_true_value();
# endif
#else
return mrb_false_value();
#endif
}
void
mrb_mruby_io_gem_test(mrb_state* mrb)
{
struct RClass *io_test = mrb_define_module(mrb, "MRubyIOTestUtil");
mrb_define_class_method(mrb, io_test, "io_test_setup", mrb_io_test_io_setup, MRB_ARGS_NONE());
mrb_define_class_method(mrb, io_test, "io_test_cleanup", mrb_io_test_io_cleanup, MRB_ARGS_NONE());
mrb_define_class_method(mrb, io_test, "file_test_setup", mrb_io_test_file_setup, MRB_ARGS_NONE());
mrb_define_class_method(mrb, io_test, "file_test_cleanup", mrb_io_test_file_cleanup, MRB_ARGS_NONE());
mrb_define_class_method(mrb, io_test, "mkdtemp", mrb_io_test_mkdtemp, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, io_test, "rmdir", mrb_io_test_rmdir, MRB_ARGS_REQ(1));
mrb_define_class_method(mrb, io_test, "win?", mrb_io_win_p, MRB_ARGS_NONE());
}
+13
View File
@@ -0,0 +1,13 @@
module Kernel
# call-seq:
# obj.yield_self {|_obj|...} -> an_object
#
# Yields <i>obj</i> and returns the result.
#
# 'my string'.yield_self {|s|s.upcase} #=> "MY STRING"
#
def yield_self(&block)
return to_enum :yield_self unless block
block.call(self)
end
end
+21
View File
@@ -114,6 +114,7 @@ mrb_f_integer(mrb_state *mrb, mrb_value self)
return mrb_convert_to_integer(mrb, arg, base);
}
#ifndef MRB_WITHOUT_FLOAT
/*
* call-seq:
* Float(arg) -> float
@@ -134,6 +135,7 @@ mrb_f_float(mrb_state *mrb, mrb_value self)
mrb_get_args(mrb, "o", &arg);
return mrb_Float(mrb, arg);
}
#endif
/*
* call-seq:
@@ -222,6 +224,22 @@ mrb_f_hash(mrb_state *mrb, mrb_value self)
return tmp;
}
/*
* call-seq:
* obj.itself -> an_object
*
* Returns <i>obj</i>.
*
* string = 'my string' #=> "my string"
* string.itself.object_id == string.object_id #=> true
*
*/
static mrb_value
mrb_f_itself(mrb_state *mrb, mrb_value self)
{
return self;
}
void
mrb_mruby_kernel_ext_gem_init(mrb_state *mrb)
{
@@ -231,10 +249,13 @@ mrb_mruby_kernel_ext_gem_init(mrb_state *mrb)
mrb_define_module_function(mrb, krn, "caller", mrb_f_caller, MRB_ARGS_OPT(2));
mrb_define_method(mrb, krn, "__method__", mrb_f_method, MRB_ARGS_NONE());
mrb_define_module_function(mrb, krn, "Integer", mrb_f_integer, MRB_ARGS_ANY());
#ifndef MRB_WITHOUT_FLOAT
mrb_define_module_function(mrb, krn, "Float", mrb_f_float, MRB_ARGS_REQ(1));
#endif
mrb_define_module_function(mrb, krn, "String", mrb_f_string, MRB_ARGS_REQ(1));
mrb_define_module_function(mrb, krn, "Array", mrb_f_array, MRB_ARGS_REQ(1));
mrb_define_module_function(mrb, krn, "Hash", mrb_f_hash, MRB_ARGS_REQ(1));
mrb_define_module_function(mrb, krn, "itself", mrb_f_itself, MRB_ARGS_NONE());
}
void
+2 -2
View File
@@ -49,7 +49,7 @@ assert('Kernel#__method__') do
end
assert('Kernel#Integer') do
assert_equal(123, Integer(123.999))
assert_equal(123, Integer(123.999)) if class_defined?("Float")
assert_equal(26, Integer("0x1a"))
assert_equal(930, Integer("0930", 10))
assert_equal(7, Integer("111", 2))
@@ -63,7 +63,7 @@ assert('Kernel#Float') do
assert_equal(123.456, Float(123.456))
assert_equal(123.456, Float("123.456"))
assert_raise(TypeError) { Float(nil) }
end
end if class_defined?("Float")
assert('Kernel#String') do
assert_equal("main", String(self))
+2 -2
View File
@@ -486,7 +486,7 @@ static mrb_value
math_log(mrb_state *mrb, mrb_value obj)
{
mrb_float x, base;
int argc;
mrb_int argc;
argc = mrb_get_args(mrb, "f|f", &x, &base);
if (x < 0.0) {
@@ -657,7 +657,7 @@ math_ldexp(mrb_state *mrb, mrb_value obj)
mrb_int i;
mrb_get_args(mrb, "fi", &x, &i);
x = ldexp(x, i);
x = ldexp(x, (int)i);
return mrb_float_value(mrb, x);
}
+59
View File
@@ -0,0 +1,59 @@
mruby-method
===
A implementetion of class **Method** and **UnboundMethod** for mruby
```ruby
p Enumerable.instance_method(:find_all).source_location
#=> ["mruby/mruby/mrblib/enum.rb", 148]
```
# Note
`source_location` method need this configuration in build_config.rb
```ruby
MRuby::Build.new do |conf|
enable_debug
end
```
# Supported Methods
## Kernel
- `Kernel#method`
- `Kernel#singleton_method`
## Module
- `Module#instance_method`
## Method class
- `Method#name`
- `Method#call`
- `Method#super_method`
- `Method#arity`
- `Method#unbind`
- `Method#[]`
- `Method#owner`
- `Method#receiver`
- `Method#parameters`
- `Method#source_location`
- `Method#to_proc`
## UnboundMethod class
- `UnboundMethod#name`
- `UnboundMethod#bind`
- `UnboundMethod#super_method`
- `UnboundMethod#arity`
- `UnboundMethod#owner`
- `UnboundMethod#parameters`
- `UnboundMethod#source_location`
# See also
- https://ruby-doc.org/core-2.3.3/Method.html
- https://ruby-doc.org/core-2.3.3/UnboundMethod.html

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