esruby 0.0.9 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|