summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/mruby/boxing_nan.h1
-rw-r--r--include/mruby/boxing_no.h5
-rw-r--r--include/mruby/boxing_word.h13
-rw-r--r--include/mruby/error.h6
-rw-r--r--include/mruby/object.h1
-rw-r--r--include/mruby/value.h13
-rw-r--r--mrbgems/mruby-array-ext/mrblib/array.rb14
-rw-r--r--mrbgems/mruby-array-ext/test/array.rb9
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c47
-rw-r--r--mrbgems/mruby-fiber/src/fiber.c19
10 files changed, 78 insertions, 50 deletions
diff --git a/include/mruby/boxing_nan.h b/include/mruby/boxing_nan.h
index 702fa13fb..4b47a3f17 100644
--- a/include/mruby/boxing_nan.h
+++ b/include/mruby/boxing_nan.h
@@ -20,7 +20,6 @@
#endif
#define MRB_FIXNUM_SHIFT 0
-#define MRB_TT_HAS_BASIC MRB_TT_OBJECT
#ifdef MRB_ENDIAN_BIG
#define MRB_ENDIAN_LOHI(a,b) a b
diff --git a/include/mruby/boxing_no.h b/include/mruby/boxing_no.h
index b22580bf6..19372b587 100644
--- a/include/mruby/boxing_no.h
+++ b/include/mruby/boxing_no.h
@@ -8,9 +8,8 @@
#define MRUBY_BOXING_NO_H
#define MRB_FIXNUM_SHIFT 0
-#define MRB_TT_HAS_BASIC MRB_TT_OBJECT
-union mrb_value_value {
+union mrb_value_union {
#ifndef MRB_WITHOUT_FLOAT
mrb_float f;
#endif
@@ -20,7 +19,7 @@ union mrb_value_value {
};
typedef struct mrb_value {
- union mrb_value_value value;
+ union mrb_value_union value;
enum mrb_vtype tt;
} mrb_value;
diff --git a/include/mruby/boxing_word.h b/include/mruby/boxing_word.h
index bd8105496..9e4ee456f 100644
--- a/include/mruby/boxing_word.h
+++ b/include/mruby/boxing_word.h
@@ -28,11 +28,6 @@ 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,
@@ -41,9 +36,10 @@ enum mrb_special_consts {
MRB_Qundef = 6,
};
-#define MRB_FIXNUM_FLAG 0x01
-#define MRB_SYMBOL_FLAG 0x0e
-#define MRB_SPECIAL_SHIFT 8
+#define MRB_IMMEDIATE_MASK 0x07
+#define MRB_FIXNUM_FLAG 0x01
+#define MRB_SYMBOL_FLAG 0x0e
+#define MRB_SPECIAL_SHIFT 8
#if defined(MRB_64BIT)
#define MRB_SYMBOL_BITSIZE (sizeof(mrb_sym) * CHAR_BIT)
@@ -113,6 +109,7 @@ mrb_type(mrb_value o)
}
#define mrb_bool(o) ((o).w != MRB_Qnil && (o).w != MRB_Qfalse)
+#define mrb_immediate_p(o) ((o).w & MRB_IMMEDIATE_MASK || (o).w == MRB_Qnil)
#define mrb_fixnum_p(o) ((o).value.i_flag == MRB_FIXNUM_FLAG)
#define mrb_undef_p(o) ((o).w == MRB_Qundef)
#define mrb_nil_p(o) ((o).w == MRB_Qnil)
diff --git a/include/mruby/error.h b/include/mruby/error.h
index 15855f96e..20090d197 100644
--- a/include/mruby/error.h
+++ b/include/mruby/error.h
@@ -44,21 +44,21 @@ struct RBreak {
struct RBreak {
MRB_OBJECT_HEADER;
struct RProc *proc;
- union mrb_value_value val_val;
+ union mrb_value_union value;
};
#define RBREAK_VALUE_TT_MASK ((1 << 8) - 1)
static inline mrb_value
mrb_break_value_get(struct RBreak *brk)
{
mrb_value val;
- val.value = brk->val_val;
+ val.value = brk->value;
val.tt = brk->flags & RBREAK_VALUE_TT_MASK;
return val;
}
static inline void
mrb_break_value_set(struct RBreak *brk, mrb_value val)
{
- brk->val_val = val.value;
+ brk->value = val.value;
brk->flags &= ~RBREAK_VALUE_TT_MASK;
brk->flags |= val.tt;
}
diff --git a/include/mruby/object.h b/include/mruby/object.h
index 1cb4ca6e8..53511a1bb 100644
--- a/include/mruby/object.h
+++ b/include/mruby/object.h
@@ -32,7 +32,6 @@ struct RObject {
};
#define mrb_obj_ptr(v) ((struct RObject*)(mrb_ptr(v)))
-#define mrb_immediate_p(x) (mrb_type(x) < MRB_TT_HAS_BASIC)
#define mrb_special_const_p(x) mrb_immediate_p(x)
struct RFiber {
diff --git a/include/mruby/value.h b/include/mruby/value.h
index 7dd3dbae2..d2b85078e 100644
--- a/include/mruby/value.h
+++ b/include/mruby/value.h
@@ -108,13 +108,13 @@ static const unsigned int IEEE754_INFINITY_BITS_SINGLE = 0x7F800000;
enum mrb_vtype {
MRB_TT_FALSE = 0, /* 0 */
- MRB_TT_FREE, /* 1 */
- MRB_TT_TRUE, /* 2 */
+ MRB_TT_TRUE, /* 1 */
+ MRB_TT_FLOAT, /* 2 */
MRB_TT_FIXNUM, /* 3 */
MRB_TT_SYMBOL, /* 4 */
MRB_TT_UNDEF, /* 5 */
- MRB_TT_FLOAT, /* 6 */
- MRB_TT_CPTR, /* 7 */
+ MRB_TT_CPTR, /* 6 */
+ MRB_TT_FREE, /* 7 */
MRB_TT_OBJECT, /* 8 */
MRB_TT_CLASS, /* 9 */
MRB_TT_MODULE, /* 10 */
@@ -161,6 +161,11 @@ typedef void mrb_value;
#include "boxing_no.h"
#endif
+#define MRB_TT_HAS_BASIC MRB_TT_FREE
+
+#ifndef mrb_immediate_p
+#define mrb_immediate_p(o) (mrb_type(o) < MRB_TT_HAS_BASIC)
+#endif
#ifndef mrb_fixnum_p
#define mrb_fixnum_p(o) (mrb_type(o) == MRB_TT_FIXNUM)
#endif
diff --git a/mrbgems/mruby-array-ext/mrblib/array.rb b/mrbgems/mruby-array-ext/mrblib/array.rb
index 1cd1eb643..fc5d87f2c 100644
--- a/mrbgems/mruby-array-ext/mrblib/array.rb
+++ b/mrbgems/mruby-array-ext/mrblib/array.rb
@@ -815,12 +815,11 @@ class Array
# 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
+ size = self.size
if n == 0
- yield []
- else
+ yield []
+ elsif 0 < n && n <= size
i = 0
while i<size
result = [self[i]]
@@ -835,6 +834,7 @@ class Array
i += 1
end
end
+ self
end
##
@@ -861,9 +861,8 @@ class Array
# 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
+ size = self.size
if n == 0
yield []
elsif n == 1
@@ -872,7 +871,7 @@ class Array
yield [self[i]]
i += 1
end
- else
+ elsif n <= size
i = 0
while i<size
result = [self[i]]
@@ -882,6 +881,7 @@ class Array
i += 1
end
end
+ self
end
##
diff --git a/mrbgems/mruby-array-ext/test/array.rb b/mrbgems/mruby-array-ext/test/array.rb
index 4fad42518..a4e328b71 100644
--- a/mrbgems/mruby-array-ext/test/array.rb
+++ b/mrbgems/mruby-array-ext/test/array.rb
@@ -3,8 +3,11 @@
def assert_permutation_combination(exp, receiver, meth, *args)
act = []
- receiver.__send__(meth, *args) { |v| act << v }
- assert_equal(exp, act.sort)
+ ret = receiver.__send__(meth, *args) { |v| act << v }
+ assert "assert_#{meth}" do
+ assert_equal(exp, act.sort)
+ assert_same(receiver, ret)
+ end
end
def assert_permutation(exp, receiver, *args)
@@ -389,6 +392,7 @@ assert("Array#permutation") do
assert_permutation([[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]], a, 3)
assert_permutation([[]], a, 0)
assert_permutation([], a, 4)
+ assert_permutation([], a, -1)
end
assert("Array#combination") do
@@ -399,6 +403,7 @@ assert("Array#combination") do
assert_combination([[1,2,3,4]], a, 4)
assert_combination([[]], a, 0)
assert_combination([], a, 5)
+ assert_combination([], a, -1)
end
assert('Array#transpose') do
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index d397ace8c..c0986893c 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -1558,7 +1558,7 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_IF:
{
- int pos1, pos2;
+ int pos1, pos2, nil_p = FALSE;
node *elsepart = tree->cdr->cdr->car;
if (!tree->car) {
@@ -1575,26 +1575,38 @@ codegen(codegen_scope *s, node *tree, int val)
case NODE_NIL:
codegen(s, elsepart, val);
goto exit;
+ case NODE_CALL:
+ {
+ node *n = tree->car->cdr;
+ mrb_sym mid = nsym(n->cdr->car);
+ mrb_sym mnil = mrb_intern_lit(s->mrb, "nil?");
+ if (mid == mnil && n->cdr->cdr->car == NULL) {
+ nil_p = TRUE;
+ codegen(s, n->car, VAL);
+ }
+ }
+ break;
+ }
+ if (!nil_p) {
+ codegen(s, tree->car, VAL);
}
- codegen(s, tree->car, VAL);
pop();
if (val || tree->cdr->car) {
- pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
- codegen(s, tree->cdr->car, val);
- if (elsepart) {
- if (val) pop();
- pos2 = genjmp(s, OP_JMP, 0);
- dispatch(s, pos1);
- codegen(s, elsepart, val);
+ if (nil_p) {
+ pos2 = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
+ pos1 = genjmp(s, OP_JMP, 0);
dispatch(s, pos2);
}
- else if (val) {
- pop();
+ else {
+ pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
+ }
+ codegen(s, tree->cdr->car, val);
+ if (val) pop();
+ if (elsepart || val) {
pos2 = genjmp(s, OP_JMP, 0);
dispatch(s, pos1);
- genop_1(s, OP_LOADNIL, cursp());
+ codegen(s, elsepart, val);
dispatch(s, pos2);
- push();
}
else {
dispatch(s, pos1);
@@ -1602,11 +1614,16 @@ codegen(codegen_scope *s, node *tree, int val)
}
else { /* empty then-part */
if (elsepart) {
- pos1 = genjmp2(s, OP_JMPIF, cursp(), 0, val);
+ if (nil_p) {
+ pos1 = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
+ }
+ else {
+ pos1 = genjmp2(s, OP_JMPIF, cursp(), 0, val);
+ }
codegen(s, elsepart, val);
dispatch(s, pos1);
}
- else if (val) {
+ else if (val && !nil_p) {
genop_1(s, OP_LOADNIL, cursp());
push();
}
diff --git a/mrbgems/mruby-fiber/src/fiber.c b/mrbgems/mruby-fiber/src/fiber.c
index 17ce77c5d..b702a3811 100644
--- a/mrbgems/mruby-fiber/src/fiber.c
+++ b/mrbgems/mruby-fiber/src/fiber.c
@@ -191,14 +191,21 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr
fiber_check_cfunc(mrb, c);
status = c->status;
- if (resume && status == MRB_FIBER_TRANSFERRED) {
- mrb_raise(mrb, E_FIBER_ERROR, "resuming transferred fiber");
- }
- if (status == MRB_FIBER_RUNNING || status == MRB_FIBER_RESUMED) {
+ switch (status) {
+ case MRB_FIBER_TRANSFERRED:
+ if (resume) {
+ mrb_raise(mrb, E_FIBER_ERROR, "resuming transferred fiber");
+ }
+ break;
+ case MRB_FIBER_RUNNING:
+ case MRB_FIBER_RESUMED:
mrb_raise(mrb, E_FIBER_ERROR, "double resume");
- }
- if (status == MRB_FIBER_TERMINATED) {
+ break;
+ case MRB_FIBER_TERMINATED:
mrb_raise(mrb, E_FIBER_ERROR, "resuming dead fiber");
+ break;
+ default:
+ break;
}
old_c->status = resume ? MRB_FIBER_RESUMED : MRB_FIBER_TRANSFERRED;
c->prev = resume ? mrb->c : (c->prev ? c->prev : mrb->root_c);