summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile13
-rw-r--r--src/array.c7
-rw-r--r--src/class.c44
-rw-r--r--src/codegen.c1
-rw-r--r--src/compile.h8
-rw-r--r--src/error.c1
-rw-r--r--src/etc.c20
-rw-r--r--src/eval_intern.h223
-rw-r--r--src/gc.c38
-rw-r--r--src/gc.h12
-rw-r--r--src/hash.c116
-rw-r--r--src/init.c1
-rw-r--r--src/kernel.c16
-rw-r--r--src/object.c2
-rw-r--r--src/parse.y44
-rw-r--r--src/proc.c2
-rw-r--r--src/range.c17
-rw-r--r--src/re.c94
-rw-r--r--src/re.h10
-rw-r--r--src/string.c6
-rw-r--r--src/time.c679
-rw-r--r--src/variable.c4
-rw-r--r--src/vm.c34
-rw-r--r--src/vm_core.h409
24 files changed, 958 insertions, 843 deletions
diff --git a/src/Makefile b/src/Makefile
index 1b139389a..11a00b41c 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -4,12 +4,7 @@
# project-specific macros
# extension of the executable-file is modifiable(.exe .out ...)
BASEDIR = .
-TARGET := ../lib/mruby
-ifeq ($(OS),Windows_NT)
-LIB := $(TARGET).lib
-else
-LIB := $(TARGET).a
-endif
+TARGET := ../lib/libmruby.a
YSRC := $(BASEDIR)/parse.y
YC := $(BASEDIR)/y.tab.c
EXCEPT1 := $(YC) $(BASEDIR)/minimain.c
@@ -40,11 +35,11 @@ ALL_CFLAGS = -Wall -Werror-implicit-function-declaration $(CFLAGS)
# generic build targets, rules
.PHONY : all
-all : $(LIB)
+all : $(TARGET)
@echo "make: built targets of `pwd`"
# executable constructed using linker from object files
-$(LIB) : $(OBJS) $(OBJY)
+$(TARGET) : $(OBJS) $(OBJY)
$(AR) r $@ $(OBJS) $(OBJY)
-include $(OBJS:.o=.d) $(OBJY:.o=.d)
@@ -65,6 +60,6 @@ $(YC) : $(YSRC)
.PHONY : clean #cleandep
clean :
@echo "make: removing targets, objects and depend files of `pwd`"
- -rm -f $(LIB) $(OBJS) $(OBJY) $(YC)
+ -rm -f $(TARGET) $(OBJS) $(OBJY) $(YC)
-rm -f $(OBJS:.o=.d) $(OBJY:.o=.d)
-rm -f $(patsubst %.c,%.o,$(EXCEPT1)) $(patsubst %.c,%.d,$(EXCEPT1))
diff --git a/src/array.c b/src/array.c
index 249ae8d8c..b28bc7f3f 100644
--- a/src/array.c
+++ b/src/array.c
@@ -725,7 +725,12 @@ mrb_ary_rindex_m(mrb_state *mrb, mrb_value self)
mrb_value
mrb_ary_splat(mrb_state *mrb, mrb_value v)
{
- return v;
+ if (mrb_type(v) == MRB_TT_ARRAY) {
+ return v;
+ }
+ else {
+ return mrb_ary_new_from_values(mrb, &v, 1);
+ }
}
static mrb_value
diff --git a/src/class.c b/src/class.c
index 366bde96d..34ffd2fa8 100644
--- a/src/class.c
+++ b/src/class.c
@@ -309,9 +309,9 @@ mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t f
}
void
-mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int apec)
+mrb_define_method(mrb_state *mrb, struct RClass *c, const char *name, mrb_func_t func, int aspec)
{
- return mrb_define_method_id(mrb, c, mrb_intern(mrb, name), func, apec);
+ return mrb_define_method_id(mrb, c, mrb_intern(mrb, name), func, aspec);
}
void
@@ -348,7 +348,7 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
{
mrb_value *p;
p = va_arg(ap, mrb_value*);
- *p = (argc > i) ? *sp : mrb_nil_value();
+ *p = *sp;
i++; sp++;
}
break;
@@ -357,7 +357,25 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
mrb_int *p;
p = va_arg(ap, mrb_int*);
- *p = (argc > i) ? mrb_fixnum(*sp) : 0;
+ switch (sp->tt) {
+ case MRB_TT_FIXNUM:
+ *p = mrb_fixnum(*sp);
+ break;
+ case MRB_TT_FLOAT:
+ *p = (mrb_int)mrb_float(*sp);
+ break;
+ case MRB_TT_FALSE:
+ *p = 0;
+ break;
+ default:
+ {
+ mrb_value tmp;
+
+ tmp = mrb_convert_type(mrb, *sp, MRB_TT_FIXNUM, "Integer", "to_int");
+ *p = mrb_fixnum(tmp);
+ }
+ break;
+ }
i++; sp++;
}
break;
@@ -368,13 +386,21 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
p = va_arg(ap, mrb_float*);
switch (sp->tt) {
case MRB_TT_FLOAT:
- *p = (argc > i) ? mrb_float(*sp) : 0;
+ *p = mrb_float(*sp);
break;
case MRB_TT_FIXNUM:
- *p = (argc > i) ? (mrb_float)mrb_fixnum(*sp) : 0;
+ *p = (mrb_float)mrb_fixnum(*sp);
+ break;
+ case MRB_TT_FALSE:
+ *p = 0.0;
break;
default:
- // error
+ {
+ mrb_value tmp;
+
+ tmp = mrb_convert_type(mrb, *sp, MRB_TT_FLOAT, "Float", "to_f");
+ *p = mrb_float(tmp);
+ }
break;
}
i++; sp++;
@@ -502,6 +528,7 @@ mrb_mod_include(mrb_state *mrb, mrb_value klass)
mrb_value mod;
mrb_get_args(mrb, "o", &mod);
+ mrb_check_type(mrb, mod, MRB_TT_MODULE);
mrb_include_module(mrb, mrb_class_ptr(klass), mrb_class_ptr(mod));
return mod;
}
@@ -835,7 +862,8 @@ mrb_check_inheritable(mrb_state *mrb, struct RClass *super)
* \param super a class from which the new class derives.
* \exception TypeError \a super is not inheritable.
* \exception TypeError \a super is the Class class.
- */struct RClass *
+ */
+struct RClass *
mrb_class_new(mrb_state *mrb, struct RClass *super)
{
struct RClass *c;
diff --git a/src/codegen.c b/src/codegen.c
index b0f5abc1a..89af78c63 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -1893,7 +1893,6 @@ loop_break(codegen_scope *s, node *tree)
if (tree) {
codegen(s, tree, VAL);
- printf("break op %d\n", cursp());
pop();
}
diff --git a/src/compile.h b/src/compile.h
index 9d58acaa0..19894f3aa 100644
--- a/src/compile.h
+++ b/src/compile.h
@@ -41,7 +41,7 @@ struct mrb_parser_state {
mrb_state *mrb;
struct mrb_pool *pool;
mrb_ast_node *cells;
- char *s, *send;
+ const char *s, *send;
FILE *f;
int lineno;
int column;
@@ -78,9 +78,9 @@ struct mrb_parser_state {
};
struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*);
-struct mrb_parser_state* mrb_parse_string(mrb_state*,char*);
-struct mrb_parser_state* mrb_parse_nstring(mrb_state*,char*,size_t);
-struct mrb_parser_state* mrb_parse_nstring_ext(mrb_state*,char*,size_t);
+struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*);
+struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,size_t);
+struct mrb_parser_state* mrb_parse_nstring_ext(mrb_state*,const char*,size_t);
int mrb_generate_code(mrb_state*, mrb_ast_node*);
int mrb_compile_file(mrb_state*,FILE*);
diff --git a/src/error.c b/src/error.c
index d18311633..f57f0e5e6 100644
--- a/src/error.c
+++ b/src/error.c
@@ -16,7 +16,6 @@
#include "mruby/numeric.h"
#include "mruby/variable.h"
#include "mruby/string.h"
-#include "eval_intern.h"
#include "mruby/class.h"
#define warn_printf printf
diff --git a/src/etc.c b/src/etc.c
index 51ed9ada1..eac71459c 100644
--- a/src/etc.c
+++ b/src/etc.c
@@ -8,6 +8,7 @@
#include "mruby/string.h"
#include "error.h"
#include "mruby/numeric.h"
+#include "mruby/data.h"
#ifndef FALSE
#define FALSE 0
@@ -17,13 +18,6 @@
#define TRUE 1
#endif
-void
-ruby_xfree(void *x)
-{
- //if (x)
- // vm_xfree(&mrb_objspace, x);
-}
-
struct RData*
mrb_data_object_alloc(mrb_state *mrb, struct RClass *klass, void *ptr, const struct mrb_data_type *type)
{
@@ -37,6 +31,18 @@ mrb_data_object_alloc(mrb_state *mrb, struct RClass *klass, void *ptr, const str
}
void *
+mrb_get_datatype(mrb_state *mrb, mrb_value obj, const struct mrb_data_type *type)
+{
+ if (SPECIAL_CONST_P(obj) || (mrb_type(obj) != MRB_TT_DATA)) {
+ return NULL;
+ }
+ if (DATA_TYPE(obj) != type) {
+ return NULL;
+ }
+ return DATA_PTR(obj);
+}
+
+void *
mrb_check_datatype(mrb_state *mrb, mrb_value obj, const struct mrb_data_type *type)
{
static const char mesg[] = "wrong argument type %s (expected %s)";
diff --git a/src/eval_intern.h b/src/eval_intern.h
deleted file mode 100644
index 4324f26cc..000000000
--- a/src/eval_intern.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
-** eval_intern.h -
-**
-** See Copyright Notice in mruby.h
-*/
-
-#ifndef RUBY_EVAL_INTERN_H
-#define RUBY_EVAL_INTERN_H
-
-//#include "ruby/ruby.h"
-#include "mruby.h"
-#define HAVE_STRING_H
-//#include "vm_core.h"
-#include "node.h"
-
-/* other frame flag */
-#define VM_FRAME_FLAG_PASSED 0x0100
-#define PASS_PASSED_BLOCK_TH(th) do { \
- (th)->passed_block = GC_GUARDED_PTR_REF((mrb_block_t *)(th)->cfp->lfp[0]); \
- (th)->cfp->flag |= VM_FRAME_FLAG_PASSED; \
-} while (0)
-
-#define PASS_PASSED_BLOCK() do { \
- mrb_thread_t * const __th__ = GET_THREAD(); \
- PASS_PASSED_BLOCK_TH(__th__); \
-} while (0)
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifndef EXIT_SUCCESS
-#define EXIT_SUCCESS 0
-#endif
-#ifndef EXIT_FAILURE
-#define EXIT_FAILURE 1
-#endif
-
-#include <stdio.h>
-#include <setjmp.h>
-
-#ifdef __APPLE__
-#include <crt_externs.h>
-#endif
-
-/* Make alloca work the best possible way. */
-#ifdef __GNUC__
-# ifndef atarist
-# ifndef alloca
-# define alloca __builtin_alloca
-# endif
-# endif /* atarist */
-#else
-# ifdef HAVE_ALLOCA_H
-# include <alloca.h>
-# else
-# ifdef _AIX
-#pragma alloca
-# else
-# ifndef alloca /* predefined by HP cc +Olibcalls */
-void *alloca();
-# endif
-# endif /* AIX */
-# endif /* HAVE_ALLOCA_H */
-#endif /* __GNUC__ */
-
-#ifndef HAVE_STRING_H
-char *strrchr(const char *, const char);
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_NET_SOCKET_H
-#include <net/socket.h>
-#endif
-
-
-
-#include <sys/types.h>
-#include <signal.h>
-#include <errno.h>
-
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-/*
- Solaris sys/select.h switches select to select_large_fdset to support larger
- file descriptors if FD_SETSIZE is larger than 1024 on 32bit environment.
- But Ruby doesn't change FD_SETSIZE because fd_set is allocated dynamically.
- So following definition is required to use select_large_fdset.
-*/
-#ifdef HAVE_SELECT_LARGE_FDSET
-#define select(n, r, w, e, t) select_large_fdset(n, r, w, e, t)
-#endif
-
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-
-#include <sys/stat.h>
-
-#define SAVE_ROOT_JMPBUF(th, stmt) do \
- if (ruby_setjmp((th)->root_jmpbuf) == 0) { \
- stmt; \
- } while (0)
-
-#define TH_PUSH_TAG(th) do { \
- mrb_thread_t * const _th = th; \
- struct mrb_vm_tag _tag; \
- _tag.tag = 0; \
- _tag.prev = _th->tag; \
- _th->tag = &_tag;
-
-#define TH_POP_TAG() \
- _th->tag = _tag.prev; \
-} while (0)
-
-#define TH_POP_TAG2() \
- _th->tag = _tag.prev
-
-#define PUSH_TAG() TH_PUSH_TAG(GET_THREAD())
-#define POP_TAG() TH_POP_TAG()
-
-#define TH_EXEC_TAG() ruby_setjmp(_th->tag->buf)
-
-#define EXEC_TAG() \
- TH_EXEC_TAG()
-
-#define TH_JUMP_TAG(th, st) do { \
- ruby_longjmp(th->tag->buf,(st)); \
-} while (0)
-
-//#define JUMP_TAG(st) TH_JUMP_TAG(GET_THREAD(), st)
-
-enum ruby_tag_type {
- RUBY_TAG_RETURN = 0x1,
- RUBY_TAG_BREAK = 0x2,
- RUBY_TAG_NEXT = 0x3,
- RUBY_TAG_RETRY = 0x4,
- RUBY_TAG_REDO = 0x5,
- RUBY_TAG_RAISE = 0x6,
- RUBY_TAG_THROW = 0x7,
- RUBY_TAG_FATAL = 0x8,
- RUBY_TAG_MASK = 0xf
-};
-#define TAG_RETURN RUBY_TAG_RETURN
-#define TAG_BREAK RUBY_TAG_BREAK
-#define TAG_NEXT RUBY_TAG_NEXT
-#define TAG_RETRY RUBY_TAG_RETRY
-#define TAG_REDO RUBY_TAG_REDO
-#define TAG_RAISE RUBY_TAG_RAISE
-#define TAG_THROW RUBY_TAG_THROW
-#define TAG_FATAL RUBY_TAG_FATAL
-#define TAG_MASK RUBY_TAG_MASK
-
-#define NEW_THROW_OBJECT(val, pt, st) \
- ((mrb_value)mrb_node_newnode(NODE_LIT, (mrb_value)(val), (mrb_value)(pt), (mrb_value)(st)))
-//#define SET_THROWOBJ_CATCH_POINT(obj, val)
-// (RNODE((obj))->u2.value = (val))
-//#define SET_THROWOBJ_STATE(obj, val)
-// (RNODE((obj))->u3.value = (val))
-
-#define GET_THROWOBJ_VAL(obj) ((mrb_value)RNODE((obj))->u1.value)
-#define GET_THROWOBJ_CATCH_POINT(obj) ((mrb_value*)RNODE((obj))->u2.value)
-#define GET_THROWOBJ_STATE(obj) ((int)RNODE((obj))->u3.value)
-
-#define SCOPE_TEST(f) (mrb_vm_cref()->nd_visi & (f))
-#define SCOPE_CHECK(f) (mrb_vm_cref()->nd_visi == (f))
-#define SCOPE_SET(f) (mrb_vm_cref()->nd_visi = (f))
-
-#define sysstack_error mrb_fixnum_value(0)
-
-#define CHECK_STACK_OVERFLOW(mrb, cfp, margin) do \
- if ((mrb_value *)((char *)(((mrb_value *)(cfp)->sp) + (margin)) + sizeof(mrb_control_frame_t)) >= ((mrb_value *)cfp)) { \
- mrb_exc_raise(mrb, sysstack_error); \
- } \
-while (0)
-
-void mrb_thread_cleanup(void);
-void mrb_thread_wait_other_threads(void);
-
-enum {
- RAISED_EXCEPTION = 1,
- RAISED_STACKOVERFLOW = 2,
- RAISED_NOMEMORY = 4
-};
-//int rb_threadptr_set_raised(mrb_thread_t *th);
-//int rb_threadptr_reset_raised(mrb_thread_t *th);
-#define mrb_thread_raised_set(th, f) ((th)->raised_flag |= (f))
-#define mrb_thread_raised_reset(th, f) ((th)->raised_flag &= ~(f))
-#define mrb_thread_raised_p(th, f) (((th)->raised_flag & (f)) != 0)
-#define mrb_thread_raised_clear(th) ((th)->raised_flag = 0)
-
-//mrb_value mrb_f_eval(int argc, mrb_value *argv, mrb_value self);
-//mrb_value mrb_make_exception(int argc, mrb_value *argv);
-#ifndef NORETURN
-# define NORETURN(x) x
-#endif
-#ifndef DEPRECATED
-# define DEPRECATED(x) x
-#endif
-
-NORETURN(void mrb_fiber_start(void));
-
-NORETURN(void rb_print_undef(mrb_value, mrb_sym, int));
-NORETURN(void rb_vm_localjump_error(const char *,mrb_value, int));
-NORETURN(void rb_vm_jump_tag_but_local_jump(int, mrb_value));
-//NORETURN(void mrb_raise_method_missing(mrb_thread_t *th, int argc, mrb_value *argv,
-// mrb_value obj, int call_status));
-
-mrb_value mrb_vm_make_jump_tag_but_local_jump(int state, mrb_value val);
-NODE *mrb_vm_cref(void);
-//mrb_value rb_vm_call_cfunc(mrb_value recv, mrb_value (*func)(mrb_value), mrb_value arg, const mrb_block_t *blockptr, mrb_value filename, mrb_value filepath);
-void mrb_vm_set_progname(mrb_value filename);
-void mrb_thread_terminate_all(mrb_state *mrb);
-//mrb_value mrb_vm_top_self();
-mrb_value mrb_vm_cbase(void);
-//int mrb_vm_get_sourceline(const mrb_control_frame_t *);
-void mrb_trap_restore_mask(void);
-
-#endif /* RUBY_EVAL_INTERN_H */
diff --git a/src/gc.c b/src/gc.c
index 06360036a..8f11f1e1d 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -345,7 +345,8 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj)
break;
case MRB_TT_HASH:
- mrb_gc_mark_ht(mrb, (struct RClass*)obj);
+ mrb_gc_mark_iv(mrb, (struct RObject*)obj);
+ mrb_gc_mark_ht(mrb, (struct RHash*)obj);
break;
case MRB_TT_STRING:
@@ -368,6 +369,24 @@ gc_mark_children(mrb_state *mrb, struct RBasic *obj)
}
break;
+#ifdef INCLUDE_REGEXP
+ case MRB_TT_MATCH:
+ {
+ struct RMatch *m = (struct RMatch*)obj;
+
+ mrb_gc_mark(mrb, (struct RBasic*)m->str);
+ mrb_gc_mark(mrb, (struct RBasic*)m->regexp);
+ }
+ break;
+ case MRB_TT_REGEX:
+ {
+ struct RRegexp *r = (struct RRegexp*)obj;
+
+ mrb_gc_mark(mrb, (struct RBasic*)r->src);
+ }
+ break;
+#endif
+
default:
break;
}
@@ -422,7 +441,8 @@ obj_free(mrb_state *mrb, struct RBasic *obj)
break;
case MRB_TT_HASH:
- mrb_gc_free_ht(mrb, (struct RClass*)obj);
+ mrb_gc_free_iv(mrb, (struct RObject*)obj);
+ mrb_gc_free_ht(mrb, (struct RHash*)obj);
break;
case MRB_TT_STRING:
@@ -441,7 +461,7 @@ obj_free(mrb_state *mrb, struct RBasic *obj)
d->type->dfree(mrb, d->data);
}
}
- break;
+ break;
default:
break;
@@ -530,7 +550,8 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj)
break;
case MRB_TT_HASH:
- children += mrb_gc_mark_ht_size(mrb, (struct RClass*)obj);
+ children += mrb_gc_mark_iv_size(mrb, (struct RObject*)obj);
+ children += mrb_gc_mark_ht_size(mrb, (struct RHash*)obj);
break;
case MRB_TT_PROC:
@@ -538,6 +559,15 @@ gc_gray_mark(mrb_state *mrb, struct RBasic *obj)
children+=2;
break;
+#ifdef INCLUDE_REGEXP
+ case MRB_TT_MATCH:
+ children+=2;
+ break;
+ case MRB_TT_REGEX:
+ children+=1;
+ break;
+#endif
+
default:
break;
}
diff --git a/src/gc.h b/src/gc.h
index 3c18905d3..61f8ce96a 100644
--- a/src/gc.h
+++ b/src/gc.h
@@ -29,4 +29,16 @@ typedef struct {
} as;
} RVALUE;
+void mrb_gc_mark_gv(mrb_state*);
+void mrb_gc_free_gv(mrb_state*);
+void mrb_gc_mark_iv(mrb_state*, struct RObject*);
+size_t mrb_gc_mark_iv_size(mrb_state*, struct RObject*);
+void mrb_gc_free_iv(mrb_state*, struct RObject*);
+void mrb_gc_mark_mt(mrb_state*, struct RClass*);
+size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*);
+void mrb_gc_free_mt(mrb_state*, struct RClass*);
+void mrb_gc_mark_ht(mrb_state*, struct RHash*);
+size_t mrb_gc_mark_ht_size(mrb_state*, struct RHash*);
+void mrb_gc_free_ht(mrb_state*, struct RHash*);
+
#endif /* MRUBY_GC_H */
diff --git a/src/hash.c b/src/hash.c
index 078faf1d3..cb34dae75 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -9,10 +9,8 @@
#include "mruby/khash.h"
#include "mruby/class.h"
#include "mruby/array.h"
-#include "error.h"
#include "mruby/string.h"
-#include "mruby/numeric.h"
-#include "mruby/struct.h"
+#include "mruby/variable.h"
#include "st.h"
#include <errno.h>
#include <string.h>
@@ -66,12 +64,11 @@ mrb_hash_ht_key(mrb_state *mrb, mrb_value key)
#define KEY(key) mrb_hash_ht_key(mrb, key)
void
-mrb_gc_mark_ht(mrb_state *mrb, struct RClass *c)
+mrb_gc_mark_ht(mrb_state *mrb, struct RHash *c)
{
khiter_t k;
khash_t(ht) *h = ((struct RHash*)c)->ht;
- mrb_gc_mark_value(mrb, ((struct RHash*)c)->ifnone);
if (!h) return;
for (k = kh_begin(h); k != kh_end(h); k++)
if (kh_exist(h, k)) {
@@ -86,9 +83,6 @@ mrb_gc_mark_ht_size(mrb_state *mrb, struct RClass *c)
size_t ht_size = 0;
khash_t(ht) *h = ((struct RHash*)c)->ht;
- /* ((struct RHash*)c)->ifnone */
- ht_size++;
-
/* ((struct RHash*)c)->ht */
if (h) ht_size += kh_size(h)*2;
@@ -112,7 +106,7 @@ mrb_hash_new_capa(mrb_state *mrb, size_t capa)
h = mrb_obj_alloc(mrb, MRB_TT_HASH, mrb->hash_class);
h->ht = kh_init(ht, mrb);
kh_resize(ht, h->ht, capa);
- h->ifnone = mrb_nil_value();
+ h->iv = 0;
return mrb_obj_value(h);
}
@@ -125,7 +119,7 @@ mrb_hash_new(mrb_state *mrb, int capa)
mrb_value
mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) /* mrb_hash_aref */ /* mrb_hash_lookup */
{
- khash_t(ht) *h = RHASH_H_TBL(hash);
+ khash_t(ht) *h = RHASH_TBL(hash);
khiter_t k;
if (h) {
@@ -138,15 +132,13 @@ mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key) /* mrb_hash_aref */
if (MRB_RHASH_PROCDEFAULT_P(hash)) {
return mrb_funcall(mrb, RHASH_PROCDEFAULT(hash), "call", 2, hash, key);
}
- else {
- return RHASH_IFNONE(hash);
- }
+ return RHASH_IFNONE(hash);
}
mrb_value
mrb_hash_getWithDef(mrb_state *mrb, mrb_value hash, mrb_value vkey, mrb_value def) /* mrb_hash_lookup2 */
{
- khash_t(ht) *h = RHASH_H_TBL(hash);
+ khash_t(ht) *h = RHASH_TBL(hash);
khiter_t k;
if (h) {
@@ -166,7 +158,7 @@ mrb_hash_set(mrb_state *mrb, mrb_value hash, mrb_value key, mrb_value val) /* mr
khiter_t k;
mrb_hash_modify(mrb, hash);
- h = RHASH_H_TBL(hash);
+ h = RHASH_TBL(hash);
k = kh_get(ht, h, key);
if (k == kh_end(h)) {
@@ -201,18 +193,6 @@ retry:
}
}
-static mrb_value
-hash_s_new(mrb_state *mrb, mrb_value klass)
-{
- mrb_value *argv;
- int argc;
-
- mrb_get_args(mrb, "*", &argv, &argc);
- mrb_value hash = mrb_hash_new_capa(mrb, 0);
- mrb_obj_call_init(mrb, hash, argc, argv);
- return hash;
-}
-
mrb_value
mrb_hash_dup(mrb_state *mrb, mrb_value hash)
{
@@ -224,7 +204,7 @@ mrb_hash_dup(mrb_state *mrb, mrb_value hash)
ret->ht = kh_init(ht, mrb);
if (!RHASH_EMPTY_P(hash)) {
- h = RHASH_H_TBL(hash);
+ h = RHASH_TBL(hash);
ret_h = ret->ht;
for (k = kh_begin(h); k != kh_end(h); k++) {
@@ -247,10 +227,10 @@ mrb_hash_modify_check(mrb_state *mrb, mrb_value hash)
khash_t(ht) *
mrb_hash_tbl(mrb_state *mrb, mrb_value hash)
{
- khash_t(ht) *h = RHASH_H_TBL(hash);
+ khash_t(ht) *h = RHASH_TBL(hash);
- if (!RHASH_H_TBL(hash)) {
- RHASH_H_TBL(hash) = kh_init(ht, mrb);
+ if (!RHASH_TBL(hash)) {
+ RHASH_TBL(hash) = kh_init(ht, mrb);
}
return h;
}
@@ -301,21 +281,20 @@ mrb_hash_modify(mrb_state *mrb, mrb_value hash)
static mrb_value
mrb_hash_init_core(mrb_state *mrb, mrb_value hash)
{
- mrb_value block;
+ mrb_value block, ifnone;
mrb_value *argv;
int argc;
mrb_get_args(mrb, "o*", &block, &argv, &argc);
mrb_hash_modify(mrb, hash);
-
if (mrb_nil_p(block)) {
if (argc > 0) {
if (argc != 1) mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
- RHASH_IFNONE(hash) = argv[0];
+ ifnone = argv[0];
}
else {
- RHASH_IFNONE(hash) = mrb_nil_value();
+ ifnone = mrb_nil_value();
}
}
else {
@@ -323,9 +302,9 @@ mrb_hash_init_core(mrb_state *mrb, mrb_value hash)
mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
}
RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT;
- RHASH_PROCDEFAULT(hash) = block;
+ ifnone = block;
}
-
+ mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone);
return hash;
}
@@ -497,7 +476,7 @@ mrb_hash_set_default(mrb_state *mrb, mrb_value hash)
mrb_get_args(mrb, "o", &ifnone);
mrb_hash_modify(mrb, hash);
- RHASH_IFNONE(hash) = ifnone;
+ mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone);
RHASH(hash)->flags &= ~(MRB_HASH_PROC_DEFAULT);
return ifnone;
@@ -541,10 +520,23 @@ mrb_hash_default_proc(mrb_state *mrb, mrb_value hash)
* h["cat"] #=> "catcat"
*/
+static mrb_value
+mrb_hash_set_default_proc(mrb_state *mrb, mrb_value hash)
+{
+ mrb_value ifnone;
+ mrb_get_args(mrb, "o", &ifnone);
+
+ mrb_hash_modify(mrb, hash);
+ mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone);
+ RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT;
+
+ return ifnone;
+}
+
mrb_value
mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key)
{
- khash_t(ht) *h = RHASH_H_TBL(hash);
+ khash_t(ht) *h = RHASH_TBL(hash);
khiter_t k;
mrb_value delVal;
@@ -610,7 +602,7 @@ struct shift_var {
static mrb_value
mrb_hash_shift(mrb_state *mrb, mrb_value hash)
{
- khash_t(ht) *h = RHASH_H_TBL(hash);
+ khash_t(ht) *h = RHASH_TBL(hash);
khiter_t k;
mrb_value delKey, delVal;
mrb_value result;
@@ -625,8 +617,8 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash)
delVal = mrb_hash_delete_key(mrb, hash, delKey);
result = mrb_hash_new(mrb, 1);
- k = kh_put(ht, RHASH_H_TBL(result), KEY(delKey));
- kh_value(RHASH_H_TBL(result), k) = delVal;
+ k = kh_put(ht, RHASH_TBL(result), KEY(delKey));
+ kh_value(RHASH_TBL(result), k) = delVal;
return result;
}
}
@@ -688,7 +680,7 @@ mrb_hash_shift(mrb_state *mrb, mrb_value hash)
mrb_value
mrb_hash_values_at(mrb_state *mrb, int argc, mrb_value *argv, mrb_value hash)
{
- mrb_value result = mrb_ary_new_capa(mrb, argc);//mrb_ary_new2(argc);
+ mrb_value result = mrb_ary_new_capa(mrb, argc);
long i;
for (i=0; i<argc; i++) {
@@ -747,7 +739,7 @@ mrb_hash_values_at(mrb_state *mrb, int argc, mrb_value *argv, mrb_value hash)
static mrb_value
mrb_hash_clear(mrb_state *mrb, mrb_value hash)
{
- khash_t(ht) *h = RHASH_H_TBL(hash);
+ khash_t(ht) *h = RHASH_TBL(hash);
kh_clear(ht, h);
return hash;
@@ -799,7 +791,7 @@ mrb_hash_aset(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_hash_replace(mrb_state *mrb, mrb_value hash)
{
- mrb_value hash2;
+ mrb_value hash2, ifnone;
khash_t(ht) *h2;
khiter_t k;
@@ -810,7 +802,7 @@ mrb_hash_replace(mrb_state *mrb, mrb_value hash)
if (mrb_obj_equal(mrb, hash, hash2)) return hash;
mrb_hash_clear(mrb, hash);
- h2 = RHASH_H_TBL(hash2);
+ h2 = RHASH_TBL(hash2);
if (h2) {
for (k = kh_begin(h2); k != kh_end(h2); k++) {
if (kh_exist(h2, k))
@@ -820,11 +812,13 @@ mrb_hash_replace(mrb_state *mrb, mrb_value hash)
if (MRB_RHASH_PROCDEFAULT_P(hash2)) {
RHASH(hash)->flags |= MRB_HASH_PROC_DEFAULT;
- RHASH_PROCDEFAULT(hash) = RHASH_PROCDEFAULT(hash2);
+ ifnone = RHASH_PROCDEFAULT(hash2);
}
else {
- RHASH_IFNONE(hash) = RHASH_IFNONE(hash2);
+ ifnone = RHASH_IFNONE(hash2);
}
+ mrb_iv_set(mrb, hash, mrb_intern(mrb, "ifnone"), ifnone);
+
return hash;
}
@@ -845,7 +839,7 @@ mrb_hash_replace(mrb_state *mrb, mrb_value hash)
static mrb_value
mrb_hash_size_m(mrb_state *mrb, mrb_value self)
{
- khash_t(ht) *h = RHASH_H_TBL(self);
+ khash_t(ht) *h = RHASH_TBL(self);
if (!h) return mrb_fixnum_value(0);
return mrb_fixnum_value(kh_size(h));
@@ -864,7 +858,7 @@ mrb_hash_size_m(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_hash_empty_p(mrb_state *mrb, mrb_value self)
{
- khash_t(ht) *h = RHASH_H_TBL(self);
+ khash_t(ht) *h = RHASH_TBL(self);
khiter_t k;
if (h) {
for (k = kh_begin(h); k != kh_end(h); k++)
@@ -941,12 +935,12 @@ static mrb_value
inspect_hash(mrb_state *mrb, mrb_value hash, int recur)
{
mrb_value str, str2;
- khash_t(ht) *h = RHASH_H_TBL(hash);
+ khash_t(ht) *h = RHASH_TBL(hash);
khiter_t k;
- if (recur) return mrb_str_new2(mrb, "{...}");
+ if (recur) return mrb_str_new_cstr(mrb, "{...}");
- str = mrb_str_new2(mrb, "{");
+ str = mrb_str_new_cstr(mrb, "{");
if (h && kh_size(h) > 0) {
for (k = kh_begin(h); k != kh_end(h); k++) {
int ai;
@@ -987,7 +981,7 @@ static mrb_value
mrb_hash_inspect(mrb_state *mrb, mrb_value hash)
{
if (RHASH_EMPTY_P(hash))
- return mrb_str_new2(mrb, "{}");
+ return mrb_str_new_cstr(mrb, "{}");
return inspect_hash(mrb, hash, 0);
}
@@ -1021,7 +1015,7 @@ mrb_hash_to_hash(mrb_state *mrb, mrb_value hash)
static mrb_value
mrb_hash_keys(mrb_state *mrb, mrb_value hash)
{
- khash_t(ht) *h = RHASH_H_TBL(hash);
+ khash_t(ht) *h = RHASH_TBL(hash);
khiter_t k;
mrb_value ary = mrb_ary_new(mrb);
@@ -1053,7 +1047,7 @@ mrb_hash_keys(mrb_state *mrb, mrb_value hash)
static mrb_value
mrb_hash_values(mrb_state *mrb, mrb_value hash)
{
- khash_t(ht) *h = RHASH_H_TBL(hash);
+ khash_t(ht) *h = RHASH_TBL(hash);
khiter_t k;
mrb_value ary = mrb_ary_new(mrb);
@@ -1072,7 +1066,7 @@ mrb_hash_values(mrb_state *mrb, mrb_value hash)
static mrb_value
mrb_hash_has_keyWithKey(mrb_state *mrb, mrb_value hash, mrb_value key)
{
- khash_t(ht) *h = RHASH_H_TBL(hash);
+ khash_t(ht) *h = RHASH_TBL(hash);
khiter_t k;
if (h) {
@@ -1115,7 +1109,7 @@ mrb_hash_has_key(mrb_state *mrb, mrb_value hash)
static mrb_value
mrb_hash_has_valueWithvalue(mrb_state *mrb, mrb_value hash, mrb_value value)
{
- khash_t(ht) *h = RHASH_H_TBL(hash);
+ khash_t(ht) *h = RHASH_TBL(hash);
khiter_t k;
if (h) {
@@ -1158,8 +1152,8 @@ mrb_hash_has_value(mrb_state *mrb, mrb_value hash)
static mrb_value
recursive_eql(mrb_state *mrb, mrb_value hash, mrb_value dt, int recur)
{
- khash_t(ht) *h1 = RHASH_H_TBL(hash);
- khash_t(ht) *h2 = RHASH_H_TBL(dt);
+ khash_t(ht) *h1 = RHASH_TBL(hash);
+ khash_t(ht) *h2 = RHASH_TBL(dt);
khiter_t k1, k2;
mrb_value key1;
@@ -1388,7 +1382,6 @@ mrb_init_hash(mrb_state *mrb)
h = mrb->hash_class = mrb_define_class(mrb, "Hash", mrb->object_class);
MRB_SET_INSTANCE_TT(h, MRB_TT_HASH);
- //mrb_define_class_method(mrb, h, "new", hash_s_new, ARGS_ANY());
mrb_include_module(mrb, h, mrb_class_get(mrb, "Enumerable"));
mrb_define_method(mrb, h, "==", mrb_hash_equal, ARGS_REQ(1)); /* 15.2.13.4.1 */
mrb_define_method(mrb, h, "[]", mrb_hash_aget, ARGS_REQ(1)); /* 15.2.13.4.2 */
@@ -1397,6 +1390,7 @@ mrb_init_hash(mrb_state *mrb)
mrb_define_method(mrb, h, "default", mrb_hash_default, ARGS_ANY()); /* 15.2.13.4.5 */
mrb_define_method(mrb, h, "default=", mrb_hash_set_default, ARGS_REQ(1)); /* 15.2.13.4.6 */
mrb_define_method(mrb, h, "default_proc", mrb_hash_default_proc,ARGS_NONE()); /* 15.2.13.4.7 */
+ mrb_define_method(mrb, h, "default_proc=", mrb_hash_set_default_proc,ARGS_REQ(1)); /* 15.2.13.4.7 */
mrb_define_method(mrb, h, "__delete", mrb_hash_delete, ARGS_REQ(1)); /* core of 15.2.13.4.8 */
//mrb_define_method(mrb, h, "each", mrb_hash_each_pair, ARGS_NONE()); /* 15.2.13.4.9 */ /* move to mrblib\hash.rb */
//mrb_define_method(mrb, h, "each_key", mrb_hash_each_key, ARGS_NONE()); /* 15.2.13.4.10 */ /* move to mrblib\hash.rb */
diff --git a/src/init.c b/src/init.c
index 9dbdc44d1..347c6919f 100644
--- a/src/init.c
+++ b/src/init.c
@@ -98,6 +98,7 @@ mrb_init_core(mrb_state *mrb)
#endif
mrb_init_exception(mrb);
mrb_init_print(mrb);
+ mrb_init_time(mrb);
#ifdef MANDEL
mrb_define_method(mrb, mrb->kernel_module, "pow", mpow, ARGS_REQ(2));
diff --git a/src/kernel.c b/src/kernel.c
index 8d7b38880..09ac59eef 100644
--- a/src/kernel.c
+++ b/src/kernel.c
@@ -638,6 +638,13 @@ mrb_obj_instance_eval(mrb_state *mrb, mrb_value self)
return mrb_yield_with_self(mrb, b, 0, 0, self);
}
+int
+mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c)
+{
+ if (mrb_obj_class(mrb, obj) == c) return TRUE;
+ return FALSE;
+}
+
/* 15.3.1.3.19 */
/*
* call-seq:
@@ -646,8 +653,8 @@ mrb_obj_instance_eval(mrb_state *mrb, mrb_value self)
* Returns <code>true</code> if <i>obj</i> is an instance of the given
* class. See also <code>Object#kind_of?</code>.
*/
-mrb_value
-rb_obj_is_instance_of(mrb_state *mrb, mrb_value self)
+static mrb_value
+obj_is_instance_of(mrb_state *mrb, mrb_value self)
{
mrb_value arg;
@@ -994,9 +1001,6 @@ mrb_obj_methods(mrb_state *mrb, int argc, mrb_value *argv, mrb_value obj, mrb_me
{
retry:
if (argc == 0) {
- mrb_value args[1];
-
- args[0] = mrb_true_value();
return class_instance_method_list(mrb, argc, argv, mrb_class(mrb, obj), 0);
}
else {
@@ -1417,7 +1421,7 @@ mrb_init_kernel(mrb_state *mrb)
mrb_define_method(mrb, krn, "initialize_copy", mrb_obj_init_copy, ARGS_REQ(1)); /* 15.3.1.3.16 */
mrb_define_method(mrb, krn, "inspect", mrb_obj_inspect, ARGS_NONE()); /* 15.3.1.3.17 */
mrb_define_method(mrb, krn, "instance_eval", mrb_obj_instance_eval, ARGS_ANY()); /* 15.3.1.3.18 */
- mrb_define_method(mrb, krn, "instance_of?", rb_obj_is_instance_of, ARGS_REQ(1)); /* 15.3.1.3.19 */
+ mrb_define_method(mrb, krn, "instance_of?", obj_is_instance_of, ARGS_REQ(1)); /* 15.3.1.3.19 */
mrb_define_method(mrb, krn, "instance_variable_defined?", mrb_obj_ivar_defined, ARGS_REQ(1)); /* 15.3.1.3.20 */
mrb_define_method(mrb, krn, "instance_variable_get", mrb_obj_ivar_get, ARGS_REQ(1)); /* 15.3.1.3.21 */
mrb_define_method(mrb, krn, "instance_variable_set", mrb_obj_ivar_set, ARGS_REQ(2)); /* 15.3.1.3.22 */
diff --git a/src/object.c b/src/object.c
index 6c0e944a8..4e479a119 100644
--- a/src/object.c
+++ b/src/object.c
@@ -310,7 +310,7 @@ mrb_init_object(mrb_state *mrb)
mrb_define_method(mrb, f, "|", false_or, ARGS_REQ(1)); /* 15.2.6.3.4 */
}
-mrb_value
+static mrb_value
convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *method, int raise)
{
mrb_sym m = 0;
diff --git a/src/parse.y b/src/parse.y
index 04e0a9d01..f3ab49e6f 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -660,7 +660,7 @@ new_op_asgn(parser_state *p, node *a, mrb_sym op, node *b)
static node*
new_int(parser_state *p, const char *s, int base)
{
- return list3((node*)NODE_INT, (node*)strdup(s), (node*)base);
+ return list3((node*)NODE_INT, (node*)strdup(s), (node*)(intptr_t)base);
}
// (:float . i)
@@ -688,14 +688,14 @@ new_dstr(parser_state *p, node *a)
static node*
new_back_ref(parser_state *p, int n)
{
- return cons((node*)NODE_BACK_REF, (node*)n);
+ return cons((node*)NODE_BACK_REF, (node*)(intptr_t)n);
}
// (:nthref . n)
static node*
new_nth_ref(parser_state *p, int n)
{
- return cons((node*)NODE_NTH_REF, (node*)n);
+ return cons((node*)NODE_NTH_REF, (node*)(intptr_t)n);
}
static void
@@ -774,7 +774,7 @@ ret_args(parser_state *p, node *n)
static void
assignable(parser_state *p, node *lhs)
{
- switch ((int)lhs->car) {
+ switch ((int)(intptr_t)lhs->car) {
case NODE_LVAR:
local_add(p, (mrb_sym)lhs->cdr);
break;
@@ -788,7 +788,7 @@ var_reference(parser_state *p, node *lhs)
{
node *n;
- switch ((int)lhs->car) {
+ switch ((int)(intptr_t)lhs->car) {
case NODE_LVAR:
if (!local_var_p(p, (mrb_sym)lhs->cdr)) {
n = new_fcall(p, (mrb_sym)lhs->cdr, 0);
@@ -1989,7 +1989,7 @@ primary : literal
}
term
{
- $<node>$ = cons(local_switch(p), (node*)p->in_single);
+ $<node>$ = cons(local_switch(p), (node*)(intptr_t)p->in_single);
p->in_single = 0;
}
bodystmt
@@ -1998,7 +1998,7 @@ primary : literal
$$ = new_sclass(p, $3, $7);
local_resume(p, $<node>6->car);
p->in_def = $<num>4;
- p->in_single = (int)$<node>6->cdr;
+ p->in_single = (int)(intptr_t)$<node>6->cdr;
}
| keyword_module cpath
{
@@ -2972,12 +2972,12 @@ yywarning_s(parser_state *p, const char *fmt, const char *s)
static void
backref_error(parser_state *p, node *n)
{
- switch ((int)n->car) {
+ switch ((int)(intptr_t)n->car) {
case NODE_NTH_REF:
- yyerror_i(p, "can't set variable $%d", (int)n->cdr);
+ yyerror_i(p, "can't set variable $%d", (int)(intptr_t)n->cdr);
break;
case NODE_BACK_REF:
- yyerror_i(p, "can't set variable $%c", (int)n->cdr);
+ yyerror_i(p, "can't set variable $%c", (int)(intptr_t)n->cdr);
break;
}
}
@@ -2993,7 +2993,7 @@ nextc(parser_state *p)
if (p->pb) {
node *tmp;
- c = (int)p->pb->car;
+ c = (int)(intptr_t)p->pb->car;
tmp = p->pb;
p->pb = p->pb->cdr;
cons_free(tmp);
@@ -3030,7 +3030,7 @@ pushback(parser_state *p, int c)
{
if (c < 0) return;
p->column--;
- p->pb = cons((node*)c, p->pb);
+ p->pb = cons((node*)(intptr_t)c, p->pb);
}
static void
@@ -3055,7 +3055,7 @@ peek_n(parser_state *p, int c, int n)
while (n--) {
c0 = nextc(p);
if (c0 < 0) return FALSE;
- list = push(list, (node*)c0);
+ list = push(list, (node*)(intptr_t)c0);
}
if (p->pb) {
p->pb = push(p->pb, (node*)list);
@@ -3819,7 +3819,7 @@ parser_yylex(parser_state *p)
return tOP_ASGN;
}
if (c == '>') {
- p->lstate = EXPR_ARG;
+ p->lstate = EXPR_ENDFN;
return tLAMBDA;
}
if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous(p))) {
@@ -4683,7 +4683,7 @@ mrb_parse_file(mrb_state *mrb, FILE *f)
}
parser_state*
-mrb_parse_nstring(mrb_state *mrb, char *s, size_t len)
+mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len)
{
parser_state *p;
@@ -4698,7 +4698,7 @@ mrb_parse_nstring(mrb_state *mrb, char *s, size_t len)
}
parser_state*
-mrb_parse_nstring_ext(mrb_state *mrb, char *s, size_t len)
+mrb_parse_nstring_ext(mrb_state *mrb, const char *s, size_t len)
{
parser_state *p;
@@ -4714,7 +4714,7 @@ mrb_parse_nstring_ext(mrb_state *mrb, char *s, size_t len)
}
parser_state*
-mrb_parse_string(mrb_state *mrb, char *s)
+mrb_parse_string(mrb_state *mrb, const char *s)
{
return mrb_parse_nstring(mrb, s, strlen(s));
}
@@ -4812,7 +4812,7 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
if (!tree) return;
again:
dump_prefix(offset);
- n = (int)tree->car;
+ n = (int)(intptr_t)tree->car;
tree = tree->cdr;
switch (n) {
case NODE_BEGIN:
@@ -5051,7 +5051,7 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
dump_prefix(offset+1);
printf("method='%s' (%d)\n",
mrb_sym2name(mrb, (mrb_sym)tree->cdr->car),
- (int)tree->cdr->car);
+ (int)(intptr_t)tree->cdr->car);
tree = tree->cdr->cdr->car;
if (tree) {
dump_prefix(offset+1);
@@ -5164,7 +5164,7 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
parser_dump(mrb, tree->car, offset+2);
tree = tree->cdr;
dump_prefix(offset+1);
- printf("op='%s' (%d)\n", mrb_sym2name(mrb, (mrb_sym)tree->car), (int)tree->car);
+ printf("op='%s' (%d)\n", mrb_sym2name(mrb, (mrb_sym)tree->car), (int)(intptr_t)tree->car);
tree = tree->cdr;
parser_dump(mrb, tree->car, offset+1);
break;
@@ -5255,7 +5255,7 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
break;
case NODE_INT:
- printf("NODE_INT %s base %d\n", (char*)tree->car, (int)tree->cdr->car);
+ printf("NODE_INT %s base %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr->car);
break;
case NODE_FLOAT:
@@ -5268,7 +5268,7 @@ parser_dump(mrb_state *mrb, node *tree, int offset)
break;
case NODE_STR:
- printf("NODE_STR \"%s\" len %d\n", (char*)tree->car, (int)tree->cdr);
+ printf("NODE_STR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr);
break;
case NODE_DSTR:
diff --git a/src/proc.c b/src/proc.c
index b77c7342a..c579d8d17 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -31,7 +31,7 @@ mrb_closure_new(mrb_state *mrb, mrb_irep *irep)
if (!mrb->ci->env) {
e = mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass *) mrb->ci->proc->env);
- e->flags= (unsigned int)irep->nlocals;
+ e->flags= (unsigned int)mrb->ci->proc->body.irep->nlocals;
e->mid = mrb->ci->mid;
e->cioff = mrb->ci - mrb->cibase;
e->stack = mrb->stack;
diff --git a/src/range.c b/src/range.c
index 020ae7ec0..f298d336e 100644
--- a/src/range.c
+++ b/src/range.c
@@ -31,23 +31,6 @@ mrb_value mrb_exec_recursive_paired(mrb_state *mrb, mrb_value (*func) (mrb_state
mrb_value obj, mrb_value paired_obj, void* arg);
int printf (const char*, ...);
-/*--------- <1.8.7>object.c ---------> */
-
-/*
- * call-seq:
- * obj.instance_of?(class) => true or false
- *
- * Returns <code>true</code> if <i>obj</i> is an instance of the given
- * class. See also <code>Object#kind_of?</code>.
- */
-
-int
-mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c)
-{
- if (mrb_obj_class(mrb, obj) == c) return TRUE;
- return FALSE;
-}
-/*--------- <1.8.7>object.c ---------< */
mrb_value
mrb_range_new(mrb_state *mrb, mrb_value beg, mrb_value end, int excl)
diff --git a/src/re.c b/src/re.c
index d7d9914ec..d2a57196f 100644
--- a/src/re.c
+++ b/src/re.c
@@ -90,7 +90,7 @@ mrb_reg_s_new_instance(mrb_state *mrb, /*int argc, mrb_value *argv, */mrb_value
struct RRegexp *re;
re = mrb_obj_alloc(mrb, MRB_TT_REGEX, mrb->regex_class);
re->ptr = 0;
- re->src = mrb_nil_value();
+ re->src = 0;
re->usecnt = 0;
return mrb_funcall_argv(mrb, mrb_obj_value(re), "initialize", argc, argv);
}
@@ -237,7 +237,7 @@ static void
match_check(mrb_state *mrb, mrb_value match)
{
struct RMatch *m = mrb_match_ptr(match);
- if (!m->str.tt) {
+ if (!m->str) {
mrb_raise(mrb, E_TYPE_ERROR, "uninitialized Match");
}
}
@@ -262,7 +262,7 @@ mrb_reg_nth_match(mrb_state *mrb, mrb_int nth, mrb_value match)
if (start == -1) return mrb_nil_value();
end = m->rmatch->regs.end[nth];
len = end - start;
- str = mrb_str_substr(mrb, m->str, start, len);
+ str = mrb_str_substr(mrb, mrb_obj_value(m->str), start, len);
return str;
}
@@ -281,7 +281,7 @@ match_backref_number(mrb_state *mrb, mrb_value match, mrb_value backref)
int num;
struct re_registers *regs = RMATCH_REGS(match);
- mrb_value regexp = RMATCH(match)->regexp;
+ struct RRegexp *regexp = RMATCH(match)->regexp;
match_check(mrb, match);
switch(mrb_type(backref)) {
@@ -297,7 +297,7 @@ match_backref_number(mrb_state *mrb, mrb_value match, mrb_value backref)
name = mrb_string_value_cstr(mrb, &backref);
break;
}
- num = onig_name_to_backref_number(mrb_regex_ptr(regexp)->ptr,
+ num = onig_name_to_backref_number(regexp->ptr,
(const unsigned char*)name,
(const unsigned char*)name + strlen(name),
regs);
@@ -361,10 +361,7 @@ mrb_reg_check(mrb_state *mrb, mrb_value re)
if (!(RREGEXP(re)->ptr)) {
mrb_raise(mrb, E_TYPE_ERROR, "uninitialized Regexp");
}
- if (RREGEXP_SRC(re).tt == 0) {
- mrb_raise(mrb, E_TYPE_ERROR, "uninitialized Regexp");
- }
- if (!RREGEXP_SRC_PTR(re)) {
+ if (RREGEXP(re)->src == 0) {
mrb_raise(mrb, E_TYPE_ERROR, "uninitialized Regexp");
}
}
@@ -488,7 +485,7 @@ mrb_reg_prepare_re(mrb_state *mrb, mrb_value re, mrb_value str)
pattern = RREGEXP_SRC_PTR(re);
unescaped = mrb_reg_preprocess(mrb,
- pattern, pattern + RREGEXP_SRC_LEN(re), enc,
+ pattern, pattern + RREGEXP(re)->src->len, enc,
&fixed_enc, err);
if (mrb_nil_p(unescaped)) {
@@ -581,8 +578,8 @@ mrb_reg_search(mrb_state *mrb, mrb_value re, mrb_value str, mrb_int pos, mrb_int
onig_region_free(regs, 0);
}
- RMATCH(match)->str = str_new4(mrb, str.tt, str);
- RMATCH(match)->regexp = re;
+ RMATCH(match)->str = mrb_str_ptr(str);
+ RMATCH(match)->regexp = mrb_regex_ptr(re);
RMATCH(match)->rmatch->char_offset_updated = 0;
mrb_backref_set(mrb, match);
@@ -811,9 +808,7 @@ read_escaped_byte(const char **pp, const char *end, onig_errmsg_buffer err)
int code;
int meta_prefix = 0, ctrl_prefix = 0;
size_t len;
- int retbyte;
- retbyte = -1;
if (p == end || *p++ != '\\') {
//errcpy(err, "too short escaped multibyte character");
printf("too short escaped multibyte character");
@@ -1211,10 +1206,8 @@ mrb_reg_initialize(mrb_state *mrb, mrb_value obj, const char *s, long len, mrb_e
options & ARG_REG_OPTION_MASK, err,
sourcefile, sourceline);
if (!re->ptr) return -1;
- re->src = mrb_enc_str_new(mrb, s, len, enc);
+ re->src = mrb_str_ptr(mrb_enc_str_new(mrb, s, len, enc));
- /*OBJ_FREEZE(re->src);
- RB_GC_GUARD(unescaped);*/
return 0;
}
@@ -1360,6 +1353,15 @@ mrb_reg_init_copy(mrb_state *mrb, mrb_value re/*, mrb_value copy*/)
}
static int
+reg_equal(mrb_state *mrb, struct RRegexp *re1, struct RRegexp *re2)
+{
+ if (re1->ptr->options != re2->ptr->options) return FALSE;
+ if (!mrb_equal(mrb, mrb_obj_value(re1->src), mrb_obj_value(re2->src)))
+ return FALSE;
+ return TRUE;
+}
+
+static int
mrb_reg_equal(mrb_state *mrb, mrb_value re1, mrb_value re2)
{
if (mrb_obj_equal(mrb, re1, re2)) return TRUE;
@@ -1367,14 +1369,7 @@ mrb_reg_equal(mrb_state *mrb, mrb_value re1, mrb_value re2)
if (mrb_type(re2) != MRB_TT_REGEX) return FALSE;
mrb_reg_check(mrb, re1);
mrb_reg_check(mrb, re2);
- /*if (FL_TEST(re1, KCODE_FIXED) != FL_TEST(re2, KCODE_FIXED)) return Qfalse; */
- if (RREGEXP(re1)->ptr->options != RREGEXP(re2)->ptr->options) return FALSE;
- if (RREGEXP_SRC_LEN(re1) != RREGEXP_SRC_LEN(re2)) return FALSE;
- /*if (ENCODING_GET(re1) != ENCODING_GET(re2)) return mrb_false_value();*/
- if (memcmp(RREGEXP_SRC_PTR(re1), RREGEXP_SRC_PTR(re2), RREGEXP_SRC_LEN(re1)) == 0) {
- return TRUE;
- }
- return FALSE;
+ return reg_equal(mrb, RREGEXP(re1), RREGEXP(re2));
}
/* 15.2.15.7.3 */
@@ -1636,11 +1631,11 @@ mrb_reg_source(mrb_state *mrb, mrb_value re)
}
static int
-name_to_backref_number(mrb_state *mrb, struct re_registers *regs, mrb_value regexp, const char* name, const char* name_end)
+name_to_backref_number(mrb_state *mrb, struct re_registers *regs, struct RRegexp*regexp, const char* name, const char* name_end)
{
int num;
- num = onig_name_to_backref_number(RREGEXP(regexp)->ptr,
+ num = onig_name_to_backref_number(regexp->ptr,
(const unsigned char* )name, (const unsigned char* )name_end, regs);
if (num >= 1) {
return num;
@@ -1674,9 +1669,9 @@ match_alloc(mrb_state *mrb)
// NEWOBJ(match, struct RMatch);
// OBJSETUP(match, klass, T_MATCH);
- m->str = mrb_nil_value();
+ m->str = 0;
m->rmatch = 0;
- m->regexp = mrb_nil_value();
+ m->regexp = 0;
m->rmatch = mrb_malloc(mrb, sizeof(struct rmatch));//ALLOC(struct rmatch);
memset(m->rmatch, 0, sizeof(struct rmatch));
@@ -1718,13 +1713,12 @@ mrb_match_aref(mrb_state *mrb, /*int argc, mrb_value *argv,*/ mrb_value match)
{
mrb_value argv[16];
int argc;
- mrb_value idx, rest;
+ mrb_value idx;
match_check(mrb, match);
//mrb_scan_args(argc, argv, "11", &idx, &rest);
mrb_get_args(mrb, "*", &argv, &argc);
idx = argv[0];
- rest = argv[1];
if (argc<2) {
if (mrb_type(idx) == MRB_TT_FIXNUM) {
if (mrb_fixnum(idx) >= 0) {
@@ -1777,7 +1771,7 @@ update_char_offset(mrb_state *mrb, mrb_value match)
struct re_registers *regs;
int i, num_regs, num_pos;
long c;
- char *s, *p, *q, *e;
+ char *s, *p, *q;
mrb_encoding *enc;
pair_t *pairs;
@@ -1793,7 +1787,7 @@ update_char_offset(mrb_state *mrb, mrb_value match)
rm->char_offset_num_allocated = num_regs;
}
- enc = mrb_enc_get(mrb, RMATCH(match)->str);
+ enc = mrb_enc_get(mrb, mrb_obj_value(RMATCH(match)->str));
if (mrb_enc_mbmaxlen(enc) == 1) {
for (i = 0; i < num_regs; i++) {
rm->char_offset[i].beg = BEG(i);
@@ -1815,8 +1809,7 @@ update_char_offset(mrb_state *mrb, mrb_value match)
}
qsort(pairs, num_pos, sizeof(pair_t), pair_byte_cmp);
- s = p = RSTRING_PTR(RMATCH(match)->str);
- e = s + RSTRING_LEN(RMATCH(match)->str);
+ s = p = RMATCH(match)->str->buf;
c = 0;
for (i = 0; i < num_pos; i++) {
q = s + pairs[i].byte_pos;
@@ -1889,7 +1882,7 @@ match_array(mrb_state *mrb, mrb_value match, int start)
{
struct re_registers *regs;
mrb_value ary;
- mrb_value target;
+ struct RString *target;
int i;
match_check(mrb, match);
@@ -1902,7 +1895,7 @@ match_array(mrb_state *mrb, mrb_value match, int start)
mrb_ary_push(mrb, ary, mrb_nil_value());
}
else {
- mrb_value str = mrb_str_subseq(mrb, target, regs->beg[i], regs->end[i]-regs->beg[i]);
+ mrb_value str = mrb_str_subseq(mrb, mrb_obj_value(target), regs->beg[i], regs->end[i]-regs->beg[i]);
mrb_ary_push(mrb, ary, str);
}
}
@@ -2087,7 +2080,7 @@ mrb_match_offset(mrb_state *mrb, mrb_value match/*, mrb_value n*/)
mrb_value
mrb_reg_match_post(mrb_state *mrb, mrb_value match)
{
- mrb_value str;
+ struct RString *str;
long pos;
struct re_registers *regs;
@@ -2097,9 +2090,7 @@ mrb_reg_match_post(mrb_state *mrb, mrb_value match)
if (BEG(0) == -1) return mrb_nil_value();
str = RMATCH(match)->str;
pos = END(0);
- str = mrb_str_subseq(mrb, str, pos, RSTRING_LEN(str) - pos);
-
- return str;
+ return mrb_str_subseq(mrb, mrb_obj_value(str), pos, str->len - pos);
}
/* 15.2.16.3.9 */
@@ -2124,7 +2115,7 @@ mrb_reg_match_pre(mrb_state *mrb, mrb_value match)
match_check(mrb, match);
regs = RMATCH_REGS(match);
if (BEG(0) == -1) return mrb_nil_value();
- str = mrb_str_subseq(mrb, RMATCH(match)->str, 0, BEG(0));
+ str = mrb_str_subseq(mrb, mrb_obj_value(RMATCH(match)->str), 0, BEG(0));
return str;
}
@@ -2144,7 +2135,7 @@ static mrb_value
mrb_match_string(mrb_state *mrb, mrb_value match)
{
match_check(mrb, match);
- return RMATCH(match)->str; /* str is frozen */
+ return mrb_obj_value(RMATCH(match)->str);
}
/* 15.2.16.3.12 */
@@ -2441,7 +2432,7 @@ again:
static mrb_value
mrb_reg_inspect(mrb_state *mrb, mrb_value re)
{
- if (!RREGEXP(re)->ptr || mrb_nil_p(RREGEXP_SRC(re)) || !RREGEXP_SRC_PTR(re)) {
+ if (!RREGEXP(re)->ptr || !RREGEXP_SRC(re) || !RREGEXP_SRC_PTR(re)) {
return mrb_any_to_s(mrb, re);
}
return mrb_reg_desc(mrb, RREGEXP_SRC_PTR(re), RREGEXP_SRC_LEN(re), re);
@@ -2457,7 +2448,7 @@ mrb_reg_s_alloc(mrb_state *mrb, mrb_value dummy)
re = mrb_obj_alloc(mrb, MRB_TT_REGEX, mrb->regex_class);
re->ptr = 0;
- re->src.tt = 0;
+ re->src = 0;
re->usecnt = 0;
return mrb_obj_value(re);
@@ -2526,9 +2517,9 @@ mrb_match_inspect(mrb_state *mrb, mrb_value match)
struct re_registers *regs = RMATCH_REGS(match);
int num_regs = regs->num_regs;
struct backref_name_tag *names;
- mrb_value regexp = RMATCH(match)->regexp;
+ struct RRegexp *regexp = RMATCH(match)->regexp;
- if (regexp.value.p == 0) {
+ if (!regexp) {
return mrb_sprintf(mrb, "#<%s:%p>", cname, (void*)&match);
}
@@ -2537,7 +2528,7 @@ mrb_match_inspect(mrb_state *mrb, mrb_value match)
names = mrb_malloc(mrb, sizeof(struct backref_name_tag)*num_regs);
memset(names, 0, sizeof(struct backref_name_tag)*num_regs);
- onig_foreach_name(RREGEXP(regexp)->ptr,
+ onig_foreach_name(regexp->ptr,
match_inspect_name_iter, names);
str = mrb_str_new_cstr(mrb, "#<");//mrb_str_buf_new2("#<");
@@ -2587,8 +2578,9 @@ mrb_match_equal(mrb_state *mrb, mrb_value match1)
mrb_get_args(mrb, "o", &match2);
if (mrb_obj_equal(mrb, match1, match2)) return mrb_true_value();
if (mrb_type(match2) != MRB_TT_MATCH) return mrb_false_value();
- if (!mrb_str_equal(mrb, RMATCH(match1)->str, RMATCH(match2)->str)) return mrb_false_value();
- if (!mrb_reg_equal(mrb, RMATCH(match1)->regexp, RMATCH(match2)->regexp)) return mrb_false_value();
+ if (!mrb_str_equal(mrb, mrb_obj_value(RMATCH(match1)->str), mrb_obj_value(RMATCH(match2)->str)))
+ return mrb_false_value();
+ if (!reg_equal(mrb, RMATCH(match1)->regexp, RMATCH(match2)->regexp)) return mrb_false_value();
regs1 = RMATCH_REGS(match1);
regs2 = RMATCH_REGS(match2);
if (regs1->num_regs != regs2->num_regs) return mrb_false_value();
@@ -2767,7 +2759,7 @@ mrb_reg_regsub(mrb_state *mrb, mrb_value str, mrb_value src, struct re_registers
name_end += c == -1 ? mbclen(name_end, e, str_enc) : clen;
}
if (name_end < e) {
- no = name_to_backref_number(mrb, regs, regexp, name, name_end);
+ no = name_to_backref_number(mrb, regs, RREGEXP(regexp), name, name_end);
p = s = name_end + clen;
break;
}
diff --git a/src/re.h b/src/re.h
index 686120569..238b4e408 100644
--- a/src/re.h
+++ b/src/re.h
@@ -37,23 +37,23 @@ struct rmatch {
//};
struct RMatch {
MRUBY_OBJECT_HEADER;
- mrb_value str;
+ struct RString *str;
struct rmatch *rmatch;
- mrb_value regexp; /* RRegexp */
+ struct RRegexp *regexp;
};
struct RRegexp {
MRUBY_OBJECT_HEADER;
struct re_pattern_buffer *ptr;
- mrb_value src;
+ struct RString *src;
unsigned long usecnt;
};
#define mrb_regex_ptr(r) ((struct RRegexp*)((r).value.p))
#define RREGEXP(r) ((struct RRegexp*)((r).value.p))
#define RREGEXP_SRC(r) (RREGEXP(r)->src)
-#define RREGEXP_SRC_PTR(r) (((struct RString*)(RREGEXP_SRC(r).value.p))->buf)
-#define RREGEXP_SRC_LEN(r) RSTRING_LEN(RREGEXP(r)->src)
+#define RREGEXP_SRC_PTR(r) (RREGEXP_SRC(r)->buf)
+#define RREGEXP_SRC_LEN(r) (RREGEXP_SRC(r)->len)
int re_adjust_startpos(struct re_pattern_buffer *bufp, const char *string, int size, int startpos, int range);
typedef struct re_pattern_buffer Regexp;
diff --git a/src/string.c b/src/string.c
index e2987db57..466c3dee9 100644
--- a/src/string.c
+++ b/src/string.c
@@ -479,11 +479,11 @@ mrb_enc_cr_str_exact_copy(mrb_state *mrb, mrb_value dest, mrb_value src)
#endif //INCLUDE_ENCODING
mrb_value
-str_new4(mrb_state *mrb, enum mrb_vtype ttype, mrb_value str)
+str_new4(mrb_state *mrb, mrb_value str)
{
mrb_value str2;
- str2 = mrb_obj_value(mrb_obj_alloc(mrb, ttype, mrb->string_class));//str_alloc(klass);
+ str2 = mrb_obj_value(mrb_obj_alloc(mrb, MRB_TT_STRING, mrb->string_class));
RSTRING(str2)->len = RSTRING_LEN(str);
RSTRING(str2)->buf = RSTRING_PTR(str);
@@ -2225,7 +2225,7 @@ mrb_str_new_frozen(mrb_state *mrb, mrb_value orig)
}
}
else {
- str = str_new4(mrb, orig.tt, orig);
+ str = str_new4(mrb, orig);
}
return str;
}
diff --git a/src/time.c b/src/time.c
new file mode 100644
index 000000000..ed42f1f76
--- /dev/null
+++ b/src/time.c
@@ -0,0 +1,679 @@
+/*
+** time.c - Time class
+**
+** See Copyright Notice in mruby.h
+*/
+
+
+#include "mruby.h"
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+#include "mruby/class.h"
+#include "mruby/data.h"
+
+/* Time class configuration */
+#undef USE_GETTIMEOFDAY /* C99 does not have gettimeofday */
+#define USE_GETTIMEOFDAY /* need gettimeofday to retrieve microseconds */
+#undef USE_GMTIME_R /* C99 does not have reentrant gmtime_r */
+#ifndef _WIN32
+#define USE_GMTIME_R /* use reentrant gmtime_r */
+#endif
+#undef USE_TIMEGM /* C99 does not have timegm */
+#define USE_TIMEGM /* use faster gmtime */
+
+#ifdef USE_GETTIMEOFDAY
+#include <sys/time.h>
+#endif
+#ifndef USE_GMTIME_R
+#define gmtime_r(t,r) gmtime(t)
+#define localtime_r(t,r) localtime(t)
+#endif
+
+#ifndef USE_TIMEGM
+time_t
+timegm(struct tm *tm)
+{
+ time_t ret;
+ char *tz;
+
+ tz = getenv("TZ");
+ setenv("TZ", "", 1);
+ tzset();
+ ret = mktime(tm);
+ if (tz)
+ setenv("TZ", tz, 1);
+ else
+ unsetenv("TZ");
+ tzset();
+ return ret;
+}
+#endif
+
+/* Since we are limited to using ISO C89, this implementation is based
+* on time_t. That means the resolution of time is only precise to the
+* second level. Also, there are only 2 timezones, namely UTC and LOCAL.
+*/
+
+#ifndef mrb_bool_value
+#define mrb_bool_value(val) ((val) ? mrb_true_value() : mrb_false_value())
+#endif
+
+
+enum mrb_timezone {
+ MRB_TIMEZONE_NONE = 0,
+ MRB_TIMEZONE_UTC = 1,
+ MRB_TIMEZONE_LOCAL = 2,
+ MRB_TIMEZONE_LAST = 3
+};
+
+static const char *timezone_names[] = {
+ "none",
+ "UTC",
+ "LOCAL",
+ NULL
+};
+
+static const char *mon_names[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+};
+
+static const char *wday_names[] = {
+ "Sun", "Mon", "Tus", "Wed", "Thu", "Fri", "Sat",
+};
+
+struct mrb_time {
+ time_t sec;
+ time_t usec;
+ enum mrb_timezone timezone;
+ struct tm datetime;
+};
+
+static void
+mrb_time_free(mrb_state *mrb, void *ptr)
+{
+ mrb_free(mrb, ptr);
+}
+
+static struct mrb_data_type mrb_time_type = { "Time", mrb_time_free };
+
+/** Updates the datetime of a mrb_time based on it's timezone and
+seconds setting. Returns self on cussess, NULL of failure. */
+struct mrb_time*
+mrb_time_update_datetime(struct mrb_time *self)
+{
+ struct tm *aid;
+
+ if(self->timezone == MRB_TIMEZONE_UTC) {
+ aid = gmtime_r(&self->sec, &self->datetime);
+ }
+ else {
+#ifdef USE_GMTIME_R
+ tzset();
+#endif
+ aid = localtime_r(&self->sec, &self->datetime);
+ }
+ if(!aid) return NULL;
+#ifndef USE_GMTIME_R
+ self->datetime = *aid; // copy data
+#endif
+
+ return self;
+}
+
+static mrb_value
+mrb_time_wrap(mrb_state *mrb, struct RClass *tc, struct mrb_time *tm)
+{
+ return mrb_obj_value(Data_Wrap_Struct(mrb, tc, &mrb_time_type, tm));
+}
+
+
+/* Allocates a mrb_time object and initializes it. */
+static struct mrb_time*
+mrb_time_alloc(mrb_state *mrb, mrb_float seconds, enum mrb_timezone timezone)
+{
+ struct mrb_time *tm;
+
+ tm = mrb_malloc(mrb, sizeof(struct mrb_time));
+ tm->sec = (time_t)seconds;
+ tm->usec = (seconds - tm->sec) * 1.0e6;
+ tm->timezone = timezone;
+ mrb_time_update_datetime(tm);
+
+ return tm;
+}
+
+static mrb_value
+mrb_time_make(mrb_state *mrb, struct RClass *c, mrb_float seconds, enum mrb_timezone timezone)
+{
+ return mrb_time_wrap(mrb, c, mrb_time_alloc(mrb, seconds, timezone));
+}
+
+static struct mrb_time*
+current_time(mrb_state *mrb)
+{
+ struct mrb_time *tm;
+
+ tm = mrb_malloc(mrb, sizeof(*tm));
+#ifdef USE_GETTIMEOFDAY
+ {
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ tm->sec = tv.tv_sec;
+ tm->usec = tv.tv_usec;
+ }
+#else
+ tm->sec = time(NULL);
+ tm->usec = 0;
+#endif
+ tm->timezone = MRB_TIMEZONE_LOCAL;
+ mrb_time_update_datetime(tm);
+
+ return tm;
+}
+
+/* Allocates a new Time object with given millis value. */
+static mrb_value
+mrb_time_now(mrb_state *mrb, mrb_value self)
+{
+ return mrb_time_wrap(mrb, mrb_class_ptr(self), current_time(mrb));
+}
+
+/* 15.2.19.6.1 */
+/* Creates an instance of time at the given time in seconds, etc. */
+static mrb_value
+mrb_time_at(mrb_state *mrb, mrb_value self)
+{
+ mrb_float f;
+
+ mrb_get_args(mrb, "f", &f);
+ return mrb_time_make(mrb, mrb_class_ptr(self), f, MRB_TIMEZONE_LOCAL);
+}
+
+#ifdef _WIN32
+static unsigned int
+is_leapyear(unsigned int y)
+{
+ return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0);
+}
+
+static time_t
+timegm(struct tm *tm)
+{
+ static const unsigned int ndays[2][12] = {
+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+ {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+ };
+ time_t r = 0;
+ int i;
+ unsigned int *nday = (unsigned int*) ndays[is_leapyear(tm->tm_year+1900)];
+
+ for (i = 70; i < tm->tm_year; ++i)
+ r += is_leapyear(i+1900) ? 366*24*60*60 : 365*24*60*60;
+ for (i = 0; i < tm->tm_mon; ++i)
+ r += nday[i] * 24 * 60 * 60;
+ r += (tm->tm_mday - 1) * 24 * 60 * 60;
+ r += tm->tm_hour * 60 * 60;
+ r += tm->tm_min * 60;
+ r += tm->tm_sec;
+ return r;
+}
+#endif
+
+static struct mrb_time*
+time_mktime(mrb_state *mrb, mrb_int ayear, mrb_int amonth, mrb_int aday,
+ mrb_int ahour, mrb_int amin, mrb_int asec, mrb_int ausec,
+ enum mrb_timezone timezone)
+{
+ time_t nowsecs;
+ struct tm nowtime;
+
+ memset(&nowtime, 0, sizeof(struct tm));
+ nowtime.tm_year = (int)ayear - 1900;
+ nowtime.tm_mon = (int)amonth - 1;
+ nowtime.tm_mday = (int)aday;
+ nowtime.tm_hour = (int)ahour;
+ nowtime.tm_min = (int)amin;
+ nowtime.tm_sec = (int)asec;
+ nowtime.tm_isdst = -1;
+ if (timezone == MRB_TIMEZONE_UTC) {
+ nowsecs = timegm(&nowtime);
+ }
+ else {
+ nowsecs = mktime(&nowtime);
+ }
+ if (nowsecs < 0) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "Not a valid time.");
+ }
+
+ return mrb_time_alloc(mrb, nowsecs+ausec/10e6, timezone);
+}
+
+/* 15.2.19.6.2 */
+/* Creates an instance of time at the given time in UTC. */
+static mrb_value
+mrb_time_gm(mrb_state *mrb, mrb_value self)
+{
+ mrb_int ayear = 0.0, amonth = 1.0, aday = 1.0, ahour = 0.0,
+ amin = 0.0, asec = 0.0, ausec = 0.0;
+
+ mrb_get_args(mrb, "iiiiiii",
+ &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec);
+ return mrb_time_wrap(mrb, mrb_class_ptr(self),
+ time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_UTC));
+}
+
+
+/* 15.2.19.6.3 */
+/* Creates an instance of time at the given time in local time zone. */
+static mrb_value
+mrb_time_local(mrb_state *mrb, mrb_value self)
+{
+ mrb_float ayear = 0.0, amonth = 1.0, aday = 1.0, ahour = 0.0,
+ amin = 0.0, asec = 0.0, ausec = 0.0;
+
+ mrb_get_args(mrb, "fffffff",
+ &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec);
+ return mrb_time_wrap(mrb, mrb_class_ptr(self),
+ time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL));
+}
+
+
+static mrb_value
+mrb_time_eq(mrb_state *mrb, mrb_value self)
+{
+ mrb_value other;
+ struct mrb_time *tm1, *tm2;
+
+ mrb_get_args(mrb, "o", &other);
+ tm1 = mrb_get_datatype(mrb, self, &mrb_time_type);
+ tm2 = mrb_get_datatype(mrb, other, &mrb_time_type);
+ if (!tm1 || !tm2) return mrb_false_value();
+ if (tm1->sec == tm2->sec && tm1->usec == tm2->usec) {
+ return mrb_true_value();
+ }
+ return mrb_false_value();
+}
+
+static mrb_value
+mrb_time_cmp(mrb_state *mrb, mrb_value self)
+{
+ mrb_value other;
+ struct mrb_time *tm1, *tm2;
+
+ mrb_get_args(mrb, "o", &other);
+ tm1 = mrb_get_datatype(mrb, self, &mrb_time_type);
+ tm2 = mrb_get_datatype(mrb, other, &mrb_time_type);
+ if (!tm1 || !tm2) return mrb_nil_value();
+ if (tm1->sec > tm2->sec) {
+ return mrb_fixnum_value(1);
+ }
+ else if (tm1->sec < tm2->sec) {
+ return mrb_fixnum_value(-1);
+ }
+ /* tm1->sec == tm2->sec */
+ if (tm1->usec > tm2->usec) {
+ return mrb_fixnum_value(1);
+ }
+ else if (tm1->usec < tm2->usec) {
+ return mrb_fixnum_value(-1);
+ }
+ return mrb_fixnum_value(0);
+}
+
+static mrb_value
+mrb_time_plus(mrb_state *mrb, mrb_value self)
+{
+ mrb_float f;
+ struct mrb_time *tm;
+
+ mrb_get_args(mrb, "f", &f);
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return mrb_nil_value();
+ f += tm->sec;
+ f += (mrb_float)tm->usec / 1.0e6;
+ return mrb_time_make(mrb, mrb_obj_class(mrb, self), f, tm->timezone);
+}
+
+static mrb_value
+mrb_time_minus(mrb_state *mrb, mrb_value self)
+{
+ mrb_float f;
+ struct mrb_time *tm;
+
+ mrb_get_args(mrb, "f", &f);
+
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return mrb_nil_value();
+ f -= tm->sec;
+ f -= (mrb_float)tm->usec / 1.0e6;
+ return mrb_time_make(mrb, mrb_obj_class(mrb, self), f, tm->timezone);
+}
+
+/* 15.2.19.7.30 */
+/* Returns week day number of time. */
+static mrb_value
+mrb_time_wday(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return mrb_nil_value();
+ return mrb_fixnum_value(tm->datetime.tm_wday);
+}
+
+/* 15.2.19.7.31 */
+/* Returns year day number of time. */
+static mrb_value
+mrb_time_yday(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = mrb_check_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return mrb_nil_value();
+ return mrb_fixnum_value(tm->datetime.tm_yday);
+}
+
+/* 15.2.19.7.32 */
+/* Returns year of time. */
+static mrb_value
+mrb_time_year(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return mrb_nil_value();
+ return mrb_fixnum_value(tm->datetime.tm_year + 1900);
+}
+
+/* 15.2.19.7.33 */
+/* Returns name of time's timezone. */
+static mrb_value
+mrb_time_zone(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return mrb_nil_value();
+ if(tm->timezone <= MRB_TIMEZONE_NONE) return mrb_nil_value();
+ if(tm->timezone >= MRB_TIMEZONE_LAST) return mrb_nil_value();
+ return mrb_str_new_cstr(mrb, timezone_names[tm->timezone]);
+}
+
+/* 15.2.19.7.4 */
+/* Returns a string that describes the time. */
+static mrb_value
+mrb_time_asctime(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+ struct tm *d;
+ char buf[256];
+
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return mrb_nil_value();
+ d = &tm->datetime;
+ snprintf(buf, 256, "%s %s %02d %02d:%02d:%02d %s%d",
+ wday_names[d->tm_wday], mon_names[d->tm_mon], d->tm_mday,
+ d->tm_hour, d->tm_min, d->tm_sec,
+ tm->timezone == MRB_TIMEZONE_UTC ? "UTC " : "",
+ d->tm_year + 1900);
+ return mrb_str_new_cstr(mrb, buf);
+}
+
+/* 15.2.19.7.6 */
+/* Returns the day in the month of the time. */
+static mrb_value
+mrb_time_day(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return mrb_nil_value();
+ return mrb_fixnum_value(tm->datetime.tm_mday);
+}
+
+
+/* 15.2.19.7.7 */
+/* Returns true if daylight saving was applied for this time. */
+static mrb_value
+mrb_time_dstp(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return mrb_nil_value();
+ return mrb_bool_value(tm->datetime.tm_isdst);
+}
+
+/* 15.2.19.7.15 */
+/* Returns hour of time. */
+static mrb_value
+mrb_time_hour(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return mrb_nil_value();
+ return mrb_fixnum_value(tm->datetime.tm_hour);
+}
+
+/* 15.2.19.7.16 */
+/* Initializes a time by setting the amount of milliseconds since the epoch.*/
+static mrb_value
+mrb_time_initialize(mrb_state *mrb, mrb_value self)
+{
+ mrb_int ayear = 0, amonth = 1, aday = 1, ahour = 0,
+ amin = 0, asec = 0, ausec = 0;
+ struct mrb_time *tm;
+
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (tm) {
+ mrb_time_free(mrb, tm);
+ }
+ if (mrb->ci->argc == 0) {
+ tm = current_time(mrb);
+ }
+ else {
+ mrb_get_args(mrb, "iiiiiii",
+ &ayear, &amonth, &aday, &ahour, &amin, &asec, &ausec);
+ tm = time_mktime(mrb, ayear, amonth, aday, ahour, amin, asec, ausec, MRB_TIMEZONE_LOCAL);
+ }
+ DATA_PTR(self) = tm;
+ DATA_TYPE(self) = &mrb_time_type;
+ return self;
+}
+
+/* 15.2.19.7.17(x) */
+/* Initializes a copy of this time object. */
+static mrb_value
+mrb_time_initialize_copy(mrb_state *mrb, mrb_value copy)
+{
+ mrb_value src;
+ mrb_get_args(mrb, "o", &src);
+
+ if (mrb_obj_equal(mrb, copy, src)) return copy;
+ if (!mrb_obj_is_instance_of(mrb, src, mrb_obj_class(mrb, copy))) {
+ mrb_raise(mrb, E_TYPE_ERROR, "wrong argument class");
+ }
+ if (!DATA_PTR(copy)) {
+ DATA_PTR(copy) = mrb_malloc(mrb, sizeof(struct mrb_time));
+ DATA_TYPE(copy) = &mrb_time_type;
+ }
+ memcpy(DATA_PTR(copy), DATA_PTR(src), sizeof(struct mrb_time));
+ return copy;
+}
+
+/* 15.2.19.7.18 */
+/* Sets the timezone attribute of the Time object to LOCAL. */
+static mrb_value
+mrb_time_localtime(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return self;
+ tm->timezone = MRB_TIMEZONE_LOCAL;
+ mrb_time_update_datetime(tm);
+ return self;
+}
+
+/* 15.2.19.7.19 */
+/* Returns day of month of time. */
+static mrb_value
+mrb_time_mday(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return mrb_nil_value();
+ return mrb_fixnum_value(tm->datetime.tm_mday);
+}
+
+/* 15.2.19.7.20 */
+/* Returns minutes of time. */
+static mrb_value
+mrb_time_min(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return mrb_nil_value();
+ return mrb_fixnum_value(tm->datetime.tm_min);
+}
+
+/* 15.2.19.7.21 and 15.2.19.7.22 */
+/* Returns month of time. */
+static mrb_value
+mrb_time_mon(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return mrb_nil_value();
+ return mrb_fixnum_value(tm->datetime.tm_mon + 1);
+}
+
+/* 15.2.19.7.23 */
+/* Returns seconds in minute of time. */
+static mrb_value
+mrb_time_sec(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return mrb_nil_value();
+ return mrb_fixnum_value(tm->datetime.tm_sec);
+}
+
+
+/* 15.2.19.7.24 */
+/* Returns a Float with the time since the epoch in seconds. */
+static mrb_value
+mrb_time_to_f(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return mrb_nil_value();
+ return mrb_float_value((mrb_float)tm->sec + (mrb_float)tm->usec/1.0e6);
+}
+
+/* 15.2.19.7.25 */
+/* Returns a Fixnum with the time since the epoch in seconds. */
+static mrb_value
+mrb_time_to_i(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return mrb_nil_value();
+ return mrb_fixnum_value(tm->sec);
+}
+
+/* 15.2.19.7.26 */
+/* Returns a Float with the time since the epoch in microseconds. */
+static mrb_value
+mrb_time_usec(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return mrb_nil_value();
+ return mrb_fixnum_value(tm->usec);
+}
+
+/* 15.2.19.7.27 */
+/* Sets the timzeone attribute of the Time object to UTC. */
+static mrb_value
+mrb_time_utc(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if (tm) {
+ tm->timezone = MRB_TIMEZONE_UTC;
+ mrb_time_update_datetime(tm);
+ }
+ return self;
+}
+
+/* 15.2.19.7.28 */
+/* Returns true if this time is in the UTC timze zone false if not. */
+static mrb_value
+mrb_time_utcp(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_time *tm;
+ tm = mrb_get_datatype(mrb, self, &mrb_time_type);
+ if(!tm) return mrb_nil_value();
+ return mrb_bool_value(tm->timezone == MRB_TIMEZONE_UTC);
+}
+
+
+
+void
+mrb_init_time(mrb_state *mrb)
+{
+ struct RClass *tc;
+ /* ISO 15.2.19.2 */
+ tc = mrb_define_class(mrb, "Time", mrb->object_class);
+ MRB_SET_INSTANCE_TT(tc, MRB_TT_DATA);
+ mrb_include_module(mrb, tc, mrb_class_get(mrb, "Comparable"));
+ mrb_define_class_method(mrb, tc, "now", mrb_time_now, ARGS_NONE());
+ mrb_define_class_method(mrb, tc, "at", mrb_time_at, ARGS_ANY());
+ mrb_define_class_method(mrb, tc, "gm", mrb_time_gm, ARGS_REQ(1)|ARGS_OPT(6));
+ mrb_define_class_method(mrb, tc, "local", mrb_time_local, ARGS_REQ(1)|ARGS_OPT(6));
+
+ mrb_define_method(mrb, tc, "==" , mrb_time_eq , ARGS_REQ(1));
+ mrb_define_method(mrb, tc, "<=>" , mrb_time_cmp , ARGS_REQ(1));
+ mrb_define_method(mrb, tc, "+" , mrb_time_plus , ARGS_REQ(1));
+ mrb_define_method(mrb, tc, "-" , mrb_time_minus , ARGS_REQ(1));
+ mrb_define_method(mrb, tc, "to_s" , mrb_time_asctime, ARGS_NONE());
+ mrb_define_method(mrb, tc, "asctime", mrb_time_asctime, ARGS_NONE());
+ mrb_define_method(mrb, tc, "ctime" , mrb_time_asctime, ARGS_NONE());
+ mrb_define_method(mrb, tc, "day" , mrb_time_day , ARGS_NONE());
+ mrb_define_method(mrb, tc, "dst?" , mrb_time_dstp , ARGS_NONE());
+ mrb_define_method(mrb, tc, "gmt?" , mrb_time_utcp , ARGS_NONE());
+ mrb_define_method(mrb, tc, "gmtime" , mrb_time_utc , ARGS_NONE());
+ mrb_define_method(mrb, tc, "hour" , mrb_time_hour, ARGS_NONE());
+ mrb_define_method(mrb, tc, "localtime", mrb_time_localtime, ARGS_NONE());
+ mrb_define_method(mrb, tc, "mday" , mrb_time_mday, ARGS_NONE());
+ mrb_define_method(mrb, tc, "min" , mrb_time_min, ARGS_NONE());
+
+ mrb_define_method(mrb, tc, "mon" , mrb_time_mon, ARGS_NONE());
+ mrb_define_method(mrb, tc, "month", mrb_time_mon, ARGS_NONE());
+
+ mrb_define_method(mrb, tc, "sec" , mrb_time_sec, ARGS_NONE());
+ mrb_define_method(mrb, tc, "to_i", mrb_time_to_i, ARGS_NONE());
+ mrb_define_method(mrb, tc, "to_f", mrb_time_to_f, ARGS_NONE());
+ mrb_define_method(mrb, tc, "usec", mrb_time_usec, ARGS_NONE());
+ mrb_define_method(mrb, tc, "utc" , mrb_time_utc, ARGS_NONE());
+ mrb_define_method(mrb, tc, "utc?", mrb_time_utcp, ARGS_NONE());
+ mrb_define_method(mrb, tc, "wday", mrb_time_wday, ARGS_NONE());
+ mrb_define_method(mrb, tc, "yday", mrb_time_yday, ARGS_NONE());
+ mrb_define_method(mrb, tc, "year", mrb_time_year, ARGS_NONE());
+ mrb_define_method(mrb, tc, "zone", mrb_time_zone, ARGS_NONE());
+
+ mrb_define_method(mrb, tc, "initialize", mrb_time_initialize, ARGS_REQ(1));
+ mrb_define_method(mrb, tc, "initialize_copy", mrb_time_initialize_copy, ARGS_REQ(1));
+}
diff --git a/src/variable.c b/src/variable.c
index f4ec46789..d1fc18263 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -436,7 +436,7 @@ mrb_class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym id)
}
struct RClass *
-mrb_class_get(mrb_state *mrb, char *name)
+mrb_class_get(mrb_state *mrb, const char *name)
{
return mrb_class_from_sym(mrb, mrb->object_class, mrb_intern(mrb, name));
}
@@ -449,7 +449,7 @@ mrb_attr_get(mrb_state *mrb, mrb_value obj, mrb_sym id)
}
struct RClass *
-mrb_class_obj_get(mrb_state *mrb, char *name)
+mrb_class_obj_get(mrb_state *mrb, const char *name)
{
mrb_value mod = mrb_obj_value(mrb->object_class);
mrb_sym sym = mrb_intern(mrb, name);
diff --git a/src/vm.c b/src/vm.c
index 9915200de..9c79a7afe 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -261,14 +261,33 @@ mrb_yield(mrb_state *mrb, mrb_value b, mrb_value v)
return mrb_yield_with_self(mrb, b, 1, &v, mrb->stack[0]);
}
-void
+static void
localjump_error(mrb_state *mrb, const char *kind)
{
char buf[256];
mrb_value exc;
snprintf(buf, 256, "unexpected %s", kind);
- exc = mrb_exc_new(mrb, E_LOCALJUMP_ERROR, buf, sizeof(buf));
+ exc = mrb_exc_new(mrb, E_LOCALJUMP_ERROR, buf, strlen(buf));
+ mrb->exc = mrb_object(exc);
+}
+
+static void
+argnum_error(mrb_state *mrb, int num)
+{
+ char buf[256];
+ mrb_value exc;
+
+ if (mrb->ci->mid) {
+ snprintf(buf, 256, "'%s': wrong number of arguments (%d for %d)",
+ mrb_sym2name(mrb, mrb->ci->mid),
+ mrb->ci->argc, num);
+ }
+ else {
+ snprintf(buf, 256, "wrong number of arguments (%d for %d)",
+ mrb->ci->argc, num);
+ }
+ exc = mrb_exc_new(mrb, E_ARGUMENT_ERROR, buf, strlen(buf));
mrb->exc = mrb_object(exc);
}
@@ -717,7 +736,9 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
ci->target_class = m->target_class;
ci->proc = m;
if (m->env) {
- ci->mid = m->env->mid;
+ if (m->env->mid) {
+ ci->mid = m->env->mid;
+ }
if (!m->env->stack) {
m->env->stack = mrb->stack;
}
@@ -895,10 +916,8 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
if (mrb->ci->proc && MRB_PROC_STRICT_P(mrb->ci->proc)) {
if (argc >= 0) {
if (argc < m1 + m2 || (r == 0 && argc > len)) {
- fprintf(stderr, "'%s': wrong number of arguments (%d for %d)\n",
- mrb_sym2name(mrb, mrb->ci->mid),
- mrb->ci->argc, m1+m2);
- exit(1);
+ argnum_error(mrb, m1+m2);
+ goto L_RAISE;
}
}
}
@@ -992,6 +1011,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
case OP_R_RETURN:
if (proc->env->cioff < 0) {
localjump_error(mrb, "return");
+ goto L_RAISE;
}
ci = mrb->ci = mrb->cibase + proc->env->cioff;
break;
diff --git a/src/vm_core.h b/src/vm_core.h
deleted file mode 100644
index 46eb99969..000000000
--- a/src/vm_core.h
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
-** vm_core.h - RiteVM core
-**
-** See Copyright Notice in mruby.h
-*/
-
-#ifndef RUBY_VM_CORE_H
-#define RUBY_VM_CORE_H
-
-#define RUBY_VM_THREAD_MODEL 2
-
-//#include "ruby/ruby.h"
-#include "st.h" /* define ANYARGS */
-
-//#include "node.h"
-//#include "debug.h"
-//#include "vm_opts.h"
-//#include "id.h"
-#include "method.h"
-
-#if defined(_WIN32)
-#include "thread_win32.h"
-#elif defined(HAVE_PTHREAD_H)
-#include "thread_pthread.h"
-#else
-#error "unsupported thread type"
-#endif
-
-#ifndef ENABLE_VM_OBJSPACE
-#ifdef _WIN32
-/*
- * TODO: object space indenpendent st_table.
- * socklist needs st_table in mrb_w32_sysinit(), before object space
- * initialization.
- * It is too early now to change st_hash_type, since it breaks binary
- * compatibility.
- */
-#define ENABLE_VM_OBJSPACE 0
-#else
-#define ENABLE_VM_OBJSPACE 1
-#endif
-#endif
-
-#include <setjmp.h>
-#include <signal.h>
-
-//#ifndef NSIG
-//# define NSIG (_SIGMAX + 1) /* For QNX */
-//#endif
-
-//#define RUBY_NSIG NSIG
-
-#ifdef HAVE_STDARG_PROTOTYPES
-#include <stdarg.h>
-#define va_init_list(a,b) va_start(a,b)
-#else
-#include <varargs.h>
-#define va_init_list(a,b) va_start(a)
-#endif
-
-#if defined(SIGSEGV) && defined(HAVE_SIGALTSTACK) && defined(SA_SIGINFO) && !defined(__NetBSD__)
-#define USE_SIGALTSTACK
-#endif
-
-/*****************/
-/* configuration */
-/*****************/
-
-/* gcc ver. check */
-#if defined(__GNUC__) && __GNUC__ >= 2
-
-#if OPT_TOKEN_THREADED_CODE
-#if OPT_DIRECT_THREADED_CODE
-#undef OPT_DIRECT_THREADED_CODE
-#endif
-#endif
-
-#else /* defined(__GNUC__) && __GNUC__ >= 2 */
-
-/* disable threaded code options */
-#if OPT_DIRECT_THREADED_CODE
-#undef OPT_DIRECT_THREADED_CODE
-#endif
-#if OPT_TOKEN_THREADED_CODE
-#undef OPT_TOKEN_THREADED_CODE
-#endif
-#endif
-
-/* call threaded code */
-#if OPT_CALL_THREADED_CODE
-#if OPT_DIRECT_THREADED_CODE
-#undef OPT_DIRECT_THREADED_CODE
-#endif /* OPT_DIRECT_THREADED_CODE */
-#if OPT_STACK_CACHING
-#undef OPT_STACK_CACHING
-#endif /* OPT_STACK_CACHING */
-#endif /* OPT_CALL_THREADED_CODE */
-
-/* likely */
-#if __GNUC__ >= 3
-#define LIKELY(x) (__builtin_expect((x), 1))
-#define UNLIKELY(x) (__builtin_expect((x), 0))
-#else /* __GNUC__ >= 3 */
-#define LIKELY(x) (x)
-#define UNLIKELY(x) (x)
-#endif /* __GNUC__ >= 3 */
-
-#if __GNUC__ >= 3
-#define UNINITIALIZED_VAR(x) x = x
-#else
-#define UNINITIALIZED_VAR(x) x
-#endif
-
-typedef unsigned long mrb_num_t;
-
-/* iseq data type */
-
-struct iseq_compile_data_ensure_node_stack;
-
-typedef struct mrb_compile_option_struct {
- int inline_const_cache;
- int peephole_optimization;
- int tailcall_optimization;
- int specialized_instruction;
- int operands_unification;
- int instructions_unification;
- int stack_caching;
- int trace_instruction;
- int debug_level;
-} mrb_compile_option_t;
-
-struct iseq_inline_cache_entry {
- mrb_value ic_vmstat;
- mrb_value ic_class;
- union {
- mrb_value value;
- mrb_method_entry_t *method;
- long index;
- } ic_value;
-};
-
-#if 1
-#define GetCoreDataFromValue(obj, type, ptr) do { \
- ptr = (type*)DATA_PTR(obj); \
-} while (0)
-#else
-#define GetCoreDataFromValue(obj, type, ptr) Data_Get_Struct(obj, type, ptr)
-#endif
-
-#define GetISeqPtr(obj, ptr) \
- GetCoreDataFromValue(obj, mrb_iseq_t, ptr)
-
-struct mrb_iseq_struct;
-
-//enum ruby_special_exceptions {
-// ruby_error_reenter,
-// ruby_error_nomemory,
-// ruby_error_sysstack,
-// ruby_special_error_count
-//};
-
-#define GetVMPtr(obj, ptr) \
- GetCoreDataFromValue(obj, mrb_vm_t, ptr)
-
-#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
-struct mrb_objspace;
-void mrb_objspace_free(struct mrb_objspace *);
-#endif
-
-typedef struct mrb_block_struct {
- mrb_value self; /* share with method frame if it's only block */
- mrb_value *lfp; /* share with method frame if it's only block */
- mrb_value *dfp; /* share with method frame if it's only block */
- mrb_iseq_t *iseq;
- mrb_value proc;
-} mrb_block_t;
-
-#define GetThreadPtr(obj, ptr) \
- GetCoreDataFromValue(obj, mrb_thread_t, ptr)
-
-//typedef RUBY_JMP_BUF mrb_jmpbuf_t; /* kusuda */
-#define mrb_jmpbuf_t void* /* kusuda */
-
-struct mrb_vm_protect_tag {
- struct mrb_vm_protect_tag *prev;
-};
-
-#define RUBY_VM_VALUE_CACHE_SIZE 0x1000
-#define USE_VALUE_CACHE 0
-
-struct mrb_mutex_struct;
-
-
-/* iseq.c */
-mrb_value mrb_iseq_new(NODE*, mrb_value, mrb_value, mrb_value, mrb_value, mrb_value);
-mrb_value mrb_iseq_new_top(NODE *node, mrb_value name, mrb_value filename, mrb_value filepath, mrb_value parent);
-mrb_value mrb_iseq_new_main(NODE *node, mrb_value filename, mrb_value filepath);
-mrb_value mrb_iseq_new_with_bopt(NODE*, mrb_value, mrb_value, mrb_value, mrb_value, mrb_value, mrb_value, mrb_value);
-mrb_value mrb_iseq_new_with_opt(NODE*, mrb_value, mrb_value, mrb_value, mrb_value, mrb_value, mrb_value, const mrb_compile_option_t*);
-mrb_value mrb_iseq_compile(mrb_value src, mrb_value file, mrb_value line);
-mrb_value mrb_iseq_disasm(mrb_value self);
-int mrb_iseq_disasm_insn(mrb_value str, mrb_value *iseqval, size_t pos, mrb_iseq_t *iseq, mrb_value child);
-const char *ruby_node_name(int node);
-int mrb_iseq_first_lineno(mrb_iseq_t *iseq);
-
-RUBY_EXTERN mrb_value mrb_cISeq;
-RUBY_EXTERN mrb_value mrb_cRubyVM;
-RUBY_EXTERN mrb_value mrb_cEnv;
-RUBY_EXTERN mrb_value mrb_mRubyVMFrozenCore;
-
-/* each thread has this size stack : 128KB */
-#define RUBY_VM_THREAD_STACK_SIZE (128 * 1024)
-
-#define GetProcPtr(obj, ptr) \
- GetCoreDataFromValue(obj, mrb_proc_t, ptr)
-
-typedef struct {
- mrb_block_t block;
-
- mrb_value envval; /* for GC mark */
- mrb_value blockprocval;
- int safe_level;
- int is_from_method;
- int is_lambda;
-} mrb_proc_t;
-
-#define GetEnvPtr(obj, ptr) \
- GetCoreDataFromValue(obj, mrb_env_t, ptr)
-
-typedef struct {
- mrb_value *env;
- int env_size;
- int local_size;
- mrb_value prev_envval; /* for GC mark */
- mrb_block_t block;
-} mrb_env_t;
-
-//#define GetBindingPtr(obj, ptr)
-// GetCoreDataFromValue(obj, mrb_binding_t, ptr)
-
-//typedef struct {
-// mrb_value env;
-// mrb_value filename;
-// unsigned short line_no;
-//} mrb_binding_t;
-
-/* used by compile time and send insn */
-#define VM_CALL_ARGS_SPLAT_BIT (0x01 << 1)
-#define VM_CALL_ARGS_BLOCKARG_BIT (0x01 << 2)
-#define VM_CALL_FCALL_BIT (0x01 << 3)
-#define VM_CALL_VCALL_BIT (0x01 << 4)
-#define VM_CALL_TAILCALL_BIT (0x01 << 5)
-#define VM_CALL_TAILRECURSION_BIT (0x01 << 6)
-#define VM_CALL_SUPER_BIT (0x01 << 7)
-#define VM_CALL_OPT_SEND_BIT (0x01 << 8)
-
-#define VM_SPECIAL_OBJECT_VMCORE 0x01
-#define VM_SPECIAL_OBJECT_CBASE 0x02
-#define VM_SPECIAL_OBJECT_CONST_BASE 0x03
-
-#define VM_FRAME_MAGIC_METHOD 0x11
-#define VM_FRAME_MAGIC_BLOCK 0x21
-#define VM_FRAME_MAGIC_CLASS 0x31
-#define VM_FRAME_MAGIC_TOP 0x41
-#define VM_FRAME_MAGIC_FINISH 0x51
-#define VM_FRAME_MAGIC_CFUNC 0x61
-#define VM_FRAME_MAGIC_PROC 0x71
-#define VM_FRAME_MAGIC_IFUNC 0x81
-#define VM_FRAME_MAGIC_EVAL 0x91
-#define VM_FRAME_MAGIC_LAMBDA 0xa1
-#define VM_FRAME_MAGIC_MASK_BITS 8
-#define VM_FRAME_MAGIC_MASK (~(~0<<VM_FRAME_MAGIC_MASK_BITS))
-
-#define VM_FRAME_TYPE(cfp) ((cfp)->flag & VM_FRAME_MAGIC_MASK)
-
-/* other frame flag */
-#define VM_FRAME_FLAG_PASSED 0x0100
-
-#define RUBYVM_CFUNC_FRAME_P(cfp) \
- (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC)
-
-/* inline cache */
-typedef struct iseq_inline_cache_entry *IC;
-
-extern mrb_value ruby_vm_global_state_version;
-
-#define GET_VM_STATE_VERSION() (ruby_vm_global_state_version)
-#define INC_VM_STATE_VERSION() \
- (ruby_vm_global_state_version = (ruby_vm_global_state_version+1) & 0x8fffffff)
-void mrb_vm_change_state(void);
-
-typedef mrb_value CDHASH;
-
-#define GC_GUARDED_PTR(p) ((mrb_value)((mrb_value)(p) | 0x01))
-#define GC_GUARDED_PTR_REF(p) ((void *)(((mrb_value)p) & ~0x03))
-#define GC_GUARDED_PTR_P(p) (((mrb_value)p) & 0x01)
-
-#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp) (cfp+1)
-#define RUBY_VM_NEXT_CONTROL_FRAME(cfp) (cfp-1)
-#define RUBY_VM_END_CONTROL_FRAME(th) \
- ((mrb_control_frame_t *)((th)->stack + (th)->stack_size))
-#define RUBY_VM_VALID_CONTROL_FRAME_P(cfp, ecfp) \
- ((void *)(ecfp) > (void *)(cfp))
-#define RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp) \
- (!RUBY_VM_VALID_CONTROL_FRAME_P((cfp), RUBY_VM_END_CONTROL_FRAME(th)))
-
-#define RUBY_VM_IFUNC_P(ptr) (BUILTIN_TYPE(ptr) == T_NODE)
-#define RUBY_VM_NORMAL_ISEQ_P(ptr) \
- (ptr && !RUBY_VM_IFUNC_P(ptr))
-
-#define RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp) ((mrb_block_t *)(&(cfp)->self))
-#define RUBY_VM_GET_CFP_FROM_BLOCK_PTR(b) \
- ((mrb_control_frame_t *)((mrb_value *)(b) - 5))
-
-/* VM related object allocate functions */
-//mrb_value mrb_thread_alloc(mrb_value klass);
-mrb_value mrb_proc_alloc(mrb_value klass);
-
-/* for debug */
-extern void mrb_vmdebug_stack_dump_raw(mrb_thread_t *, mrb_control_frame_t *);
-#define SDR() mrb_vmdebug_stack_dump_raw(GET_THREAD(), GET_THREAD()->cfp)
-#define SDR2(cfp) mrb_vmdebug_stack_dump_raw(GET_THREAD(), (cfp))
-void mrb_vm_bugreport(void);
-
-/* functions about thread/vm execution */
-mrb_value mrb_iseq_eval(mrb_value iseqval);
-mrb_value mrb_iseq_eval_main(mrb_value iseqval);
-void mrb_enable_interrupt(void);
-void mrb_disable_interrupt(void);
-//int mrb_thread_method_id_and_class(mrb_thread_t *th, mrb_sym *idp, mrb_value *klassp);
-
-mrb_value mrb_vm_invoke_proc(mrb_thread_t *th, mrb_proc_t *proc, mrb_value self,
- int argc, const mrb_value *argv, const mrb_block_t *blockptr);
-mrb_value mrb_vm_make_proc(mrb_thread_t *th, const mrb_block_t *block, mrb_value klass);
-mrb_value mrb_vm_make_env_object(mrb_thread_t *th, mrb_control_frame_t *cfp);
-
-//void mrb_thread_start_timer_thread(void);
-//void mrb_thread_stop_timer_thread(void);
-//void mrb_thread_reset_timer_thread(void);
-//void *mrb_thread_call_with_gvl(void *(*func)(void *), void *data1);
-int ruby_thread_has_gvl_p(void);
-mrb_value mrb_make_backtrace(void);
-typedef int mrb_backtrace_iter_func(void *, mrb_value, int, mrb_value);
-int mrb_backtrace_each(mrb_backtrace_iter_func *iter, void *arg);
-//mrb_control_frame_t *mrb_vm_get_ruby_level_next_cfp(mrb_thread_t *th, mrb_control_frame_t *cfp);
-int mrb_vm_get_sourceline(const mrb_control_frame_t *);
-mrb_value mrb_name_err_mesg_new(mrb_value obj, mrb_value mesg, mrb_value recv, mrb_value method);
-
-NOINLINE(void mrb_gc_save_machine_context(mrb_thread_t *));
-
-//#define sysstack_error GET_VM()->special_exceptions[ruby_error_sysstack]
-
-mrb_value mrb_str_resurrect(mrb_value str);
-mrb_value mrb_ary_resurrect(mrb_value ary);
-
-/* for thread */
-
-#if RUBY_VM_THREAD_MODEL == 2
-RUBY_EXTERN mrb_thread_t *ruby_current_thread;
-extern mrb_vm_t *ruby_current_vm;
-
-#define GET_VM() ruby_current_vm
-#define GET_THREAD() ruby_current_thread
-#define mrb_thread_set_current_raw(th) (void)(ruby_current_thread = (th))
-#define mrb_thread_set_current(th) do { \
- mrb_thread_set_current_raw(th); \
- th->vm->running_thread = th; \
-} while (0)
-
-#else
-#error "unsupported thread model"
-#endif
-
-#define RUBY_VM_SET_INTERRUPT(th) ((th)->interrupt_flag |= 0x02)
-#define RUBY_VM_SET_TIMER_INTERRUPT(th) ((th)->interrupt_flag |= 0x01)
-#define RUBY_VM_SET_FINALIZER_INTERRUPT(th) ((th)->interrupt_flag |= 0x04)
-#define RUBY_VM_INTERRUPTED(th) ((th)->interrupt_flag & 0x02)
-
-void mrb_threadptr_check_signal(mrb_thread_t *mth);
-//void mrb_threadptr_signal_raise(mrb_thread_t *th, int sig);
-void mrb_threadptr_signal_exit(mrb_state *mrb, mrb_thread_t *th);
-//void mrb_threadptr_execute_interrupts(mrb_thread_t *);
-
-void mrb_thread_lock_unlock(mrb_thread_lock_t *);
-void mrb_thread_lock_destroy(mrb_thread_lock_t *);
-
-//#define RUBY_VM_CHECK_INTS_TH(th) do { \
-// if (UNLIKELY(th->interrupt_flag)) { \
-// mrb_threadptr_execute_interrupts(th); \
-// } \
-//} while (0)
-
-//#define RUBY_VM_CHECK_INTS() \
-// RUBY_VM_CHECK_INTS_TH(GET_THREAD())
-
-/* tracer */
-//void
-//mrb_threadptr_exec_event_hooks(mrb_thread_t *th, mrb_event_flag_t flag, mrb_value self, mrb_sym id, mrb_value klass);
-#if 0
-#define EXEC_EVENT_HOOK(th, flag, self, id, klass) do { \
- mrb_event_flag_t wait_event__ = th->event_flags; \
- if (UNLIKELY(wait_event__)) { \
- if (wait_event__ & (flag | RUBY_EVENT_VM)) { \
- mrb_threadptr_exec_event_hooks(th, flag, self, id, klass); \
- } \
- } \
-} while (0)
-#endif
-#endif /* RUBY_VM_CORE_H */