summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/mruby.h18
-rw-r--r--include/mruby/class.h4
-rw-r--r--include/mruby/data.h1
-rw-r--r--include/mruby/hash.h11
-rw-r--r--include/mruby/object.h4
-rw-r--r--include/mruby/range.h2
-rw-r--r--include/mruby/string.h7
-rw-r--r--mrblib/array.rb4
-rw-r--r--mrblib/hash.rb52
-rw-r--r--mrblib/kernel.rb64
-rw-r--r--mrblib/numeric.rb5
-rw-r--r--mrblib/range.rb17
-rw-r--r--src/array.c7
-rw-r--r--src/class.c43
-rw-r--r--src/codegen.c1
-rw-r--r--src/compile.h8
-rw-r--r--src/etc.c19
-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.y42
-rw-r--r--src/pool.c11
-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.c31
-rw-r--r--test/test_time.rb48
33 files changed, 1143 insertions, 251 deletions
diff --git a/include/mruby.h b/include/mruby.h
index 6efa54858..ab9f5ee92 100644
--- a/include/mruby.h
+++ b/include/mruby.h
@@ -68,7 +68,7 @@ typedef struct mrb_value {
mrb_int i;
mrb_sym sym;
} value;
- enum mrb_vtype tt;
+ enum mrb_vtype tt:8;
} mrb_value;
#define mrb_type(o) (o).tt
@@ -300,8 +300,8 @@ mrb_value mrb_instance_new(mrb_state *mrb, mrb_value cv);
struct RClass * mrb_class_new(mrb_state *mrb, struct RClass *super);
struct RClass * mrb_module_new(mrb_state *mrb);
struct RClass * mrb_class_from_sym(mrb_state *mrb, struct RClass *klass, mrb_sym name);
-struct RClass * mrb_class_get(mrb_state *mrb, char *name);
-struct RClass * mrb_class_obj_get(mrb_state *mrb, char *name);
+struct RClass * mrb_class_get(mrb_state *mrb, const char *name);
+struct RClass * mrb_class_obj_get(mrb_state *mrb, const char *name);
mrb_value mrb_obj_dup(mrb_state *mrb, mrb_value obj);
mrb_value mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method);
@@ -342,6 +342,7 @@ void *mrb_realloc(mrb_state*, void*, size_t);
void *mrb_obj_alloc(mrb_state*, enum mrb_vtype, struct RClass*);
void *mrb_free(mrb_state*, void*);
+mrb_value mrb_str_new(mrb_state *mrb, const char *p, size_t len); /* mrb_str_new */
mrb_value mrb_str_new_cstr(mrb_state*, const char*);
mrb_state* mrb_open(void);
@@ -371,17 +372,6 @@ void mrb_gc_mark(mrb_state*,struct RBasic*);
#define mrb_gc_mark_value(mrb,val) do {\
if ((val).tt >= MRB_TT_OBJECT) mrb_gc_mark((mrb), mrb_object(val));\
} while (0);
-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 RClass*);
-size_t mrb_gc_mark_ht_size(mrb_state*, struct RClass*);
-void mrb_gc_free_ht(mrb_state*, struct RClass*);
void mrb_field_write_barrier(mrb_state *, struct RBasic*, struct RBasic*);
#define mrb_field_write_barrier_value(mrb, obj, val) do{\
if ((val.tt >= MRB_TT_OBJECT)) mrb_field_write_barrier((mrb), (obj), mrb_object(val));\
diff --git a/include/mruby/class.h b/include/mruby/class.h
index 0713f9b36..62829bd68 100644
--- a/include/mruby/class.h
+++ b/include/mruby/class.h
@@ -64,13 +64,15 @@ struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb_sym);
struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym);
void mrb_define_method_vm(mrb_state*, struct RClass*, mrb_sym, mrb_value);
void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, struct RProc *);
+void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, int aspec);
struct RClass *mrb_class_outer_module(mrb_state*, struct RClass *);
struct RProc *mrb_method_search_vm(mrb_state*, struct RClass**, mrb_sym);
struct RProc *mrb_method_search(mrb_state*, struct RClass*, mrb_sym);
int mrb_respond_to(mrb_state *mrb, mrb_value obj, mrb_sym mid);
-void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, int aspec);
+int mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c);
+struct RClass* mrb_class_real(struct RClass* cl);
void mrb_obj_call_init(mrb_state *mrb, mrb_value obj, int argc, mrb_value *argv);
diff --git a/include/mruby/data.h b/include/mruby/data.h
index f839389f9..d4ce82e40 100644
--- a/include/mruby/data.h
+++ b/include/mruby/data.h
@@ -38,6 +38,7 @@ struct RData *mrb_data_object_alloc(mrb_state *mrb, struct RClass* klass, void *
#define RDATA(obj) ((struct RData *)((obj).value.p))
#define DATA_PTR(d) (RDATA(d)->data)
#define DATA_TYPE(d) (RDATA(d)->type)
+void *mrb_get_datatype(mrb_state *mrb, mrb_value, const struct mrb_data_type*);
void *mrb_check_datatype(mrb_state *mrb, mrb_value, const struct mrb_data_type*);
#define Data_Get_Struct(mrb,obj,type,sval) do {\
sval = mrb_check_datatype(mrb, obj, type); \
diff --git a/include/mruby/hash.h b/include/mruby/hash.h
index 94f6a693f..3a15ecd1d 100644
--- a/include/mruby/hash.h
+++ b/include/mruby/hash.h
@@ -9,8 +9,8 @@
struct RHash {
MRUBY_OBJECT_HEADER;
+ struct kh_iv *iv;
struct kh_ht *ht;
- mrb_value ifnone;
};
#define N 624
@@ -47,12 +47,11 @@ void ruby_setenv(mrb_state *mrb, const char *name, const char *value);
/* RHASH_TBL allocates st_table if not available. */
#define RHASH(obj) ((struct RHash*)((obj).value.p))
-#define RHASH_TBL(h) mrb_hash_tbl(h)
-#define RHASH_H_TBL(h) (RHASH(h)->ht)
-#define RHASH_SIZE(h) (RHASH_H_TBL(h)->size)
+#define RHASH_TBL(h) (RHASH(h)->ht)
+#define RHASH_SIZE(h) (RHASH_TBL(h)->size)
#define RHASH_EMPTY_P(h) (RHASH_SIZE(h) == 0)
-#define RHASH_IFNONE(h) (RHASH(h)->ifnone)
-#define RHASH_PROCDEFAULT(h) (RHASH(h)->ifnone)
+#define RHASH_IFNONE(h) mrb_iv_get(mrb, (h), mrb_intern(mrb, "ifnone"))
+#define RHASH_PROCDEFAULT(h) RHASH_IFNONE(h)
struct kh_ht * mrb_hash_tbl(mrb_state *mrb, mrb_value hash);
#define MRB_HASH_PROC_DEFAULT 256
diff --git a/include/mruby/object.h b/include/mruby/object.h
index a4d2d2dac..0c3f3a6dd 100644
--- a/include/mruby/object.h
+++ b/include/mruby/object.h
@@ -7,8 +7,8 @@
#ifndef MRUBY_OBJECT_H
#define MRUBY_OBJECT_H
-#define MRUBY_OBJECT_HEADER \
- enum mrb_vtype tt:8;\
+#define MRUBY_OBJECT_HEADER \
+ enum mrb_vtype tt:8; \
int color:3;\
unsigned int flags:21;\
struct RClass *c;\
diff --git a/include/mruby/range.h b/include/mruby/range.h
index 9a59f645a..1b07ca197 100644
--- a/include/mruby/range.h
+++ b/include/mruby/range.h
@@ -21,7 +21,5 @@ struct RRange {
mrb_value mrb_range_new(mrb_state*, mrb_value, mrb_value, int);
mrb_int mrb_range_beg_len(mrb_state *mrb, mrb_value range, mrb_int *begp, mrb_int *lenp, mrb_int len, mrb_int err);
-int mrb_obj_is_instance_of(mrb_state *mrb, mrb_value obj, struct RClass* c);
-struct RClass* mrb_class_real(struct RClass* cl);
#endif /* MRUBY_RANGE_H */
diff --git a/include/mruby/string.h b/include/mruby/string.h
index 5a2c46a99..6fe2cc9fd 100644
--- a/include/mruby/string.h
+++ b/include/mruby/string.h
@@ -70,7 +70,6 @@ void mrb_str_concat(mrb_state*, mrb_value, mrb_value);
mrb_value mrb_obj_to_str(mrb_state*, mrb_value);
mrb_value mrb_str_plus(mrb_state*, mrb_value, mrb_value);
mrb_value mrb_obj_as_string(mrb_state *mrb, mrb_value obj);
-mrb_value mrb_str_new(mrb_state *mrb, const char *p, size_t len); /* mrb_str_new */
mrb_value mrb_str_resize(mrb_state *mrb, mrb_value str, size_t len); /* mrb_str_resize */
mrb_value mrb_string_value(mrb_state *mrb, mrb_value *ptr); /* StringValue */
mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, int len);
@@ -79,8 +78,8 @@ mrb_value mrb_str_buf_new(mrb_state *mrb, size_t capa);
mrb_value mrb_str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len);
mrb_value str_buf_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len);
-char * mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr);
-char * mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr);
+char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr);
+char *mrb_string_value_ptr(mrb_state *mrb, mrb_value ptr);
mrb_value mrb_str_subseq(mrb_state *mrb, mrb_value str, long beg, long len);
size_t mrb_str_sublen(mrb_state *mrb, mrb_value str, long pos);
mrb_value mrb_str_size(mrb_state *mrb, mrb_value self);
@@ -111,7 +110,7 @@ void mrb_str_setter(mrb_state *mrb, mrb_value val, mrb_sym id, mrb_value *var);
int mrb_str_is_ascii_only_p(mrb_state *mrb, mrb_value str);
mrb_value mrb_str_inspect(mrb_state *mrb, mrb_value str);
int mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2);
-mrb_value str_new4(mrb_state *mrb, enum mrb_vtype ttype, mrb_value str);
+mrb_value str_new4(mrb_state *mrb, mrb_value str);
mrb_value * mrb_svar(mrb_int cnt);
mrb_value mrb_str_drop_bytes(mrb_state *mrb, mrb_value str, long len);
mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str);
diff --git a/mrblib/array.rb b/mrblib/array.rb
index 905b41cb0..881f22df7 100644
--- a/mrblib/array.rb
+++ b/mrblib/array.rb
@@ -88,10 +88,12 @@ class Array
end
end
-# include modules
+##
+# Array is enumerable and comparable
module Enumerable; end
module Comparable; end
class Array
+ # ISO 15.2.12.3
include Enumerable
include Comparable
diff --git a/mrblib/hash.rb b/mrblib/hash.rb
index 7157684f8..d6ad55e47 100644
--- a/mrblib/hash.rb
+++ b/mrblib/hash.rb
@@ -1,8 +1,17 @@
+##
+# Hash
#
-# Hash
-#
+# ISO 15.2.13
class Hash
- # 15.2.13.4.8
+
+ ##
+ # Delete the element with the key +key+.
+ # Return the value of the element if +key+
+ # was found. Return nil if nothing was
+ # found. If a block is given, call the
+ # block with the value of the element.
+ #
+ # ISO 15.2.13.4.8
def delete(key, &block)
if block && ! self.has_key?(key)
block.call(key)
@@ -11,30 +20,52 @@ class Hash
end
end
- # 15.2.13.4.9
+ ##
+ # Calls the given block for each element of +self+
+ # and pass the key and value of each element.
+ #
+ # ISO 15.2.13.4.9
def each(&block)
self.keys.each{|k| block.call([k, self[k]])}
self
end
- # 15.2.13.4.10
+ ##
+ # Calls the given block for each element of +self+
+ # and pass the key of each element.
+ #
+ # ISO 15.2.13.4.10
def each_key(&block)
self.keys.each{|k| block.call(k)}
self
end
- # 15.2.13.4.11
+ ##
+ # Calls the given block for each element of +self+
+ # and pass the value of each element.
+ #
+ # ISO 15.2.13.4.11
def each_value(&block)
self.keys.each{|k| block.call(self[k])}
self
end
- # 15.2.13.4.16
+ ##
+ # Create a direct instance of the class Hash.
+ #
+ # ISO 15.2.13.4.16
def initialize(*args, &block)
self.__init_core(block, *args)
end
- # 15.2.13.4.22
+ ##
+ # Return a hash which contains the content of
+ # +self+ and +other+. If a block is given
+ # it will be called for each element with
+ # a duplicate key. The value of the block
+ # will be the final value of this element.
+ #
+ # ISO 15.2.13.4.22
def merge(other, &block)
h = {}
raise "can't convert argument into Hash" unless other.respond_to?(:to_hash)
@@ -51,7 +82,10 @@ class Hash
end
end
-# include modules
+##
+# Hash is enumerable
+#
+# ISO 15.2.13.3
module Enumerable; end
class Hash
include Enumerable
diff --git a/mrblib/kernel.rb b/mrblib/kernel.rb
index c09755d6c..af743e12a 100644
--- a/mrblib/kernel.rb
+++ b/mrblib/kernel.rb
@@ -1,21 +1,33 @@
+##
+# Kernel
#
-# Kernel
-#
+# ISO 15.3.1
module Kernel
- # 15.3.1.2.6
+
+ ##
+ # Takes the given block, create a lambda
+ # out of it and +call+ it.
+ #
+ # ISO 15.3.1.2.6
def self.lambda(&block)
### *** TODO *** ###
block # dummy
end
- # 15.3.1.2.8
+ ##
+ # Calls the given block repetitively.
+ #
+ # ISO 15.3.1.2.8
def self.loop #(&block)
while(true)
yield
end
end
- # 15.3.1.3.4
+ ##
+ # Alias for +send+.
+ #
+ # ISO 15.3.1.3.4
def __send__(symbol, *args, &block)
### *** TODO *** ###
end
@@ -25,21 +37,57 @@ module Kernel
### *** TODO *** ###
end
- # 15.3.1.3.27
+ ##
+ # Alias for +Kernel.lambda+.
+ #
+ # ISO 15.3.1.3.27
def lambda(&block)
### *** TODO *** ###
block # dummy
end
- # 15.3.1.3.29
+ ##
+ # Alias for +Kernel.loop+.
+ #
+ # ISO 15.3.1.3.29
def loop #(&block)
while(true)
yield
end
end
- # 15.3.1.3.44
+ ##
+ # Invoke the method with the name +symbol+ on
+ # the receiver and pass +args+ and the given
+ # block.
+ #
+ # ISO 15.3.1.3.44
def send(symbol, *args, &block)
### *** TODO *** ###
end
+
+ ##
+ # Print arguments
+ #
+ # ISO 15.3.1.2.10
+ def print(*args)
+ args.each do|x|
+ if x.nil?
+ __printstr__ "nil"
+ else
+ __printstr__ x.to_s
+ end
+ end
+ end
+
+ ##
+ # Print arguments with newline
+ #
+ # ISO 15.3.1.2.11
+ def puts(*args)
+ args.each do|x|
+ __printstr__ x.to_s
+ __printstr__ "\n"
+ end
+ end
end
diff --git a/mrblib/numeric.rb b/mrblib/numeric.rb
index 08600b0bf..9f65d5633 100644
--- a/mrblib/numeric.rb
+++ b/mrblib/numeric.rb
@@ -48,7 +48,10 @@ class Integer
end
end
-# include modules
+##
+# Numeric is comparable
+#
+# ISO 15.2.7.3
module Comparable; end
class Numeric
include Comparable
diff --git a/mrblib/range.rb b/mrblib/range.rb
index 79bc40ecd..44be0305b 100644
--- a/mrblib/range.rb
+++ b/mrblib/range.rb
@@ -1,8 +1,14 @@
+##
+# Range
#
-# Range
-#
+# ISO 15.2.14
class Range
- # 15.2.14.4.4
+
+ ##
+ # Calls the given block for each element of +self+
+ # and pass the respective element.
+ #
+ # ISO 15.2.14.4.4
def each(&block)
val = self.first
unless val.respond_to? :succ
@@ -23,7 +29,10 @@ class Range
end
end
-# include modules
+##
+# Range is enumerable
+#
+# ISO 15.2.14.3
module Enumerable; end
class Range
include Enumerable
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 f517cc19a..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++;
@@ -836,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/etc.c b/src/etc.c
index 477a78ebc..eac71459c 100644
--- a/src/etc.c
+++ b/src/etc.c
@@ -18,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)
{
@@ -38,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/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 639913958..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);
@@ -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/pool.c b/src/pool.c
index 369953699..adcf3b6b5 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -17,6 +17,12 @@
#define POOL_PAGE_SIZE 16000
+#ifdef ALLOC_ALIGN
+# define ALIGN_PADDING(x) ((x % ALLOC_ALIGN) ? ALLOC_ALIGN - (x % ALLOC_ALLOC) : 0)
+#else
+# define ALIGN_PADDING(x) (0)
+#endif
+
mrb_pool*
mrb_pool_open(mrb_state *mrb)
{
@@ -68,7 +74,7 @@ mrb_pool_alloc(mrb_pool *pool, size_t len)
size_t n;
if (!pool) return 0;
-
+ len += ALIGN_PADDING(len);
page = pool->pages;
while (page) {
if (page->offset + len <= page->len) {
@@ -95,6 +101,7 @@ mrb_pool_can_realloc(mrb_pool *pool, void *p, size_t len)
struct mrb_pool_page *page;
if (!pool) return 0;
+ len += ALIGN_PADDING(len);
page = pool->pages;
while (page) {
if (page->last == p) {
@@ -116,6 +123,8 @@ mrb_pool_realloc(mrb_pool *pool, void *p, size_t oldlen, size_t newlen)
void *np;
if (!pool) return 0;
+ oldlen += ALIGN_PADDING(oldlen);
+ newlen += ALIGN_PADDING(newlen);
page = pool->pages;
while (page) {
if (page->last == p) {
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 38306d4ba..2e12bd156 100644
--- a/src/variable.c
+++ b/src/variable.c
@@ -446,7 +446,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));
}
@@ -459,7 +459,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 f2f59cfbb..9c79a7afe 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -261,7 +261,7 @@ 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];
@@ -272,6 +272,25 @@ localjump_error(mrb_state *mrb, const char *kind)
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);
+}
+
#define SET_TRUE_VALUE(r) {\
(r).tt = MRB_TT_TRUE;\
(r).value.i = 1;\
@@ -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;
}
}
}
diff --git a/test/test_time.rb b/test/test_time.rb
new file mode 100644
index 000000000..ea6e98696
--- /dev/null
+++ b/test/test_time.rb
@@ -0,0 +1,48 @@
+$ok = 0
+$failed = 0
+$ftest = []
+
+def assert(str = "Assertion failed")
+ if(!yield)
+ $ftest.push(str)
+ $failed += 1
+ print "F"
+ else
+ $ok += 1
+ print "."
+ end
+end
+
+def report()
+ print "\n"
+ $ftest.each do |str|
+ puts("Test Failed: #{str}");
+ end
+ $total = $ok + $failed
+ puts "Ran #{$total} tests: #{$ok} OK and #{$failed} failed."
+end
+
+doom = Time.gm(2012, 12, 23)
+assert("Time.gm") { doom }
+assert("gm year") { doom.year == 2012 }
+assert("gm month") { doom.month == 12 }
+assert("gm day") { doom.mday == 23 }
+
+t0 = Time.new
+assert("Can create time.") { t0 }
+
+t1 = Time.at(1300000000.0).utc
+assert("asctime") { t1.asctime == "Sun Mar 13 07:06:40 UTC 2011" }
+assert("usec") { t1.usec == 0 }
+assert("to_i") { t1.to_i == 1300000000 }
+assert("to_f") { t1.to_f == 1300000000.0 }
+assert("utc?") { t1.utc? }
+assert("zone") { t1.zone == "UTC" }
+assert("wday") { t1.wday == 0 }
+assert("yday") { t1.yday == 71 }
+assert("year") { t1.year == 2011 }
+
+t2 = Time.at(7.0e6)
+assert("initialize_copy") { t2.clone == t2 }
+
+report()