mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge branch 'master' into fix_mruby-io_test
This commit is contained in:
@@ -102,6 +102,7 @@ codegen_error(codegen_scope *s, const char *message)
|
||||
while (s->prev) {
|
||||
codegen_scope *tmp = s->prev;
|
||||
mrb_free(s->mrb, s->iseq);
|
||||
mrb_free(s->mrb, s->lines);
|
||||
mrb_pool_close(s->mpool);
|
||||
s = tmp;
|
||||
}
|
||||
@@ -272,8 +273,7 @@ genop_W(codegen_scope *s, mrb_code i, uint32_t a)
|
||||
#define NOVAL 0
|
||||
#define VAL 1
|
||||
|
||||
//static
|
||||
mrb_bool
|
||||
static mrb_bool
|
||||
no_optimize(codegen_scope *s)
|
||||
{
|
||||
if (s && s->parser && s->parser->no_optimize)
|
||||
@@ -3020,6 +3020,9 @@ scope_finish(codegen_scope *s)
|
||||
mrb_state *mrb = s->mrb;
|
||||
mrb_irep *irep = s->irep;
|
||||
|
||||
if (s->nlocals >= 0x3ff) {
|
||||
codegen_error(s, "too many local variables");
|
||||
}
|
||||
irep->flags = 0;
|
||||
if (s->iseq) {
|
||||
irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
|
||||
|
||||
@@ -3716,8 +3716,9 @@ yyerror_c(parser_state *p, const char *msg, char c)
|
||||
{
|
||||
char buf[256];
|
||||
|
||||
strcpy(buf, msg);
|
||||
strcat(buf, &c);
|
||||
strncpy(buf, msg, sizeof(buf) - 2);
|
||||
buf[sizeof(buf) - 2] = '\0';
|
||||
strncat(buf, &c, 1);
|
||||
yyerror(p, buf);
|
||||
}
|
||||
|
||||
@@ -3760,9 +3761,10 @@ yywarning_s(parser_state *p, const char *msg, const char *s)
|
||||
{
|
||||
char buf[256];
|
||||
|
||||
strcpy(buf, msg);
|
||||
strcat(buf, ": ");
|
||||
strcat(buf, s);
|
||||
strncpy(buf, msg, sizeof(buf) - 1);
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
strncat(buf, ": ", sizeof(buf) - strlen(buf) - 1);
|
||||
strncat(buf, s, sizeof(buf) - strlen(buf) - 1);
|
||||
yywarning(p, buf);
|
||||
}
|
||||
|
||||
@@ -4326,11 +4328,12 @@ parse_string(parser_state *p)
|
||||
|
||||
if (sizeof(s1)+sizeof(s2)+strlen(hinf->term)+1 >= sizeof(buf)) {
|
||||
yyerror(p, "can't find heredoc delimiter anywhere before EOF");
|
||||
} else {
|
||||
strcpy(buf, s1);
|
||||
strcat(buf, hinf->term);
|
||||
strcat(buf, s2);
|
||||
yyerror(p, buf);
|
||||
}
|
||||
strcpy(buf, s1);
|
||||
strcat(buf, hinf->term);
|
||||
strcat(buf, s2);
|
||||
yyerror(p, buf);
|
||||
return 0;
|
||||
}
|
||||
pylval.nd = new_str(p, tok(p), toklen(p));
|
||||
@@ -4487,7 +4490,7 @@ parse_string(parser_state *p)
|
||||
strcat(msg, "s");
|
||||
}
|
||||
strcat(msg, " - ");
|
||||
strcat(msg, tok(p));
|
||||
strncat(msg, tok(p), sizeof(msg) - strlen(msg) - 1);
|
||||
yyerror(p, msg);
|
||||
}
|
||||
if (f != 0) {
|
||||
@@ -4918,7 +4921,7 @@ parser_yylex(parser_state *p)
|
||||
char cc = (char)c2;
|
||||
|
||||
strcpy(buf, "invalid character syntax; use ?\\");
|
||||
strcat(buf, &cc);
|
||||
strncat(buf, &cc, 1);
|
||||
yyerror(p, buf);
|
||||
}
|
||||
}
|
||||
@@ -5709,11 +5712,12 @@ parser_yylex(parser_state *p)
|
||||
if (!identchar(c)) {
|
||||
char buf[36];
|
||||
const char s[] = "Invalid char in expression: 0x";
|
||||
const char hexdigits[] = "0123456789ABCDEF";
|
||||
|
||||
strcpy(buf, s);
|
||||
buf[sizeof(s)] = (c & 0xff00) >> 8;
|
||||
buf[sizeof(s)+1] = (c & 0xff);
|
||||
buf[sizeof(s)+2] = 0;
|
||||
buf[sizeof(s)-1] = hexdigits[(c & 0xf0) >> 4];
|
||||
buf[sizeof(s)] = hexdigits[(c & 0x0f)];
|
||||
buf[sizeof(s)+1] = 0;
|
||||
yyerror(p, buf);
|
||||
goto retry;
|
||||
}
|
||||
@@ -6147,7 +6151,7 @@ mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c)
|
||||
strcpy(buf, "line ");
|
||||
dump_int(p->error_buffer[0].lineno, buf+5);
|
||||
strcat(buf, ": ");
|
||||
strcat(buf, p->error_buffer[0].message);
|
||||
strncat(buf, p->error_buffer[0].message, sizeof(buf) - strlen(buf) - 1);
|
||||
mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, strlen(buf)));
|
||||
mrb_parser_free(p);
|
||||
return mrb_undef_value();
|
||||
|
||||
@@ -1,48 +1,66 @@
|
||||
##
|
||||
# Random Test
|
||||
|
||||
assert("Random#srand") do
|
||||
assert("Random.new") do
|
||||
r1 = Random.new(123)
|
||||
r2 = Random.new(123)
|
||||
r1.rand == r2.rand
|
||||
r3 = Random.new(124)
|
||||
assert_equal(r1.rand, r2.rand)
|
||||
assert_not_equal(r1.rand, r3.rand)
|
||||
end
|
||||
|
||||
assert("Kernel::srand") do
|
||||
assert("Kernel.srand") do
|
||||
srand(234)
|
||||
r1 = rand
|
||||
srand(234)
|
||||
r2 = rand
|
||||
r1 == r2
|
||||
srand(235)
|
||||
r3 = rand
|
||||
assert_equal(r1, r2)
|
||||
assert_not_equal(r1, r3)
|
||||
end
|
||||
|
||||
assert("Random::srand") do
|
||||
assert("Random.srand") do
|
||||
Random.srand(345)
|
||||
r1 = rand
|
||||
srand(345)
|
||||
r2 = Random.rand
|
||||
r1 == r2
|
||||
Random.srand(346)
|
||||
r3 = rand
|
||||
assert_equal(r1, r2)
|
||||
assert_not_equal(r1, r3)
|
||||
end
|
||||
|
||||
assert("fixnum") do
|
||||
rand(3).class == Fixnum
|
||||
end
|
||||
|
||||
assert("float") do
|
||||
rand.class == Float
|
||||
assert("return class of Kernel.rand") do
|
||||
assert_kind_of(Fixnum, rand(3))
|
||||
assert_kind_of(Fixnum, rand(1.5))
|
||||
assert_kind_of(Float, rand)
|
||||
assert_kind_of(Float, rand(0.5))
|
||||
end
|
||||
|
||||
assert("Array#shuffle") do
|
||||
ary = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
orig = ary.dup
|
||||
shuffled = ary.shuffle
|
||||
|
||||
ary == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and shuffled != ary and 10.times { |x| ary.include? x }
|
||||
assert_equal(orig, ary)
|
||||
assert_not_equal(ary, shuffled)
|
||||
assert_equal(ary.size, shuffled.size)
|
||||
shuffled.each do |x|
|
||||
assert_include(ary, x)
|
||||
ary.delete(x)
|
||||
end
|
||||
end
|
||||
|
||||
assert('Array#shuffle!') do
|
||||
ary = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
ary.shuffle!
|
||||
|
||||
ary != [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and 10.times { |x| ary.include? x }
|
||||
orig = ary.dup
|
||||
assert_same(ary, ary.shuffle!)
|
||||
assert_not_equal(orig, ary)
|
||||
assert_equal(orig.size, ary.size)
|
||||
ary.each do |x|
|
||||
assert_include(orig, x)
|
||||
orig.delete(x)
|
||||
end
|
||||
end
|
||||
|
||||
assert("Array#shuffle(random)") do
|
||||
@@ -52,12 +70,12 @@ assert("Array#shuffle(random)") do
|
||||
end
|
||||
|
||||
# verify that the same seed causes the same results
|
||||
ary1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
shuffle1 = ary1.shuffle Random.new 345
|
||||
ary2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
shuffle2 = ary2.shuffle Random.new 345
|
||||
|
||||
ary1 != shuffle1 and 10.times { |x| shuffle1.include? x } and shuffle1 == shuffle2
|
||||
ary = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
shuffled1 = ary.shuffle Random.new 345
|
||||
shuffled2 = ary.shuffle Random.new 345
|
||||
shuffled3 = ary.shuffle Random.new 346
|
||||
assert_equal(shuffled1, shuffled2)
|
||||
assert_not_equal(shuffled1, shuffled3)
|
||||
end
|
||||
|
||||
assert('Array#shuffle!(random)') do
|
||||
@@ -71,6 +89,8 @@ assert('Array#shuffle!(random)') do
|
||||
ary1.shuffle! Random.new 345
|
||||
ary2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
ary2.shuffle! Random.new 345
|
||||
|
||||
ary1 != [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and 10.times { |x| ary1.include? x } and ary1 == ary2
|
||||
ary3 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
ary3.shuffle! Random.new 346
|
||||
assert_equal(ary1, ary2)
|
||||
assert_not_equal(ary1, ary3)
|
||||
end
|
||||
|
||||
@@ -205,7 +205,6 @@ mrb_regexp_p(mrb_state *mrb, mrb_value v)
|
||||
return mrb_obj_is_kind_of(mrb, v, mrb_class_get(mrb, REGEXP_CLASS));
|
||||
}
|
||||
else {
|
||||
mrb->flags |= MRB_STATE_REGEXP;
|
||||
mrb->flags |= MRB_STATE_NO_REGEXP;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <mruby/array.h>
|
||||
#include <mruby/class.h>
|
||||
#include <mruby/data.h>
|
||||
#include <mruby/istruct.h>
|
||||
#include <mruby/hash.h>
|
||||
#include <mruby/proc.h>
|
||||
#include <mruby/range.h>
|
||||
@@ -109,8 +110,10 @@ typedef struct {
|
||||
struct RHash hash;
|
||||
struct RRange range;
|
||||
struct RData data;
|
||||
struct RIstruct istruct;
|
||||
struct RProc proc;
|
||||
struct REnv env;
|
||||
struct RFiber fiber;
|
||||
struct RException exc;
|
||||
struct RBreak brk;
|
||||
#ifdef MRB_WORD_BOXING
|
||||
@@ -396,7 +399,7 @@ mrb_gc_init(mrb_state *mrb, mrb_gc *gc)
|
||||
|
||||
static void obj_free(mrb_state *mrb, struct RBasic *obj, int end);
|
||||
|
||||
void
|
||||
static void
|
||||
free_heap(mrb_state *mrb, mrb_gc *gc)
|
||||
{
|
||||
mrb_heap_page *page = gc->heaps;
|
||||
|
||||
+1
-1
@@ -182,7 +182,7 @@ ht_index(mrb_state *mrb, htable *t)
|
||||
if (!index || index->capa < size) {
|
||||
index = (segindex*)mrb_realloc_simple(mrb, index, sizeof(segindex)+sizeof(struct segkv*)*size);
|
||||
if (index == NULL) {
|
||||
mrb_free(mrb, index);
|
||||
mrb_free(mrb, t->index);
|
||||
t->index = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
+4
-4
@@ -510,7 +510,7 @@ flo_shift(mrb_state *mrb, mrb_value x, mrb_int width)
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
flo_lshift(mrb_state *mrb, mrb_value x)
|
||||
flo_rshift(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_int width;
|
||||
|
||||
@@ -519,7 +519,7 @@ flo_lshift(mrb_state *mrb, mrb_value x)
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
flo_rshift(mrb_state *mrb, mrb_value x)
|
||||
flo_lshift(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_int width;
|
||||
|
||||
@@ -1608,8 +1608,8 @@ mrb_init_numeric(mrb_state *mrb)
|
||||
mrb_define_method(mrb, fl, "&", flo_and, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, fl, "|", flo_or, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, fl, "^", flo_xor, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, fl, ">>", flo_lshift, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, fl, "<<", flo_rshift, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, fl, ">>", flo_rshift, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, fl, "<<", flo_lshift, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, fl, "ceil", flo_ceil, MRB_ARGS_NONE()); /* 15.2.9.3.8 */
|
||||
mrb_define_method(mrb, fl, "finite?", flo_finite_p, MRB_ARGS_NONE()); /* 15.2.9.3.9 */
|
||||
mrb_define_method(mrb, fl, "floor", flo_floor, MRB_ARGS_NONE()); /* 15.2.9.3.10 */
|
||||
|
||||
+1
-1
@@ -91,7 +91,7 @@ sym_inline_unpack(mrb_sym sym, char *buf, mrb_int *lenp)
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t
|
||||
static uint8_t
|
||||
symhash(const char *key, size_t len)
|
||||
{
|
||||
uint32_t hash, i;
|
||||
|
||||
+2
-2
@@ -79,19 +79,19 @@ iv_put(mrb_state *mrb, iv_tbl *t, mrb_sym sym, mrb_value val)
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
t->size++;
|
||||
if (matched_seg) {
|
||||
matched_seg->key[matched_idx] = sym;
|
||||
matched_seg->val[matched_idx] = val;
|
||||
t->size++;
|
||||
return;
|
||||
}
|
||||
|
||||
seg = (segment*)mrb_malloc(mrb, sizeof(segment));
|
||||
if (!seg) return;
|
||||
seg->next = NULL;
|
||||
seg->key[0] = sym;
|
||||
seg->val[0] = val;
|
||||
t->last_len = 1;
|
||||
t->size++;
|
||||
if (prev) {
|
||||
prev->next = seg;
|
||||
}
|
||||
|
||||
@@ -486,6 +486,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
|
||||
ci->argc = (int)argc;
|
||||
ci->target_class = c;
|
||||
mrb->c->stack = mrb->c->stack + n;
|
||||
if (argc < 0) argc = 1;
|
||||
if (mrb->c->stbase <= argv && argv < mrb->c->stend) {
|
||||
voff = argv - mrb->c->stbase;
|
||||
}
|
||||
@@ -500,11 +501,10 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
|
||||
ci->argc = -1;
|
||||
argc = 1;
|
||||
}
|
||||
else {
|
||||
else if (MRB_METHOD_PROC_P(m)) {
|
||||
struct RProc *p = MRB_METHOD_PROC(m);
|
||||
|
||||
ci->proc = p;
|
||||
if (argc < 0) argc = 1;
|
||||
mrb_stack_extend(mrb, p->body.irep->nregs + argc);
|
||||
}
|
||||
if (voff >= 0) {
|
||||
@@ -520,9 +520,6 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc
|
||||
int ai = mrb_gc_arena_save(mrb);
|
||||
|
||||
ci->acc = CI_ACC_DIRECT;
|
||||
if (MRB_METHOD_PROC_P(m)) {
|
||||
ci->proc = MRB_METHOD_PROC(m);
|
||||
}
|
||||
val = MRB_METHOD_CFUNC(m)(mrb, self);
|
||||
mrb->c->stack = mrb->c->ci->stackent;
|
||||
cipop(mrb);
|
||||
@@ -2217,184 +2214,67 @@ RETRY_TRY_BLOCK:
|
||||
}
|
||||
|
||||
#define TYPES2(a,b) ((((uint16_t)(a))<<8)|(((uint16_t)(b))&0xff))
|
||||
#define OP_MATH_BODY(op,v1,v2) do {\
|
||||
v1(regs[a]) = v1(regs[a]) op v2(regs[a+1]);\
|
||||
} while(0)
|
||||
#define OP_MATH(op_name) \
|
||||
/* need to check if op is overridden */ \
|
||||
switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) { \
|
||||
OP_MATH_CASE_FIXNUM(op_name); \
|
||||
OP_MATH_CASE_FLOAT(op_name, fixnum, float); \
|
||||
OP_MATH_CASE_FLOAT(op_name, float, fixnum); \
|
||||
OP_MATH_CASE_FLOAT(op_name, float, float); \
|
||||
OP_MATH_CASE_STRING_##op_name(); \
|
||||
default: \
|
||||
c = 1; \
|
||||
mid = mrb_intern_lit(mrb, MRB_STRINGIZE(OP_MATH_OP_##op_name)); \
|
||||
goto L_SEND_SYM; \
|
||||
} \
|
||||
NEXT;
|
||||
#define OP_MATH_CASE_FIXNUM(op_name) \
|
||||
case TYPES2(MRB_TT_FIXNUM, MRB_TT_FIXNUM): \
|
||||
{ \
|
||||
mrb_int x = mrb_fixnum(regs[a]), y = mrb_fixnum(regs[a+1]), z; \
|
||||
if (mrb_int_##op_name##_overflow(x, y, &z)) \
|
||||
OP_MATH_OVERFLOW_INT(op_name, x, y, z); \
|
||||
else \
|
||||
SET_INT_VALUE(regs[a], z); \
|
||||
} \
|
||||
break
|
||||
#ifdef MRB_WITHOUT_FLOAT
|
||||
#define OP_MATH_CASE_FLOAT(op_name, t1, t2) (void)0
|
||||
#define OP_MATH_OVERFLOW_INT(op_name, x, y, z) SET_INT_VALUE(regs[a], z)
|
||||
#else
|
||||
#define OP_MATH_CASE_FLOAT(op_name, t1, t2) \
|
||||
case TYPES2(OP_MATH_TT_##t1, OP_MATH_TT_##t2): \
|
||||
{ \
|
||||
mrb_float z = mrb_##t1(regs[a]) OP_MATH_OP_##op_name mrb_##t2(regs[a+1]); \
|
||||
SET_FLOAT_VALUE(mrb, regs[a], z); \
|
||||
} \
|
||||
break
|
||||
#define OP_MATH_OVERFLOW_INT(op_name, x, y, z) \
|
||||
SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x OP_MATH_OP_##op_name (mrb_float)y)
|
||||
#endif
|
||||
#define OP_MATH_CASE_STRING_add() \
|
||||
case TYPES2(MRB_TT_STRING, MRB_TT_STRING): \
|
||||
regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]); \
|
||||
mrb_gc_arena_restore(mrb, ai); \
|
||||
break
|
||||
#define OP_MATH_CASE_STRING_sub() (void)0
|
||||
#define OP_MATH_CASE_STRING_mul() (void)0
|
||||
#define OP_MATH_OP_add +
|
||||
#define OP_MATH_OP_sub -
|
||||
#define OP_MATH_OP_mul *
|
||||
#define OP_MATH_TT_fixnum MRB_TT_FIXNUM
|
||||
#define OP_MATH_TT_float MRB_TT_FLOAT
|
||||
|
||||
CASE(OP_ADD, B) {
|
||||
/* need to check if op is overridden */
|
||||
switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
|
||||
case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
|
||||
{
|
||||
mrb_int x, y, z;
|
||||
mrb_value *regs_a = regs + a;
|
||||
|
||||
x = mrb_fixnum(regs_a[0]);
|
||||
y = mrb_fixnum(regs_a[1]);
|
||||
if (mrb_int_add_overflow(x, y, &z)) {
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x + (mrb_float)y);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
SET_INT_VALUE(regs[a], z);
|
||||
}
|
||||
break;
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
|
||||
{
|
||||
mrb_int x = mrb_fixnum(regs[a]);
|
||||
mrb_float y = mrb_float(regs[a+1]);
|
||||
SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + y);
|
||||
}
|
||||
break;
|
||||
case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
|
||||
#ifdef MRB_WORD_BOXING
|
||||
{
|
||||
mrb_float x = mrb_float(regs[a]);
|
||||
mrb_int y = mrb_fixnum(regs[a+1]);
|
||||
SET_FLOAT_VALUE(mrb, regs[a], x + y);
|
||||
}
|
||||
#else
|
||||
OP_MATH_BODY(+,mrb_float,mrb_fixnum);
|
||||
#endif
|
||||
break;
|
||||
case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
|
||||
#ifdef MRB_WORD_BOXING
|
||||
{
|
||||
mrb_float x = mrb_float(regs[a]);
|
||||
mrb_float y = mrb_float(regs[a+1]);
|
||||
SET_FLOAT_VALUE(mrb, regs[a], x + y);
|
||||
}
|
||||
#else
|
||||
OP_MATH_BODY(+,mrb_float,mrb_float);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
case TYPES2(MRB_TT_STRING,MRB_TT_STRING):
|
||||
regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]);
|
||||
break;
|
||||
default:
|
||||
c = 1;
|
||||
mid = mrb_intern_lit(mrb, "+");
|
||||
goto L_SEND_SYM;
|
||||
}
|
||||
mrb_gc_arena_restore(mrb, ai);
|
||||
NEXT;
|
||||
OP_MATH(add);
|
||||
}
|
||||
|
||||
CASE(OP_SUB, B) {
|
||||
/* need to check if op is overridden */
|
||||
switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
|
||||
case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
|
||||
{
|
||||
mrb_int x, y, z;
|
||||
|
||||
x = mrb_fixnum(regs[a]);
|
||||
y = mrb_fixnum(regs[a+1]);
|
||||
if (mrb_int_sub_overflow(x, y, &z)) {
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - (mrb_float)y);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
SET_INT_VALUE(regs[a], z);
|
||||
}
|
||||
break;
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
|
||||
{
|
||||
mrb_int x = mrb_fixnum(regs[a]);
|
||||
mrb_float y = mrb_float(regs[a+1]);
|
||||
SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - y);
|
||||
}
|
||||
break;
|
||||
case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
|
||||
#ifdef MRB_WORD_BOXING
|
||||
{
|
||||
mrb_float x = mrb_float(regs[a]);
|
||||
mrb_int y = mrb_fixnum(regs[a+1]);
|
||||
SET_FLOAT_VALUE(mrb, regs[a], x - y);
|
||||
}
|
||||
#else
|
||||
OP_MATH_BODY(-,mrb_float,mrb_fixnum);
|
||||
#endif
|
||||
break;
|
||||
case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
|
||||
#ifdef MRB_WORD_BOXING
|
||||
{
|
||||
mrb_float x = mrb_float(regs[a]);
|
||||
mrb_float y = mrb_float(regs[a+1]);
|
||||
SET_FLOAT_VALUE(mrb, regs[a], x - y);
|
||||
}
|
||||
#else
|
||||
OP_MATH_BODY(-,mrb_float,mrb_float);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
c = 1;
|
||||
mid = mrb_intern_lit(mrb, "-");
|
||||
goto L_SEND_SYM;
|
||||
}
|
||||
NEXT;
|
||||
OP_MATH(sub);
|
||||
}
|
||||
|
||||
CASE(OP_MUL, B) {
|
||||
/* need to check if op is overridden */
|
||||
switch (TYPES2(mrb_type(regs[a]),mrb_type(regs[a+1]))) {
|
||||
case TYPES2(MRB_TT_FIXNUM,MRB_TT_FIXNUM):
|
||||
{
|
||||
mrb_int x, y, z;
|
||||
|
||||
x = mrb_fixnum(regs[a]);
|
||||
y = mrb_fixnum(regs[a+1]);
|
||||
if (mrb_int_mul_overflow(x, y, &z)) {
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x * (mrb_float)y);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
SET_INT_VALUE(regs[a], z);
|
||||
}
|
||||
break;
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT):
|
||||
{
|
||||
mrb_int x = mrb_fixnum(regs[a]);
|
||||
mrb_float y = mrb_float(regs[a+1]);
|
||||
SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x * y);
|
||||
}
|
||||
break;
|
||||
case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM):
|
||||
#ifdef MRB_WORD_BOXING
|
||||
{
|
||||
mrb_float x = mrb_float(regs[a]);
|
||||
mrb_int y = mrb_fixnum(regs[a+1]);
|
||||
SET_FLOAT_VALUE(mrb, regs[a], x * y);
|
||||
}
|
||||
#else
|
||||
OP_MATH_BODY(*,mrb_float,mrb_fixnum);
|
||||
#endif
|
||||
break;
|
||||
case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT):
|
||||
#ifdef MRB_WORD_BOXING
|
||||
{
|
||||
mrb_float x = mrb_float(regs[a]);
|
||||
mrb_float y = mrb_float(regs[a+1]);
|
||||
SET_FLOAT_VALUE(mrb, regs[a], x * y);
|
||||
}
|
||||
#else
|
||||
OP_MATH_BODY(*,mrb_float,mrb_float);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
c = 1;
|
||||
mid = mrb_intern_lit(mrb, "*");
|
||||
goto L_SEND_SYM;
|
||||
}
|
||||
NEXT;
|
||||
OP_MATH(mul);
|
||||
}
|
||||
|
||||
CASE(OP_DIV, B) {
|
||||
@@ -2449,84 +2329,46 @@ RETRY_TRY_BLOCK:
|
||||
NEXT;
|
||||
}
|
||||
|
||||
CASE(OP_ADDI, BB) {
|
||||
/* need to check if + is overridden */
|
||||
switch (mrb_type(regs[a])) {
|
||||
case MRB_TT_FIXNUM:
|
||||
{
|
||||
mrb_int x = mrb_fixnum(regs[a]);
|
||||
mrb_int y = (mrb_int)b;
|
||||
mrb_int z;
|
||||
|
||||
if (mrb_int_add_overflow(x, y, &z)) {
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x + (mrb_float)y);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
SET_INT_VALUE(regs[a], z);
|
||||
}
|
||||
break;
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
case MRB_TT_FLOAT:
|
||||
#ifdef MRB_WORD_BOXING
|
||||
{
|
||||
mrb_float x = mrb_float(regs[a]);
|
||||
SET_FLOAT_VALUE(mrb, regs[a], x + b);
|
||||
}
|
||||
#define OP_MATHI(op_name) \
|
||||
/* need to check if op is overridden */ \
|
||||
switch (mrb_type(regs[a])) { \
|
||||
OP_MATHI_CASE_FIXNUM(op_name); \
|
||||
OP_MATHI_CASE_FLOAT(op_name); \
|
||||
default: \
|
||||
SET_INT_VALUE(regs[a+1], b); \
|
||||
c = 1; \
|
||||
mid = mrb_intern_lit(mrb, MRB_STRINGIZE(OP_MATH_OP_##op_name)); \
|
||||
goto L_SEND_SYM; \
|
||||
} \
|
||||
NEXT;
|
||||
#define OP_MATHI_CASE_FIXNUM(op_name) \
|
||||
case MRB_TT_FIXNUM: \
|
||||
{ \
|
||||
mrb_int x = mrb_fixnum(regs[a]), y = (mrb_int)b, z; \
|
||||
if (mrb_int_##op_name##_overflow(x, y, &z)) \
|
||||
OP_MATH_OVERFLOW_INT(op_name, x, y, z); \
|
||||
else \
|
||||
SET_INT_VALUE(regs[a], z); \
|
||||
} \
|
||||
break
|
||||
#ifdef MRB_WITHOUT_FLOAT
|
||||
#define OP_MATHI_CASE_FLOAT(op_name) (void)0
|
||||
#else
|
||||
mrb_float(regs[a]) += b;
|
||||
#define OP_MATHI_CASE_FLOAT(op_name) \
|
||||
case MRB_TT_FLOAT: \
|
||||
{ \
|
||||
mrb_float z = mrb_float(regs[a]) OP_MATH_OP_##op_name b; \
|
||||
SET_FLOAT_VALUE(mrb, regs[a], z); \
|
||||
} \
|
||||
break
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
SET_INT_VALUE(regs[a+1], b);
|
||||
c = 1;
|
||||
mid = mrb_intern_lit(mrb, "+");
|
||||
goto L_SEND_SYM;
|
||||
}
|
||||
NEXT;
|
||||
|
||||
CASE(OP_ADDI, BB) {
|
||||
OP_MATHI(add);
|
||||
}
|
||||
|
||||
CASE(OP_SUBI, BB) {
|
||||
mrb_value *regs_a = regs + a;
|
||||
|
||||
/* need to check if + is overridden */
|
||||
switch (mrb_type(regs_a[0])) {
|
||||
case MRB_TT_FIXNUM:
|
||||
{
|
||||
mrb_int x = mrb_fixnum(regs_a[0]);
|
||||
mrb_int y = (mrb_int)b;
|
||||
mrb_int z;
|
||||
|
||||
if (mrb_int_sub_overflow(x, y, &z)) {
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
SET_FLOAT_VALUE(mrb, regs_a[0], (mrb_float)x - (mrb_float)y);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
SET_INT_VALUE(regs_a[0], z);
|
||||
}
|
||||
break;
|
||||
#ifndef MRB_WITHOUT_FLOAT
|
||||
case MRB_TT_FLOAT:
|
||||
#ifdef MRB_WORD_BOXING
|
||||
{
|
||||
mrb_float x = mrb_float(regs[a]);
|
||||
SET_FLOAT_VALUE(mrb, regs[a], (mrb_float)x - (mrb_float)b);
|
||||
}
|
||||
#else
|
||||
mrb_float(regs_a[0]) -= b;
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
SET_INT_VALUE(regs_a[1], b);
|
||||
c = 1;
|
||||
mid = mrb_intern_lit(mrb, "-");
|
||||
goto L_SEND_SYM;
|
||||
}
|
||||
NEXT;
|
||||
OP_MATHI(sub);
|
||||
}
|
||||
|
||||
#define OP_CMP_BODY(op,v1,v2) (v1(regs[a]) op v2(regs[a+1]))
|
||||
|
||||
+3
-3
@@ -149,11 +149,11 @@ end
|
||||
# Fails unless +exp+ is equal to +act+ in terms of a Float
|
||||
def assert_float(exp, act, msg = nil)
|
||||
e, a = exp.to_f, act.to_f
|
||||
if (e.infinite? || a.infinite?) && e != a ||
|
||||
if e.finite? && a.finite? && (n = (e - a).abs) > Mrbtest::FLOAT_TOLERANCE
|
||||
flunk(msg, " Expected |#{exp} - #{act}| (#{n}) to be <= #{Mrbtest::FLOAT_TOLERANCE}.")
|
||||
elsif (e.infinite? || a.infinite?) && e != a ||
|
||||
e.nan? && !a.nan? || !e.nan? && a.nan?
|
||||
flunk(msg, " Expected #{act} to be #{exp}.")
|
||||
elsif (n = (e - a).abs) > Mrbtest::FLOAT_TOLERANCE
|
||||
flunk(msg, " Expected |#{exp} - #{act}| (#{n}) to be <= #{Mrbtest::FLOAT_TOLERANCE}.")
|
||||
else
|
||||
pass
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user