Commit cdfeb538 authored by Shokuji's avatar Shokuji

Merge branch 'master' into fix_mruby-io_test

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