esruby 0.0.9 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/lib/esruby/build.rb +7 -4
- data/resources/build_config.eruby +1 -0
- data/resources/cpp/main.cpp +14 -0
- data/resources/mruby/doc/guides/mrbgems.md +5 -0
- data/resources/mruby/include/mrbconf.h +3 -5
- data/resources/mruby/include/mruby/proc.h +2 -2
- data/resources/mruby/include/mruby.h +11 -4
- data/resources/mruby/lib/mruby/build/load_gems.rb +5 -3
- data/resources/mruby/lib/mruby/build.rb +23 -0
- data/resources/mruby/lib/mruby/gem.rb +12 -13
- data/resources/mruby/mrbgems/default.gembox +6 -0
- data/resources/mruby/mrbgems/mruby-compiler/core/codegen.c +7 -1
- data/resources/mruby/mrbgems/mruby-compiler/core/parse.y +31 -36
- data/resources/mruby/mrbgems/mruby-enum-ext/mrblib/enum.rb +33 -10
- data/resources/mruby/mrbgems/mruby-enum-ext/test/enum.rb +6 -0
- data/resources/mruby/mrbgems/mruby-enum-lazy/test/lazy.rb +1 -1
- data/resources/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb +32 -17
- data/resources/mruby/mrbgems/mruby-enumerator/test/enumerator.rb +10 -0
- data/resources/mruby/mrbgems/mruby-fiber/src/fiber.c +3 -2
- data/resources/mruby/mrbgems/mruby-io/mrblib/io.rb +3 -2
- data/resources/mruby/mrbgems/mruby-io/src/file.c +15 -0
- data/resources/mruby/mrbgems/mruby-io/src/io.c +16 -8
- data/resources/mruby/mrbgems/mruby-io/test/file.rb +17 -1
- data/resources/mruby/mrbgems/mruby-io/test/io.rb +4 -0
- data/resources/mruby/mrbgems/mruby-pack/src/pack.c +16 -6
- data/resources/mruby/mrbgems/mruby-socket/mrbgem.rake +2 -2
- data/resources/mruby/mrbgems/mruby-socket/test/sockettest.c +42 -6
- data/resources/mruby/mrbgems/mruby-test/init_mrbtest.c +1 -0
- data/resources/mruby/mrbgems/mruby-test/mrbgem.rake +1 -0
- data/resources/mruby/mrbgems/mruby-time/src/time.c +22 -3
- data/resources/mruby/mrbgems/mruby-time/test/time.rb +4 -0
- data/resources/mruby/mrblib/array.rb +8 -9
- data/resources/mruby/mrblib/enum.rb +1 -1
- data/resources/mruby/src/array.c +1 -1
- data/resources/mruby/src/class.c +8 -2
- data/resources/mruby/src/error.c +2 -1
- data/resources/mruby/src/gc.c +1 -1
- data/resources/mruby/src/object.c +2 -2
- data/resources/mruby/src/string.c +8 -8
- data/resources/mruby/src/variable.c +41 -7
- data/resources/mruby/src/vm.c +5 -4
- data/resources/mruby/tasks/toolchains/visualcpp.rake +10 -9
- data/resources/mruby/test/t/string.rb +2 -1
- data/resources/project_template/config.rb +5 -0
- data/resources/rb/append.rb +3 -0
- metadata +3 -4
- data/resources/cpp/esruby.cpp +0 -51
- data/resources/cpp/esruby.hpp +0 -38
- data/resources/js/esruby.js +0 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a16d0112d53861ad14f8c825229b924f1a980cdf
|
|
4
|
+
data.tar.gz: 0df764960a1cdff6f71723c596825a92995f4709
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 233b64432005b46c61fdcad9a06ef7e9a84f9a1eb79ce02ac38c6172a1e0c8a16a584f6e35b8b340b412d34e84a608468356a67fe6677df5e1e0d13e76957c30
|
|
7
|
+
data.tar.gz: 65d573fe29d8430b7ac4a55a8590c3e1396f0a43cc559d1050834b73eda6fcf0b3de97ba0314965463424f9ddbbe811c58b7811ff6ccbaae1c3ba0b5f50ef720
|
data/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
#
|
|
1
|
+
# esruby
|
|
2
2
|
This project brings *mruby* to the browser. It uses [*emscripten*](https://github.com/kripken/emscripten) to compile the mruby source code into
|
|
3
3
|
JavaScript (ECMAScript) and runs in the browser. It is heavily based off [*webruby*](https://github.com/xxuejie/webruby) but has been adjusted to work with the updates to *emscripten* and *mruby*.
|
|
4
4
|
|
|
5
5
|
# Install
|
|
6
|
-
*
|
|
6
|
+
*esruby* depends on [emsdk](http://kripken.github.io/emscripten-site/index.html) to provide a tool chain consisting of *emscripten* and *LLVM*. Although the tool chain is available from `apt-get` we will need to build emscripten from source using my branch as I have introduced some new features that have not made it into the release yet.
|
|
7
7
|
|
|
8
8
|
* we will start with a clean instance of Ubuntu 16.04 with ruby MRI installed
|
|
9
9
|
* `sudo apt-get install build-essential cmake`
|
data/lib/esruby/build.rb
CHANGED
|
@@ -13,7 +13,7 @@ module ESRuby
|
|
|
13
13
|
new_build
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
def_delegators :@configuration, :root_directory, :
|
|
16
|
+
def_delegators :@configuration, :root_directory, :build_directory,
|
|
17
17
|
:build_mode, :output, :mruby_directory, :gems
|
|
18
18
|
|
|
19
19
|
def initialize(&block)
|
|
@@ -55,10 +55,13 @@ module ESRuby
|
|
|
55
55
|
js_files += specification.appended_js_sources
|
|
56
56
|
end
|
|
57
57
|
js_files += @configuration.appended_js_sources
|
|
58
|
-
js_files << "#{gem_directory}/resources/js/esruby.js"
|
|
59
58
|
js_files
|
|
60
59
|
end
|
|
61
60
|
|
|
61
|
+
def ruby_sources
|
|
62
|
+
@configuration.ruby_sources + ["#{gem_directory}/resources/rb/append.rb"]
|
|
63
|
+
end
|
|
64
|
+
|
|
62
65
|
def build_mruby_config
|
|
63
66
|
template = File.read("#{gem_directory}/resources/build_config.eruby")
|
|
64
67
|
eruby = Erubis::Eruby.new(template)
|
|
@@ -117,8 +120,8 @@ module ESRuby
|
|
|
117
120
|
js_arguments += appended_js_sources.map { |path| "--post-js #{path}" }.join(" ")
|
|
118
121
|
RakeFileUtils.sh "#{mrbc} -B app -o #{build_directory}/app.c #{ruby_sources.join(" ")}"
|
|
119
122
|
RakeFileUtils.sh "emcc --bind -I #{mruby_directory}/include #{build_directory}/app.c -o #{build_directory}/app.o #{build_directory}/emscripten/lib/libmruby.a -lm #{js_arguments} #{optimization_argument} #{closure_argument} #{debug_argument}"
|
|
120
|
-
RakeFileUtils.sh "emcc -std=c++11 --bind -I #{mruby_directory}/include #{gem_directory}/resources/cpp/
|
|
121
|
-
RakeFileUtils.sh "emcc --bind -I #{mruby_directory}/include -o #{build_directory}/output.js #{build_directory}/app.o #{build_directory}/
|
|
123
|
+
RakeFileUtils.sh "emcc -std=c++11 --bind -I #{mruby_directory}/include #{gem_directory}/resources/cpp/main.cpp -o #{build_directory}/main.o #{build_directory}/emscripten/lib/libmruby.a -lm #{js_arguments} #{optimization_argument} #{closure_argument} #{debug_argument}"
|
|
124
|
+
RakeFileUtils.sh "emcc --bind -I #{mruby_directory}/include -o #{build_directory}/output.js #{build_directory}/app.o #{build_directory}/main.o #{build_directory}/emscripten/lib/libmruby.a -lm #{js_arguments} #{optimization_argument} #{closure_argument} #{debug_argument}"
|
|
122
125
|
#if build.build_mode == 'production'
|
|
123
126
|
# sh "java -jar #{PROJECT_DIRECTORY}/emsdk/emscripten/incoming/third_party/closure-compiler/compiler.jar --js #{build.absolute_build_directory}/output.js --js_output_file #{build.absolute_output}"
|
|
124
127
|
#else
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#include "/media/file_server/file_drive/projects/esruby/esruby-esruby/include/esruby.hpp"
|
|
2
|
+
|
|
3
|
+
// we need to load the esruby bindings here, see issue:
|
|
4
|
+
// https://github.com/kripken/emscripten/issues/5537
|
|
5
|
+
// although you can observe that the bindings in esruby-bind do work
|
|
6
|
+
// so im not sure what the problem is
|
|
7
|
+
// idealy i would like to use a compiler option like EXPORTED_FUNCTIONS, for classes
|
|
8
|
+
EMSCRIPTEN_BINDINGS(esruby)
|
|
9
|
+
{
|
|
10
|
+
emscripten::class_<ESRuby>("ESRuby")
|
|
11
|
+
.class_function("start", &ESRuby::start)
|
|
12
|
+
.class_function("stop", &ESRuby::stop)
|
|
13
|
+
;
|
|
14
|
+
}
|
|
@@ -26,6 +26,11 @@ conf.gem :github => 'masuidrive/mrbgems-example', :branch => 'master'
|
|
|
26
26
|
conf.gem :bitbucket => 'mruby/mrbgems-example', :branch => 'master'
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
+
You can specify the sub directory of the repository with `:path` option:
|
|
30
|
+
```ruby
|
|
31
|
+
conf.gem github: 'mruby/mruby', path: 'mrbgems/mruby-socket'
|
|
32
|
+
```
|
|
33
|
+
|
|
29
34
|
To use mrbgem from [mgem-list](https://github.com/mruby/mgem-list) use `:mgem` option:
|
|
30
35
|
```ruby
|
|
31
36
|
conf.gem :mgem => 'mruby-yaml'
|
|
@@ -36,12 +36,10 @@
|
|
|
36
36
|
/* size of the method cache (need to be the power of 2) */
|
|
37
37
|
//#define MRB_METHOD_CACHE_SIZE (1<<7)
|
|
38
38
|
|
|
39
|
-
/* add -DMRB_METHOD_TABLE_INLINE
|
|
39
|
+
/* add -DMRB_METHOD_TABLE_INLINE to reduce the size of method table */
|
|
40
|
+
/* MRB_METHOD_TABLE_INLINE requires LSB of function pointers to be zero */
|
|
41
|
+
/* you might need to specify --falign-functions=n (where n>1) */
|
|
40
42
|
//#define MRB_METHOD_TABLE_INLINE
|
|
41
|
-
/* turn MRB_METHOD_TABLE_INLINE on for linux by default */
|
|
42
|
-
#if !defined(MRB_METHOD_TABLE_INLINE) && defined(__linux__)
|
|
43
|
-
# define MRB_METHOD_TABLE_INLINE
|
|
44
|
-
#endif
|
|
45
43
|
|
|
46
44
|
/* add -DMRB_INT16 to use 16bit integer for mrb_int; conflict with MRB_INT64 */
|
|
47
45
|
//#define MRB_INT16
|
|
@@ -98,8 +98,8 @@ MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state*, mrb_int);
|
|
|
98
98
|
|
|
99
99
|
#ifdef MRB_METHOD_TABLE_INLINE
|
|
100
100
|
|
|
101
|
-
#define MRB_METHOD_FUNC_FL ((uintptr_t)
|
|
102
|
-
#define MRB_METHOD_FUNC_P(m) ((uintptr_t)(m)&MRB_METHOD_FUNC_FL)
|
|
101
|
+
#define MRB_METHOD_FUNC_FL ((uintptr_t)1)
|
|
102
|
+
#define MRB_METHOD_FUNC_P(m) (((uintptr_t)(m))&MRB_METHOD_FUNC_FL)
|
|
103
103
|
#define MRB_METHOD_FUNC(m) ((mrb_func_t)((uintptr_t)(m)&(~MRB_METHOD_FUNC_FL)))
|
|
104
104
|
#define MRB_METHOD_FROM_FUNC(m,fn) m=(mrb_method_t)((struct RProc*)((uintptr_t)(fn)|MRB_METHOD_FUNC_FL))
|
|
105
105
|
#define MRB_METHOD_FROM_PROC(m,pr) m=(mrb_method_t)(struct RProc*)(pr)
|
|
@@ -829,22 +829,22 @@ MRB_API struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *o
|
|
|
829
829
|
*
|
|
830
830
|
* Must be a C string composed of the following format specifiers:
|
|
831
831
|
*
|
|
832
|
-
* | char | Ruby type | C types | Notes
|
|
832
|
+
* | char | Ruby type | C types | Notes |
|
|
833
833
|
* |:----:|----------------|-------------------|----------------------------------------------------|
|
|
834
834
|
* | `o` | {Object} | {mrb_value} | Could be used to retrieve any type of argument |
|
|
835
835
|
* | `C` | {Class}/{Module} | {mrb_value} | |
|
|
836
836
|
* | `S` | {String} | {mrb_value} | when `!` follows, the value may be `nil` |
|
|
837
837
|
* | `A` | {Array} | {mrb_value} | when `!` follows, the value may be `nil` |
|
|
838
838
|
* | `H` | {Hash} | {mrb_value} | when `!` follows, the value may be `nil` |
|
|
839
|
-
* | `s` | {String} | char *, {mrb_int} |
|
|
839
|
+
* | `s` | {String} | char *, {mrb_int} | Receive two arguments; `s!` gives (`NULL`,`0`) for `nil` |
|
|
840
840
|
* | `z` | {String} | char * | `NULL` terminated string; `z!` gives `NULL` for `nil` |
|
|
841
841
|
* | `a` | {Array} | {mrb_value} *, {mrb_int} | Receive two arguments; `a!` gives (`NULL`,`0`) for `nil` |
|
|
842
842
|
* | `f` | {Float} | {mrb_float} | |
|
|
843
843
|
* | `i` | {Integer} | {mrb_int} | |
|
|
844
844
|
* | `b` | boolean | {mrb_bool} | |
|
|
845
845
|
* | `n` | {Symbol} | {mrb_sym} | |
|
|
846
|
-
* | `&` | block | {mrb_value} |
|
|
847
|
-
* | `*` | rest arguments | {mrb_value} *, {mrb_int} | Receive the rest of arguments as an array. |
|
|
846
|
+
* | `&` | block | {mrb_value} | &! raises exception if no block given. |
|
|
847
|
+
* | `*` | rest arguments | {mrb_value} *, {mrb_int} | Receive the rest of arguments as an array; *! avoid copy of the stack. |
|
|
848
848
|
* | | | optional | | After this spec following specs would be optional. |
|
|
849
849
|
* | `?` | optional given | {mrb_bool} | `TRUE` if preceding argument is given. Used to check optional argument is given. |
|
|
850
850
|
*
|
|
@@ -1225,6 +1225,13 @@ MRB_API mrb_value mrb_fiber_resume(mrb_state *mrb, mrb_value fib, mrb_int argc,
|
|
|
1225
1225
|
*/
|
|
1226
1226
|
MRB_API mrb_value mrb_fiber_yield(mrb_state *mrb, mrb_int argc, const mrb_value *argv);
|
|
1227
1227
|
|
|
1228
|
+
/*
|
|
1229
|
+
* Check if a Fiber is alive
|
|
1230
|
+
*
|
|
1231
|
+
* @mrbgem mruby-fiber
|
|
1232
|
+
*/
|
|
1233
|
+
MRB_API mrb_value mrb_fiber_alive_p(mrb_state *mrb, mrb_value fib);
|
|
1234
|
+
|
|
1228
1235
|
/*
|
|
1229
1236
|
* FiberError reference
|
|
1230
1237
|
*
|
|
@@ -76,9 +76,6 @@ module MRuby
|
|
|
76
76
|
|
|
77
77
|
if params[:core]
|
|
78
78
|
gemdir = "#{root}/mrbgems/#{params[:core]}"
|
|
79
|
-
elsif params[:path]
|
|
80
|
-
require 'pathname'
|
|
81
|
-
gemdir = Pathname.new(params[:path]).absolute? ? params[:path] : "#{root}/#{params[:path]}"
|
|
82
79
|
elsif params[:git]
|
|
83
80
|
url = params[:git]
|
|
84
81
|
gemdir = "#{gem_clone_dir}/#{url.match(/([-\w]+)(\.[-\w]+|)$/).to_a[1]}"
|
|
@@ -108,6 +105,11 @@ module MRuby
|
|
|
108
105
|
# Jump to the top of the branch
|
|
109
106
|
git.run_checkout gemdir, branch if $pull_gems
|
|
110
107
|
end
|
|
108
|
+
|
|
109
|
+
gemdir << "/#{params[:path]}" if params[:path]
|
|
110
|
+
elsif params[:path]
|
|
111
|
+
require 'pathname'
|
|
112
|
+
gemdir = Pathname.new(params[:path]).absolute? ? params[:path] : "#{root}/#{params[:path]}"
|
|
111
113
|
else
|
|
112
114
|
fail "unknown gem option #{params}"
|
|
113
115
|
end
|
|
@@ -334,6 +334,7 @@ EOS
|
|
|
334
334
|
attr_accessor :host_target, :build_target
|
|
335
335
|
|
|
336
336
|
def initialize(name, build_dir=nil, &block)
|
|
337
|
+
@endian = nil
|
|
337
338
|
@test_runner = Command::CrossTestRunner.new(self)
|
|
338
339
|
super
|
|
339
340
|
end
|
|
@@ -343,6 +344,7 @@ EOS
|
|
|
343
344
|
end
|
|
344
345
|
|
|
345
346
|
def run_test
|
|
347
|
+
@test_runner.runner_options << ' -v' if $verbose
|
|
346
348
|
mrbtest = exefile("#{build_dir}/bin/mrbtest")
|
|
347
349
|
if (@test_runner.command == nil)
|
|
348
350
|
puts "You should run #{mrbtest} on target device."
|
|
@@ -351,5 +353,26 @@ EOS
|
|
|
351
353
|
@test_runner.run(mrbtest)
|
|
352
354
|
end
|
|
353
355
|
end
|
|
356
|
+
|
|
357
|
+
def big_endian
|
|
358
|
+
if @endian
|
|
359
|
+
puts "Endian has already specified as #{@endian}."
|
|
360
|
+
return
|
|
361
|
+
end
|
|
362
|
+
@endian = :big
|
|
363
|
+
@mrbc.compile_options += ' -E'
|
|
364
|
+
compilers.each do |c|
|
|
365
|
+
c.defines += %w(MRB_ENDIAN_BIG)
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
def little_endian
|
|
370
|
+
if @endian
|
|
371
|
+
puts "Endian has already specified as #{@endian}."
|
|
372
|
+
return
|
|
373
|
+
end
|
|
374
|
+
@endian = :little
|
|
375
|
+
@mrbc.compile_options += ' -e'
|
|
376
|
+
end
|
|
354
377
|
end # CrossBuild
|
|
355
378
|
end # MRuby
|
|
@@ -176,6 +176,7 @@ module MRuby
|
|
|
176
176
|
f.puts %Q[ mrb_load_irep(mrb, gem_mrblib_irep_#{funcname});]
|
|
177
177
|
f.puts %Q[ if (mrb->exc) {]
|
|
178
178
|
f.puts %Q[ mrb_print_error(mrb);]
|
|
179
|
+
f.puts %Q[ mrb_close(mrb);]
|
|
179
180
|
f.puts %Q[ exit(EXIT_FAILURE);]
|
|
180
181
|
f.puts %Q[ }]
|
|
181
182
|
end
|
|
@@ -323,20 +324,22 @@ module MRuby
|
|
|
323
324
|
@ary.empty?
|
|
324
325
|
end
|
|
325
326
|
|
|
327
|
+
def default_gem_params dep
|
|
328
|
+
if dep[:default]; dep
|
|
329
|
+
elsif File.exist? "#{MRUBY_ROOT}/mrbgems/#{dep[:gem]}" # check core
|
|
330
|
+
{ :gem => dep[:gem], :default => { :core => dep[:gem] } }
|
|
331
|
+
else # fallback to mgem-list
|
|
332
|
+
{ :gem => dep[:gem], :default => { :mgem => dep[:gem] } }
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
|
|
326
336
|
def generate_gem_table build
|
|
327
337
|
gem_table = @ary.reduce({}) { |res,v| res[v.name] = v; res }
|
|
328
338
|
|
|
329
339
|
default_gems = []
|
|
330
340
|
each do |g|
|
|
331
341
|
g.dependencies.each do |dep|
|
|
332
|
-
unless gem_table.key? dep[:gem]
|
|
333
|
-
if dep[:default]; default_gems << dep
|
|
334
|
-
elsif File.exist? "#{MRUBY_ROOT}/mrbgems/#{dep[:gem]}" # check core
|
|
335
|
-
default_gems << { :gem => dep[:gem], :default => { :core => dep[:gem] } }
|
|
336
|
-
else # fallback to mgem-list
|
|
337
|
-
default_gems << { :gem => dep[:gem], :default => { :mgem => dep[:gem] } }
|
|
338
|
-
end
|
|
339
|
-
end
|
|
342
|
+
default_gems << default_gem_params(dep) unless gem_table.key? dep[:gem]
|
|
340
343
|
end
|
|
341
344
|
end
|
|
342
345
|
|
|
@@ -348,11 +351,7 @@ module MRuby
|
|
|
348
351
|
spec.setup
|
|
349
352
|
|
|
350
353
|
spec.dependencies.each do |dep|
|
|
351
|
-
unless gem_table.key? dep[:gem]
|
|
352
|
-
if dep[:default]; default_gems << dep
|
|
353
|
-
else default_gems << { :gem => dep[:gem], :default => { :mgem => dep[:gem] } }
|
|
354
|
-
end
|
|
355
|
-
end
|
|
354
|
+
default_gems << default_gem_params(dep) unless gem_table.key? dep[:gem]
|
|
356
355
|
end
|
|
357
356
|
gem_table[spec.name] = spec
|
|
358
357
|
end
|
|
@@ -149,8 +149,14 @@ new_label(codegen_scope *s)
|
|
|
149
149
|
static inline int
|
|
150
150
|
genop(codegen_scope *s, mrb_code i)
|
|
151
151
|
{
|
|
152
|
-
if (s->pc
|
|
152
|
+
if (s->pc >= s->icapa) {
|
|
153
153
|
s->icapa *= 2;
|
|
154
|
+
if (s->pc >= MAXARG_sBx) {
|
|
155
|
+
codegen_error(s, "too big code block");
|
|
156
|
+
}
|
|
157
|
+
if (s->icapa > MAXARG_sBx) {
|
|
158
|
+
s->icapa = MAXARG_sBx;
|
|
159
|
+
}
|
|
154
160
|
s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
|
|
155
161
|
if (s->lines) {
|
|
156
162
|
s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(short)*s->icapa);
|
|
@@ -781,7 +781,7 @@ new_dxstr(parser_state *p, node *a)
|
|
|
781
781
|
static node*
|
|
782
782
|
new_dsym(parser_state *p, node *a)
|
|
783
783
|
{
|
|
784
|
-
return cons((node*)NODE_DSYM,
|
|
784
|
+
return cons((node*)NODE_DSYM, a);
|
|
785
785
|
}
|
|
786
786
|
|
|
787
787
|
/* (:regx . (s . (opt . enc))) */
|
|
@@ -1106,9 +1106,9 @@ heredoc_end(parser_state *p)
|
|
|
1106
1106
|
keyword__FILE__
|
|
1107
1107
|
keyword__ENCODING__
|
|
1108
1108
|
|
|
1109
|
-
%token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR
|
|
1109
|
+
%token <id> tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL_TAG
|
|
1110
1110
|
%token <nd> tINTEGER tFLOAT tCHAR tXSTRING tREGEXP
|
|
1111
|
-
%token <nd> tSTRING tSTRING_PART tSTRING_MID
|
|
1111
|
+
%token <nd> tSTRING tSTRING_PART tSTRING_MID
|
|
1112
1112
|
%token <nd> tNTH_REF tBACK_REF
|
|
1113
1113
|
%token <num> tREGEXP_END
|
|
1114
1114
|
|
|
@@ -1180,7 +1180,7 @@ heredoc_end(parser_state *p)
|
|
|
1180
1180
|
%right keyword_not
|
|
1181
1181
|
%right '=' tOP_ASGN
|
|
1182
1182
|
%left modifier_rescue
|
|
1183
|
-
%right '?' ':'
|
|
1183
|
+
%right '?' ':' tLABEL_TAG
|
|
1184
1184
|
%nonassoc tDOT2 tDOT3
|
|
1185
1185
|
%left tOROP
|
|
1186
1186
|
%left tANDOP
|
|
@@ -1926,6 +1926,10 @@ arg : lhs '=' arg_rhs
|
|
|
1926
1926
|
{
|
|
1927
1927
|
$$ = new_if(p, cond($1), $3, $6);
|
|
1928
1928
|
}
|
|
1929
|
+
| arg '?' arg opt_nl tLABEL_TAG arg
|
|
1930
|
+
{
|
|
1931
|
+
$$ = new_if(p, cond($1), $3, $6);
|
|
1932
|
+
}
|
|
1929
1933
|
| primary
|
|
1930
1934
|
{
|
|
1931
1935
|
$$ = $1;
|
|
@@ -2568,7 +2572,7 @@ lambda_body : tLAMBEG compstmt '}'
|
|
|
2568
2572
|
{
|
|
2569
2573
|
$$ = $2;
|
|
2570
2574
|
}
|
|
2571
|
-
| keyword_do_LAMBDA
|
|
2575
|
+
| keyword_do_LAMBDA bodystmt keyword_end
|
|
2572
2576
|
{
|
|
2573
2577
|
$$ = $2;
|
|
2574
2578
|
}
|
|
@@ -2861,7 +2865,7 @@ symbol : basic_symbol
|
|
|
2861
2865
|
| tSYMBEG tSTRING_BEG string_rep tSTRING
|
|
2862
2866
|
{
|
|
2863
2867
|
p->lstate = EXPR_ENDARG;
|
|
2864
|
-
$$ = new_dsym(p, push($3, $4));
|
|
2868
|
+
$$ = new_dsym(p, new_dstr(p, push($3, $4)));
|
|
2865
2869
|
}
|
|
2866
2870
|
;
|
|
2867
2871
|
|
|
@@ -3266,25 +3270,20 @@ assoc : arg tASSOC arg
|
|
|
3266
3270
|
void_expr_error(p, $3);
|
|
3267
3271
|
$$ = cons($1, $3);
|
|
3268
3272
|
}
|
|
3269
|
-
|
|
|
3270
|
-
{
|
|
3271
|
-
void_expr_error(p, $2);
|
|
3272
|
-
$$ = cons(new_sym(p, $1), $2);
|
|
3273
|
-
}
|
|
3274
|
-
| tLABEL_END arg
|
|
3275
|
-
{
|
|
3276
|
-
void_expr_error(p, $2);
|
|
3277
|
-
$$ = cons(new_sym(p, new_strsym(p, $1)), $2);
|
|
3278
|
-
}
|
|
3279
|
-
| tSTRING_BEG tLABEL_END arg
|
|
3273
|
+
| tIDENTIFIER tLABEL_TAG arg
|
|
3280
3274
|
{
|
|
3281
3275
|
void_expr_error(p, $3);
|
|
3282
|
-
$$ = cons(new_sym(p,
|
|
3276
|
+
$$ = cons(new_sym(p, $1), $3);
|
|
3283
3277
|
}
|
|
3284
|
-
|
|
|
3278
|
+
| string tLABEL_TAG arg
|
|
3285
3279
|
{
|
|
3286
|
-
void_expr_error(p, $
|
|
3287
|
-
|
|
3280
|
+
void_expr_error(p, $3);
|
|
3281
|
+
if ($1->car == (node*)NODE_DSTR) {
|
|
3282
|
+
$$ = cons(new_dsym(p, $1), $3);
|
|
3283
|
+
}
|
|
3284
|
+
else {
|
|
3285
|
+
$$ = cons(new_sym(p, new_strsym(p, $1)), $3);
|
|
3286
|
+
}
|
|
3288
3287
|
}
|
|
3289
3288
|
;
|
|
3290
3289
|
|
|
@@ -3973,7 +3972,6 @@ parse_string(parser_state *p)
|
|
|
3973
3972
|
int beg = intn(p->lex_strterm->cdr->cdr->car);
|
|
3974
3973
|
int end = intn(p->lex_strterm->cdr->cdr->cdr);
|
|
3975
3974
|
parser_heredoc_info *hinf = (type & STR_FUNC_HEREDOC) ? parsing_heredoc_inf(p) : NULL;
|
|
3976
|
-
int cmd_state = p->cmd_start;
|
|
3977
3975
|
|
|
3978
3976
|
if (beg == 0) beg = -3; /* should never happen */
|
|
3979
3977
|
if (end == 0) end = -3;
|
|
@@ -4188,13 +4186,6 @@ parse_string(parser_state *p)
|
|
|
4188
4186
|
return tREGEXP;
|
|
4189
4187
|
}
|
|
4190
4188
|
pylval.nd = new_str(p, tok(p), toklen(p));
|
|
4191
|
-
if (IS_LABEL_POSSIBLE()) {
|
|
4192
|
-
if (IS_LABEL_SUFFIX(0)) {
|
|
4193
|
-
p->lstate = EXPR_BEG;
|
|
4194
|
-
nextc(p);
|
|
4195
|
-
return tLABEL_END;
|
|
4196
|
-
}
|
|
4197
|
-
}
|
|
4198
4189
|
|
|
4199
4190
|
return tSTRING;
|
|
4200
4191
|
}
|
|
@@ -5012,14 +5003,19 @@ parser_yylex(parser_state *p)
|
|
|
5012
5003
|
p->lstate = EXPR_DOT;
|
|
5013
5004
|
return tCOLON2;
|
|
5014
5005
|
}
|
|
5015
|
-
if (
|
|
5006
|
+
if (!space_seen && IS_END()) {
|
|
5016
5007
|
pushback(p, c);
|
|
5017
5008
|
p->lstate = EXPR_BEG;
|
|
5018
|
-
return
|
|
5009
|
+
return tLABEL_TAG;
|
|
5010
|
+
}
|
|
5011
|
+
if (!ISSPACE(c) || IS_BEG()) {
|
|
5012
|
+
pushback(p, c);
|
|
5013
|
+
p->lstate = EXPR_FNAME;
|
|
5014
|
+
return tSYMBEG;
|
|
5019
5015
|
}
|
|
5020
5016
|
pushback(p, c);
|
|
5021
|
-
p->lstate =
|
|
5022
|
-
return
|
|
5017
|
+
p->lstate = EXPR_BEG;
|
|
5018
|
+
return ':';
|
|
5023
5019
|
|
|
5024
5020
|
case '/':
|
|
5025
5021
|
if (IS_BEG()) {
|
|
@@ -5443,11 +5439,10 @@ parser_yylex(parser_state *p)
|
|
|
5443
5439
|
|
|
5444
5440
|
if (IS_LABEL_POSSIBLE()) {
|
|
5445
5441
|
if (IS_LABEL_SUFFIX(0)) {
|
|
5446
|
-
p->lstate =
|
|
5447
|
-
nextc(p);
|
|
5442
|
+
p->lstate = EXPR_END;
|
|
5448
5443
|
tokfix(p);
|
|
5449
5444
|
pylval.id = intern_cstr(tok(p));
|
|
5450
|
-
return
|
|
5445
|
+
return tIDENTIFIER;
|
|
5451
5446
|
}
|
|
5452
5447
|
}
|
|
5453
5448
|
if (p->lstate != EXPR_DOT) {
|
|
@@ -201,7 +201,7 @@ module Enumerable
|
|
|
201
201
|
ary.push([block.call(e), i])
|
|
202
202
|
}
|
|
203
203
|
if ary.size > 1
|
|
204
|
-
__sort_sub__(
|
|
204
|
+
ary.__sort_sub__(0, ary.size - 1) do |a,b|
|
|
205
205
|
a <=> b
|
|
206
206
|
end
|
|
207
207
|
end
|
|
@@ -610,9 +610,7 @@ module Enumerable
|
|
|
610
610
|
# #=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
|
|
611
611
|
#
|
|
612
612
|
|
|
613
|
-
def each_with_object(obj
|
|
614
|
-
raise ArgumentError, "wrong number of arguments (0 for 1)" if obj.nil?
|
|
615
|
-
|
|
613
|
+
def each_with_object(obj, &block)
|
|
616
614
|
return to_enum(:each_with_object, obj) unless block
|
|
617
615
|
|
|
618
616
|
self.each {|*val| block.call(val.__svalue, obj) }
|
|
@@ -742,18 +740,39 @@ module Enumerable
|
|
|
742
740
|
##
|
|
743
741
|
# call-seq:
|
|
744
742
|
# enum.zip(arg, ...) -> an_array_of_array
|
|
743
|
+
# enum.zip(arg, ...) { |arr| block } -> nil
|
|
745
744
|
#
|
|
746
745
|
# Takes one element from <i>enum</i> and merges corresponding
|
|
747
746
|
# elements from each <i>args</i>. This generates a sequence of
|
|
748
747
|
# <em>n</em>-element arrays, where <em>n</em> is one more than the
|
|
749
748
|
# count of arguments. The length of the resulting sequence will be
|
|
750
749
|
# <code>enum#size</code>. If the size of any argument is less than
|
|
751
|
-
# <code>enum#size</code>, <code>nil</code> values are supplied.
|
|
750
|
+
# <code>enum#size</code>, <code>nil</code> values are supplied. If
|
|
751
|
+
# a block is given, it is invoked for each output array, otherwise
|
|
752
|
+
# an array of arrays is returned.
|
|
753
|
+
#
|
|
754
|
+
# a = [ 4, 5, 6 ]
|
|
755
|
+
# b = [ 7, 8, 9 ]
|
|
756
|
+
#
|
|
757
|
+
# a.zip(b) #=> [[4, 7], [5, 8], [6, 9]]
|
|
758
|
+
# [1, 2, 3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
|
|
759
|
+
# [1, 2].zip(a, b) #=> [[1, 4, 7], [2, 5, 8]]
|
|
760
|
+
# a.zip([1, 2], [8]) #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]
|
|
761
|
+
#
|
|
762
|
+
# c = []
|
|
763
|
+
# a.zip(b) { |x, y| c << x + y } #=> nil
|
|
764
|
+
# c #=> [11, 13, 15]
|
|
752
765
|
#
|
|
753
766
|
|
|
754
|
-
def zip(*arg)
|
|
755
|
-
|
|
756
|
-
arg = arg.map
|
|
767
|
+
def zip(*arg, &block)
|
|
768
|
+
result = block ? nil : []
|
|
769
|
+
arg = arg.map do |a|
|
|
770
|
+
unless a.respond_to?(:to_a)
|
|
771
|
+
raise TypeError, "wrong argument type #{a.class} (must respond to :to_a)"
|
|
772
|
+
end
|
|
773
|
+
a.to_a
|
|
774
|
+
end
|
|
775
|
+
|
|
757
776
|
i = 0
|
|
758
777
|
self.each do |*val|
|
|
759
778
|
a = []
|
|
@@ -763,10 +782,14 @@ module Enumerable
|
|
|
763
782
|
a.push(arg[idx][i])
|
|
764
783
|
idx += 1
|
|
765
784
|
end
|
|
766
|
-
ary.push(a)
|
|
767
785
|
i += 1
|
|
786
|
+
if result.nil?
|
|
787
|
+
block.call(a)
|
|
788
|
+
else
|
|
789
|
+
result.push(a)
|
|
790
|
+
end
|
|
768
791
|
end
|
|
769
|
-
|
|
792
|
+
result
|
|
770
793
|
end
|
|
771
794
|
|
|
772
795
|
##
|
|
@@ -166,6 +166,12 @@ assert("Enumerable#zip") do
|
|
|
166
166
|
assert_equal [[1, 4, 7], [2, 5, 8], [3, 6, 9]], [1, 2, 3].zip(a, b)
|
|
167
167
|
assert_equal [[1, 4, 7], [2, 5, 8]], [1, 2].zip(a, b)
|
|
168
168
|
assert_equal [[4, 1, 8], [5, 2, nil], [6, nil, nil]], a.zip([1, 2], [8])
|
|
169
|
+
|
|
170
|
+
ret = []
|
|
171
|
+
assert_equal nil, a.zip([1, 2], [8]) { |i| ret << i }
|
|
172
|
+
assert_equal [[4, 1, 8], [5, 2, nil], [6, nil, nil]], ret
|
|
173
|
+
|
|
174
|
+
assert_raise(TypeError) { [1].zip(1) }
|
|
169
175
|
end
|
|
170
176
|
|
|
171
177
|
assert("Enumerable#to_h") do
|
|
@@ -40,7 +40,7 @@ assert("Enumerator::Lazy laziness") do
|
|
|
40
40
|
assert_equal [10,20], a.b
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
assert("
|
|
43
|
+
assert("Enumerator::Lazy#to_enum") do
|
|
44
44
|
lazy_enum = (0..Float::INFINITY).lazy.to_enum(:each_slice, 2)
|
|
45
45
|
assert_kind_of Enumerator::Lazy, lazy_enum
|
|
46
46
|
assert_equal [0*1, 2*3, 4*5, 6*7], lazy_enum.map { |a| a.first * a.last }.first(4)
|
|
@@ -621,25 +621,40 @@ end
|
|
|
621
621
|
|
|
622
622
|
module Enumerable
|
|
623
623
|
# use Enumerator to use infinite sequence
|
|
624
|
-
def zip(*
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
624
|
+
def zip(*args, &block)
|
|
625
|
+
args = args.map do |a|
|
|
626
|
+
if a.respond_to?(:to_ary)
|
|
627
|
+
a.to_ary.to_enum(:each)
|
|
628
|
+
elsif a.respond_to?(:each)
|
|
629
|
+
a.to_enum(:each)
|
|
630
|
+
else
|
|
631
|
+
raise TypeError, "wrong argument type #{a.class} (must respond to :each)"
|
|
632
|
+
end
|
|
633
|
+
end
|
|
634
|
+
|
|
635
|
+
result = block ? nil : []
|
|
636
|
+
|
|
637
|
+
each do |*val|
|
|
638
|
+
tmp = [val.__svalue]
|
|
639
|
+
args.each do |arg|
|
|
640
|
+
v = if arg.nil?
|
|
641
|
+
nil
|
|
642
|
+
else
|
|
643
|
+
begin
|
|
644
|
+
arg.next
|
|
645
|
+
rescue StopIteration
|
|
646
|
+
nil
|
|
647
|
+
end
|
|
637
648
|
end
|
|
638
|
-
|
|
649
|
+
tmp.push(v)
|
|
650
|
+
end
|
|
651
|
+
if result.nil?
|
|
652
|
+
block.call(tmp)
|
|
653
|
+
else
|
|
654
|
+
result.push(tmp)
|
|
639
655
|
end
|
|
640
|
-
ary.push(a)
|
|
641
|
-
i += 1
|
|
642
656
|
end
|
|
643
|
-
|
|
657
|
+
|
|
658
|
+
result
|
|
644
659
|
end
|
|
645
660
|
end
|
|
@@ -544,3 +544,13 @@ assert 'Range#each' do
|
|
|
544
544
|
end
|
|
545
545
|
assert_equal [1,2,3,4,5], c
|
|
546
546
|
end
|
|
547
|
+
|
|
548
|
+
assert 'Enumerable#zip' do
|
|
549
|
+
assert_equal [[1, 10], [2, 11], [3, 12]], [1,2,3].zip(10..Float::INFINITY)
|
|
550
|
+
|
|
551
|
+
ret = []
|
|
552
|
+
assert_equal nil, [1,2,3].zip(10..Float::INFINITY) { |i| ret << i }
|
|
553
|
+
assert_equal [[1, 10], [2, 11], [3, 12]], ret
|
|
554
|
+
|
|
555
|
+
assert_raise(TypeError) { [1].zip(1) }
|
|
556
|
+
end
|
|
@@ -274,12 +274,13 @@ mrb_fiber_resume(mrb_state *mrb, mrb_value fib, mrb_int len, const mrb_value *a)
|
|
|
274
274
|
* Returns true if the fiber can still be resumed. After finishing
|
|
275
275
|
* execution of the fiber block this method will always return false.
|
|
276
276
|
*/
|
|
277
|
-
|
|
278
|
-
|
|
277
|
+
MRB_API mrb_value
|
|
278
|
+
mrb_fiber_alive_p(mrb_state *mrb, mrb_value self)
|
|
279
279
|
{
|
|
280
280
|
struct mrb_context *c = fiber_check(mrb, self);
|
|
281
281
|
return mrb_bool_value(c->status != MRB_FIBER_TERMINATED);
|
|
282
282
|
}
|
|
283
|
+
#define fiber_alive_p mrb_fiber_alive_p
|
|
283
284
|
|
|
284
285
|
static mrb_value
|
|
285
286
|
fiber_eq(mrb_state *mrb, mrb_value self)
|