diff options
45 files changed, 1416 insertions, 960 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/Makefile b/mrblib/Makefile index 10cf654cd..1fd0eb5a7 100644 --- a/mrblib/Makefile +++ b/mrblib/Makefile @@ -12,12 +12,7 @@ RLIB := $(TARGET).rbtmp DEPLIB := $(TARGET).d MRB1 := $(BASEDIR)/*.rb MRBS := $(MRB1) -LIB := ../lib/mruby -ifeq ($(OS),Windows_NT) -LIBR := $(LIB).lib -else -LIBR := $(LIB).a -endif +LIBR := ../lib/libmruby.a # C compiler (gcc) CC = gcc diff --git a/mrblib/array.rb b/mrblib/array.rb index a70832399..881f22df7 100644 --- a/mrblib/array.rb +++ b/mrblib/array.rb @@ -1,8 +1,14 @@ +## +# Array # -# Array -# +# ISO 15.2.12 class Array - # 15.2.12.5.10 + + ## + # Calls the given block for each element of +self+ + # and pass the respective element. + # + # ISO 15.2.12.5.10 def each(&block) idx = 0 while(idx < length) @@ -12,7 +18,11 @@ class Array self end - # 15.2.12.5.11 + ## + # Calls the given block for each element of +self+ + # and pass the index of the respective elment. + # + # ISO 15.2.12.5.11 def each_index(&block) idx = 0 while(idx < length) @@ -22,7 +32,12 @@ class Array self end - # 15.2.12.5.7 + ## + # Calls the given block for each element of +self+ + # and pass the respective element. Each element will + # be replaced by the resulting values. + # + # ISO 15.2.12.5.7 def collect!(&block) self.each_index{|idx| self[idx] = block.call(self[idx]) @@ -30,11 +45,16 @@ class Array self end - # 15.2.12.5.20 - # map!(&block) + ## + # Alias for collect! + # + # ISO 15.2.12.5.20 alias map! collect! - # 15.2.12.5.15 + ## + # Private method for Array creation. + # + # ISO 15.2.12.5.15 def initialize(size=0, obj=nil, &block) raise TypeError, "expected Integer for 1st argument" unless size.kind_of? Integer raise ArgumentError, "negative array size" if size < 0 @@ -53,6 +73,8 @@ class Array self end + ## + # Delete element with index +key+ def delete(key, &block) while i = self.index(key) self.delete_at(i) @@ -66,13 +88,18 @@ 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 + ## + # Sort all elements and replace +self+ with these + # elements. def sort!(&block) self.replace(self.sort(&block)) end diff --git a/mrblib/enum.rb b/mrblib/enum.rb index b5a387f43..31a94b93f 100644 --- a/mrblib/enum.rb +++ b/mrblib/enum.rb @@ -1,8 +1,17 @@ +## +# Enumerable # -# Enumerable -# +# ISO 15.3.2 module Enumerable - # 15.3.2.2.1 + + ## + # Call the given block for each element + # which is yield by +each+. Return false + # if one block value is false. Otherwise + # return true. If no block is given and + # +self+ is false return false. + # + # ISO 15.3.2.2.1 def all?(&block) st = true if block @@ -23,7 +32,14 @@ module Enumerable st end - # 15.3.2.2.2 + ## + # Call the given block for each element + # which is yield by +each+. Return true + # if one block value is true. Otherwise + # return false. If no block is given and + # +self+ is true object return true. + # + # ISO 15.3.2.2.2 def any?(&block) st = false if block @@ -44,7 +60,13 @@ module Enumerable st end - # 15.3.2.2.3 + ## + # Call the given block for each element + # which is yield by +each+. Append all + # values of each block together and + # return this value. + # + # ISO 15.3.2.2.3 def collect(&block) ary = [] self.each{|val| @@ -53,7 +75,14 @@ module Enumerable ary end - # 15.3.2.2.4 + ## + # Call the given block for each element + # which is yield by +each+. Return + # +ifnone+ if no block value was true. + # Otherwise return the first block value + # which had was true. + # + # ISO 15.3.2.2.4 def detect(ifnone=nil, &block) ret = ifnone self.each{|val| @@ -65,7 +94,13 @@ module Enumerable ret end - # 15.3.2.2.5 + ## + # Call the given block for each element + # which is yield by +each+. Pass an + # index to the block which starts at 0 + # and increase by 1 for each element. + # + # ISO 15.3.2.2.5 def each_with_index(&block) i = 0 self.each{|val| @@ -75,7 +110,11 @@ module Enumerable self end - # 15.3.2.2.6 + ## + # Return an array of all elements which + # are yield by +each+. + # + # ISO 15.3.2.2.6 def entries ary = [] self.each{|val| @@ -84,11 +123,19 @@ module Enumerable ary end - # 15.3.2.2.7 - # find(ifnone=nil, &block) + ## + # Alias for find + # + # ISO 15.3.2.2.7 alias find detect - # 15.3.2.2.8 + ## + # Call the given block for each element + # which is yield by +each+. Return an array + # which contains all elements whose block + # value was true. + # + # ISO 15.3.2.2.8 def find_all(&block) ary = [] self.each{|val| @@ -97,7 +144,14 @@ module Enumerable ary end - # 15.3.2.2.9 + ## + # Call the given block for each element + # which is yield by +each+ and which return + # value was true when invoking === with + # +pattern+. Return an array with all + # elements or the respective block values. + # + # ISO 15.3.2.2.9 def grep(pattern, &block) ary = [] self.each{|val| @@ -108,7 +162,13 @@ module Enumerable ary end - # 15.3.2.2.10 + ## + # Return true if at least one element which + # is yield by +each+ returns a true value + # by invoking == with +obj+. Otherwise return + # false. + # + # ISO 15.3.2.2.10 def include?(obj) st = false self.each{|val| @@ -120,7 +180,14 @@ module Enumerable st end - # 15.3.2.2.11 + ## + # Call the given block for each element + # which is yield by +each+. Return value + # is the sum of all block values. Pass + # to each block the current sum and the + # current element. + # + # ISO 15.3.2.2.11 def inject(*args, &block) raise ArgumentError, "too many arguments" if args.size > 2 flag = true # 1st element? @@ -137,11 +204,19 @@ module Enumerable result end - # 15.3.2.2.12 - # map(&block) + ## + # Alias for collect + # + # ISO 15.3.2.2.12 alias map collect - # 15.3.2.2.13 + ## + # Return the maximum value of all elements + # yield by +each+. If no block is given <=> + # will be invoked to define this value. If + # a block is given it will be used instead. + # + # ISO 15.3.2.2.13 def max(&block) flag = true # 1st element? result = nil @@ -161,7 +236,13 @@ module Enumerable result end - # 15.3.2.2.14 + ## + # Return the minimum value of all elements + # yield by +each+. If no block is given <=> + # will be invoked to define this value. If + # a block is given it will be used instead. + # + # ISO 15.3.2.2.14 def min(&block) flag = true # 1st element? result = nil @@ -181,11 +262,22 @@ module Enumerable result end - # 15.3.2.2.15 - # member?(obj) + ## + # Alias for include? + # + # ISO 15.3.2.2.15 alias member? include? - # 15.3.2.2.16 + ## + # Call the given block for each element + # which is yield by +each+. Return an + # array which contains two arrays. The + # first array contains all elements + # whose block value was true. The second + # array contains all elements whose + # block value was false. + # + # ISO 15.3.2.2.16 def partition(&block) ary_T = [] ary_F = [] @@ -199,7 +291,13 @@ module Enumerable [ary_T, ary_F] end - # 15.3.2.2.17 + ## + # Call the given block for each element + # which is yield by +each+. Return an + # array which contains only the elements + # whose block value was false. + # + # ISO 15.3.2.2.17 def reject(&block) ary = [] self.each{|val| @@ -208,11 +306,14 @@ module Enumerable ary end - # 15.3.2.2.18 - # select(&block) + ## + # Alias for find_all. + # + # ISO 15.3.2.2.18 alias select find_all - + ## + # TODO # Does this OK? Please test it. def __sort_sub__(sorted, work, src_ary, head, tail, &block) if head == tail @@ -250,7 +351,15 @@ module Enumerable end # private :__sort_sub__ - # 15.3.2.2.19 + ## + # Return a sorted array of all elements + # which are yield by +each+. If no block + # is given <=> will be invoked on each + # element to define the order. Otherwise + # the given block will be used for + # sorting. + # + # ISO 15.3.2.2.19 def sort(&block) ary = [] self.each{|val| ary.push(val)} @@ -260,7 +369,9 @@ module Enumerable ary end - # 15.3.2.2.20 - # to_a + ## + # Alias for entries. + # + # ISO 15.3.2.2.20 alias to_a entries end diff --git a/mrblib/error.rb b/mrblib/error.rb index 88da1825c..5660d8235 100644 --- a/mrblib/error.rb +++ b/mrblib/error.rb @@ -1,8 +1,13 @@ +## +# Exception # -# Exception -# +# ISO 15.2.22 class Exception - # 15.2.22.4.1 + + ## + # Raise an exception. + # + # ISO 15.2.22.4.1 def self.exception(*args, &block) self.new(*args, &block) end 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/print.rb b/mrblib/print.rb index cb1fad75d..840a1249a 100644 --- a/mrblib/print.rb +++ b/mrblib/print.rb @@ -1,4 +1,13 @@ +## +# Kernel +# +# ISO 15.3.1 module Kernel + + ## + # Invoke method +print+ on STDOUT and passing +*args+ + # + # ISO 15.3.1.2.10 def print(*args) i = 0 len = args.size @@ -7,6 +16,11 @@ module Kernel i += 1 end end + + ## + # Invoke method +puts+ on STDOUT and passing +*args*+ + # + # ISO 15.3.1.2.11 def puts(*args) i = 0 len = args.size 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/mrblib/string.rb b/mrblib/string.rb index 78f2bea9d..ad7e1fca1 100644 --- a/mrblib/string.rb +++ b/mrblib/string.rb @@ -1,8 +1,14 @@ +## +# String # -# String -# +# ISO 15.2.10 class String - # 15.2.10.5.15 + + ## + # Calls the given block for each line + # and pass the respective line. + # + # ISO 15.2.10.5.15 def each_line(&block) # expect that str.index accepts an Integer for 1st argument as a byte data offset = 0 @@ -14,7 +20,13 @@ class String self end - # 15.2.10.5.18 + ## + # Replace all matches of +pattern+ with +replacement+. + # Call block (if given) for each match and replace + # +pattern+ with the value of the block. Return the + # final value. + # + # ISO 15.2.10.5.18 def gsub(*args, &block) unless (args.size == 1 && block) || args.size == 2 raise ArgumentError, "wrong number of arguments" @@ -23,7 +35,13 @@ class String ### *** TODO *** ### end - # 15.2.10.5.19 + ## + # Replace all matches of +pattern+ with +replacement+. + # Call block (if given) for each match and replace + # +pattern+ with the value of the block. Modify + # +self+ with the final value. + # + # ISO 15.2.10.5.19 def gsub!(*args, &block) str = self.gsub(*args, &block) if str != self @@ -34,12 +52,23 @@ class String end end - # 15.2.10.5.32 + ## + # Calls the given block for each match of +pattern+ + # If no block is given return an array with all + # matches of +pattern+. + # + # ISO 15.2.10.5.32 def scan(reg, &block) ### *** TODO *** ### end - # 15.2.10.5.36 + ## + # Replace only the first match of +pattern+ with + # +replacement+. Call block (if given) for each + # match and replace +pattern+ with the value of the + # block. Return the final value. + # + # ISO 15.2.10.5.36 def sub(*args, &block) unless (args.size == 1 && block) || args.size == 2 raise ArgumentError, "wrong number of arguments" @@ -48,7 +77,13 @@ class String ### *** TODO *** ### end - # 15.2.10.5.37 + ## + # Replace only the first match of +pattern+ with + # +replacement+. Call block (if given) for each + # match and replace +pattern+ with the value of the + # block. Modify +self+ with the final value. + # + # ISO 15.2.10.5.37 def sub!(*args, &block) str = self.sub(*args, &block) if str != self @@ -59,6 +94,9 @@ class String end end + ## + # Call the given block for each character of + # +self+. def each_char(&block) pos = 0 while(pos < self.size) @@ -68,6 +106,8 @@ class String self end + ## + # Call the given block for each byte of +self+. def each_byte(&block) bytes = self.unpack("C*") pos = 0 @@ -78,6 +118,9 @@ class String self end + ## + # Modify +self+ by replacing the content of +self+ + # at the position +pos+ with +value+. def []=(pos, value) b = self[0, pos] a = self[pos+1..-1] @@ -86,7 +129,10 @@ class String end end -# include modules +## +# String is comparable +# +# ISO 15.2.10.3 module Comparable; end class String include Comparable diff --git a/mrblib/struct.rb b/mrblib/struct.rb index b11f59f2a..4b6d767a9 100644 --- a/mrblib/struct.rb +++ b/mrblib/struct.rb @@ -1,8 +1,14 @@ +## +# Struct # -# Struct -# +# ISO 15.2.18 class Struct - # 15.2.18.4.4 + + ## + # Calls the given block for each element of +self+ + # and pass the respective element. + # + # ISO 15.2.18.4.4 def each(&block) self.class.members.each{|field| block.call(self[field]) @@ -10,7 +16,12 @@ class Struct self end - # 15.2.18.4.5 + ## + # Calls the given block for each element of +self+ + # and pass the name and value of the respectiev + # element. + # + # ISO 15.2.18.4.5 def each_pair(&block) self.class.members.each{|field| block.call(field.to_sym, self[field]) @@ -18,7 +29,12 @@ class Struct self end - # 15.2.18.4.7 + ## + # Calls the given block for each element of +self+ + # and returns an array with all elements of which + # block is not false. + # + # ISO 15.2.18.4.7 def select(&block) ary = [] self.class.members.each{|field| 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 @@ -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 */ @@ -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; } @@ -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) @@ -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; } @@ -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); @@ -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 */ 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() diff --git a/tools/mrbc/Makefile b/tools/mrbc/Makefile index 282032c76..1137baa03 100644 --- a/tools/mrbc/Makefile +++ b/tools/mrbc/Makefile @@ -5,13 +5,11 @@ # extension of the executable-file is modifiable(.exe .out ...) BASEDIR := ../../src TARGET := ../../bin/mrbc -LIB := ../../lib/mruby +LIBR := ../../lib/libmruby.a ifeq ($(OS),Windows_NT) EXE := $(TARGET).exe -LIBR := $(LIB).lib else EXE := $(TARGET) -LIBR := $(LIB).a endif EXCEPT1 := OBJ0 := $(patsubst %.c,%.o,$(wildcard $(BASEDIR)/../tools/mrbc/*.c)) diff --git a/tools/mruby/Makefile b/tools/mruby/Makefile index 7b7eb83be..19140aabb 100644 --- a/tools/mruby/Makefile +++ b/tools/mruby/Makefile @@ -5,13 +5,11 @@ # extension of the executable-file is modifiable(.exe .out ...) BASEDIR = ../../src TARGET := ../../bin/mruby -LIB := ../../lib/mruby +LIBR := ../../lib/libmruby.a ifeq ($(OS),Windows_NT) EXE := $(TARGET).exe -LIBR := $(LIB).lib else EXE := $(TARGET) -LIBR := $(LIB).a endif OBJ0 := $(patsubst %.c,%.o,$(wildcard $(BASEDIR)/../tools/mruby/*.c)) #OBJ1 := $(patsubst %.c,%.o,$(filter-out $(EXCEPT1),$(wildcard $(BASEDIR)/*.c))) |
