Ignore:
Timestamp:
Jul 9, 2020, 8:51:43 AM (4 years ago)
Author:
coas-nagasima
Message:

mrubyを2.1.1に更新

Location:
EcnlProtoTool/trunk/mruby-2.1.1
Files:
111 added
5 deleted
95 edited
1 moved

Legend:

Unmodified
Added
Removed
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/default.gembox

    r331 r439  
    11MRuby::GemBox.new do |conf|
     2  # Meta-programming features
     3  conf.gem :core => "mruby-metaprog"
     4
     5  # Use standard IO/File class
     6  conf.gem :core => "mruby-io"
     7
     8  # Use standard Array#pack, String#unpack methods
     9  conf.gem :core => "mruby-pack"
     10
    211  # Use standard Kernel#sprintf method
    312  conf.gem :core => "mruby-sprintf"
     
    1423  # Use standard Struct class
    1524  conf.gem :core => "mruby-struct"
     25
     26  # Use Comparable module extension
     27  conf.gem :core => "mruby-compar-ext"
    1628
    1729  # Use Enumerable module extension
     
    7587  conf.gem :core => "mruby-class-ext"
    7688
     89  # Use Method/UnboundMethod class
     90  conf.gem :core => "mruby-method"
     91
    7792  # Use mruby-compiler to build other mrbgems
    7893  conf.gem :core => "mruby-compiler"
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-array-ext/mrblib/array.rb

    r331 r439  
    11class Array
    2   ##
    3   # call-seq:
    4   #    Array.try_convert(obj) -> array or nil
    5   #
    6   # Tries to convert +obj+ into an array, using +to_ary+ method.
    7   # converted array or +nil+ if +obj+ cannot be converted for any reason.
    8   # This method can be used to check if an argument is an array.
    9   #
    10   #    Array.try_convert([1])   #=> [1]
    11   #    Array.try_convert("1")   #=> nil
    12   #
    13   #    if tmp = Array.try_convert(arg)
    14   #      # the argument is an array
    15   #    elsif tmp = String.try_convert(arg)
    16   #      # the argument is a string
    17   #    end
    18   #
    19   def self.try_convert(obj)
    20     if obj.respond_to?(:to_ary)
    21       obj.to_ary
    22     else
    23       nil
    24     end
    25   end
    26 
    272  ##
    283  # call-seq:
     
    4217  #
    4318  def uniq!(&block)
    44     ary = self.dup
    45     result = []
     19    hash = {}
    4620    if block
     21      self.each do |val|
     22        key = block.call(val)
     23        hash[key] = val unless hash.key?(key)
     24      end
     25      result = hash.values
     26    else
    4727      hash = {}
    48       while ary.size > 0
    49         val = ary.shift
    50         key = block.call(val)
    51         hash[key] = val unless hash.has_key?(key)
    52       end
    53       hash.each_value do |value|
    54         result << value
    55       end
    56     else
    57       while ary.size > 0
    58         result << ary.shift
    59         ary.delete(result.last)
    60       end
     28      self.each do |val|
     29        hash[val] = val
     30      end
     31      result = hash.keys
    6132    end
    6233    if result.size == self.size
     
    8253  def uniq(&block)
    8354    ary = self.dup
    84     if block
    85       ary.uniq!(&block)
    86     else
    87       ary.uniq!
    88     end
     55    ary.uniq!(&block)
    8956    ary
    9057  end
     
    10673    hash = {}
    10774    array = []
    108     elem.each { |x| hash[x] = true }
    109     self.each { |x| array << x unless hash[x] }
     75    idx = 0
     76    len = elem.size
     77    while idx < len
     78      hash[elem[idx]] = true
     79      idx += 1
     80    end
     81    idx = 0
     82    len = size
     83    while idx < len
     84      v = self[idx]
     85      array << v unless hash[v]
     86      idx += 1
     87    end
    11088    array
     89  end
     90
     91  ##
     92  # call-seq:
     93  #    ary.difference(other_ary1, other_ary2, ...)   -> new_ary
     94  #
     95  # Returns a new array that is a copy of the original array, removing all
     96  # occurrences of any item that also appear in +other_ary+. The order is
     97  # preserved from the original array.
     98  #
     99  def difference(*args)
     100    ary = self
     101    args.each do |x|
     102      ary = ary - x
     103    end
     104    ary
    111105  end
    112106
     
    130124  ##
    131125  # call-seq:
     126  #    ary.union(other_ary,...)  -> new_ary
     127  #
     128  # Set Union---Returns a new array by joining this array with
     129  # <i>other_ary</i>, removing duplicates.
     130  #
     131  #    ["a", "b", "c"].union(["c", "d", "a"], ["a", "c", "e"])
     132  #           #=> ["a", "b", "c", "d", "e"]
     133  #
     134  def union(*args)
     135    ary = self.dup
     136    args.each do |x|
     137      ary.concat(x)
     138      ary.uniq!
     139    end
     140    ary
     141  end
     142
     143  ##
     144  # call-seq:
    132145  #    ary & other_ary      -> new_ary
    133146  #
     
    142155    hash = {}
    143156    array = []
    144     elem.each{|v| hash[v] = true }
    145     self.each do |v|
     157    idx = 0
     158    len = elem.size
     159    while idx < len
     160      hash[elem[idx]] = true
     161      idx += 1
     162    end
     163    idx = 0
     164    len = size
     165    while idx < len
     166      v = self[idx]
    146167      if hash[v]
    147168        array << v
    148169        hash.delete v
    149170      end
     171      idx += 1
    150172    end
    151173    array
     174  end
     175
     176  ##
     177  # call-seq:
     178  #    ary.intersection(other_ary,...)  -> new_ary
     179  #
     180  # Set Intersection---Returns a new array containing elements common to
     181  # this array and <i>other_ary</i>s, removing duplicates. The order is
     182  # preserved from the original array.
     183  #
     184  #    [1, 2, 3].intersection([3, 4, 1], [1, 3, 5])  #=> [1, 3]
     185  #
     186  def intersection(*args)
     187    ary = self
     188    args.each do |x|
     189      ary = ary & x
     190    end
     191    ary
    152192  end
    153193
     
    170210  #
    171211  def flatten(depth=nil)
    172     ar = []
    173     self.each do |e|
    174       if e.is_a?(Array) && (depth.nil? || depth > 0)
    175         ar += e.flatten(depth.nil? ? nil : depth - 1)
    176       else
    177         ar << e
    178       end
    179     end
    180     ar
     212    res = dup
     213    res.flatten! depth
     214    res
    181215  end
    182216
     
    201235    modified = false
    202236    ar = []
    203     self.each do |e|
     237    idx = 0
     238    len = size
     239    while idx < len
     240      e = self[idx]
    204241      if e.is_a?(Array) && (depth.nil? || depth > 0)
    205242        ar += e.flatten(depth.nil? ? nil : depth - 1)
     
    208245        ar << e
    209246      end
     247      idx += 1
    210248    end
    211249    if modified
     
    253291  # for efficiency
    254292  def reverse_each(&block)
    255     return to_enum :reverse_each unless block_given?
     293    return to_enum :reverse_each unless block
    256294
    257295    i = self.size - 1
     
    263301  end
    264302
    265   NONE=Object.new
    266303  ##
    267304  #  call-seq:
     
    288325  #
    289326
    290   def fetch(n=nil, ifnone=NONE, &block)
     327  def fetch(n, ifnone=NONE, &block)
    291328    warn "block supersedes default value argument" if !n.nil? && ifnone != NONE && block
    292329
     
    475512
    476513  def delete_if(&block)
    477     return to_enum :delete_if unless block_given?
     514    return to_enum :delete_if unless block
    478515
    479516    idx = 0
     
    504541
    505542  def reject!(&block)
    506     return to_enum :reject! unless block_given?
     543    return to_enum :reject! unless block
    507544
    508545    len = self.size
     
    594631
    595632  def bsearch(&block)
    596     return to_enum :bsearch unless block_given?
     633    return to_enum :bsearch unless block
     634
     635    if idx = bsearch_index(&block)
     636      self[idx]
     637    else
     638      nil
     639    end
     640  end
     641
     642  ##
     643  #  call-seq:
     644  #     ary.bsearch_index {|x| block }  -> int or nil
     645  #
     646  #  By using binary search, finds an index of a value from this array which
     647  #  meets the given condition in O(log n) where n is the size of the array.
     648  #
     649  #  It supports two modes, depending on the nature of the block and they are
     650  #  exactly the same as in the case of #bsearch method with the only difference
     651  #  being that this method returns the index of the element instead of the
     652  #  element itself. For more details consult the documentation for #bsearch.
     653
     654  def bsearch_index(&block)
     655    return to_enum :bsearch_index unless block
    597656
    598657    low = 0
    599     high = self.size
     658    high = size
    600659    satisfied = false
     660
    601661    while low < high
    602       mid = low + ((high - low) / 2).truncate
    603       val = self[mid]
    604       v = block.call(val)
    605       if v.is_a?(Integer)
    606         return val if v == 0
    607         smaller = v < 0
    608       elsif v == true
     662      mid = ((low+high)/2).truncate
     663      res = block.call self[mid]
     664
     665      case res
     666      when 0 # find-any mode: Found!
     667        return mid
     668      when Numeric # find-any mode: Continue...
     669        in_lower_half = res < 0
     670      when true # find-min mode
     671        in_lower_half = true
    609672        satisfied = true
    610         smaller = true
    611       elsif v == false || v.nil?
    612         smaller = false
    613       end
    614       if smaller
     673      when false, nil # find-min mode
     674        in_lower_half = false
     675      else
     676        raise TypeError, 'invalid block result (must be numeric, true, false or nil)'
     677      end
     678
     679      if in_lower_half
    615680        high = mid
    616681      else
     
    618683      end
    619684    end
    620     return nil if low == self.size
    621     return nil unless satisfied
    622     self[low]
    623   end
    624 
    625   ##
    626   #  call-seq:
    627   #     ary.delete_if { |item| block }  -> ary
    628   #     ary.delete_if                   -> Enumerator
    629   #
    630   #  Deletes every element of +self+ for which block evaluates to +true+.
    631   #
    632   #  The array is changed instantly every time the block is called, not after
    633   #  the iteration is over.
    634   #
    635   #  See also Array#reject!
    636   #
    637   #  If no block is given, an Enumerator is returned instead.
    638   #
    639   #     scores = [ 97, 42, 75 ]
    640   #     scores.delete_if {|score| score < 80 }   #=> [97]
    641 
    642   def delete_if(&block)
    643     return to_enum :delete_if unless block_given?
    644 
    645     idx = 0
    646     while idx < self.size do
    647       if block.call(self[idx])
    648         self.delete_at(idx)
    649       else
    650         idx += 1
    651       end
    652     end
    653     self
     685
     686    satisfied ? low : nil
    654687  end
    655688
     
    670703
    671704  def keep_if(&block)
    672     return to_enum :keep_if unless block_given?
     705    return to_enum :keep_if unless block
    673706
    674707    idx = 0
     
    699732
    700733  def select!(&block)
    701     return to_enum :select! unless block_given?
     734    return to_enum :select! unless block
    702735
    703736    result = []
    704     self.each do |x|
    705       result << x if block.call(x)
    706     end
    707     return nil if self.size == result.size
     737    idx = 0
     738    len = size
     739    while idx < len
     740      elem = self[idx]
     741      result << elem if block.call(elem)
     742      idx += 1
     743    end
     744    return nil if len == result.size
    708745    self.replace(result)
    709746  end
     
    727764    if block
    728765      idx = 0
    729       self.each do |*e|
    730         return idx if block.call(*e)
     766      len = size
     767      while idx < len
     768        return idx if block.call self[idx]
    731769        idx += 1
    732770      end
     
    735773    end
    736774    nil
    737   end
    738 
    739   ##
    740   #  call-seq:
    741   #     ary.to_ary -> ary
    742   #
    743   #  Returns +self+.
    744   #
    745   def to_ary
    746     self
    747775  end
    748776
     
    763791    end
    764792  end
     793
     794  ##
     795  # call-seq:
     796  #    ary.permutation { |p| block }          -> ary
     797  #    ary.permutation                        -> Enumerator
     798  #    ary.permutation(n) { |p| block }       -> ary
     799  #    ary.permutation(n)                     -> Enumerator
     800  #
     801  # When invoked with a block, yield all permutations of length +n+ of the
     802  # elements of the array, then return the array itself.
     803  #
     804  # If +n+ is not specified, yield all permutations of all elements.
     805  #
     806  # The implementation makes no guarantees about the order in which the
     807  # permutations are yielded.
     808  #
     809  # If no block is given, an Enumerator is returned instead.
     810  #
     811  # Examples:
     812  #
     813  #  a = [1, 2, 3]
     814  #  a.permutation.to_a    #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
     815  #  a.permutation(1).to_a #=> [[1],[2],[3]]
     816  #  a.permutation(2).to_a #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
     817  #  a.permutation(3).to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
     818  #  a.permutation(0).to_a #=> [[]] # one permutation of length 0
     819  #  a.permutation(4).to_a #=> []   # no permutations of length 4
     820  def permutation(n=self.size, &block)
     821    return to_enum(:permutation, n) unless block
     822    size = self.size
     823    if n == 0
     824      yield []
     825    elsif 0 < n && n <= size
     826      i = 0
     827      while i<size
     828        result = [self[i]]
     829        if n-1 > 0
     830          ary = self[0...i] + self[i+1..-1]
     831          ary.permutation(n-1) do |c|
     832            yield result + c
     833          end
     834        else
     835          yield result
     836        end
     837        i += 1
     838      end
     839    end
     840    self
     841  end
     842
     843  ##
     844  # call-seq:
     845  #    ary.combination(n) { |c| block }    -> ary
     846  #    ary.combination(n)                  -> Enumerator
     847  #
     848  # When invoked with a block, yields all combinations of length +n+ of elements
     849  # from the array and then returns the array itself.
     850  #
     851  # The implementation makes no guarantees about the order in which the
     852  # combinations are yielded.
     853  #
     854  # If no block is given, an Enumerator is returned instead.
     855  #
     856  # Examples:
     857  #
     858  #    a = [1, 2, 3, 4]
     859  #    a.combination(1).to_a  #=> [[1],[2],[3],[4]]
     860  #    a.combination(2).to_a  #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
     861  #    a.combination(3).to_a  #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
     862  #    a.combination(4).to_a  #=> [[1,2,3,4]]
     863  #    a.combination(0).to_a  #=> [[]] # one combination of length 0
     864  #    a.combination(5).to_a  #=> []   # no combinations of length 5
     865
     866  def combination(n, &block)
     867    return to_enum(:combination, n) unless block
     868    size = self.size
     869    if n == 0
     870       yield []
     871    elsif n == 1
     872      i = 0
     873      while i<size
     874        yield [self[i]]
     875        i += 1
     876      end
     877    elsif n <= size
     878      i = 0
     879      while i<size
     880        result = [self[i]]
     881        self[i+1..-1].combination(n-1) do |c|
     882          yield result + c
     883        end
     884        i += 1
     885      end
     886    end
     887    self
     888  end
     889
     890  ##
     891  # call-seq:
     892  #    ary.transpose -> new_ary
     893  #
     894  # Assumes that self is an array of arrays and transposes the rows and columns.
     895  #
     896  # If the length of the subarrays don't match, an IndexError is raised.
     897  #
     898  # Examples:
     899  #
     900  #    a = [[1,2], [3,4], [5,6]]
     901  #    a.transpose   #=> [[1, 3, 5], [2, 4, 6]]
     902
     903  def transpose
     904    return [] if empty?
     905
     906    column_count = nil
     907    self.each do |row|
     908      raise TypeError unless row.is_a?(Array)
     909      column_count ||= row.size
     910      raise IndexError, 'element size differs' unless column_count == row.size
     911    end
     912
     913    Array.new(column_count) do |column_index|
     914      self.map { |row| row[column_index] }
     915    end
     916  end
     917
     918  ##
     919  #  call-seq:
     920  #    ary.to_h                ->   Hash
     921  #    ary.to_h{|item| ... }   ->   Hash
     922  #
     923  # Returns the result of interpreting <i>aray</i> as an array of
     924  # <tt>[key, value]</tt> pairs. If a block is given, it should
     925  # return <tt>[key, value]</tt> pairs to construct a hash.
     926  #
     927  #     [[:foo, :bar], [1, 2]].to_h
     928  #       # => {:foo => :bar, 1 => 2}
     929  #     [1, 2].to_h{|x| [x, x*2]}
     930  #       # => {1 => 2, 2 => 4}
     931  #
     932  def to_h(&blk)
     933    h = {}
     934    self.each do |v|
     935      v = blk.call(v) if blk
     936      raise TypeError, "wrong element type #{v.class}" unless Array === v
     937      raise ArgumentError, "wrong array length (expected 2, was #{v.length})" unless v.length == 2
     938      h[v[0]] = v[1]
     939    end
     940    h
     941  end
     942
     943  alias append push
     944  alias prepend unshift
     945  alias filter! select!
    765946end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-array-ext/src/array.c

    r331 r439  
    6666  for (i = 0; i < RARRAY_LEN(ary); ++i) {
    6767    v = RARRAY_PTR(ary)[i];
    68     if (mrb_type(v) == MRB_TT_ARRAY &&
     68    if (mrb_array_p(v) &&
    6969        RARRAY_LEN(v) > 1 &&
    7070        mrb_equal(mrb, RARRAY_PTR(v)[1], value))
     
    107107}
    108108
    109 /*
    110  *  call-seq:
    111  *     ary.to_h   ->   Hash
    112  *
    113  *  Returns the result of interpreting <i>aray</i> as an array of
    114  *  <tt>[key, value]</tt> paris.
    115  *
    116  *      [[:foo, :bar], [1, 2]].to_h
    117  *        # => {:foo => :bar, 1 => 2}
    118  *
    119  */
    120 
    121 static mrb_value
    122 mrb_ary_to_h(mrb_state *mrb, mrb_value ary)
    123 {
    124   mrb_int i;
    125   mrb_value v, hash;
    126 
    127   hash = mrb_hash_new_capa(mrb, 0);
    128 
    129   for (i = 0; i < RARRAY_LEN(ary); ++i) {
    130     v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]);
    131 
    132     if (mrb_nil_p(v)) {
    133       mrb_raisef(mrb, E_TYPE_ERROR, "wrong element type %S at %S (expected array)",
    134         mrb_str_new_cstr(mrb,  mrb_obj_classname(mrb, ary_elt(ary, i))),
    135         mrb_fixnum_value(i)
    136       );
    137     }
    138 
    139     if (RARRAY_LEN(v) != 2) {
    140       mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong array length at %S (expected 2, was %S)",
    141         mrb_fixnum_value(i),
    142         mrb_fixnum_value(RARRAY_LEN(v))
    143       );
    144     }
    145 
    146     mrb_hash_set(mrb, hash, RARRAY_PTR(v)[0], RARRAY_PTR(v)[1]);
    147   }
    148 
    149   return hash;
    150 }
    151109
    152110/*
     
    175133{
    176134  struct RArray *a = mrb_ary_ptr(self);
    177   mrb_int i, j, k, len;
    178   mrb_value index;
     135  mrb_int i, j, k, len, alen;
    179136  mrb_value val;
    180137  mrb_value *ptr;
     
    183140  mrb_ary_modify(mrb, a);
    184141
    185   if (mrb_get_args(mrb, "o|i", &index, &len) == 1) {
     142  if (mrb_get_argc(mrb) == 1) {
     143    mrb_value index;
     144
     145    mrb_get_args(mrb, "o|i", &index, &len);
    186146    switch (mrb_type(index)) {
    187147    case MRB_TT_RANGE:
    188       if (mrb_range_beg_len(mrb, index, &i, &len, a->len, TRUE) == 1) {
     148      if (mrb_range_beg_len(mrb, index, &i, &len, ARY_LEN(a), TRUE) == MRB_RANGE_OK) {
    189149        goto delete_pos_len;
    190150      }
     
    201161  }
    202162
    203   i = mrb_fixnum(index);
     163  mrb_get_args(mrb, "ii", &i, &len);
    204164 delete_pos_len:
    205   if (i < 0) i += a->len;
    206   if (i < 0 || a->len < i) return mrb_nil_value();
     165  alen = ARY_LEN(a);
     166  if (i < 0) i += alen;
     167  if (i < 0 || alen < i) return mrb_nil_value();
    207168  if (len < 0) return mrb_nil_value();
    208   if (a->len == i) return mrb_ary_new(mrb);
    209   if (len > a->len - i) len = a->len - i;
     169  if (alen == i) return mrb_ary_new(mrb);
     170  if (len > alen - i) len = alen - i;
    210171
    211172  ary = mrb_ary_new_capa(mrb, len);
    212 
     173  ptr = ARY_PTR(a);
    213174  for (j = i, k = 0; k < len; ++j, ++k) {
    214     mrb_ary_push(mrb, ary, a->ptr[j]);
    215   }
    216 
    217   ptr = a->ptr + i;
    218   for (j = i; j < a->len - len; ++j) {
     175    mrb_ary_push(mrb, ary, ptr[j]);
     176  }
     177
     178  ptr += i;
     179  for (j = i; j < alen - len; ++j) {
    219180    *ptr = *(ptr+len);
    220181    ++ptr;
    221182  }
    222183
    223   mrb_ary_resize(mrb, self, a->len - len);
     184  mrb_ary_resize(mrb, self, alen - len);
    224185  return ary;
    225186}
     
    234195  mrb_define_method(mrb, a, "rassoc", mrb_ary_rassoc, MRB_ARGS_REQ(1));
    235196  mrb_define_method(mrb, a, "values_at", mrb_ary_values_at, MRB_ARGS_ANY());
    236   mrb_define_method(mrb, a, "to_h",   mrb_ary_to_h, MRB_ARGS_REQ(0));
    237   mrb_define_method(mrb, a, "slice!", mrb_ary_slice_bang,   MRB_ARGS_ANY());
     197  mrb_define_method(mrb, a, "slice!", mrb_ary_slice_bang,   MRB_ARGS_ARG(1,1));
    238198}
    239199
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-array-ext/test/array.rb

    r331 r439  
    22# Array(Ext) Test
    33
    4 assert("Array.try_convert") do
    5   assert_nil Array.try_convert(0)
    6   assert_nil Array.try_convert(nil)
    7   assert_equal [], Array.try_convert([])
    8   assert_equal [1,2,3], Array.try_convert([1,2,3])
     4def assert_permutation_combination(exp, receiver, meth, *args)
     5  act = []
     6  ret = receiver.__send__(meth, *args) { |v| act << v }
     7  assert "assert_#{meth}" do
     8    assert_equal(exp, act.sort)
     9    assert_same(receiver, ret)
     10  end
     11end
     12
     13def assert_permutation(exp, receiver, *args)
     14  assert_permutation_combination(exp, receiver, :permutation, *args)
     15end
     16
     17def assert_combination(exp, receiver, *args)
     18  assert_permutation_combination(exp, receiver, :combination, *args)
    919end
    1020
     
    7686end
    7787
     88assert("Array#union") do
     89  a = [1, 2, 3, 1]
     90  b = [1, 4]
     91  c = [1, 5]
     92
     93  assert_equal [1, 2, 3, 4, 5], a.union(b,c)
     94end
     95
     96assert("Array#difference") do
     97  a = [1, 2, 3, 1, 6, 7]
     98  b = [1, 4, 6]
     99  c = [1, 5, 7]
     100
     101  assert_equal [2, 3], a.difference(b,c)
     102end
     103
    78104assert("Array#&") do
    79105  a = [1, 2, 3, 1]
     
    84110  assert_equal [1], (a & b)
    85111  assert_equal [1, 2, 3, 1], a
     112end
     113
     114assert("Array#intersection") do
     115  a = [1, 2, 3, 1, 8, 6, 7, 8]
     116  b = [1, 4, 6, 8]
     117  c = [1, 5, 7, 8]
     118
     119  assert_equal [1, 8], a.intersection(b,c)
    86120end
    87121
     
    162196  end
    163197  assert_equal [ "d", "c", "b", "a" ], b
    164 
    165   if Object.const_defined?(:Enumerator)
    166     assert_equal [ "d", "c", "b", "a" ], a.reverse_each.to_a
    167   else
    168     true
    169   end
    170198end
    171199
     
    229257assert("Array#bsearch") do
    230258  # Find minimum mode
    231   a = [0, 4, 7, 10, 12]
    232   assert_include [4, 7], a.bsearch {|x| x >= 4 }
    233   assert_equal 7, a.bsearch {|x| x >= 6 }
    234   assert_equal 0, a.bsearch {|x| x >= -1 }
    235   assert_nil a.bsearch {|x| x >= 100 }
     259  a = [0, 2, 4]
     260  assert_equal 0, a.bsearch{ |x| x >= -1 }
     261  assert_equal 0, a.bsearch{ |x| x >= 0 }
     262  assert_equal 2, a.bsearch{ |x| x >= 1 }
     263  assert_equal 2, a.bsearch{ |x| x >= 2 }
     264  assert_equal 4, a.bsearch{ |x| x >= 3 }
     265  assert_equal 4, a.bsearch{ |x| x >= 4 }
     266  assert_nil      a.bsearch{ |x| x >= 5 }
    236267
    237268  # Find any mode
    238   a = [0, 4, 7, 10, 12]
    239   assert_include [4, 7], a.bsearch {|x| 1 - (x / 4).truncate }
    240   assert_nil a.bsearch {|x| 4 - (x / 2).truncate }
    241   assert_equal(nil, a.bsearch {|x| 1 })
    242   assert_equal(nil, a.bsearch {|x| -1 })
    243 end
    244 
    245 assert("Array#delete_if") do
    246   a = [1, 2, 3, 4, 5]
    247   assert_equal [1, 2, 3, 4, 5], a.delete_if { false }
    248   assert_equal [1, 2, 3, 4, 5], a
    249 
    250   a = [1, 2, 3, 4, 5]
    251   assert_equal [], a.delete_if { true }
    252   assert_equal [], a
    253 
    254   a = [ 1, 2, 3, 4, 5 ]
    255   assert_equal [1, 2, 3], a.delete_if { |val| val > 3 }
    256 end
     269  a = [0, 4, 8]
     270  def between(lo, x, hi)
     271    if x < lo
     272      1
     273    elsif x > hi
     274      -1
     275    else
     276      0
     277    end
     278  end
     279  assert_nil      a.bsearch{ |x| between(-3, x, -1) }
     280  assert_equal 0, a.bsearch{ |x| between(-1, x,  1) }
     281  assert_nil      a.bsearch{ |x| between( 1, x,  3) }
     282  assert_equal 4, a.bsearch{ |x| between( 3, x,  5) }
     283  assert_nil      a.bsearch{ |x| between( 5, x,  7) }
     284  assert_equal 8, a.bsearch{ |x| between( 7, x,  9) }
     285  assert_nil      a.bsearch{ |x| between( 9, x, 11) }
     286
     287  assert_equal 0, a.bsearch{ |x| between( 0, x,  3) }
     288  assert_equal 4, a.bsearch{ |x| between( 0, x,  4) }
     289  assert_equal 4, a.bsearch{ |x| between( 4, x,  8) }
     290  assert_equal 8, a.bsearch{ |x| between( 5, x,  8) }
     291
     292  # Invalid block result
     293  assert_raise TypeError, 'invalid block result (must be numeric, true, false or nil)' do
     294    a.bsearch{ 'I like to watch the world burn' }
     295  end
     296end
     297
     298# tested through Array#bsearch
     299#assert("Array#bsearch_index") do
     300#end
    257301
    258302assert("Array#keep_if") do
     
    302346end
    303347
    304 assert('Array#to_h (Modified)') do
    305   class A
    306     def to_ary
    307       $a.clear
    308       nil
    309     end
    310   end
    311   $a = [A.new]
    312   assert_raise(TypeError) { $a.to_h }
    313 end
    314 
    315348assert("Array#index (block)") do
    316349  assert_nil (1..10).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
    317350  assert_equal 34, (1..100).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
    318 end
    319 
    320 assert("Array#to_ary") do
    321   assert_equal [], [].to_ary
    322   assert_equal [1,2,3], [1,2,3].to_ary
    323351end
    324352
     
    353381  assert_equal(j, nil)
    354382end
     383
     384assert("Array#permutation") do
     385  a = [1, 2, 3]
     386  assert_permutation([[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]], a)
     387  assert_permutation([[1],[2],[3]], a, 1)
     388  assert_permutation([[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]], a, 2)
     389  assert_permutation([[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]], a, 3)
     390  assert_permutation([[]], a, 0)
     391  assert_permutation([], a, 4)
     392  assert_permutation([], a, -1)
     393end
     394
     395assert("Array#combination") do
     396  a = [1, 2, 3, 4]
     397  assert_combination([[1],[2],[3],[4]], a, 1)
     398  assert_combination([[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]], a, 2)
     399  assert_combination([[1,2,3],[1,2,4],[1,3,4],[2,3,4]], a, 3)
     400  assert_combination([[1,2,3,4]], a, 4)
     401  assert_combination([[]], a, 0)
     402  assert_combination([], a, 5)
     403  assert_combination([], a, -1)
     404end
     405
     406assert('Array#transpose') do
     407  assert_equal([].transpose, [])
     408  assert_equal([[]].transpose, [])
     409  assert_equal([[1]].transpose, [[1]])
     410  assert_equal([[1,2,3]].transpose, [[1], [2], [3]])
     411  assert_equal([[1], [2], [3]].transpose, [[1,2,3]])
     412  assert_equal([[1,2], [3,4], [5,6]].transpose, [[1,3,5], [2,4,6]])
     413  assert_raise(TypeError) { [1].transpose }
     414  assert_raise(IndexError) { [[1], [2,3,4]].transpose }
     415end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-debugger/bintest/print.rb

    r331 r439  
    11require 'open3'
    22require 'tempfile'
     3require 'strscan'
    34
    45class BinTest_MrubyBinDebugger
    5   @debug1=false
    6   @debug2=true
     6#  @debug1=false
     7#  @debug2=true
    78  def self.test(rubysource, testcase)
    89    script, bin = Tempfile.new(['test', '.rb']), Tempfile.new(['test', '.mrb'])
     
    2021    stdin_data = testcase.map{|t| t[:cmd]}.join("\n") << "\n"
    2122
     23    prompt = /^\(#{Regexp.escape(script.path)}:\d+\) /
    2224    ["bin/mrdb #{script.path}","bin/mrdb -b #{bin.path}"].each do |cmd|
    2325      o, s = Open3.capture2(cmd, :stdin_data => stdin_data)
    24 
    25       exp_vals = testcase.map{|t| t.fetch(:exp, nil)}
     26      scanner = StringScanner.new(o)
     27      scanner.skip_until(prompt)
     28      testcase.each do |tc|
     29        exp = tc[:exp]
     30        if exp
     31          act = scanner.scan_until(/\n/)
     32          break unless assert_operator act, :start_with?, exp
     33        end
     34        scanner.skip_until(prompt)
     35      end
     36
    2637=begin
    2738if @debug1
     
    4253      end
    4354=end
    44       idx = 0
    45       exp_vals.each do |exp|
    46         next if exp.nil?
    47         idx = o.index(exp, idx)
    48         assert_false idx.nil?
    49         break unless idx
    50         idx += 1
    51       end
    5255    end
    5356  end
     
    9194  # test case
    9295  tc = []
    93   tc << {:cmd=>"p (1+2",  :exp=>'$1 = SyntaxError'}
    94   tc << {:cmd=>"p bar",   :exp=>'$2 = NoMethodError'}
     96  tc << {:cmd=>"p (1+2",  :exp=>'$1 = line 1: syntax error'}
     97  tc << {:cmd=>"p bar",   :exp=>'$2 = undefined method'}
    9598
    9699  BinTest_MrubyBinDebugger.test(src, tc)
     
    318321SRC
    319322
    320   # todo: wait for 'break' to be implimented
     323  # todo: wait for 'break' to be implemented
    321324  tc = []
    322325  9.times { tc << {:cmd=>"s"} }
     
    342345  tc << {:cmd=>"p 0x100",   :exp=>'$4 = 256'}
    343346  tc << {:cmd=>"p 1_234",   :exp=>'$5 = 1234'}
    344   tc << {:cmd=>"p 0b1000_0000", :exp=>"$6 = #{0b1000_0000.to_s}"}
    345   tc << {:cmd=>"p 0x1000_0000", :exp=>"$7 = #{0x1000_0000.to_s}"}
     347  tc << {:cmd=>"p 0b1000_0000", :exp=>"$6 = #{0b1000_0000}"}
     348  tc << {:cmd=>"p 0x1000_0000", :exp=>"$7 = #{0x1000_0000}"}
    346349
    347350  tc << {:cmd=>"p 3.14",    :exp=>'$8 = 3.14'}
    348351  tc << {:cmd=>"p -12.3",   :exp=>'$9 = -12.3'}
    349   tc << {:cmd=>"p +12.000", :exp=>'$10 = 12.0'}
    350   tc << {:cmd=>"p 1e4",     :exp=>'$11 = 10000.0'}
     352  tc << {:cmd=>"p +12.000", :exp=>'$10 = 12'}
     353  tc << {:cmd=>"p 1e4",     :exp=>'$11 = 10000'}
    351354  tc << {:cmd=>"p -0.1e-2", :exp=>'$12 = -0.001'}
    352355
     
    369372  tc << {:cmd=>'p "str"',        :exp=>'$1 = "str"'}
    370373  tc << {:cmd=>'p "s\tt\rr\n"',  :exp=>'$2 = "s\\tt\\rr\\n"'}
    371   tc << {:cmd=>'p "\C-a\C-z"',   :exp=>'$3 = "\\001\\032"'}
     374  tc << {:cmd=>'p "\C-a\C-z"',   :exp=>'$3 = "\\x01\\x1a"'}
    372375  tc << {:cmd=>'p "#{foo+bar}"', :exp=>'$4 = "foobar"'}
    373376
     
    375378  tc << {:cmd=>'p \'s\\tt\\rr\\n\'', :exp=>'$6 = "s\\\\tt\\\\rr\\\\n"'}
    376379  tc << {:cmd=>'p \'\\C-a\\C-z\'',   :exp=>'$7 = "\\\\C-a\\\\C-z"'}
    377   tc << {:cmd=>'p \'#{foo+bar}\'',   :exp=>'$8 = "#{foo+bar}"'}
     380  tc << {:cmd=>'p \'#{foo+bar}\'',   :exp=>'$8 = "\\#{foo+bar}"'}
    378381
    379382  tc << {:cmd=>'p %!str!',        :exp=>'$9 = "str"'}
    380383  tc << {:cmd=>'p %!s\tt\rr\n!',  :exp=>'$10 = "s\\tt\\rr\\n"'}
    381   tc << {:cmd=>'p %!\C-a\C-z!',   :exp=>'$11 = "\\001\\032"'}
     384  tc << {:cmd=>'p %!\C-a\C-z!',   :exp=>'$11 = "\\x01\\x1a"'}
    382385  tc << {:cmd=>'p %!#{foo+bar}!', :exp=>'$12 = "foobar"'}
    383386
    384387  tc << {:cmd=>'p %Q!str!',        :exp=>'$13 = "str"'}
    385388  tc << {:cmd=>'p %Q!s\tt\rr\n!',  :exp=>'$14 = "s\\tt\\rr\\n"'}
    386   tc << {:cmd=>'p %Q!\C-a\C-z!',   :exp=>'$15 = "\\001\\032"'}
     389  tc << {:cmd=>'p %Q!\C-a\C-z!',   :exp=>'$15 = "\\x01\\x1a"'}
    387390  tc << {:cmd=>'p %Q!#{foo+bar}!', :exp=>'$16 = "foobar"'}
    388391
     
    390393  tc << {:cmd=>'p %q!s\\tt\\rr\\n!', :exp=>'$18 = "s\\\\tt\\\\rr\\\\n"'}
    391394  tc << {:cmd=>'p %q!\\C-a\\C-z!',   :exp=>'$19 = "\\\\C-a\\\\C-z"'}
    392   tc << {:cmd=>'p %q!#{foo+bar}!',   :exp=>'$20 = "#{foo+bar}"'}
     395  tc << {:cmd=>'p %q!#{foo+bar}!',   :exp=>'$20 = "\\#{foo+bar}"'}
    393396
    394397  BinTest_MrubyBinDebugger.test(src, tc)
     
    411414  tc << {:cmd=>'p [ 5,  12,   8,    10, ]', :exp=>'$2 = [5, 12, 8, 10]'}
    412415  tc << {:cmd=>'p [1,2.5,"#{foo+bar}"]',    :exp=>'$3 = [1, 2.5, "foobar"]'}
    413   tc << {:cmd=>'p %w[3.14 A\ &\ B #{foo}]', :exp=>'$4 = ["3.14", "A & B", "#{foo}"]'}
     416  tc << {:cmd=>'p %w[3.14 A\ &\ B #{foo}]', :exp=>'$4 = ["3.14", "A & B", "\#{foo}"]'}
    414417  tc << {:cmd=>'p %W[3.14 A\ &\ B #{foo}]', :exp=>'$5 = ["3.14", "A & B", "foo"]'}
    415418
     
    589592
    590593  tc << {:cmd=>'p undefined=-1',      :exp=>'$3 = -1'}
    591   tc << {:cmd=>'p "#{undefined}"',    :exp=>'$4 = NoMethodError'}
     594  tc << {:cmd=>'p "#{undefined}"',    :exp=>'$4 = undefined method'}
    592595
    593596  BinTest_MrubyBinDebugger.test(src, tc)
     
    627630
    628631  tc << {:cmd=>'p undefined=-1',    :exp=>'$14 = -1'}
    629   tc << {:cmd=>'p "#{undefined}"',  :exp=>'$15 = NoMethodError'}
     632  tc << {:cmd=>'p "#{undefined}"',  :exp=>'$15 = undefined method'}
    630633
    631634  BinTest_MrubyBinDebugger.test(src, tc)
     
    695698
    696699  tc << {:cmd=>'p undefined=-1',    :exp=>'$14 = -1'}
    697   tc << {:cmd=>'p "#{undefined}"',  :exp=>'$15 = NoMethodError'}
    698 
    699   BinTest_MrubyBinDebugger.test(src, tc)
    700 end
    701 
     700  tc << {:cmd=>'p "#{undefined}"',  :exp=>'$15 = undefined method'}
     701
     702  BinTest_MrubyBinDebugger.test(src, tc)
     703end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c

    r331 r439  
    8585
    8686static uint16_t
    87 check_file_lineno(struct mrb_irep *irep, const char *file, uint16_t lineno)
     87check_file_lineno(mrb_state *mrb, struct mrb_irep *irep, const char *file, uint16_t lineno)
    8888{
    8989  mrb_irep_debug_info_file *info_file;
     
    9494
    9595  for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
     96    const char *filename;
    9697    info_file = irep->debug_info->files[f_idx];
    97     if (!strcmp(info_file->filename, file)) {
     98    filename = mrb_sym_name_len(mrb, info_file->filename_sym, NULL);
     99    if (!strcmp(filename, file)) {
    98100      result = MRB_DEBUG_BP_FILE_OK;
    99101
     
    104106    }
    105107    for (i=0; i < irep->rlen; ++i) {
    106       result  |= check_file_lineno(irep->reps[i], file, lineno);
     108      result  |= check_file_lineno(mrb, irep->reps[i], file, lineno);
    107109      if (result == (MRB_DEBUG_BP_FILE_OK | MRB_DEBUG_BP_LINENO_OK)) {
    108110        return result;
     
    113115}
    114116
    115 static const char*
    116 get_class_name(mrb_state *mrb, struct RClass *class_obj)
    117 {
    118   struct RClass *outer;
    119   mrb_sym class_sym;
    120 
    121   outer = mrb_class_outer_module(mrb, class_obj);
    122   class_sym = mrb_class_sym(mrb, class_obj, outer);
    123   return mrb_sym2name(mrb, class_sym);
    124 }
    125 
    126117static int32_t
    127118compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *class_obj, mrb_sym method_sym, mrb_bool* isCfunc)
     
    129120  const char* class_name;
    130121  const char* method_name;
    131   struct RProc* m;
     122  mrb_method_t m;
    132123  struct RClass* sc;
    133124  const char* sn;
     
    136127  mrb_bool is_defined;
    137128
    138   method_name = mrb_sym2name(mrb, method_sym);
     129  method_name = mrb_sym_name(mrb, method_sym);
    139130
    140131  method_p = &bp->point.methodpoint;
    141132  if (strcmp(method_p->method_name, method_name) == 0) {
    142     class_name = get_class_name(mrb, class_obj);
     133    class_name = mrb_class_name(mrb, class_obj);
    143134    if (class_name == NULL) {
    144135      if (method_p->class_name == NULL) {
     
    148139    else if (method_p->class_name != NULL) {
    149140      m = mrb_method_search_vm(mrb, &class_obj, method_sym);
    150       if (m == NULL) {
     141      if (MRB_METHOD_UNDEF_P(m)) {
    151142        return MRB_DEBUG_OK;
    152143      }
    153       if (MRB_PROC_CFUNC_P(m)) {
     144      if (MRB_METHOD_CFUNC_P(m)) {
    154145        *isCfunc = TRUE;
    155146      }
     
    163154      ssym = mrb_symbol(mrb_check_intern_cstr(mrb, method_p->method_name));
    164155      m = mrb_method_search_vm(mrb, &sc, ssym);
    165       if (m == NULL) {
     156      if (MRB_METHOD_UNDEF_P(m)) {
    166157        return MRB_DEBUG_OK;
    167158      }
    168159
    169       class_name = get_class_name(mrb, class_obj);
    170       sn = get_class_name(mrb, sc);
     160      class_name = mrb_class_name(mrb, class_obj);
     161      sn = mrb_class_name(mrb, sc);
    171162      if (strcmp(sn, class_name) == 0) {
    172163        return bp->bpno;
     
    197188
    198189  /* file and lineno check (line type mrb_debug_line_ary only.) */
    199   result = check_file_lineno(dbg->root_irep, file, lineno);
     190  result = check_file_lineno(mrb, dbg->root_irep, file, lineno);
    200191  if (result == 0) {
    201192    return MRB_DEBUG_BREAK_INVALID_FILE;
     
    205196  }
    206197
    207   set_file = mrb_malloc(mrb, strlen(file) + 1);
     198  set_file = (char*)mrb_malloc(mrb, strlen(file) + 1);
    208199
    209200  index = dbg->bpnum;
     
    242233
    243234  if (class_name != NULL) {
    244     set_class = mrb_malloc(mrb, strlen(class_name) + 1);
     235    set_class = (char*)mrb_malloc(mrb, strlen(class_name) + 1);
    245236    strncpy(set_class, class_name, strlen(class_name) + 1);
    246237  }
     
    249240  }
    250241
    251   set_method = mrb_malloc(mrb, strlen(method_name) + 1);
     242  set_method = (char*)mrb_malloc(mrb, strlen(method_name) + 1);
    252243
    253244  strncpy(set_method, method_name, strlen(method_name) + 1);
     
    438429
    439430static mrb_bool
    440 check_start_pc_for_line(mrb_irep *irep, mrb_code *pc, uint16_t line)
     431check_start_pc_for_line(mrb_state *mrb, mrb_irep *irep, const mrb_code *pc, uint16_t line)
    441432{
    442433  if (pc > irep->iseq) {
    443     if (line == mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq - 1))) {
     434    if (line == mrb_debug_get_line(mrb, irep, pc - irep->iseq - 1)) {
    444435      return FALSE;
    445436    }
     
    459450  }
    460451
    461   if (!check_start_pc_for_line(dbg->irep, dbg->pc, line)) {
     452  if (!check_start_pc_for_line(mrb, dbg->irep, dbg->pc, line)) {
    462453    return MRB_DEBUG_OK;
    463454  }
     
    515506  return 0;
    516507}
    517 
    518 
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c

    r331 r439  
    4949  }
    5050
    51   path = mrb_malloc(mrb, len);
     51  path = (char*)mrb_malloc(mrb, len);
    5252  memset(path, 0, len);
    5353
     
    6565{
    6666  size_t len;
    67   char *p, *dir;
     67  const char *p;
     68  char *dir;
    6869
    6970  if (path == NULL) {
     
    7475  len = p != NULL ? (size_t)(p - path) : strlen(path);
    7576
    76   dir = mrb_malloc(mrb, len + 1);
     77  dir = (char*)mrb_malloc(mrb, len + 1);
    7778  strncpy(dir, path, len);
    7879  dir[len] = '\0';
     
    8485source_file_new(mrb_state *mrb, mrb_debug_context *dbg, char *filename)
    8586{
    86   source_file *file = NULL;
    87 
    88   file = mrb_malloc(mrb, sizeof(source_file));
     87  source_file *file;
     88
     89  file = (source_file*)mrb_malloc(mrb, sizeof(source_file));
    8990
    9091  memset(file, '\0', sizeof(source_file));
     
    9798
    9899  file->lineno = 1;
    99   file->path = mrb_malloc(mrb, strlen(filename) + 1);
     100  file->path = (char*)mrb_malloc(mrb, strlen(filename) + 1);
    100101  strcpy(file->path, filename);
    101102  return file;
     
    175176  const char *search_path[3];
    176177  char *path = NULL;
     178  const char *srcname = strrchr(filename, '/');
     179
     180  if (srcname) srcname++;
     181  else srcname = filename;
    177182
    178183  search_path[0] = srcpath;
    179   search_path[1] = dirname(mrb, mrb_debug_get_filename(mrdb->dbg->root_irep, 0));
     184  search_path[1] = dirname(mrb, mrb_debug_get_filename(mrb, mrdb->dbg->irep, 0));
    180185  search_path[2] = ".";
    181186
     
    185190    }
    186191
    187     if ((path = build_path(mrb, search_path[i], filename)) == NULL) {
     192    if ((path = build_path(mrb, search_path[i], srcname)) == NULL) {
    188193      continue;
    189194    }
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c

    r331 r439  
    2222  c->no_exec = TRUE;
    2323  c->capture_errors = TRUE;
    24   c->filename = (char*)dbg->prvfile;
     24  mrbc_filename(mrb, c, (const char*)dbg->prvfile);
    2525  c->lineno = dbg->prvline;
    2626
     
    3232
    3333mrb_value
    34 mrb_debug_eval(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size_t len, mrb_bool *exc)
     34mrb_debug_eval(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size_t len, mrb_bool *exc, int direct_eval)
    3535{
    36   void (*tmp)(struct mrb_state *, struct mrb_irep *, mrb_code *, mrb_value *);
     36  void (*tmp)(struct mrb_state *, struct mrb_irep *, const mrb_code *, mrb_value *);
    3737  mrb_value ruby_code;
    3838  mrb_value s;
     
    4848    v = mrb_obj_value(mrb->exc);
    4949    mrb->exc = 0;
     50  }
     51  else if (direct_eval) {
     52    recv = dbg->regs[0];
     53
     54    v = mrb_funcall(mrb, recv, expr, 0);
    5055  }
    5156  else {
     
    7075  }
    7176
    72   s = mrb_funcall(mrb, v, "inspect", 0);
     77  s = mrb_inspect(mrb, v);
    7378
    7479  /* enable code_fetch_hook */
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h

    r331 r439  
    99#include "mrdb.h"
    1010
    11 mrb_value mrb_debug_eval(mrb_state*, mrb_debug_context*, const char*, size_t, mrb_bool*);
     11mrb_value mrb_debug_eval(mrb_state*, mrb_debug_context*, const char*, size_t, mrb_bool*, int);
    1212
    1313#endif /* APIPRINT_H_ */
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c

    r331 r439  
    243243
    244244mrb_debug_bptype
    245 parse_breakcommand(mrdb_state *mrdb, const char **file, uint32_t *line, char **cname, char **method)
     245parse_breakcommand(mrb_state *mrb, mrdb_state *mrdb, const char **file, uint32_t *line, char **cname, char **method)
    246246{
    247247  mrb_debug_context *dbg = mrdb->dbg;
     
    275275      if (l <= 65535) {
    276276        *line = l;
    277         *file = (body == args)? mrb_debug_get_filename(dbg->irep, (uint32_t)(dbg->pc - dbg->irep->iseq)): args;
     277        *file = (body == args)? mrb_debug_get_filename(mrb, dbg->irep, dbg->pc - dbg->irep->iseq): args;
    278278      }
    279279      else {
     
    333333  int32_t ret;
    334334
    335   type = parse_breakcommand(mrdb, &file, &line, &cname, &method);
     335  type = parse_breakcommand(mrb, mrdb, &file, &line, &cname, &method);
    336336  switch (type) {
    337337    case MRB_DEBUG_BPTYPE_LINE:
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c

    r331 r439  
    8181    "Status of specified breakpoints (all user-settable breakpoints if no argument).\n"
    8282    "Arguments are breakpoint numbers with spaces in between.\n"
     83  },
     84  {
     85    "i[nfo]", "l[ocals]", "Print name of local variables",
     86    "Usage: info locals\n"
     87    "\n"
     88    "Print name of local variables.\n"
    8389  },
    8490  {
     
    134140listcmd_parser_state_new(mrb_state *mrb)
    135141{
    136   listcmd_parser_state *st = mrb_malloc(mrb, sizeof(listcmd_parser_state));
     142  listcmd_parser_state *st = (listcmd_parser_state*)mrb_malloc(mrb, sizeof(listcmd_parser_state));
    137143  memset(st, 0, sizeof(listcmd_parser_state));
    138144  return st;
     
    228234
    229235  if (len > 0) {
    230     st->filename = mrb_malloc(mrb, len + 1);
     236    st->filename = (char*)mrb_malloc(mrb, len + 1);
    231237    strncpy(st->filename, *sp, len);
    232238    st->filename[len] = '\0';
     
    243249{
    244250  size_t len;
    245   char *p, *s;
     251  const char *p;
     252  char *s;
    246253
    247254  if (filename == NULL) {
     
    256263  }
    257264
    258   s = mrb_malloc(mrb, len + strlen(ext) + 1);
     265  s = (char*)mrb_malloc(mrb, len + strlen(ext) + 1);
    259266  memset(s, '\0', len + strlen(ext) + 1);
    260267  strncpy(s, filename, len);
     
    326333check_cmd_pattern(const char *pattern, const char *cmd)
    327334{
    328   char *lbracket, *rbracket, *p, *q;
     335  const char *lbracket, *rbracket, *p, *q;
    329336
    330337  if (pattern == NULL && cmd == NULL) {
     
    495502  if (mrdb->dbg->xm == DBG_QUIT) {
    496503    struct RClass *exc;
    497     exc = mrb_define_class(mrb, "DebuggerExit", mrb_class_get(mrb, "Exception"));
     504    exc = mrb_define_class(mrb, "DebuggerExit", mrb->eException_class);
    498505    mrb_raise(mrb, exc, "Exit mrdb.");
    499506  }
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c

    r331 r439  
    1919  mrb_value expr;
    2020  mrb_value result;
    21   mrb_value s;
    2221  uint8_t wcnt;
    2322  int ai;
     
    3736  }
    3837
    39   result = mrb_debug_eval(mrb, mrdb->dbg, RSTRING_PTR(expr), RSTRING_LEN(expr), NULL);
     38  result = mrb_debug_eval(mrb, mrdb->dbg, RSTRING_PTR(expr), RSTRING_LEN(expr), NULL, 0);
    4039
    4140  /* $print_no = result */
    42   s = mrb_str_cat_lit(mrb, result, "\0");
    43   printf("$%lu = %s\n", (unsigned long)mrdb->print_no++, RSTRING_PTR(s));
     41  printf("$%lu = ", (unsigned long)mrdb->print_no++);
     42  fwrite(RSTRING_PTR(result), RSTRING_LEN(result), 1, stdout);
     43  putc('\n', stdout);
    4444
    4545  if (mrdb->print_no == 0) {
     
    5757  return dbgcmd_print(mrb, mrdb);
    5858}
     59
     60dbgcmd_state
     61dbgcmd_info_local(mrb_state *mrb, mrdb_state *mrdb)
     62{
     63  mrb_value result;
     64  mrb_value s;
     65  int ai;
     66
     67  ai = mrb_gc_arena_save(mrb);
     68
     69  result = mrb_debug_eval(mrb, mrdb->dbg, "local_variables", 0, NULL, 1);
     70
     71  s = mrb_str_cat_lit(mrb, result, "\0");
     72  printf("$%lu = %s\n", (unsigned long)mrdb->print_no++, RSTRING_PTR(s));
     73
     74  if (mrdb->print_no == 0) {
     75    mrdb->print_no = 1;
     76  }
     77
     78  mrb_gc_arena_restore(mrb, ai);
     79
     80  return DBGST_PROMPT;
     81}
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c

    r331 r439  
    2020      struct RClass *exc;
    2121      puts("Start it from the beginning.");
    22       exc = mrb_define_class(mrb, "DebuggerRestart", mrb_class_get(mrb, "Exception"));
     22      exc = mrb_define_class(mrb, "DebuggerRestart", mrb->eException_class);
    2323      mrb_raise(mrb, exc, "Restart mrdb.");
    2424    }
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c

    r331 r439  
    66#include <stdlib.h>
    77#include <string.h>
    8 #include <stdio.h>
    98#include <ctype.h>
    109
     
    5352  {"help",      NULL,           1, 0, 1, DBGCMD_HELP,           dbgcmd_help},            /* h[elp] */
    5453  {"info",      "breakpoints",  1, 1, 1, DBGCMD_INFO_BREAK,     dbgcmd_info_break},      /* i[nfo] b[reakpoints] */
     54  {"info",      "locals",       1, 1, 0, DBGCMD_INFO_LOCAL,     dbgcmd_info_local},      /* i[nfo] l[ocals] */
    5555  {"list",      NULL,           1, 0, 1, DBGCMD_LIST,           dbgcmd_list},            /* l[ist] */
    5656  {"print",     NULL,           1, 0, 0, DBGCMD_PRINT,          dbgcmd_print},           /* p[rint] */
     
    185185mrb_debug_context_new(mrb_state *mrb)
    186186{
    187   mrb_debug_context *dbg = mrb_malloc(mrb, sizeof(mrb_debug_context));
     187  mrb_debug_context *dbg = (mrb_debug_context*)mrb_malloc(mrb, sizeof(mrb_debug_context));
    188188
    189189  memset(dbg, 0, sizeof(mrb_debug_context));
     
    224224mrdb_state_new(mrb_state *mrb)
    225225{
    226   mrdb_state *mrdb = mrb_malloc(mrb, sizeof(mrdb_state));
     226  mrdb_state *mrdb = (mrdb_state*)mrb_malloc(mrb, sizeof(mrdb_state));
    227227
    228228  memset(mrdb, 0, sizeof(mrdb_state));
    229229
    230230  mrdb->dbg = mrb_debug_context_get(mrb);
    231   mrdb->command = mrb_malloc(mrb, MAX_COMMAND_LINE+1);
     231  mrdb->command = (char*)mrb_malloc(mrb, MAX_COMMAND_LINE+1);
    232232  mrdb->print_no = 1;
    233233
     
    505505
    506506static int32_t
    507 check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *regs)
     507check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, const mrb_code *pc, mrb_value *regs)
    508508{
    509509  struct RClass* c;
     
    511511  int32_t bpno;
    512512  mrb_bool isCfunc;
     513  struct mrb_insn_data insn;
    513514
    514515  mrb_debug_context *dbg = mrb_debug_context_get(mrb);
     
    518519  dbg->method_bpno = 0;
    519520
    520   switch(GET_OPCODE(*pc)) {
     521  insn = mrb_decode_insn(pc);
     522  switch(insn.insn) {
    521523    case OP_SEND:
    522524    case OP_SENDB:
    523       c = mrb_class(mrb, regs[GETARG_A(*pc)]);
    524       sym = irep->syms[GETARG_B(*pc)];
     525      c = mrb_class(mrb, regs[insn.a]);
     526      sym = irep->syms[insn.b];
    525527      break;
    526528    case OP_SUPER:
     
    544546
    545547static void
    546 mrb_code_fetch_hook(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *regs)
     548mrb_code_fetch_hook(mrb_state *mrb, mrb_irep *irep, const mrb_code *pc, mrb_value *regs)
    547549{
    548550  const char *file;
     
    567569  }
    568570
    569   file = mrb_debug_get_filename(irep, (uint32_t)(pc - irep->iseq));
    570   line = mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq));
     571  file = mrb_debug_get_filename(mrb, irep, pc - irep->iseq);
     572  line = mrb_debug_get_line(mrb, irep, pc - irep->iseq);
    571573
    572574  switch (dbg->xm) {
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h

    r331 r439  
    2424  DBGCMD_BREAK,
    2525  DBGCMD_INFO_BREAK,
     26  DBGCMD_INFO_LOCAL,
    2627  DBGCMD_WATCH,
    2728  DBGCMD_INFO_WATCH,
     
    105106  struct mrb_irep *root_irep;
    106107  struct mrb_irep *irep;
    107   mrb_code *pc;
     108  const mrb_code *pc;
    108109  mrb_value *regs;
    109110
     
    152153dbgcmd_state dbgcmd_break(mrb_state*, mrdb_state*);
    153154dbgcmd_state dbgcmd_info_break(mrb_state*, mrdb_state*);
     155dbgcmd_state dbgcmd_info_local(mrb_state*, mrdb_state*);
    154156dbgcmd_state dbgcmd_delete(mrb_state*, mrdb_state*);
    155157dbgcmd_state dbgcmd_enable(mrb_state*, mrdb_state*);
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h

    r321 r439  
    66#ifndef MRDBCONF_H
    77#define MRDBCONF_H
     8
     9#ifndef MRB_ENABLE_DEBUG_HOOK
     10# error mruby-bin-debugger need 'MRB_ENABLE_DEBUG_HOOK' configuration in your 'build_config.rb'
     11#endif
     12
     13#ifdef MRB_DISABLE_STDIO
     14# error mruby-bin-debugger conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
     15#endif
    816
    917/* configuration options: */
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-mirb/bintest/mirb.rb

    r321 r439  
    1111  assert_true o.include?('=> 3')
    1212end
     13
     14assert('mirb -d option') do
     15  o, _ = Open3.capture2('bin/mirb', :stdin_data => "$DEBUG\n")
     16  assert_true o.include?('=> false')
     17  o, _ = Open3.capture2('bin/mirb -d', :stdin_data => "$DEBUG\n")
     18  assert_true o.include?('=> true')
     19end
     20
     21assert('mirb -r option') do
     22  lib = Tempfile.new('lib.rb')
     23  lib.write <<EOS
     24class Hoge
     25  def hoge
     26    :hoge
     27  end
     28end
     29EOS
     30  lib.flush
     31
     32  o, _ = Open3.capture2("bin/mirb -r #{lib.path}", :stdin_data => "Hoge.new.hoge\n")
     33  assert_true o.include?('=> :hoge')
     34end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c

    r331 r439  
    77*/
    88
     9#include <mruby.h>
     10
     11#ifdef MRB_DISABLE_STDIO
     12# error mruby-bin-mirb conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
     13#endif
     14
     15#include <mruby/array.h>
     16#include <mruby/proc.h>
     17#include <mruby/compile.h>
     18#include <mruby/dump.h>
     19#include <mruby/string.h>
     20#include <mruby/variable.h>
     21#include <mruby/throw.h>
     22
    923#include <stdlib.h>
    1024#include <string.h>
    11 #include <stdio.h>
    1225#include <ctype.h>
    1326
     
    2033#define MIRB_ADD_HISTORY(line) add_history(line)
    2134#define MIRB_READLINE(ch) readline(ch)
     35#if !defined(RL_READLINE_VERSION) || RL_READLINE_VERSION < 0x600
     36/* libedit & older readline do not have rl_free() */
     37#define MIRB_LINE_FREE(line) free(line)
     38#else
     39#define MIRB_LINE_FREE(line) rl_free(line)
     40#endif
    2241#define MIRB_WRITE_HISTORY(path) write_history(path)
    2342#define MIRB_READ_HISTORY(path) read_history(path)
     
    2847#define MIRB_ADD_HISTORY(line) linenoiseHistoryAdd(line)
    2948#define MIRB_READLINE(ch) linenoise(ch)
     49#define MIRB_LINE_FREE(line) linenoiseFree(line)
    3050#define MIRB_WRITE_HISTORY(path) linenoiseHistorySave(path)
    3151#define MIRB_READ_HISTORY(path) linenoiseHistoryLoad(history_path)
     
    4262#define SIGJMP_BUF jmp_buf
    4363#endif
    44 
    45 #include <mruby.h>
    46 #include <mruby/array.h>
    47 #include <mruby/proc.h>
    48 #include <mruby/compile.h>
    49 #include <mruby/string.h>
    5064
    5165#ifdef ENABLE_READLINE
     
    89103{
    90104  mrb_value val;
     105  char* msg;
    91106
    92107  val = mrb_funcall(mrb, obj, "inspect", 0);
     
    102117    val = mrb_obj_as_string(mrb, obj);
    103118  }
    104   fwrite(RSTRING_PTR(val), RSTRING_LEN(val), 1, stdout);
     119  msg = mrb_locale_from_utf8(RSTRING_PTR(val), (int)RSTRING_LEN(val));
     120  fwrite(msg, strlen(msg), 1, stdout);
     121  mrb_locale_free(msg);
    105122  putc('\n', stdout);
    106123}
     
    115132  /* check for heredoc */
    116133  if (parser->parsing_heredoc != NULL) return TRUE;
    117   if (parser->heredoc_end_now) {
    118     parser->heredoc_end_now = FALSE;
    119     return FALSE;
    120   }
    121134
    122135  /* check for unterminated string */
     
    210223  FILE *rfp;
    211224  mrb_bool verbose      : 1;
     225  mrb_bool debug        : 1;
    212226  int argc;
    213227  char** argv;
     228  int libc;
     229  char **libv;
    214230};
    215231
     
    219235  static const char *const usage_msg[] = {
    220236  "switches:",
     237  "-d           set $DEBUG to true (same as `mruby -d`)",
     238  "-r library   same as `mruby -r`",
    221239  "-v           print version number, then run in verbose mode",
    222240  "--verbose    run in verbose mode",
     
    227245  const char *const *p = usage_msg;
    228246
    229   printf("Usage: %s [switches]\n", name);
     247  printf("Usage: %s [switches] [programfile] [arguments]\n", name);
    230248  while (*p)
    231249    printf("  %s\n", *p++);
    232250}
    233251
     252static char *
     253dup_arg_item(mrb_state *mrb, const char *item)
     254{
     255  size_t buflen = strlen(item) + 1;
     256  char *buf = (char*)mrb_malloc(mrb, buflen);
     257  memcpy(buf, item, buflen);
     258  return buf;
     259}
     260
    234261static int
    235262parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
    236263{
     264  char **origargv = argv;
    237265  static const struct _args args_zero = { 0 };
    238266
     
    245273    item = argv[0] + 1;
    246274    switch (*item++) {
     275    case 'd':
     276      args->debug = TRUE;
     277      break;
     278    case 'r':
     279      if (!item[0]) {
     280        if (argc <= 1) {
     281          printf("%s: No library specified for -r\n", *origargv);
     282          return EXIT_FAILURE;
     283        }
     284        argc--; argv++;
     285        item = argv[0];
     286      }
     287      if (args->libc == 0) {
     288        args->libv = (char**)mrb_malloc(mrb, sizeof(char*));
     289      }
     290      else {
     291        args->libv = (char**)mrb_realloc(mrb, args->libv, sizeof(char*) * (args->libc + 1));
     292      }
     293      args->libv[args->libc++] = dup_arg_item(mrb, item);
     294      break;
    247295    case 'v':
    248296      if (!args->verbose) mrb_show_version(mrb);
     
    290338    fclose(args->rfp);
    291339  mrb_free(mrb, args->argv);
     340  if (args->libc) {
     341    while (args->libc--) {
     342      mrb_free(mrb, args->libv[args->libc]);
     343    }
     344    mrb_free(mrb, args->libv);
     345  }
    292346  mrb_close(mrb);
    293347}
     
    324378
    325379  /* skip preceding spaces */
    326   while (*p && isspace((unsigned char)*p)) {
     380  while (*p && ISSPACE(*p)) {
    327381    p++;
    328382  }
     
    334388  /* skip trailing spaces */
    335389  while (*p) {
    336     if (!isspace((unsigned char)*p)) return 0;
     390    if (!ISSPACE(*p)) return 0;
    337391    p++;
    338392  }
     
    354408{
    355409  MIRB_SIGLONGJMP(ctrl_c_buf, 1);
     410}
     411#endif
     412
     413#ifndef DISABLE_MIRB_UNDERSCORE
     414void decl_lv_underscore(mrb_state *mrb, mrbc_context *cxt)
     415{
     416  struct RProc *proc;
     417  struct mrb_parser_state *parser;
     418
     419  parser = mrb_parse_string(mrb, "_=nil", cxt);
     420  if (parser == NULL) {
     421    fputs("create parser state error\n", stderr);
     422    mrb_close(mrb);
     423    exit(EXIT_FAILURE);
     424  }
     425
     426  proc = mrb_generate_code(mrb, parser);
     427  mrb_vm_run(mrb, proc, mrb_top_self(mrb), 0);
     428
     429  mrb_parser_free(parser);
    356430}
    357431#endif
     
    404478  }
    405479  mrb_define_global_const(mrb, "ARGV", ARGV);
     480  mrb_gv_set(mrb, mrb_intern_lit(mrb, "$DEBUG"), mrb_bool_value(args.debug));
    406481
    407482#ifdef ENABLE_READLINE
     
    420495
    421496  cxt = mrbc_context_new(mrb);
     497
     498#ifndef DISABLE_MIRB_UNDERSCORE
     499  decl_lv_underscore(mrb, cxt);
     500#endif
     501
     502  /* Load libraries */
     503  for (i = 0; i < args.libc; i++) {
     504    FILE *lfp = fopen(args.libv[i], "r");
     505    if (lfp == NULL) {
     506      printf("Cannot open library file. (%s)\n", args.libv[i]);
     507      cleanup(mrb, &args);
     508      return EXIT_FAILURE;
     509    }
     510    mrb_load_file_cxt(mrb, lfp, cxt);
     511    fclose(lfp);
     512  }
     513
    422514  cxt->capture_errors = TRUE;
    423515  cxt->lineno = 1;
     
    429521  while (TRUE) {
    430522    char *utf8;
    431 
     523    struct mrb_jmpbuf c_jmp;
     524
     525    MRB_TRY(&c_jmp);
     526    mrb->jmp = &c_jmp;
    432527    if (args.rfp) {
    433528      if (fgets(last_code_line, sizeof(last_code_line)-1, args.rfp) != NULL)
     
    490585    strcat(last_code_line, "\n");
    491586    MIRB_ADD_HISTORY(line);
    492     free(line);
    493 #endif
    494 
    495 done:
    496 
     587    MIRB_LINE_FREE(line);
     588#endif
     589
     590  done:
    497591    if (code_block_open) {
    498592      if (strlen(ruby_code)+strlen(last_code_line) > sizeof(ruby_code)-1) {
     
    529623    }
    530624    else {
     625      if (0 < parser->nwarn) {
     626        /* warning */
     627        char* msg = mrb_locale_from_utf8(parser->warn_buffer[0].message, -1);
     628        printf("line %d: %s\n", parser->warn_buffer[0].lineno, msg);
     629        mrb_locale_free(msg);
     630      }
    531631      if (0 < parser->nerr) {
    532632        /* syntax error */
    533         printf("line %d: %s\n", parser->error_buffer[0].lineno, parser->error_buffer[0].message);
     633        char* msg = mrb_locale_from_utf8(parser->error_buffer[0].message, -1);
     634        printf("line %d: %s\n", parser->error_buffer[0].lineno, msg);
     635        mrb_locale_free(msg);
    534636      }
    535637      else {
     
    544646        if (args.verbose) {
    545647          mrb_codedump_all(mrb, proc);
     648        }
     649        /* adjust stack length of toplevel environment */
     650        if (mrb->c->cibase->env) {
     651          struct REnv *e = mrb->c->cibase->env;
     652          if (e && MRB_ENV_STACK_LEN(e) < proc->body.irep->nlocals) {
     653            MRB_ENV_SET_STACK_LEN(e, proc->body.irep->nlocals);
     654          }
    546655        }
    547656        /* pass a proc for evaluation */
     
    563672          }
    564673          p(mrb, result, 1);
     674#ifndef DISABLE_MIRB_UNDERSCORE
     675          *(mrb->c->stack + 1) = result;
     676#endif
    565677        }
    566678      }
     
    571683    mrb_parser_free(parser);
    572684    cxt->lineno++;
     685    MRB_CATCH(&c_jmp) {
     686      p(mrb, mrb_obj_value(mrb->exc), 0);
     687      mrb->exc = 0;
     688    }
     689    MRB_END_EXC(&c_jmp);
    573690  }
    574691
     
    578695#endif
    579696
     697  if (args.rfp) fclose(args.rfp);
     698  mrb_free(mrb, args.argv);
     699  if (args.libv) {
     700    for (i = 0; i < args.libc; ++i) {
     701      mrb_free(mrb, args.libv[i]);
     702    }
     703    mrb_free(mrb, args.libv);
     704  }
    580705  mrbc_context_free(mrb, cxt);
    581706  mrb_close(mrb);
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-mrbc/mrbgem.rake

    r321 r439  
    99  mrbc_objs = Dir.glob("#{spec.dir}/tools/mrbc/*.c").map { |f| objfile(f.pathmap("#{spec.build_dir}/tools/mrbc/%n")) }.flatten
    1010
    11   file exec => mrbc_objs + [libfile("#{build.build_dir}/lib/libmruby_core")] do |t|
     11  file exec => mrbc_objs + [build.libmruby_core_static] do |t|
    1212    build.linker.run t.name, t.prerequisites
    1313  end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c

    r331 r439  
    1 #include <stdio.h>
     1#include <mruby.h>
     2
     3#ifdef MRB_DISABLE_STDIO
     4# error mruby-bin-mrbc conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
     5#endif
     6
    27#include <stdlib.h>
    38#include <string.h>
    4 #include <mruby.h>
    59#include <mruby/compile.h>
    610#include <mruby/dump.h>
     
    1923  mrb_bool check_syntax : 1;
    2024  mrb_bool verbose      : 1;
     25  mrb_bool remove_lv    : 1;
    2126  unsigned int flags    : 4;
    2227};
     
    3439  "-e           generate little endian iseq data",
    3540  "-E           generate big endian iseq data",
     41  "--remove-lv  remove local variables",
    3642  "--verbose    run at verbose mode",
    3743  "--version    print the version",
     
    7076parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
    7177{
    72   char *outfile = NULL;
    7378  static const struct mrbc_args args_zero = { 0 };
    7479  int i;
     
    8590        if (args->outfile) {
    8691          fprintf(stderr, "%s: an output file is already specified. (%s)\n",
    87                   args->prog, outfile);
     92                  args->prog, args->outfile);
    8893          return -1;
    8994        }
     
    143148          exit(EXIT_SUCCESS);
    144149        }
     150        else if (strcmp(argv[i] + 2, "remove-lv") == 0) {
     151          args->remove_lv = TRUE;
     152          break;
     153        }
    145154        return -1;
    146155      default:
     
    179188  }
    180189  fn = args->argv[args->idx++];
    181   p->f = fopen(fn, "r");
     190  p->f = fopen(fn, "rb");
    182191  if (p->f == NULL) {
    183192    fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, fn);
     
    206215  else {
    207216    need_close = TRUE;
    208     if ((infile = fopen(input, "r")) == NULL) {
     217    if ((infile = fopen(input, "rb")) == NULL) {
    209218      fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, input);
    210219      return mrb_nil_value();
     
    233242  mrb_irep *irep = proc->body.irep;
    234243
     244  if (args->remove_lv) {
     245    mrb_irep_remove_lv(mrb, irep);
     246  }
    235247  if (args->initname) {
    236248    n = mrb_dump_irep_cfunc(mrb, irep, args->flags, wfp, args->initname);
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-mruby/bintest/mruby.rb

    r331 r439  
    11require 'tempfile'
     2require 'open3'
     3
     4def assert_mruby(exp_out, exp_err, exp_success, args)
     5  out, err, stat = Open3.capture3(cmd("mruby"), *args)
     6  assert "assert_mruby" do
     7    assert_operator(exp_out, :===, out, "standard output")
     8    assert_operator(exp_err, :===, err, "standard error")
     9    assert_equal(exp_success, stat.success?, "exit success?")
     10  end
     11end
    212
    313assert('regression for #1564') do
    4   o = `#{cmd('mruby')} -e #{shellquote('<<')} 2>&1`
    5   assert_include o, "-e:1:2: syntax error"
    6   o = `#{cmd('mruby')} -e #{shellquote('<<-')} 2>&1`
    7   assert_include o, "-e:1:3: syntax error"
     14  assert_mruby("", /\A-e:1:2: syntax error, .*\n\z/, false, %w[-e <<])
     15  assert_mruby("", /\A-e:1:3: syntax error, .*\n\z/, false, %w[-e <<-])
    816end
    917
     
    1321  system "#{cmd('mrbc')} -g -o #{bin.path} #{script.path}"
    1422  o = `#{cmd('mruby')} -b #{bin.path}`.strip
    15   assert_equal o, '"ok"'
     23  assert_equal '"ok"', o
    1624end
    1725
     
    3038  # one liner
    3139  assert_equal '"-e"', `#{cmd('mruby')} -e #{shellquote('p $0')}`.chomp
     40end
     41
     42assert 'ARGV value' do
     43  assert_mruby(%{["ab", "cde"]\n}, "", true, %w[-e p(ARGV) ab cde])
     44  assert_mruby("[]\n", "", true, %w[-e p(ARGV)])
     45end
     46
     47assert('float literal') do
     48  script, bin = Tempfile.new('test.rb'), Tempfile.new('test.mrb')
     49  File.write script.path, 'p [3.21, 2e308.infinite?, -2e308.infinite?]'
     50  system "#{cmd('mrbc')} -g -o #{bin.path} #{script.path}"
     51  assert_equal "[3.21, 1, -1]", `#{cmd('mruby')} -b #{bin.path}`.chomp!
    3252end
    3353
     
    5979  assert_equal 0, $?.exitstatus
    6080end
     81
     82assert('mruby -c option') do
     83  assert_mruby("Syntax OK\n", "", true, ["-c", "-e", "p 1"])
     84  assert_mruby("", /\A-e:1:7: syntax error, .*\n\z/, false, ["-c", "-e", "p 1; 1."])
     85end
     86
     87assert('mruby -d option') do
     88  assert_mruby("false\n", "", true, ["-e", "p $DEBUG"])
     89  assert_mruby("true\n", "", true, ["-dep $DEBUG"])
     90end
     91
     92assert('mruby -e option (no code specified)') do
     93  assert_mruby("", /\A.*: No code specified for -e\n\z/, false, %w[-e])
     94end
     95
     96assert('mruby -h option') do
     97  assert_mruby(/\AUsage: #{Regexp.escape cmd("mruby")} .*/m, "", true, %w[-h])
     98end
     99
     100assert('mruby -r option') do
     101  lib = Tempfile.new('lib.rb')
     102  lib.write <<EOS
     103class Hoge
     104  def hoge
     105    :hoge
     106  end
     107end
     108EOS
     109  lib.flush
     110
     111  script = Tempfile.new('test.rb')
     112  script.write <<EOS
     113print Hoge.new.hoge
     114EOS
     115  script.flush
     116  assert_equal 'hoge', `#{cmd('mruby')} -r #{lib.path} #{script.path}`
     117  assert_equal 0, $?.exitstatus
     118
     119  assert_equal 'hogeClass', `#{cmd('mruby')} -r #{lib.path} -r #{script.path} -e #{shellquote('print Hoge.class')}`
     120  assert_equal 0, $?.exitstatus
     121end
     122
     123assert('mruby -r option (no library specified)') do
     124  assert_mruby("", /\A.*: No library specified for -r\n\z/, false, %w[-r])
     125end
     126
     127assert('mruby -r option (file not found)') do
     128  assert_mruby("", /\A.*: Cannot open library file: .*\n\z/, false, %w[-r _no_exists_])
     129end
     130
     131assert('mruby -v option') do
     132  ver_re = '\Amruby \d+\.\d+\.\d+ \(\d+-\d+-\d+\)\n'
     133  assert_mruby(/#{ver_re}\z/, "", true, %w[-v])
     134  assert_mruby(/#{ver_re}^[^\n]*NODE.*\n:end\n\z/m, "", true, %w[-v -e p(:end)])
     135end
     136
     137assert('mruby --verbose option') do
     138  assert_mruby(/\A[^\n]*NODE.*\n:end\n\z/m, "", true, %w[--verbose -e p(:end)])
     139end
     140
     141assert('mruby --') do
     142  assert_mruby(%{["-x", "1"]\n}, "", true, %w[-e p(ARGV) -- -x 1])
     143end
     144
     145assert('mruby invalid short option') do
     146  assert_mruby("", /\A.*: invalid option -1 .*\n\z/, false, %w[-1])
     147end
     148
     149assert('mruby invalid long option') do
     150  assert_mruby("", /\A.*: invalid option --longopt .*\n\z/, false, %w[--longopt])
     151end
     152
     153assert('unhandled exception') do
     154  assert_mruby("", /\bEXCEPTION\b.*\n\z/, false, %w[-e raise("EXCEPTION")])
     155end
     156
     157assert('program file not found') do
     158  assert_mruby("", /\A.*: Cannot open program file: .*\n\z/, false, %w[_no_exists_])
     159end
     160
     161assert('codegen error') do
     162  code = "def f(#{(1..100).map{|n| "a#{n}"} * ","}); end"
     163  assert_mruby("", /\Acodegen error:.*\n\z/, false, ["-e", code])
     164end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-mruby/mrbgem.rake

    r331 r439  
    66  spec.add_dependency('mruby-compiler', :core => 'mruby-compiler')
    77  spec.add_dependency('mruby-error', :core => 'mruby-error')
     8  spec.add_test_dependency('mruby-print', :core => 'mruby-print')
    89
    910  if build.cxx_exception_enabled?
    10     @objs << build.compile_as_cxx("#{spec.dir}/tools/mruby/mruby.c", "#{spec.build_dir}/tools/mruby/mruby.cxx")
    11     @objs.delete_if { |v| v == objfile("#{spec.build_dir}/tools/mruby/mruby") }
     11    build.compile_as_cxx("#{spec.dir}/tools/mruby/mruby.c", "#{spec.build_dir}/tools/mruby/mruby.cxx")
    1212  end
    1313end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c

    r331 r439  
    1 #include <stdio.h>
     1#include <mruby.h>
     2
     3#ifdef MRB_DISABLE_STDIO
     4# error mruby-bin-mruby conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
     5#endif
     6
    27#include <stdlib.h>
    38#include <string.h>
    4 #include <mruby.h>
    59#include <mruby/array.h>
    610#include <mruby/compile.h>
     
    812#include <mruby/variable.h>
    913
    10 #ifdef MRB_DISABLE_STDIO
    11 static void
    12 p(mrb_state *mrb, mrb_value obj)
    13 {
    14   mrb_value val = mrb_inspect(mrb, obj);
    15 
    16   fwrite(RSTRING_PTR(val), RSTRING_LEN(val), 1, stdout);
    17   putc('\n', stdout);
    18 }
    19 #else
    20 #define p(mrb,obj) mrb_p(mrb,obj)
    21 #endif
    22 
    2314struct _args {
    2415  FILE *rfp;
    25   char* cmdline;
     16  char *cmdline;
    2617  mrb_bool fname        : 1;
    2718  mrb_bool mrbfile      : 1;
    2819  mrb_bool check_syntax : 1;
    2920  mrb_bool verbose      : 1;
     21  mrb_bool version      : 1;
     22  mrb_bool debug        : 1;
    3023  int argc;
    31   char** argv;
     24  char **argv;
     25  int libc;
     26  char **libv;
     27};
     28
     29struct options {
     30  int argc;
     31  char **argv;
     32  char *program;
     33  char *opt;
     34  char short_opt[2];
    3235};
    3336
     
    3942  "-b           load and execute RiteBinary (mrb) file",
    4043  "-c           check syntax only",
     44  "-d           set debugging flags (set $DEBUG to true)",
    4145  "-e 'command' one line of script",
     46  "-r library   load the library before executing your script",
    4247  "-v           print version number, then run in verbose mode",
    4348  "--verbose    run in verbose mode",
     
    4853  const char *const *p = usage_msg;
    4954
    50   printf("Usage: %s [switches] programfile\n", name);
     55  printf("Usage: %s [switches] [programfile] [arguments]\n", name);
    5156  while (*p)
    5257    printf("  %s\n", *p++);
    5358}
    5459
     60static void
     61options_init(struct options *opts, int argc, char **argv)
     62{
     63  opts->argc = argc;
     64  opts->argv = argv;
     65  opts->program = *argv;
     66  *opts->short_opt = 0;
     67}
     68
     69static const char *
     70options_opt(struct options *opts)
     71{
     72  /* concatenated short options (e.g. `-cv`) */
     73  if (*opts->short_opt && *++opts->opt) {
     74   short_opt:
     75    opts->short_opt[0] = *opts->opt;
     76    opts->short_opt[1] = 0;
     77    return opts->short_opt;
     78  }
     79
     80  while (++opts->argv, --opts->argc) {
     81    opts->opt = *opts->argv;
     82
     83    /*  empty         || not start with `-`  || `-` */
     84    if (!opts->opt[0] || opts->opt[0] != '-' || !opts->opt[1]) return NULL;
     85
     86    if (opts->opt[1] == '-') {
     87      /* `--` */
     88      if (!opts->opt[2]) {
     89        ++opts->argv, --opts->argc;
     90        return NULL;
     91      }
     92      /* long option */
     93      opts->opt += 2;
     94      *opts->short_opt = 0;
     95      return opts->opt;
     96    }
     97    else {
     98      /* short option */
     99      ++opts->opt;
     100      goto short_opt;
     101    }
     102  }
     103  return NULL;
     104}
     105
     106static const char *
     107options_arg(struct options *opts)
     108{
     109  if (*opts->short_opt && opts->opt[1]) {
     110    /* concatenated short option and option argument (e.g. `-rLIBRARY`) */
     111    *opts->short_opt = 0;
     112    return opts->opt + 1;
     113  }
     114  --opts->argc, ++opts->argv;
     115  return opts->argc ? *opts->argv : NULL;
     116}
     117
     118static char *
     119dup_arg_item(mrb_state *mrb, const char *item)
     120{
     121  size_t buflen = strlen(item) + 1;
     122  char *buf = (char*)mrb_malloc(mrb, buflen);
     123  memcpy(buf, item, buflen);
     124  return buf;
     125}
     126
    55127static int
    56128parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
    57129{
    58   char **origargv = argv;
    59130  static const struct _args args_zero = { 0 };
     131  struct options opts[1];
     132  const char *opt, *item;
    60133
    61134  *args = args_zero;
    62 
    63   for (argc--,argv++; argc > 0; argc--,argv++) {
    64     char *item;
    65     if (argv[0][0] != '-') break;
    66 
    67     if (strlen(*argv) <= 1) {
    68       argc--; argv++;
    69       args->rfp = stdin;
    70       break;
    71     }
    72 
    73     item = argv[0] + 1;
    74     switch (*item++) {
    75     case 'b':
     135  options_init(opts, argc, argv);
     136  while ((opt = options_opt(opts))) {
     137    if (strcmp(opt, "b") == 0) {
    76138      args->mrbfile = TRUE;
    77       break;
    78     case 'c':
     139    }
     140    else if (strcmp(opt, "c") == 0) {
    79141      args->check_syntax = TRUE;
    80       break;
    81     case 'e':
    82       if (item[0]) {
    83         goto append_cmdline;
    84       }
    85       else if (argc > 1) {
    86         argc--; argv++;
    87         item = argv[0];
    88 append_cmdline:
     142    }
     143    else if (strcmp(opt, "d") == 0) {
     144      args->debug = TRUE;
     145    }
     146    else if (strcmp(opt, "e") == 0) {
     147      if ((item = options_arg(opts))) {
    89148        if (!args->cmdline) {
    90           size_t buflen;
    91           char *buf;
    92 
    93           buflen = strlen(item) + 1;
    94           buf = (char *)mrb_malloc(mrb, buflen);
    95           memcpy(buf, item, buflen);
    96           args->cmdline = buf;
     149          args->cmdline = dup_arg_item(mrb, item);
    97150        }
    98151        else {
     
    109162      }
    110163      else {
    111         printf("%s: No code specified for -e\n", *origargv);
    112         return EXIT_SUCCESS;
    113       }
    114       break;
    115     case 'v':
    116       if (!args->verbose) mrb_show_version(mrb);
     164        fprintf(stderr, "%s: No code specified for -e\n", opts->program);
     165        return EXIT_FAILURE;
     166      }
     167    }
     168    else if (strcmp(opt, "h") == 0) {
     169      usage(opts->program);
     170      exit(EXIT_SUCCESS);
     171    }
     172    else if (strcmp(opt, "r") == 0) {
     173      if ((item = options_arg(opts))) {
     174        if (args->libc == 0) {
     175          args->libv = (char**)mrb_malloc(mrb, sizeof(char*));
     176        }
     177        else {
     178          args->libv = (char**)mrb_realloc(mrb, args->libv, sizeof(char*) * (args->libc + 1));
     179        }
     180        args->libv[args->libc++] = dup_arg_item(mrb, item);
     181      }
     182      else {
     183        fprintf(stderr, "%s: No library specified for -r\n", opts->program);
     184        return EXIT_FAILURE;
     185      }
     186    }
     187    else if (strcmp(opt, "v") == 0) {
     188      if (!args->verbose) {
     189        mrb_show_version(mrb);
     190        args->version = TRUE;
     191      }
    117192      args->verbose = TRUE;
    118       break;
    119     case '-':
    120       if (strcmp((*argv) + 2, "version") == 0) {
    121         mrb_show_version(mrb);
    122         exit(EXIT_SUCCESS);
    123       }
    124       else if (strcmp((*argv) + 2, "verbose") == 0) {
    125         args->verbose = TRUE;
    126         break;
    127       }
    128       else if (strcmp((*argv) + 2, "copyright") == 0) {
    129         mrb_show_copyright(mrb);
    130         exit(EXIT_SUCCESS);
    131       }
    132     default:
     193    }
     194    else if (strcmp(opt, "version") == 0) {
     195      mrb_show_version(mrb);
     196      exit(EXIT_SUCCESS);
     197    }
     198    else if (strcmp(opt, "verbose") == 0) {
     199      args->verbose = TRUE;
     200    }
     201    else if (strcmp(opt, "copyright") == 0) {
     202      mrb_show_copyright(mrb);
     203      exit(EXIT_SUCCESS);
     204    }
     205    else {
     206      fprintf(stderr, "%s: invalid option %s%s (-h will show valid options)\n",
     207              opts->program, opt[1] ? "--" : "-", opt);
    133208      return EXIT_FAILURE;
    134209    }
    135210  }
    136211
    137   if (args->rfp == NULL && args->cmdline == NULL) {
    138     if (*argv == NULL) args->rfp = stdin;
    139     else {
    140       args->rfp = fopen(argv[0], args->mrbfile ? "rb" : "r");
     212  argc = opts->argc; argv = opts->argv;
     213  if (args->cmdline == NULL) {
     214    if (*argv == NULL) {
     215      if (args->version) exit(EXIT_SUCCESS);
     216      args->rfp = stdin;
     217    }
     218    else {
     219      args->rfp = strcmp(argv[0], "-") == 0 ?
     220        stdin : fopen(argv[0], args->mrbfile ? "rb" : "r");
    141221      if (args->rfp == NULL) {
    142         printf("%s: Cannot open program file. (%s)\n", *origargv, *argv);
     222        fprintf(stderr, "%s: Cannot open program file: %s\n", opts->program, argv[0]);
    143223        return EXIT_FAILURE;
    144224      }
     
    163243    mrb_free(mrb, args->cmdline);
    164244  mrb_free(mrb, args->argv);
     245  if (args->libc) {
     246    while (args->libc--) {
     247      mrb_free(mrb, args->libv[args->libc]);
     248    }
     249    mrb_free(mrb, args->libv);
     250  }
    165251  mrb_close(mrb);
    166252}
     
    179265
    180266  if (mrb == NULL) {
    181     fputs("Invalid mrb_state, exiting mruby\n", stderr);
     267    fprintf(stderr, "%s: Invalid mrb_state, exiting mruby\n", *argv);
    182268    return EXIT_FAILURE;
    183269  }
     
    186272  if (n == EXIT_FAILURE || (args.cmdline == NULL && args.rfp == NULL)) {
    187273    cleanup(mrb, &args);
    188     usage(argv[0]);
    189274    return n;
    190275  }
     
    200285    }
    201286    mrb_define_global_const(mrb, "ARGV", ARGV);
     287    mrb_gv_set(mrb, mrb_intern_lit(mrb, "$DEBUG"), mrb_bool_value(args.debug));
    202288
    203289    c = mrbc_context_new(mrb);
     
    220306    }
    221307
     308    /* Load libraries */
     309    for (i = 0; i < args.libc; i++) {
     310      FILE *lfp = fopen(args.libv[i], args.mrbfile ? "rb" : "r");
     311      if (lfp == NULL) {
     312        fprintf(stderr, "%s: Cannot open library file: %s\n", *argv, args.libv[i]);
     313        mrbc_context_free(mrb, c);
     314        cleanup(mrb, &args);
     315        return EXIT_FAILURE;
     316      }
     317      if (args.mrbfile) {
     318        v = mrb_load_irep_file_cxt(mrb, lfp, c);
     319      }
     320      else {
     321        v = mrb_load_file_cxt(mrb, lfp, c);
     322      }
     323      fclose(lfp);
     324    }
     325
    222326    /* Load program */
    223327    if (args.mrbfile) {
     
    237341    mrbc_context_free(mrb, c);
    238342    if (mrb->exc) {
    239       if (mrb_undef_p(v)) {
    240         mrb_p(mrb, mrb_obj_value(mrb->exc));
    241       }
    242       else {
     343      if (!mrb_undef_p(v)) {
    243344        mrb_print_error(mrb);
    244345      }
    245       n = -1;
     346      n = EXIT_FAILURE;
    246347    }
    247348    else if (args.check_syntax) {
    248       printf("Syntax OK\n");
     349      puts("Syntax OK");
    249350    }
    250351  }
    251352  cleanup(mrb, &args);
    252353
    253   return n == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
    254 }
     354  return n;
     355}
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-strip/bintest/mruby-strip.rb

    r321 r439  
    6868  `#{cmd('mruby-strip')} -l #{without_lv.path}`
    6969  assert_true without_lv.size < with_lv.size
    70 
    71   assert_equal '[:a, :b]', `#{cmd('mruby')} -b #{with_lv.path}`.chomp
    72   assert_equal '[]', `#{cmd('mruby')} -b #{without_lv.path}`.chomp
     70#
     71#  assert_equal '[:a, :b]', `#{cmd('mruby')} -b #{with_lv.path}`.chomp
     72#  assert_equal '[]', `#{cmd('mruby')} -b #{without_lv.path}`.chomp
    7373end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-bin-strip/tools/mruby-strip/mruby-strip.c

    r331 r439  
    1 #include <stdio.h>
     1#include <mruby.h>
     2
     3#ifdef MRB_DISABLE_STDIO
     4# error mruby-bin-strip conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
     5#endif
     6
    27#include <stdlib.h>
    38#include <string.h>
    4 #include <mruby.h>
    59#include <mruby/irep.h>
    610#include <mruby/dump.h>
     
    1216  mrb_bool lvar;
    1317};
    14 
    15 
    16 static void
    17 irep_remove_lv(mrb_state *mrb, mrb_irep *irep)
    18 {
    19   size_t i;
    20 
    21   if (irep->lv) {
    22     mrb_free(mrb, irep->lv);
    23     irep->lv = NULL;
    24   }
    25 
    26   for (i = 0; i < irep->rlen; ++i) {
    27     irep_remove_lv(mrb, irep->reps[i]);
    28   }
    29 }
    3018
    3119static void
     
    10088    /* clear lv if --lvar is enabled */
    10189    if (args->lvar) {
    102       irep_remove_lv(mrb, irep);
     90      mrb_irep_remove_lv(mrb, irep);
    10391    }
    10492
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-class-ext/src/class.c

    r331 r439  
    66mrb_mod_name(mrb_state *mrb, mrb_value self)
    77{
    8   mrb_value name = mrb_class_path(mrb, mrb_class_ptr(self));
    9   return mrb_nil_p(name)? name : mrb_str_dup(mrb, name);
     8  mrb_value name =  mrb_class_path(mrb, mrb_class_ptr(self));
     9  if (mrb_string_p(name)) {
     10    MRB_SET_FROZEN_FLAG(mrb_basic_ptr(name));
     11  }
     12  return name;
     13}
     14
     15static mrb_value
     16mrb_mod_singleton_class_p(mrb_state *mrb, mrb_value self)
     17{
     18  return mrb_bool_value(mrb_sclass_p(self));
     19}
     20
     21/*
     22 *  call-seq:
     23 *     module_exec(arg...) {|var...| block } -> obj
     24 *     class_exec(arg...) {|var...| block } -> obj
     25 *
     26 * Evaluates the given block in the context of the
     27 * class/module. The method defined in the block will belong
     28 * to the receiver. Any arguments passed to the method will be
     29 * passed to the block. This can be used if the block needs to
     30 * access instance variables.
     31 *
     32 *     class Thing
     33 *     end
     34 *     Thing.class_exec{
     35 *       def hello() "Hello there!" end
     36 *     }
     37 *     puts Thing.new.hello()
     38 */
     39
     40static mrb_value
     41mrb_mod_module_exec(mrb_state *mrb, mrb_value self)
     42{
     43  const mrb_value *argv;
     44  mrb_int argc;
     45  mrb_value blk;
     46
     47  mrb_get_args(mrb, "*&!", &argv, &argc, &blk);
     48
     49  mrb->c->ci->target_class = mrb_class_ptr(self);
     50  return mrb_yield_cont(mrb, blk, self, argc, argv);
    1051}
    1152
     
    1657
    1758  mrb_define_method(mrb, mod, "name", mrb_mod_name, MRB_ARGS_NONE());
     59  mrb_define_method(mrb, mod, "singleton_class?", mrb_mod_singleton_class_p, MRB_ARGS_NONE());
     60  mrb_define_method(mrb, mod, "module_exec", mrb_mod_module_exec, MRB_ARGS_ANY()|MRB_ARGS_BLOCK());
     61  mrb_define_method(mrb, mod, "class_exec", mrb_mod_module_exec, MRB_ARGS_ANY()|MRB_ARGS_BLOCK());
    1862}
    1963
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-class-ext/test/module.rb

    r331 r439  
     1assert 'Module#<' do
     2  a = Class.new
     3  b = Class.new(a)
     4  c = Class.new(a)
     5  d = Module.new
     6  e = Class.new { include d }
     7  f = Module.new { include d }
     8
     9  # compare class to class
     10  assert_true b < a
     11  assert_false b < b
     12  assert_false a < b
     13  assert_nil c < b
     14
     15  # compare class to module
     16  assert_true e < d
     17  assert_false d < e
     18  assert_nil a < d
     19
     20  # compare module to module
     21  assert_true f < d
     22  assert_false f < f
     23  assert_false d < f
     24
     25  assert_raise(TypeError) { a < Object.new }
     26end
     27
     28assert 'Module#<=' do
     29  a = Class.new
     30  b = Class.new(a)
     31  c = Class.new(a)
     32  d = Module.new
     33  e = Class.new { include d }
     34  f = Module.new { include d }
     35
     36  # compare class to class
     37  assert_true b <= a
     38  assert_true b <= b
     39  assert_false a <= b
     40  assert_nil c <= b
     41
     42  # compare class to module
     43  assert_true e <= d
     44  assert_false d <= e
     45  assert_nil a <= d
     46
     47  # compare module to module
     48  assert_true f <= d
     49  assert_true f <= f
     50  assert_false d <= f
     51
     52  assert_raise(TypeError) { a <= Object.new }
     53end
     54
    155assert 'Module#name' do
    2   module A
    3     class B
     56  module Outer
     57    class Inner; end
     58    const_set :SetInner, Class.new
     59  end
     60
     61  assert_equal 'Outer', Outer.name
     62  assert_equal 'Outer::Inner', Outer::Inner.name
     63  assert_equal 'Outer::SetInner', Outer::SetInner.name
     64
     65  outer = Module.new do
     66    const_set :SetInner, Class.new
     67  end
     68  Object.const_set :SetOuter, outer
     69
     70  assert_equal 'SetOuter', SetOuter.name
     71  assert_equal 'SetOuter::SetInner', SetOuter::SetInner.name
     72
     73  mod = Module.new
     74  cls = Class.new
     75
     76  assert_nil mod.name
     77  assert_nil cls.name
     78end
     79
     80assert 'Module#singleton_class?' do
     81  mod = Module.new
     82  cls = Class.new
     83  scl = (class <<cls; self; end)
     84
     85  assert_false mod.singleton_class?
     86  assert_false cls.singleton_class?
     87  assert_true scl.singleton_class?
     88end
     89
     90assert 'Module#module_eval' do
     91  mod = Module.new
     92  mod.class_exec(1,2,3) do |a,b,c|
     93    assert_equal([1,2,3], [a,b,c])
     94    def hi
     95      "hi"
    496    end
    597  end
    6 
    7   assert_nil A::B.singleton_class.name
    8   assert_equal 'Fixnum', Fixnum.name
    9   assert_equal 'A::B', A::B.name
     98  cls = Class.new
     99  cls.class_exec(42) do |x|
     100    assert_equal(42, x)
     101    include mod
     102    def hello
     103      "hello"
     104    end
     105  end
     106  obj = cls.new
     107  assert_equal("hi", obj.hi)
     108  assert_equal("hello", obj.hello)
    10109end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-compiler/core/codegen.c

    r331 r439  
    99#include <stdlib.h>
    1010#include <string.h>
     11#include <math.h>
    1112#include <mruby.h>
    1213#include <mruby/compile.h>
     
    2425#endif
    2526
     27#define MAXARG_S (1<<16)
     28
    2629typedef mrb_ast_node node;
    2730typedef struct mrb_parser_state parser_state;
     
    3740struct loopinfo {
    3841  enum looptype type;
    39   int pc1, pc2, pc3, acc;
     42  int pc0, pc1, pc2, pc3, acc;
    4043  int ensure_level;
    4144  struct loopinfo *prev;
     
    5154  node *lv;
    5255
    53   int sp;
    54   int pc;
    55   int lastlabel;
     56  uint16_t sp;
     57  uint16_t pc;
     58  uint16_t lastpc;
     59  uint16_t lastlabel;
    5660  int ainfo:15;
    5761  mrb_bool mscope:1;
     
    5963  struct loopinfo *loop;
    6064  int ensure_level;
    61   char const *filename;
     65  mrb_sym filename_sym;
    6266  uint16_t lineno;
    6367
    6468  mrb_code *iseq;
    6569  uint16_t *lines;
    66   int icapa;
     70  uint32_t icapa;
    6771
    6872  mrb_irep *irep;
    69   size_t pcapa;
    70   size_t scapa;
    71   size_t rcapa;
     73  uint32_t pcapa, scapa, rcapa;
    7274
    7375  uint16_t nlocals;
     
    101103    codegen_scope *tmp = s->prev;
    102104    mrb_free(s->mrb, s->iseq);
     105    mrb_free(s->mrb, s->lines);
    103106    mrb_pool_close(s->mpool);
    104107    s = tmp;
    105108  }
    106109#ifndef MRB_DISABLE_STDIO
    107   if (s->filename && s->lineno) {
    108     fprintf(stderr, "codegen error:%s:%d: %s\n", s->filename, s->lineno, message);
     110  if (s->filename_sym && s->lineno) {
     111    const char *filename = mrb_sym_name_len(s->mrb, s->filename_sym, NULL);
     112    fprintf(stderr, "codegen error:%s:%d: %s\n", filename, s->lineno, message);
    109113  }
    110114  else {
     
    125129
    126130static void*
    127 codegen_malloc(codegen_scope *s, size_t len)
    128 {
    129   void *p = mrb_malloc_simple(s->mrb, len);
    130 
    131   if (!p) codegen_error(s, "mrb_malloc");
    132   return p;
    133 }
    134 
    135 static void*
    136131codegen_realloc(codegen_scope *s, void *p, size_t len)
    137132{
     
    145140new_label(codegen_scope *s)
    146141{
    147   s->lastlabel = s->pc;
    148   return s->pc;
    149 }
    150 
    151 static inline int
    152 genop(codegen_scope *s, mrb_code i)
    153 {
    154   if (s->pc == s->icapa) {
     142  return s->lastlabel = s->pc;
     143}
     144
     145static void
     146emit_B(codegen_scope *s, uint32_t pc, uint8_t i)
     147{
     148  if (pc >= MAXARG_S || s->icapa >= MAXARG_S) {
     149    codegen_error(s, "too big code block");
     150  }
     151  if (pc >= s->icapa) {
    155152    s->icapa *= 2;
     153    if (s->icapa > MAXARG_S) {
     154      s->icapa = MAXARG_S;
     155    }
    156156    s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa);
    157157    if (s->lines) {
    158       s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(short)*s->icapa);
    159       s->irep->lines = s->lines;
    160     }
    161   }
    162   s->iseq[s->pc] = i;
     158      s->lines = (uint16_t*)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->icapa);
     159    }
     160  }
    163161  if (s->lines) {
    164     s->lines[s->pc] = s->lineno;
    165   }
    166   return s->pc++;
     162    if (s->lineno > 0 || pc == 0)
     163      s->lines[pc] = s->lineno;
     164    else
     165      s->lines[pc] = s->lines[pc-1];
     166  }
     167  s->iseq[pc] = i;
     168}
     169
     170static void
     171emit_S(codegen_scope *s, int pc, uint16_t i)
     172{
     173  uint8_t hi = i>>8;
     174  uint8_t lo = i&0xff;
     175
     176  emit_B(s, pc,   hi);
     177  emit_B(s, pc+1, lo);
     178}
     179
     180static void
     181gen_B(codegen_scope *s, uint8_t i)
     182{
     183  emit_B(s, s->pc, i);
     184  s->pc++;
     185}
     186
     187static void
     188gen_S(codegen_scope *s, uint16_t i)
     189{
     190  emit_S(s, s->pc, i);
     191  s->pc += 2;
     192}
     193
     194static void
     195genop_0(codegen_scope *s, mrb_code i)
     196{
     197  s->lastpc = s->pc;
     198  gen_B(s, i);
     199}
     200
     201static void
     202genop_1(codegen_scope *s, mrb_code i, uint16_t a)
     203{
     204  s->lastpc = s->pc;
     205  if (a > 0xff) {
     206    gen_B(s, OP_EXT1);
     207    gen_B(s, i);
     208    gen_S(s, a);
     209  }
     210  else {
     211    gen_B(s, i);
     212    gen_B(s, (uint8_t)a);
     213  }
     214}
     215
     216static void
     217genop_2(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b)
     218{
     219  s->lastpc = s->pc;
     220  if (a > 0xff && b > 0xff) {
     221    gen_B(s, OP_EXT3);
     222    gen_B(s, i);
     223    gen_S(s, a);
     224    gen_S(s, b);
     225  }
     226  else if (b > 0xff) {
     227    gen_B(s, OP_EXT2);
     228    gen_B(s, i);
     229    gen_B(s, (uint8_t)a);
     230    gen_S(s, b);
     231  }
     232  else if (a > 0xff) {
     233    gen_B(s, OP_EXT1);
     234    gen_B(s, i);
     235    gen_S(s, a);
     236    gen_B(s, (uint8_t)b);
     237  }
     238  else {
     239    gen_B(s, i);
     240    gen_B(s, (uint8_t)a);
     241    gen_B(s, (uint8_t)b);
     242  }
     243}
     244
     245static void
     246genop_3(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b, uint8_t c)
     247{
     248  genop_2(s, i, a, b);
     249  gen_B(s, c);
     250}
     251
     252static void
     253genop_2S(codegen_scope *s, mrb_code i, uint16_t a, uint16_t b)
     254{
     255  genop_1(s, i, a);
     256  gen_S(s, b);
     257}
     258
     259static void
     260genop_W(codegen_scope *s, mrb_code i, uint32_t a)
     261{
     262  uint8_t a1 = (a>>16) & 0xff;
     263  uint8_t a2 = (a>>8) & 0xff;
     264  uint8_t a3 = a & 0xff;
     265
     266  s->lastpc = s->pc;
     267  gen_B(s, i);
     268  gen_B(s, a1);
     269  gen_B(s, a2);
     270  gen_B(s, a3);
    167271}
    168272
     
    178282}
    179283
    180 static int
    181 genop_peep(codegen_scope *s, mrb_code i, int val)
    182 {
    183   /* peephole optimization */
    184   if (!no_optimize(s) && s->lastlabel != s->pc && s->pc > 0) {
    185     mrb_code i0 = s->iseq[s->pc-1];
    186     int c1 = GET_OPCODE(i);
    187     int c0 = GET_OPCODE(i0);
    188 
    189     switch (c1) {
     284static
     285mrb_bool
     286on_eval(codegen_scope *s)
     287{
     288  if (s && s->parser && s->parser->on_eval)
     289    return TRUE;
     290  return FALSE;
     291}
     292
     293struct mrb_insn_data
     294mrb_decode_insn(const mrb_code *pc)
     295{
     296  struct mrb_insn_data data = { 0 };
     297  mrb_code insn = READ_B();
     298  uint16_t a = 0;
     299  uint16_t b = 0;
     300  uint8_t  c = 0;
     301
     302  switch (insn) {
     303#define FETCH_Z() /* empty */
     304#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x (); break;
     305#include "mruby/ops.h"
     306#undef OPCODE
     307  }
     308  switch (insn) {
     309  case OP_EXT1:
     310    insn = READ_B();
     311    switch (insn) {
     312#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); break;
     313#include "mruby/ops.h"
     314#undef OPCODE
     315    }
     316    break;
     317  case OP_EXT2:
     318    insn = READ_B();
     319    switch (insn) {
     320#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); break;
     321#include "mruby/ops.h"
     322#undef OPCODE
     323    }
     324    break;
     325  case OP_EXT3:
     326    insn = READ_B();
     327    switch (insn) {
     328#define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); break;
     329#include "mruby/ops.h"
     330#undef OPCODE
     331    }
     332    break;
     333  default:
     334    break;
     335  }
     336  data.insn = insn;
     337  data.a = a;
     338  data.b = b;
     339  data.c = c;
     340  return data;
     341}
     342
     343static struct mrb_insn_data
     344mrb_last_insn(codegen_scope *s)
     345{
     346  if (s->pc == s->lastpc) {
     347    struct mrb_insn_data data;
     348
     349    data.insn = OP_NOP;
     350    return data;
     351  }
     352  return mrb_decode_insn(&s->iseq[s->lastpc]);
     353}
     354
     355static mrb_bool
     356no_peephole(codegen_scope *s)
     357{
     358  return no_optimize(s) || s->lastlabel == s->pc || s->pc == 0 || s->pc == s->lastpc;
     359}
     360
     361static uint16_t
     362genjmp(codegen_scope *s, mrb_code i, uint16_t pc)
     363{
     364  uint16_t pos;
     365
     366  s->lastpc = s->pc;
     367  gen_B(s, i);
     368  pos = s->pc;
     369  gen_S(s, pc);
     370  return pos;
     371}
     372
     373static uint16_t
     374genjmp2(codegen_scope *s, mrb_code i, uint16_t a, int pc, int val)
     375{
     376  uint16_t pos;
     377
     378  if (!no_peephole(s) && !val) {
     379    struct mrb_insn_data data = mrb_last_insn(s);
     380
     381    if (data.insn == OP_MOVE && data.a == a) {
     382      s->pc = s->lastpc;
     383      a = data.b;
     384    }
     385  }
     386
     387  s->lastpc = s->pc;
     388  if (a > 0xff) {
     389    gen_B(s, OP_EXT1);
     390    gen_B(s, i);
     391    gen_S(s, a);
     392    pos = s->pc;
     393    gen_S(s, pc);
     394  }
     395  else {
     396    gen_B(s, i);
     397    gen_B(s, (uint8_t)a);
     398    pos = s->pc;
     399    gen_S(s, pc);
     400  }
     401  return pos;
     402}
     403
     404static void
     405gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep)
     406{
     407  if (no_peephole(s)) {
     408  normal:
     409    genop_2(s, OP_MOVE, dst, src);
     410    if (on_eval(s)) {
     411      genop_0(s, OP_NOP);
     412    }
     413    return;
     414  }
     415  else {
     416    struct mrb_insn_data data = mrb_last_insn(s);
     417
     418    switch (data.insn) {
    190419    case OP_MOVE:
    191       if (GETARG_A(i) == GETARG_B(i)) {
    192         /* skip useless OP_MOVE */
    193         return 0;
    194       }
    195       if (val) break;
    196       switch (c0) {
    197       case OP_MOVE:
    198         if (GETARG_A(i) == GETARG_A(i0)) {
    199           /* skip overriden OP_MOVE */
    200           s->pc--;
    201           s->iseq[s->pc] = i;
    202         }
    203         if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i) == GETARG_B(i0)) {
    204           /* skip swapping OP_MOVE */
    205           return 0;
    206         }
    207         if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
    208           s->pc--;
    209           return genop_peep(s, MKOP_AB(OP_MOVE, GETARG_A(i), GETARG_B(i0)), val);
    210         }
    211         break;
    212       case OP_LOADI:
    213         if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
    214           s->iseq[s->pc-1] = MKOP_AsBx(OP_LOADI, GETARG_A(i), GETARG_sBx(i0));
    215           return 0;
    216         }
    217         break;
    218       case OP_ARRAY:
    219       case OP_HASH:
    220       case OP_RANGE:
    221       case OP_AREF:
    222       case OP_GETUPVAR:
    223         if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
    224           s->iseq[s->pc-1] = MKOP_ABC(c0, GETARG_A(i), GETARG_B(i0), GETARG_C(i0));
    225           return 0;
    226         }
    227         break;
    228       case OP_LOADSYM:
    229       case OP_GETGLOBAL:
    230       case OP_GETIV:
    231       case OP_GETCV:
    232       case OP_GETCONST:
    233       case OP_GETSPECIAL:
    234       case OP_LOADL:
    235       case OP_STRING:
    236         if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
    237           s->iseq[s->pc-1] = MKOP_ABx(c0, GETARG_A(i), GETARG_Bx(i0));
    238           return 0;
    239         }
    240         break;
    241       case OP_SCLASS:
    242         if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
    243           s->iseq[s->pc-1] = MKOP_AB(c0, GETARG_A(i), GETARG_B(i0));
    244           return 0;
    245         }
    246         break;
    247       case OP_LOADNIL:
    248       case OP_LOADSELF:
    249       case OP_LOADT:
    250       case OP_LOADF:
    251       case OP_OCLASS:
    252         if (GETARG_B(i) == GETARG_A(i0) && GETARG_A(i0) >= s->nlocals) {
    253           s->iseq[s->pc-1] = MKOP_A(c0, GETARG_A(i));
    254           return 0;
    255         }
    256         break;
    257       default:
    258         break;
    259       }
     420      if (dst == src) return;             /* remove useless MOVE */
     421      if (data.b == dst && data.a == src) /* skip swapping MOVE */
     422        return;
     423      goto normal;
     424    case OP_LOADNIL: case OP_LOADSELF: case OP_LOADT: case OP_LOADF:
     425    case OP_LOADI__1:
     426    case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3:
     427    case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7:
     428      if (nopeep || data.a != src || data.a < s->nlocals) goto normal;
     429      s->pc = s->lastpc;
     430      genop_1(s, data.insn, dst);
    260431      break;
    261     case OP_SETIV:
    262     case OP_SETCV:
    263     case OP_SETCONST:
    264     case OP_SETMCNST:
    265     case OP_SETGLOBAL:
    266       if (val) break;
    267       if (c0 == OP_MOVE) {
    268         if (GETARG_A(i) == GETARG_A(i0)) {
    269           s->iseq[s->pc-1] = MKOP_ABx(c1, GETARG_B(i0), GETARG_Bx(i));
    270           return 0;
    271         }
    272       }
    273       break;
    274     case OP_SETUPVAR:
    275       if (val) break;
    276       if (c0 == OP_MOVE) {
    277         if (GETARG_A(i) == GETARG_A(i0)) {
    278           s->iseq[s->pc-1] = MKOP_ABC(c1, GETARG_B(i0), GETARG_B(i), GETARG_C(i));
    279           return 0;
    280         }
    281       }
    282       break;
    283     case OP_EPOP:
    284       if (c0 == OP_EPOP) {
    285         s->iseq[s->pc-1] = MKOP_A(OP_EPOP, GETARG_A(i0)+GETARG_A(i));
    286         return 0;
    287       }
    288       break;
    289     case OP_POPERR:
    290       if (c0 == OP_POPERR) {
    291         s->iseq[s->pc-1] = MKOP_A(OP_POPERR, GETARG_A(i0)+GETARG_A(i));
    292         return 0;
    293       }
    294       break;
    295     case OP_RETURN:
    296       switch (c0) {
    297       case OP_RETURN:
    298         return 0;
    299       case OP_MOVE:
    300         if (GETARG_A(i0) >= s->nlocals) {
    301           s->iseq[s->pc-1] = MKOP_AB(OP_RETURN, GETARG_B(i0), OP_R_NORMAL);
    302           return 0;
    303         }
    304         break;
    305       case OP_SETIV:
    306       case OP_SETCV:
    307       case OP_SETCONST:
    308       case OP_SETMCNST:
    309       case OP_SETUPVAR:
    310       case OP_SETGLOBAL:
    311         s->pc--;
    312         genop_peep(s, i0, NOVAL);
    313         i0 = s->iseq[s->pc-1];
    314         return genop(s, MKOP_AB(OP_RETURN, GETARG_A(i0), OP_R_NORMAL));
    315 #if 0
    316       case OP_SEND:
    317         if (GETARG_B(i) == OP_R_NORMAL && GETARG_A(i) == GETARG_A(i0)) {
    318           s->iseq[s->pc-1] = MKOP_ABC(OP_TAILCALL, GETARG_A(i0), GETARG_B(i0), GETARG_C(i0));
    319           return;
    320         }
    321         break;
    322 #endif
    323       default:
    324         break;
    325       }
    326       break;
    327     case OP_ADD:
    328     case OP_SUB:
    329       if (c0 == OP_LOADI) {
    330         int c = GETARG_sBx(i0);
    331 
    332         if (c1 == OP_SUB) c = -c;
    333         if (c > 127 || c < -127) break;
    334         if (0 <= c)
    335           s->iseq[s->pc-1] = MKOP_ABC(OP_ADDI, GETARG_A(i), GETARG_B(i), c);
    336         else
    337           s->iseq[s->pc-1] = MKOP_ABC(OP_SUBI, GETARG_A(i), GETARG_B(i), -c);
    338         return 0;
    339       }
    340     case OP_STRCAT:
    341       if (c0 == OP_STRING) {
    342         mrb_value v = s->irep->pool[GETARG_Bx(i0)];
    343 
    344         if (mrb_string_p(v) && RSTRING_LEN(v) == 0) {
    345           s->pc--;
    346           return 0;
    347         }
    348       }
    349       if (c0 == OP_LOADNIL) {
    350         if (GETARG_B(i) == GETARG_A(i0)) {
    351           s->pc--;
    352           return 0;
    353         }
    354       }
    355       break;
    356     case OP_JMPIF:
    357     case OP_JMPNOT:
    358       if (c0 == OP_MOVE && GETARG_A(i) == GETARG_A(i0)) {
    359         s->iseq[s->pc-1] = MKOP_AsBx(c1, GETARG_B(i0), GETARG_sBx(i));
    360         return s->pc-1;
    361       }
     432    case OP_LOADI: case OP_LOADINEG: case OP_LOADL: case OP_LOADSYM:
     433    case OP_GETGV: case OP_GETSV: case OP_GETIV: case OP_GETCV:
     434    case OP_GETCONST: case OP_STRING:
     435    case OP_LAMBDA: case OP_BLOCK: case OP_METHOD: case OP_BLKPUSH:
     436      if (nopeep || data.a != src || data.a < s->nlocals) goto normal;
     437      s->pc = s->lastpc;
     438      genop_2(s, data.insn, dst, data.b);
    362439      break;
    363440    default:
     441      goto normal;
     442    }
     443  }
     444}
     445
     446static void
     447gen_return(codegen_scope *s, uint8_t op, uint16_t src)
     448{
     449  if (no_peephole(s)) {
     450    genop_1(s, op, src);
     451  }
     452  else {
     453    struct mrb_insn_data data = mrb_last_insn(s);
     454
     455    if (data.insn == OP_MOVE && src == data.a) {
     456      s->pc = s->lastpc;
     457      genop_1(s, op, data.b);
     458    }
     459    else if (data.insn != OP_RETURN) {
     460      genop_1(s, op, src);
     461    }
     462  }
     463}
     464
     465static void
     466gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst)
     467{
     468  if (no_peephole(s)) {
     469  normal:
     470    genop_1(s, op, dst);
     471    return;
     472  }
     473  else {
     474    struct mrb_insn_data data = mrb_last_insn(s);
     475
     476    switch (data.insn) {
     477    case OP_LOADI__1:
     478      if (op == OP_ADD) op = OP_SUB;
     479      else op = OP_ADD;
     480      data.b = 1;
     481      goto replace;
     482    case OP_LOADI_0: case OP_LOADI_1: case OP_LOADI_2: case OP_LOADI_3:
     483    case OP_LOADI_4: case OP_LOADI_5: case OP_LOADI_6: case OP_LOADI_7:
     484      data.b = data.insn - OP_LOADI_0;
     485      /* fall through */
     486    case OP_LOADI:
     487    replace:
     488      if (data.b >= 128) goto normal;
     489      s->pc = s->lastpc;
     490      if (op == OP_ADD) {
     491        genop_2(s, OP_ADDI, dst, (uint8_t)data.b);
     492      }
     493      else {
     494        genop_2(s, OP_SUBI, dst, (uint8_t)data.b);
     495      }
    364496      break;
    365     }
    366   }
    367   return genop(s, i);
     497    default:
     498      goto normal;
     499    }
     500  }
     501}
     502
     503static int
     504dispatch(codegen_scope *s, uint16_t pos0)
     505{
     506  uint16_t newpos;
     507
     508  s->lastlabel = s->pc;
     509  newpos = PEEK_S(s->iseq+pos0);
     510  emit_S(s, pos0, s->pc);
     511  return newpos;
    368512}
    369513
    370514static void
    371 scope_error(codegen_scope *s)
    372 {
    373   exit(EXIT_FAILURE);
    374 }
    375 
    376 static inline void
    377 dispatch(codegen_scope *s, int pc)
    378 {
    379   int diff = s->pc - pc;
    380   mrb_code i = s->iseq[pc];
    381   int c = GET_OPCODE(i);
    382 
    383   s->lastlabel = s->pc;
    384   switch (c) {
    385   case OP_JMP:
    386   case OP_JMPIF:
    387   case OP_JMPNOT:
    388   case OP_ONERR:
    389     break;
    390   default:
    391 #ifndef MRB_DISABLE_STDIO
    392     fprintf(stderr, "bug: dispatch on non JMP op\n");
    393 #endif
    394     scope_error(s);
    395     break;
    396   }
    397   if (diff > MAXARG_sBx) {
    398     codegen_error(s, "too distant jump address");
    399   }
    400   s->iseq[pc] = MKOP_AsBx(c, GETARG_A(i), diff);
    401 }
    402 
    403 static void
    404 dispatch_linked(codegen_scope *s, int pc)
    405 {
    406   mrb_code i;
    407   int pos;
    408 
    409   if (!pc) return;
     515dispatch_linked(codegen_scope *s, uint16_t pos)
     516{
     517  if (pos==0) return;
    410518  for (;;) {
    411     i = s->iseq[pc];
    412     pos = GETARG_sBx(i);
    413     dispatch(s, pc);
    414     if (!pos) break;
    415     pc = pos;
     519    pos = dispatch(s, pos);
     520    if (pos==0) break;
    416521  }
    417522}
     
    419524#define nregs_update do {if (s->sp > s->nregs) s->nregs = s->sp;} while (0)
    420525static void
    421 push_(codegen_scope *s)
    422 {
    423   if (s->sp > 511) {
    424     codegen_error(s, "too complex expression");
    425   }
    426   s->sp++;
    427   nregs_update;
    428 }
    429 
    430 static void
    431 push_n_(codegen_scope *s, size_t n)
    432 {
    433   if (s->sp+n > 511) {
     526push_n_(codegen_scope *s, int n)
     527{
     528  if (s->sp+n >= 0xffff) {
    434529    codegen_error(s, "too complex expression");
    435530  }
     
    438533}
    439534
    440 #define push() push_(s)
     535static void
     536pop_n_(codegen_scope *s, int n)
     537{
     538  if ((int)s->sp-n < 0) {
     539    codegen_error(s, "stack pointer underflow");
     540  }
     541  s->sp-=n;
     542}
     543
     544#define push() push_n_(s,1)
    441545#define push_n(n) push_n_(s,n)
    442 #define pop_(s) ((s)->sp--)
    443 #define pop() pop_(s)
    444 #define pop_n(n) (s->sp-=(n))
     546#define pop() pop_n_(s,1)
     547#define pop_n(n) pop_n_(s,n)
    445548#define cursp() (s->sp)
    446549
     
    448551new_lit(codegen_scope *s, mrb_value val)
    449552{
    450   size_t i;
     553  int i;
    451554  mrb_value *pv;
    452555
     
    457560      pv = &s->irep->pool[i];
    458561
    459       if (mrb_type(*pv) != MRB_TT_STRING) continue;
     562      if (!mrb_string_p(*pv)) continue;
    460563      if ((len = RSTRING_LEN(*pv)) != RSTRING_LEN(val)) continue;
    461564      if (memcmp(RSTRING_PTR(*pv), RSTRING_PTR(val), len) == 0)
     
    463566    }
    464567    break;
     568#ifndef MRB_WITHOUT_FLOAT
    465569  case MRB_TT_FLOAT:
    466570    for (i=0; i<s->irep->plen; i++) {
     571      mrb_float f1, f2;
    467572      pv = &s->irep->pool[i];
    468       if (mrb_type(*pv) != MRB_TT_FLOAT) continue;
    469       if (mrb_float(*pv) == mrb_float(val)) return i;
    470     }
    471     break;
     573      if (!mrb_float_p(*pv)) continue;
     574      f1 = mrb_float(*pv);
     575      f2 = mrb_float(val);
     576      if (f1 == f2 && !signbit(f1) == !signbit(f2)) return i;
     577    }
     578    break;
     579#endif
    472580  case MRB_TT_FIXNUM:
    473581    for (i=0; i<s->irep->plen; i++) {
     
    492600  switch (mrb_type(val)) {
    493601  case MRB_TT_STRING:
    494     *pv = mrb_str_pool(s->mrb, val);
    495     break;
    496 
     602    *pv = mrb_str_pool(s->mrb, RSTRING_PTR(val), RSTRING_LEN(val), RSTR_NOFREE_P(RSTRING(val)));
     603    break;
     604
     605#ifndef MRB_WITHOUT_FLOAT
    497606  case MRB_TT_FLOAT:
    498607#ifdef MRB_WORD_BOXING
     
    500609    break;
    501610#endif
     611#endif
    502612  case MRB_TT_FIXNUM:
    503613    *pv = val;
     
    511621}
    512622
    513 /* method symbols should be fit in 9 bits */
    514 #define MAXMSYMLEN 512
    515623/* maximum symbol numbers */
    516 #define MAXSYMLEN 65536
     624#define MAXSYMLEN 0x10000
    517625
    518626static int
    519 new_msym(codegen_scope *s, mrb_sym sym)
    520 {
    521   size_t i, len;
     627new_sym(codegen_scope *s, mrb_sym sym)
     628{
     629  int i, len;
    522630
    523631  mrb_assert(s->irep);
    524632
    525633  len = s->irep->slen;
    526   if (len > MAXMSYMLEN) len = MAXMSYMLEN;
    527634  for (i=0; i<len; i++) {
    528635    if (s->irep->syms[i] == sym) return i;
    529     if (s->irep->syms[i] == 0) break;
    530   }
    531   if (i == MAXMSYMLEN) {
    532     codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXMSYMLEN) ")");
    533   }
    534   s->irep->syms[i] = sym;
    535   if (i == s->irep->slen) s->irep->slen++;
    536   return i;
    537 }
    538 
    539 static int
    540 new_sym(codegen_scope *s, mrb_sym sym)
    541 {
    542   size_t i;
    543 
    544   for (i=0; i<s->irep->slen; i++) {
    545     if (s->irep->syms[i] == sym) return i;
    546   }
    547   if (s->irep->slen == MAXSYMLEN) {
    548     codegen_error(s, "too many symbols (max " MRB_STRINGIZE(MAXSYMLEN) ")");
    549   }
    550 
    551   if (s->irep->slen > MAXMSYMLEN/2 && s->scapa == MAXMSYMLEN) {
    552     s->scapa = MAXSYMLEN;
    553     s->irep->syms = (mrb_sym *)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*MAXSYMLEN);
    554     for (i = s->irep->slen; i < MAXMSYMLEN; i++) {
    555       static const mrb_sym mrb_sym_zero = { 0 };
    556       s->irep->syms[i] = mrb_sym_zero;
    557     }
    558     s->irep->slen = MAXMSYMLEN;
     636  }
     637  if (s->irep->slen >= s->scapa) {
     638    s->scapa *= 2;
     639    s->irep->syms = (mrb_sym*)codegen_realloc(s, s->irep->syms, sizeof(mrb_sym)*s->scapa);
    559640  }
    560641  s->irep->syms[s->irep->slen] = sym;
     
    574655}
    575656
    576 #define sym(x) ((mrb_sym)(intptr_t)(x))
    577 #define lv_name(lv) sym((lv)->car)
     657#define nint(x) ((int)(intptr_t)(x))
     658#define nchar(x) ((char)(intptr_t)(x))
     659#define nsym(x) ((mrb_sym)(intptr_t)(x))
     660
     661#define lv_name(lv) nsym((lv)->car)
     662
    578663static int
    579664lv_idx(codegen_scope *s, mrb_sym id)
     
    597682  struct loopinfo *lp;
    598683  node *n2;
    599   mrb_code c;
    600684
    601685  /* generate receiver */
     
    603687  /* generate loop-block */
    604688  s = scope_new(s->mrb, s, NULL);
    605   if (s == NULL) {
    606     raise_error(prev, "unexpected scope");
    607   }
    608689
    609690  push();                       /* push for a block parameter */
     
    611692  /* generate loop variable */
    612693  n2 = tree->car;
    613   genop(s, MKOP_Ax(OP_ENTER, 0x40000));
     694  genop_W(s, OP_ENTER, 0x40000);
    614695  if (n2->car && !n2->car->cdr && !n2->cdr) {
    615696    gen_assignment(s, n2->car->car, 1, NOVAL);
     
    625706  codegen(s, tree->cdr->cdr->car, VAL);
    626707  pop();
    627   if (s->pc > 0) {
    628     c = s->iseq[s->pc-1];
    629     if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel)
    630       genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
    631   }
     708  gen_return(s, OP_RETURN, cursp());
    632709  loop_pop(s, NOVAL);
    633710  scope_finish(s);
    634711  s = prev;
    635   genop(s, MKOP_Abc(OP_LAMBDA, cursp(), s->irep->rlen-1, OP_L_BLOCK));
     712  genop_2(s, OP_BLOCK, cursp(), s->irep->rlen-1);
     713  push();pop(); /* space for a block */
    636714  pop();
    637   idx = new_msym(s, mrb_intern_lit(s->mrb, "each"));
    638   genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, 0));
     715  idx = new_sym(s, mrb_intern_lit(s->mrb, "each"));
     716  genop_3(s, OP_SENDB, cursp(), idx, 0);
    639717}
    640718
     
    642720lambda_body(codegen_scope *s, node *tree, int blk)
    643721{
    644   mrb_code c;
    645722  codegen_scope *parent = s;
    646723  s = scope_new(s->mrb, s, tree->car);
    647   if (s == NULL) {
    648     raise_error(parent, "unexpected scope");
    649   }
    650724
    651725  s->mscope = !blk;
     
    653727  if (blk) {
    654728    struct loopinfo *lp = loop_push(s, LOOP_BLOCK);
    655     lp->pc1 = new_label(s);
     729    lp->pc0 = new_label(s);
    656730  }
    657731  tree = tree->cdr;
    658   if (tree->car) {
     732  if (tree->car == NULL) {
     733    genop_W(s, OP_ENTER, 0);
     734  }
     735  else {
    659736    mrb_aspec a;
    660737    int ma, oa, ra, pa, ka, kd, ba;
    661738    int pos, i;
    662     node *n, *opt;
    663 
     739    node *opt;
     740    node *margs, *pargs;
     741    node *tail;
     742
     743    /* mandatory arguments */
    664744    ma = node_len(tree->car->car);
    665     n = tree->car->car;
    666     while (n) {
    667       n = n->cdr;
    668     }
     745    margs = tree->car->car;
     746    tail = tree->car->cdr->cdr->cdr->cdr;
     747
     748    /* optional arguments */
    669749    oa = node_len(tree->car->cdr->car);
     750    /* rest argument? */
    670751    ra = tree->car->cdr->cdr->car ? 1 : 0;
     752    /* mandatory arugments after rest argument */
    671753    pa = node_len(tree->car->cdr->cdr->cdr->car);
    672     ka = kd = 0;
    673     ba = tree->car->cdr->cdr->cdr->cdr ? 1 : 0;
     754    pargs = tree->car->cdr->cdr->cdr->car;
     755    /* keyword arguments */
     756    ka = tail? node_len(tail->cdr->car) : 0;
     757    /* keyword dictionary? */
     758    kd = tail && tail->cdr->cdr->car? 1 : 0;
     759    /* block argument? */
     760    ba = tail && tail->cdr->cdr->cdr->car ? 1 : 0;
    674761
    675762    if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) {
    676763      codegen_error(s, "too many formal arguments");
    677764    }
    678     a = ((mrb_aspec)(ma & 0x1f) << 18)
    679       | ((mrb_aspec)(oa & 0x1f) << 13)
    680       | ((ra & 1) << 12)
    681       | ((pa & 0x1f) << 7)
    682       | ((ka & 0x1f) << 2)
    683       | ((kd & 1)<< 1)
    684       | (ba & 1);
    685     s->ainfo = (((ma+oa) & 0x3f) << 6) /* (12bits = 6:1:5) */
    686       | ((ra & 1) << 5)
    687       | (pa & 0x1f);
    688     genop(s, MKOP_Ax(OP_ENTER, a));
     765    a = MRB_ARGS_REQ(ma)
     766      | MRB_ARGS_OPT(oa)
     767      | (ra? MRB_ARGS_REST() : 0)
     768      | MRB_ARGS_POST(pa)
     769      | MRB_ARGS_KEY(ka, kd)
     770      | (ba? MRB_ARGS_BLOCK() : 0);
     771    s->ainfo = (((ma+oa) & 0x3f) << 7) /* (12bits = 5:1:5:1) */
     772      | ((ra & 0x1) << 6)
     773      | ((pa & 0x1f) << 1)
     774      | ((ka | kd) != 0 ? 0x01 : 0x00);
     775    genop_W(s, OP_ENTER, a);
     776    /* generate jump table for optional arguments initializer */
    689777    pos = new_label(s);
    690778    for (i=0; i<oa; i++) {
    691779      new_label(s);
    692       genop(s, MKOP_sBx(OP_JMP, 0));
     780      genjmp(s, OP_JMP, 0);
    693781    }
    694782    if (oa > 0) {
    695       genop(s, MKOP_sBx(OP_JMP, 0));
     783      genjmp(s, OP_JMP, 0);
    696784    }
    697785    opt = tree->car->cdr->car;
     
    700788      int idx;
    701789
    702       dispatch(s, pos+i);
     790      dispatch(s, pos+i*3+1);
    703791      codegen(s, opt->car->cdr, VAL);
    704       idx = lv_idx(s, (mrb_sym)(intptr_t)opt->car->car);
    705792      pop();
    706       genop_peep(s, MKOP_AB(OP_MOVE, idx, cursp()), NOVAL);
     793      idx = lv_idx(s, nsym(opt->car->car));
     794      gen_move(s, idx, cursp(), 0);
    707795      i++;
    708796      opt = opt->cdr;
    709797    }
    710798    if (oa > 0) {
    711       dispatch(s, pos+i);
    712     }
    713   }
     799      dispatch(s, pos+i*3+1);
     800    }
     801
     802    /* keyword arguments */
     803    if (tail) {
     804      node *kwds = tail->cdr->car;
     805      int kwrest = 0;
     806
     807      if (tail->cdr->cdr->car) {
     808        kwrest = 1;
     809      }
     810      mrb_assert(nint(tail->car) == NODE_ARGS_TAIL);
     811      mrb_assert(node_len(tail) == 4);
     812
     813      while (kwds) {
     814        int jmpif_key_p, jmp_def_set = -1;
     815        node *kwd = kwds->car, *def_arg = kwd->cdr->cdr->car;
     816        mrb_sym kwd_sym = nsym(kwd->cdr->car);
     817
     818        mrb_assert(nint(kwd->car) == NODE_KW_ARG);
     819
     820        if (def_arg) {
     821          genop_2(s, OP_KEY_P, lv_idx(s, kwd_sym), new_sym(s, kwd_sym));
     822          jmpif_key_p = genjmp2(s, OP_JMPIF, lv_idx(s, kwd_sym), 0, 0);
     823          codegen(s, def_arg, VAL);
     824          pop();
     825          gen_move(s, lv_idx(s, kwd_sym), cursp(), 0);
     826          jmp_def_set = genjmp(s, OP_JMP, 0);
     827          dispatch(s, jmpif_key_p);
     828        }
     829        genop_2(s, OP_KARG, lv_idx(s, kwd_sym), new_sym(s, kwd_sym));
     830        if (jmp_def_set != -1) {
     831          dispatch(s, jmp_def_set);
     832        }
     833        i++;
     834
     835        kwds = kwds->cdr;
     836      }
     837      if (tail->cdr->car && !kwrest) {
     838        genop_0(s, OP_KEYEND);
     839      }
     840    }
     841
     842    /* argument destructuring */
     843    if (margs) {
     844      node *n = margs;
     845
     846      pos = 1;
     847      while (n) {
     848        if (nint(n->car->car) == NODE_MASGN) {
     849          gen_vmassignment(s, n->car->cdr->car, pos, NOVAL);
     850        }
     851        pos++;
     852        n = n->cdr;
     853      }
     854    }
     855    if (pargs) {
     856      node *n = margs;
     857
     858      pos = ma+oa+ra+1;
     859      while (n) {
     860        if (nint(n->car->car) == NODE_MASGN) {
     861          gen_vmassignment(s, n->car->cdr->car, pos, NOVAL);
     862        }
     863        pos++;
     864        n = n->cdr;
     865      }
     866    }
     867  }
     868
    714869  codegen(s, tree->cdr->car, VAL);
    715870  pop();
    716871  if (s->pc > 0) {
    717     c = s->iseq[s->pc-1];
    718     if (GET_OPCODE(c) != OP_RETURN || GETARG_B(c) != OP_R_NORMAL || s->pc == s->lastlabel) {
    719       if (s->nregs == 0) {
    720         genop(s, MKOP_A(OP_LOADNIL, 0));
    721         genop(s, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
    722       }
    723       else {
    724         genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
    725       }
    726     }
     872    gen_return(s, OP_RETURN, cursp());
    727873  }
    728874  if (blk) {
     
    737883{
    738884  codegen_scope *scope = scope_new(s->mrb, s, tree->car);
    739   if (scope == NULL) {
    740     raise_error(s, "unexpected scope");
    741   }
    742885
    743886  codegen(scope, tree->cdr, VAL);
     887  gen_return(scope, OP_RETURN, scope->sp-1);
    744888  if (!s->iseq) {
    745     genop(scope, MKOP_A(OP_STOP, 0));
    746   }
    747   else if (!val) {
    748     genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
    749   }
    750   else {
    751     if (scope->nregs == 0) {
    752       genop(scope, MKOP_A(OP_LOADNIL, 0));
    753       genop(scope, MKOP_AB(OP_RETURN, 0, OP_R_NORMAL));
    754     }
    755     else {
    756       genop_peep(scope, MKOP_AB(OP_RETURN, scope->sp-1, OP_R_NORMAL), NOVAL);
    757     }
     889    genop_0(scope, OP_STOP);
    758890  }
    759891  scope_finish(scope);
     
    769901{
    770902  while (t) {
    771     if ((intptr_t)t->car->car == NODE_SPLAT) return FALSE;
     903    if (nint(t->car->car) == NODE_SPLAT) return FALSE;
    772904    t = t->cdr;
    773905  }
     
    782914  char *name2;
    783915
    784   name = mrb_sym2name_len(s->mrb, a, &len);
     916  name = mrb_sym_name_len(s->mrb, a, &len);
    785917  name2 = (char *)codegen_palloc(s,
    786918                                 (size_t)len
     
    805937
    806938  while (t) {
    807     is_splat = (intptr_t)t->car->car == NODE_SPLAT; /* splat mode */
     939    is_splat = nint(t->car->car) == NODE_SPLAT; /* splat mode */
    808940    if (
    809941      n+extra >= CALL_MAXARGS - 1 /* need to subtract one because vm.c expects an array if n == CALL_MAXARGS */
    810942      || is_splat) {
    811943      if (val) {
    812         if (is_splat && n == 0 && (intptr_t)t->car->cdr->car == NODE_ARRAY) {
     944        if (is_splat && n == 0 && nint(t->car->cdr->car) == NODE_ARRAY) {
    813945          codegen(s, t->car->cdr, VAL);
    814946          pop();
     
    816948        else {
    817949          pop_n(n);
    818           genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
     950          if (n == 0 && is_splat) {
     951            genop_1(s, OP_LOADNIL, cursp());
     952          }
     953          else {
     954            genop_2(s, OP_ARRAY, cursp(), n);
     955          }
    819956          push();
    820957          codegen(s, t->car, VAL);
    821958          pop(); pop();
    822959          if (is_splat) {
    823             genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
     960            genop_1(s, OP_ARYCAT, cursp());
    824961          }
    825962          else {
    826             genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
     963            genop_1(s, OP_ARYPUSH, cursp());
    827964          }
    828965        }
     
    832969          codegen(s, t->car, VAL);
    833970          pop(); pop();
    834           if ((intptr_t)t->car->car == NODE_SPLAT) {
    835             genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
     971          if (nint(t->car->car) == NODE_SPLAT) {
     972            genop_1(s, OP_ARYCAT, cursp());
    836973          }
    837974          else {
    838             genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
     975            genop_1(s, OP_ARYPUSH, cursp());
    839976          }
    840977          t = t->cdr;
     
    860997gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
    861998{
    862   mrb_sym sym = name ? name : sym(tree->cdr->car);
    863   int idx, skip = 0;
     999  mrb_sym sym = name ? name : nsym(tree->cdr->car);
     1000  int skip = 0;
    8641001  int n = 0, noop = 0, sendv = 0, blk = 0;
    8651002
     
    8671004  if (safe) {
    8681005    int recv = cursp()-1;
    869     genop(s, MKOP_A(OP_LOADNIL, cursp()));
    870     push();
    871     genop(s, MKOP_AB(OP_MOVE, cursp(), recv));
    872     push(); pop();              /* space for a block */
    873     pop();
    874     idx = new_msym(s, mrb_intern_lit(s->mrb, "=="));
    875     genop(s, MKOP_ABC(OP_EQ, cursp(), idx, 1));
    876     skip = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
    877   }
    878   idx = new_msym(s, sym);
     1006    gen_move(s, cursp(), recv, 1);
     1007    skip = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
     1008  }
    8791009  tree = tree->cdr->cdr->car;
    8801010  if (tree) {
     
    8851015    }
    8861016  }
    887   if (sp) {
     1017  if (sp) {                     /* last argument pushed (attr=) */
    8881018    if (sendv) {
     1019      gen_move(s, cursp(), sp, 0);
    8891020      pop();
    890       genop(s, MKOP_AB(OP_ARYPUSH, cursp(), sp));
     1021      genop_1(s, OP_ARYPUSH, cursp());
    8911022      push();
    8921023    }
    8931024    else {
    894       genop(s, MKOP_AB(OP_MOVE, cursp(), sp));
     1025      gen_move(s, cursp(), sp, 0);
    8951026      push();
    8961027      n++;
     
    9011032    codegen(s, tree->cdr, VAL);
    9021033    pop();
    903   }
    904   else {
    905     blk = cursp();
     1034    blk = 1;
    9061035  }
    9071036  push();pop();
     
    9091038  {
    9101039    mrb_int symlen;
    911     const char *symname = mrb_sym2name_len(s->mrb, sym, &symlen);
     1040    const char *symname = mrb_sym_name_len(s->mrb, sym, &symlen);
    9121041
    9131042    if (!noop && symlen == 1 && symname[0] == '+' && n == 1)  {
    914       genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, n), val);
     1043      gen_addsub(s, OP_ADD, cursp());
    9151044    }
    9161045    else if (!noop && symlen == 1 && symname[0] == '-' && n == 1)  {
    917       genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, n), val);
     1046      gen_addsub(s, OP_SUB, cursp());
    9181047    }
    9191048    else if (!noop && symlen == 1 && symname[0] == '*' && n == 1)  {
    920       genop(s, MKOP_ABC(OP_MUL, cursp(), idx, n));
     1049      genop_1(s, OP_MUL, cursp());
    9211050    }
    9221051    else if (!noop && symlen == 1 && symname[0] == '/' && n == 1)  {
    923       genop(s, MKOP_ABC(OP_DIV, cursp(), idx, n));
     1052      genop_1(s, OP_DIV, cursp());
    9241053    }
    9251054    else if (!noop && symlen == 1 && symname[0] == '<' && n == 1)  {
    926       genop(s, MKOP_ABC(OP_LT, cursp(), idx, n));
     1055      genop_1(s, OP_LT, cursp());
    9271056    }
    9281057    else if (!noop && symlen == 2 && symname[0] == '<' && symname[1] == '=' && n == 1)  {
    929       genop(s, MKOP_ABC(OP_LE, cursp(), idx, n));
     1058      genop_1(s, OP_LE, cursp());
    9301059    }
    9311060    else if (!noop && symlen == 1 && symname[0] == '>' && n == 1)  {
    932       genop(s, MKOP_ABC(OP_GT, cursp(), idx, n));
     1061      genop_1(s, OP_GT, cursp());
    9331062    }
    9341063    else if (!noop && symlen == 2 && symname[0] == '>' && symname[1] == '=' && n == 1)  {
    935       genop(s, MKOP_ABC(OP_GE, cursp(), idx, n));
     1064      genop_1(s, OP_GE, cursp());
    9361065    }
    9371066    else if (!noop && symlen == 2 && symname[0] == '=' && symname[1] == '=' && n == 1)  {
    938       genop(s, MKOP_ABC(OP_EQ, cursp(), idx, n));
     1067      genop_1(s, OP_EQ, cursp());
    9391068    }
    9401069    else {
    941       if (sendv) n = CALL_MAXARGS;
    942       if (blk > 0) {                   /* no block */
    943         genop(s, MKOP_ABC(OP_SEND, cursp(), idx, n));
     1070      int idx = new_sym(s, sym);
     1071
     1072      if (sendv) {
     1073        genop_2(s, blk ? OP_SENDVB : OP_SENDV, cursp(), idx);
    9441074      }
    9451075      else {
    946         genop(s, MKOP_ABC(OP_SENDB, cursp(), idx, n));
     1076        genop_3(s, blk ? OP_SENDB : OP_SEND, cursp(), idx, n);
    9471077      }
    9481078    }
     
    9601090{
    9611091  int idx;
    962   int type = (intptr_t)tree->car;
     1092  int type = nint(tree->car);
    9631093
    9641094  tree = tree->cdr;
    9651095  switch (type) {
    9661096  case NODE_GVAR:
    967     idx = new_sym(s, sym(tree));
    968     genop_peep(s, MKOP_ABx(OP_SETGLOBAL, sp, idx), val);
    969     break;
     1097    idx = new_sym(s, nsym(tree));
     1098    genop_2(s, OP_SETGV, sp, idx);
     1099    break;
     1100  case NODE_ARG:
    9701101  case NODE_LVAR:
    971     idx = lv_idx(s, sym(tree));
     1102    idx = lv_idx(s, nsym(tree));
    9721103    if (idx > 0) {
    9731104      if (idx != sp) {
    974         genop_peep(s, MKOP_AB(OP_MOVE, idx, sp), val);
     1105        gen_move(s, idx, sp, val);
     1106        if (val && on_eval(s)) genop_0(s, OP_NOP);
    9751107      }
    9761108      break;
     
    9811113
    9821114      while (up) {
    983         idx = lv_idx(up, sym(tree));
     1115        idx = lv_idx(up, nsym(tree));
    9841116        if (idx > 0) {
    985           genop_peep(s, MKOP_ABC(OP_SETUPVAR, sp, idx, lv), val);
     1117          genop_3(s, OP_SETUPVAR, sp, idx, lv);
    9861118          break;
    9871119        }
     
    9911123    }
    9921124    break;
     1125  case NODE_NVAR:
     1126    idx = nint(tree);
     1127    codegen_error(s, "Can't assign to numbered parameter");
     1128    break;
    9931129  case NODE_IVAR:
    994     idx = new_sym(s, sym(tree));
    995     genop_peep(s, MKOP_ABx(OP_SETIV, sp, idx), val);
     1130    idx = new_sym(s, nsym(tree));
     1131    genop_2(s, OP_SETIV, sp, idx);
    9961132    break;
    9971133  case NODE_CVAR:
    998     idx = new_sym(s, sym(tree));
    999     genop_peep(s, MKOP_ABx(OP_SETCV, sp, idx), val);
     1134    idx = new_sym(s, nsym(tree));
     1135    genop_2(s, OP_SETCV, sp, idx);
    10001136    break;
    10011137  case NODE_CONST:
    1002     idx = new_sym(s, sym(tree));
    1003     genop_peep(s, MKOP_ABx(OP_SETCONST, sp, idx), val);
     1138    idx = new_sym(s, nsym(tree));
     1139    genop_2(s, OP_SETCONST, sp, idx);
    10041140    break;
    10051141  case NODE_COLON2:
    1006     idx = new_sym(s, sym(tree->cdr));
    1007     genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), NOVAL);
     1142    gen_move(s, cursp(), sp, 0);
    10081143    push();
    10091144    codegen(s, tree->car, VAL);
    10101145    pop_n(2);
    1011     genop_peep(s, MKOP_ABx(OP_SETMCNST, cursp(), idx), val);
     1146    idx = new_sym(s, nsym(tree->cdr));
     1147    genop_2(s, OP_SETMCNST, sp, idx);
    10121148    break;
    10131149
     
    10151151  case NODE_SCALL:
    10161152    push();
    1017     gen_call(s, tree, attrsym(s, sym(tree->cdr->car)), sp, NOVAL,
     1153    gen_call(s, tree, attrsym(s, nsym(tree->cdr->car)), sp, NOVAL,
    10181154             type == NODE_SCALL);
    10191155    pop();
    10201156    if (val) {
    1021       genop_peep(s, MKOP_AB(OP_MOVE, cursp(), sp), val);
     1157      gen_move(s, cursp(), sp, 0);
    10221158    }
    10231159    break;
     
    10501186    n = 0;
    10511187    while (t) {
    1052       genop(s, MKOP_ABC(OP_AREF, cursp(), rhs, n));
    1053       gen_assignment(s, t->car, cursp(), NOVAL);
     1188      int sp = cursp();
     1189
     1190      genop_3(s, OP_AREF, sp, rhs, n);
     1191      push();
     1192      gen_assignment(s, t->car, sp, NOVAL);
     1193      pop();
    10541194      n++;
    10551195      t = t->cdr;
     
    10651205      }
    10661206    }
    1067     if (val) {
    1068       genop(s, MKOP_AB(OP_MOVE, cursp(), rhs));
    1069     }
    1070     else {
    1071       pop();
    1072     }
    1073     push_n(post);
    1074     pop_n(post);
    1075     genop(s, MKOP_ABC(OP_APOST, cursp(), n, post));
     1207    gen_move(s, cursp(), rhs, val);
     1208    push_n(post+1);
     1209    pop_n(post+1);
     1210    genop_3(s, OP_APOST, cursp(), n, post);
    10761211    n = 1;
    1077     if (t->car) {              /* rest */
     1212    if (t->car && t->car != (node*)-1) { /* rest */
    10781213      gen_assignment(s, t->car, cursp(), NOVAL);
    10791214    }
     
    10861221      }
    10871222    }
    1088     if (!val) {
    1089       push();
     1223    if (val) {
     1224      gen_move(s, cursp(), rhs, 0);
    10901225    }
    10911226  }
     
    10931228
    10941229static void
    1095 gen_send_intern(codegen_scope *s)
     1230gen_intern(codegen_scope *s)
    10961231{
    10971232  pop();
    1098   genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "intern")), 0));
     1233  genop_1(s, OP_INTERN, cursp());
    10991234  push();
    11001235}
     1236
    11011237static void
    11021238gen_literal_array(codegen_scope *s, node *tree, mrb_bool sym, int val)
     
    11061242
    11071243    while (tree) {
    1108       switch ((intptr_t)tree->car->car) {
     1244      switch (nint(tree->car->car)) {
    11091245      case NODE_STR:
    1110         if ((tree->cdr == NULL) && ((intptr_t)tree->car->cdr->cdr == 0))
     1246        if ((tree->cdr == NULL) && (nint(tree->car->cdr->cdr) == 0))
    11111247          break;
    11121248        /* fall through */
     
    11211257          ++i;
    11221258          if (sym)
    1123             gen_send_intern(s);
     1259            gen_intern(s);
    11241260        }
    11251261        break;
    11261262      }
    1127       if (j >= 2) {
     1263      while (j >= 2) {
    11281264        pop(); pop();
    1129         genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
     1265        genop_1(s, OP_STRCAT, cursp());
    11301266        push();
    1131         j = 1;
     1267        j--;
    11321268      }
    11331269      tree = tree->cdr;
     
    11361272      ++i;
    11371273      if (sym)
    1138         gen_send_intern(s);
     1274        gen_intern(s);
    11391275    }
    11401276    pop_n(i);
    1141     genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i));
     1277    genop_2(s, OP_ARRAY, cursp(), i);
    11421278    push();
    11431279  }
    11441280  else {
    11451281    while (tree) {
    1146       switch ((intptr_t)tree->car->car) {
     1282      switch (nint(tree->car->car)) {
    11471283      case NODE_BEGIN: case NODE_BLOCK:
    11481284        codegen(s, tree->car, NOVAL);
     
    11581294  int idx = new_lit(s, mrb_str_new_cstr(s->mrb, msg));
    11591295
    1160   genop(s, MKOP_ABx(OP_ERR, 1, idx));
    1161 }
    1162 
     1296  genop_1(s, OP_ERR, idx);
     1297}
     1298
     1299#ifndef MRB_WITHOUT_FLOAT
    11631300static double
    11641301readint_float(codegen_scope *s, const char *p, int base)
     
    11861323  return f;
    11871324}
     1325#endif
    11881326
    11891327static mrb_int
     
    12331371gen_retval(codegen_scope *s, node *tree)
    12341372{
    1235   if ((intptr_t)tree->car == NODE_SPLAT) {
    1236     genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), 0));
    1237     push();
     1373  if (nint(tree->car) == NODE_SPLAT) {
    12381374    codegen(s, tree, VAL);
    1239     pop(); pop();
    1240     genop(s, MKOP_AB(OP_ARYCAT, cursp(), cursp()+1));
     1375    pop();
     1376    genop_1(s, OP_ARYDUP, cursp());
    12411377  }
    12421378  else {
     
    12541390  if (!tree) {
    12551391    if (val) {
    1256       genop(s, MKOP_A(OP_LOADNIL, cursp()));
     1392      genop_1(s, OP_LOADNIL, cursp());
    12571393      push();
    12581394    }
     
    12651401  }
    12661402  if (s->irep && s->filename_index != tree->filename_index) {
    1267     s->irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
    1268     mrb_debug_info_append_file(s->mrb, s->irep, s->debug_start_pos, s->pc);
     1403    mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
     1404    const char *filename = mrb_sym_name_len(s->mrb, fname, NULL);
     1405
     1406    mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
     1407                               filename, s->lines, s->debug_start_pos, s->pc);
    12691408    s->debug_start_pos = s->pc;
    12701409    s->filename_index = tree->filename_index;
    1271     s->filename = mrb_parser_get_filename(s->parser, tree->filename_index);
    1272   }
    1273 
    1274   nt = (intptr_t)tree->car;
     1410    s->filename_sym = mrb_parser_get_filename(s->parser, tree->filename_index);
     1411  }
     1412
     1413  nt = nint(tree->car);
    12751414  s->lineno = tree->lineno;
    12761415  tree = tree->cdr;
     
    12781417  case NODE_BEGIN:
    12791418    if (val && !tree) {
    1280       genop(s, MKOP_A(OP_LOADNIL, cursp()));
     1419      genop_1(s, OP_LOADNIL, cursp());
    12811420      push();
    12821421    }
     
    12891428  case NODE_RESCUE:
    12901429    {
    1291       int onerr, noexc, exend, pos1, pos2, tmp;
     1430      int noexc, exend, pos1, pos2, tmp;
    12921431      struct loopinfo *lp;
    12931432
    12941433      if (tree->car == NULL) goto exit;
    1295       onerr = genop(s, MKOP_Bx(OP_ONERR, 0));
    12961434      lp = loop_push(s, LOOP_BEGIN);
    1297       lp->pc1 = onerr;
     1435      lp->pc0 = new_label(s);
     1436      lp->pc1 = genjmp(s, OP_ONERR, 0);
    12981437      codegen(s, tree->car, VAL);
    12991438      pop();
    13001439      lp->type = LOOP_RESCUE;
    1301       noexc = genop(s, MKOP_Bx(OP_JMP, 0));
    1302       dispatch(s, onerr);
     1440      noexc = genjmp(s, OP_JMP, 0);
     1441      dispatch(s, lp->pc1);
    13031442      tree = tree->cdr;
    13041443      exend = 0;
     
    13081447        int exc = cursp();
    13091448
    1310         genop(s, MKOP_ABC(OP_RESCUE, exc, 0, 0));
     1449        genop_1(s, OP_EXCEPT, exc);
    13111450        push();
    13121451        while (n2) {
     
    13171456          pos2 = 0;
    13181457          do {
    1319             if (n4 && n4->car && (intptr_t)n4->car->car == NODE_SPLAT) {
     1458            if (n4 && n4->car && nint(n4->car->car) == NODE_SPLAT) {
    13201459              codegen(s, n4->car, VAL);
    1321               genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
     1460              gen_move(s, cursp(), exc, 0);
     1461              push_n(2); pop_n(2); /* space for one arg and a block */
    13221462              pop();
    1323               genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
     1463              genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1);
    13241464            }
    13251465            else {
     
    13281468              }
    13291469              else {
    1330                 genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError"))));
     1470                genop_2(s, OP_GETCONST, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "StandardError")));
    13311471                push();
    13321472              }
    13331473              pop();
    1334               genop(s, MKOP_ABC(OP_RESCUE, exc, cursp(), 1));
     1474              genop_2(s, OP_RESCUE, exc, cursp());
    13351475            }
    1336             tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
     1476            tmp = genjmp2(s, OP_JMPIF, cursp(), pos2, val);
    13371477            pos2 = tmp;
    13381478            if (n4) {
     
    13401480            }
    13411481          } while (n4);
    1342           pos1 = genop(s, MKOP_sBx(OP_JMP, 0));
     1482          pos1 = genjmp(s, OP_JMP, 0);
    13431483          dispatch_linked(s, pos2);
    13441484
     
    13511491            if (val) pop();
    13521492          }
    1353           tmp = genop(s, MKOP_sBx(OP_JMP, exend));
     1493          tmp = genjmp(s, OP_JMP, exend);
    13541494          exend = tmp;
    13551495          n2 = n2->cdr;
     
    13581498        if (pos1) {
    13591499          dispatch(s, pos1);
    1360           genop(s, MKOP_A(OP_RAISE, exc));
     1500          genop_1(s, OP_RAISE, exc);
    13611501        }
    13621502      }
     
    13641504      tree = tree->cdr;
    13651505      dispatch(s, noexc);
    1366       genop(s, MKOP_A(OP_POPERR, 1));
     1506      genop_1(s, OP_POPERR, 1);
    13671507      if (tree->car) {
    13681508        codegen(s, tree->car, val);
     
    13781518  case NODE_ENSURE:
    13791519    if (!tree->cdr || !tree->cdr->cdr ||
    1380         ((intptr_t)tree->cdr->cdr->car == NODE_BEGIN &&
     1520        (nint(tree->cdr->cdr->car) == NODE_BEGIN &&
    13811521         tree->cdr->cdr->cdr)) {
    13821522      int idx;
    1383       int epush = s->pc;
    1384 
    1385       genop(s, MKOP_Bx(OP_EPUSH, 0));
     1523
    13861524      s->ensure_level++;
     1525      idx = scope_body(s, tree->cdr, NOVAL);
     1526      genop_1(s, OP_EPUSH, idx);
    13871527      codegen(s, tree->car, val);
    1388       idx = scope_body(s, tree->cdr, NOVAL);
    1389       s->iseq[epush] = MKOP_Bx(OP_EPUSH, idx);
    13901528      s->ensure_level--;
    1391       genop_peep(s, MKOP_A(OP_EPOP, 1), NOVAL);
     1529      genop_1(s, OP_EPOP, 1);
    13921530    }
    13931531    else {                      /* empty ensure ignored */
     
    14001538      int idx = lambda_body(s, tree, 1);
    14011539
    1402       genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_LAMBDA));
     1540      genop_2(s, OP_LAMBDA, cursp(), idx);
    14031541      push();
    14041542    }
     
    14091547      int idx = lambda_body(s, tree, 1);
    14101548
    1411       genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_BLOCK));
     1549      genop_2(s, OP_BLOCK, cursp(), idx);
    14121550      push();
    14131551    }
     
    14161554  case NODE_IF:
    14171555    {
    1418       int pos1, pos2;
    1419       node *e = tree->cdr->cdr->car;
     1556      int pos1, pos2, nil_p = FALSE;
     1557      node *elsepart = tree->cdr->cdr->car;
    14201558
    14211559      if (!tree->car) {
    1422         codegen(s, e, val);
     1560        codegen(s, elsepart, val);
    14231561        goto exit;
    14241562      }
    1425       switch ((intptr_t)tree->car->car) {
     1563      switch (nint(tree->car->car)) {
    14261564      case NODE_TRUE:
    14271565      case NODE_INT:
     
    14311569      case NODE_FALSE:
    14321570      case NODE_NIL:
    1433         codegen(s, e, val);
     1571        codegen(s, elsepart, val);
    14341572        goto exit;
    1435       }
    1436       codegen(s, tree->car, VAL);
     1573      case NODE_CALL:
     1574        {
     1575          node *n = tree->car->cdr;
     1576          mrb_sym mid = nsym(n->cdr->car);
     1577          mrb_sym mnil = mrb_intern_lit(s->mrb, "nil?");
     1578          if (mid == mnil && n->cdr->cdr->car == NULL) {
     1579            nil_p = TRUE;
     1580            codegen(s, n->car, VAL);
     1581          }
     1582        }
     1583        break;
     1584      }
     1585      if (!nil_p) {
     1586        codegen(s, tree->car, VAL);
     1587      }
    14371588      pop();
    1438       pos1 = genop_peep(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0), NOVAL);
    1439 
    1440       codegen(s, tree->cdr->car, val);
    1441       if (e) {
     1589      if (val || tree->cdr->car) {
     1590        if (nil_p) {
     1591          pos2 = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
     1592          pos1 = genjmp(s, OP_JMP, 0);
     1593          dispatch(s, pos2);
     1594        }
     1595        else {
     1596          pos1 = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
     1597        }
     1598        codegen(s, tree->cdr->car, val);
    14421599        if (val) pop();
    1443         pos2 = genop(s, MKOP_sBx(OP_JMP, 0));
    1444         dispatch(s, pos1);
    1445         codegen(s, e, val);
    1446         dispatch(s, pos2);
    1447       }
    1448       else {
    1449         if (val) {
    1450           pop();
    1451           pos2 = genop(s, MKOP_sBx(OP_JMP, 0));
     1600        if (elsepart || val) {
     1601          pos2 = genjmp(s, OP_JMP, 0);
    14521602          dispatch(s, pos1);
    1453           genop(s, MKOP_A(OP_LOADNIL, cursp()));
     1603          codegen(s, elsepart, val);
    14541604          dispatch(s, pos2);
    1455           push();
    14561605        }
    14571606        else {
    14581607          dispatch(s, pos1);
     1608        }
     1609      }
     1610      else {                    /* empty then-part */
     1611        if (elsepart) {
     1612          if (nil_p) {
     1613            pos1 = genjmp2(s, OP_JMPNIL, cursp(), 0, val);
     1614          }
     1615          else {
     1616            pos1 = genjmp2(s, OP_JMPIF, cursp(), 0, val);
     1617          }
     1618          codegen(s, elsepart, val);
     1619          dispatch(s, pos1);
     1620        }
     1621        else if (val && !nil_p) {
     1622          genop_1(s, OP_LOADNIL, cursp());
     1623          push();
    14591624        }
    14601625      }
     
    14681633      codegen(s, tree->car, VAL);
    14691634      pop();
    1470       pos = genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), 0));
     1635      pos = genjmp2(s, OP_JMPNOT, cursp(), 0, val);
    14711636      codegen(s, tree->cdr, val);
    14721637      dispatch(s, pos);
     
    14801645      codegen(s, tree->car, VAL);
    14811646      pop();
    1482       pos = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), 0));
     1647      pos = genjmp2(s, OP_JMPIF, cursp(), 0, val);
    14831648      codegen(s, tree->cdr, val);
    14841649      dispatch(s, pos);
     
    14901655      struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
    14911656
    1492       lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0));
     1657      lp->pc0 = new_label(s);
     1658      lp->pc1 = genjmp(s, OP_JMP, 0);
    14931659      lp->pc2 = new_label(s);
    14941660      codegen(s, tree->cdr, NOVAL);
     
    14961662      codegen(s, tree->car, VAL);
    14971663      pop();
    1498       genop(s, MKOP_AsBx(OP_JMPIF, cursp(), lp->pc2 - s->pc));
     1664      genjmp2(s, OP_JMPIF, cursp(), lp->pc2, NOVAL);
    14991665
    15001666      loop_pop(s, val);
     
    15061672      struct loopinfo *lp = loop_push(s, LOOP_NORMAL);
    15071673
    1508       lp->pc1 = genop(s, MKOP_sBx(OP_JMP, 0));
     1674      lp->pc0 = new_label(s);
     1675      lp->pc1 = genjmp(s, OP_JMP, 0);
    15091676      lp->pc2 = new_label(s);
    15101677      codegen(s, tree->cdr, NOVAL);
     
    15121679      codegen(s, tree->car, VAL);
    15131680      pop();
    1514       genop(s, MKOP_AsBx(OP_JMPNOT, cursp(), lp->pc2 - s->pc));
     1681      genjmp2(s, OP_JMPNOT, cursp(), lp->pc2, NOVAL);
    15151682
    15161683      loop_pop(s, val);
     
    15411708          codegen(s, n->car, VAL);
    15421709          if (head) {
    1543             genop(s, MKOP_AB(OP_MOVE, cursp(), head));
    1544             pop();
    1545             if ((intptr_t)n->car->car == NODE_SPLAT) {
    1546               genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
     1710            gen_move(s, cursp(), head, 0);
     1711            push(); push(); pop(); pop(); pop();
     1712            if (nint(n->car->car) == NODE_SPLAT) {
     1713              genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1);
    15471714            }
    15481715            else {
    1549               genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1));
     1716              genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "===")), 1);
    15501717            }
    15511718          }
     
    15531720            pop();
    15541721          }
    1555           tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
     1722          tmp = genjmp2(s, OP_JMPIF, cursp(), pos2, NOVAL);
    15561723          pos2 = tmp;
    15571724          n = n->cdr;
    15581725        }
    15591726        if (tree->car->car) {
    1560           pos1 = genop(s, MKOP_sBx(OP_JMP, 0));
     1727          pos1 = genjmp(s, OP_JMP, 0);
    15611728          dispatch_linked(s, pos2);
    15621729        }
    15631730        codegen(s, tree->car->cdr, val);
    15641731        if (val) pop();
    1565         tmp = genop(s, MKOP_sBx(OP_JMP, pos3));
     1732        tmp = genjmp(s, OP_JMP, pos3);
    15661733        pos3 = tmp;
    15671734        if (pos1) dispatch(s, pos1);
     
    15701737      if (val) {
    15711738        int pos = cursp();
    1572         genop(s, MKOP_A(OP_LOADNIL, cursp()));
     1739        genop_1(s, OP_LOADNIL, cursp());
    15731740        if (pos3) dispatch_linked(s, pos3);
    15741741        if (head) pop();
    15751742        if (cursp() != pos) {
    1576           genop(s, MKOP_AB(OP_MOVE, cursp(), pos));
     1743          gen_move(s, cursp(), pos, 0);
    15771744        }
    15781745        push();
     
    16061773    if (val) {
    16071774      pop(); pop();
    1608       genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), FALSE));
     1775      genop_1(s, OP_RANGE_INC, cursp());
    16091776      push();
    16101777    }
     
    16161783    if (val) {
    16171784      pop(); pop();
    1618       genop(s, MKOP_ABC(OP_RANGE, cursp(), cursp(), TRUE));
     1785      genop_1(s, OP_RANGE_EXC, cursp());
    16191786      push();
    16201787    }
     
    16231790  case NODE_COLON2:
    16241791    {
    1625       int sym = new_sym(s, sym(tree->cdr));
     1792      int sym = new_sym(s, nsym(tree->cdr));
    16261793
    16271794      codegen(s, tree->car, VAL);
    16281795      pop();
    1629       genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
     1796      genop_2(s, OP_GETMCNST, cursp(), sym);
    16301797      if (val) push();
    16311798    }
     
    16341801  case NODE_COLON3:
    16351802    {
    1636       int sym = new_sym(s, sym(tree));
    1637 
    1638       genop(s, MKOP_A(OP_OCLASS, cursp()));
    1639       genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
     1803      int sym = new_sym(s, nsym(tree));
     1804
     1805      genop_1(s, OP_OCLASS, cursp());
     1806      genop_2(s, OP_GETMCNST, cursp(), sym);
    16401807      if (val) push();
    16411808    }
     
    16501817        if (val) {
    16511818          pop_n(n);
    1652           genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), n));
     1819          genop_2(s, OP_ARRAY, cursp(), n);
    16531820          push();
    16541821        }
     
    16611828
    16621829  case NODE_HASH:
     1830  case NODE_KW_HASH:
    16631831    {
    16641832      int len = 0;
     
    16661834
    16671835      while (tree) {
    1668         codegen(s, tree->car->car, val);
    1669         codegen(s, tree->car->cdr, val);
    1670         len++;
     1836        if (nint(tree->car->car->car) == NODE_KW_REST_ARGS) {
     1837          if (len > 0) {
     1838            pop_n(len*2);
     1839            if (!update) {
     1840              genop_2(s, OP_HASH, cursp(), len);
     1841            }
     1842            else {
     1843              pop();
     1844              genop_2(s, OP_HASHADD, cursp(), len);
     1845            }
     1846            push();
     1847          }
     1848          codegen(s, tree->car->cdr, VAL);
     1849          if (len > 0 || update) {
     1850            pop(); pop();
     1851            genop_1(s, OP_HASHCAT, cursp());
     1852            push();
     1853          }
     1854          update = TRUE;
     1855          len = 0;
     1856        }
     1857        else {
     1858          codegen(s, tree->car->car, val);
     1859          codegen(s, tree->car->cdr, val);
     1860          len++;
     1861        }
    16711862        tree = tree->cdr;
    1672         if (val && len == 126) {
     1863        if (val && len == 255) {
    16731864          pop_n(len*2);
    1674           genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len));
    1675           if (update) {
     1865          if (!update) {
     1866            genop_2(s, OP_HASH, cursp(), len);
     1867          }
     1868          else {
    16761869            pop();
    1677             genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1));
     1870            genop_2(s, OP_HASHADD, cursp(), len);
    16781871          }
    16791872          push();
     
    16841877      if (val) {
    16851878        pop_n(len*2);
    1686         genop(s, MKOP_ABC(OP_HASH, cursp(), cursp(), len));
    1687         if (update) {
     1879        if (!update) {
     1880          genop_2(s, OP_HASH, cursp(), len);
     1881        }
     1882        else {
    16881883          pop();
    1689           genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__update")), 1));
     1884          if (len > 0) {
     1885            genop_2(s, OP_HASHADD, cursp(), len);
     1886          }
    16901887        }
    16911888        push();
     
    17101907      int rhs = cursp();
    17111908
    1712       if ((intptr_t)t->car == NODE_ARRAY && t->cdr && nosplat(t->cdr)) {
     1909      if (nint(t->car) == NODE_ARRAY && t->cdr && nosplat(t->cdr)) {
    17131910        /* fixed rhs */
    17141911        t = t->cdr;
     
    17281925            }
    17291926            else {
    1730               genop(s, MKOP_A(OP_LOADNIL, rhs+n));
     1927              genop_1(s, OP_LOADNIL, rhs+n);
    17311928              gen_assignment(s, t->car, rhs+n, NOVAL);
    17321929            }
     
    17521949              rn = len - post - n;
    17531950            }
    1754             genop(s, MKOP_ABC(OP_ARRAY, cursp(), rhs+n, rn));
     1951            genop_3(s, OP_ARRAY2, cursp(), rhs+n, rn);
    17551952            gen_assignment(s, t->car, cursp(), NOVAL);
    17561953            n += rn;
     
    17671964        pop_n(len);
    17681965        if (val) {
    1769           genop(s, MKOP_ABC(OP_ARRAY, rhs, rhs, len));
     1966          genop_2(s, OP_ARRAY, rhs, len);
    17701967          push();
    17711968        }
     
    17841981  case NODE_OP_ASGN:
    17851982    {
    1786       mrb_sym sym = sym(tree->cdr->car);
     1983      mrb_sym sym = nsym(tree->cdr->car);
    17871984      mrb_int len;
    1788       const char *name = mrb_sym2name_len(s->mrb, sym, &len);
     1985      const char *name = mrb_sym_name_len(s->mrb, sym, &len);
    17891986      int idx, callargs = -1, vsp = -1;
    17901987
    17911988      if ((len == 2 && name[0] == '|' && name[1] == '|') &&
    1792           ((intptr_t)tree->car->car == NODE_CONST ||
    1793            (intptr_t)tree->car->car == NODE_CVAR)) {
     1989          (nint(tree->car->car) == NODE_CONST ||
     1990           nint(tree->car->car) == NODE_CVAR)) {
    17941991        int onerr, noexc, exc;
    17951992        struct loopinfo *lp;
    17961993
    1797         onerr = genop(s, MKOP_Bx(OP_ONERR, 0));
     1994        onerr = genjmp(s, OP_ONERR, 0);
    17981995        lp = loop_push(s, LOOP_BEGIN);
    17991996        lp->pc1 = onerr;
     
    18011998        codegen(s, tree->car, VAL);
    18021999        lp->type = LOOP_RESCUE;
    1803         genop(s, MKOP_A(OP_POPERR, 1));
    1804         noexc = genop(s, MKOP_Bx(OP_JMP, 0));
     2000        genop_1(s, OP_POPERR, 1);
     2001        noexc = genjmp(s, OP_JMP, 0);
    18052002        dispatch(s, onerr);
    1806         genop(s, MKOP_ABC(OP_RESCUE, exc, 0, 0));
    1807         genop(s, MKOP_A(OP_LOADF, exc));
     2003        genop_1(s, OP_EXCEPT, exc);
     2004        genop_1(s, OP_LOADF, exc);
    18082005        dispatch(s, noexc);
    18092006        loop_pop(s, NOVAL);
    18102007      }
    1811       else if ((intptr_t)tree->car->car == NODE_CALL) {
     2008      else if (nint(tree->car->car) == NODE_CALL) {
    18122009        node *n = tree->car->cdr;
     2010        int base, i, nargs = 0;
     2011        callargs = 0;
    18132012
    18142013        if (val) {
     
    18172016        }
    18182017        codegen(s, n->car, VAL);   /* receiver */
    1819         idx = new_msym(s, sym(n->cdr->car));
     2018        idx = new_sym(s, nsym(n->cdr->car));
     2019        base = cursp()-1;
    18202020        if (n->cdr->cdr->car) {
    1821           int base = cursp()-1;
    1822           int nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 1);
    1823 
    1824           /* copy receiver and arguments */
     2021          nargs = gen_values(s, n->cdr->cdr->car->car, VAL, 1);
    18252022          if (nargs >= 0) {
    1826             int i;
    1827 
    1828             genop(s, MKOP_AB(OP_MOVE, cursp(), base));
    1829             for (i=0; i<nargs; i++) {
    1830               genop(s, MKOP_AB(OP_MOVE, cursp()+i+1, base+i+1));
    1831             }
    1832             push_n(nargs+1);
    1833             pop_n(nargs+1);
    18342023            callargs = nargs;
    18352024          }
    1836           else {
    1837             /* varargs */
     2025          else { /* varargs */
    18382026            push();
    1839             genop(s, MKOP_AB(OP_MOVE, cursp(), base));
    1840             genop(s, MKOP_AB(OP_MOVE, cursp()+1, base+1));
     2027            nargs = 1;
    18412028            callargs = CALL_MAXARGS;
    18422029          }
    1843           genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
    1844         }
    1845         else {
    1846           genop(s, MKOP_AB(OP_MOVE, cursp(), cursp()-1));
    1847           genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 0));
    1848           callargs = 0;
    1849         }
     2030        }
     2031        /* copy receiver and arguments */
     2032        gen_move(s, cursp(), base, 1);
     2033        for (i=0; i<nargs; i++) {
     2034          gen_move(s, cursp()+i+1, base+i+1, 1);
     2035        }
     2036        push_n(nargs+2);pop_n(nargs+2); /* space for receiver, arguments and a block */
     2037        genop_3(s, OP_SEND, cursp(), idx, callargs);
    18502038        push();
    18512039      }
     
    18612049        if (val) {
    18622050          if (vsp >= 0) {
    1863             genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
    1864           }
    1865           pos = genop(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0));
     2051            gen_move(s, vsp, cursp(), 1);
     2052          }
     2053          pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val);
    18662054        }
    18672055        else {
    1868           pos = genop_peep(s, MKOP_AsBx(name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0), NOVAL);
     2056          pos = genjmp2(s, name[0]=='|'?OP_JMPIF:OP_JMPNOT, cursp(), 0, val);
    18692057        }
    18702058        codegen(s, tree->cdr->cdr->car, VAL);
    18712059        pop();
    18722060        if (val && vsp >= 0) {
    1873           genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
    1874         }
    1875         if ((intptr_t)tree->car->car == NODE_CALL) {
    1876           mrb_sym m = sym(tree->car->cdr->cdr->car);
    1877           mrb_sym m2 = attrsym(s, m);
    1878 
    1879           idx = new_msym(s, m2);
    1880           pop();
     2061          gen_move(s, vsp, cursp(), 1);
     2062        }
     2063        if (nint(tree->car->car) == NODE_CALL) {
    18812064          if (callargs == CALL_MAXARGS) {
    1882             genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
    18832065            pop();
    1884             genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
     2066            genop_1(s, OP_ARYPUSH, cursp());
    18852067          }
    18862068          else {
    18872069            pop_n(callargs);
    1888             genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs+1));
    1889           }
     2070            callargs++;
     2071          }
     2072          pop();
     2073          idx = new_sym(s, attrsym(s, nsym(tree->car->cdr->cdr->car)));
     2074          genop_3(s, OP_SEND, cursp(), idx, callargs);
    18902075        }
    18912076        else {
     
    18992084      pop(); pop();
    19002085
    1901       idx = new_msym(s, sym);
    19022086      if (len == 1 && name[0] == '+')  {
    1903         genop_peep(s, MKOP_ABC(OP_ADD, cursp(), idx, 1), val);
     2087        gen_addsub(s, OP_ADD, cursp());
    19042088      }
    19052089      else if (len == 1 && name[0] == '-')  {
    1906         genop_peep(s, MKOP_ABC(OP_SUB, cursp(), idx, 1), val);
     2090        gen_addsub(s, OP_SUB, cursp());
    19072091      }
    19082092      else if (len == 1 && name[0] == '*')  {
    1909         genop(s, MKOP_ABC(OP_MUL, cursp(), idx, 1));
     2093        genop_1(s, OP_MUL, cursp());
    19102094      }
    19112095      else if (len == 1 && name[0] == '/')  {
    1912         genop(s, MKOP_ABC(OP_DIV, cursp(), idx, 1));
     2096        genop_1(s, OP_DIV, cursp());
    19132097      }
    19142098      else if (len == 1 && name[0] == '<')  {
    1915         genop(s, MKOP_ABC(OP_LT, cursp(), idx, 1));
     2099        genop_1(s, OP_LT, cursp());
    19162100      }
    19172101      else if (len == 2 && name[0] == '<' && name[1] == '=')  {
    1918         genop(s, MKOP_ABC(OP_LE, cursp(), idx, 1));
     2102        genop_1(s, OP_LE, cursp());
    19192103      }
    19202104      else if (len == 1 && name[0] == '>')  {
    1921         genop(s, MKOP_ABC(OP_GT, cursp(), idx, 1));
     2105        genop_1(s, OP_GT, cursp());
    19222106      }
    19232107      else if (len == 2 && name[0] == '>' && name[1] == '=')  {
    1924         genop(s, MKOP_ABC(OP_GE, cursp(), idx, 1));
     2108        genop_1(s, OP_GE, cursp());
    19252109      }
    19262110      else {
    1927         genop(s, MKOP_ABC(OP_SEND, cursp(), idx, 1));
     2111        idx = new_sym(s, sym);
     2112        genop_3(s, OP_SEND, cursp(), idx, 1);
    19282113      }
    19292114      if (callargs < 0) {
     
    19322117      else {
    19332118        if (val && vsp >= 0) {
    1934           genop(s, MKOP_AB(OP_MOVE, vsp, cursp()));
     2119          gen_move(s, vsp, cursp(), 0);
    19352120        }
    19362121        if (callargs == CALL_MAXARGS) {
    19372122          pop();
    1938           genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
     2123          genop_1(s, OP_ARYPUSH, cursp());
    19392124        }
    19402125        else {
     
    19432128        }
    19442129        pop();
    1945         idx = new_msym(s, attrsym(s,sym(tree->car->cdr->cdr->car)));
    1946         genop(s, MKOP_ABC(OP_SEND, cursp(), idx, callargs));
     2130        idx = new_sym(s, attrsym(s,nsym(tree->car->cdr->cdr->car)));
     2131        genop_3(s, OP_SEND, cursp(), idx, callargs);
    19472132      }
    19482133    }
     
    19612146        if (!s2) break;
    19622147      }
    1963       genop(s, MKOP_ABx(OP_ARGARY, cursp(), (lv & 0xf)));
     2148      genop_2S(s, OP_ARGARY, cursp(), (lv & 0xf));
    19642149      push(); push();         /* ARGARY pushes two values */
    19652150      pop(); pop();
     
    19792164      }
    19802165      else {
    1981         genop(s, MKOP_A(OP_LOADNIL, cursp()));
     2166        genop_1(s, OP_LOADNIL, cursp());
    19822167        push(); pop();
    19832168      }
    19842169      pop_n(n+1);
    19852170      if (sendv) n = CALL_MAXARGS;
    1986       genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, n));
     2171      genop_2(s, OP_SUPER, cursp(), n);
    19872172      if (val) push();
    19882173    }
     
    20012186      }
    20022187      if (s2) ainfo = s2->ainfo;
    2003       genop(s, MKOP_ABx(OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf)));
     2188      genop_2S(s, OP_ARGARY, cursp(), (ainfo<<4)|(lv & 0xf));
    20042189      push(); push(); pop();    /* ARGARY pushes two values */
    20052190      if (tree && tree->cdr) {
     
    20082193      }
    20092194      pop(); pop();
    2010       genop(s, MKOP_ABC(OP_SUPER, cursp(), 0, CALL_MAXARGS));
     2195      genop_2(s, OP_SUPER, cursp(), CALL_MAXARGS);
    20112196      if (val) push();
    20122197    }
     
    20182203    }
    20192204    else {
    2020       genop(s, MKOP_A(OP_LOADNIL, cursp()));
     2205      genop_1(s, OP_LOADNIL, cursp());
    20212206    }
    20222207    if (s->loop) {
    2023       genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_RETURN));
     2208      gen_return(s, OP_RETURN_BLK, cursp());
    20242209    }
    20252210    else {
    2026       genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
     2211      gen_return(s, OP_RETURN, cursp());
    20272212    }
    20282213    if (val) push();
     
    20492234        }
    20502235      }
     2236      push();pop(); /* space for a block */
    20512237      pop_n(n+1);
    2052       genop(s, MKOP_ABx(OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf)));
     2238      genop_2S(s, OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf));
    20532239      if (sendv) n = CALL_MAXARGS;
    2054       genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "call")), n));
     2240      genop_3(s, OP_SEND, cursp(), new_sym(s, mrb_intern_lit(s->mrb, "call")), n);
    20552241      if (val) push();
    20562242    }
     
    20682254    else if (s->loop->type == LOOP_NORMAL) {
    20692255      if (s->ensure_level > s->loop->ensure_level) {
    2070         genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
     2256        genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
    20712257      }
    20722258      codegen(s, tree, NOVAL);
    2073       genop(s, MKOP_sBx(OP_JMP, s->loop->pc1 - s->pc));
     2259      genjmp(s, OP_JMP, s->loop->pc0);
    20742260    }
    20752261    else {
     
    20792265      }
    20802266      else {
    2081         genop(s, MKOP_A(OP_LOADNIL, cursp()));
    2082       }
    2083       genop_peep(s, MKOP_AB(OP_RETURN, cursp(), OP_R_NORMAL), NOVAL);
     2267        genop_1(s, OP_LOADNIL, cursp());
     2268      }
     2269      gen_return(s, OP_RETURN, cursp());
    20842270    }
    20852271    if (val) push();
     
    20922278    else {
    20932279      if (s->ensure_level > s->loop->ensure_level) {
    2094         genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
    2095       }
    2096       genop(s, MKOP_sBx(OP_JMP, s->loop->pc2 - s->pc));
     2280        genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
     2281      }
     2282      genjmp(s, OP_JMP, s->loop->pc2);
    20972283    }
    20982284    if (val) push();
     
    21212307        else {
    21222308          if (n > 0) {
    2123             while (n--) {
    2124               genop_peep(s, MKOP_A(OP_POPERR, 1), NOVAL);
    2125             }
     2309            genop_1(s, OP_POPERR, n);
    21262310          }
    21272311          if (s->ensure_level > lp->ensure_level) {
    2128             genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - lp->ensure_level), NOVAL);
    2129           }
    2130           genop(s, MKOP_sBx(OP_JMP, lp->pc1 - s->pc));
     2312            genop_1(s, OP_EPOP, s->ensure_level - lp->ensure_level);
     2313          }
     2314          genjmp(s, OP_JMP, lp->pc0);
    21312315        }
    21322316      }
     
    21372321  case NODE_LVAR:
    21382322    if (val) {
    2139       int idx = lv_idx(s, sym(tree));
     2323      int idx = lv_idx(s, nsym(tree));
    21402324
    21412325      if (idx > 0) {
    2142         genop_peep(s, MKOP_AB(OP_MOVE, cursp(), idx), NOVAL);
     2326        gen_move(s, cursp(), idx, val);
     2327        if (val && on_eval(s)) genop_0(s, OP_NOP);
    21432328      }
    21442329      else {
     
    21472332
    21482333        while (up) {
    2149           idx = lv_idx(up, sym(tree));
     2334          idx = lv_idx(up, nsym(tree));
    21502335          if (idx > 0) {
    2151             genop(s, MKOP_ABC(OP_GETUPVAR, cursp(), idx, lv));
     2336            genop_3(s, OP_GETUPVAR, cursp(), idx, lv);
    21522337            break;
    21532338          }
     
    21602345    break;
    21612346
     2347  case NODE_NVAR:
     2348    if (val) {
     2349      int idx = nint(tree);
     2350
     2351      gen_move(s, cursp(), idx, val);
     2352      if (val && on_eval(s)) genop_0(s, OP_NOP);
     2353
     2354      push();
     2355    }
     2356    break;
     2357
    21622358  case NODE_GVAR:
    2163     if (val) {
    2164       int sym = new_sym(s, sym(tree));
    2165 
    2166       genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
    2167       push();
     2359    {
     2360      int sym = new_sym(s, nsym(tree));
     2361
     2362      genop_2(s, OP_GETGV, cursp(), sym);
     2363      if (val) push();
    21682364    }
    21692365    break;
    21702366
    21712367  case NODE_IVAR:
    2172     if (val) {
    2173       int sym = new_sym(s, sym(tree));
    2174 
    2175       genop(s, MKOP_ABx(OP_GETIV, cursp(), sym));
    2176       push();
     2368    {
     2369      int sym = new_sym(s, nsym(tree));
     2370
     2371      genop_2(s, OP_GETIV, cursp(), sym);
     2372      if (val) push();
    21772373    }
    21782374    break;
    21792375
    21802376  case NODE_CVAR:
    2181     if (val) {
    2182       int sym = new_sym(s, sym(tree));
    2183 
    2184       genop(s, MKOP_ABx(OP_GETCV, cursp(), sym));
    2185       push();
     2377    {
     2378      int sym = new_sym(s, nsym(tree));
     2379
     2380      genop_2(s, OP_GETCV, cursp(), sym);
     2381      if (val) push();
    21862382    }
    21872383    break;
     
    21892385  case NODE_CONST:
    21902386    {
    2191       int sym = new_sym(s, sym(tree));
    2192 
    2193       genop(s, MKOP_ABx(OP_GETCONST, cursp(), sym));
    2194       if (val) {
    2195         push();
    2196       }
    2197     }
    2198     break;
    2199 
    2200   case NODE_DEFINED:
    2201     codegen(s, tree, VAL);
     2387      int sym = new_sym(s, nsym(tree));
     2388
     2389      genop_2(s, OP_GETCONST, cursp(), sym);
     2390      if (val) push();
     2391    }
    22022392    break;
    22032393
    22042394  case NODE_BACK_REF:
    22052395    if (val) {
    2206       char buf[3];
    2207       int sym;
    2208 
    2209       buf[0] = '$';
    2210       buf[1] = (char)(intptr_t)tree;
    2211       buf[2] = 0;
    2212       sym = new_sym(s, mrb_intern_cstr(s->mrb, buf));
    2213       genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
     2396      char buf[] = {'$', nchar(tree)};
     2397      int sym = new_sym(s, mrb_intern(s->mrb, buf, sizeof(buf)));
     2398
     2399      genop_2(s, OP_GETGV, cursp(), sym);
    22142400      push();
    22152401    }
     
    22222408      int sym;
    22232409
    2224       str = mrb_format(mrb, "$%S", mrb_fixnum_value((mrb_int)(intptr_t)tree));
     2410      str = mrb_format(mrb, "$%d", nint(tree));
    22252411      sym = new_sym(s, mrb_intern_str(mrb, str));
    2226       genop(s, MKOP_ABx(OP_GETGLOBAL, cursp(), sym));
     2412      genop_2(s, OP_GETGV, cursp(), sym);
    22272413      push();
    22282414    }
     
    22342420
    22352421  case NODE_BLOCK_ARG:
    2236     codegen(s, tree, VAL);
     2422    codegen(s, tree, val);
    22372423    break;
    22382424
     
    22402426    if (val) {
    22412427      char *p = (char*)tree->car;
    2242       int base = (intptr_t)tree->cdr->car;
     2428      int base = nint(tree->cdr->car);
    22432429      mrb_int i;
    2244       mrb_code co;
    22452430      mrb_bool overflow;
    22462431
    22472432      i = readint_mrb_int(s, p, base, FALSE, &overflow);
     2433#ifndef MRB_WITHOUT_FLOAT
    22482434      if (overflow) {
    22492435        double f = readint_float(s, p, base);
    22502436        int off = new_lit(s, mrb_float_value(s->mrb, f));
    22512437
    2252         genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
    2253       }
    2254       else {
    2255         if (i < MAXARG_sBx && i > -MAXARG_sBx) {
    2256           co = MKOP_AsBx(OP_LOADI, cursp(), i);
    2257         }
     2438        genop_2(s, OP_LOADL, cursp(), off);
     2439      }
     2440      else
     2441#endif
     2442      {
     2443        if (i == -1) genop_1(s, OP_LOADI__1, cursp());
     2444        else if (i < 0) genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
     2445        else if (i < 8) genop_1(s, OP_LOADI_0 + (uint8_t)i, cursp());
     2446        else if (i <= 0xffff) genop_2(s, OP_LOADI, cursp(), (uint16_t)i);
    22582447        else {
    22592448          int off = new_lit(s, mrb_fixnum_value(i));
    2260           co = MKOP_ABx(OP_LOADL, cursp(), off);
    2261         }
    2262         genop(s, co);
     2449          genop_2(s, OP_LOADL, cursp(), off);
     2450        }
    22632451      }
    22642452      push();
     
    22662454    break;
    22672455
     2456#ifndef MRB_WITHOUT_FLOAT
    22682457  case NODE_FLOAT:
    22692458    if (val) {
     
    22722461      int off = new_lit(s, mrb_float_value(s->mrb, f));
    22732462
    2274       genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
     2463      genop_2(s, OP_LOADL, cursp(), off);
    22752464      push();
    22762465    }
    22772466    break;
     2467#endif
    22782468
    22792469  case NODE_NEGATE:
    22802470    {
    2281       nt = (intptr_t)tree->car;
    2282       tree = tree->cdr;
     2471      nt = nint(tree->car);
    22832472      switch (nt) {
     2473#ifndef MRB_WITHOUT_FLOAT
    22842474      case NODE_FLOAT:
    22852475        if (val) {
    2286           char *p = (char*)tree;
     2476          char *p = (char*)tree->cdr;
    22872477          mrb_float f = mrb_float_read(p, NULL);
    22882478          int off = new_lit(s, mrb_float_value(s->mrb, -f));
    22892479
    2290           genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
     2480          genop_2(s, OP_LOADL, cursp(), off);
    22912481          push();
    22922482        }
    22932483        break;
     2484#endif
    22942485
    22952486      case NODE_INT:
    22962487        if (val) {
    2297           char *p = (char*)tree->car;
    2298           int base = (intptr_t)tree->cdr->car;
     2488          char *p = (char*)tree->cdr->car;
     2489          int base = nint(tree->cdr->cdr->car);
    22992490          mrb_int i;
    2300           mrb_code co;
    23012491          mrb_bool overflow;
    23022492
    23032493          i = readint_mrb_int(s, p, base, TRUE, &overflow);
     2494#ifndef MRB_WITHOUT_FLOAT
    23042495          if (overflow) {
    23052496            double f = readint_float(s, p, base);
    23062497            int off = new_lit(s, mrb_float_value(s->mrb, -f));
    23072498
    2308             genop(s, MKOP_ABx(OP_LOADL, cursp(), off));
     2499            genop_2(s, OP_LOADL, cursp(), off);
    23092500          }
    23102501          else {
    2311             if (i < MAXARG_sBx && i > -MAXARG_sBx) {
    2312               co = MKOP_AsBx(OP_LOADI, cursp(), i);
     2502#endif
     2503            if (i == -1) genop_1(s, OP_LOADI__1, cursp());
     2504            else if (i >= -0xffff) {
     2505              genop_2(s, OP_LOADINEG, cursp(), (uint16_t)-i);
    23132506            }
    23142507            else {
    23152508              int off = new_lit(s, mrb_fixnum_value(i));
    2316               co = MKOP_ABx(OP_LOADL, cursp(), off);
     2509              genop_2(s, OP_LOADL, cursp(), off);
    23172510            }
    2318             genop(s, co);
    2319           }
     2511#ifndef MRB_WITHOUT_FLOAT
     2512          }
     2513#endif
    23202514          push();
    23212515        }
     
    23242518      default:
    23252519        if (val) {
    2326           int sym = new_msym(s, mrb_intern_lit(s->mrb, "-"));
    2327 
    2328           genop(s, MKOP_ABx(OP_LOADI, cursp(), 0));
     2520          int sym = new_sym(s, mrb_intern_lit(s->mrb, "-@"));
     2521          codegen(s, tree, VAL);
     2522          pop();
     2523          genop_3(s, OP_SEND, cursp(), sym, 0);
    23292524          push();
    2330           codegen(s, tree, VAL);
    2331           pop(); pop();
    2332           genop(s, MKOP_ABC(OP_SUB, cursp(), sym, 2));
    23332525        }
    23342526        else {
     
    23482540
    23492541      mrb_gc_arena_restore(s->mrb, ai);
    2350       genop(s, MKOP_ABx(OP_STRING, cursp(), off));
     2542      genop_2(s, OP_STRING, cursp(), off);
    23512543      push();
    23522544    }
     
    23612553
    23622554      if (!n) {
    2363         genop(s, MKOP_A(OP_LOADNIL, cursp()));
     2555        genop_1(s, OP_LOADNIL, cursp());
    23642556        push();
    23652557        break;
     
    23702562        codegen(s, n->car, VAL);
    23712563        pop(); pop();
    2372         genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
     2564        genop_1(s, OP_STRCAT, cursp());
    23732565        push();
    23742566        n = n->cdr;
     
    23792571
    23802572      while (n) {
    2381         if ((intptr_t)n->car->car != NODE_STR) {
     2573        if (nint(n->car->car) != NODE_STR) {
    23822574          codegen(s, n->car, NOVAL);
    23832575        }
     
    24012593      int sym = new_sym(s, mrb_intern_lit(s->mrb, "Kernel"));
    24022594
    2403       genop(s, MKOP_A(OP_LOADSELF, cursp()));
     2595      genop_1(s, OP_LOADSELF, cursp());
    24042596      push();
    24052597      codegen(s, tree->car, VAL);
    24062598      n = tree->cdr;
    24072599      while (n) {
    2408         if ((intptr_t)n->car->car == NODE_XSTR) {
     2600        if (nint(n->car->car) == NODE_XSTR) {
    24092601          n->car->car = (struct mrb_ast_node*)(intptr_t)NODE_STR;
    24102602          mrb_assert(!n->cdr); /* must be the end */
     
    24122604        codegen(s, n->car, VAL);
    24132605        pop(); pop();
    2414         genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
     2606        genop_1(s, OP_STRCAT, cursp());
    24152607        push();
    24162608        n = n->cdr;
     
    24192611      pop_n(3);
    24202612      sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
    2421       genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
     2613      genop_3(s, OP_SEND, cursp(), sym, 1);
    24222614      if (val) push();
    24232615      mrb_gc_arena_restore(s->mrb, ai);
     
    24332625      int sym;
    24342626
    2435       genop(s, MKOP_A(OP_LOADSELF, cursp()));
     2627      genop_1(s, OP_LOADSELF, cursp());
    24362628      push();
    2437       genop(s, MKOP_ABx(OP_STRING, cursp(), off));
     2629      genop_2(s, OP_STRING, cursp(), off);
    24382630      push(); push();
    24392631      pop_n(3);
    24402632      sym = new_sym(s, mrb_intern_lit(s->mrb, "`"));
    2441       genop(s, MKOP_ABC(OP_SEND, cursp(), sym, 1));
     2633      genop_3(s, OP_SEND, cursp(), sym, 1);
    24422634      if (val) push();
    24432635      mrb_gc_arena_restore(s->mrb, ai);
     
    24552647      int argc = 1;
    24562648
    2457       genop(s, MKOP_A(OP_OCLASS, cursp()));
    2458       genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
     2649      genop_1(s, OP_OCLASS, cursp());
     2650      genop_2(s, OP_GETMCNST, cursp(), sym);
    24592651      push();
    2460       genop(s, MKOP_ABx(OP_STRING, cursp(), off));
     2652      genop_2(s, OP_STRING, cursp(), off);
     2653      push();
    24612654      if (p2 || p3) {
     2655        if (p2) { /* opt */
     2656          off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
     2657          genop_2(s, OP_STRING, cursp(), off);
     2658        }
     2659        else {
     2660          genop_1(s, OP_LOADNIL, cursp());
     2661        }
    24622662        push();
    2463         if (p2) {
    2464           off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
    2465           genop(s, MKOP_ABx(OP_STRING, cursp(), off));
    2466         }
    2467         else {
    2468           genop(s, MKOP_A(OP_LOADNIL, cursp()));
    2469         }
    24702663        argc++;
    2471         if (p3) {
     2664        if (p3) { /* enc */
     2665          off = new_lit(s, mrb_str_new(s->mrb, p3, 1));
     2666          genop_2(s, OP_STRING, cursp(), off);
    24722667          push();
    2473           off = new_lit(s, mrb_str_new(s->mrb, p3, 1));
    2474           genop(s, MKOP_ABx(OP_STRING, cursp(), off));
    24752668          argc++;
    2476           pop();
    2477         }
    2478         pop();
    2479       }
    2480       pop();
     2669        }
     2670      }
     2671      push(); /* space for a block */
     2672      pop_n(argc+2);
    24812673      sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
    2482       genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
     2674      genop_3(s, OP_SEND, cursp(), sym, argc);
    24832675      mrb_gc_arena_restore(s->mrb, ai);
    24842676      push();
     
    24952687      char *p;
    24962688
    2497       genop(s, MKOP_A(OP_OCLASS, cursp()));
    2498       genop(s, MKOP_ABx(OP_GETMCNST, cursp(), sym));
     2689      genop_1(s, OP_OCLASS, cursp());
     2690      genop_2(s, OP_GETMCNST, cursp(), sym);
    24992691      push();
    25002692      codegen(s, n->car, VAL);
     
    25032695        codegen(s, n->car, VAL);
    25042696        pop(); pop();
    2505         genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
     2697        genop_1(s, OP_STRCAT, cursp());
    25062698        push();
    25072699        n = n->cdr;
    25082700      }
    25092701      n = tree->cdr->cdr;
    2510       if (n->car) {
     2702      if (n->car) { /* tail */
    25112703        p = (char*)n->car;
    25122704        off = new_lit(s, mrb_str_new_cstr(s->mrb, p));
    25132705        codegen(s, tree->car, VAL);
    2514         genop(s, MKOP_ABx(OP_STRING, cursp(), off));
     2706        genop_2(s, OP_STRING, cursp(), off);
    25152707        pop();
    2516         genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
    2517       }
    2518       if (n->cdr->car) {
     2708        genop_1(s, OP_STRCAT, cursp());
     2709        push();
     2710      }
     2711      if (n->cdr->car) { /* opt */
    25192712        char *p2 = (char*)n->cdr->car;
    2520 
     2713        off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
     2714        genop_2(s, OP_STRING, cursp(), off);
    25212715        push();
     2716        argc++;
     2717      }
     2718      if (n->cdr->cdr) { /* enc */
     2719        char *p2 = (char*)n->cdr->cdr;
    25222720        off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
    2523         genop(s, MKOP_ABx(OP_STRING, cursp(), off));
     2721        genop_2(s, OP_STRING, cursp(), off);
     2722        push();
    25242723        argc++;
    25252724      }
    2526       if (n->cdr->cdr) {
    2527         char *p2 = (char*)n->cdr->cdr;
    2528 
    2529         push();
    2530         off = new_lit(s, mrb_str_new_cstr(s->mrb, p2));
    2531         genop(s, MKOP_ABx(OP_STRING, cursp(), off));
    2532         argc++;
    2533       }
    2534       pop_n(argc);
     2725      push(); /* space for a block */
     2726      pop_n(argc+2);
    25352727      sym = new_sym(s, mrb_intern_lit(s->mrb, "compile"));
    2536       genop(s, MKOP_ABC(OP_SEND, cursp(), sym, argc));
     2728      genop_3(s, OP_SEND, cursp(), sym, argc);
    25372729      mrb_gc_arena_restore(s->mrb, ai);
    25382730      push();
     
    25422734
    25432735      while (n) {
    2544         if ((intptr_t)n->car->car != NODE_STR) {
     2736        if (nint(n->car->car) != NODE_STR) {
    25452737          codegen(s, n->car, NOVAL);
    25462738        }
     
    25522744  case NODE_SYM:
    25532745    if (val) {
    2554       int sym = new_sym(s, sym(tree));
    2555 
    2556       genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
     2746      int sym = new_sym(s, nsym(tree));
     2747
     2748      genop_2(s, OP_LOADSYM, cursp(), sym);
    25572749      push();
    25582750    }
     
    25622754    codegen(s, tree, val);
    25632755    if (val) {
    2564       gen_send_intern(s);
     2756      gen_intern(s);
    25652757    }
    25662758    break;
     
    25682760  case NODE_SELF:
    25692761    if (val) {
    2570       genop(s, MKOP_A(OP_LOADSELF, cursp()));
     2762      genop_1(s, OP_LOADSELF, cursp());
    25712763      push();
    25722764    }
     
    25752767  case NODE_NIL:
    25762768    if (val) {
    2577       genop(s, MKOP_A(OP_LOADNIL, cursp()));
     2769      genop_1(s, OP_LOADNIL, cursp());
    25782770      push();
    25792771    }
     
    25822774  case NODE_TRUE:
    25832775    if (val) {
    2584       genop(s, MKOP_A(OP_LOADT, cursp()));
     2776      genop_1(s, OP_LOADT, cursp());
    25852777      push();
    25862778    }
     
    25892781  case NODE_FALSE:
    25902782    if (val) {
    2591       genop(s, MKOP_A(OP_LOADF, cursp()));
     2783      genop_1(s, OP_LOADF, cursp());
    25922784      push();
    25932785    }
     
    25962788  case NODE_ALIAS:
    25972789    {
    2598       int a = new_msym(s, sym(tree->car));
    2599       int b = new_msym(s, sym(tree->cdr));
    2600       int c = new_msym(s, mrb_intern_lit(s->mrb, "alias_method"));
    2601 
    2602       genop(s, MKOP_A(OP_TCLASS, cursp()));
    2603       push();
    2604       genop(s, MKOP_ABx(OP_LOADSYM, cursp(), a));
    2605       push();
    2606       genop(s, MKOP_ABx(OP_LOADSYM, cursp(), b));
    2607       push();
    2608       genop(s, MKOP_A(OP_LOADNIL, cursp()));
    2609       push();
    2610       pop_n(4);
    2611       genop(s, MKOP_ABC(OP_SEND, cursp(), c, 2));
     2790      int a = new_sym(s, nsym(tree->car));
     2791      int b = new_sym(s, nsym(tree->cdr));
     2792
     2793      genop_2(s, OP_ALIAS, a, b);
    26122794      if (val) {
     2795        genop_1(s, OP_LOADNIL, cursp());
    26132796        push();
    26142797      }
     
    26182801  case NODE_UNDEF:
    26192802    {
    2620       int undef = new_msym(s, mrb_intern_lit(s->mrb, "undef_method"));
    2621       int num = 0;
    26222803      node *t = tree;
    26232804
    2624       genop(s, MKOP_A(OP_TCLASS, cursp()));
    2625       push();
    26262805      while (t) {
    2627         int symbol;
    2628         if (num >= CALL_MAXARGS - 1) {
    2629           pop_n(num);
    2630           genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), num));
    2631           while (t) {
    2632             symbol = new_msym(s, sym(t->car));
    2633             push();
    2634             genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
    2635             pop();
    2636             genop(s, MKOP_AB(OP_ARYPUSH, cursp(), cursp()+1));
    2637             t = t->cdr;
    2638           }
    2639           num = CALL_MAXARGS;
    2640           break;
    2641         }
    2642         symbol = new_msym(s, sym(t->car));
    2643         genop(s, MKOP_ABx(OP_LOADSYM, cursp(), symbol));
    2644         push();
     2806        int symbol = new_sym(s, nsym(t->car));
     2807        genop_1(s, OP_UNDEF, symbol);
    26452808        t = t->cdr;
    2646         num++;
    2647       }
    2648       pop();
    2649       if (num < CALL_MAXARGS) {
    2650         pop_n(num);
    2651       }
    2652       genop(s, MKOP_ABC(OP_SEND, cursp(), undef, num));
     2809      }
    26532810      if (val) {
     2811        genop_1(s, OP_LOADNIL, cursp());
    26542812        push();
    26552813      }
     
    26602818    {
    26612819      int idx;
     2820      node *body;
    26622821
    26632822      if (tree->car->car == (node*)0) {
    2664         genop(s, MKOP_A(OP_LOADNIL, cursp()));
     2823        genop_1(s, OP_LOADNIL, cursp());
    26652824        push();
    26662825      }
    26672826      else if (tree->car->car == (node*)1) {
    2668         genop(s, MKOP_A(OP_OCLASS, cursp()));
     2827        genop_1(s, OP_OCLASS, cursp());
    26692828        push();
    26702829      }
     
    26762835      }
    26772836      else {
    2678         genop(s, MKOP_A(OP_LOADNIL, cursp()));
     2837        genop_1(s, OP_LOADNIL, cursp());
    26792838        push();
    26802839      }
    26812840      pop(); pop();
    2682       idx = new_msym(s, sym(tree->car->cdr));
    2683       genop(s, MKOP_AB(OP_CLASS, cursp(), idx));
    2684       idx = scope_body(s, tree->cdr->cdr->car, val);
    2685       genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
     2841      idx = new_sym(s, nsym(tree->car->cdr));
     2842      genop_2(s, OP_CLASS, cursp(), idx);
     2843      body = tree->cdr->cdr->car;
     2844      if (nint(body->cdr->car) == NODE_BEGIN && body->cdr->cdr == NULL) {
     2845        genop_1(s, OP_LOADNIL, cursp());
     2846      }
     2847      else {
     2848        idx = scope_body(s, body, val);
     2849        genop_2(s, OP_EXEC, cursp(), idx);
     2850      }
    26862851      if (val) {
    26872852        push();
     
    26952860
    26962861      if (tree->car->car == (node*)0) {
    2697         genop(s, MKOP_A(OP_LOADNIL, cursp()));
     2862        genop_1(s, OP_LOADNIL, cursp());
    26982863        push();
    26992864      }
    27002865      else if (tree->car->car == (node*)1) {
    2701         genop(s, MKOP_A(OP_OCLASS, cursp()));
     2866        genop_1(s, OP_OCLASS, cursp());
    27022867        push();
    27032868      }
     
    27062871      }
    27072872      pop();
    2708       idx = new_msym(s, sym(tree->car->cdr));
    2709       genop(s, MKOP_AB(OP_MODULE, cursp(), idx));
    2710       idx = scope_body(s, tree->cdr->car, val);
    2711       genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
     2873      idx = new_sym(s, nsym(tree->car->cdr));
     2874      genop_2(s, OP_MODULE, cursp(), idx);
     2875      if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
     2876          tree->cdr->car->cdr->cdr == NULL) {
     2877        genop_1(s, OP_LOADNIL, cursp());
     2878      }
     2879      else {
     2880        idx = scope_body(s, tree->cdr->car, val);
     2881        genop_2(s, OP_EXEC, cursp(), idx);
     2882      }
    27122883      if (val) {
    27132884        push();
     
    27222893      codegen(s, tree->car, VAL);
    27232894      pop();
    2724       genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
    2725       idx = scope_body(s, tree->cdr->car, val);
    2726       genop(s, MKOP_ABx(OP_EXEC, cursp(), idx));
     2895      genop_1(s, OP_SCLASS, cursp());
     2896      if (nint(tree->cdr->car->cdr->car) == NODE_BEGIN &&
     2897          tree->cdr->car->cdr->cdr == NULL) {
     2898        genop_1(s, OP_LOADNIL, cursp());
     2899      }
     2900      else {
     2901        idx = scope_body(s, tree->cdr->car, val);
     2902        genop_2(s, OP_EXEC, cursp(), idx);
     2903      }
    27272904      if (val) {
    27282905        push();
     
    27332910  case NODE_DEF:
    27342911    {
    2735       int sym = new_msym(s, sym(tree->car));
     2912      int sym = new_sym(s, nsym(tree->car));
    27362913      int idx = lambda_body(s, tree->cdr, 0);
    27372914
    2738       genop(s, MKOP_A(OP_TCLASS, cursp()));
     2915      genop_1(s, OP_TCLASS, cursp());
    27392916      push();
    2740       genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
     2917      genop_2(s, OP_METHOD, cursp(), idx);
    27412918      push(); pop();
    27422919      pop();
    2743       genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
     2920      genop_2(s, OP_DEF, cursp(), sym);
    27442921      if (val) {
    2745         genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
     2922        genop_2(s, OP_LOADSYM, cursp(), sym);
    27462923        push();
    27472924      }
     
    27522929    {
    27532930      node *recv = tree->car;
    2754       int sym = new_msym(s, sym(tree->cdr->car));
     2931      int sym = new_sym(s, nsym(tree->cdr->car));
    27552932      int idx = lambda_body(s, tree->cdr->cdr, 0);
    27562933
    27572934      codegen(s, recv, VAL);
    27582935      pop();
    2759       genop(s, MKOP_AB(OP_SCLASS, cursp(), cursp()));
     2936      genop_1(s, OP_SCLASS, cursp());
    27602937      push();
    2761       genop(s, MKOP_Abc(OP_LAMBDA, cursp(), idx, OP_L_METHOD));
     2938      genop_2(s, OP_METHOD, cursp(), idx);
    27622939      pop();
    2763       genop(s, MKOP_AB(OP_METHOD, cursp(), sym));
     2940      genop_2(s, OP_DEF, cursp(), sym);
    27642941      if (val) {
    2765         genop(s, MKOP_ABx(OP_LOADSYM, cursp(), sym));
     2942        genop_2(s, OP_LOADSYM, cursp(), sym);
    27662943        push();
    27672944      }
     
    28022979  codegen_scope *p = (codegen_scope *)mrb_pool_alloc(pool, sizeof(codegen_scope));
    28032980
    2804   if (!p) return NULL;
     2981  if (!p) {
     2982    if (prev)
     2983      codegen_error(prev, "unexpected scope");
     2984    return NULL;
     2985  }
    28052986  *p = codegen_scope_zero;
    28062987  p->mrb = mrb;
     
    28253006  p->irep->plen = 0;
    28263007
    2827   p->scapa = MAXMSYMLEN;
     3008  p->scapa = 256;
    28283009  p->irep->syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym)*p->scapa);
    28293010  p->irep->slen = 0;
     
    28503031  p->ai = mrb_gc_arena_save(mrb);
    28513032
    2852   p->filename = prev->filename;
    2853   if (p->filename) {
     3033  p->filename_sym = prev->filename_sym;
     3034  if (p->filename_sym) {
    28543035    p->lines = (uint16_t*)mrb_malloc(mrb, sizeof(short)*p->icapa);
    28553036  }
     
    28583039  /* debug setting */
    28593040  p->debug_start_pos = 0;
    2860   if (p->filename) {
     3041  if (p->filename_sym) {
    28613042    mrb_debug_info_alloc(mrb, p->irep);
    2862     p->irep->filename = p->filename;
    2863     p->irep->lines = p->lines;
    28643043  }
    28653044  else {
     
    28793058  mrb_state *mrb = s->mrb;
    28803059  mrb_irep *irep = s->irep;
    2881   size_t fname_len;
    2882   char *fname;
    2883 
     3060
     3061  if (s->nlocals >= 0x3ff) {
     3062    codegen_error(s, "too many local variables");
     3063  }
    28843064  irep->flags = 0;
    28853065  if (s->iseq) {
    28863066    irep->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->pc);
    28873067    irep->ilen = s->pc;
    2888     if (s->lines) {
    2889       irep->lines = (uint16_t *)codegen_realloc(s, s->lines, sizeof(uint16_t)*s->pc);
    2890     }
    2891     else {
    2892       irep->lines = 0;
    2893     }
    28943068  }
    28953069  irep->pool = (mrb_value*)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen);
    28963070  irep->syms = (mrb_sym*)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen);
    28973071  irep->reps = (mrb_irep**)codegen_realloc(s, irep->reps, sizeof(mrb_irep*)*irep->rlen);
    2898   if (s->filename) {
    2899     irep->filename = mrb_parser_get_filename(s->parser, s->filename_index);
    2900     mrb_debug_info_append_file(mrb, irep, s->debug_start_pos, s->pc);
    2901 
    2902     fname_len = strlen(s->filename);
    2903     fname = (char*)codegen_malloc(s, fname_len + 1);
    2904     memcpy(fname, s->filename, fname_len);
    2905     fname[fname_len] = '\0';
    2906     irep->filename = fname;
    2907     irep->own_filename = TRUE;
    2908   }
     3072  if (s->filename_sym) {
     3073    mrb_sym fname = mrb_parser_get_filename(s->parser, s->filename_index);
     3074    const char *filename = mrb_sym_name_len(s->mrb, fname, NULL);
     3075
     3076    mrb_debug_info_append_file(s->mrb, s->irep->debug_info,
     3077                               filename, s->lines, s->debug_start_pos, s->pc);
     3078  }
     3079  mrb_free(s->mrb, s->lines);
    29093080
    29103081  irep->nlocals = s->nlocals;
     
    29213092
    29223093  p->type = t;
    2923   p->pc1 = p->pc2 = p->pc3 = 0;
     3094  p->pc0 = p->pc1 = p->pc2 = p->pc3 = 0;
    29243095  p->prev = s->loop;
    29253096  p->ensure_level = s->ensure_level;
     
    29393110  else {
    29403111    struct loopinfo *loop;
     3112    int n = 0;
    29413113
    29423114    if (tree) {
     
    29453117
    29463118    loop = s->loop;
    2947     while (loop && loop->type == LOOP_BEGIN) {
    2948       genop_peep(s, MKOP_A(OP_POPERR, 1), NOVAL);
    2949       loop = loop->prev;
    2950     }
    2951     while (loop && loop->type == LOOP_RESCUE) {
    2952       loop = loop->prev;
     3119    while (loop) {
     3120      if (loop->type == LOOP_BEGIN) {
     3121        n++;
     3122        loop = loop->prev;
     3123      }
     3124      else if (loop->type == LOOP_RESCUE) {
     3125        loop = loop->prev;
     3126      }
     3127      else{
     3128        break;
     3129      }
    29533130    }
    29543131    if (!loop) {
     
    29563133      return;
    29573134    }
     3135    if (n > 0) {
     3136      genop_1(s, OP_POPERR, n);
     3137    }
    29583138
    29593139    if (loop->type == LOOP_NORMAL) {
     
    29613141
    29623142      if (s->ensure_level > s->loop->ensure_level) {
    2963         genop_peep(s, MKOP_A(OP_EPOP, s->ensure_level - s->loop->ensure_level), NOVAL);
     3143        genop_1(s, OP_EPOP, s->ensure_level - s->loop->ensure_level);
    29643144      }
    29653145      if (tree) {
    2966         genop_peep(s, MKOP_AB(OP_MOVE, loop->acc, cursp()), NOVAL);
    2967       }
    2968       tmp = genop(s, MKOP_sBx(OP_JMP, loop->pc3));
     3146        gen_move(s, loop->acc, cursp(), 0);
     3147      }
     3148      tmp = genjmp(s, OP_JMP, loop->pc3);
    29693149      loop->pc3 = tmp;
    29703150    }
    29713151    else {
    29723152      if (!tree) {
    2973         genop(s, MKOP_A(OP_LOADNIL, cursp()));
    2974       }
    2975       genop(s, MKOP_AB(OP_RETURN, cursp(), OP_R_BREAK));
     3153        genop_1(s, OP_LOADNIL, cursp());
     3154      }
     3155      gen_return(s, OP_BREAK, cursp());
    29763156    }
    29773157  }
     
    29813161loop_pop(codegen_scope *s, int val)
    29823162{
     3163  if (val) {
     3164    genop_1(s, OP_LOADNIL, cursp());
     3165  }
    29833166  dispatch_linked(s, s->loop->pc3);
    2984   if (val) {
    2985     genop(s, MKOP_A(OP_LOADNIL, cursp()));
    2986   }
    29873167  s->loop = s->loop->prev;
    29883168  if (val) push();
    29893169}
    29903170
    2991 MRB_API struct RProc*
    2992 mrb_generate_code(mrb_state *mrb, parser_state *p)
     3171static struct RProc*
     3172generate_code(mrb_state *mrb, parser_state *p, int val)
    29933173{
    29943174  codegen_scope *scope = scope_new(mrb, 0, 0);
     
    29963176  struct mrb_jmpbuf *prev_jmp = mrb->jmp;
    29973177
    2998   if (!scope) {
    2999     return NULL;
    3000   }
    30013178  scope->mrb = mrb;
    30023179  scope->parser = p;
    3003   scope->filename = p->filename;
     3180  scope->filename_sym = p->filename_sym;
    30043181  scope->filename_index = p->current_filename_index;
    30053182
    30063183  MRB_TRY(&scope->jmp) {
    3007     mrb->jmp = &scope->jmp; 
     3184    mrb->jmp = &scope->jmp;
    30083185    /* prepare irep */
    3009     codegen(scope, p->tree, NOVAL);
     3186    codegen(scope, p->tree, val);
    30103187    proc = mrb_proc_new(mrb, scope->irep);
    30113188    mrb_irep_decref(mrb, scope->irep);
    30123189    mrb_pool_close(scope->mpool);
    30133190    proc->c = NULL;
     3191    if (mrb->c->cibase && mrb->c->cibase->proc == proc->upper) {
     3192      proc->upper = NULL;
     3193    }
    30143194    mrb->jmp = prev_jmp;
    30153195    return proc;
     
    30233203  MRB_END_EXC(&scope->jmp);
    30243204}
     3205
     3206MRB_API struct RProc*
     3207mrb_generate_code(mrb_state *mrb, parser_state *p)
     3208{
     3209  return generate_code(mrb, p, VAL);
     3210}
     3211
     3212void
     3213mrb_irep_remove_lv(mrb_state *mrb, mrb_irep *irep)
     3214{
     3215  int i;
     3216
     3217  if (irep->lv) {
     3218    mrb_free(mrb, irep->lv);
     3219    irep->lv = NULL;
     3220  }
     3221
     3222  for (i = 0; i < irep->rlen; ++i) {
     3223    mrb_irep_remove_lv(mrb, irep->reps[i]);
     3224  }
     3225}
     3226
     3227#undef OPCODE
     3228#define Z 1
     3229#define S 3
     3230#define W 4
     3231/* instruction sizes */
     3232uint8_t mrb_insn_size[] = {
     3233#define B 2
     3234#define BB 3
     3235#define BBB 4
     3236#define BS 4
     3237#define SB 4
     3238#define OPCODE(_,x) x,
     3239#include "mruby/ops.h"
     3240#undef OPCODE
     3241#undef B
     3242#undef BB
     3243#undef BS
     3244#undef SB
     3245#undef BBB
     3246};
     3247/* EXT1 instruction sizes */
     3248uint8_t mrb_insn_size1[] = {
     3249#define B 3
     3250#define BB 4
     3251#define BBB 5
     3252#define BS 5
     3253#define SB 5
     3254#define OPCODE(_,x) x,
     3255#include "mruby/ops.h"
     3256#undef OPCODE
     3257#undef B
     3258};
     3259/* EXT2 instruction sizes */
     3260uint8_t mrb_insn_size2[] = {
     3261#define B 2
     3262#define OPCODE(_,x) x,
     3263#include "mruby/ops.h"
     3264#undef OPCODE
     3265#undef BB
     3266#undef BBB
     3267#undef BS
     3268#undef SB
     3269};
     3270/* EXT3 instruction sizes */
     3271#define BB 5
     3272#define BBB 6
     3273#define BS 4
     3274#define SB 5
     3275uint8_t mrb_insn_size3[] = {
     3276#define OPCODE(_,x) x,
     3277#include "mruby/ops.h"
     3278};
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-compiler/core/keywords

    r270 r439  
    11%{
    22struct kwtable {const char *name; int id[2]; enum mrb_lex_state_enum state;};
    3 const struct kwtable *mrb_reserved_word(const char *, unsigned int);
    4 static const struct kwtable *reserved_word(const char *, unsigned int);
    5 #define mrb_reserved_word(str, len) reserved_word(str, len)
    63%}
    74
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-compiler/core/lex.def

    r331 r439  
    1 /* ANSI-C code produced by gperf version 3.0.4 */
     1/* ANSI-C code produced by gperf version 3.1 */
    22/* Command-line: gperf -L ANSI-C -C -p -j1 -i 1 -g -o -t -N mrb_reserved_word -k'1,3,$' /home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords  */
    33
     
    2626      && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
    2727/* The character set is not based on ISO-646.  */
    28 #error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
     28#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>."
    2929#endif
    3030
     
    3232
    3333struct kwtable {const char *name; int id[2]; enum mrb_lex_state_enum state;};
    34 const struct kwtable *mrb_reserved_word(const char *, unsigned int);
    35 static const struct kwtable *reserved_word(const char *, unsigned int);
    36 #define mrb_reserved_word(str, len) reserved_word(str, len)
    37 #line 8 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     34#line 5 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    3835struct kwtable;
    3936
     
    5350#endif
    5451static unsigned int
    55 hash (register const char *str, register unsigned int len)
     52hash (register const char *str, register size_t len)
    5653{
    5754  static const unsigned char asso_values[] =
     
    8481      51, 51, 51, 51, 51, 51
    8582    };
    86   register int hval = len;
     83  register unsigned int hval = len;
    8784
    8885  switch (hval)
     
    9996}
    10097
    101 #ifdef __GNUC__
    102 __inline
    103 #if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
    104 __attribute__ ((__gnu_inline__))
    105 #endif
    106 #endif
    10798const struct kwtable *
    108 mrb_reserved_word (register const char *str, register unsigned int len)
     99mrb_reserved_word (register const char *str, register size_t len)
    109100{
    110101  static const struct kwtable wordlist[] =
    111102    {
    112103      {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
     104#line 15 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     105      {"break",        {keyword_break,       keyword_break},       EXPR_MID},
     106#line 20 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     107      {"else",         {keyword_else,        keyword_else},        EXPR_BEG},
     108#line 30 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     109      {"nil",          {keyword_nil,         keyword_nil},         EXPR_END},
     110#line 23 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     111      {"ensure",       {keyword_ensure,      keyword_ensure},      EXPR_BEG},
     112#line 22 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     113      {"end",          {keyword_end,         keyword_end},         EXPR_END},
     114#line 39 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     115      {"then",         {keyword_then,        keyword_then},        EXPR_BEG},
     116#line 31 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     117      {"not",          {keyword_not,         keyword_not},         EXPR_ARG},
     118#line 24 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     119      {"false",        {keyword_false,       keyword_false},       EXPR_END},
     120#line 37 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     121      {"self",         {keyword_self,        keyword_self},        EXPR_END},
     122#line 21 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     123      {"elsif",        {keyword_elsif,       keyword_elsif},       EXPR_VALUE},
     124#line 34 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     125      {"rescue",       {keyword_rescue,      modifier_rescue},     EXPR_MID},
     126#line 40 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     127      {"true",         {keyword_true,        keyword_true},        EXPR_END},
     128#line 43 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     129      {"until",        {keyword_until,       modifier_until},      EXPR_VALUE},
     130#line 42 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     131      {"unless",       {keyword_unless,      modifier_unless},     EXPR_VALUE},
     132#line 36 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     133      {"return",       {keyword_return,      keyword_return},      EXPR_MID},
    113134#line 18 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    114       {"break",        {keyword_break,       keyword_break},       EXPR_MID},
    115 #line 23 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    116       {"else",         {keyword_else,        keyword_else},        EXPR_BEG},
     135      {"def",          {keyword_def,         keyword_def},         EXPR_FNAME},
     136#line 13 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     137      {"and",          {keyword_and,         keyword_and},         EXPR_VALUE},
     138#line 19 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     139      {"do",           {keyword_do,          keyword_do},          EXPR_BEG},
     140#line 46 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     141      {"yield",        {keyword_yield,       keyword_yield},       EXPR_ARG},
     142#line 25 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     143      {"for",          {keyword_for,         keyword_for},         EXPR_VALUE},
     144#line 41 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     145      {"undef",        {keyword_undef,       keyword_undef},       EXPR_FNAME},
     146#line 32 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     147      {"or",           {keyword_or,          keyword_or},          EXPR_VALUE},
     148#line 27 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     149      {"in",           {keyword_in,          keyword_in},          EXPR_VALUE},
     150#line 44 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     151      {"when",         {keyword_when,        keyword_when},        EXPR_VALUE},
     152#line 35 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     153      {"retry",        {keyword_retry,       keyword_retry},       EXPR_END},
     154#line 26 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     155      {"if",           {keyword_if,          modifier_if},         EXPR_VALUE},
     156#line 16 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     157      {"case",         {keyword_case,        keyword_case},        EXPR_VALUE},
    117158#line 33 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    118       {"nil",          {keyword_nil,         keyword_nil},         EXPR_END},
    119 #line 26 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    120       {"ensure",       {keyword_ensure,      keyword_ensure},      EXPR_BEG},
    121 #line 25 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    122       {"end",          {keyword_end,         keyword_end},         EXPR_END},
    123 #line 42 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    124       {"then",         {keyword_then,        keyword_then},        EXPR_BEG},
    125 #line 34 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    126       {"not",          {keyword_not,         keyword_not},         EXPR_ARG},
    127 #line 27 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    128       {"false",        {keyword_false,       keyword_false},       EXPR_END},
    129 #line 40 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    130       {"self",         {keyword_self,        keyword_self},        EXPR_END},
    131 #line 24 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    132       {"elsif",        {keyword_elsif,       keyword_elsif},       EXPR_VALUE},
    133 #line 37 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    134       {"rescue",       {keyword_rescue,      modifier_rescue},     EXPR_MID},
    135 #line 43 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    136       {"true",         {keyword_true,        keyword_true},        EXPR_END},
    137 #line 46 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    138       {"until",        {keyword_until,       modifier_until},      EXPR_VALUE},
    139 #line 45 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    140       {"unless",       {keyword_unless,      modifier_unless},     EXPR_VALUE},
    141 #line 39 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    142       {"return",       {keyword_return,      keyword_return},      EXPR_MID},
    143 #line 21 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    144       {"def",          {keyword_def,         keyword_def},         EXPR_FNAME},
    145 #line 16 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    146       {"and",          {keyword_and,         keyword_and},         EXPR_VALUE},
    147 #line 22 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    148       {"do",           {keyword_do,          keyword_do},          EXPR_BEG},
    149 #line 49 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    150       {"yield",        {keyword_yield,       keyword_yield},       EXPR_ARG},
     159      {"redo",         {keyword_redo,        keyword_redo},        EXPR_END},
     160#line 29 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     161      {"next",         {keyword_next,        keyword_next},        EXPR_MID},
     162#line 38 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     163      {"super",        {keyword_super,       keyword_super},       EXPR_ARG},
    151164#line 28 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    152       {"for",          {keyword_for,         keyword_for},         EXPR_VALUE},
    153 #line 44 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    154       {"undef",        {keyword_undef,       keyword_undef},       EXPR_FNAME},
    155 #line 35 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    156       {"or",           {keyword_or,          keyword_or},          EXPR_VALUE},
    157 #line 30 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    158       {"in",           {keyword_in,          keyword_in},          EXPR_VALUE},
    159 #line 47 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    160       {"when",         {keyword_when,        keyword_when},        EXPR_VALUE},
    161 #line 38 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    162       {"retry",        {keyword_retry,       keyword_retry},       EXPR_END},
    163 #line 29 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    164       {"if",           {keyword_if,          modifier_if},         EXPR_VALUE},
    165 #line 19 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    166       {"case",         {keyword_case,        keyword_case},        EXPR_VALUE},
    167 #line 36 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    168       {"redo",         {keyword_redo,        keyword_redo},        EXPR_END},
    169 #line 32 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    170       {"next",         {keyword_next,        keyword_next},        EXPR_MID},
    171 #line 41 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    172       {"super",        {keyword_super,       keyword_super},       EXPR_ARG},
    173 #line 31 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    174165      {"module",       {keyword_module,      keyword_module},      EXPR_VALUE},
    175 #line 17 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     166#line 14 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    176167      {"begin",        {keyword_begin,       keyword_begin},       EXPR_BEG},
     168#line 9 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     169      {"__LINE__",     {keyword__LINE__,     keyword__LINE__},     EXPR_END},
     170#line 8 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     171      {"__FILE__",     {keyword__FILE__,     keyword__FILE__},     EXPR_END},
     172#line 7 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     173      {"__ENCODING__", {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END},
     174#line 11 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     175      {"END",          {keyword_END,         keyword_END},         EXPR_END},
    177176#line 12 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    178       {"__LINE__",     {keyword__LINE__,     keyword__LINE__},     EXPR_END},
    179 #line 11 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    180       {"__FILE__",     {keyword__FILE__,     keyword__FILE__},     EXPR_END},
     177      {"alias",        {keyword_alias,       keyword_alias},       EXPR_FNAME},
    181178#line 10 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    182       {"__ENCODING__", {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END},
    183 #line 14 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    184       {"END",          {keyword_END,         keyword_END},         EXPR_END},
    185 #line 15 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    186       {"alias",        {keyword_alias,       keyword_alias},       EXPR_FNAME},
    187 #line 13 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    188179      {"BEGIN",        {keyword_BEGIN,       keyword_BEGIN},       EXPR_END},
    189180      {""},
    190 #line 20 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     181#line 17 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    191182      {"class",        {keyword_class,       keyword_class},       EXPR_CLASS},
    192183      {""}, {""},
    193 #line 48 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     184#line 45 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    194185      {"while",        {keyword_while,       modifier_while},      EXPR_VALUE}
    195186    };
     
    197188  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
    198189    {
    199       register int key = hash (str, len);
    200 
    201       if (key <= MAX_HASH_VALUE && key >= 0)
     190      register unsigned int key = hash (str, len);
     191
     192      if (key <= MAX_HASH_VALUE)
    202193        {
    203194          register const char *s = wordlist[key].name;
     
    209200  return 0;
    210201}
    211 #line 50 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
    212 
     202#line 47 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
     203
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-compiler/core/node.h

    r331 r439  
    1010enum node_type {
    1111  NODE_METHOD,
    12   NODE_FBODY,
    13   NODE_CFUNC,
    1412  NODE_SCOPE,
    1513  NODE_BLOCK,
     
    1715  NODE_CASE,
    1816  NODE_WHEN,
    19   NODE_OPT_N,
    2017  NODE_WHILE,
    2118  NODE_UNTIL,
     
    4138  NODE_SCALL,
    4239  NODE_FCALL,
    43   NODE_VCALL,
    4440  NODE_SUPER,
    4541  NODE_ZSUPER,
     
    4743  NODE_ZARRAY,
    4844  NODE_HASH,
     45  NODE_KW_HASH,
    4946  NODE_RETURN,
    5047  NODE_YIELD,
     
    5552  NODE_CONST,
    5653  NODE_CVAR,
     54  NODE_NVAR,
    5755  NODE_NTH_REF,
    5856  NODE_BACK_REF,
    5957  NODE_MATCH,
    60   NODE_MATCH2,
    61   NODE_MATCH3,
    6258  NODE_INT,
    6359  NODE_FLOAT,
     
    7268  NODE_DREGX,
    7369  NODE_DREGX_ONCE,
    74   NODE_LIST,
    7570  NODE_ARG,
    76   NODE_ARGSCAT,
    77   NODE_ARGSPUSH,
     71  NODE_ARGS_TAIL,
     72  NODE_KW_ARG,
     73  NODE_KW_REST_ARGS,
    7874  NODE_SPLAT,
    7975  NODE_TO_ARY,
     
    8985  NODE_COLON2,
    9086  NODE_COLON3,
    91   NODE_CREF,
    9287  NODE_DOT2,
    9388  NODE_DOT3,
    94   NODE_FLIP2,
    95   NODE_FLIP3,
    96   NODE_ATTRSET,
    9789  NODE_SELF,
    9890  NODE_NIL,
     
    10092  NODE_FALSE,
    10193  NODE_DEFINED,
    102   NODE_NEWLINE,
    10394  NODE_POSTEXE,
    104   NODE_ALLOCA,
    105   NODE_DMETHOD,
    106   NODE_BMETHOD,
    107   NODE_MEMO,
    108   NODE_IFUNC,
    10995  NODE_DSYM,
    110   NODE_ATTRASGN,
    11196  NODE_HEREDOC,
    11297  NODE_LITERAL_DELIM,
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-compiler/core/parse.y

    r331 r439  
    1111#endif
    1212#define YYERROR_VERBOSE 1
    13 /*
    14  * Force yacc to use our memory management.  This is a little evil because
    15  * the macros assume that "parser_state *p" is in scope
    16  */
    17 #define YYMALLOC(n)    mrb_malloc(p->mrb, (n))
    18 #define YYFREE(o)      mrb_free(p->mrb, (o))
    19 #define YYSTACK_USE_ALLOCA 0
     13#define YYSTACK_USE_ALLOCA 1
    2014
    2115#include <ctype.h>
     
    2822#include <mruby/error.h>
    2923#include <mruby/throw.h>
     24#include <mruby/string.h>
    3025#include "node.h"
    3126
     
    7772#define intn(x) ((int)(intptr_t)(x))
    7873
     74#define NUM_SUFFIX_R   (1<<0)
     75#define NUM_SUFFIX_I   (1<<1)
     76
    7977static inline mrb_sym
    8078intern_cstr_gen(parser_state *p, const char *s)
     
    9189#define intern(s,len) intern_gen(p,(s),(len))
    9290
    93 static inline mrb_sym
    94 intern_gen_c(parser_state *p, const char c)
    95 {
    96   return mrb_intern(p->mrb, &c, 1);
    97 }
    98 #define intern_c(c) intern_gen_c(p,(c))
     91#define intern_lit(s) mrb_intern_lit(p->mrb, s)
    9992
    10093static void
     
    134127  c->lineno = p->lineno;
    135128  c->filename_index = p->current_filename_index;
     129  /* beginning of next partial file; need to point the previous file */
     130  if (p->lineno == 0 && p->current_filename_index > 0) {
     131    c->filename_index-- ;
     132  }
    136133  return c;
    137134}
     
    186183
    187184  if (!a) return b;
     185  if (!b) return a;
    188186  while (c->cdr) {
    189187    c = c->cdr;
    190188  }
    191   if (b) {
    192     c->cdr = b;
    193   }
     189  c->cdr = b;
    194190  return a;
    195191}
     
    216212#undef strdup
    217213#define strdup(s) parser_strdup(p, s)
     214
     215static void
     216dump_int(uint16_t i, char *s)
     217{
     218  char *p = s;
     219  char *t = s;
     220
     221  while (i > 0) {
     222    *p++ = (i % 10)+'0';
     223    i /= 10;
     224  }
     225  if (p == s) *p++ = '0';
     226  *p = 0;
     227  p--;  /* point the last char */
     228  while (t < p) {
     229    char c = *t;
     230    *t++ = *p;
     231    *p-- = c;
     232  }
     233}
    218234
    219235/* xxx ----------------------------- */
     
    280296}
    281297
     298static void
     299local_add_blk(parser_state *p, mrb_sym blk)
     300{
     301  /* allocate register for block */
     302  local_add_f(p, blk ? blk : mrb_intern_lit(p->mrb, "&"));
     303}
     304
     305static void
     306local_add_kw(parser_state *p, mrb_sym kwd)
     307{
     308  /* allocate register for keywords hash */
     309  local_add_f(p, kwd ? kwd : mrb_intern_lit(p->mrb, "**"));
     310}
     311
    282312static node*
    283313locals_node(parser_state *p)
    284314{
    285315  return p->locals ? p->locals->car : NULL;
     316}
     317
     318static void
     319nvars_nest(parser_state *p)
     320{
     321  p->nvars = cons(nint(0), p->nvars);
     322}
     323
     324static void
     325nvars_block(parser_state *p)
     326{
     327  p->nvars = cons(nint(-2), p->nvars);
     328}
     329
     330static void
     331nvars_unnest(parser_state *p)
     332{
     333  p->nvars = p->nvars->cdr;
    286334}
    287335
     
    569617}
    570618
     619/* (:kw_hash (k . v) (k . v)...) */
     620static node*
     621new_kw_hash(parser_state *p, node *a)
     622{
     623  return cons((node*)NODE_KW_HASH, a);
     624}
     625
    571626/* (:sym . a) */
    572627static node*
     
    613668}
    614669
     670/* (:nvar . a) */
     671static node*
     672new_nvar(parser_state *p, int num)
     673{
     674  int nvars = intn(p->nvars->car);
     675
     676  p->nvars->car = nint(nvars > num ? nvars : num);
     677  return cons((node*)NODE_NVAR, nint(num));
     678}
     679
    615680/* (:const . a) */
    616681static node*
     
    672737}
    673738
    674 /* (m o r m2 b) */
     739static void
     740local_add_margs(parser_state *p, node *n)
     741{
     742  while (n) {
     743    if (n->car->car == (node*)NODE_MASGN) {
     744      node *t = n->car->cdr->cdr;
     745
     746      n->car->cdr->cdr = NULL;
     747      while (t) {
     748        local_add_f(p, sym(t->car));
     749        t = t->cdr;
     750      }
     751      local_add_margs(p, n->car->cdr->car->car);
     752      local_add_margs(p, n->car->cdr->car->cdr->cdr->car);
     753    }
     754    n = n->cdr;
     755  }
     756}
     757
     758static void
     759local_add_lv(parser_state *p, node *lv)
     760{
     761  while (lv) {
     762    local_add_f(p, sym(lv->car));
     763    lv = lv->cdr;
     764  }
     765}
     766
     767/* (m o r m2 tail) */
    675768/* m: (a b c) */
    676769/* o: ((a . e1) (b . e2)) */
     
    679772/* b: a */
    680773static node*
    681 new_args(parser_state *p, node *m, node *opt, mrb_sym rest, node *m2, mrb_sym blk)
     774new_args(parser_state *p, node *m, node *opt, mrb_sym rest, node *m2, node *tail)
    682775{
    683776  node *n;
    684777
    685   n = cons(m2, nsym(blk));
     778  local_add_margs(p, m);
     779  local_add_margs(p, m2);
     780  n = cons(m2, tail);
    686781  n = cons(nsym(rest), n);
    687782  n = cons(opt, n);
     783  while (opt) {
     784    /* opt: (sym . (opt . lv)) -> (sym . opt) */
     785    local_add_lv(p, opt->car->cdr->cdr);
     786    opt->car->cdr = opt->car->cdr->car;
     787    opt = opt->cdr;
     788  }
    688789  return cons(m, n);
    689790}
    690791
     792/* (:args_tail keywords rest_keywords_sym block_sym) */
     793static node*
     794new_args_tail(parser_state *p, node *kws, node *kwrest, mrb_sym blk)
     795{
     796  node *k;
     797
     798  if (kws || kwrest) {
     799    local_add_kw(p, (kwrest && kwrest->cdr)? sym(kwrest->cdr) : 0);
     800  }
     801
     802  local_add_blk(p, blk);
     803
     804  /* allocate register for keywords arguments */
     805  /* order is for Proc#parameters */
     806  for (k = kws; k; k = k->cdr) {
     807    if (!k->car->cdr->cdr->car) { /* allocate required keywords */
     808      local_add_f(p, sym(k->car->cdr->car));
     809    }
     810  }
     811  for (k = kws; k; k = k->cdr) {
     812    if (k->car->cdr->cdr->car) { /* allocate keywords with default */
     813      local_add_lv(p, k->car->cdr->cdr->car->cdr);
     814      k->car->cdr->cdr->car = k->car->cdr->cdr->car->car;
     815      local_add_f(p, sym(k->car->cdr->car));
     816    }
     817  }
     818
     819  return list4((node*)NODE_ARGS_TAIL, kws, kwrest, nsym(blk));
     820}
     821
     822/* (:kw_arg kw_sym def_arg) */
     823static node*
     824new_kw_arg(parser_state *p, mrb_sym kw, node *def_arg)
     825{
     826  mrb_assert(kw);
     827  return list3((node*)NODE_KW_ARG, nsym(kw), def_arg);
     828}
     829
    691830/* (:block_arg . a) */
    692831static node*
     
    696835}
    697836
     837static node*
     838setup_numparams(parser_state *p, node *a)
     839{
     840  int nvars = intn(p->nvars->car);
     841  if (nvars > 0) {
     842    int i;
     843    mrb_sym sym;
     844    // m || opt || rest || tail
     845    if (a && (a->car || (a->cdr && a->cdr->car) || (a->cdr->cdr && a->cdr->cdr->car) || (a->cdr->cdr->cdr->cdr && a->cdr->cdr->cdr->cdr->car))) {
     846      yyerror(p, "ordinary parameter is defined");
     847    }
     848    else if (p->locals) {
     849      /* p->locals should not be NULL unless error happens before the point */
     850      node* args = 0;
     851      for (i = nvars; i > 0; i--) {
     852        char buf[3];
     853
     854        buf[0] = '_';
     855        buf[1] = i+'0';
     856        buf[2] = '\0';
     857        sym = intern_cstr(buf);
     858        args = cons(new_arg(p, sym), args);
     859        p->locals->car = cons(nsym(sym), p->locals->car);
     860      }
     861      a = new_args(p, args, 0, 0, 0, 0);
     862    }
     863  }
     864  return a;
     865}
     866
    698867/* (:block arg body) */
    699868static node*
    700869new_block(parser_state *p, node *a, node *b)
    701870{
     871  a = setup_numparams(p, a);
    702872  return list4((node*)NODE_BLOCK, locals_node(p), a, b);
    703873}
     
    726896}
    727897
     898/* (:masgn mlhs mrhs) no check */
     899static node*
     900new_masgn_param(parser_state *p, node *a, node *b)
     901{
     902  return cons((node*)NODE_MASGN, cons(a, b));
     903}
     904
    728905/* (:asgn lhs rhs) */
    729906static node*
     
    734911}
    735912
     913static node*
     914new_imaginary(parser_state *p, node *imaginary)
     915{
     916  return new_call(p, new_const(p, intern_lit("Kernel")), intern_lit("Complex"), list1(list2(list3((node*)NODE_INT, (node*)strdup("0"), nint(10)), imaginary)), 1);
     917}
     918
     919static node*
     920new_rational(parser_state *p, node *rational)
     921{
     922  return new_call(p, new_const(p, intern_lit("Kernel")), intern_lit("Rational"), list1(list1(rational)), 1);
     923}
     924
    736925/* (:int . i) */
    737926static node*
    738 new_int(parser_state *p, const char *s, int base)
    739 {
    740   return list3((node*)NODE_INT, (node*)strdup(s), nint(base));
    741 }
    742 
     927new_int(parser_state *p, const char *s, int base, int suffix)
     928{
     929  node* result = list3((node*)NODE_INT, (node*)strdup(s), nint(base));
     930  if (suffix & NUM_SUFFIX_R) {
     931    result = new_rational(p, result);
     932  }
     933  if (suffix & NUM_SUFFIX_I) {
     934    result = new_imaginary(p, result);
     935  }
     936  return result;
     937}
     938
     939#ifndef MRB_WITHOUT_FLOAT
    743940/* (:float . i) */
    744941static node*
    745 new_float(parser_state *p, const char *s)
    746 {
    747   return cons((node*)NODE_FLOAT, (node*)strdup(s));
    748 }
     942new_float(parser_state *p, const char *s, int suffix)
     943{
     944  node* result = cons((node*)NODE_FLOAT, (node*)strdup(s));
     945  if (suffix & NUM_SUFFIX_R) {
     946    result = new_rational(p, result);
     947  }
     948  if (suffix & NUM_SUFFIX_I) {
     949    result = new_imaginary(p, result);
     950  }
     951  return result;
     952}
     953#endif
    749954
    750955/* (:str . (s . len)) */
    751956static node*
    752 new_str(parser_state *p, const char *s, int len)
     957new_str(parser_state *p, const char *s, size_t len)
    753958{
    754959  return cons((node*)NODE_STR, cons((node*)strndup(s, len), nint(len)));
     
    762967}
    763968
     969static int
     970string_node_p(node *n)
     971{
     972  return (int)((enum node_type)(intptr_t)n->car == NODE_STR);
     973}
     974
     975static node*
     976composite_string_node(parser_state *p, node *a, node *b)
     977{
     978  size_t newlen = (size_t)a->cdr + (size_t)b->cdr;
     979  char *str = (char*)mrb_pool_realloc(p->pool, a->car, (size_t)a->cdr + 1, newlen + 1);
     980  memcpy(str + (size_t)a->cdr, b->car, (size_t)b->cdr);
     981  str[newlen] = '\0';
     982  a->car = (node*)str;
     983  a->cdr = (node*)newlen;
     984  cons_free(b);
     985  return a;
     986}
     987
     988static node*
     989concat_string(parser_state *p, node *a, node *b)
     990{
     991  if (string_node_p(a)) {
     992    if (string_node_p(b)) {
     993      /* a == NODE_STR && b == NODE_STR */
     994      composite_string_node(p, a->cdr, b->cdr);
     995      cons_free(b);
     996      return a;
     997    }
     998    else {
     999      /* a == NODE_STR && b == NODE_DSTR */
     1000
     1001      if (string_node_p(b->cdr->car)) {
     1002        /* a == NODE_STR && b->[NODE_STR, ...] */
     1003        composite_string_node(p, a->cdr, b->cdr->car->cdr);
     1004        cons_free(b->cdr->car);
     1005        b->cdr->car = a;
     1006        return b;
     1007      }
     1008    }
     1009  }
     1010  else {
     1011    node *c; /* last node of a */
     1012    for (c = a; c->cdr != NULL; c = c->cdr) ;
     1013
     1014    if (string_node_p(b)) {
     1015      /* a == NODE_DSTR && b == NODE_STR */
     1016      if (string_node_p(c->car)) {
     1017        /* a->[..., NODE_STR] && b == NODE_STR */
     1018        composite_string_node(p, c->car->cdr, b->cdr);
     1019        cons_free(b);
     1020        return a;
     1021      }
     1022
     1023      push(a, b);
     1024      return a;
     1025    }
     1026    else {
     1027      /* a == NODE_DSTR && b == NODE_DSTR */
     1028      if (string_node_p(c->car) && string_node_p(b->cdr->car)) {
     1029        /* a->[..., NODE_STR] && b->[NODE_STR, ...] */
     1030        node *d = b->cdr;
     1031        cons_free(b);
     1032        composite_string_node(p, c->car->cdr, d->car->cdr);
     1033        cons_free(d->car);
     1034        c->cdr = d->cdr;
     1035        cons_free(d);
     1036        return a;
     1037      }
     1038      else {
     1039        c->cdr = b->cdr;
     1040        cons_free(b);
     1041        return a;
     1042      }
     1043    }
     1044  }
     1045
     1046  return new_dstr(p, list2(a, b));
     1047}
     1048
    7641049/* (:str . (s . len)) */
    7651050static node*
     
    7801065new_dsym(parser_state *p, node *a)
    7811066{
    782   return cons((node*)NODE_DSYM, new_dstr(p, a));
     1067  return cons((node*)NODE_DSYM, a);
    7831068}
    7841069
     
    10241309  if (p->parsing_heredoc == NULL) {
    10251310    p->lstate = EXPR_BEG;
    1026     p->cmd_start = TRUE;
    10271311    end_strterm(p);
    10281312    p->lex_strterm = p->lex_strterm_before_heredoc;
    10291313    p->lex_strterm_before_heredoc = NULL;
    1030     p->heredoc_end_now = TRUE;
    10311314  }
    10321315  else {
     
    11051388        keyword__ENCODING__
    11061389
    1107 %token <id>  tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL
     1390%token <id>  tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL_TAG
    11081391%token <nd>  tINTEGER tFLOAT tCHAR tXSTRING tREGEXP
    1109 %token <nd>  tSTRING tSTRING_PART tSTRING_MID tLABEL_END
     1392%token <nd>  tSTRING tSTRING_PART tSTRING_MID
    11101393%token <nd>  tNTH_REF tBACK_REF
    11111394%token <num> tREGEXP_END
    1112 
    1113 %type <nd> singleton string string_rep string_interp xstring regexp
     1395%token <num> tNUMPARAM
     1396
     1397%type <nd> singleton string string_fragment string_rep string_interp xstring regexp
    11141398%type <nd> literal numeric cpath symbol
    11151399%type <nd> top_compstmt top_stmts top_stmt
     
    11221406%type <nd> command_asgn command_rhs mrhs superclass block_call block_command
    11231407%type <nd> f_block_optarg f_block_opt
    1124 %type <nd> f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_list f_margs
     1408%type <nd> f_arglist f_args f_arg f_arg_item f_optarg f_margs
    11251409%type <nd> assoc_list assocs assoc undef_list backref for_var
    11261410%type <nd> block_param opt_block_param block_param_def f_opt
     
    11321416%type <nd> heredoc words symbols
    11331417%type <num> call_op call_op2     /* 0:'&.', 1:'.', 2:'::' */
     1418
     1419%type <nd> args_tail opt_args_tail f_kwarg f_kw f_kwrest
     1420%type <nd> f_block_kwarg f_block_kw block_args_tail opt_block_args_tail
     1421%type <id> f_label
    11341422
    11351423%token tUPLUS             /* unary+ */
     
    11581446%token tLBRACE_ARG        /* { */
    11591447%token tSTAR              /* * */
     1448%token tDSTAR             /* ** */
    11601449%token tAMPER             /* & */
    11611450%token tLAMBDA            /* -> */
     
    11791468%right '=' tOP_ASGN
    11801469%left modifier_rescue
    1181 %right '?' ':'
     1470%right '?' ':' tLABEL_TAG
    11821471%nonassoc tDOT2 tDOT3
    11831472%left  tOROP
     
    12371526                    {
    12381527                      $<nd>$ = local_switch(p);
     1528                      nvars_block(p);
    12391529                    }
    12401530                  '{' top_compstmt '}'
     
    12421532                      yyerror(p, "BEGIN not supported");
    12431533                      local_resume(p, $<nd>2);
     1534                      nvars_unnest(p);
    12441535                      $$ = 0;
    12451536                    }
     
    13591650                      $$ = new_op_asgn(p, $1, $2, $3);
    13601651                    }
    1361                 | primary_value '[' opt_call_args rbracket tOP_ASGN command_rhs
    1362                     {
    1363                       $$ = new_op_asgn(p, new_call(p, $1, intern("[]",2), $3, '.'), $5, $6);
     1652                | primary_value '[' opt_call_args ']' tOP_ASGN command_rhs
     1653                    {
     1654                      $$ = new_op_asgn(p, new_call(p, $1, intern_lit("[]"), $3, '.'), $5, $6);
    13641655                    }
    13651656                | primary_value call_op tIDENTIFIER tOP_ASGN command_rhs
     
    13851676                      $$ = new_begin(p, 0);
    13861677                    }
    1387                 ;
     1678                ;
    13881679
    13891680command_rhs     : command_call   %prec tOP_ASGN
     
    14391730                    {
    14401731                      local_nest(p);
     1732                      nvars_nest(p);
    14411733                    }
    14421734                  opt_block_param
     
    14461738                      $$ = new_block(p, $3, $4);
    14471739                      local_unnest(p);
     1740                      nvars_unnest(p);
    14481741                    }
    14491742                ;
     
    15881881                      assignable(p, $1);
    15891882                    }
    1590                 | primary_value '[' opt_call_args rbracket
    1591                     {
    1592                       $$ = new_call(p, $1, intern("[]",2), $3, '.');
     1883                | primary_value '[' opt_call_args ']'
     1884                    {
     1885                      $$ = new_call(p, $1, intern_lit("[]"), $3, '.');
    15931886                    }
    15941887                | primary_value call_op tIDENTIFIER
     
    16271920                      assignable(p, $1);
    16281921                    }
    1629                 | primary_value '[' opt_call_args rbracket
    1630                     {
    1631                       $$ = new_call(p, $1, intern("[]",2), $3, '.');
     1922                | primary_value '[' opt_call_args ']'
     1923                    {
     1924                      $$ = new_call(p, $1, intern_lit("[]"), $3, '.');
    16321925                    }
    16331926                | primary_value call_op tIDENTIFIER
     
    16591952                      backref_error(p, $1);
    16601953                      $$ = 0;
     1954                    }
     1955                | tNUMPARAM
     1956                    {
     1957                      yyerror(p, "can't assign to numbered parameter");
    16611958                    }
    16621959                ;
     
    17132010                ;
    17142011
    1715 op              : '|'           { $$ = intern_c('|');   }
    1716                 | '^'           { $$ = intern_c('^');   }
    1717                 | '&'           { $$ = intern_c('&');   }
    1718                 | tCMP          { $$ = intern("<=>",3); }
    1719                 | tEQ           { $$ = intern("==",2);  }
    1720                 | tEQQ          { $$ = intern("===",3); }
    1721                 | tMATCH        { $$ = intern("=~",2);  }
    1722                 | tNMATCH       { $$ = intern("!~",2);  }
    1723                 | '>'           { $$ = intern_c('>');   }
    1724                 | tGEQ          { $$ = intern(">=",2);  }
    1725                 | '<'           { $$ = intern_c('<');   }
    1726                 | tLEQ          { $$ = intern("<=",2);  }
    1727                 | tNEQ          { $$ = intern("!=",2);  }
    1728                 | tLSHFT        { $$ = intern("<<",2);  }
    1729                 | tRSHFT        { $$ = intern(">>",2);  }
    1730                 | '+'           { $$ = intern_c('+');   }
    1731                 | '-'           { $$ = intern_c('-');   }
    1732                 | '*'           { $$ = intern_c('*');   }
    1733                 | tSTAR         { $$ = intern_c('*');   }
    1734                 | '/'           { $$ = intern_c('/');   }
    1735                 | '%'           { $$ = intern_c('%');   }
    1736                 | tPOW          { $$ = intern("**",2);  }
    1737                 | '!'           { $$ = intern_c('!');   }
    1738                 | '~'           { $$ = intern_c('~');   }
    1739                 | tUPLUS        { $$ = intern("+@",2);  }
    1740                 | tUMINUS       { $$ = intern("-@",2);  }
    1741                 | tAREF         { $$ = intern("[]",2);  }
    1742                 | tASET         { $$ = intern("[]=",3); }
    1743                 | '`'           { $$ = intern_c('`');   }
     2012op              : '|'           { $$ = intern_lit("|");   }
     2013                | '^'           { $$ = intern_lit("^");   }
     2014                | '&'           { $$ = intern_lit("&");   }
     2015                | tCMP          { $$ = intern_lit("<=>"); }
     2016                | tEQ           { $$ = intern_lit("==");  }
     2017                | tEQQ          { $$ = intern_lit("==="); }
     2018                | tMATCH        { $$ = intern_lit("=~");  }
     2019                | tNMATCH       { $$ = intern_lit("!~");  }
     2020                | '>'           { $$ = intern_lit(">");   }
     2021                | tGEQ          { $$ = intern_lit(">=");  }
     2022                | '<'           { $$ = intern_lit("<");   }
     2023                | tLEQ          { $$ = intern_lit("<=");  }
     2024                | tNEQ          { $$ = intern_lit("!=");  }
     2025                | tLSHFT        { $$ = intern_lit("<<");  }
     2026                | tRSHFT        { $$ = intern_lit(">>");  }
     2027                | '+'           { $$ = intern_lit("+");   }
     2028                | '-'           { $$ = intern_lit("-");   }
     2029                | '*'           { $$ = intern_lit("*");   }
     2030                | tSTAR         { $$ = intern_lit("*");   }
     2031                | '/'           { $$ = intern_lit("/");   }
     2032                | '%'           { $$ = intern_lit("%");   }
     2033                | tPOW          { $$ = intern_lit("**");  }
     2034                | tDSTAR        { $$ = intern_lit("**");  }
     2035                | '!'           { $$ = intern_lit("!");   }
     2036                | '~'           { $$ = intern_lit("~");   }
     2037                | tUPLUS        { $$ = intern_lit("+@");  }
     2038                | tUMINUS       { $$ = intern_lit("-@");  }
     2039                | tAREF         { $$ = intern_lit("[]");  }
     2040                | tASET         { $$ = intern_lit("[]="); }
     2041                | '`'           { $$ = intern_lit("`");   }
    17442042                ;
    17452043
     
    17662064                      $$ = new_op_asgn(p, $1, $2, $3);
    17672065                    }
    1768                 | primary_value '[' opt_call_args rbracket tOP_ASGN arg_rhs
    1769                     {
    1770                       $$ = new_op_asgn(p, new_call(p, $1, intern("[]",2), $3, '.'), $5, $6);
     2066                | primary_value '[' opt_call_args ']' tOP_ASGN arg_rhs
     2067                    {
     2068                      $$ = new_op_asgn(p, new_call(p, $1, intern_lit("[]"), $3, '.'), $5, $6);
    17712069                    }
    17722070                | primary_value call_op tIDENTIFIER tOP_ASGN arg_rhs
     
    19252223                      $$ = new_if(p, cond($1), $3, $6);
    19262224                    }
     2225                | arg '?' arg opt_nl tLABEL_TAG arg
     2226                    {
     2227                      $$ = new_if(p, cond($1), $3, $6);
     2228                    }
    19272229                | primary
    19282230                    {
     
    19392241                | args comma assocs trailer
    19402242                    {
    1941                       $$ = push($1, new_hash(p, $3));
     2243                      $$ = push($1, new_kw_hash(p, $3));
    19422244                    }
    19432245                | assocs trailer
    19442246                    {
    1945                       $$ = cons(new_hash(p, $1), 0);
     2247                      $$ = cons(new_kw_hash(p, $1), 0);
    19462248                      NODE_LINENO($$, $1);
    19472249                    }
     
    19602262                ;
    19612263
    1962 paren_args      : '(' opt_call_args rparen
     2264paren_args      : '(' opt_call_args ')'
    19632265                    {
    19642266                      $$ = $2;
     
    19712273
    19722274opt_call_args   : none
    1973                 | call_args
    1974                 | args ','
     2275                | call_args opt_terms
     2276                | args comma
    19752277                    {
    19762278                      $$ = cons($1,0);
    19772279                      NODE_LINENO($$, $1);
    19782280                    }
    1979                 | args comma assocs ','
    1980                     {
    1981                       $$ = cons(push($1, new_hash(p, $3)), 0);
     2281                | args comma assocs comma
     2282                    {
     2283                      $$ = cons(push($1, new_kw_hash(p, $3)), 0);
    19822284                      NODE_LINENO($$, $1);
    19832285                    }
    1984                 | assocs ','
    1985                     {
    1986                       $$ = cons(list1(new_hash(p, $1)), 0);
     2286                | assocs comma
     2287                    {
     2288                      $$ = cons(list1(new_kw_hash(p, $1)), 0);
    19872289                      NODE_LINENO($$, $1);
    19882290                    }
     
    20022304                | assocs opt_block_arg
    20032305                    {
    2004                       $$ = cons(list1(new_hash(p, $1)), $2);
     2306                      $$ = cons(list1(new_kw_hash(p, $1)), $2);
    20052307                      NODE_LINENO($$, $1);
    20062308                    }
    20072309                | args comma assocs opt_block_arg
    20082310                    {
    2009                       $$ = cons(push($1, new_hash(p, $3)), $4);
     2311                      $$ = cons(push($1, new_kw_hash(p, $3)), $4);
    20102312                      NODE_LINENO($$, $1);
    20112313                    }
     
    20452347
    20462348comma           : ','
    2047                 | ','  heredoc_bodies
     2349                | ','  opt_nl heredoc_bodies
    20482350                ;
    20492351
     
    20962398                | var_ref
    20972399                | backref
     2400                | tNUMPARAM
     2401                    {
     2402                      $$ = new_nvar(p, $1);
     2403                    }
    20982404                | tFID
    20992405                    {
     
    22482554                        yyerror(p, "class definition in method body");
    22492555                      $<nd>$ = local_switch(p);
     2556                      nvars_block(p);
    22502557                    }
    22512558                  bodystmt
     
    22552562                      SET_LINENO($$, $1);
    22562563                      local_resume(p, $<nd>4);
     2564                      nvars_unnest(p);
    22572565                    }
    22582566                | keyword_class
     
    22652573                    {
    22662574                      $<nd>$ = cons(local_switch(p), nint(p->in_single));
     2575                      nvars_block(p);
    22672576                      p->in_single = 0;
    22682577                    }
     
    22732582                      SET_LINENO($$, $1);
    22742583                      local_resume(p, $<nd>6->car);
     2584                      nvars_unnest(p);
    22752585                      p->in_def = $<num>4;
    22762586                      p->in_single = intn($<nd>6->cdr);
     
    22822592                        yyerror(p, "module definition in method body");
    22832593                      $<nd>$ = local_switch(p);
     2594                      nvars_block(p);
    22842595                    }
    22852596                  bodystmt
     
    22892600                      SET_LINENO($$, $1);
    22902601                      local_resume(p, $<nd>3);
     2602                      nvars_unnest(p);
    22912603                    }
    22922604                | keyword_def fname
     
    22982610                      p->in_def++;
    22992611                      $<nd>$ = local_switch(p);
     2612                      nvars_block(p);
    23002613                    }
    23012614                  f_arglist
     
    23062619                      SET_LINENO($$, $1);
    23072620                      local_resume(p, $<nd>4);
     2621                      nvars_unnest(p);
    23082622                      p->in_def--;
    23092623                      p->cmdarg_stack = $<stack>3;
     
    23202634                      p->lstate = EXPR_ENDFN; /* force for args */
    23212635                      $<nd>$ = local_switch(p);
     2636                      nvars_block(p);
    23222637                    }
    23232638                  f_arglist
     
    23282643                      SET_LINENO($$, $1);
    23292644                      local_resume(p, $<nd>6);
     2645                      nvars_unnest(p);
    23302646                      p->in_single--;
    23312647                      p->cmdarg_stack = $<stack>4;
     
    23882704                ;
    23892705
    2390 f_marg          : f_norm_arg
    2391                     {
    2392                       $$ = new_arg(p, $1);
    2393                     }
    2394                 | tLPAREN f_margs rparen
    2395                     {
    2396                       $$ = new_masgn(p, $2, 0);
    2397                     }
    2398                 ;
    2399 
    2400 f_marg_list     : f_marg
    2401                     {
    2402                       $$ = list1($1);
    2403                     }
    2404                 | f_marg_list ',' f_marg
    2405                     {
    2406                       $$ = push($1, $3);
    2407                     }
    2408                 ;
    2409 
    2410 f_margs         : f_marg_list
     2706f_margs         : f_arg
    24112707                    {
    24122708                      $$ = list3($1,0,0);
    24132709                    }
    2414                 | f_marg_list ',' tSTAR f_norm_arg
     2710                | f_arg ',' tSTAR f_norm_arg
    24152711                    {
    24162712                      $$ = list3($1, new_arg(p, $4), 0);
    24172713                    }
    2418                 | f_marg_list ',' tSTAR f_norm_arg ',' f_marg_list
     2714                | f_arg ',' tSTAR f_norm_arg ',' f_arg
    24192715                    {
    24202716                      $$ = list3($1, new_arg(p, $4), $6);
    24212717                    }
    2422                 | f_marg_list ',' tSTAR
    2423                     {
     2718                | f_arg ',' tSTAR
     2719                    {
     2720                      local_add_f(p, 0);
    24242721                      $$ = list3($1, (node*)-1, 0);
    24252722                    }
    2426                 | f_marg_list ',' tSTAR ',' f_marg_list
     2723                | f_arg ',' tSTAR ',' f_arg
    24272724                    {
    24282725                      $$ = list3($1, (node*)-1, $5);
     
    24322729                      $$ = list3(0, new_arg(p, $2), 0);
    24332730                    }
    2434                 | tSTAR f_norm_arg ',' f_marg_list
     2731                | tSTAR f_norm_arg ',' f_arg
    24352732                    {
    24362733                      $$ = list3(0, new_arg(p, $2), $4);
     
    24382735                | tSTAR
    24392736                    {
     2737                      local_add_f(p, 0);
    24402738                      $$ = list3(0, (node*)-1, 0);
    24412739                    }
    2442                 | tSTAR ',' f_marg_list
    2443                     {
    2444                       $$ = list3(0, (node*)-1, $3);
    2445                     }
    2446                 ;
    2447 
    2448 block_param     : f_arg ',' f_block_optarg ',' f_rest_arg opt_f_block_arg
     2740                | tSTAR ','
     2741                    {
     2742                      local_add_f(p, 0);
     2743                    }
     2744                  f_arg
     2745                    {
     2746                      $$ = list3(0, (node*)-1, $4);
     2747                    }
     2748                ;
     2749
     2750block_args_tail : f_block_kwarg ',' f_kwrest opt_f_block_arg
     2751                    {
     2752                      $$ = new_args_tail(p, $1, $3, $4);
     2753                    }
     2754                | f_block_kwarg opt_f_block_arg
     2755                    {
     2756                      $$ = new_args_tail(p, $1, 0, $2);
     2757                    }
     2758                | f_kwrest opt_f_block_arg
     2759                    {
     2760                      $$ = new_args_tail(p, 0, $1, $2);
     2761                    }
     2762                | f_block_arg
     2763                    {
     2764                      $$ = new_args_tail(p, 0, 0, $1);
     2765                    }
     2766                ;
     2767
     2768opt_block_args_tail : ',' block_args_tail
     2769                    {
     2770                      $$ = $2;
     2771                    }
     2772                | /* none */
     2773                    {
     2774                      $$ = new_args_tail(p, 0, 0, 0);
     2775                    }
     2776                ;
     2777
     2778block_param     : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail
    24492779                    {
    24502780                      $$ = new_args(p, $1, $3, $5, 0, $6);
    24512781                    }
    2452                 | f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
     2782                | f_arg ',' f_block_optarg ',' f_rest_arg ',' f_arg opt_block_args_tail
    24532783                    {
    24542784                      $$ = new_args(p, $1, $3, $5, $7, $8);
    24552785                    }
    2456                 | f_arg ',' f_block_optarg opt_f_block_arg
     2786                | f_arg ',' f_block_optarg opt_block_args_tail
    24572787                    {
    24582788                      $$ = new_args(p, $1, $3, 0, 0, $4);
    24592789                    }
    2460                 | f_arg ',' f_block_optarg ',' f_arg opt_f_block_arg
     2790                | f_arg ',' f_block_optarg ',' f_arg opt_block_args_tail
    24612791                    {
    24622792                      $$ = new_args(p, $1, $3, 0, $5, $6);
    24632793                    }
    2464                 | f_arg ',' f_rest_arg opt_f_block_arg
     2794                | f_arg ',' f_rest_arg opt_block_args_tail
    24652795                    {
    24662796                      $$ = new_args(p, $1, 0, $3, 0, $4);
    24672797                    }
    2468                 | f_arg ','
    2469                     {
    2470                       $$ = new_args(p, $1, 0, 0, 0, 0);
    2471                     }
    2472                 | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
     2798                | f_arg ',' opt_block_args_tail
     2799                    {
     2800                      $$ = new_args(p, $1, 0, 0, 0, $3);
     2801                    }
     2802                | f_arg ',' f_rest_arg ',' f_arg opt_block_args_tail
    24732803                    {
    24742804                      $$ = new_args(p, $1, 0, $3, $5, $6);
    24752805                    }
    2476                 | f_arg opt_f_block_arg
     2806                | f_arg opt_block_args_tail
    24772807                    {
    24782808                      $$ = new_args(p, $1, 0, 0, 0, $2);
    24792809                    }
    2480                 | f_block_optarg ',' f_rest_arg opt_f_block_arg
     2810                | f_block_optarg ',' f_rest_arg opt_block_args_tail
    24812811                    {
    24822812                      $$ = new_args(p, 0, $1, $3, 0, $4);
    24832813                    }
    2484                 | f_block_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
     2814                | f_block_optarg ',' f_rest_arg ',' f_arg opt_block_args_tail
    24852815                    {
    24862816                      $$ = new_args(p, 0, $1, $3, $5, $6);
    24872817                    }
    2488                 | f_block_optarg opt_f_block_arg
     2818                | f_block_optarg opt_block_args_tail
    24892819                    {
    24902820                      $$ = new_args(p, 0, $1, 0, 0, $2);
    24912821                    }
    2492                 | f_block_optarg ',' f_arg opt_f_block_arg
     2822                | f_block_optarg ',' f_arg opt_block_args_tail
    24932823                    {
    24942824                      $$ = new_args(p, 0, $1, 0, $3, $4);
    24952825                    }
    2496                 | f_rest_arg opt_f_block_arg
     2826                | f_rest_arg opt_block_args_tail
    24972827                    {
    24982828                      $$ = new_args(p, 0, 0, $1, 0, $2);
    24992829                    }
    2500                 | f_rest_arg ',' f_arg opt_f_block_arg
     2830                | f_rest_arg ',' f_arg opt_block_args_tail
    25012831                    {
    25022832                      $$ = new_args(p, 0, 0, $1, $3, $4);
    25032833                    }
    2504                 | f_block_arg
     2834                | block_args_tail
    25052835                    {
    25062836                      $$ = new_args(p, 0, 0, 0, 0, $1);
     
    25092839
    25102840opt_block_param : none
     2841                    {
     2842                      local_add_blk(p, 0);
     2843                      $$ = 0;
     2844                    }
    25112845                | block_param_def
    2512                     {
     2846                   {
    25132847                      p->cmd_start = TRUE;
    25142848                      $$ = $1;
     
    25162850                ;
    25172851
    2518 block_param_def : '|' opt_bv_decl '|'
     2852block_param_def : '|' {local_add_blk(p, 0);} opt_bv_decl '|'
    25192853                    {
    25202854                      $$ = 0;
     
    25222856                | tOROP
    25232857                    {
     2858                      local_add_blk(p, 0);
    25242859                      $$ = 0;
    25252860                    }
     
    25672902                      $$ = $2;
    25682903                    }
    2569                 | keyword_do_LAMBDA compstmt keyword_end
     2904                | keyword_do_LAMBDA bodystmt keyword_end
    25702905                    {
    25712906                      $$ = $2;
     
    25762911                    {
    25772912                      local_nest(p);
     2913                      nvars_nest(p);
    25782914                    }
    25792915                  opt_block_param
    2580                   compstmt
     2916                  bodystmt
    25812917                  keyword_end
    25822918                    {
    25832919                      $$ = new_block(p,$3,$4);
    25842920                      local_unnest(p);
     2921                      nvars_unnest(p);
    25852922                    }
    25862923                ;
     
    26302967                | primary_value call_op paren_args
    26312968                    {
    2632                       $$ = new_call(p, $1, intern("call",4), $3, $2);
     2969                      $$ = new_call(p, $1, intern_lit("call"), $3, $2);
    26332970                    }
    26342971                | primary_value tCOLON2 paren_args
    26352972                    {
    2636                       $$ = new_call(p, $1, intern("call",4), $3, tCOLON2);
     2973                      $$ = new_call(p, $1, intern_lit("call"), $3, tCOLON2);
    26372974                    }
    26382975                | keyword_super paren_args
     
    26442981                      $$ = new_zsuper(p);
    26452982                    }
    2646                 | primary_value '[' opt_call_args rbracket
    2647                     {
    2648                       $$ = new_call(p, $1, intern("[]",2), $3, '.');
     2983                | primary_value '[' opt_call_args ']'
     2984                    {
     2985                      $$ = new_call(p, $1, intern_lit("[]"), $3, '.');
    26492986                    }
    26502987                ;
     
    26532990                    {
    26542991                      local_nest(p);
     2992                      nvars_nest(p);
    26552993                      $<num>$ = p->lineno;
    26562994                    }
     
    26612999                      SET_LINENO($$, $<num>2);
    26623000                      local_unnest(p);
     3001                      nvars_unnest(p);
    26633002                    }
    26643003                | keyword_do
    26653004                    {
    26663005                      local_nest(p);
     3006                      nvars_nest(p);
    26673007                      $<num>$ = p->lineno;
    26683008                    }
    26693009                  opt_block_param
    2670                   compstmt keyword_end
     3010                  bodystmt keyword_end
    26713011                    {
    26723012                      $$ = new_block(p,$3,$4);
    26733013                      SET_LINENO($$, $<num>2);
    26743014                      local_unnest(p);
     3015                      nvars_unnest(p);
    26753016                    }
    26763017                ;
     
    27343075                ;
    27353076
    2736 string          : tCHAR
     3077string          : string_fragment
     3078                | string string_fragment
     3079                    {
     3080                      $$ = concat_string(p, $1, $2);
     3081                    }
     3082                ;
     3083
     3084string_fragment : tCHAR
    27373085                | tSTRING
    27383086                | tSTRING_BEG tSTRING
     
    28543202symbol          : basic_symbol
    28553203                    {
     3204                      p->lstate = EXPR_ENDARG;
    28563205                      $$ = new_sym(p, $1);
    28573206                    }
    28583207                | tSYMBEG tSTRING_BEG string_rep tSTRING
    28593208                    {
    2860                       p->lstate = EXPR_END;
    2861                       $$ = new_dsym(p, push($3, $4));
     3209                      p->lstate = EXPR_ENDARG;
     3210                      $$ = new_dsym(p, new_dstr(p, push($3, $4)));
    28623211                    }
    28633212                ;
     
    28653214basic_symbol    : tSYMBEG sym
    28663215                    {
    2867                       p->lstate = EXPR_END;
    28683216                      $$ = $2;
    28693217                    }
     
    29323280                      assignable(p, $1);
    29333281                    }
     3282                | tNUMPARAM
     3283                    {
     3284                      yyerror(p, "can't assign to numbered parameter");
     3285                    }
    29343286                ;
    29353287
     
    29563308                | keyword__FILE__
    29573309                    {
    2958                       const char *fn = p->filename;
     3310                      const char *fn = mrb_sym_name_len(p->mrb, p->filename_sym, NULL);
    29593311                      if (!fn) {
    29603312                        fn = "(null)";
     
    29663318                      char buf[16];
    29673319
    2968                       snprintf(buf, sizeof(buf), "%d", p->lineno);
    2969                       $$ = new_int(p, buf, 10);
     3320                      dump_int(p->lineno, buf);
     3321                      $$ = new_int(p, buf, 10, 0);
     3322                    }
     3323                | keyword__ENCODING__
     3324                    {
     3325#ifdef MRB_UTF8_STRING
     3326                      const char *enc = "UTF-8";
     3327#else
     3328                      const char *enc = "ASCII-8BIT";
     3329#endif
     3330                      $$ = new_str(p, enc, strlen(enc));
    29703331                    }
    29713332                ;
     
    30073368                ;
    30083369
    3009 f_args          : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
     3370f_label         : tIDENTIFIER tLABEL_TAG
     3371                    {
     3372                      local_nest(p);
     3373                    }
     3374                ;
     3375
     3376f_kw            : f_label arg
     3377                    {
     3378                      void_expr_error(p, $2);
     3379                      $$ = new_kw_arg(p, $1, cons($2, locals_node(p)));
     3380                      local_unnest(p);
     3381                    }
     3382                | f_label
     3383                    {
     3384                      $$ = new_kw_arg(p, $1, 0);
     3385                      local_unnest(p);
     3386                    }
     3387                ;
     3388
     3389f_block_kw      : f_label primary_value
     3390                    {
     3391                      $$ = new_kw_arg(p, $1, cons($2, locals_node(p)));
     3392                      local_unnest(p);
     3393                    }
     3394                | f_label
     3395                    {
     3396                      $$ = new_kw_arg(p, $1, 0);
     3397                      local_unnest(p);
     3398                    }
     3399                ;
     3400
     3401f_block_kwarg   : f_block_kw
     3402                    {
     3403                      $$ = list1($1);
     3404                    }
     3405                | f_block_kwarg ',' f_block_kw
     3406                    {
     3407                      $$ = push($1, $3);
     3408                    }
     3409                ;
     3410
     3411f_kwarg         : f_kw
     3412                    {
     3413                      $$ = list1($1);
     3414                    }
     3415                | f_kwarg ',' f_kw
     3416                    {
     3417                      $$ = push($1, $3);
     3418                    }
     3419                ;
     3420
     3421kwrest_mark     : tPOW
     3422                | tDSTAR
     3423                ;
     3424
     3425f_kwrest        : kwrest_mark tIDENTIFIER
     3426                    {
     3427                      $$ = cons((node*)NODE_KW_REST_ARGS, nsym($2));
     3428                    }
     3429                | kwrest_mark
     3430                    {
     3431                      $$ = cons((node*)NODE_KW_REST_ARGS, 0);
     3432                    }
     3433                ;
     3434
     3435args_tail       : f_kwarg ',' f_kwrest opt_f_block_arg
     3436                    {
     3437                      $$ = new_args_tail(p, $1, $3, $4);
     3438                    }
     3439                | f_kwarg opt_f_block_arg
     3440                    {
     3441                      $$ = new_args_tail(p, $1, 0, $2);
     3442                    }
     3443                | f_kwrest opt_f_block_arg
     3444                    {
     3445                      $$ = new_args_tail(p, 0, $1, $2);
     3446                    }
     3447                | f_block_arg
     3448                    {
     3449                      $$ = new_args_tail(p, 0, 0, $1);
     3450                    }
     3451                ;
     3452
     3453opt_args_tail   : ',' args_tail
     3454                    {
     3455                      $$ = $2;
     3456                    }
     3457                | /* none */
     3458                    {
     3459                      $$ = new_args_tail(p, 0, 0, 0);
     3460                    }
     3461                ;
     3462
     3463f_args          : f_arg ',' f_optarg ',' f_rest_arg opt_args_tail
    30103464                    {
    30113465                      $$ = new_args(p, $1, $3, $5, 0, $6);
    30123466                    }
    3013                 | f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
     3467                | f_arg ',' f_optarg ',' f_rest_arg ',' f_arg opt_args_tail
    30143468                    {
    30153469                      $$ = new_args(p, $1, $3, $5, $7, $8);
    30163470                    }
    3017                 | f_arg ',' f_optarg opt_f_block_arg
     3471                | f_arg ',' f_optarg opt_args_tail
    30183472                    {
    30193473                      $$ = new_args(p, $1, $3, 0, 0, $4);
    30203474                    }
    3021                 | f_arg ',' f_optarg ',' f_arg opt_f_block_arg
     3475                | f_arg ',' f_optarg ',' f_arg opt_args_tail
    30223476                    {
    30233477                      $$ = new_args(p, $1, $3, 0, $5, $6);
    30243478                    }
    3025                 | f_arg ',' f_rest_arg opt_f_block_arg
     3479                | f_arg ',' f_rest_arg opt_args_tail
    30263480                    {
    30273481                      $$ = new_args(p, $1, 0, $3, 0, $4);
    30283482                    }
    3029                 | f_arg ',' f_rest_arg ',' f_arg opt_f_block_arg
     3483                | f_arg ',' f_rest_arg ',' f_arg opt_args_tail
    30303484                    {
    30313485                      $$ = new_args(p, $1, 0, $3, $5, $6);
    30323486                    }
    3033                 | f_arg opt_f_block_arg
     3487                | f_arg opt_args_tail
    30343488                    {
    30353489                      $$ = new_args(p, $1, 0, 0, 0, $2);
    30363490                    }
    3037                 | f_optarg ',' f_rest_arg opt_f_block_arg
     3491                | f_optarg ',' f_rest_arg opt_args_tail
    30383492                    {
    30393493                      $$ = new_args(p, 0, $1, $3, 0, $4);
    30403494                    }
    3041                 | f_optarg ',' f_rest_arg ',' f_arg opt_f_block_arg
     3495                | f_optarg ',' f_rest_arg ',' f_arg opt_args_tail
    30423496                    {
    30433497                      $$ = new_args(p, 0, $1, $3, $5, $6);
    30443498                    }
    3045                 | f_optarg opt_f_block_arg
     3499                | f_optarg opt_args_tail
    30463500                    {
    30473501                      $$ = new_args(p, 0, $1, 0, 0, $2);
    30483502                    }
    3049                 | f_optarg ',' f_arg opt_f_block_arg
     3503                | f_optarg ',' f_arg opt_args_tail
    30503504                    {
    30513505                      $$ = new_args(p, 0, $1, 0, $3, $4);
    30523506                    }
    3053                 | f_rest_arg opt_f_block_arg
     3507                | f_rest_arg opt_args_tail
    30543508                    {
    30553509                      $$ = new_args(p, 0, 0, $1, 0, $2);
    30563510                    }
    3057                 | f_rest_arg ',' f_arg opt_f_block_arg
     3511                | f_rest_arg ',' f_arg opt_args_tail
    30583512                    {
    30593513                      $$ = new_args(p, 0, 0, $1, $3, $4);
    30603514                    }
    3061                 | f_block_arg
     3515                | args_tail
    30623516                    {
    30633517                      $$ = new_args(p, 0, 0, 0, 0, $1);
     
    30653519                | /* none */
    30663520                    {
    3067                       local_add_f(p, 0);
     3521                      local_add_f(p, mrb_intern_lit(p->mrb, "&"));
    30683522                      $$ = new_args(p, 0, 0, 0, 0, 0);
    30693523                    }
     
    30903544                      $$ = 0;
    30913545                    }
     3546                | tNUMPARAM
     3547                    {
     3548                      yyerror(p, "formal argument cannot be a numbered parameter");
     3549                      $$ = 0;
     3550                    }
    30923551                ;
    30933552
     
    31073566                      $$ = new_arg(p, $1);
    31083567                    }
    3109                 | tLPAREN f_margs rparen
    3110                     {
    3111                       $$ = new_masgn(p, $2, 0);
     3568                | tLPAREN
     3569                    {
     3570                      $<nd>$ = local_switch(p);
     3571                    }
     3572                  f_margs rparen
     3573                    {
     3574                      $$ = new_masgn_param(p, $3, p->locals->car);
     3575                      local_resume(p, $<nd>2);
     3576                      local_add_f(p, 0);
    31123577                    }
    31133578                ;
     
    31263591                    {
    31273592                      local_add_f(p, $1);
     3593                      local_nest(p);
    31283594                      $$ = $1;
    31293595                    }
     
    31333599                    {
    31343600                      void_expr_error(p, $2);
    3135                       $$ = cons(nsym($1), $2);
     3601                      $$ = cons(nsym($1), cons($2, locals_node(p)));
     3602                      local_unnest(p);
    31363603                    }
    31373604                ;
     
    31403607                    {
    31413608                      void_expr_error(p, $2);
    3142                       $$ = cons(nsym($1), $2);
     3609                      $$ = cons(nsym($1), cons($2, locals_node(p)));
     3610                      local_unnest(p);
    31433611                    }
    31443612                ;
     
    31753643                | restarg_mark
    31763644                    {
    3177                       local_add_f(p, 0);
     3645                      local_add_f(p, mrb_intern_lit(p->mrb, "*"));
    31783646                      $$ = -1;
    31793647                    }
     
    31863654f_block_arg     : blkarg_mark tIDENTIFIER
    31873655                    {
    3188                       local_add_f(p, $2);
    31893656                      $$ = $2;
    31903657                    }
     
    31973664                | none
    31983665                    {
    3199                       local_add_f(p, 0);
    32003666                      $$ = 0;
    32013667                    }
     
    32443710                      NODE_LINENO($$, $1);
    32453711                    }
    3246                 | assocs ',' assoc
     3712                | assocs comma assoc
    32473713                    {
    32483714                      $$ = push($1, $3);
    32493715                    }
     3716                ;
     3717
     3718label_tag       : tLABEL_TAG
     3719                | tLABEL_TAG heredoc_bodies
    32503720                ;
    32513721
     
    32563726                      $$ = cons($1, $3);
    32573727                    }
    3258                 | tLABEL arg
     3728                | tIDENTIFIER label_tag arg
     3729                    {
     3730                      void_expr_error(p, $3);
     3731                      $$ = cons(new_sym(p, $1), $3);
     3732                    }
     3733                | string_fragment label_tag arg
     3734                    {
     3735                      void_expr_error(p, $3);
     3736                      if ($1->car == (node*)NODE_DSTR) {
     3737                        $$ = cons(new_dsym(p, $1), $3);
     3738                      }
     3739                      else {
     3740                        $$ = cons(new_sym(p, new_strsym(p, $1)), $3);
     3741                      }
     3742                    }
     3743                | tDSTAR arg
    32593744                    {
    32603745                      void_expr_error(p, $2);
    3261                       $$ = cons(new_sym(p, $1), $2);
    3262                     }
    3263                 | tLABEL_END arg
    3264                     {
    3265                       void_expr_error(p, $2);
    3266                       $$ = cons(new_sym(p, new_strsym(p, $1)), $2);
    3267                     }
    3268                 | tSTRING_BEG tLABEL_END arg
    3269                     {
    3270                       void_expr_error(p, $3);
    3271                       $$ = cons(new_sym(p, new_strsym(p, $2)), $3);
    3272                     }
    3273                 | tSTRING_BEG string_rep tLABEL_END arg
    3274                     {
    3275                       void_expr_error(p, $4);
    3276                       $$ = cons(new_dsym(p, push($2, $3)), $4);
     3746                      $$ = cons(cons((node*)NODE_KW_REST_ARGS, 0), $2);
    32773747                    }
    32783748                ;
     
    33233793                ;
    33243794
    3325 rparen          : opt_nl ')'
    3326                 ;
    3327 
    3328 rbracket        : opt_nl ']'
     3795rparen          : opt_terms ')'
    33293796                ;
    33303797
    33313798trailer         : /* none */
    3332                 | nl
     3799                | terms
    33333800                | comma
    33343801                ;
     
    33623829{
    33633830  char* c;
    3364   int n;
     3831  size_t n;
    33653832
    33663833  if (! p->capture_errors) {
    33673834#ifndef MRB_DISABLE_STDIO
    3368     if (p->filename) {
    3369       fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s);
     3835    if (p->filename_sym) {
     3836      const char *filename = mrb_sym_name_len(p->mrb, p->filename_sym, NULL);
     3837      fprintf(stderr, "%s:%d:%d: %s\n", filename, p->lineno, p->column, s);
    33703838    }
    33713839    else {
     
    33863854
    33873855static void
    3388 yyerror_i(parser_state *p, const char *fmt, int i)
     3856yyerror_c(parser_state *p, const char *msg, char c)
    33893857{
    33903858  char buf[256];
    33913859
    3392   snprintf(buf, sizeof(buf), fmt, i);
     3860  strncpy(buf, msg, sizeof(buf) - 2);
     3861  buf[sizeof(buf) - 2] = '\0';
     3862  strncat(buf, &c, 1);
    33933863  yyerror(p, buf);
    33943864}
     
    33983868{
    33993869  char* c;
    3400   int n;
     3870  size_t n;
    34013871
    34023872  if (! p->capture_errors) {
    34033873#ifndef MRB_DISABLE_STDIO
    3404     if (p->filename) {
    3405       fprintf(stderr, "%s:%d:%d: %s\n", p->filename, p->lineno, p->column, s);
     3874    if (p->filename_sym) {
     3875      const char *filename = mrb_sym_name_len(p->mrb, p->filename_sym, NULL);
     3876      fprintf(stderr, "%s:%d:%d: warning: %s\n", filename, p->lineno, p->column, s);
    34063877    }
    34073878    else {
    3408       fprintf(stderr, "line %d:%d: %s\n", p->lineno, p->column, s);
     3879      fprintf(stderr, "line %d:%d: warning: %s\n", p->lineno, p->column, s);
    34093880    }
    34103881#endif
     
    34283899
    34293900static void
    3430 yywarning_s(parser_state *p, const char *fmt, const char *s)
     3901yywarning_s(parser_state *p, const char *msg, const char *s)
    34313902{
    34323903  char buf[256];
    34333904
    3434   snprintf(buf, sizeof(buf), fmt, s);
     3905  strncpy(buf, msg, sizeof(buf) - 1);
     3906  buf[sizeof(buf) - 1] = '\0';
     3907  strncat(buf, ": ", sizeof(buf) - strlen(buf) - 1);
     3908  strncat(buf, s, sizeof(buf) - strlen(buf) - 1);
    34353909  yywarning(p, buf);
    34363910}
     
    34413915  int c;
    34423916
    3443   c = (int)(intptr_t)n->car;
     3917  c = intn(n->car);
    34443918
    34453919  if (c == NODE_NTH_REF) {
    3446     yyerror_i(p, "can't set variable $%" MRB_PRId, (mrb_int)(intptr_t)n->cdr);
     3920    yyerror_c(p, "can't set variable $", (char)intn(n->cdr)+'0');
    34473921  }
    34483922  else if (c == NODE_BACK_REF) {
    3449     yyerror_i(p, "can't set variable $%c", (int)(intptr_t)n->cdr);
     3923    yyerror_c(p, "can't set variable $", (char)intn(n->cdr));
    34503924  }
    34513925  else {
    3452     mrb_bug(p->mrb, "Internal error in backref_error() : n=>car == %S", mrb_fixnum_value(c));
     3926    mrb_bug(p->mrb, "Internal error in backref_error() : n=>car == %d", c);
    34533927  }
    34543928}
     
    34603934
    34613935  if (n == NULL) return;
    3462   c = (int)(intptr_t)n->car;
     3936  c = intn(n->car);
    34633937  switch (c) {
    34643938  case NODE_BREAK:
     
    34713945  case NODE_AND:
    34723946  case NODE_OR:
    3473     void_expr_error(p, n->cdr->car);
    3474     void_expr_error(p, n->cdr->cdr);
     3947    if (n->cdr) {
     3948      void_expr_error(p, n->cdr->car);
     3949      void_expr_error(p, n->cdr->cdr);
     3950    }
    34753951    break;
    34763952  case NODE_BEGIN:
     
    34923968
    34933969static inline int
     3970nextc0(parser_state *p)
     3971{
     3972  int c;
     3973#ifndef MRB_DISABLE_STDIO
     3974  if (p->f) {
     3975    if (feof(p->f)) return -1;
     3976    c = fgetc(p->f);
     3977    if (c == EOF) return -1;
     3978  }
     3979  else
     3980#endif
     3981    if (!p->s || p->s >= p->send) {
     3982      return -1;
     3983    }
     3984    else {
     3985      c = (unsigned char)*p->s++;
     3986    }
     3987  return c;
     3988}
     3989
     3990static inline int
    34943991nextc(parser_state *p)
    34953992{
     
    34993996    node *tmp;
    35003997
    3501     c = (int)(intptr_t)p->pb->car;
     3998    c = intn(p->pb->car);
    35023999    tmp = p->pb;
    35034000    p->pb = p->pb->cdr;
     
    35054002  }
    35064003  else {
    3507 #ifndef MRB_DISABLE_STDIO
    3508     if (p->f) {
    3509       if (feof(p->f)) goto eof;
    3510       c = fgetc(p->f);
    3511       if (c == EOF) goto eof;
    3512     }
    3513     else
    3514 #endif
    3515       if (!p->s || p->s >= p->send) {
    3516         goto eof;
    3517       }
    3518       else {
    3519         c = (unsigned char)*p->s++;
    3520       }
     4004    c = nextc0(p);
     4005    if (c < 0) goto eof;
    35214006  }
    35224007  if (c >= 0) {
     
    35244009  }
    35254010  if (c == '\r') {
    3526     c = nextc(p);
    3527     if (c != '\n') {
    3528       pushback(p, c);
    3529       return '\r';
    3530     }
    3531     return c;
     4011    const int lf = nextc0(p);
     4012    if (lf == '\n') {
     4013      return '\n';
     4014    }
     4015    if (lf > 0) pushback(p, lf);
    35324016  }
    35334017  return c;
     
    35484032    p->column--;
    35494033  }
    3550   p->pb = cons((node*)(intptr_t)c, p->pb);
     4034  p->pb = cons(nint(c), p->pb);
    35514035}
    35524036
     
    35734057    if (c0 == -1) return c0;    /* do not skip partial EOF */
    35744058    if (c0 >= 0) --p->column;
    3575     list = push(list, (node*)(intptr_t)c0);
     4059    list = push(list, nint(c0));
    35764060  } while(n--);
    35774061  if (p->pb) {
     
    35944078peeks(parser_state *p, const char *s)
    35954079{
    3596   int len = strlen(s);
     4080  size_t len = strlen(s);
    35974081
    35984082#ifndef MRB_DISABLE_STDIO
     
    36304114    s++;
    36314115    if (peeks(p, s)) {
    3632       int len = strlen(s);
     4116      size_t len = strlen(s);
    36334117
    36344118      while (len--) {
     
    37524236#define IS_LABEL_SUFFIX(n) (peek_n(p, ':',(n)) && !peek_n(p, ':', (n)+1))
    37534237
    3754 static int
     4238static int32_t
    37554239scan_oct(const int *start, int len, int *retlen)
    37564240{
    37574241  const int *s = start;
    3758   int retval = 0;
     4242  int32_t retval = 0;
    37594243
    37604244  /* mrb_assert(len <= 3) */
     
    37634247    retval |= *s++ - '0';
    37644248  }
    3765   *retlen = s - start;
     4249  *retlen = (int)(s - start);
    37664250
    37674251  return retval;
     
    37694253
    37704254static int32_t
    3771 scan_hex(const int *start, int len, int *retlen)
     4255scan_hex(parser_state *p, const int *start, int len, int *retlen)
    37724256{
    37734257  static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
    37744258  const int *s = start;
    3775   int32_t retval = 0;
     4259  uint32_t retval = 0;
    37764260  char *tmp;
    37774261
     
    37824266    s++;
    37834267  }
    3784   *retlen = s - start;
    3785 
    3786   return retval;
     4268  *retlen = (int)(s - start);
     4269
     4270  return (int32_t)retval;
    37874271}
    37884272
     
    37904274read_escape_unicode(parser_state *p, int limit)
    37914275{
    3792   int32_t c;
    37934276  int buf[9];
    37944277  int i;
     4278  int32_t hex;
    37954279
    37964280  /* Look for opening brace */
    37974281  i = 0;
    37984282  buf[0] = nextc(p);
    3799   if (buf[0] < 0) goto eof;
     4283  if (buf[0] < 0) {
     4284  eof:
     4285    yyerror(p, "invalid escape character syntax");
     4286    return -1;
     4287  }
    38004288  if (ISXDIGIT(buf[0])) {
    38014289    /* \uxxxx form */
     
    38124300    pushback(p, buf[0]);
    38134301  }
    3814   c = scan_hex(buf, i, &i);
    3815   if (i == 0) {
    3816   eof:
    3817     yyerror(p, "Invalid escape character syntax");
     4302  hex = scan_hex(p, buf, i, &i);
     4303  if (i == 0 || hex > 0x10FFFF || (hex & 0xFFFFF800) == 0xD800) {
     4304    yyerror(p, "invalid Unicode code point");
    38184305    return -1;
    38194306  }
    3820   if (c < 0 || c > 0x10FFFF || (c & 0xFFFFF800) == 0xD800) {
    3821     yyerror(p, "Invalid Unicode code point");
    3822     return -1;
    3823   }
    3824   return c;
     4307  return hex;
    38254308}
    38264309
     
    38884371      }
    38894372    }
    3890     c = scan_hex(buf, i, &i);
    38914373    if (i == 0) {
    3892       yyerror(p, "Invalid escape character syntax");
    3893       return 0;
    3894     }
    3895   }
    3896   return c;
     4374      yyerror(p, "invalid hex escape");
     4375      return -1;
     4376    }
     4377    return scan_hex(p, buf, i, &i);
     4378  }
    38974379
    38984380  case 'u':     /* Unicode */
     
    39614443  int c;
    39624444  string_type type = (string_type)(intptr_t)p->lex_strterm->car;
    3963   int nest_level = (intptr_t)p->lex_strterm->cdr->car;
    3964   int beg = (intptr_t)p->lex_strterm->cdr->cdr->car;
    3965   int end = (intptr_t)p->lex_strterm->cdr->cdr->cdr;
     4445  int nest_level = intn(p->lex_strterm->cdr->car);
     4446  int beg = intn(p->lex_strterm->cdr->cdr->car);
     4447  int end = intn(p->lex_strterm->cdr->cdr->cdr);
    39664448  parser_heredoc_info *hinf = (type & STR_FUNC_HEREDOC) ? parsing_heredoc_inf(p) : NULL;
    3967   int cmd_state = p->cmd_start;
    39684449
    39694450  if (beg == 0) beg = -3;       /* should never happen */
     
    39904471        }
    39914472        if ((len-1 == hinf->term_len) && (strncmp(s, hinf->term, len-1) == 0)) {
    3992           if (c < 0) {
    3993             p->parsing_heredoc = NULL;
    3994           }
    3995           else {
    3996             return tHEREDOC_END;
    3997           }
     4473          return tHEREDOC_END;
    39984474        }
    39994475      }
    40004476      if (c < 0) {
    40014477        char buf[256];
    4002         snprintf(buf, sizeof(buf), "can't find heredoc delimiter \"%s\" anywhere before EOF", hinf->term);
    4003         yyerror(p, buf);
     4478        const char s1[] = "can't find heredoc delimiter \"";
     4479        const char s2[] = "\" anywhere before EOF";
     4480
     4481        if (sizeof(s1)+sizeof(s2)+strlen(hinf->term)+1 >= sizeof(buf)) {
     4482          yyerror(p, "can't find heredoc delimiter anywhere before EOF");
     4483        } else {
     4484          strcpy(buf, s1);
     4485          strcat(buf, hinf->term);
     4486          strcat(buf, s2);
     4487          yyerror(p, buf);
     4488        }
    40044489        return 0;
    40054490      }
     
    40134498    else if (c == beg) {
    40144499      nest_level++;
    4015       p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level;
     4500      p->lex_strterm->cdr->car = nint(nest_level);
    40164501    }
    40174502    else if (c == end) {
    40184503      nest_level--;
    4019       p->lex_strterm->cdr->car = (node*)(intptr_t)nest_level;
     4504      p->lex_strterm->cdr->car = nint(nest_level);
    40204505    }
    40214506    else if (c == '\\') {
     
    41194604
    41204605  tokfix(p);
    4121   p->lstate = EXPR_END;
     4606  p->lstate = EXPR_ENDARG;
    41224607  end_strterm(p);
    41234608
     
    41454630      case 'u': f |= 16; break;
    41464631      case 'n': f |= 32; break;
     4632      case 'o': break;
    41474633      default: tokadd(p, re_opt); break;
    41484634      }
     
    41514637    if (toklen(p)) {
    41524638      char msg[128];
     4639
     4640      strcpy(msg, "unknown regexp option");
    41534641      tokfix(p);
    4154       snprintf(msg, sizeof(msg), "unknown regexp option%s - %s",
    4155           toklen(p) > 1 ? "s" : "", tok(p));
     4642      if (toklen(p) > 1) {
     4643        strcat(msg, "s");
     4644      }
     4645      strcat(msg, " - ");
     4646      strncat(msg, tok(p), sizeof(msg) - strlen(msg) - 1);
    41564647      yyerror(p, msg);
    41574648    }
     
    41804671  }
    41814672  pylval.nd = new_str(p, tok(p), toklen(p));
    4182   if (IS_LABEL_POSSIBLE()) {
    4183     if (IS_LABEL_SUFFIX(0)) {
    4184       p->lstate = EXPR_BEG;
    4185       nextc(p);
    4186       return tLABEL_END;
    4187     }
    4188   }
    41894673
    41904674  return tSTRING;
    41914675}
    41924676
     4677static int
     4678number_literal_suffix(parser_state *p)
     4679{
     4680  int c, result = 0;
     4681  node *list = 0;
     4682  int column = p->column;
     4683  int mask = NUM_SUFFIX_R|NUM_SUFFIX_I;
     4684
     4685  while ((c = nextc(p)) != -1) {
     4686    list = push(list, (node*)(intptr_t)c);
     4687
     4688    if ((mask & NUM_SUFFIX_I) && c == 'i') {
     4689      result |= (mask & NUM_SUFFIX_I);
     4690      mask &= ~NUM_SUFFIX_I;
     4691      /* r after i, rational of complex is disallowed */
     4692      mask &= ~NUM_SUFFIX_R;
     4693      continue;
     4694    }
     4695    if ((mask & NUM_SUFFIX_R) && c == 'r') {
     4696      result |= (mask & NUM_SUFFIX_R);
     4697      mask &= ~NUM_SUFFIX_R;
     4698      continue;
     4699    }
     4700    if (!ISASCII(c) || ISALPHA(c) || c == '_') {
     4701      p->column = column;
     4702      if (p->pb) {
     4703        p->pb = append((node*)list, p->pb);
     4704      }
     4705      else {
     4706        p->pb = list;
     4707      }
     4708      return 0;
     4709    }
     4710    pushback(p, c);
     4711    break;
     4712  }
     4713  return result;
     4714}
    41934715
    41944716static int
     
    43114833  case -2:      /* end of a file */
    43124834  case '\n':
    4313     maybe_heredoc:
     4835  maybe_heredoc:
    43144836    heredoc_treat_nextline(p);
    4315   switch (p->lstate) {
    4316   case EXPR_BEG:
    4317   case EXPR_FNAME:
    4318   case EXPR_DOT:
    4319   case EXPR_CLASS:
    4320   case EXPR_VALUE:
    4321     p->lineno++;
    43224837    p->column = 0;
     4838    switch (p->lstate) {
     4839    case EXPR_BEG:
     4840    case EXPR_FNAME:
     4841    case EXPR_DOT:
     4842    case EXPR_CLASS:
     4843    case EXPR_VALUE:
     4844      p->lineno++;
     4845      if (p->parsing_heredoc != NULL) {
     4846        if (p->lex_strterm) {
     4847          return parse_string(p);
     4848        }
     4849      }
     4850      goto retry;
     4851    default:
     4852      break;
     4853    }
    43234854    if (p->parsing_heredoc != NULL) {
    4324       if (p->lex_strterm) {
    4325         return parse_string(p);
    4326       }
    4327     }
    4328     goto retry;
    4329   default:
    4330     break;
    4331   }
    4332   if (p->parsing_heredoc != NULL) {
     4855      return '\n';
     4856    }
     4857    while ((c = nextc(p))) {
     4858      switch (c) {
     4859      case ' ': case '\t': case '\f': case '\r':
     4860      case '\13': /* '\v' */
     4861        space_seen = 1;
     4862        break;
     4863      case '#': /* comment as a whitespace */
     4864        pushback(p, '#');
     4865        p->lineno++;
     4866        goto retry;
     4867      case '.':
     4868        if (!peek(p, '.')) {
     4869          pushback(p, '.');
     4870          p->lineno++;
     4871          goto retry;
     4872        }
     4873        pushback(p, c);
     4874        goto normal_newline;
     4875      case '&':
     4876        if (peek(p, '.')) {
     4877          pushback(p, '&');
     4878          p->lineno++;
     4879          goto retry;
     4880        }
     4881        pushback(p, c);
     4882        goto normal_newline;
     4883      case -1:                  /* EOF */
     4884      case -2:                  /* end of a file */
     4885        goto normal_newline;
     4886      default:
     4887        pushback(p, c);
     4888        goto normal_newline;
     4889      }
     4890    }
     4891  normal_newline:
     4892    p->cmd_start = TRUE;
     4893    p->lstate = EXPR_BEG;
    43334894    return '\n';
    4334   }
    4335   while ((c = nextc(p))) {
    4336     switch (c) {
    4337     case ' ': case '\t': case '\f': case '\r':
    4338     case '\13': /* '\v' */
    4339       space_seen = 1;
    4340       break;
    4341     case '.':
    4342       if ((c = nextc(p)) != '.') {
    4343         pushback(p, c);
    4344         pushback(p, '.');
    4345         goto retry;
    4346       }
    4347     case -1:                  /* EOF */
    4348     case -2:                  /* end of a file */
    4349       goto normal_newline;
    4350     default:
    4351       pushback(p, c);
    4352       goto normal_newline;
    4353     }
    4354   }
    4355   normal_newline:
    4356   p->cmd_start = TRUE;
    4357   p->lstate = EXPR_BEG;
    4358   return '\n';
    43594895
    43604896  case '*':
    43614897    if ((c = nextc(p)) == '*') {
    43624898      if ((c = nextc(p)) == '=') {
    4363         pylval.id = intern("**",2);
     4899        pylval.id = intern_lit("**");
    43644900        p->lstate = EXPR_BEG;
    43654901        return tOP_ASGN;
    43664902      }
    43674903      pushback(p, c);
    4368       c = tPOW;
     4904      if (IS_SPCARG(c)) {
     4905        yywarning(p, "'**' interpreted as argument prefix");
     4906        c = tDSTAR;
     4907      }
     4908      else if (IS_BEG()) {
     4909        c = tDSTAR;
     4910      }
     4911      else {
     4912        c = tPOW; /* "**", "argument prefix" */
     4913      }
    43694914    }
    43704915    else {
    43714916      if (c == '=') {
    4372         pylval.id = intern_c('*');
     4917        pylval.id = intern_lit("*");
    43734918        p->lstate = EXPR_BEG;
    43744919        return tOP_ASGN;
     
    44865031    if (c == '<') {
    44875032      if ((c = nextc(p)) == '=') {
    4488         pylval.id = intern("<<",2);
     5033        pylval.id = intern_lit("<<");
    44895034        p->lstate = EXPR_BEG;
    44905035        return tOP_ASGN;
     
    45085053    if (c == '>') {
    45095054      if ((c = nextc(p)) == '=') {
    4510         pylval.id = intern(">>",2);
     5055        pylval.id = intern_lit(">>");
    45115056        p->lstate = EXPR_BEG;
    45125057        return tOP_ASGN;
     
    45795124        if (c2) {
    45805125          char buf[256];
    4581           snprintf(buf, sizeof(buf), "invalid character syntax; use ?\\%c", c2);
     5126          char cc[] = { (char)c2, '\0' };
     5127
     5128          strcpy(buf, "invalid character syntax; use ?\\");
     5129          strncat(buf, cc, 2);
    45825130          yyerror(p, buf);
    45835131        }
     
    45905138    newtok(p);
    45915139    /* need support UTF-8 if configured */
    4592     if ((isalnum(c) || c == '_')) {
     5140    if ((ISALNUM(c) || c == '_')) {
    45935141      int c2 = nextc(p);
    45945142      pushback(p, c2);
    4595       if ((isalnum(c2) || c2 == '_')) {
     5143      if ((ISALNUM(c2) || c2 == '_')) {
    45965144        goto ternary;
    45975145      }
     
    46065154    tokfix(p);
    46075155    pylval.nd = new_str(p, tok(p), toklen(p));
    4608     p->lstate = EXPR_END;
     5156    p->lstate = EXPR_ENDARG;
    46095157    return tCHAR;
    46105158
     
    46135161      p->lstate = EXPR_BEG;
    46145162      if ((c = nextc(p)) == '=') {
    4615         pylval.id = intern("&&",2);
     5163        pylval.id = intern_lit("&&");
    46165164        p->lstate = EXPR_BEG;
    46175165        return tOP_ASGN;
     
    46255173    }
    46265174    else if (c == '=') {
    4627       pylval.id = intern_c('&');
     5175      pylval.id = intern_lit("&");
    46285176      p->lstate = EXPR_BEG;
    46295177      return tOP_ASGN;
     
    46525200      p->lstate = EXPR_BEG;
    46535201      if ((c = nextc(p)) == '=') {
    4654         pylval.id = intern("||",2);
     5202        pylval.id = intern_lit("||");
    46555203        p->lstate = EXPR_BEG;
    46565204        return tOP_ASGN;
     
    46605208    }
    46615209    if (c == '=') {
    4662       pylval.id = intern_c('|');
     5210      pylval.id = intern_lit("|");
    46635211      p->lstate = EXPR_BEG;
    46645212      return tOP_ASGN;
     
    46845232    }
    46855233    if (c == '=') {
    4686       pylval.id = intern_c('+');
     5234      pylval.id = intern_lit("+");
    46875235      p->lstate = EXPR_BEG;
    46885236      return tOP_ASGN;
     
    47125260    }
    47135261    if (c == '=') {
    4714       pylval.id = intern_c('-');
     5262      pylval.id = intern_lit("-");
    47155263      p->lstate = EXPR_BEG;
    47165264      return tOP_ASGN;
     
    47535301  {
    47545302    int is_float, seen_point, seen_e, nondigit;
     5303    int suffix = 0;
    47555304
    47565305    is_float = seen_point = seen_e = nondigit = 0;
    4757     p->lstate = EXPR_END;
     5306    p->lstate = EXPR_ENDARG;
    47585307    newtok(p);
    47595308    if (c == '-' || c == '+') {
     
    47865335        }
    47875336        else if (nondigit) goto trailing_uc;
    4788         pylval.nd = new_int(p, tok(p), 16);
     5337        suffix = number_literal_suffix(p);
     5338        pylval.nd = new_int(p, tok(p), 16, suffix);
    47895339        return tINTEGER;
    47905340      }
     
    48105360        }
    48115361        else if (nondigit) goto trailing_uc;
    4812         pylval.nd = new_int(p, tok(p), 2);
     5362        suffix = number_literal_suffix(p);
     5363        pylval.nd = new_int(p, tok(p), 2, suffix);
    48135364        return tINTEGER;
    48145365      }
     
    48345385        }
    48355386        else if (nondigit) goto trailing_uc;
    4836         pylval.nd = new_int(p, tok(p), 10);
     5387        suffix = number_literal_suffix(p);
     5388        pylval.nd = new_int(p, tok(p), 10, suffix);
    48375389        return tINTEGER;
    48385390      }
     
    48675419          tokfix(p);
    48685420          if (nondigit) goto trailing_uc;
    4869           pylval.nd = new_int(p, tok(p), 8);
     5421          suffix = number_literal_suffix(p);
     5422          pylval.nd = new_int(p, tok(p), 8, suffix);
    48705423          return tINTEGER;
    48715424        }
     
    48845437      else {
    48855438        pushback(p, c);
    4886         pylval.nd = new_int(p, "0", 10);
     5439        suffix = number_literal_suffix(p);
     5440        pylval.nd = new_int(p, "0", 10, suffix);
    48875441        return tINTEGER;
    48885442      }
     
    49525506    if (nondigit) {
    49535507      trailing_uc:
    4954       yyerror_i(p, "trailing '%c' in number", nondigit);
     5508      yyerror_c(p, "trailing non digit in number: ", (char)nondigit);
    49555509    }
    49565510    tokfix(p);
    49575511    if (is_float) {
     5512#ifdef MRB_WITHOUT_FLOAT
     5513      yywarning_s(p, "floating point numbers are not supported", tok(p));
     5514      pylval.nd = new_int(p, "0", 10, 0);
     5515      return tINTEGER;
     5516#else
    49585517      double d;
    49595518      char *endp;
     
    49625521      d = mrb_float_read(tok(p), &endp);
    49635522      if (d == 0 && endp == tok(p)) {
    4964         yywarning_s(p, "corrupted float value %s", tok(p));
     5523        yywarning_s(p, "corrupted float value", tok(p));
    49655524      }
    49665525      else if (errno == ERANGE) {
    4967         yywarning_s(p, "float %s out of range", tok(p));
     5526        yywarning_s(p, "float out of range", tok(p));
    49685527        errno = 0;
    49695528      }
    4970       pylval.nd = new_float(p, tok(p));
     5529      suffix = number_literal_suffix(p);
     5530      pylval.nd = new_float(p, tok(p), suffix);
    49715531      return tFLOAT;
    4972     }
    4973     pylval.nd = new_int(p, tok(p), 10);
     5532#endif
     5533    }
     5534    suffix = number_literal_suffix(p);
     5535    pylval.nd = new_int(p, tok(p), 10, suffix);
    49745536    return tINTEGER;
    49755537  }
     
    49855547      p->lstate = EXPR_ENDFN;
    49865548    else
    4987       p->lstate = EXPR_ENDARG;
     5549      p->lstate = EXPR_END;
    49885550    return c;
    49895551
     
    49985560      return tCOLON2;
    49995561    }
    5000     if (IS_END() || ISSPACE(c)) {
     5562    if (!space_seen && IS_END()) {
    50015563      pushback(p, c);
    50025564      p->lstate = EXPR_BEG;
    5003       return ':';
     5565      return tLABEL_TAG;
     5566    }
     5567    if (!ISSPACE(c) || IS_BEG()) {
     5568      pushback(p, c);
     5569      p->lstate = EXPR_FNAME;
     5570      return tSYMBEG;
    50045571    }
    50055572    pushback(p, c);
    5006     p->lstate = EXPR_FNAME;
    5007     return tSYMBEG;
     5573    p->lstate = EXPR_BEG;
     5574    return ':';
    50085575
    50095576  case '/':
     
    50135580    }
    50145581    if ((c = nextc(p)) == '=') {
    5015       pylval.id = intern_c('/');
     5582      pylval.id = intern_lit("/");
    50165583      p->lstate = EXPR_BEG;
    50175584      return tOP_ASGN;
     
    50325599  case '^':
    50335600    if ((c = nextc(p)) == '=') {
    5034       pylval.id = intern_c('^');
     5601      pylval.id = intern_lit("^");
    50355602      p->lstate = EXPR_BEG;
    50365603      return tOP_ASGN;
     
    50705637    }
    50715638    else if (IS_SPCARG(-1)) {
     5639      c = tLPAREN_ARG;
     5640    }
     5641    else if (p->lstate == EXPR_END && space_seen) {
    50725642      c = tLPAREN_ARG;
    50735643    }
     
    51475717      else {
    51485718        term = nextc(p);
    5149         if (isalnum(term)) {
     5719        if (ISALNUM(term)) {
    51505720          yyerror(p, "unknown type of %string");
    51515721          return 0;
     
    52065776    }
    52075777    if ((c = nextc(p)) == '=') {
    5208       pylval.id = intern_c('%');
     5778      pylval.id = intern_lit("%");
    52095779      p->lstate = EXPR_BEG;
    52105780      return tOP_ASGN;
     
    52605830      tokadd(p, c);
    52615831      tokfix(p);
    5262       pylval.id = intern_cstr(tok(p));
     5832      pylval.id = intern(tok(p), toklen(p));
    52635833      return tGVAR;
    52645834
     
    52705840      gvar:
    52715841      tokfix(p);
    5272       pylval.id = intern_cstr(tok(p));
     5842      pylval.id = intern(tok(p), toklen(p));
    52735843      return tGVAR;
    52745844
     
    52915861        tokadd(p, c);
    52925862        c = nextc(p);
    5293       } while (c >= 0 && isdigit(c));
     5863      } while (c >= 0 && ISDIGIT(c));
    52945864      pushback(p, c);
    52955865      if (last_state == EXPR_FNAME) goto gvar;
     
    52985868        unsigned long n = strtoul(tok(p), NULL, 10);
    52995869        if (n > INT_MAX) {
    5300           yyerror_i(p, "capture group index must be <= %d", INT_MAX);
     5870          yyerror(p, "capture group index must be <= " MRB_STRINGIZE(INT_MAX));
    53015871          return 0;
    53025872        }
     
    53335903        return 0;
    53345904      }
    5335       else if (isdigit(c)) {
     5905      else if (ISDIGIT(c)) {
    53365906        if (p->tidx == 1) {
    5337           yyerror_i(p, "'@%c' is not allowed as an instance variable name", c);
     5907          yyerror_c(p, "wrong instance variable name: @", c);
    53385908        }
    53395909        else {
    5340           yyerror_i(p, "'@@%c' is not allowed as a class variable name", c);
     5910          yyerror_c(p, "wrong class variable name: @@", c);
    53415911        }
    53425912        return 0;
     
    53545924    default:
    53555925      if (!identchar(c)) {
    5356         yyerror_i(p,  "Invalid char '\\x%02X' in expression", c);
     5926        char buf[36];
     5927        const char s[] = "Invalid char in expression: 0x";
     5928        const char hexdigits[] = "0123456789ABCDEF";
     5929
     5930        strcpy(buf, s);
     5931        buf[sizeof(s)-1] = hexdigits[(c & 0xf0) >> 4];
     5932        buf[sizeof(s)]   = hexdigits[(c & 0x0f)];
     5933        buf[sizeof(s)+1] = 0;
     5934        yyerror(p, buf);
    53575935        goto retry;
    53585936      }
     
    54005978      break;
    54015979
     5980    case '_':
     5981      if (toklen(p) == 2 && ISDIGIT(tok(p)[1]) && p->nvars) {
     5982        int n = tok(p)[1] - '0';
     5983        int nvar;
     5984
     5985        if (n > 0) {
     5986          node *nvars = p->nvars->cdr;
     5987
     5988          while (nvars) {
     5989            nvar = intn(nvars->car);
     5990            if (nvar == -2) break; /* top of the scope */
     5991            if (nvar > 0) {
     5992              yywarning(p, "numbered parameter used in outer block");
     5993              break;
     5994            }
     5995            nvars->car = nint(-1);
     5996            nvars = nvars->cdr;
     5997          }
     5998          nvar = intn(p->nvars->car);
     5999          if (nvar == -1) {
     6000            yywarning(p, "numbered parameter used in inner block");
     6001          }
     6002          if (nvar >= -1) {
     6003            pylval.num = n;
     6004            p->lstate = EXPR_END;
     6005            return tNUMPARAM;
     6006          }
     6007          else {
     6008            yywarning(p, "identifier for numbered parameter; consider another name");
     6009          }
     6010        }
     6011      }
     6012      /* fall through */
    54026013    default:
    54036014      if (toklast(p) == '!' || toklast(p) == '?') {
     
    54066017      else {
    54076018        if (p->lstate == EXPR_FNAME) {
     6019          if ((c = nextc(p)) == '=' && !peek(p, '~') && !peek(p, '>') &&
     6020              (!peek(p, '=') || (peek_n(p, '>', 1)))) {
     6021            result = tIDENTIFIER;
     6022            tokadd(p, c);
     6023            tokfix(p);
     6024          }
     6025          else {
     6026            pushback(p, c);
     6027          }
    54086028          if ((c = nextc(p)) == '=' && !peek(p, '~') && !peek(p, '>') &&
    54096029              (!peek(p, '=') || (peek_n(p, '>', 1)))) {
     
    54266046      if (IS_LABEL_POSSIBLE()) {
    54276047        if (IS_LABEL_SUFFIX(0)) {
    5428           p->lstate = EXPR_BEG;
    5429           nextc(p);
     6048          p->lstate = EXPR_END;
    54306049          tokfix(p);
    5431           pylval.id = intern_cstr(tok(p));
    5432           return tLABEL;
     6050          pylval.id = intern(tok(p), toklen(p));
     6051          return tIDENTIFIER;
    54336052        }
    54346053      }
     
    54886107    }
    54896108    {
    5490       mrb_sym ident = intern_cstr(tok(p));
     6109      mrb_sym ident = intern(tok(p), toklen(p));
    54916110
    54926111      pylval.id = ident;
    5493 #if 0
    5494       if (last_state != EXPR_DOT && islower(tok(p)[0]) && lvar_defined(ident)) {
     6112      if (last_state != EXPR_DOT && ISLOWER(tok(p)[0]) && local_var_p(p, ident)) {
    54956113        p->lstate = EXPR_END;
    54966114      }
    5497 #endif
    54986115    }
    54996116    return result;
     
    55246141  p->capture_errors = cxt->capture_errors;
    55256142  p->no_optimize = cxt->no_optimize;
     6143  p->on_eval = cxt->on_eval;
    55266144  if (cxt->partial_hook) {
    55276145    p->cxt = cxt;
     
    55366154
    55376155  if (!cxt) return;
    5538   if ((int)(intptr_t)p->tree->car != NODE_SCOPE) return;
     6156  if (intn(p->tree->car) != NODE_SCOPE) return;
    55396157  n0 = n = p->tree->cdr->car;
    55406158  while (n) {
     
    55596177
    55606178  MRB_TRY(p->jmp) {
    5561     int n;
     6179    int n = 1;
    55626180
    55636181    p->cmd_start = TRUE;
     
    56756293{
    56766294  if (s) {
    5677     int len = strlen(s);
     6295    size_t len = strlen(s);
    56786296    char *p = (char *)mrb_malloc(mrb, len + 1);
    56796297
     
    57026320
    57036321  sym = mrb_intern_cstr(p->mrb, f);
    5704   p->filename = mrb_sym2name_len(p->mrb, sym, NULL);
     6322  p->filename_sym = sym;
    57056323  p->lineno = (p->filename_table_length > 0)? 0 : 1;
    57066324
    57076325  for (i = 0; i < p->filename_table_length; ++i) {
    57086326    if (p->filename_table[i] == sym) {
    5709       p->current_filename_index = i;
     6327      p->current_filename_index = (int)i;
    57106328      return;
    57116329    }
    57126330  }
    57136331
     6332  if (p->filename_table_length == UINT16_MAX) {
     6333    yyerror(p, "too many files to compile");
     6334    return;
     6335  }
    57146336  p->current_filename_index = p->filename_table_length++;
    57156337
    57166338  new_table = (mrb_sym*)parser_palloc(p, sizeof(mrb_sym) * p->filename_table_length);
    57176339  if (p->filename_table) {
    5718     memmove(new_table, p->filename_table, sizeof(mrb_sym) * p->filename_table_length);
     6340    memmove(new_table, p->filename_table, sizeof(mrb_sym) * p->current_filename_index);
    57196341  }
    57206342  p->filename_table = new_table;
     
    57226344}
    57236345
    5724 MRB_API char const*
     6346MRB_API mrb_sym
    57256347mrb_parser_get_filename(struct mrb_parser_state* p, uint16_t idx) {
    5726   if (idx >= p->filename_table_length) { return NULL; }
     6348  if (idx >= p->filename_table_length) return 0;
    57276349  else {
    5728     return mrb_sym2name_len(p->mrb, p->filename_table[idx], NULL);
     6350    return p->filename_table[idx];
    57296351  }
    57306352}
     
    57476369
    57486370MRB_API parser_state*
    5749 mrb_parse_nstring(mrb_state *mrb, const char *s, int len, mrbc_context *c)
     6371mrb_parse_nstring(mrb_state *mrb, const char *s, size_t len, mrbc_context *c)
    57506372{
    57516373  parser_state *p;
     
    57786400  }
    57796401  if (!p->tree || p->nerr) {
     6402    if (c) c->parser_nerr = p->nerr;
    57806403    if (p->capture_errors) {
    57816404      char buf[256];
    5782       int n;
    5783 
    5784       n = snprintf(buf, sizeof(buf), "line %d: %s\n",
    5785           p->error_buffer[0].lineno, p->error_buffer[0].message);
    5786       mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, n));
     6405
     6406      strcpy(buf, "line ");
     6407      dump_int(p->error_buffer[0].lineno, buf+5);
     6408      strcat(buf, ": ");
     6409      strncat(buf, p->error_buffer[0].message, sizeof(buf) - strlen(buf) - 1);
     6410      mrb->exc = mrb_obj_ptr(mrb_exc_new(mrb, E_SYNTAX_ERROR, buf, strlen(buf)));
    57876411      mrb_parser_free(p);
    57886412      return mrb_undef_value();
     
    58176441    }
    58186442  }
    5819   proc->target_class = target;
     6443  MRB_PROC_SET_TARGET_CLASS(proc, target);
    58206444  if (mrb->c->ci) {
    58216445    mrb->c->ci->target_class = target;
     
    58416465
    58426466MRB_API mrb_value
    5843 mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *c)
     6467mrb_load_nstring_cxt(mrb_state *mrb, const char *s, size_t len, mrbc_context *c)
    58446468{
    58456469  return mrb_load_exec(mrb, mrb_parse_nstring(mrb, s, len, c), c);
     
    58476471
    58486472MRB_API mrb_value
    5849 mrb_load_nstring(mrb_state *mrb, const char *s, int len)
     6473mrb_load_nstring(mrb_state *mrb, const char *s, size_t len)
    58506474{
    58516475  return mrb_load_nstring_cxt(mrb, s, len, NULL);
     
    58856509}
    58866510
     6511static void
     6512dump_args(mrb_state *mrb, node *n, int offset)
     6513{
     6514  if (n->car) {
     6515    dump_prefix(n, offset+1);
     6516    printf("mandatory args:\n");
     6517    dump_recur(mrb, n->car, offset+2);
     6518  }
     6519  n = n->cdr;
     6520  if (n->car) {
     6521    dump_prefix(n, offset+1);
     6522    printf("optional args:\n");
     6523    {
     6524      node *n2 = n->car;
     6525
     6526      while (n2) {
     6527        dump_prefix(n2, offset+2);
     6528        printf("%s=\n", mrb_sym_name(mrb, sym(n2->car->car)));
     6529        mrb_parser_dump(mrb, n2->car->cdr, offset+3);
     6530        n2 = n2->cdr;
     6531      }
     6532    }
     6533  }
     6534  n = n->cdr;
     6535  if (n->car) {
     6536    dump_prefix(n, offset+1);
     6537    printf("rest=*%s\n", mrb_sym_name(mrb, sym(n->car)));
     6538  }
     6539  n = n->cdr;
     6540  if (n->car) {
     6541    dump_prefix(n, offset+1);
     6542    printf("post mandatory args:\n");
     6543    dump_recur(mrb, n->car, offset+2);
     6544  }
     6545
     6546  n = n->cdr;
     6547  if (n) {
     6548    mrb_assert(intn(n->car) == NODE_ARGS_TAIL);
     6549    mrb_parser_dump(mrb, n, offset);
     6550  }
     6551}
     6552
     6553/*
     6554 * This function restores the GC arena on return.
     6555 * For this reason, if a process that further generates an object is
     6556 * performed at the caller, the string pointer returned as the return
     6557 * value may become invalid.
     6558 */
     6559static const char*
     6560str_dump(mrb_state *mrb, const char *str, int len)
     6561{
     6562  mrb_int ai = mrb_gc_arena_save(mrb);
     6563  mrb_value s;
     6564# if INT_MAX > MRB_INT_MAX / 4
     6565  /* check maximum length with "\xNN" charactor */
     6566  if (len > MRB_INT_MAX / 4) {
     6567    len = MRB_INT_MAX / 4;
     6568  }
     6569# endif
     6570  s = mrb_str_new(mrb, str, (mrb_int)len);
     6571  s = mrb_str_dump(mrb, s);
     6572  mrb_gc_arena_restore(mrb, ai);
     6573  return RSTRING_PTR(s);
     6574}
    58876575#endif
    58886576
     
    58966584  again:
    58976585  dump_prefix(tree, offset);
    5898   nodetype = (int)(intptr_t)tree->car;
     6586  nodetype = intn(tree->car);
    58996587  tree = tree->cdr;
    59006588  switch (nodetype) {
     
    59566644
    59576645  case NODE_LAMBDA:
    5958     printf("NODE_BLOCK:\n");
     6646    printf("NODE_LAMBDA:\n");
     6647    dump_prefix(tree, offset);
    59596648    goto block;
    59606649
     
    59646653    tree = tree->cdr;
    59656654    if (tree->car) {
    5966       node *n = tree->car;
    5967 
    5968       if (n->car) {
    5969         dump_prefix(n, offset+1);
    5970         printf("mandatory args:\n");
    5971         dump_recur(mrb, n->car, offset+2);
    5972       }
    5973       n = n->cdr;
    5974       if (n->car) {
    5975         dump_prefix(n, offset+1);
    5976         printf("optional args:\n");
    5977         {
    5978           node *n2 = n->car;
    5979 
    5980           while (n2) {
    5981             dump_prefix(n2, offset+2);
    5982             printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
    5983             mrb_parser_dump(mrb, n2->car->cdr, 0);
    5984             n2 = n2->cdr;
    5985           }
    5986         }
    5987       }
    5988       n = n->cdr;
    5989       if (n->car) {
    5990         dump_prefix(n, offset+1);
    5991         printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
    5992       }
    5993       n = n->cdr;
    5994       if (n->car) {
    5995         dump_prefix(n, offset+1);
    5996         printf("post mandatory args:\n");
    5997         dump_recur(mrb, n->car, offset+2);
    5998       }
    5999       if (n->cdr) {
    6000         dump_prefix(n, offset+1);
    6001         printf("blk=&%s\n", mrb_sym2name(mrb, sym(n->cdr)));
    6002       }
     6655      dump_args(mrb, tree->car, offset+1);
    60036656    }
    60046657    dump_prefix(tree, offset+1);
     
    61236776          if (n2->car) {
    61246777            if (!first_lval) printf(", ");
    6125             printf("%s", mrb_sym2name(mrb, sym(n2->car)));
     6778            printf("%s", mrb_sym_name(mrb, sym(n2->car)));
    61266779            first_lval = FALSE;
    61276780          }
     
    61516804    dump_prefix(tree, offset+1);
    61526805    printf("method='%s' (%d)\n",
    6153         mrb_sym2name(mrb, sym(tree->cdr->car)),
    6154         (int)(intptr_t)tree->cdr->car);
     6806        mrb_sym_dump(mrb, sym(tree->cdr->car)),
     6807        intn(tree->cdr->car));
    61556808    tree = tree->cdr->cdr->car;
    61566809    if (tree) {
     
    61826835    mrb_parser_dump(mrb, tree->car, offset+1);
    61836836    dump_prefix(tree, offset+1);
    6184     printf("::%s\n", mrb_sym2name(mrb, sym(tree->cdr)));
     6837    printf("::%s\n", mrb_sym_name(mrb, sym(tree->cdr)));
    61856838    break;
    61866839
    61876840  case NODE_COLON3:
    6188     printf("NODE_COLON3: ::%s\n", mrb_sym2name(mrb, sym(tree)));
     6841    printf("NODE_COLON3: ::%s\n", mrb_sym_name(mrb, sym(tree)));
    61896842    break;
    61906843
     
    61966849  case NODE_HASH:
    61976850    printf("NODE_HASH:\n");
     6851    while (tree) {
     6852      dump_prefix(tree, offset+1);
     6853      printf("key:\n");
     6854      mrb_parser_dump(mrb, tree->car->car, offset+2);
     6855      dump_prefix(tree, offset+1);
     6856      printf("value:\n");
     6857      mrb_parser_dump(mrb, tree->car->cdr, offset+2);
     6858      tree = tree->cdr;
     6859    }
     6860    break;
     6861
     6862  case NODE_KW_HASH:
     6863    printf("NODE_KW_HASH:\n");
    61986864    while (tree) {
    61996865      dump_prefix(tree, offset+1);
     
    62696935    tree = tree->cdr;
    62706936    dump_prefix(tree, offset+1);
    6271     printf("op='%s' (%d)\n", mrb_sym2name(mrb, sym(tree->car)), (int)(intptr_t)tree->car);
     6937    printf("op='%s' (%d)\n", mrb_sym_name(mrb, sym(tree->car)), intn(tree->car));
    62726938    tree = tree->cdr;
    62736939    mrb_parser_dump(mrb, tree->car, offset+1);
     
    63216987
    63226988  case NODE_LVAR:
    6323     printf("NODE_LVAR %s\n", mrb_sym2name(mrb, sym(tree)));
     6989    printf("NODE_LVAR %s\n", mrb_sym_name(mrb, sym(tree)));
    63246990    break;
    63256991
    63266992  case NODE_GVAR:
    6327     printf("NODE_GVAR %s\n", mrb_sym2name(mrb, sym(tree)));
     6993    printf("NODE_GVAR %s\n", mrb_sym_name(mrb, sym(tree)));
    63286994    break;
    63296995
    63306996  case NODE_IVAR:
    6331     printf("NODE_IVAR %s\n", mrb_sym2name(mrb, sym(tree)));
     6997    printf("NODE_IVAR %s\n", mrb_sym_name(mrb, sym(tree)));
    63326998    break;
    63336999
    63347000  case NODE_CVAR:
    6335     printf("NODE_CVAR %s\n", mrb_sym2name(mrb, sym(tree)));
     7001    printf("NODE_CVAR %s\n", mrb_sym_name(mrb, sym(tree)));
     7002    break;
     7003
     7004  case NODE_NVAR:
     7005    printf("NODE_NVAR %d\n", intn(tree));
    63367006    break;
    63377007
    63387008  case NODE_CONST:
    6339     printf("NODE_CONST %s\n", mrb_sym2name(mrb, sym(tree)));
     7009    printf("NODE_CONST %s\n", mrb_sym_name(mrb, sym(tree)));
    63407010    break;
    63417011
     
    63517021
    63527022  case NODE_BACK_REF:
    6353     printf("NODE_BACK_REF: $%c\n", (int)(intptr_t)tree);
     7023    printf("NODE_BACK_REF: $%c\n", intn(tree));
    63547024    break;
    63557025
    63567026  case NODE_NTH_REF:
    6357     printf("NODE_NTH_REF: $%" MRB_PRId "\n", (mrb_int)(intptr_t)tree);
     7027    printf("NODE_NTH_REF: $%d\n", intn(tree));
    63587028    break;
    63597029
    63607030  case NODE_ARG:
    6361     printf("NODE_ARG %s\n", mrb_sym2name(mrb, sym(tree)));
     7031    printf("NODE_ARG %s\n", mrb_sym_name(mrb, sym(tree)));
    63627032    break;
    63637033
     
    63687038
    63697039  case NODE_INT:
    6370     printf("NODE_INT %s base %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr->car);
     7040    printf("NODE_INT %s base %d\n", (char*)tree->car, intn(tree->cdr->car));
    63717041    break;
    63727042
     
    63767046
    63777047  case NODE_NEGATE:
    6378     printf("NODE_NEGATE\n");
     7048    printf("NODE_NEGATE:\n");
    63797049    mrb_parser_dump(mrb, tree, offset+1);
    63807050    break;
    63817051
    63827052  case NODE_STR:
    6383     printf("NODE_STR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr);
     7053    printf("NODE_STR %s len %d\n", str_dump(mrb, (char*)tree->car, intn(tree->cdr)), intn(tree->cdr));
    63847054    break;
    63857055
    63867056  case NODE_DSTR:
    6387     printf("NODE_DSTR\n");
     7057    printf("NODE_DSTR:\n");
    63887058    dump_recur(mrb, tree, offset+1);
    63897059    break;
    63907060
    63917061  case NODE_XSTR:
    6392     printf("NODE_XSTR \"%s\" len %d\n", (char*)tree->car, (int)(intptr_t)tree->cdr);
     7062    printf("NODE_XSTR %s len %d\n", str_dump(mrb, (char*)tree->car, intn(tree->cdr)), intn(tree->cdr));
    63937063    break;
    63947064
    63957065  case NODE_DXSTR:
    6396     printf("NODE_DXSTR\n");
     7066    printf("NODE_DXSTR:\n");
    63977067    dump_recur(mrb, tree, offset+1);
    63987068    break;
     
    64037073
    64047074  case NODE_DREGX:
    6405     printf("NODE_DREGX\n");
     7075    printf("NODE_DREGX:\n");
    64067076    dump_recur(mrb, tree->car, offset+1);
    64077077    dump_prefix(tree, offset);
     
    64187088
    64197089  case NODE_SYM:
    6420     printf("NODE_SYM :%s (%d)\n", mrb_sym2name(mrb, sym(tree)),
    6421            (int)(intptr_t)tree);
     7090    printf("NODE_SYM :%s (%d)\n", mrb_sym_dump(mrb, sym(tree)),
     7091           intn(tree));
     7092    break;
     7093
     7094  case NODE_DSYM:
     7095    printf("NODE_DSYM:\n");
     7096    mrb_parser_dump(mrb, tree, offset+1);
     7097    break;
     7098
     7099  case NODE_WORDS:
     7100    printf("NODE_WORDS:\n");
     7101    dump_recur(mrb, tree, offset+1);
     7102    break;
     7103
     7104  case NODE_SYMBOLS:
     7105    printf("NODE_SYMBOLS:\n");
     7106    dump_recur(mrb, tree, offset+1);
     7107    break;
     7108
     7109  case NODE_LITERAL_DELIM:
     7110    printf("NODE_LITERAL_DELIM\n");
    64227111    break;
    64237112
     
    64407129  case NODE_ALIAS:
    64417130    printf("NODE_ALIAS %s %s:\n",
    6442         mrb_sym2name(mrb, sym(tree->car)),
    6443         mrb_sym2name(mrb, sym(tree->cdr)));
     7131        mrb_sym_dump(mrb, sym(tree->car)),
     7132        mrb_sym_dump(mrb, sym(tree->cdr)));
    64447133    break;
    64457134
     
    64497138      node *t = tree;
    64507139      while (t) {
    6451         printf(" %s", mrb_sym2name(mrb, sym(t->car)));
     7140        printf(" %s", mrb_sym_dump(mrb, sym(t->car)));
    64527141        t = t->cdr;
    64537142      }
     
    64607149    if (tree->car->car == (node*)0) {
    64617150      dump_prefix(tree, offset+1);
    6462       printf(":%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
     7151      printf(":%s\n", mrb_sym_name(mrb, sym(tree->car->cdr)));
    64637152    }
    64647153    else if (tree->car->car == (node*)1) {
    64657154      dump_prefix(tree, offset+1);
    6466       printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
     7155      printf("::%s\n", mrb_sym_name(mrb, sym(tree->car->cdr)));
    64677156    }
    64687157    else {
    64697158      mrb_parser_dump(mrb, tree->car->car, offset+1);
    64707159      dump_prefix(tree, offset+1);
    6471       printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
     7160      printf("::%s\n", mrb_sym_name(mrb, sym(tree->car->cdr)));
    64727161    }
    64737162    if (tree->cdr->car) {
     
    64857174    if (tree->car->car == (node*)0) {
    64867175      dump_prefix(tree, offset+1);
    6487       printf(":%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
     7176      printf(":%s\n", mrb_sym_name(mrb, sym(tree->car->cdr)));
    64887177    }
    64897178    else if (tree->car->car == (node*)1) {
    64907179      dump_prefix(tree, offset+1);
    6491       printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
     7180      printf("::%s\n", mrb_sym_name(mrb, sym(tree->car->cdr)));
    64927181    }
    64937182    else {
    64947183      mrb_parser_dump(mrb, tree->car->car, offset+1);
    64957184      dump_prefix(tree, offset+1);
    6496       printf("::%s\n", mrb_sym2name(mrb, sym(tree->car->cdr)));
     7185      printf("::%s\n", mrb_sym_name(mrb, sym(tree->car->cdr)));
    64977186    }
    64987187    dump_prefix(tree, offset+1);
     
    65127201    printf("NODE_DEF:\n");
    65137202    dump_prefix(tree, offset+1);
    6514     printf("%s\n", mrb_sym2name(mrb, sym(tree->car)));
     7203    printf("%s\n", mrb_sym_dump(mrb, sym(tree->car)));
    65157204    tree = tree->cdr;
    65167205    {
     
    65257214          if (n2->car) {
    65267215            if (!first_lval) printf(", ");
    6527             printf("%s", mrb_sym2name(mrb, sym(n2->car)));
     7216            printf("%s", mrb_sym_name(mrb, sym(n2->car)));
    65287217            first_lval = FALSE;
    65297218          }
     
    65357224    tree = tree->cdr;
    65367225    if (tree->car) {
    6537       node *n = tree->car;
    6538 
    6539       if (n->car) {
    6540         dump_prefix(n, offset+1);
    6541         printf("mandatory args:\n");
    6542         dump_recur(mrb, n->car, offset+2);
    6543       }
    6544       n = n->cdr;
    6545       if (n->car) {
    6546         dump_prefix(n, offset+1);
    6547         printf("optional args:\n");
    6548         {
    6549           node *n2 = n->car;
    6550 
    6551           while (n2) {
    6552             dump_prefix(n2, offset+2);
    6553             printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
    6554             mrb_parser_dump(mrb, n2->car->cdr, 0);
    6555             n2 = n2->cdr;
    6556           }
    6557         }
    6558       }
    6559       n = n->cdr;
    6560       if (n->car) {
    6561         dump_prefix(n, offset+1);
    6562         printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
    6563       }
    6564       n = n->cdr;
    6565       if (n->car) {
    6566         dump_prefix(n, offset+1);
    6567         printf("post mandatory args:\n");
    6568         dump_recur(mrb, n->car, offset+2);
    6569       }
    6570       if (n->cdr) {
    6571         dump_prefix(n, offset+1);
    6572         printf("blk=&%s\n", mrb_sym2name(mrb, sym(n->cdr)));
    6573       }
     7226      dump_args(mrb, tree->car, offset);
    65747227    }
    65757228    mrb_parser_dump(mrb, tree->cdr->car, offset+1);
     
    65817234    tree = tree->cdr;
    65827235    dump_prefix(tree, offset+1);
    6583     printf(":%s\n", mrb_sym2name(mrb, sym(tree->car)));
     7236    printf(":%s\n", mrb_sym_dump(mrb, sym(tree->car)));
    65847237    tree = tree->cdr->cdr;
    65857238    if (tree->car) {
    6586       node *n = tree->car;
    6587 
    6588       if (n->car) {
    6589         dump_prefix(n, offset+1);
    6590         printf("mandatory args:\n");
    6591         dump_recur(mrb, n->car, offset+2);
    6592       }
    6593       n = n->cdr;
    6594       if (n->car) {
    6595         dump_prefix(n, offset+1);
    6596         printf("optional args:\n");
    6597         {
    6598           node *n2 = n->car;
    6599 
    6600           while (n2) {
    6601             dump_prefix(n2, offset+2);
    6602             printf("%s=", mrb_sym2name(mrb, sym(n2->car->car)));
    6603             mrb_parser_dump(mrb, n2->car->cdr, 0);
    6604             n2 = n2->cdr;
    6605           }
    6606         }
    6607       }
    6608       n = n->cdr;
    6609       if (n->car) {
    6610         dump_prefix(n, offset+1);
    6611         printf("rest=*%s\n", mrb_sym2name(mrb, sym(n->car)));
    6612       }
    6613       n = n->cdr;
    6614       if (n->car) {
    6615         dump_prefix(n, offset+1);
    6616         printf("post mandatory args:\n");
    6617         dump_recur(mrb, n->car, offset+2);
    6618       }
    6619       n = n->cdr;
    6620       if (n) {
    6621         dump_prefix(n, offset+1);
    6622         printf("blk=&%s\n", mrb_sym2name(mrb, sym(n)));
    6623       }
     7239      dump_args(mrb, tree->car, offset+1);
    66247240    }
    66257241    tree = tree->cdr;
     
    66377253    break;
    66387254
     7255  case NODE_ARGS_TAIL:
     7256    printf("NODE_ARGS_TAIL:\n");
     7257    {
     7258      node *kws = tree->car;
     7259
     7260      while (kws) {
     7261        mrb_parser_dump(mrb, kws->car, offset+1);
     7262        kws = kws->cdr;
     7263      }
     7264    }
     7265    tree = tree->cdr;
     7266    if (tree->car) {
     7267      mrb_assert(intn(tree->car->car) == NODE_KW_REST_ARGS);
     7268      mrb_parser_dump(mrb, tree->car, offset+1);
     7269    }
     7270    tree = tree->cdr;
     7271    if (tree->car) {
     7272      dump_prefix(tree, offset+1);
     7273      printf("block='%s'\n", mrb_sym_name(mrb, sym(tree->car)));
     7274    }
     7275    break;
     7276
     7277  case NODE_KW_ARG:
     7278    printf("NODE_KW_ARG %s:\n", mrb_sym_name(mrb, sym(tree->car)));
     7279    mrb_parser_dump(mrb, tree->cdr->car, offset + 1);
     7280    break;
     7281
     7282  case NODE_KW_REST_ARGS:
     7283    printf("NODE_KW_REST_ARGS %s\n", mrb_sym_name(mrb, sym(tree)));
     7284    break;
     7285
    66397286  default:
    66407287    printf("node type: %d (0x%x)\n", nodetype, (unsigned)nodetype);
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-compiler/mrbgem.rake

    r331 r439  
    2424    end
    2525  end
    26   file objfile("#{current_build_dir}/core/y.tab") => lex_def
    2726
    2827  # Parser
    29   file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y"] do |t|
     28  file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y", lex_def] do |t|
     29    mkdir_p File.dirname t.name
    3030    yacc.run t.name, t.prerequisites.first
    3131  end
     
    3636  end
    3737
    38   file libfile("#{build.build_dir}/lib/libmruby_core") => core_objs
     38  file build.libmruby_core_static => core_objs
    3939  build.libmruby << core_objs
    4040end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-enum-ext/mrblib/enum.rb

    r331 r439  
    1414
    1515  def drop(n)
    16     raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
     16    n = n.__to_int
    1717    raise ArgumentError, "attempt to drop negative size" if n < 0
    1818
    19     n = n.to_int
    2019    ary = []
    2120    self.each {|*val| n == 0 ? ary << val.__svalue : n -= 1 }
     
    5857
    5958  def take(n)
    60     raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
    61     i = n.to_int
     59    n = n.__to_int
     60    i = n.to_i
    6261    raise ArgumentError, "attempt to take negative size" if i < 0
    6362    ary = []
     
    114113
    115114  def each_cons(n, &block)
    116     raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
     115    n = n.__to_int
    117116    raise ArgumentError, "invalid size" if n <= 0
    118117
    119118    return to_enum(:each_cons,n) unless block
    120119    ary = []
    121     n = n.to_int
     120    n = n.to_i
    122121    self.each do |*val|
    123122      ary.shift if ary.size == n
     
    142141
    143142  def each_slice(n, &block)
    144     raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
     143    n = n.__to_int
    145144    raise ArgumentError, "invalid slice size" if n <= 0
    146145
    147146    return to_enum(:each_slice,n) unless block
    148147    ary = []
    149     n = n.to_int
     148    n = n.to_i
    150149    self.each do |*val|
    151150      ary << val.__svalue
     
    202201    }
    203202    if ary.size > 1
    204       __sort_sub__(ary, ::Array.new(ary.size), 0, 0, ary.size - 1) do |a,b|
    205         a <=> b
    206       end
     203      ary.sort!
    207204    end
    208205    ary.collect{|e,i| orig[i]}
    209206  end
    210207
    211   NONE = Object.new
    212208  ##
    213209  # call-seq:
     
    226222      return nil
    227223    when 1
    228       n = args[0]
    229       raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
    230       i = n.to_int
     224      i = args[0].__to_int
    231225      raise ArgumentError, "attempt to take negative size" if i < 0
    232226      ary = []
     
    452446  #  call-seq:
    453447  #     enum.none? [{ |obj| block }]   -> true or false
     448  #     enum.none?(pattern)            -> true or false
    454449  #
    455450  #  Passes each element of the collection to the given block. The method
     
    458453  #  <code>true</code> only if none of the collection members is true.
    459454  #
     455  #  If a pattern is supplied instead, the method returns whether
     456  #  <code>pattern === element</code> for none of the collection members.
     457  #
    460458  #     %w(ant bear cat).none? { |word| word.length == 5 } #=> true
    461459  #     %w(ant bear cat).none? { |word| word.length >= 4 } #=> false
     460  #     %w{ant bear cat}.none?(/d/)                        #=> true
     461  #     [1, 3.14, 42].none?(Float)                         #=> false
    462462  #     [].none?                                           #=> true
    463463  #     [nil, false].none?                                 #=> true
    464464  #     [nil, true].none?                                  #=> false
    465465
    466   def none?(&block)
    467     if block
     466  def none?(pat=NONE, &block)
     467    if pat != NONE
     468      self.each do |*val|
     469        return false if pat === val.__svalue
     470      end
     471    elsif block
    468472      self.each do |*val|
    469473        return false if block.call(*val)
     
    480484  #  call-seq:
    481485  #    enum.one? [{ |obj| block }]   -> true or false
     486  #    enum.one?(pattern)            -> true or false
    482487  #
    483488  # Passes each element of the collection to the given block. The method
     
    487492  # true.
    488493  #
     494  # If a pattern is supplied instead, the method returns whether
     495  # <code>pattern === element</code> for exactly one collection member.
     496  #
    489497  #    %w(ant bear cat).one? { |word| word.length == 4 }  #=> true
    490498  #    %w(ant bear cat).one? { |word| word.length > 4 }   #=> false
    491499  #    %w(ant bear cat).one? { |word| word.length < 4 }   #=> false
     500  #    %w{ant bear cat}.one?(/t/)                         #=> false
    492501  #    [nil, true, 99].one?                               #=> false
    493502  #    [nil, true, false].one?                            #=> true
    494   #
    495 
    496   def one?(&block)
     503  #    [ nil, true, 99 ].one?(Integer)                    #=> true
     504  #    [].one?                                            #=> false
     505
     506  def one?(pat=NONE, &block)
    497507    count = 0
    498     if block
     508    if pat!=NONE
     509      self.each do |*val|
     510        count += 1 if pat === val.__svalue
     511        return false if count > 1
     512      end
     513    elsif block
    499514      self.each do |*val|
    500515        count += 1 if block.call(*val)
     
    511526  end
    512527
     528  # ISO 15.3.2.2.1
     529  #  call-seq:
     530  #     enum.all? [{ |obj| block } ]   -> true or false
     531  #     enum.all?(pattern)             -> true or false
     532  #
     533  #  Passes each element of the collection to the given block. The method
     534  #  returns <code>true</code> if the block never returns
     535  #  <code>false</code> or <code>nil</code>. If the block is not given,
     536  #  Ruby adds an implicit block of <code>{ |obj| obj }</code> which will
     537  #  cause #all? to return +true+ when none of the collection members are
     538  #  +false+ or +nil+.
     539  #
     540  #  If a pattern is supplied instead, the method returns whether
     541  #  <code>pattern === element</code> for every collection member.
     542  #
     543  #     %w[ant bear cat].all? { |word| word.length >= 3 } #=> true
     544  #     %w[ant bear cat].all? { |word| word.length >= 4 } #=> false
     545  #     %w[ant bear cat].all?(/t/)                        #=> false
     546  #     [1, 2i, 3.14].all?(Numeric)                       #=> true
     547  #     [nil, true, 99].all?                              #=> false
     548  #
     549  def all?(pat=NONE, &block)
     550    if pat != NONE
     551      self.each{|*val| return false unless pat === val.__svalue}
     552    elsif block
     553      self.each{|*val| return false unless block.call(*val)}
     554    else
     555      self.each{|*val| return false unless val.__svalue}
     556    end
     557    true
     558  end
     559
     560  # ISO 15.3.2.2.2
     561  #  call-seq:
     562  #     enum.any? [{ |obj| block }]   -> true or false
     563  #     enum.any?(pattern)            -> true or false
     564  #
     565  #  Passes each element of the collection to the given block. The method
     566  #  returns <code>true</code> if the block ever returns a value other
     567  #  than <code>false</code> or <code>nil</code>. If the block is not
     568  #  given, Ruby adds an implicit block of <code>{ |obj| obj }</code> that
     569  #  will cause #any? to return +true+ if at least one of the collection
     570  #  members is not +false+ or +nil+.
     571  #
     572  #  If a pattern is supplied instead, the method returns whether
     573  #  <code>pattern === element</code> for any collection member.
     574  #
     575  #     %w[ant bear cat].any? { |word| word.length >= 3 } #=> true
     576  #     %w[ant bear cat].any? { |word| word.length >= 4 } #=> true
     577  #     %w[ant bear cat].any?(/d/)                        #=> false
     578  #     [nil, true, 99].any?(Integer)                     #=> true
     579  #     [nil, true, 99].any?                              #=> true
     580  #     [].any?                                           #=> false
     581  #
     582  def any?(pat=NONE, &block)
     583    if pat != NONE
     584      self.each{|*val| return true if pat === val.__svalue}
     585    elsif block
     586      self.each{|*val| return true if block.call(*val)}
     587    else
     588      self.each{|*val| return true if val.__svalue}
     589    end
     590    false
     591  end
     592
    513593  ##
    514594  #  call-seq:
     
    525605  #
    526606
    527   def each_with_object(obj=nil, &block)
    528     raise ArgumentError, "wrong number of arguments (0 for 1)" if obj.nil?
    529 
     607  def each_with_object(obj, &block)
    530608    return to_enum(:each_with_object, obj) unless block
    531609
     
    592670      n = -1
    593671    else
    594       unless nv.respond_to?(:to_int)
    595         raise TypeError, "no implicit conversion of #{nv.class} into Integer"
    596       end
    597       n = nv.to_int
    598       unless n.kind_of?(Integer)
    599         raise TypeError, "no implicit conversion of #{nv.class} into Integer"
    600       end
     672      n = nv.__to_int
    601673      return nil if n <= 0
    602674    end
     
    657729  #  call-seq:
    658730  #     enum.zip(arg, ...)                  -> an_array_of_array
     731  #     enum.zip(arg, ...) { |arr| block }  -> nil
    659732  #
    660733  #  Takes one element from <i>enum</i> and merges corresponding
     
    663736  #  count of arguments.  The length of the resulting sequence will be
    664737  #  <code>enum#size</code>.  If the size of any argument is less than
    665   #  <code>enum#size</code>, <code>nil</code> values are supplied.
    666   #
    667 
    668   def zip(*arg)
    669     ary = []
    670     arg = arg.map{|a|a.to_a}
     738  #  <code>enum#size</code>, <code>nil</code> values are supplied. If
     739  #  a block is given, it is invoked for each output array, otherwise
     740  #  an array of arrays is returned.
     741  #
     742  #     a = [ 4, 5, 6 ]
     743  #     b = [ 7, 8, 9 ]
     744  #
     745  #     a.zip(b)                 #=> [[4, 7], [5, 8], [6, 9]]
     746  #     [1, 2, 3].zip(a, b)      #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
     747  #     [1, 2].zip(a, b)         #=> [[1, 4, 7], [2, 5, 8]]
     748  #     a.zip([1, 2], [8])       #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]
     749  #
     750  #     c = []
     751  #     a.zip(b) { |x, y| c << x + y }  #=> nil
     752  #     c                               #=> [11, 13, 15]
     753  #
     754
     755  def zip(*arg, &block)
     756    result = block ? nil : []
     757    arg = arg.map do |a|
     758      unless a.respond_to?(:to_a)
     759        raise TypeError, "wrong argument type #{a.class} (must respond to :to_a)"
     760      end
     761      a.to_a
     762    end
     763
    671764    i = 0
    672765    self.each do |*val|
     
    678771        idx += 1
    679772      end
    680       ary.push(a)
    681773      i += 1
    682     end
    683     ary
     774      if result.nil?
     775        block.call(a)
     776      else
     777        result.push(a)
     778      end
     779    end
     780    result
    684781  end
    685782
     
    695792  #
    696793
    697   def to_h
     794  def to_h(&blk)
    698795    h = {}
    699     self.each do |*v|
    700       v = v.__svalue
    701       raise TypeError, "wrong element type #{v.class} (expected Array)" unless v.is_a? Array
    702       raise ArgumentError, "element has wrong array length (expected 2, was #{v.size})" if v.size != 2
    703       h[v[0]] = v[1]
     796    if blk
     797      self.each do |v|
     798        v = blk.call(v)
     799        raise TypeError, "wrong element type #{v.class} (expected Array)" unless v.is_a? Array
     800        raise ArgumentError, "element has wrong array length (expected 2, was #{v.size})" if v.size != 2
     801        h[v[0]] = v[1]
     802      end
     803    else
     804      self.each do |*v|
     805        v = v.__svalue
     806        raise TypeError, "wrong element type #{v.class} (expected Array)" unless v.is_a? Array
     807        raise ArgumentError, "element has wrong array length (expected 2, was #{v.size})" if v.size != 2
     808        h[v[0]] = v[1]
     809      end
    704810    end
    705811    h
    706812  end
    707813
    708   def nil.to_h
    709     {}
     814  def uniq(&block)
     815    hash = {}
     816    if block
     817      self.each do|*v|
     818        v = v.__svalue
     819        hash[block.call(v)] ||= v
     820      end
     821    else
     822      self.each do|*v|
     823        v = v.__svalue
     824        hash[v] ||= v
     825      end
     826    end
     827    hash.values
     828  end
     829
     830  def filter_map(&blk)
     831    return to_enum(:filter_map) unless blk
     832
     833    ary = []
     834    self.each do |x|
     835      x = blk.call(x)
     836      ary.push x if x
     837    end
     838    ary
     839  end
     840
     841  alias filter select
     842
     843  ##
     844  # call-seq:
     845  #   enum.tally -> a_hash
     846  #
     847  # Tallys the collection.  Returns a hash where the keys are the
     848  # elements and the values are numbers of elements in the collection
     849  # that correspond to the key.
     850  #
     851  #    ["a", "b", "c", "b"].tally #=> {"a"=>1, "b"=>2, "c"=>1}
     852  def tally
     853    hash = {}
     854    self.each do |x|
     855      hash[x] = (hash[x]||0)+1
     856    end
     857    hash
    710858  end
    711859end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-enum-ext/test/enum.rb

    r331 r439  
    101101  assert_true %w(ant bear cat).none? { |word| word.length == 5 }
    102102  assert_false %w(ant bear cat).none? { |word| word.length >= 4 }
     103  assert_false [1, 3.14, 42].none?(Float)
    103104  assert_true [].none?
    104105  assert_true [nil, false].none?
     
    110111  assert_false %w(ant bear cat).one? { |word| word.length > 4 }
    111112  assert_false %w(ant bear cat).one? { |word| word.length < 4 }
     113  assert_true [1, 3.14, 42].one?(Float)
    112114  assert_false [nil, true, 99].one?
    113115  assert_true [nil, true, false].one?
     116  assert_true [ nil, true, 99 ].one?(Integer)
     117  assert_false [].one?
     118end
     119
     120assert("Enumerable#all? (enhancement)") do
     121  assert_false [1, 2, 3.14].all?(Integer)
     122  assert_true [1, 2, 3.14].all?(Numeric)
     123end
     124
     125assert("Enumerable#any? (enhancement)") do
     126  assert_false [1, 2, 3].all?(Float)
     127  assert_true [nil, true, 99].any?(Integer)
    114128end
    115129
    116130assert("Enumerable#each_with_object") do
    117   assert_true [2, 4, 6, 8, 10, 12, 14, 16, 18, 20], (1..10).each_with_object([]) { |i, a| a << i*2 }
     131  assert_equal [2, 4, 6, 8, 10, 12, 14, 16, 18, 20], (1..10).each_with_object([]) { |i, a| a << i*2 }
    118132  assert_raise(ArgumentError) { (1..10).each_with_object() { |i, a| a << i*2 } }
    119133end
     
    122136  r = (1..3)
    123137  a = []
    124   assert_equal (1..3), r.reverse_each { |v| a << v }
     138  assert_same r, r.reverse_each { |v| a << v }
    125139  assert_equal [3, 2, 1], a
    126140end
     
    153167  assert_equal [[1, 4, 7], [2, 5, 8]], [1, 2].zip(a, b)
    154168  assert_equal [[4, 1, 8], [5, 2, nil], [6, nil, nil]], a.zip([1, 2], [8])
     169
     170  ret = []
     171  assert_equal nil, a.zip([1, 2], [8]) { |i| ret << i }
     172  assert_equal [[4, 1, 8], [5, 2, nil], [6, nil, nil]], ret
     173
     174  assert_raise(TypeError) { [1].zip(1) }
    155175end
    156176
     
    167187  assert_equal Hash, h.class
    168188  assert_equal h0, h
    169   # mruby-enum-ext also provides nil.to_h
    170   assert_equal Hash.new, nil.to_h
     189  assert_equal({1=>4,3=>8}, c.new.to_h{|k,v|[k,v*2]})
    171190end
     191
     192assert("Enumerable#filter_map") do
     193  assert_equal [4, 8, 12, 16, 20], (1..10).filter_map{|i| i * 2 if i%2==0}
     194end
     195
     196assert("Enumerable#tally") do
     197  assert_equal({"a"=>1, "b"=>2, "c"=>1}, ["a", "b", "c", "b"].tally)
     198end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-enum-lazy/mrblib/lazy.rb

    r331 r439  
    4444
    4545    def to_enum(meth=:each, *args, &block)
     46      unless self.respond_to?(meth)
     47        raise ArgumentError, "undefined method #{meth}"
     48      end
    4649      lz = Lazy.new(self, &block)
    4750      lz.obj = self
     
    7073    def reject(&block)
    7174      Lazy.new(self){|yielder, val|
    72         if not block.call(val)
     75        unless block.call(val)
    7376          yielder << val
    7477        end
     
    156159    end
    157160
     161    def uniq(&block)
     162      hash = {}
     163      Lazy.new(self){|yielder, val|
     164        if block
     165          v = block.call(val)
     166        else
     167          v = val
     168        end
     169        unless hash.include?(v)
     170          yielder << val
     171          hash[v] = val
     172        end
     173      }
     174    end
     175
    158176    alias force to_a
    159177  end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-enum-lazy/test/lazy.rb

    r331 r439  
    4141end
    4242
    43 assert("Enumrator::Lazy#to_enum") do
     43assert("Enumerator::Lazy#to_enum") do
    4444  lazy_enum = (0..Float::INFINITY).lazy.to_enum(:each_slice, 2)
    4545  assert_kind_of Enumerator::Lazy, lazy_enum
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-enumerator/mrbgem.rake

    r321 r439  
    33  spec.author  = 'mruby developers'
    44  spec.add_dependency('mruby-fiber', :core => 'mruby-fiber')
    5   spec.add_dependency 'mruby-enum-ext', :core => 'mruby-enum-ext'
    65  spec.summary = 'Enumerator class'
    76end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-enumerator/mrblib/enumerator.rb

    r331 r439  
    9090
    9191  ##
    92   # @overload initialize(size = nil, &block)
    9392  # @overload initialize(obj, method = :each, *args)
    9493  #
     
    110109  #     p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
    111110  #
    112   def initialize(obj=nil, meth=:each, *args, &block)
    113     if block_given?
     111  # In the second, deprecated, form, a generated Enumerator iterates over the
     112  # given object using the given method with the given arguments passed. This
     113  # form is left only for internal use.
     114  #
     115  # Use of this form is discouraged.  Use Kernel#enum_for or Kernel#to_enum
     116  # instead.
     117  def initialize(obj=NONE, meth=:each, *args, &block)
     118    if block
    114119      obj = Generator.new(&block)
    115     else
    116       raise ArgumentError unless obj
     120    elsif obj == NONE
     121      raise ArgumentError, "wrong number of arguments (given 0, expected 1+)"
    117122    end
    118123
    119124    @obj = obj
    120125    @meth = meth
    121     @args = args.dup
     126    @args = args
    122127    @fib = nil
    123128    @dst = nil
     
    126131    @stop_exc = false
    127132  end
    128   attr_accessor :obj, :meth, :args, :fib
    129   private :obj, :meth, :args, :fib
     133  attr_accessor :obj, :meth, :args
     134  attr_reader :fib
    130135
    131136  def initialize_copy(obj)
     
    152157  # +offset+:: the starting index to use
    153158  #
    154   def with_index(offset=0)
    155     return to_enum :with_index, offset unless block_given?
    156     offset = if offset.nil?
    157       0
    158     elsif offset.respond_to?(:to_int)
    159       offset.to_int
     159  def with_index(offset=0, &block)
     160    return to_enum :with_index, offset unless block
     161
     162    if offset.nil?
     163      offset = 0
    160164    else
    161       raise TypeError, "no implicit conversion of #{offset.class} into Integer"
     165      offset = offset.__to_int
    162166    end
    163167
     
    165169    enumerator_block_call do |*i|
    166170      n += 1
    167       yield i.__svalue, n
     171      block.call i.__svalue, n
    168172    end
    169173  end
     
    210214  #   # => foo:2
    211215  #
    212   def with_object(object)
    213     return to_enum(:with_object, object) unless block_given?
     216  def with_object(object, &block)
     217    return to_enum(:with_object, object) unless block
    214218
    215219    enumerator_block_call do |i|
    216       yield [i,object]
     220      block.call [i,object]
    217221    end
    218222    object
     
    220224
    221225  def inspect
    222     return "#<#{self.class}: uninitialized>" unless @obj
    223 
    224226    if @args && @args.size > 0
    225227      args = @args.join(", ")
    226       "#<#{self.class}: #{@obj}:#{@meth}(#{args})>"
     228      "#<#{self.class}: #{@obj.inspect}:#{@meth}(#{args})>"
    227229    else
    228       "#<#{self.class}: #{@obj}:#{@meth}>"
     230      "#<#{self.class}: #{@obj.inspect}:#{@meth}>"
    229231    end
    230232  end
     
    242244  # === Examples
    243245  #
    244   #   "Hello, world!".scan(/\w+/)                     #=> ["Hello", "world"]
    245   #   "Hello, world!".to_enum(:scan, /\w+/).to_a      #=> ["Hello", "world"]
    246   #   "Hello, world!".to_enum(:scan).each(/\w+/).to_a #=> ["Hello", "world"]
     246  #   Array.new(3)                     #=> [nil, nil, nil]
     247  #   Array.new(3) { |i| i }           #=> [0, 1, 2]
     248  #   Array.to_enum(:new, 3).to_a      #=> [0, 1, 2]
     249  #   Array.to_enum(:new).each(3).to_a #=> [0, 1, 2]
    247250  #
    248251  #   obj = Object.new
     
    278281      obj.args = args
    279282    end
    280     return obj unless block_given?
     283    return obj unless block
    281284    enumerator_block_call(&block)
    282285  end
     
    539542  class Yielder
    540543    def initialize(&block)
    541       raise LocalJumpError, "no block given" unless block_given?
     544      raise LocalJumpError, "no block given" unless block
    542545
    543546      @proc = block
     
    553556    end
    554557  end
     558
     559  ##
     560  # call-seq:
     561  #    Enumerator.produce(initial = nil) { |val| } -> enumerator
     562  #
     563  # Creates an infinite enumerator from any block, just called over and
     564  # over.  Result of the previous iteration is passed to the next one.
     565  # If +initial+ is provided, it is passed to the first iteration, and
     566  # becomes the first element of the enumerator; if it is not provided,
     567  # first iteration receives +nil+, and its result becomes first
     568  # element of the iterator.
     569  #
     570  # Raising StopIteration from the block stops an iteration.
     571  #
     572  # Examples of usage:
     573  #
     574  #   Enumerator.produce(1, &:succ)   # => enumerator of 1, 2, 3, 4, ....
     575  #
     576  #   Enumerator.produce { rand(10) } # => infinite random number sequence
     577  #
     578  #   ancestors = Enumerator.produce(node) { |prev| node = prev.parent or raise StopIteration }
     579  #   enclosing_section = ancestors.find { |n| n.type == :section }
     580  def Enumerator.produce(init=NONE, &block)
     581    raise ArgumentError, "no block given" if block.nil?
     582    Enumerator.new do |y|
     583      if init == NONE
     584        val = nil
     585      else
     586        val = init
     587        y.yield(val)
     588      end
     589      begin
     590        while true
     591          y.yield(val = block.call(val))
     592        end
     593      rescue StopIteration
     594        # do nothing
     595      end
     596    end
     597  end
    555598end
    556599
     
    560603  #   obj.to_enum(method = :each, *args)                 -> enum
    561604  #   obj.enum_for(method = :each, *args)                -> enum
    562   #   obj.to_enum(method = :each, *args) {|*args| block} -> enum
    563   #   obj.enum_for(method = :each, *args){|*args| block} -> enum
    564605  #
    565606  # Creates a new Enumerator which will enumerate by calling +method+ on
    566607  # +obj+, passing +args+ if any.
    567   #
    568   # If a block is given, it will be used to calculate the size of
    569   # the enumerator without the need to iterate it (see Enumerator#size).
    570608  #
    571609  # === Examples
     
    586624  # a generic Enumerable, in case no block is passed.
    587625  #
    588   # Here is such an example, with parameter passing and a sizing block:
     626  # Here is such an example with parameter passing:
    589627  #
    590628  #     module Enumerable
     
    593631  #         raise ArgumentError, "#{n} is negative!" if n < 0
    594632  #         unless block_given?
    595   #           return to_enum(__method__, n) do # __method__ is :repeat here
    596   #             sz = size     # Call size and multiply by n...
    597   #             sz * n if sz  # but return nil if size itself is nil
    598   #           end
     633  #           return to_enum(__method__, n) # __method__ is :repeat here
    599634  #         end
    600635  #         each do |*val|
     
    613648    Enumerator.new self, meth, *args
    614649  end
    615   alias :enum_for :to_enum
     650  alias enum_for to_enum
    616651end
    617652
    618653module Enumerable
    619654  # use Enumerator to use infinite sequence
    620   def zip(*arg)
    621     ary = []
    622     arg = arg.map{|a|a.each}
    623     i = 0
    624     self.each do |*val|
    625       a = []
    626       a.push(val.__svalue)
    627       idx = 0
    628       while idx < arg.size
    629         begin
    630           a.push(arg[idx].next)
    631         rescue StopIteration
    632           a.push(nil)
     655  def zip(*args, &block)
     656    args = args.map do |a|
     657      if a.respond_to?(:each)
     658        a.to_enum(:each)
     659      else
     660        raise TypeError, "wrong argument type #{a.class} (must respond to :each)"
     661      end
     662    end
     663
     664    result = block ? nil : []
     665
     666    each do |*val|
     667      tmp = [val.__svalue]
     668      args.each do |arg|
     669        v = if arg.nil?
     670          nil
     671        else
     672          begin
     673            arg.next
     674          rescue StopIteration
     675            nil
     676          end
    633677        end
    634         idx += 1
     678        tmp.push(v)
    635679      end
    636       ary.push(a)
    637       i += 1
    638     end
    639     ary
     680      if result.nil?
     681        block.call(tmp)
     682      else
     683        result.push(tmp)
     684      end
     685    end
     686
     687    result
    640688  end
    641689end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-enumerator/test/enumerator.rb

    r331 r439  
    77end
    88
    9 assert 'Enumerator' do
     9def assert_take(exp, enumerator)
     10  result = []
     11  n = exp.size
     12  enumerator.each do |v|
     13    result << v
     14    n -= 1
     15    break if n == 0
     16  end if n > 0
     17  assert_equal exp, result
     18end
     19
     20assert 'Enumerator.class' do
    1021  assert_equal Class, Enumerator.class
    1122end
    1223
    13 assert 'Enumerator' do
     24assert 'Enumerator.superclass' do
    1425  assert_equal Object, Enumerator.superclass
    1526end
     
    2031  assert_equal [[:x,1],[:y,2]], {x:1, y:2}.each.map{|i| i}.sort
    2132  assert_equal [1,2,3], @obj.to_enum(:foo, 1,2,3).to_a
    22   assert_equal [1,2,3], Enumerator.new(@obj, :foo, 1,2,3).to_a
    23   assert_equal [1,2,3], Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.take(3)
     33  assert_take [1,2,3], Enumerator.new { |y| i = 0; loop { y << (i += 1) } }
    2434  assert_raise(ArgumentError) { Enumerator.new }
    25   enum = @obj.to_enum
    26   assert_raise(NoMethodError) { enum.each {} }
    2735
    2836  # examples
     
    3442    end
    3543  end
    36   assert_equal fib.take(10), [1,1,2,3,5,8,13,21,34,55]
     44  assert_take [1,1,2,3,5,8,13,21,34,55], fib
    3745end
    3846
     
    5462  @obj.to_enum(:foo, 1, 2, 3).with_index(10).with_index(20) { |*i| a << i }
    5563  assert_equal [[[1, 10], 20], [[2, 11], 21], [[3, 12], 22]], a
    56 end
    57 
    58 assert 'Enumerator#with_index nonnum offset' do
    59   s = Object.new
    60   def s.to_int; 1 end
    61   assert_equal([[1,1],[2,2],[3,3]], @obj.to_enum(:foo, 1, 2, 3).with_index(s).to_a)
    6264end
    6365
     
    100102assert 'Enumerator#inspect' do
    101103  e = (0..10).each
    102   assert_equal("#<Enumerator: 0..10:each>", e.inspect)
    103   e = Enumerator.new("FooObject", :foo, 1)
    104   assert_equal("#<Enumerator: FooObject:foo(1)>", e.inspect)
    105   e = Enumerator.new("FooObject", :foo, 1, 2, 3)
    106   assert_equal("#<Enumerator: FooObject:foo(1, 2, 3)>", e.inspect)
     104  assert_equal('#<Enumerator: 0..10:each>', e.inspect)
     105  e = 'FooObject'.enum_for(:foo, 1)
     106  assert_equal('#<Enumerator: "FooObject":foo(1)>', e.inspect)
     107  e = 'FooObject'.enum_for(:foo, 1, 2, 3)
     108  assert_equal('#<Enumerator: "FooObject":foo(1, 2, 3)>', e.inspect)
     109  e = nil.enum_for(:to_s)
     110  assert_equal('#<Enumerator: nil:to_s>', e.inspect)
    107111end
    108112
     
    426430
    427431assert 'Kernel#to_enum' do
     432  e = nil
    428433  assert_equal Enumerator, [].to_enum.class
    429   assert_raise(ArgumentError){ nil.to_enum }
     434  assert_nothing_raised { e = [].to_enum(:_not_implemented_) }
     435  assert_raise(NoMethodError) { e.first }
    430436end
    431437
     
    510516assert 'Hash#select' do
    511517  h = {1=>2,3=>4,5=>6}
    512   hret = h.select.with_index {|a,b| a[1] == 4}
     518  hret = h.select.with_index {|a,_b| a[1] == 4}
    513519  assert_equal({3=>4}, hret)
    514520  assert_equal({1=>2,3=>4,5=>6}, h)
     
    517523assert 'Hash#select!' do
    518524  h = {1=>2,3=>4,5=>6}
    519   hret = h.select!.with_index {|a,b| a[1] == 4}
     525  hret = h.select!.with_index {|a,_b| a[1] == 4}
    520526  assert_equal h, hret
    521527  assert_equal({3=>4}, h)
     
    524530assert 'Hash#reject' do
    525531  h = {1=>2,3=>4,5=>6}
    526   hret = h.reject.with_index {|a,b| a[1] == 4}
     532  hret = h.reject.with_index {|a,_b| a[1] == 4}
    527533  assert_equal({1=>2,5=>6}, hret)
    528534  assert_equal({1=>2,3=>4,5=>6}, h)
     
    531537assert 'Hash#reject!' do
    532538  h = {1=>2,3=>4,5=>6}
    533   hret = h.reject!.with_index {|a,b| a[1] == 4}
     539  hret = h.reject!.with_index {|a,_b| a[1] == 4}
    534540  assert_equal h, hret
    535541  assert_equal({1=>2,5=>6}, h)
     
    545551  assert_equal [1,2,3,4,5], c
    546552end
     553
     554assert 'Enumerable#zip' do
     555  assert_equal [[1, 10], [2, 11], [3, 12]], [1,2,3].zip(10..Float::INFINITY)
     556
     557  ret = []
     558  assert_equal nil, [1,2,3].zip(10..Float::INFINITY) { |i| ret << i }
     559  assert_equal [[1, 10], [2, 11], [3, 12]], ret
     560
     561  assert_raise(TypeError) { [1].zip(1) }
     562end
     563
     564assert 'Enumerator.produce' do
     565  assert_raise(ArgumentError) { Enumerator.produce }
     566
     567  # Without initial object
     568  passed_args = []
     569  enum = Enumerator.produce {|obj| passed_args << obj; (obj || 0).succ }
     570  assert_equal Enumerator, enum.class
     571  assert_take [1, 2, 3], enum
     572  assert_equal [nil, 1, 2], passed_args
     573
     574  # With initial object
     575  passed_args = []
     576  enum = Enumerator.produce(1) {|obj| passed_args << obj; obj.succ }
     577  assert_take [1, 2, 3], enum
     578  assert_equal [1, 2], passed_args
     579
     580  # Raising StopIteration
     581  words = %w[The quick brown fox jumps over the lazy dog]
     582  enum = Enumerator.produce { words.shift or raise StopIteration }
     583  assert_equal %w[The quick brown fox jumps over the lazy dog], enum.to_a
     584
     585  # Raising StopIteration
     586  object = [[[["abc", "def"], "ghi", "jkl"], "mno", "pqr"], "stuv", "wxyz"]
     587  enum = Enumerator.produce(object) {|obj|
     588    obj.respond_to?(:first) or raise StopIteration
     589    obj.first
     590  }
     591  assert_nothing_raised {
     592    assert_equal [
     593      [[[["abc", "def"], "ghi", "jkl"], "mno", "pqr"], "stuv", "wxyz"],
     594      [[["abc", "def"], "ghi", "jkl"], "mno", "pqr"],
     595      [["abc", "def"], "ghi", "jkl"],
     596      ["abc", "def"],
     597      "abc",
     598    ], enum.to_a
     599  }
     600end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-error/src/exception.c

    r331 r439  
    99  struct mrb_jmpbuf c_jmp;
    1010  mrb_value result = mrb_nil_value();
     11  int ai = mrb_gc_arena_save(mrb);
    1112
    1213  if (state) { *state = FALSE; }
     
    2324  } MRB_END_EXC(&c_jmp);
    2425
     26  mrb_gc_arena_restore(mrb, ai);
    2527  mrb_gc_protect(mrb, result);
    2628  return result;
     
    3335  struct mrb_jmpbuf c_jmp;
    3436  mrb_value result;
     37  int ai = mrb_gc_arena_save(mrb);
    3538
    3639  MRB_TRY(&c_jmp) {
     
    4043  } MRB_CATCH(&c_jmp) {
    4144    mrb->jmp = prev_jmp;
     45    mrb_gc_arena_restore(mrb, ai);
    4246    ensure(mrb, e_data);
    4347    MRB_THROW(mrb->jmp); /* rethrow catched exceptions */
    4448  } MRB_END_EXC(&c_jmp);
    4549
     50  mrb_gc_arena_restore(mrb, ai);
     51  mrb_gc_protect(mrb, result);
    4652  ensure(mrb, e_data);
     53  mrb_gc_arena_restore(mrb, ai);
    4754  mrb_gc_protect(mrb, result);
    4855  return result;
     
    6572  mrb_bool error_matched = FALSE;
    6673  mrb_int i;
     74  int ai = mrb_gc_arena_save(mrb);
    6775
    6876  MRB_TRY(&c_jmp) {
     
    8391
    8492    mrb->exc = NULL;
     93    mrb_gc_arena_restore(mrb, ai);
    8594    result = rescue(mrb, r_data);
    8695  } MRB_END_EXC(&c_jmp);
    8796
     97  mrb_gc_arena_restore(mrb, ai);
    8898  mrb_gc_protect(mrb, result);
    8999  return result;
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-eval/src/eval.c

    r331 r439  
    1313get_closure_irep(mrb_state *mrb, int level)
    1414{
    15   struct mrb_context *c = mrb->c;
    16   struct REnv *e = c->ci[-1].proc->env;
    17   struct RProc *proc;
    18 
    19   if (level == 0) {
    20     proc = c->ci[-1].proc;
    21     if (MRB_PROC_CFUNC_P(proc)) {
    22       return NULL;
    23     }
    24     return proc->body.irep;
    25   }
    26 
    27   while (--level) {
    28     e = (struct REnv*)e->c;
    29     if (!e) return NULL;
    30   }
    31 
    32   if (!e) return NULL;
    33   if (!MRB_ENV_STACK_SHARED_P(e)) return NULL;
    34   c = e->cxt.c;
    35   proc = c->cibase[e->cioff].proc;
    36 
    37   if (!proc || MRB_PROC_CFUNC_P(proc)) {
     15  struct RProc *proc = mrb->c->ci[-1].proc;
     16
     17  while (level--) {
     18    if (!proc) return NULL;
     19    proc = proc->upper;
     20  }
     21  if (!proc) return NULL;
     22  if (MRB_PROC_CFUNC_P(proc)) {
    3823    return NULL;
    3924  }
     
    4126}
    4227
    43 static inline mrb_code
     28/* search for irep lev above the bottom */
     29static mrb_irep*
     30search_irep(mrb_irep *top, int bnest, int lev, mrb_irep *bottom)
     31{
     32  int i;
     33
     34  for (i=0; i<top->rlen; i++) {
     35    mrb_irep* tmp = top->reps[i];
     36
     37    if (tmp == bottom) return top;
     38    tmp = search_irep(tmp, bnest-1, lev, bottom);
     39    if (tmp) {
     40      if (bnest == lev) return top;
     41      return tmp;
     42    }
     43  }
     44  return NULL;
     45}
     46
     47static uint16_t
    4448search_variable(mrb_state *mrb, mrb_sym vsym, int bnest)
    4549{
     
    4953
    5054  for (level = 0; (virep = get_closure_irep(mrb, level)); level++) {
    51     if (!virep || virep->lv == NULL) {
     55    if (virep->lv == NULL) {
    5256      continue;
    5357    }
    5458    for (pos = 0; pos < virep->nlocals - 1; pos++) {
    5559      if (vsym == virep->lv[pos].name) {
    56         return (MKARG_B(pos + 1) | MKARG_C(level + bnest));
    57       }
    58     }
    59   }
    60 
     60        return (pos+1)<<8 | (level+bnest);
     61      }
     62    }
     63  }
     64
     65  return 0;
     66}
     67
     68static int
     69irep_argc(mrb_irep *irep)
     70{
     71  mrb_code c;
     72
     73  c = irep->iseq[0];
     74  if (c == OP_ENTER) {
     75    mrb_aspec ax = PEEK_W(irep->iseq+1);
     76    /* extra 1 means a slot for block */
     77    return MRB_ASPEC_REQ(ax)+MRB_ASPEC_OPT(ax)+MRB_ASPEC_REST(ax)+MRB_ASPEC_POST(ax)+1;
     78  }
    6179  return 0;
    6280}
     
    7189}
    7290
     91extern uint8_t mrb_insn_size[];
     92extern uint8_t mrb_insn_size1[];
     93extern uint8_t mrb_insn_size2[];
     94extern uint8_t mrb_insn_size3[];
     95
    7396static void
    74 patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest)
    75 {
    76   size_t i;
    77   mrb_code c;
    78   int argc = 0;
    79 
    80   for (i = 0; i < irep->ilen; i++) {
    81     c = irep->iseq[i];
    82     switch(GET_OPCODE(c)){
    83     case OP_ENTER:
    84       {
    85         mrb_aspec ax = GETARG_Ax(c);
    86         /* extra 1 means a slot for block */
    87         argc = MRB_ASPEC_REQ(ax)+MRB_ASPEC_OPT(ax)+MRB_ASPEC_REST(ax)+MRB_ASPEC_POST(ax)+1;
    88       }
    89       break;
    90 
     97patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
     98{
     99  int i;
     100  uint32_t a;
     101  uint16_t b;
     102  uint8_t c;
     103  mrb_code insn;
     104  int argc = irep_argc(irep);
     105  mrb_code *iseq = (mrb_code *)irep->iseq;
     106
     107  mrb_assert((irep->flags & MRB_ISEQ_NO_FREE) == 0);
     108
     109  for (i = 0; i < irep->ilen; ) {
     110    insn = iseq[i];
     111    switch(insn){
    91112    case OP_EPUSH:
    92       patch_irep(mrb, irep->reps[GETARG_Bx(c)], bnest + 1);
     113      a = PEEK_B(iseq+i+1);
     114      patch_irep(mrb, irep->reps[a], bnest + 1, top);
    93115      break;
    94116
    95117    case OP_LAMBDA:
    96       {
    97         int arg_c = GETARG_c(c);
    98         if (arg_c & OP_L_CAPTURE) {
    99           patch_irep(mrb, irep->reps[GETARG_b(c)], bnest + 1);
    100         }
    101       }
     118    case OP_BLOCK:
     119      a = PEEK_B(iseq+i+1);
     120      b = PEEK_B(iseq+i+2);
     121      patch_irep(mrb, irep->reps[b], bnest + 1, top);
    102122      break;
    103123
    104124    case OP_SEND:
    105       if (GETARG_C(c) != 0) {
     125      b = PEEK_B(iseq+i+2);
     126      c = PEEK_B(iseq+i+3);
     127      if (c != 0) {
    106128        break;
    107129      }
    108       {
    109         mrb_code arg = search_variable(mrb, irep->syms[GETARG_B(c)], bnest);
     130      else {
     131        uint16_t arg = search_variable(mrb, irep->syms[b], bnest);
    110132        if (arg != 0) {
    111133          /* must replace */
    112           irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
     134          iseq[i] = OP_GETUPVAR;
     135          iseq[i+2] = arg >> 8;
     136          iseq[i+3] = arg & 0xff;
    113137        }
    114138      }
     
    116140
    117141    case OP_MOVE:
     142      a = PEEK_B(iseq+i+1);
     143      b = PEEK_B(iseq+i+2);
    118144      /* src part */
    119       if (potential_upvar_p(irep->lv, GETARG_B(c), argc, irep->nlocals)) {
    120         mrb_code arg = search_variable(mrb, irep->lv[GETARG_B(c) - 1].name, bnest);
     145      if (potential_upvar_p(irep->lv, b, argc, irep->nlocals)) {
     146        uint16_t arg = search_variable(mrb, irep->lv[b - 1].name, bnest);
    121147        if (arg != 0) {
    122148          /* must replace */
    123           irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
     149          iseq[i] = insn = OP_GETUPVAR;
     150          iseq[i+2] = arg >> 8;
     151          iseq[i+3] = arg & 0xff;
    124152        }
    125153      }
    126154      /* dst part */
    127       if (potential_upvar_p(irep->lv, GETARG_A(c), argc, irep->nlocals)) {
    128         mrb_code arg = search_variable(mrb, irep->lv[GETARG_A(c) - 1].name, bnest);
     155      if (potential_upvar_p(irep->lv, a, argc, irep->nlocals)) {
     156        uint16_t arg = search_variable(mrb, irep->lv[a - 1].name, bnest);
    129157        if (arg != 0) {
    130158          /* must replace */
    131           irep->iseq[i] = MKOPCODE(OP_SETUPVAR) | MKARG_A(GETARG_B(c)) | arg;
    132         }
    133       }
    134       break;
    135 
    136     case OP_STOP:
    137       if (mrb->c->ci->acc >= 0) {
    138         irep->iseq[i] = MKOP_AB(OP_RETURN, irep->nlocals, OP_R_NORMAL);
    139       }
    140       break;
    141     }
     159          iseq[i] = insn = OP_SETUPVAR;
     160          iseq[i+1] = (mrb_code)b;
     161          iseq[i+2] = arg >> 8;
     162          iseq[i+3] = arg & 0xff;
     163        }
     164      }
     165      break;
     166
     167    case OP_GETUPVAR:
     168      a = PEEK_B(iseq+i+1);
     169      b = PEEK_B(iseq+i+2);
     170      c = PEEK_B(iseq+i+3);
     171      {
     172        int lev = c+1;
     173        mrb_irep *tmp = search_irep(top, bnest, lev, irep);
     174        if (potential_upvar_p(tmp->lv, b, irep_argc(tmp), tmp->nlocals)) {
     175          uint16_t arg = search_variable(mrb, tmp->lv[b-1].name, bnest);
     176          if (arg != 0) {
     177            /* must replace */
     178            iseq[i] = OP_GETUPVAR;
     179            iseq[i+2] = arg >> 8;
     180            iseq[i+3] = arg & 0xff;
     181          }
     182        }
     183      }
     184      break;
     185
     186    case OP_SETUPVAR:
     187      a = PEEK_B(iseq+i+1);
     188      b = PEEK_B(iseq+i+2);
     189      c = PEEK_B(iseq+i+3);
     190      {
     191        int lev = c+1;
     192        mrb_irep *tmp = search_irep(top, bnest, lev, irep);
     193        if (potential_upvar_p(tmp->lv, b, irep_argc(tmp), tmp->nlocals)) {
     194          uint16_t arg = search_variable(mrb, tmp->lv[b-1].name, bnest);
     195          if (arg != 0) {
     196            /* must replace */
     197            iseq[i] = OP_SETUPVAR;
     198            iseq[i+1] = a;
     199            iseq[i+2] = arg >> 8;
     200            iseq[i+3] = arg & 0xff;
     201          }
     202        }
     203      }
     204      break;
     205
     206    case OP_EXT1:
     207      insn = PEEK_B(iseq+i+1);
     208      i += mrb_insn_size1[insn]+1;
     209      continue;
     210    case OP_EXT2:
     211      insn = PEEK_B(iseq+i+1);
     212      i += mrb_insn_size2[insn]+1;
     213      continue;
     214    case OP_EXT3:
     215      insn = PEEK_B(iseq+i+1);
     216      i += mrb_insn_size3[insn]+1;
     217      continue;
     218    }
     219    i+=mrb_insn_size[insn];
    142220  }
    143221}
     
    146224
    147225static struct RProc*
    148 create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, const char *file, mrb_int line)
     226create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding, const char *file, mrb_int line)
    149227{
    150228  mrbc_context *cxt;
     
    152230  struct RProc *proc;
    153231  struct REnv *e;
    154   struct mrb_context *c = mrb->c;
     232  mrb_callinfo *ci; /* callinfo of eval caller */
     233  struct RClass *target_class = NULL;
     234  int bidx;
    155235
    156236  if (!mrb_nil_p(binding)) {
     
    159239
    160240  cxt = mrbc_context_new(mrb);
    161   cxt->lineno = line;
     241  cxt->lineno = (uint16_t)line;
    162242
    163243  mrbc_filename(mrb, cxt, file ? file : "(eval)");
    164244  cxt->capture_errors = TRUE;
    165245  cxt->no_optimize = TRUE;
     246  cxt->on_eval = TRUE;
    166247
    167248  p = mrb_parse_nstring(mrb, s, len, cxt);
     
    177258
    178259    if (file) {
    179       str = mrb_format(mrb, " file %S line %S: %S",
    180                        mrb_str_new_cstr(mrb, file),
    181                        mrb_fixnum_value(p->error_buffer[0].lineno),
    182                        mrb_str_new_cstr(mrb, p->error_buffer[0].message));
     260      str = mrb_format(mrb, "file %s line %d: %s",
     261                       file,
     262                       p->error_buffer[0].lineno,
     263                       p->error_buffer[0].message);
    183264    }
    184265    else {
    185       str = mrb_format(mrb, " line %S: %S",
    186                        mrb_fixnum_value(p->error_buffer[0].lineno),
    187                        mrb_str_new_cstr(mrb, p->error_buffer[0].message));
     266      str = mrb_format(mrb, "line %d: %s",
     267                       p->error_buffer[0].lineno,
     268                       p->error_buffer[0].message);
    188269    }
    189270    mrb_parser_free(p);
     
    199280    mrb_raise(mrb, E_SCRIPT_ERROR, "codegen error");
    200281  }
    201   if (c->ci[-1].proc->target_class) {
    202     proc->target_class = c->ci[-1].proc->target_class;
    203   }
    204   e = c->ci[-1].proc->env;
    205   if (!e) e = c->ci[-1].env;
    206   e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)e);
    207   e->cxt.c = c;
    208   e->cioff = c->ci - c->cibase;
    209   e->stack = c->ci->stackent;
    210   MRB_SET_ENV_STACK_LEN(e, c->ci->proc->body.irep->nlocals);
    211   c->ci->target_class = proc->target_class;
    212   c->ci->env = 0;
    213   proc->env = e;
    214   patch_irep(mrb, proc->body.irep, 0);
     282  if (mrb->c->ci > mrb->c->cibase) {
     283    ci = &mrb->c->ci[-1];
     284  }
     285  else {
     286    ci = mrb->c->cibase;
     287  }
     288  if (ci->proc) {
     289    target_class = MRB_PROC_TARGET_CLASS(ci->proc);
     290  }
     291  if (ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) {
     292    if (ci->env) {
     293      e = ci->env;
     294    }
     295    else {
     296      e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV,
     297                                      (struct RClass*)target_class);
     298      e->mid = ci->mid;
     299      e->stack = ci[1].stackent;
     300      e->cxt = mrb->c;
     301      MRB_ENV_SET_STACK_LEN(e, ci->proc->body.irep->nlocals);
     302      bidx = ci->argc;
     303      if (ci->argc < 0) bidx = 2;
     304      else bidx += 1;
     305      MRB_ENV_SET_BIDX(e, bidx);
     306      ci->env = e;
     307    }
     308    proc->e.env = e;
     309    proc->flags |= MRB_PROC_ENVSET;
     310    mrb_field_write_barrier(mrb, (struct RBasic*)proc, (struct RBasic*)e);
     311  }
     312  proc->upper = ci->proc;
     313  mrb->c->ci->target_class = target_class;
     314  patch_irep(mrb, proc->body.irep, 0, proc->body.irep);
     315  /* mrb_codedump_all(mrb, proc); */
    215316
    216317  mrb_parser_free(p);
     
    223324exec_irep(mrb_state *mrb, mrb_value self, struct RProc *proc)
    224325{
     326  /* no argument passed from eval() */
     327  mrb->c->ci->argc = 0;
    225328  if (mrb->c->ci->acc < 0) {
    226     mrb_value ret = mrb_top_run(mrb, proc, mrb->c->stack[0], 0);
     329    ptrdiff_t cioff = mrb->c->ci - mrb->c->cibase;
     330    mrb_value ret = mrb_top_run(mrb, proc, self, 0);
    227331    if (mrb->exc) {
    228332      mrb_exc_raise(mrb, mrb_obj_value(mrb->exc));
    229333    }
     334    mrb->c->ci = mrb->c->cibase + cioff;
    230335    return ret;
    231336  }
     337  /* clear block */
     338  mrb->c->stack[1] = mrb_nil_value();
    232339  return mrb_exec_irep(mrb, self, proc);
    233340}
     
    256363  mrb_int argc; mrb_value *argv;
    257364
    258   mrb_get_args(mrb, "*&", &argv, &argc, &b);
     365  mrb_get_args(mrb, "*!&", &argv, &argc, &b);
    259366
    260367  if (mrb_nil_p(b)) {
     
    269376    cv = mrb_singleton_class(mrb, self);
    270377    proc = create_proc_from_string(mrb, s, len, mrb_nil_value(), file, line);
    271     proc->target_class = mrb_class_ptr(cv);
    272     mrb->c->ci->env = NULL;
     378    MRB_PROC_SET_TARGET_CLASS(proc, mrb_class_ptr(cv));
    273379    mrb_assert(!MRB_PROC_CFUNC_P(proc));
     380    mrb->c->ci->target_class = mrb_class_ptr(cv);
    274381    return exec_irep(mrb, self, proc);
    275382  }
     
    284391{
    285392  mrb_define_module_function(mrb, mrb->kernel_module, "eval", f_eval, MRB_ARGS_ARG(1, 3));
    286   mrb_define_method(mrb, mrb->kernel_module, "instance_eval", f_instance_eval, MRB_ARGS_ARG(1, 2));
     393  mrb_define_method(mrb, mrb_class_get(mrb, "BasicObject"), "instance_eval", f_instance_eval, MRB_ARGS_OPT(3)|MRB_ARGS_BLOCK());
    287394}
    288395
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-eval/test/eval.rb

    r331 r439  
    3535  assert_equal(2) {
    3636    a = 10
    37     Kernel.eval 'def f(a); b=a.send(:+, 1); end'
     37    Kernel.eval 'def f(a); b=a+1; end'
    3838    f(1)
    3939  }
     
    5959assert('String instance_eval') do
    6060  obj = Object.new
    61   obj.instance_variable_set :@test, 'test'
     61  obj.instance_eval{ @test = 'test' }
    6262  assert_raise(ArgumentError) { obj.instance_eval(0) { } }
    6363  assert_raise(ArgumentError) { obj.instance_eval('0', 'test', 0, 'test') }
     
    8181end
    8282
    83 assert('Object#instance_eval with begin-rescue-ensure execution order') do
     83assert('BasicObject#instance_eval with begin-rescue-ensure execution order') do
    8484  class HellRaiser
    8585    def raise_hell
     
    100100  assert_equal([:enter_raise_hell, :begin, :rescue, :ensure], hell_raiser.raise_hell)
    101101end
     102
     103assert('BasicObject#instance_eval to define singleton methods Issue #3141') do
     104  foo_class = Class.new do
     105    def bar(x)
     106      instance_eval "def baz; #{x}; end"
     107    end
     108  end
     109
     110  f1 = foo_class.new
     111  f2 = foo_class.new
     112  f1.bar 1
     113  f2.bar 2
     114  assert_equal(1){f1.baz}
     115  assert_equal(2){f2.baz}
     116end
     117
     118assert('Kernel.#eval(string) Issue #4021') do
     119  assert_equal('FOO') { (eval <<'EOS').call }
     120foo = "FOO"
     121Proc.new { foo }
     122EOS
     123  assert_equal('FOO') {
     124    def do_eval(code)
     125      eval(code)
     126    end
     127    do_eval(<<'EOS').call
     128foo = "FOO"
     129Proc.new { foo }
     130EOS
     131  }
     132end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-exit/src/mruby-exit.c

    r331 r439  
    55f_exit(mrb_state *mrb, mrb_value self)
    66{
    7   mrb_int i = EXIT_SUCCESS;
     7  mrb_value status = mrb_true_value();
     8  int istatus;
    89
    9   mrb_get_args(mrb, "|i", &i);
    10   exit(i);
     10  mrb_get_args(mrb, "|o", &status);
     11  istatus = mrb_true_p(status) ? EXIT_SUCCESS :
     12            mrb_false_p(status) ? EXIT_FAILURE :
     13            (int)mrb_int(mrb, status);
     14  exit(istatus);
     15
    1116  /* not reached */
    12   return mrb_nil_value();
     17  return status;
    1318}
    1419
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-fiber/src/fiber.c

    r331 r439  
    7373  size_t slen;
    7474
    75   mrb_get_args(mrb, "&", &blk);
     75  mrb_get_args(mrb, "&!", &blk);
    7676
    7777  if (f->cxt) {
    7878    mrb_raise(mrb, E_RUNTIME_ERROR, "cannot initialize twice");
    79   }
    80   if (mrb_nil_p(blk)) {
    81     mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Fiber object without a block");
    8279  }
    8380  p = mrb_proc_ptr(blk);
     
    124121  /* adjust return callinfo */
    125122  ci = c->ci;
    126   ci->target_class = p->target_class;
     123  ci->target_class = MRB_PROC_TARGET_CLASS(p);
    127124  ci->proc = p;
     125  mrb_field_write_barrier(mrb, (struct RBasic*)mrb_obj_ptr(self), (struct RBasic*)p);
    128126  ci->pc = p->body.irep->iseq;
    129   ci->nregs = p->body.irep->nregs;
    130127  ci[1] = ci[0];
    131128  c->ci++;                      /* push dummy callinfo */
     
    187184  struct mrb_context *c = fiber_check(mrb, self);
    188185  struct mrb_context *old_c = mrb->c;
     186  enum mrb_fiber_state status;
    189187  mrb_value value;
    190188
    191189  fiber_check_cfunc(mrb, c);
    192   if (resume && c->status == MRB_FIBER_TRANSFERRED) {
    193     mrb_raise(mrb, E_FIBER_ERROR, "resuming transferred fiber");
    194   }
    195   if (c->status == MRB_FIBER_RUNNING || c->status == MRB_FIBER_RESUMED) {
    196     mrb_raise(mrb, E_FIBER_ERROR, "double resume (fib)");
    197   }
    198   if (c->status == MRB_FIBER_TERMINATED) {
     190  status = c->status;
     191  switch (status) {
     192  case MRB_FIBER_TRANSFERRED:
     193    if (resume) {
     194      mrb_raise(mrb, E_FIBER_ERROR, "resuming transferred fiber");
     195    }
     196    break;
     197  case MRB_FIBER_RUNNING:
     198  case MRB_FIBER_RESUMED:
     199    mrb_raise(mrb, E_FIBER_ERROR, "double resume");
     200    break;
     201  case MRB_FIBER_TERMINATED:
    199202    mrb_raise(mrb, E_FIBER_ERROR, "resuming dead fiber");
    200   }
    201   mrb->c->status = resume ? MRB_FIBER_RESUMED : MRB_FIBER_TRANSFERRED;
     203    break;
     204  default:
     205    break;
     206  }
     207  old_c->status = resume ? MRB_FIBER_RESUMED : MRB_FIBER_TRANSFERRED;
    202208  c->prev = resume ? mrb->c : (c->prev ? c->prev : mrb->root_c);
    203   if (c->status == MRB_FIBER_CREATED) {
     209  fiber_switch_context(mrb, c);
     210  if (status == MRB_FIBER_CREATED) {
    204211    mrb_value *b, *e;
    205212
    206     if (len >= c->stend - c->stack) {
    207       mrb_raise(mrb, E_FIBER_ERROR, "too many arguments to fiber");
     213    if (!c->ci->proc) {
     214      mrb_raise(mrb, E_FIBER_ERROR, "double resume (current)");
    208215    }
     216    mrb_stack_extend(mrb, len+2); /* for receiver and (optional) block */
    209217    b = c->stack+1;
    210218    e = b + len;
     
    212220      *b++ = *a++;
    213221    }
    214     c->cibase->argc = len;
    215     value = c->stack[0] = c->ci->proc->env->stack[0];
     222    c->cibase->argc = (int)len;
     223    value = c->stack[0] = MRB_PROC_ENV(c->ci->proc)->stack[0];
    216224  }
    217225  else {
    218226    value = fiber_result(mrb, a, len);
    219227  }
    220   fiber_switch_context(mrb, c);
    221228
    222229  if (vmexec) {
     
    253260  mrb_bool vmexec = FALSE;
    254261
    255   mrb_get_args(mrb, "*", &a, &len);
     262  mrb_get_args(mrb, "*!", &a, &len);
    256263  if (mrb->c->ci->acc < 0) {
    257264    vmexec = TRUE;
     
    274281 *  execution of the fiber block this method will always return false.
    275282 */
    276 static mrb_value
    277 fiber_alive_p(mrb_state *mrb, mrb_value self)
     283MRB_API mrb_value
     284mrb_fiber_alive_p(mrb_state *mrb, mrb_value self)
    278285{
    279286  struct mrb_context *c = fiber_check(mrb, self);
    280287  return mrb_bool_value(c->status != MRB_FIBER_TERMINATED);
    281288}
     289#define fiber_alive_p mrb_fiber_alive_p
    282290
    283291static mrb_value
     
    287295  mrb_get_args(mrb, "o", &other);
    288296
    289   if (mrb_type(other) != MRB_TT_FIBER) {
     297  if (!mrb_fiber_p(other)) {
    290298    return mrb_false_value();
    291299  }
     
    313321
    314322  fiber_check_cfunc(mrb, mrb->c);
    315   mrb_get_args(mrb, "*", &a, &len);
     323  mrb_get_args(mrb, "*!", &a, &len);
    316324
    317325  if (c == mrb->root_c) {
     
    371379  mrb_int len;
    372380
    373   mrb_get_args(mrb, "*", &a, &len);
     381  mrb_get_args(mrb, "*!", &a, &len);
    374382  return mrb_fiber_yield(mrb, len, a);
    375383}
     
    402410  MRB_SET_INSTANCE_TT(c, MRB_TT_FIBER);
    403411
    404   mrb_define_method(mrb, c, "initialize", fiber_init,    MRB_ARGS_NONE());
     412  mrb_define_method(mrb, c, "initialize", fiber_init,    MRB_ARGS_NONE()|MRB_ARGS_BLOCK());
    405413  mrb_define_method(mrb, c, "resume",     fiber_resume,  MRB_ARGS_ANY());
    406414  mrb_define_method(mrb, c, "transfer",   fiber_transfer, MRB_ARGS_ANY());
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-fiber/test/fiber.rb

    r321 r439  
    7777
    7878assert('Fiber with splat in the block argument list') {
    79   Fiber.new{|*x|x}.resume(1) == [1]
     79  assert_equal([1], Fiber.new{|*x|x}.resume(1))
    8080}
    8181
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-hash-ext/mrbgem.rake

    r321 r439  
    33  spec.author  = 'mruby developers'
    44  spec.summary = 'Hash class extension'
    5   spec.add_dependency 'mruby-enum-ext', :core => 'mruby-enum-ext'
    6   spec.add_dependency 'mruby-array-ext', :core => 'mruby-array-ext'
     5  spec.add_dependency 'mruby-array-ext', core: 'mruby-array-ext'
    76end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-hash-ext/mrblib/hash.rb

    r331 r439  
    2828    if length == 1
    2929      o = object[0]
    30       if o.respond_to?(:to_hash)
     30      if Hash === o
    3131        h = self.new
    32         object[0].to_hash.each { |k, v| h[k] = v }
     32        o.each { |k, v| h[k] = v }
    3333        return h
    3434      elsif o.respond_to?(:to_a)
     
    6363  ##
    6464  # call-seq:
    65   #     Hash.try_convert(obj) -> hash or nil
    66   #
    67   # Try to convert <i>obj</i> into a hash, using to_hash method.
    68   # Returns converted hash or nil if <i>obj</i> cannot be converted
    69   # for any reason.
    70   #
    71   #     Hash.try_convert({1=>2})   # => {1=>2}
    72   #     Hash.try_convert("1=>2")   # => nil
    73   #
    74   def self.try_convert(obj)
    75     if obj.respond_to?(:to_hash)
    76       obj.to_hash
    77     else
    78       nil
    79     end
    80   end
    81 
    82   ##
    83   # call-seq:
    8465  #     hsh.merge!(other_hash)                                 -> hsh
    8566  #     hsh.merge!(other_hash){|key, oldval, newval| block}    -> hsh
     
    10283
    10384  def merge!(other, &block)
    104     raise TypeError, "can't convert argument into Hash" unless other.respond_to?(:to_hash)
     85    raise TypeError, "Hash required (#{other.class} given)" unless Hash === other
    10586    if block
    10687      other.each_key{|k|
     
    11495
    11596  alias update merge!
     97
     98  ##
     99  # call-seq:
     100  #   hsh.compact!    -> hsh
     101  #
     102  # Removes all nil values from the hash. Returns the hash.
     103  # Returns nil if the hash does not contain nil values.
     104  #
     105  #   h = { a: 1, b: false, c: nil }
     106  #   h.compact!     #=> { a: 1, b: false }
     107  #
     108
     109  def compact!
     110    keys = self.keys
     111    nk = keys.select{|k|
     112      self[k] != nil
     113    }
     114    return nil if (keys.size == nk.size)
     115    h = {}
     116    nk.each {|k|
     117      h[k] = self[k]
     118    }
     119    h
     120    self.replace(h)
     121  end
     122
     123  ##
     124  # call-seq:
     125  #    hsh.compact     -> new_hsh
     126  #
     127  # Returns a new hash with the nil values/key pairs removed
     128  #
     129  #    h = { a: 1, b: false, c: nil }
     130  #    h.compact     #=> { a: 1, b: false }
     131  #    h             #=> { a: 1, b: false, c: nil }
     132  #
     133  def compact
     134    h = {}
     135    self.keys.select{|k|
     136      self[k] != nil
     137    }.each {|k|
     138      h[k] = self[k]
     139    }
     140    h
     141  end
    116142
    117143  ##
     
    150176        none
    151177      else
    152         raise KeyError, "Key not found: #{key}"
     178        raise KeyError, "Key not found: #{key.inspect}"
    153179      end
    154180    else
     
    172198
    173199  def delete_if(&block)
    174     return to_enum :delete_if unless block_given?
     200    return to_enum :delete_if unless block
    175201
    176202    self.each do |k, v|
     
    229255
    230256  def keep_if(&block)
    231     return to_enum :keep_if unless block_given?
     257    return to_enum :keep_if unless block
    232258
    233259    keys = []
     
    285311  #
    286312  def <(hash)
    287     begin
    288       hash = hash.to_hash
    289     rescue NoMethodError
    290       raise TypeError, "can't convert #{hash.class} to Hash"
    291     end
     313    raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash
    292314    size < hash.size and all? {|key, val|
    293315      hash.key?(key) and hash[key] == val
     
    309331  #
    310332  def <=(hash)
    311     begin
    312       hash = hash.to_hash
    313     rescue NoMethodError
    314       raise TypeError, "can't convert #{hash.class} to Hash"
    315     end
     333    raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash
    316334    size <= hash.size and all? {|key, val|
    317335      hash.key?(key) and hash[key] == val
     
    333351  #
    334352  def >(hash)
    335     begin
    336       hash = hash.to_hash
    337     rescue NoMethodError
    338       raise TypeError, "can't convert #{hash.class} to Hash"
    339     end
     353    raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash
    340354    size > hash.size and hash.all? {|key, val|
    341355      key?(key) and self[key] == val
     
    357371  #
    358372  def >=(hash)
    359     begin
    360       hash = hash.to_hash
    361     rescue NoMethodError
    362       raise TypeError, "can't convert #{hash.class} to Hash"
    363     end
     373    raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash
    364374    size >= hash.size and hash.all? {|key, val|
    365375      key?(key) and self[key] == val
     
    383393    end
    384394  end
     395
     396  ##
     397  # call-seq:
     398  #    hsh.transform_keys {|key| block } -> new_hash
     399  #    hsh.transform_keys                -> an_enumerator
     400  #
     401  # Returns a new hash, with the keys computed from running the block
     402  # once for each key in the hash, and the values unchanged.
     403  #
     404  # If no block is given, an enumerator is returned instead.
     405  #
     406  def transform_keys(&block)
     407    return to_enum :transform_keys unless block
     408    hash = {}
     409    self.keys.each do |k|
     410      new_key = block.call(k)
     411      hash[new_key] = self[k]
     412    end
     413    hash
     414  end
     415  ##
     416  # call-seq:
     417  #    hsh.transform_keys! {|key| block } -> hsh
     418  #    hsh.transform_keys!                -> an_enumerator
     419  #
     420  # Invokes the given block once for each key in <i>hsh</i>, replacing it
     421  # with the new key returned by the block, and then returns <i>hsh</i>.
     422  #
     423  # If no block is given, an enumerator is returned instead.
     424  #
     425  def transform_keys!(&block)
     426    return to_enum :transform_keys! unless block
     427    self.keys.each do |k|
     428      value = self[k]
     429      self.__delete(k)
     430      k = block.call(k) if block
     431      self[k] = value
     432    end
     433    self
     434  end
     435  ##
     436  # call-seq:
     437  #    hsh.transform_values {|value| block } -> new_hash
     438  #    hsh.transform_values                  -> an_enumerator
     439  #
     440  # Returns a new hash with the results of running the block once for
     441  # every value.
     442  # This method does not change the keys.
     443  #
     444  # If no block is given, an enumerator is returned instead.
     445  #
     446  def transform_values(&b)
     447    return to_enum :transform_values unless block_given?
     448    hash = {}
     449    self.keys.each do |k|
     450      hash[k] = yield(self[k])
     451    end
     452    hash
     453  end
     454
     455  ##
     456  # call-seq:
     457  #    hsh.transform_values! {|key| block } -> hsh
     458  #    hsh.transform_values!                -> an_enumerator
     459  #
     460  # Invokes the given block once for each value in the hash, replacing
     461  # with the new value returned by the block, and then returns <i>hsh</i>.
     462  #
     463  # If no block is given, an enumerator is returned instead.
     464  #
     465  def transform_values!(&b)
     466    return to_enum :transform_values! unless block_given?
     467    self.keys.each do |k|
     468      self[k] = yield(self[k])
     469    end
     470    self
     471  end
     472
     473  def to_proc
     474    ->x{self[x]}
     475  end
     476
     477  ##
     478  # call-seq:
     479  #   hsh.fetch_values(key, ...)                 -> array
     480  #   hsh.fetch_values(key, ...) { |key| block } -> array
     481  #
     482  # Returns an array containing the values associated with the given keys
     483  # but also raises <code>KeyError</code> when one of keys can't be found.
     484  # Also see <code>Hash#values_at</code> and <code>Hash#fetch</code>.
     485  #
     486  #   h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
     487  #
     488  #   h.fetch_values("cow", "cat")                   #=> ["bovine", "feline"]
     489  #   h.fetch_values("cow", "bird")                  # raises KeyError
     490  #   h.fetch_values("cow", "bird") { |k| k.upcase } #=> ["bovine", "BIRD"]
     491  #
     492  def fetch_values(*keys, &block)
     493    keys.map do |k|
     494      self.fetch(k, &block)
     495    end
     496  end
     497
     498  alias filter select
     499  alias filter! select!
    385500end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-hash-ext/src/hash-ext.c

    r331 r439  
    3737}
    3838
     39/*
     40 *  call-seq:
     41 *     hsh.slice(*keys) -> a_hash
     42 *
     43 *  Returns a hash containing only the given keys and their values.
     44 *
     45 *     h = { a: 100, b: 200, c: 300 }
     46 *     h.slice(:a)           #=> {:a=>100}
     47 *     h.slice(:b, :c, :d)   #=> {:b=>200, :c=>300}
     48 */
     49static mrb_value
     50hash_slice(mrb_state *mrb, mrb_value hash)
     51{
     52  mrb_value *argv, result;
     53  mrb_int argc, i;
     54
     55  mrb_get_args(mrb, "*", &argv, &argc);
     56  result = mrb_hash_new_capa(mrb, argc);
     57  if (argc == 0) return result; /* empty hash */
     58  for (i = 0; i < argc; i++) {
     59    mrb_value key = argv[i];
     60    mrb_value val;
     61
     62    val = mrb_hash_fetch(mrb, hash, key, mrb_undef_value());
     63    if (!mrb_undef_p(val)) {
     64      mrb_hash_set(mrb, result, key, val);
     65    }
     66  }
     67  return result;
     68}
     69
    3970void
    4071mrb_mruby_hash_ext_gem_init(mrb_state *mrb)
     
    4475  h = mrb->hash_class;
    4576  mrb_define_method(mrb, h, "values_at", hash_values_at, MRB_ARGS_ANY());
     77  mrb_define_method(mrb, h, "slice",     hash_slice, MRB_ARGS_ANY());
    4678}
    4779
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-hash-ext/test/hash.rb

    r331 r439  
    4646end
    4747
    48 assert('Hash.try_convert') do
    49   assert_nil Hash.try_convert(nil)
    50   assert_nil Hash.try_convert("{1=>2}")
    51   assert_equal({1=>2}, Hash.try_convert({1=>2}))
    52 end
    53 
    5448assert('Hash#merge!') do
    5549  a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' }
     
    8175  h = Hash.new { |hash,k| hash[k] = k }
    8276  assert_equal keys, h.values_at(*keys)
     77end
     78
     79assert('Hash#compact') do
     80  h = { "cat" => "feline", "dog" => nil, "cow" => false }
     81
     82  assert_equal({ "cat" => "feline", "cow" => false }, h.compact)
     83  assert_equal({ "cat" => "feline", "dog" => nil, "cow" => false }, h)
     84end
     85
     86assert('Hash#compact!') do
     87  h = { "cat" => "feline", "dog" => nil, "cow" => false }
     88
     89  h.compact!
     90  assert_equal({ "cat" => "feline", "cow" => false }, h)
    8391end
    8492
     
    255263  assert_nil(h.dig(:d))
    256264end
     265
     266assert("Hash#transform_keys") do
     267  h = {"1" => 100, "2" => 200}
     268  assert_equal({"1!" => 100, "2!" => 200},
     269               h.transform_keys{|k| k+"!"})
     270  assert_equal({1 => 100, 2 => 200},
     271               h.transform_keys{|k|k.to_i})
     272  assert_same(h, h.transform_keys!{|k|k.to_i})
     273  assert_equal({1 => 100, 2 => 200}, h)
     274end
     275
     276assert("Hash#transform_values") do
     277  h = {a: 1, b: 2, c: 3}
     278  assert_equal({a: 2, b: 5, c: 10},
     279               h.transform_values{|v| v * v + 1})
     280  assert_equal({a: "1", b: "2", c: "3"},
     281               h.transform_values{|v|v.to_s})
     282  assert_same(h, h.transform_values!{|v|v.to_s})
     283  assert_equal({a: "1", b: "2", c: "3"}, h)
     284end
     285
     286assert("Hash#slice") do
     287  h = { a: 100, b: 200, c: 300 }
     288  assert_equal({:a=>100}, h.slice(:a))
     289  assert_equal({:b=>200, :c=>300}, h.slice(:b, :c, :d))
     290end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-inline-struct/test/inline.c

    r331 r439  
    1212  mrb_get_args(mrb, "o", &object);
    1313
    14   if (mrb_float_p(object))
    15   {
    16     snprintf(string, size, "float(%.3f)", mrb_float(object));
     14  if (mrb_fixnum_p(object)) {
     15    strncpy(string, "fixnum", size-1);
    1716  }
    18   else if (mrb_fixnum_p(object))
    19   {
    20     snprintf(string, size, "fixnum(%" MRB_PRId ")", mrb_fixnum(object));
     17#ifndef MRB_WITHOUT_FLOAT
     18  else if (mrb_float_p(object)) {
     19    strncpy(string, "float", size-1);
    2120  }
    22   else if (mrb_string_p(object))
    23   {
    24     snprintf(string, size, "string(%s)", mrb_string_value_cstr(mrb, &object));
     21#endif
     22  else if (mrb_string_p(object)) {
     23    strncpy(string, "string", size-1);
     24  }
     25  else {
     26    strncpy(string, "anything", size-1);
    2527  }
    2628
     
    4850  if (mrb_obj_class(mrb, object) != mrb_class_get(mrb, "InlineStructTest"))
    4951  {
    50     mrb_raisef(mrb, E_TYPE_ERROR, "Expected InlineStructTest");
     52    mrb_raise(mrb, E_TYPE_ERROR, "Expected InlineStructTest");
    5153  }
    5254  return mrb_bool_value(((char*)mrb_istruct_ptr(object))[0] == 's');
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-inline-struct/test/inline.rb

    r331 r439  
    1818assert('InlineStructTest#dup') do
    1919  obj = InlineStructTest.new(1)
    20   assert_equal obj.to_s, 'fixnum(1)'
    21   assert_equal obj.dup.to_s, 'fixnum(1)'
     20  assert_equal obj.to_s, 'fixnum'
     21  assert_equal obj.dup.to_s, 'fixnum'
    2222end
    2323
    2424assert('InlineStructTest#clone') do
    2525  obj = InlineStructTest.new(1)
    26   assert_equal obj.to_s, 'fixnum(1)'
    27   assert_equal obj.clone.to_s, 'fixnum(1)'
     26  assert_equal obj.to_s, 'fixnum'
     27  assert_equal obj.clone.to_s, 'fixnum'
    2828end
    2929
     
    3939assert('InlineStructTest#mutate (dup)') do
    4040  obj1 = InlineStructTest.new("foo")
    41   assert_equal obj1.to_s, "string(foo)"
     41  assert_equal obj1.to_s, "string"
    4242  obj2 = obj1.dup
    43   assert_equal obj2.to_s, "string(foo)"
     43  assert_equal obj2.to_s, "string"
    4444  obj1.mutate
    45   assert_equal obj1.to_s, "mutate(foo)"
    46   assert_equal obj2.to_s, "string(foo)"
     45  assert_equal obj1.to_s, "mutate"
     46  assert_equal obj2.to_s, "string"
    4747end
    4848
    4949assert('InlineStructTest#mutate (clone)') do
    5050  obj1 = InlineStructTest.new("foo")
    51   assert_equal obj1.to_s, "string(foo)"
     51  assert_equal obj1.to_s, "string"
    5252  obj2 = obj1.clone
    53   assert_equal obj2.to_s, "string(foo)"
     53  assert_equal obj2.to_s, "string"
    5454  obj1.mutate
    55   assert_equal obj1.to_s, "mutate(foo)"
    56   assert_equal obj2.to_s, "string(foo)"
     55  assert_equal obj1.to_s, "mutate"
     56  assert_equal obj2.to_s, "string"
    5757end
    5858
     
    102102    assert_equal InlineStructTest.length, 3 * 8
    103103  end
    104 
    105   assert('InlineStructTest w/float [64 bit]') do
    106     obj = InlineStructTest.new(1.25)
    107     assert_equal obj.to_s, "float(1.250)"
    108   end
    109 
    110   assert('InlineStructTest w/fixnum [64 bit]') do
    111     obj = InlineStructTest.new(42)
    112     assert_equal obj.to_s, "fixnum(42)"
    113   end
    114 
    115   assert('InlineStructTest w/string [64 bit]') do
    116     obj = InlineStructTest.new("hello")
    117     assert_equal obj.to_s, "string(hello)"
    118   end
    119 
    120   assert('InlineStructTest w/long string [64 bit]') do
    121     obj = InlineStructTest.new("this won't fit in 3 * 8 bytes available for the structure")
    122     assert_equal obj.to_s, "string(this won't fit i"
    123   end
    124104end
    125105
     
    129109    assert_equal InlineStructTest.length, 3 * 4
    130110  end
     111end
    131112
    132   assert('InlineStructTest w/float [32 bit]') do
    133     obj = InlineStructTest.new(1.25)
    134     assert_equal obj.to_s, "float(1.250"
    135   end
    136 
    137   assert('InlineStructTest w/fixnum [32 bit]') do
    138     obj = InlineStructTest.new(42)
    139     assert_equal obj.to_s, "fixnum(42)"
    140   end
    141 
    142   assert('InlineStructTest w/string [32 bit]') do
    143     obj = InlineStructTest.new("hello")
    144     assert_equal obj.to_s, "string(hell"
    145   end
    146 
    147   assert('InlineStructTest w/long string [32 bit]') do
    148     obj = InlineStructTest.new("this won't fit in 3 * 4 bytes available for the structure")
    149     assert_equal obj.to_s, "string(this"
     113# 16-bit mode
     114if InlineStructTest.length == 6
     115  assert('InlineStructTest length [16 bit]') do
     116    assert_equal InlineStructTest.length, 3 * 2
    150117  end
    151118end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-kernel-ext/mrbgem.rake

    r321 r439  
    22  spec.license = 'MIT'
    33  spec.author  = 'mruby developers'
    4   spec.summary = 'Kernel module extension'
     4  spec.summary = 'extensional function-like methods'
    55end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-kernel-ext/src/kernel.c

    r331 r439  
    2121      break;
    2222    case 1:
    23       if (mrb_type(v) == MRB_TT_RANGE) {
     23      if (mrb_range_p(v)) {
    2424        mrb_int beg, len;
    25         if (mrb_range_beg_len(mrb, v, &beg, &len, bt_len, TRUE) == 1) {
     25        if (mrb_range_beg_len(mrb, v, &beg, &len, bt_len, TRUE) == MRB_RANGE_OK) {
    2626          lev = beg;
    2727          n = len;
     
    3232      }
    3333      else {
    34         v = mrb_to_int(mrb, v);
    35         lev = mrb_fixnum(v);
     34        lev = mrb_int(mrb, v);
    3635        if (lev < 0) {
    37           mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative level (%S)", v);
     36          mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative level (%v)", v);
    3837        }
    3938        n = bt_len - lev;
     
    4140      break;
    4241    case 2:
    43       lev = mrb_fixnum(mrb_to_int(mrb, v));
    44       n = mrb_fixnum(mrb_to_int(mrb, length));
     42      lev = mrb_int(mrb, v);
     43      n = mrb_int(mrb, length);
    4544      if (lev < 0) {
    46         mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative level (%S)", v);
     45        mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative level (%v)", v);
    4746      }
    4847      if (n < 0) {
    49         mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative size (%S)", length);
     48        mrb_raisef(mrb, E_ARGUMENT_ERROR, "negative size (%v)", length);
    5049      }
    5150      break;
     
    9493 *  In any case, strings should be strictly conformed to numeric
    9594 *  representation. This behavior is different from that of
    96  *  <code>String#to_i</code>.  Non string values will be converted using
    97  *  <code>to_int</code>, and <code>to_i</code>. Passing <code>nil</code>
    98  *  raises a TypeError.
     95 *  <code>String#to_i</code>.  Non string values will be treated as integers.
     96 *  Passing <code>nil</code> raises a TypeError.
    9997 *
    10098 *     Integer(123.999)    #=> 123
     
    115113}
    116114
     115#ifndef MRB_WITHOUT_FLOAT
    117116/*
    118117 *  call-seq:
     
    135134  return mrb_Float(mrb, arg);
    136135}
     136#endif
    137137
    138138/*
     
    141141 *
    142142 *  Returns <i>arg</i> as an <code>String</code>.
    143  *
    144  *  First tries to call its <code>to_str</code> method, then its to_s method.
     143 *  converted using <code>to_s</code> method.
    145144 *
    146145 *     String(self)        #=> "main"
     
    154153
    155154  mrb_get_args(mrb, "o", &arg);
    156   tmp = mrb_check_convert_type(mrb, arg, MRB_TT_STRING, "String", "to_str");
    157   if (mrb_nil_p(tmp)) {
    158     tmp = mrb_check_convert_type(mrb, arg, MRB_TT_STRING, "String", "to_s");
    159   }
     155  tmp = mrb_convert_type(mrb, arg, MRB_TT_STRING, "String", "to_s");
    160156  return tmp;
    161157}
     
    165161 *     Array(arg)    -> array
    166162 *
    167  *  Returns +arg+ as an Array.
    168  *
    169  *  First tries to call Array#to_ary on +arg+, then Array#to_a.
     163 *  Returns +arg+ as an Array using to_a method.
    170164 *
    171165 *     Array(1..5)   #=> [1, 2, 3, 4, 5]
     
    178172
    179173  mrb_get_args(mrb, "o", &arg);
    180   tmp = mrb_check_convert_type(mrb, arg, MRB_TT_ARRAY, "Array", "to_ary");
    181   if (mrb_nil_p(tmp)) {
    182     tmp = mrb_check_convert_type(mrb, arg, MRB_TT_ARRAY, "Array", "to_a");
    183   }
     174  tmp = mrb_check_convert_type(mrb, arg, MRB_TT_ARRAY, "Array", "to_a");
    184175  if (mrb_nil_p(tmp)) {
    185176    return mrb_ary_new_from_values(mrb, 1, &arg);
     
    193184 *     Hash(arg)    -> hash
    194185 *
    195  *  Converts <i>arg</i> to a <code>Hash</code> by calling
    196  *  <i>arg</i><code>.to_hash</code>. Returns an empty <code>Hash</code> when
    197  *  <i>arg</i> is <tt>nil</tt> or <tt>[]</tt>.
     186 *  Returns a <code>Hash</code> if <i>arg</i> is a <code>Hash</code>.
     187 *  Returns an empty <code>Hash</code> when <i>arg</i> is <tt>nil</tt>
     188 *  or <tt>[]</tt>.
    198189 *
    199190 *      Hash([])          #=> {}
     
    206197mrb_f_hash(mrb_state *mrb, mrb_value self)
    207198{
    208   mrb_value arg, tmp;
    209 
    210   mrb_get_args(mrb, "o", &arg);
    211   if (mrb_nil_p(arg)) {
     199  mrb_value arg;
     200
     201  mrb_get_args(mrb, "o", &arg);
     202  if (mrb_nil_p(arg) || (mrb_array_p(arg) && RARRAY_LEN(arg) == 0)) {
    212203    return mrb_hash_new(mrb);
    213204  }
    214   tmp = mrb_check_convert_type(mrb, arg, MRB_TT_HASH, "Hash", "to_hash");
    215   if (mrb_nil_p(tmp)) {
    216     if (mrb_array_p(arg) && RARRAY_LEN(arg) == 0) {
    217       return mrb_hash_new(mrb);
    218     }
    219     mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into Hash",
    220       mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, arg)));
    221   }
    222   return tmp;
     205  return mrb_ensure_hash_type(mrb, arg);
    223206}
    224207
     
    231214  mrb_define_module_function(mrb, krn, "caller", mrb_f_caller, MRB_ARGS_OPT(2));
    232215  mrb_define_method(mrb, krn, "__method__", mrb_f_method, MRB_ARGS_NONE());
    233   mrb_define_module_function(mrb, krn, "Integer", mrb_f_integer, MRB_ARGS_ANY());
     216  mrb_define_module_function(mrb, krn, "Integer", mrb_f_integer, MRB_ARGS_ARG(1,1));
     217#ifndef MRB_WITHOUT_FLOAT
    234218  mrb_define_module_function(mrb, krn, "Float", mrb_f_float, MRB_ARGS_REQ(1));
     219#endif
    235220  mrb_define_module_function(mrb, krn, "String", mrb_f_string, MRB_ARGS_REQ(1));
    236221  mrb_define_module_function(mrb, krn, "Array", mrb_f_array, MRB_ARGS_REQ(1));
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-kernel-ext/test/kernel.rb

    r331 r439  
    5050
    5151assert('Kernel#Integer') do
    52   assert_equal(123, Integer(123.999))
    53   assert_equal(26, Integer("0x1a"))
    54   assert_equal(930, Integer("0930", 10))
    55   assert_equal(7, Integer("111", 2))
    56   assert_equal(0, Integer("0"))
    57   assert_equal(0, Integer("00000"))
     52  assert_operator(26, :eql?, Integer("0x1a"))
     53  assert_operator(930, :eql?, Integer("0930", 10))
     54  assert_operator(7, :eql?, Integer("111", 2))
     55  assert_operator(0, :eql?, Integer("0"))
     56  assert_operator(0, :eql?, Integer("00000"))
     57  assert_operator(123, :eql?, Integer('1_2_3'))
     58  assert_operator(123, :eql?, Integer("\t\r\n\f\v 123 \t\r\n\f\v"))
    5859  assert_raise(TypeError) { Integer(nil) }
     60  assert_raise(ArgumentError) { Integer('a') }
     61  assert_raise(ArgumentError) { Integer('4a5') }
     62  assert_raise(ArgumentError) { Integer('1_2__3') }
     63  assert_raise(ArgumentError) { Integer('68_') }
     64  assert_raise(ArgumentError) { Integer('68_ ') }
     65  assert_raise(ArgumentError) { Integer('_68') }
     66  assert_raise(ArgumentError) { Integer(' _68') }
     67  assert_raise(ArgumentError) { Integer('6 8') }
     68  assert_raise(ArgumentError) { Integer("15\0") }
     69  assert_raise(ArgumentError) { Integer("15.0") }
     70  skip unless Object.const_defined?(:Float)
     71  assert_operator(123, :eql?, Integer(123.999))
    5972end
    6073
    6174assert('Kernel#Float') do
    62   assert_equal(1.0, Float(1))
    63   assert_equal(123.456, Float(123.456))
    64   assert_equal(123.456, Float("123.456"))
     75  skip unless Object.const_defined?(:Float)
     76  assert_operator(1.0, :eql?, Float(1))
     77  assert_operator(123.456, :eql?, Float(123.456))
     78  assert_operator(123.456, :eql?, Float("123.456"))
     79  assert_operator(123.0, :eql?, Float('1_2_3'))
     80  assert_operator(12.34, :eql?, Float('1_2.3_4'))
     81  assert_operator(0.9, :eql?, Float('.9'))
     82  assert_operator(0.9, :eql?, Float(" \t\r\n\f\v.9 \t\r\n\f\v"))
     83  assert_operator(16.0, :eql?, Float("0x10"))
    6584  assert_raise(TypeError) { Float(nil) }
     85  assert_raise(ArgumentError) { Float("1. 5") }
     86  assert_raise(ArgumentError) { Float("1.5a") }
     87  assert_raise(ArgumentError) { Float("1.5\0") }
     88  assert_raise(ArgumentError) { Float('a') }
     89  assert_raise(ArgumentError) { Float('4a5') }
     90  assert_raise(ArgumentError) { Float('1_2__3') }
     91  assert_raise(ArgumentError) { Float('68_') }
     92  assert_raise(ArgumentError) { Float('68._7') }
     93  assert_raise(ArgumentError) { Float('68.7_') }
     94  assert_raise(ArgumentError) { Float('68.7_ ') }
     95  assert_raise(ArgumentError) { Float('_68') }
     96  assert_raise(ArgumentError) { Float(' _68') }
     97  assert_raise(ArgumentError) { Float('1_2.3__4') }
    6698end
    6799
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-math/src/math.c

    r331 r439  
    55*/
    66
     7#ifdef MRB_WITHOUT_FLOAT
     8# error Math conflicts 'MRB_WITHOUT_FLOAT' configuration in your 'build_config.rb'
     9#endif
     10
    711#include <mruby.h>
    812#include <mruby/array.h>
     
    1519  struct RClass *math = mrb_module_get(mrb, "Math");
    1620  struct RClass *domainerror = mrb_class_get_under(mrb, math, "DomainError");
    17   mrb_value str = mrb_str_new_cstr(mrb, func);
    18   mrb_raisef(mrb, domainerror, "Numerical argument is out of domain - %S", str);
     21  mrb_raisef(mrb, domainerror, "Numerical argument is out of domain - %s", func);
    1922}
    2023
     
    2326
    2427#include <float.h>
    25 
    26 #define MATH_TOLERANCE 1E-12
    2728
    2829double
     
    123124    sum  += term/(2*j+1);
    124125    ++j;
    125   } while (fabs(term/sum) > MATH_TOLERANCE);
     126    if (sum == 0) break;
     127  } while (fabs(term/sum) > DBL_EPSILON);
    126128  return two_sqrtpi*sum;
    127129}
     
    156158    q1 = q2;
    157159    q2 = b/d;
    158   } while (fabs(q1-q2)/q2 > MATH_TOLERANCE);
     160  } while (fabs(q1-q2)/q2 > DBL_EPSILON);
    159161  return one_sqrtpi*exp(-x*x)*q2;
    160162}
    161163
     164#endif
     165
     166#if defined __FreeBSD__ && !defined __FreeBSD_version
     167#include <osreldate.h> /* for __FreeBSD_version */
    162168#endif
    163169
     
    487493{
    488494  mrb_float x, base;
    489   int argc;
     495  mrb_int argc;
    490496
    491497  argc = mrb_get_args(mrb, "f|f", &x, &base);
     
    658664
    659665  mrb_get_args(mrb, "fi", &x, &i);
    660   x = ldexp(x, i);
     666  x = ldexp(x, (int)i);
    661667
    662668  return mrb_float_value(mrb, x);
     
    737743#else
    738744  mrb_define_const(mrb, mrb_math, "E", mrb_float_value(mrb, exp(1.0)));
    739 #endif
    740 
    741 #ifdef MRB_USE_FLOAT
    742   mrb_define_const(mrb, mrb_math, "TOLERANCE", mrb_float_value(mrb, 1e-5));
    743 #else
    744   mrb_define_const(mrb, mrb_math, "TOLERANCE", mrb_float_value(mrb, 1e-12));
    745745#endif
    746746
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-math/test/math.rb

    r321 r439  
    22# Math Test
    33
    4 ##
    5 # Performs fuzzy check for equality on methods returning floats
    6 # on the basis of the Math::TOLERANCE constant.
    7 def check_float(a, b)
    8   tolerance = Math::TOLERANCE
    9   a = a.to_f
    10   b = b.to_f
    11   if a.finite? and b.finite?
    12     (a-b).abs < tolerance
    13   else
    14     true
     4def assert_float_and_int(exp_ary, act_ary)
     5  assert('assert_float_and_int') do
     6    flo_exp, int_exp, flo_act, int_act = *exp_ary, *act_ary
     7    assert_float(flo_exp, flo_act)
     8    assert_operator(int_exp, :eql?, int_act)
    159  end
    1610end
    1711
    1812assert('Math.sin 0') do
    19   check_float(Math.sin(0), 0)
     13  assert_float(0, Math.sin(0))
    2014end
    2115
    2216assert('Math.sin PI/2') do
    23   check_float(Math.sin(Math::PI / 2), 1)
     17  assert_float(1, Math.sin(Math::PI / 2))
    2418end
    2519
    2620assert('Math.cos 0') do
    27   check_float(Math.cos(0), 1)
     21  assert_float(1, Math.cos(0))
    2822end
    2923
    3024assert('Math.cos PI/2') do
    31   check_float(Math.cos(Math::PI / 2), 0)
     25  assert_float(0, Math.cos(Math::PI / 2))
    3226end
    3327
    3428assert('Math.tan 0') do
    35   check_float(Math.tan(0), 0)
     29  assert_float(0, Math.tan(0))
    3630end
    3731
    3832assert('Math.tan PI/4') do
    39   check_float(Math.tan(Math::PI / 4), 1)
     33  assert_float(1, Math.tan(Math::PI / 4))
    4034end
    4135
    4236assert('Fundamental trig identities') do
    43   result = true
    4437  N = 13
    4538  N.times do |i|
     
    4942    c  = Math.cos(a)
    5043    t  = Math.tan(a)
    51     result &= check_float(s, Math.cos(ca))
    52     result &= check_float(t, 1 / Math.tan(ca))
    53     result &= check_float(s ** 2 + c ** 2, 1)
    54     result &= check_float(t ** 2 + 1, (1/c) ** 2)
    55     result &= check_float((1/t) ** 2 + 1, (1/s) ** 2)
    56   end
    57   result
     44    assert_float(Math.cos(ca), s)
     45    assert_float(1 / Math.tan(ca), t)
     46    assert_float(1, s ** 2 + c ** 2)
     47    assert_float((1/c) ** 2, t ** 2 + 1)
     48    assert_float((1/s) ** 2, (1/t) ** 2 + 1)
     49  end
    5850end
    5951
    6052assert('Math.erf 0') do
    61   check_float(Math.erf(0), 0)
     53  assert_float(0, Math.erf(0))
    6254end
    6355
    6456assert('Math.exp 0') do
    65   check_float(Math.exp(0), 1.0)
     57  assert_float(1.0, Math.exp(0))
    6658end
    6759
    6860assert('Math.exp 1') do
    69   check_float(Math.exp(1), 2.718281828459045)
     61  assert_float(2.718281828459045, Math.exp(1))
    7062end
    7163
    7264assert('Math.exp 1.5') do
    73   check_float(Math.exp(1.5), 4.4816890703380645)
     65  assert_float(4.4816890703380645, Math.exp(1.5))
    7466end
    7567
    7668assert('Math.log 1') do
    77   check_float(Math.log(1), 0)
     69  assert_float(0, Math.log(1))
    7870end
    7971
    8072assert('Math.log E') do
    81   check_float(Math.log(Math::E), 1.0)
     73  assert_float(1.0, Math.log(Math::E))
    8274end
    8375
    8476assert('Math.log E**3') do
    85   check_float(Math.log(Math::E**3), 3.0)
     77  assert_float(3.0, Math.log(Math::E**3))
    8678end
    8779
    8880assert('Math.log2 1') do
    89   check_float(Math.log2(1), 0.0)
     81  assert_float(0.0, Math.log2(1))
    9082end
    9183
    9284assert('Math.log2 2') do
    93   check_float(Math.log2(2), 1.0)
     85  assert_float(1.0, Math.log2(2))
    9486end
    9587
    9688assert('Math.log10 1') do
    97   check_float(Math.log10(1), 0.0)
     89  assert_float(0.0, Math.log10(1))
    9890end
    9991
    10092assert('Math.log10 10') do
    101   check_float(Math.log10(10), 1.0)
     93  assert_float(1.0, Math.log10(10))
    10294end
    10395
    10496assert('Math.log10 10**100') do
    105   check_float(Math.log10(10**100), 100.0)
     97  assert_float(100.0, Math.log10(10**100))
    10698end
    10799
     
    109101  num = [0.0, 1.0, 2.0, 3.0, 4.0]
    110102  sqr = [0, 1, 4, 9, 16]
    111   result = true
    112103  sqr.each_with_index do |v,i|
    113     result &= check_float(Math.sqrt(v), num[i])
    114   end
    115   result
     104    assert_float(num[i], Math.sqrt(v))
     105  end
    116106end
    117107
     
    119109  num = [-2.0, -1.0, 0.0, 1.0, 2.0]
    120110  cub = [-8, -1, 0, 1, 8]
    121   result = true
    122111  cub.each_with_index do |v,i|
    123     result &= check_float(Math.cbrt(v), num[i])
    124   end
    125   result
     112    assert_float(num[i], Math.cbrt(v))
     113  end
    126114end
    127115
    128116assert('Math.hypot') do
    129   check_float(Math.hypot(3, 4), 5.0)
    130 end
    131 
    132 assert('Math.frexp 1234') do
    133   n = 1234
    134   fraction, exponent = Math.frexp(n)
    135   check_float(Math.ldexp(fraction, exponent), n)
     117  assert_float(5.0, Math.hypot(3, 4))
    136118end
    137119
    138120assert('Math.erf 1') do
    139   check_float(Math.erf(1), 0.842700792949715)
     121  assert_float(0.842700792949715, Math.erf(1))
    140122end
    141123
    142124assert('Math.erfc 1') do
    143   check_float(Math.erfc(1), 0.157299207050285)
     125  assert_float(0.157299207050285, Math.erfc(1))
    144126end
    145127
    146128assert('Math.erf -1') do
    147   check_float(Math.erf(-1), -0.8427007929497148)
     129  assert_float(-0.8427007929497148, Math.erf(-1))
    148130end
    149131
    150132assert('Math.erfc -1') do
    151   check_float(Math.erfc(-1), 1.8427007929497148)
    152 end
     133  assert_float(1.8427007929497148, Math.erfc(-1))
     134end
     135
     136assert('Math.acos') do
     137  assert_float(0 * Math::PI / 4, Math.acos( 1.0))
     138  assert_float(1 * Math::PI / 4, Math.acos( 1.0 / Math.sqrt(2)))
     139  assert_float(2 * Math::PI / 4, Math.acos( 0.0))
     140  assert_float(4 * Math::PI / 4, Math.acos(-1.0))
     141  assert_raise(Math::DomainError) { Math.acos(+1.1) }
     142  assert_raise(Math::DomainError) { Math.acos(-1.1) }
     143end
     144
     145assert('Math.asin') do
     146  assert_float( 0 * Math::PI / 4, Math.asin( 0.0))
     147  assert_float( 1 * Math::PI / 4, Math.asin( 1.0 / Math.sqrt(2)))
     148  assert_float( 2 * Math::PI / 4, Math.asin( 1.0))
     149  assert_float(-2 * Math::PI / 4, Math.asin(-1.0))
     150  assert_raise(Math::DomainError) { Math.asin(+1.1) }
     151  assert_raise(Math::DomainError) { Math.asin(-1.1) }
     152  assert_raise(Math::DomainError) { Math.asin(2.0) }
     153end
     154
     155assert('Math.atan') do
     156  assert_float( 0 * Math::PI / 4, Math.atan( 0.0))
     157  assert_float( 1 * Math::PI / 4, Math.atan( 1.0))
     158  assert_float( 2 * Math::PI / 4, Math.atan(1.0 / 0.0))
     159  assert_float(-1 * Math::PI / 4, Math.atan(-1.0))
     160end
     161
     162assert('Math.cosh') do
     163  assert_float(1, Math.cosh(0))
     164  assert_float((Math::E ** 1 + Math::E ** -1) / 2, Math.cosh(1))
     165  assert_float((Math::E ** 2 + Math::E ** -2) / 2, Math.cosh(2))
     166end
     167
     168assert('Math.sinh') do
     169  assert_float(0, Math.sinh(0))
     170  assert_float((Math::E ** 1 - Math::E ** -1) / 2, Math.sinh(1))
     171  assert_float((Math::E ** 2 - Math::E ** -2) / 2, Math.sinh(2))
     172end
     173
     174assert('Math.tanh') do
     175  assert_float(Math.sinh(0) / Math.cosh(0), Math.tanh(0))
     176  assert_float(Math.sinh(1) / Math.cosh(1), Math.tanh(1))
     177  assert_float(Math.sinh(2) / Math.cosh(2), Math.tanh(2))
     178  assert_float(+1.0, Math.tanh(+1000.0))
     179  assert_float(-1.0, Math.tanh(-1000.0))
     180end
     181
     182assert('Math.acosh') do
     183  assert_float(0, Math.acosh(1))
     184  assert_float(1, Math.acosh((Math::E ** 1 + Math::E ** -1) / 2))
     185  assert_float(2, Math.acosh((Math::E ** 2 + Math::E ** -2) / 2))
     186  assert_raise(Math::DomainError) { Math.acosh(0.9) }
     187  assert_raise(Math::DomainError) { Math.acosh(0) }
     188end
     189
     190assert('Math.asinh') do
     191  assert_float(0, Math.asinh(0))
     192  assert_float(1, Math.asinh((Math::E ** 1 - Math::E ** -1) / 2))
     193  assert_float(2, Math.asinh((Math::E ** 2 - Math::E ** -2) / 2))
     194end
     195
     196assert('Math.atanh') do
     197  assert_float(0, Math.atanh(Math.sinh(0) / Math.cosh(0)))
     198  assert_float(1, Math.atanh(Math.sinh(1) / Math.cosh(1)))
     199  assert_float(2, Math.atanh(Math.sinh(2) / Math.cosh(2)))
     200  assert_float(Float::INFINITY, Math.atanh(1))
     201  assert_float(-Float::INFINITY, Math.atanh(-1))
     202  assert_raise(Math::DomainError) { Math.atanh(+1.1) }
     203  assert_raise(Math::DomainError) { Math.atanh(-1.1) }
     204end
     205
     206assert('Math.atan2') do
     207  assert_float(+0.0, Math.atan2(+0.0, +0.0))
     208  assert_float(-0.0, Math.atan2(-0.0, +0.0))
     209  assert_float(+Math::PI, Math.atan2(+0.0, -0.0))
     210  assert_float(-Math::PI, Math.atan2(-0.0, -0.0))
     211
     212  inf = Float::INFINITY
     213  expected = 3.0 * Math::PI / 4.0
     214  assert_float(+expected, Math.atan2(+inf, -inf))
     215  assert_float(-expected, Math.atan2(-inf, -inf))
     216  expected = Math::PI / 4.0
     217  assert_float(+expected, Math.atan2(+inf, +inf))
     218  assert_float(-expected, Math.atan2(-inf, +inf))
     219
     220  assert_float(0, Math.atan2(0, 1))
     221  assert_float(Math::PI / 4, Math.atan2(1, 1))
     222  assert_float(Math::PI / 2, Math.atan2(1, 0))
     223end
     224
     225assert('Math.ldexp') do
     226  assert_float(0.0, Math.ldexp(0.0, 0.0))
     227  assert_float(0.5, Math.ldexp(0.5, 0.0))
     228  assert_float(1.0, Math.ldexp(0.5, 1.0))
     229  assert_float(2.0, Math.ldexp(0.5, 2.0))
     230  assert_float(3.0, Math.ldexp(0.75, 2.0))
     231end
     232
     233assert('Math.frexp') do
     234  assert_float_and_int([0.0,  0], Math.frexp(0.0))
     235  assert_float_and_int([0.5,  0], Math.frexp(0.5))
     236  assert_float_and_int([0.5,  1], Math.frexp(1.0))
     237  assert_float_and_int([0.5,  2], Math.frexp(2.0))
     238  assert_float_and_int([0.75, 2], Math.frexp(3.0))
     239end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb

    r331 r439  
    1 module Integral
    2   def div(other)
    3     self.divmod(other)[0]
    4   end
    5 
     1class Numeric
    62  def zero?
    73    self == 0
     
    1511    end
    1612  end
     13
     14  def positive?
     15    self > 0
     16  end
     17
     18  def negative?
     19    self < 0
     20  end
    1721end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-numeric-ext/src/numeric_ext.c

    r331 r439  
    11#include <limits.h>
    22#include <mruby.h>
     3#include <mruby/numeric.h>
    34
     5/*
     6 *  call-seq:
     7 *     int.allbits?(mask)  ->  true or false
     8 *
     9 *  Returns +true+ if all bits of <code>+int+ & +mask+</code> are 1.
     10 */
    411static mrb_value
    5 mrb_int_chr(mrb_state *mrb, mrb_value x)
     12mrb_int_allbits(mrb_state *mrb, mrb_value self)
    613{
    7   mrb_int chr;
    8   char c;
     14  mrb_int n, m;
    915
    10   chr = mrb_fixnum(x);
    11   if (chr >= (1 << CHAR_BIT)) {
    12     mrb_raisef(mrb, E_RANGE_ERROR, "%S out of char range", x);
    13   }
    14   c = (char)chr;
     16  mrb_get_args(mrb, "i", &m);
     17  n = mrb_int(mrb, self);
     18  return mrb_bool_value((n & m) == m);
     19}
    1520
    16   return mrb_str_new(mrb, &c, 1);
     21/*
     22 *  call-seq:
     23 *     int.anybits?(mask)  ->  true or false
     24 *
     25 *  Returns +true+ if any bits of <code>+int+ & +mask+</code> are 1.
     26 */
     27static mrb_value
     28mrb_int_anybits(mrb_state *mrb, mrb_value self)
     29{
     30  mrb_int n, m;
     31
     32  mrb_get_args(mrb, "i", &m);
     33  n = mrb_int(mrb, self);
     34  return mrb_bool_value((n & m) != 0);
     35}
     36
     37/*
     38 *  call-seq:
     39 *     int.nobits?(mask)  ->  true or false
     40 *
     41 *  Returns +true+ if no bits of <code>+int+ & +mask+</code> are 1.
     42 */
     43static mrb_value
     44mrb_int_nobits(mrb_state *mrb, mrb_value self)
     45{
     46  mrb_int n, m;
     47
     48  mrb_get_args(mrb, "i", &m);
     49  n = mrb_int(mrb, self);
     50  return mrb_bool_value((n & m) == 0);
    1751}
    1852
     
    2054mrb_mruby_numeric_ext_gem_init(mrb_state* mrb)
    2155{
    22   struct RClass *i = mrb_class_get(mrb, "Integer");
     56  struct RClass *i = mrb_module_get(mrb, "Integral");
    2357
    24   mrb_define_method(mrb, i, "chr", mrb_int_chr, MRB_ARGS_NONE());
     58  mrb_define_method(mrb, i, "allbits?", mrb_int_allbits, MRB_ARGS_REQ(1));
     59  mrb_define_method(mrb, i, "anybits?", mrb_int_anybits, MRB_ARGS_REQ(1));
     60  mrb_define_method(mrb, i, "nobits?", mrb_int_nobits, MRB_ARGS_REQ(1));
     61
     62#ifndef MRB_WITHOUT_FLOAT
     63  mrb_define_const(mrb, mrb->float_class, "RADIX",        mrb_fixnum_value(MRB_FLT_RADIX));
     64  mrb_define_const(mrb, mrb->float_class, "MANT_DIG",     mrb_fixnum_value(MRB_FLT_MANT_DIG));
     65  mrb_define_const(mrb, mrb->float_class, "EPSILON",      mrb_float_value(mrb, MRB_FLT_EPSILON));
     66  mrb_define_const(mrb, mrb->float_class, "DIG",          mrb_fixnum_value(MRB_FLT_DIG));
     67  mrb_define_const(mrb, mrb->float_class, "MIN_EXP",      mrb_fixnum_value(MRB_FLT_MIN_EXP));
     68  mrb_define_const(mrb, mrb->float_class, "MIN",          mrb_float_value(mrb, MRB_FLT_MIN));
     69  mrb_define_const(mrb, mrb->float_class, "MIN_10_EXP",   mrb_fixnum_value(MRB_FLT_MIN_10_EXP));
     70  mrb_define_const(mrb, mrb->float_class, "MAX_EXP",      mrb_fixnum_value(MRB_FLT_MAX_EXP));
     71  mrb_define_const(mrb, mrb->float_class, "MAX",          mrb_float_value(mrb, MRB_FLT_MAX));
     72  mrb_define_const(mrb, mrb->float_class, "MAX_10_EXP",   mrb_fixnum_value(MRB_FLT_MAX_10_EXP));
     73#endif /* MRB_WITHOUT_FLOAT */
    2574}
    2675
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-numeric-ext/test/numeric.rb

    r331 r439  
    11##
    22# Numeric(Ext) Test
    3 
    4 assert('Integer#chr') do
    5   assert_equal("A", 65.chr)
    6   assert_equal("B", 0x42.chr)
    7 
    8   # multibyte encoding (not support yet)
    9   assert_raise(RangeError) { 256.chr }
    10 end
    113
    124assert('Integer#div') do
     
    157
    168assert('Float#div') do
     9  skip unless Object.const_defined?(:Float)
    1710  assert_float 52, 365.2425.div(7)
    1811end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-object-ext/mrbgem.rake

    r321 r439  
    22  spec.license = 'MIT'
    33  spec.author  = 'mruby developers'
    4   spec.summary = 'Object class extension'
     4  spec.summary = 'extensional methods shared by all objects'
    55end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-object-ext/mrblib/object.rb

    r321 r439  
    1 class Object
     1module Kernel
     2  # call-seq:
     3  #   obj.yield_self {|_obj|...} -> an_object
     4  #   obj.then {|_obj|...}       -> an_object
     5  #
     6  # Yields <i>obj</i> and returns the result.
     7  #
     8  #   'my string'.yield_self {|s|s.upcase} #=> "MY STRING"
     9  #
     10  def yield_self(&block)
     11    return to_enum :yield_self unless block
     12    block.call(self)
     13  end
     14  alias then yield_self
     15
    216  ##
    317  #  call-seq:
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-object-ext/src/object.c

    r331 r439  
    22#include <mruby/array.h>
    33#include <mruby/class.h>
     4#include <mruby/hash.h>
    45#include <mruby/proc.h>
    56
     
    1718}
    1819
     20#ifndef MRB_WITHOUT_FLOAT
    1921/*
    2022 *  call-seq:
     
    2830{
    2931  return mrb_float_value(mrb, 0.0);
     32}
     33#endif
     34
     35/*
     36 *  call-seq:
     37 *     nil.to_h    -> {}
     38 *
     39 *  Always returns an empty hash.
     40 */
     41
     42static mrb_value
     43nil_to_h(mrb_state *mrb, mrb_value obj)
     44{
     45  return mrb_hash_new(mrb);
    3046}
    3147
     
    4157{
    4258  return mrb_fixnum_value(0);
     59}
     60
     61/*
     62 *  call-seq:
     63 *     obj.itself -> an_object
     64 *
     65 *  Returns <i>obj</i>.
     66 *
     67 *      string = 'my string' #=> "my string"
     68 *      string.itself.object_id == string.object_id #=> true
     69 *
     70 */
     71static mrb_value
     72mrb_f_itself(mrb_state *mrb, mrb_value self)
     73{
     74  return self;
    4375}
    4476
     
    68100  mrb_value blk;
    69101  struct RClass *c;
    70   mrb_value args;
    71102
    72   mrb_get_args(mrb, "*&", &argv, &argc, &blk);
    73 
    74   if (mrb_nil_p(blk)) {
    75     mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
    76   }
     103  mrb_get_args(mrb, "*&!", &argv, &argc, &blk);
    77104
    78105  switch (mrb_type(self)) {
    79106  case MRB_TT_SYMBOL:
    80107  case MRB_TT_FIXNUM:
     108#ifndef MRB_WITHOUT_FLOAT
    81109  case MRB_TT_FLOAT:
     110#endif
    82111    c = NULL;
    83112    break;
     
    86115    break;
    87116  }
    88   args = mrb_ary_new_from_values(mrb, argc, argv);
    89   argv = RARRAY_PTR(args);
    90117  mrb->c->ci->target_class = c;
    91118  return mrb_yield_cont(mrb, blk, self, argc, argv);
     
    98125
    99126  mrb_define_method(mrb, n, "to_a", nil_to_a,       MRB_ARGS_NONE());
     127#ifndef MRB_WITHOUT_FLOAT
    100128  mrb_define_method(mrb, n, "to_f", nil_to_f,       MRB_ARGS_NONE());
     129#endif
     130  mrb_define_method(mrb, n, "to_h", nil_to_h,       MRB_ARGS_NONE());
    101131  mrb_define_method(mrb, n, "to_i", nil_to_i,       MRB_ARGS_NONE());
    102132
    103   mrb_define_method(mrb, mrb->kernel_module, "instance_exec", mrb_obj_instance_exec, MRB_ARGS_ANY() | MRB_ARGS_BLOCK());
     133  mrb_define_method(mrb, mrb->kernel_module, "itself", mrb_f_itself, MRB_ARGS_NONE());
     134
     135  mrb_define_method(mrb, mrb_class_get(mrb, "BasicObject"), "instance_exec", mrb_obj_instance_exec, MRB_ARGS_ANY() | MRB_ARGS_BLOCK());
    104136}
    105137
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-object-ext/test/nil.rb

    r321 r439  
    44
    55assert('NilClass#to_f') do
     6  skip unless Object.const_defined?(:Float)
    67  assert_equal 0.0, nil.to_f
     8end
     9
     10assert('NilClass#to_h') do
     11  assert_equal Hash.new, nil.to_h
    712end
    813
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-objectspace/src/mruby_objectspace.c

    r331 r439  
    5858  }
    5959
    60   if (!mrb_test(mrb_hash_empty_p(mrb, hash))) {
     60  if (!mrb_hash_empty_p(mrb, hash)) {
    6161    mrb_hash_clear(mrb, hash);
    6262  }
     
    162162  mrb_value cls = mrb_nil_value();
    163163  struct os_each_object_data d;
    164   mrb_get_args(mrb, "&|C", &d.block, &cls);
    165 
    166   if (mrb_nil_p(d.block)) {
    167     mrb_raise(mrb, E_ARGUMENT_ERROR, "Expected block in ObjectSpace.each_object.");
    168   }
     164  mrb_get_args(mrb, "&!|C", &d.block, &cls);
    169165
    170166  d.target_module = mrb_nil_p(cls) ? NULL : mrb_class_ptr(cls);
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-objectspace/test/objectspace.rb

    r321 r439  
    11assert('ObjectSpace.count_objects') do
    22  h = {}
    3   f = Fiber.new {} if Object.const_defined? :Fiber
     3  f = Fiber.new {} if Object.const_defined?(:Fiber)
    44  ObjectSpace.count_objects(h)
    55  assert_kind_of(Hash, h)
     
    3232    objs << {}
    3333  end
     34  ObjectSpace.count_objects(h)
    3435  objs = nil
    35   ObjectSpace.count_objects(h)
    3636  GC.start
    3737  ObjectSpace.count_objects(h_after)
     
    5757
    5858assert 'Check class pointer of ObjectSpace.each_object.' do
    59   ObjectSpace.each_object { |obj| !obj }
     59  assert_nothing_raised { ObjectSpace.each_object { |obj| !obj } }
    6060end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-print/mrblib/print.rb

    r321 r439  
    4646      i += 1
    4747    end
    48     args[0]
     48    args.__svalue
    4949  end
    5050
    51   unless Kernel.respond_to?(:sprintf)
    52     def printf(*args)
    53       raise NotImplementedError.new('printf not available')
    54     end
    55     def sprintf(*args)
    56       raise NotImplementedError.new('sprintf not available')
    57     end
    58   else
    59     def printf(*args)
    60       __printstr__(sprintf(*args))
    61       nil
    62     end
     51  def printf(*args)
     52    __printstr__(sprintf(*args))
     53    nil
    6354  end
    6455end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-print/src/print.c

    r331 r439  
    11#include <mruby.h>
     2
     3#ifdef MRB_DISABLE_STDIO
     4# error print conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
     5#endif
     6
    27#include <mruby/string.h>
    3 #include <stdio.h>
    48#include <string.h>
    59#include <stdlib.h>
     
    2024    if (isatty(fileno(stdout))) {
    2125      DWORD written;
    22       int mlen = RSTRING_LEN(obj);
     26      int mlen = (int)RSTRING_LEN(obj);
    2327      char* utf8 = RSTRING_PTR(obj);
    2428      int wlen = MultiByteToWideChar(CP_UTF8, 0, utf8, mlen, NULL, 0);
    2529      wchar_t* utf16 = (wchar_t*)mrb_malloc(mrb, (wlen+1) * sizeof(wchar_t));
    26       if (utf16 == NULL) return;
    2730      if (MultiByteToWideChar(CP_UTF8, 0, utf8, mlen, utf16, wlen) > 0) {
    2831        utf16[wlen] = 0;
     
    3437#endif
    3538      fwrite(RSTRING_PTR(obj), RSTRING_LEN(obj), 1, stdout);
     39    fflush(stdout);
    3640  }
    3741}
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-proc-ext/mrblib/proc.rb

    r321 r439  
    2828    pproc = self
    2929    make_curry = proc do |given_args=[]|
    30       send(type) do |*args|
     30      __send__(type) do |*args|
    3131        new_args = given_args + args
    3232        if new_args.size >= arity
     
    4040  end
    4141
     42  def <<(other)
     43    ->(*args, &block) { call(other.call(*args, &block)) }
     44  end
     45
     46  def >>(other)
     47    ->(*args, &block) { other.call(call(*args, &block)) }
     48  end
     49
    4250end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-proc-ext/src/proc.c

    r331 r439  
    2626    const char *filename;
    2727
    28     filename = mrb_debug_get_filename(irep, 0);
    29     line = mrb_debug_get_line(irep, 0);
     28    filename = mrb_debug_get_filename(mrb, irep, 0);
     29    line = mrb_debug_get_line(mrb, irep, 0);
    3030
    3131    return (!filename && line == -1)? mrb_nil_value()
     
    3939  struct RProc *p = mrb_proc_ptr(self);
    4040  mrb_value str = mrb_str_new_lit(mrb, "#<Proc:");
    41   mrb_str_concat(mrb, str, mrb_ptr_to_str(mrb, mrb_cptr(self)));
     41  mrb_str_cat_str(mrb, str, mrb_ptr_to_str(mrb, mrb_cptr(self)));
    4242
    4343  if (!MRB_PROC_CFUNC_P(p)) {
     
    4747    mrb_str_cat_lit(mrb, str, "@");
    4848
    49     filename = mrb_debug_get_filename(irep, 0);
     49    filename = mrb_debug_get_filename(mrb, irep, 0);
    5050    mrb_str_cat_cstr(mrb, str, filename ? filename : "-");
    5151    mrb_str_cat_lit(mrb, str, ":");
    5252
    53     line = mrb_debug_get_line(irep, 0);
     53    line = mrb_debug_get_line(mrb, irep, 0);
    5454    if (line != -1) {
    55       str = mrb_format(mrb, "%S:%S", str, mrb_fixnum_value(line));
     55      mrb_str_concat(mrb, str, mrb_fixnum_value(line));
    5656    }
    5757    else {
     
    7373  mrb_value blk;
    7474
    75   mrb_get_args(mrb, "&", &blk);
    76   if (mrb_nil_p(blk)) {
    77     mrb_raise(mrb, E_ARGUMENT_ERROR, "tried to create Proc object without a block");
    78   }
     75  mrb_get_args(mrb, "&!", &blk);
    7976
    8077  return blk;
     
    9592{
    9693  struct parameters_type {
     94    size_t len;
     95    const char *name;
    9796    int size;
    98     const char *name;
    9997  } *p, parameters_list [] = {
    100     {0, "req"},
    101     {0, "opt"},
    102     {0, "rest"},
    103     {0, "req"},
    104     {0, "block"},
    105     {0, NULL}
     98    {sizeof("req")   - 1, "req",   0},
     99    {sizeof("opt")   - 1, "opt",   0},
     100    {sizeof("rest")  - 1, "rest",  0},
     101    {sizeof("req")   - 1, "req",   0},
     102    {sizeof("block") - 1, "block", 0},
     103    {0, NULL, 0}
    106104  };
    107105  const struct RProc *proc = mrb_proc_ptr(self);
    108106  const struct mrb_irep *irep = proc->body.irep;
    109107  mrb_aspec aspec;
    110   mrb_value sname, parameters;
     108  mrb_value parameters;
    111109  int i, j;
     110  int max = -1;
    112111
    113112  if (MRB_PROC_CFUNC_P(proc)) {
     
    121120    return mrb_ary_new(mrb);
    122121  }
    123   if (GET_OPCODE(*irep->iseq) != OP_ENTER) {
     122  if (*irep->iseq != OP_ENTER) {
    124123    return mrb_ary_new(mrb);
    125124  }
    126125
    127126  if (!MRB_PROC_STRICT_P(proc)) {
     127    parameters_list[0].len = sizeof("opt") - 1;
    128128    parameters_list[0].name = "opt";
     129    parameters_list[3].len = sizeof("opt") - 1;
    129130    parameters_list[3].name = "opt";
    130131  }
    131132
    132   aspec = GETARG_Ax(*irep->iseq);
     133  aspec = PEEK_W(irep->iseq+1);
    133134  parameters_list[0].size = MRB_ASPEC_REQ(aspec);
    134135  parameters_list[1].size = MRB_ASPEC_OPT(aspec);
     
    139140  parameters = mrb_ary_new_capa(mrb, irep->nlocals-1);
    140141
     142  max = irep->nlocals-1;
    141143  for (i = 0, p = parameters_list; p->name; p++) {
    142     if (p->size <= 0) continue;
    143     sname = mrb_symbol_value(mrb_intern_cstr(mrb, p->name));
     144    mrb_value sname = mrb_symbol_value(mrb_intern_static(mrb, p->name, p->len));
     145
    144146    for (j = 0; j < p->size; i++, j++) {
    145       mrb_value a = mrb_ary_new(mrb);
     147      mrb_value a;
     148
     149      a = mrb_ary_new(mrb);
    146150      mrb_ary_push(mrb, a, sname);
    147       if (irep->lv[i].name) {
    148         mrb_ary_push(mrb, a, mrb_symbol_value(irep->lv[i].name));
     151      if (i < max && irep->lv[i].name) {
     152        mrb_sym sym = irep->lv[i].name;
     153        const char *name = mrb_sym_name(mrb, sym);
     154        switch (name[0]) {
     155        case '*': case '&':
     156          break;
     157        default:
     158          mrb_ary_push(mrb, a, mrb_symbol_value(sym));
     159          break;
     160        }
    149161      }
    150162      mrb_ary_push(mrb, parameters, a);
     
    164176  mrb_define_method(mrb, p, "parameters",      mrb_proc_parameters,      MRB_ARGS_NONE());
    165177
    166   mrb_define_class_method(mrb, mrb->kernel_module, "proc", mrb_kernel_proc, MRB_ARGS_NONE());
    167   mrb_define_method(mrb, mrb->kernel_module,       "proc", mrb_kernel_proc, MRB_ARGS_NONE());
     178  mrb_define_class_method(mrb, mrb->kernel_module, "proc", mrb_kernel_proc, MRB_ARGS_NONE()|MRB_ARGS_BLOCK());
     179  mrb_define_method(mrb, mrb->kernel_module,       "proc", mrb_kernel_proc, MRB_ARGS_NONE()|MRB_ARGS_BLOCK());
    168180}
    169181
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-proc-ext/test/proc.c

    r331 r439  
    1414  mrb_sym n;
    1515  mrb_value n_val;
     16  mrb_method_t m;
     17  struct RProc *p;
    1618  mrb_get_args(mrb, "n", &n);
    1719  n_val = mrb_symbol_value(n);
    18   mrb_define_method_raw(mrb, mrb_class_ptr(self), n,
    19                         mrb_proc_new_cfunc_with_env(mrb, return_func_name, 1, &n_val));
     20  p = mrb_proc_new_cfunc_with_env(mrb, return_func_name, 1, &n_val);
     21  MRB_METHOD_FROM_PROC(m, p);
     22  mrb_define_method_raw(mrb, mrb_class_ptr(self), n, m);
    2023  return self;
    2124}
     
    3437  mrb_sym n;
    3538  mrb_value *argv; mrb_int argc;
     39  mrb_method_t m;
     40  struct RProc *p;
    3641  mrb_get_args(mrb, "na", &n, &argv, &argc);
    37   mrb_define_method_raw(mrb, mrb_class_ptr(self), n,
    38                         mrb_proc_new_cfunc_with_env(mrb, return_env, argc, argv));
     42  p = mrb_proc_new_cfunc_with_env(mrb, return_env, argc, argv);
     43  MRB_METHOD_FROM_PROC(m, p);
     44  mrb_define_method_raw(mrb, mrb_class_ptr(self), n, m);
    3945  return self;
    4046}
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-proc-ext/test/proc.rb

    r331 r439  
    22# Proc(Ext) Test
    33
     4def enable_debug_info?
     5  return @enable_debug_info unless @enable_debug_info == nil
     6  begin
     7    raise
     8  rescue => e
     9    @enable_debug_info = !e.backtrace.empty?
     10  end
     11end
     12
    413assert('Proc#source_location') do
    5   loc = Proc.new {}.source_location
    6   next true if loc.nil?
    7   assert_equal loc[0][-7, 7], 'proc.rb'
    8   assert_equal loc[1], 5
     14  skip unless enable_debug_info?
     15  file, line = Proc.new{}.source_location
     16  assert_equal __FILE__, file
     17  assert_equal __LINE__ - 2, line
    918end
    1019
    1120assert('Proc#inspect') do
    1221  ins = Proc.new{}.inspect
    13   assert_kind_of String, ins
     22  if enable_debug_info?
     23    metas = %w(\\ * ? [ ] { })
     24    file = __FILE__.split("").map{|c| metas.include?(c) ? "\\#{c}" : c}.join
     25    line = __LINE__ - 4
     26  else
     27    file = line = "-"
     28  end
     29  assert_match "#<Proc:0x*@#{file}:#{line}>", ins
     30end
     31
     32assert('Proc#parameters') do
     33  parameters = Proc.new{|x,y=42,*other|}.parameters
     34  assert_equal [[:opt, :x], [:opt, :y], [:rest, :other]], parameters
    1435end
    1536
     
    6788assert('Kernel#proc') do
    6889  assert_true !proc{|a|}.lambda?
     90
     91  assert_raise LocalJumpError do
     92    proc{ break }.call
     93  end
     94end
     95
     96assert "Proc#<< and Proc#>>" do
     97  add3 = ->(n) { n + 3 }
     98  mul2 = ->(n) { n * 2 }
     99
     100  f1 = mul2 << add3
     101  assert_kind_of Proc, f1
     102  assert_equal 16, f1.call(5)
     103
     104  f2 = mul2 >> add3
     105  assert_kind_of Proc, f2
     106  assert_equal 13, f2.call(5)
    69107end
    70108
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-random/src/random.c

    r331 r439  
    1010#include <mruby/data.h>
    1111#include <mruby/array.h>
    12 #include "mt19937ar.h"
     12#include <mruby/istruct.h>
     13#if INT32_MAX <= INTPTR_MAX
     14# define XORSHIFT96
     15# define NSEEDS 3
     16#else
     17# define NSEEDS 4
     18#endif
     19#define LASTSEED (NSEEDS-1)
    1320
    1421#include <time.h>
    1522
    16 static char const MT_STATE_KEY[] = "$mrb_i_mt_state";
    17 
    18 static const struct mrb_data_type mt_state_type = {
    19   MT_STATE_KEY, mrb_free,
    20 };
    21 
    22 static mrb_value mrb_random_rand(mrb_state *mrb, mrb_value self);
    23 static mrb_value mrb_random_srand(mrb_state *mrb, mrb_value self);
     23typedef struct rand_state {
     24  uint32_t seed[NSEEDS];
     25} rand_state;
    2426
    2527static void
    26 mt_srand(mt_state *t, unsigned long seed)
    27 {
    28   mrb_random_init_genrand(t, seed);
    29 }
    30 
    31 static unsigned long
    32 mt_rand(mt_state *t)
    33 {
    34   return mrb_random_genrand_int32(t);
    35 }
    36 
     28rand_init(rand_state *t)
     29{
     30  t->seed[0] = 123456789;
     31  t->seed[1] = 362436069;
     32  t->seed[2] = 521288629;
     33#ifndef XORSHIFT96
     34  t->seed[3] = 88675123;
     35#endif
     36}
     37
     38static uint32_t
     39rand_seed(rand_state *t, uint32_t seed)
     40{
     41  uint32_t old_seed = t->seed[LASTSEED];
     42  rand_init(t);
     43  t->seed[LASTSEED] = seed;
     44  return old_seed;
     45}
     46
     47#ifdef XORSHIFT96
     48static uint32_t
     49rand_uint32(rand_state *state)
     50{
     51  uint32_t *seed = state->seed;
     52  uint32_t x = seed[0];
     53  uint32_t y = seed[1];
     54  uint32_t z = seed[2];
     55  uint32_t t;
     56
     57  t = (x ^ (x << 3)) ^ (y ^ (y >> 19)) ^ (z ^ (z << 6));
     58  x = y; y = z; z = t;
     59  seed[0] = x;
     60  seed[1] = y;
     61  seed[2] = z;
     62
     63  return z;
     64}
     65#else  /* XORSHIFT96 */
     66static uint32_t
     67rand_uint32(rand_state *state)
     68{
     69  uint32_t *seed = state->seed;
     70  uint32_t x = seed[0];
     71  uint32_t y = seed[1];
     72  uint32_t z = seed[2];
     73  uint32_t w = seed[3];
     74  uint32_t t;
     75
     76  t = x ^ (x << 11);
     77  x = y; y = z; z = w;
     78  w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
     79  seed[0] = x;
     80  seed[1] = y;
     81  seed[2] = z;
     82  seed[3] = w;
     83
     84  return w;
     85}
     86#endif  /* XORSHIFT96 */
     87
     88#ifndef MRB_WITHOUT_FLOAT
    3789static double
    38 mt_rand_real(mt_state *t)
    39 {
    40   return mrb_random_genrand_real1(t);
    41 }
    42 
    43 static mrb_value
    44 mrb_random_mt_srand(mrb_state *mrb, mt_state *t, mrb_value seed)
    45 {
    46   if (mrb_nil_p(seed)) {
    47     seed = mrb_fixnum_value((mrb_int)(time(NULL) + mt_rand(t)));
    48     if (mrb_fixnum(seed) < 0) {
    49       seed = mrb_fixnum_value(0 - mrb_fixnum(seed));
    50     }
    51   }
    52 
    53   mt_srand(t, (unsigned) mrb_fixnum(seed));
    54 
    55   return seed;
    56 }
    57 
    58 static mrb_value
    59 mrb_random_mt_rand(mrb_state *mrb, mt_state *t, mrb_value max)
     90rand_real(rand_state *t)
     91{
     92  uint32_t x = rand_uint32(t);
     93  return x*(1.0/4294967295.0);
     94}
     95#endif
     96
     97static mrb_value
     98random_rand(mrb_state *mrb, rand_state *t, mrb_value max)
    6099{
    61100  mrb_value value;
    62101
    63102  if (mrb_fixnum(max) == 0) {
    64     value = mrb_float_value(mrb, mt_rand_real(t));
    65   }
    66   else {
    67     value = mrb_fixnum_value(mt_rand(t) % mrb_fixnum(max));
     103#ifndef MRB_WITHOUT_FLOAT
     104    value = mrb_float_value(mrb, rand_real(t));
     105#else
     106    mrb_raise(mrb, E_ARGUMENT_ERROR, "Float not supported");
     107#endif
     108  }
     109  else {
     110    value = mrb_fixnum_value(rand_uint32(t) % mrb_fixnum(max));
    68111  }
    69112
     
    80123
    81124  if (!mrb_nil_p(arg)) {
    82     arg = mrb_check_convert_type(mrb, arg, MRB_TT_FIXNUM, "Fixnum", "to_int");
    83     if (mrb_nil_p(arg)) {
    84       mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument type");
    85     }
    86     if (mrb_fixnum(arg) < 0) {
    87       arg = mrb_fixnum_value(0 - mrb_fixnum(arg));
     125    mrb_int i;
     126
     127    arg = mrb_to_int(mrb, arg);
     128    i = mrb_fixnum(arg);
     129    if (i < 0) {
     130      arg = mrb_fixnum_value(0 - i);
    88131    }
    89132  }
     
    91134}
    92135
    93 static mrb_value
    94 get_random(mrb_state *mrb) {
    95   return mrb_const_get(mrb,
    96              mrb_obj_value(mrb_class_get(mrb, "Random")),
    97              mrb_intern_lit(mrb, "DEFAULT"));
    98 }
    99 
    100 static mt_state *
    101 get_random_state(mrb_state *mrb)
    102 {
    103   mrb_value random_val = get_random(mrb);
    104   return DATA_GET_PTR(mrb, random_val, &mt_state_type, mt_state);
    105 }
    106 
    107 static mrb_value
    108 mrb_random_g_rand(mrb_state *mrb, mrb_value self)
    109 {
    110   mrb_value random = get_random(mrb);
    111   return mrb_random_rand(mrb, random);
    112 }
    113 
    114 static mrb_value
    115 mrb_random_g_srand(mrb_state *mrb, mrb_value self)
    116 {
    117   mrb_value random = get_random(mrb);
    118   return mrb_random_srand(mrb, random);
    119 }
    120 
    121 static mrb_value
    122 mrb_random_init(mrb_state *mrb, mrb_value self)
     136static void
     137random_check(mrb_state *mrb, mrb_value random) {
     138  struct RClass *c = mrb_class_get(mrb, "Random");
     139  if (!mrb_obj_is_kind_of(mrb, random, c) || !mrb_istruct_p(random)) {
     140    mrb_raise(mrb, E_TYPE_ERROR, "Random instance required");
     141  }
     142}
     143
     144static mrb_value
     145random_default(mrb_state *mrb) {
     146  struct RClass *c = mrb_class_get(mrb, "Random");
     147  mrb_value d = mrb_const_get(mrb, mrb_obj_value(c), mrb_intern_lit(mrb, "DEFAULT"));
     148  if (!mrb_obj_is_kind_of(mrb, d, c)) {
     149    mrb_raise(mrb, E_TYPE_ERROR, "Random::DEFAULT replaced");
     150  }
     151  return d;
     152}
     153
     154#define random_ptr(v) (rand_state*)mrb_istruct_ptr(v)
     155#define random_default_state(mrb) random_ptr(random_default(mrb))
     156
     157static mrb_value
     158random_m_init(mrb_state *mrb, mrb_value self)
    123159{
    124160  mrb_value seed;
    125   mt_state *t;
     161  rand_state *t;
    126162
    127163  seed = get_opt(mrb);
    128 
    129164  /* avoid memory leaks */
    130   t = (mt_state*)DATA_PTR(self);
    131   if (t) {
    132     mrb_free(mrb, t);
    133   }
    134   mrb_data_init(self, NULL, &mt_state_type);
    135 
    136   t = (mt_state *)mrb_malloc(mrb, sizeof(mt_state));
    137   t->mti = N + 1;
    138 
    139   seed = mrb_random_mt_srand(mrb, t, seed);
     165  t = random_ptr(self);
    140166  if (mrb_nil_p(seed)) {
    141     t->has_seed = FALSE;
    142   }
    143   else {
    144     mrb_assert(mrb_fixnum_p(seed));
    145     t->has_seed = TRUE;
    146     t->seed = mrb_fixnum(seed);
    147   }
    148 
    149   mrb_data_init(self, t, &mt_state_type);
     167    rand_init(t);
     168  }
     169  else {
     170    rand_seed(t, (uint32_t)mrb_fixnum(seed));
     171  }
    150172
    151173  return self;
    152174}
    153175
    154 static void
    155 mrb_random_rand_seed(mrb_state *mrb, mt_state *t)
    156 {
    157   if (!t->has_seed) {
    158     mrb_random_mt_srand(mrb, t, mrb_nil_value());
    159   }
    160 }
    161 
    162 static mrb_value
    163 mrb_random_rand(mrb_state *mrb, mrb_value self)
     176static mrb_value
     177random_m_rand(mrb_state *mrb, mrb_value self)
    164178{
    165179  mrb_value max;
    166   mt_state *t = DATA_GET_PTR(mrb, self, &mt_state_type, mt_state);
     180  rand_state *t = random_ptr(self);
    167181
    168182  max = get_opt(mrb);
    169   mrb_random_rand_seed(mrb, t);
    170   return mrb_random_mt_rand(mrb, t, max);
    171 }
    172 
    173 static mrb_value
    174 mrb_random_srand(mrb_state *mrb, mrb_value self)
    175 {
    176   mrb_value seed;
    177   mrb_value old_seed;
    178   mt_state *t = DATA_GET_PTR(mrb, self, &mt_state_type, mt_state);
    179 
    180   seed = get_opt(mrb);
    181   seed = mrb_random_mt_srand(mrb, t, seed);
    182   old_seed = t->has_seed? mrb_fixnum_value(t->seed) : mrb_nil_value();
    183   if (mrb_nil_p(seed)) {
    184     t->has_seed = FALSE;
    185   }
    186   else {
    187     mrb_assert(mrb_fixnum_p(seed));
    188     t->has_seed = TRUE;
    189     t->seed = mrb_fixnum(seed);
    190   }
    191 
    192   return old_seed;
     183  return random_rand(mrb, t, max);
     184}
     185
     186static mrb_value
     187random_m_srand(mrb_state *mrb, mrb_value self)
     188{
     189  uint32_t seed;
     190  uint32_t old_seed;
     191  mrb_value sv;
     192  rand_state *t = random_ptr(self);
     193
     194  sv = get_opt(mrb);
     195  if (mrb_nil_p(sv)) {
     196    seed = (uint32_t)time(NULL) + rand_uint32(t);
     197  }
     198  else {
     199    seed = (uint32_t)mrb_fixnum(sv);
     200  }
     201  old_seed = rand_seed(t, seed);
     202
     203  return mrb_fixnum_value((mrb_int)old_seed);
    193204}
    194205
     
    204215{
    205216  mrb_int i;
    206   mt_state *random = NULL;
     217  mrb_value max;
     218  mrb_value r = mrb_nil_value();
     219  rand_state *random;
    207220
    208221  if (RARRAY_LEN(ary) > 1) {
    209     mrb_get_args(mrb, "|d", &random, &mt_state_type);
    210 
    211     if (random == NULL) {
    212       random = get_random_state(mrb);
    213     }
    214     mrb_random_rand_seed(mrb, random);
    215 
     222    mrb_get_args(mrb, "|o", &r);
     223
     224    if (mrb_nil_p(r)) {
     225      random = random_default_state(mrb);
     226    }
     227    else {
     228      random_check(mrb, r);
     229      random = random_ptr(r);
     230    }
    216231    mrb_ary_modify(mrb, mrb_ary_ptr(ary));
    217 
     232    max = mrb_fixnum_value(RARRAY_LEN(ary));
    218233    for (i = RARRAY_LEN(ary) - 1; i > 0; i--)  {
    219234      mrb_int j;
     235      mrb_value *ptr = RARRAY_PTR(ary);
    220236      mrb_value tmp;
    221237
    222       j = mrb_fixnum(mrb_random_mt_rand(mrb, random, mrb_fixnum_value(RARRAY_LEN(ary))));
    223 
    224       tmp = RARRAY_PTR(ary)[i];
    225       mrb_ary_ptr(ary)->ptr[i] = RARRAY_PTR(ary)[j];
    226       mrb_ary_ptr(ary)->ptr[j] = tmp;
     238      j = mrb_fixnum(random_rand(mrb, random, max));
     239
     240      tmp = ptr[i];
     241      ptr[i] = ptr[j];
     242      ptr[j] = tmp;
    227243    }
    228244  }
     
    267283  mrb_int n = 0;
    268284  mrb_bool given;
    269   mt_state *random = NULL;
     285  mrb_value r = mrb_nil_value();
     286  rand_state *random;
    270287  mrb_int len;
    271288
    272   mrb_get_args(mrb, "|i?d", &n, &given, &random, &mt_state_type);
    273   if (random == NULL) {
    274     random = get_random_state(mrb);
    275   }
    276   mrb_random_rand_seed(mrb, random);
    277   mt_rand(random);
     289  mrb_get_args(mrb, "|i?o", &n, &given, &r);
     290  if (mrb_nil_p(r)) {
     291    random = random_default_state(mrb);
     292  }
     293  else {
     294    random_check(mrb, r);
     295    random = random_ptr(r);
     296  }
    278297  len = RARRAY_LEN(ary);
    279298  if (!given) {                 /* pick one element */
     
    284303      return RARRAY_PTR(ary)[0];
    285304    default:
    286       return RARRAY_PTR(ary)[mt_rand(random) % len];
     305      return RARRAY_PTR(ary)[rand_uint32(random) % len];
    287306    }
    288307  }
     
    299318      for (;;) {
    300319      retry:
    301         r = mt_rand(random) % len;
     320        r = (mrb_int)(rand_uint32(random) % len);
    302321
    303322        for (j=0; j<i; j++) {
     
    317336}
    318337
     338static mrb_value
     339random_f_rand(mrb_state *mrb, mrb_value self)
     340{
     341  rand_state *t = random_default_state(mrb);
     342  return random_rand(mrb, t, get_opt(mrb));
     343}
     344
     345static mrb_value
     346random_f_srand(mrb_state *mrb, mrb_value self)
     347{
     348  mrb_value random = random_default(mrb);
     349  return random_m_srand(mrb, random);
     350}
     351
    319352
    320353void mrb_mruby_random_gem_init(mrb_state *mrb)
     
    323356  struct RClass *array = mrb->array_class;
    324357
    325   mrb_define_method(mrb, mrb->kernel_module, "rand", mrb_random_g_rand, MRB_ARGS_OPT(1));
    326   mrb_define_method(mrb, mrb->kernel_module, "srand", mrb_random_g_srand, MRB_ARGS_OPT(1));
     358  mrb_assert(sizeof(rand_state) <= ISTRUCT_DATA_SIZE);
     359
     360  mrb_define_method(mrb, mrb->kernel_module, "rand", random_f_rand, MRB_ARGS_OPT(1));
     361  mrb_define_method(mrb, mrb->kernel_module, "srand", random_f_srand, MRB_ARGS_OPT(1));
    327362
    328363  random = mrb_define_class(mrb, "Random", mrb->object_class);
    329   MRB_SET_INSTANCE_TT(random, MRB_TT_DATA);
    330   mrb_define_class_method(mrb, random, "rand", mrb_random_g_rand, MRB_ARGS_OPT(1));
    331   mrb_define_class_method(mrb, random, "srand", mrb_random_g_srand, MRB_ARGS_OPT(1));
    332 
    333   mrb_define_method(mrb, random, "initialize", mrb_random_init, MRB_ARGS_OPT(1));
    334   mrb_define_method(mrb, random, "rand", mrb_random_rand, MRB_ARGS_OPT(1));
    335   mrb_define_method(mrb, random, "srand", mrb_random_srand, MRB_ARGS_OPT(1));
     364  MRB_SET_INSTANCE_TT(random, MRB_TT_ISTRUCT);
     365  mrb_define_class_method(mrb, random, "rand", random_f_rand, MRB_ARGS_OPT(1));
     366  mrb_define_class_method(mrb, random, "srand", random_f_srand, MRB_ARGS_OPT(1));
     367
     368  mrb_define_method(mrb, random, "initialize", random_m_init, MRB_ARGS_OPT(1));
     369  mrb_define_method(mrb, random, "rand", random_m_rand, MRB_ARGS_OPT(1));
     370  mrb_define_method(mrb, random, "srand", random_m_srand, MRB_ARGS_OPT(1));
    336371
    337372  mrb_define_method(mrb, array, "shuffle", mrb_ary_shuffle, MRB_ARGS_OPT(1));
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-random/test/random.rb

    r331 r439  
    22# Random Test
    33
    4 assert("Random#srand") do
     4assert("Random.new") do
    55  r1 = Random.new(123)
    66  r2 = Random.new(123)
    7   r1.rand == r2.rand
     7  r3 = Random.new(124)
     8  assert_equal(r1.rand, r2.rand)
     9  assert_not_equal(r1.rand, r3.rand)
    810end
    911
    10 assert("Kernel::srand") do
     12assert("Kernel.srand") do
    1113  srand(234)
    1214  r1 = rand
    1315  srand(234)
    1416  r2 = rand
    15   r1 == r2
     17  srand(235)
     18  r3 = rand
     19  assert_equal(r1, r2)
     20  assert_not_equal(r1, r3)
    1621end
    1722
    18 assert("Random::srand") do
     23assert("Random.srand") do
    1924  Random.srand(345)
    2025  r1 = rand
    2126  srand(345)
    2227  r2 = Random.rand
    23   r1 == r2
     28  Random.srand(346)
     29  r3 = rand
     30  assert_equal(r1, r2)
     31  assert_not_equal(r1, r3)
    2432end
    2533
    26 assert("fixnum") do
    27   rand(3).class == Fixnum
    28 end
    29 
    30 assert("float") do
    31   rand.class == Float
     34assert("return class of Kernel.rand") do
     35  assert_kind_of(Fixnum, rand(3))
     36  assert_kind_of(Fixnum, rand(1.5))
     37  assert_kind_of(Float, rand)
     38  assert_kind_of(Float, rand(0.5))
    3239end
    3340
    3441assert("Array#shuffle") do
    35   ary = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
     42  orig = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
     43  ary = orig.dup
    3644  shuffled = ary.shuffle
    37 
    38   ary == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and shuffled != ary and 10.times { |x| ary.include? x }
     45  assert_equal(orig, ary)
     46  assert_not_equal(ary, shuffled)
     47  assert_equal(orig, shuffled.sort)
    3948end
    4049
    4150assert('Array#shuffle!') do
    42   ary = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    43   ary.shuffle!
    44 
    45   ary != [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and 10.times { |x| ary.include? x }
     51  orig = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
     52  ary = orig.dup
     53  assert_same(ary, ary.shuffle!)
     54  assert_not_equal(orig, ary)
     55  assert_equal(orig, ary.sort)
    4656end
    4757
     
    5363
    5464  # verify that the same seed causes the same results
    55   ary1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    56   shuffle1 = ary1.shuffle Random.new 345
    57   ary2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    58   shuffle2 = ary2.shuffle Random.new 345
    59 
    60   ary1 != shuffle1 and 10.times { |x| shuffle1.include? x } and shuffle1 == shuffle2
     65  ary = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
     66  shuffled1 = ary.shuffle Random.new 345
     67  shuffled2 = ary.shuffle Random.new 345
     68  shuffled3 = ary.shuffle Random.new 346
     69  assert_equal(shuffled1, shuffled2)
     70  assert_not_equal(shuffled1, shuffled3)
    6171end
    6272
     
    7282  ary2 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    7383  ary2.shuffle! Random.new 345
    74 
    75   ary1 != [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and 10.times { |x| ary1.include? x } and ary1 == ary2
     84  ary3 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
     85  ary3.shuffle! Random.new 346
     86  assert_equal(ary1, ary2)
     87  assert_not_equal(ary1, ary3)
    7688end
    7789
    78 assert('Array#sample checks input length after reading arguments') do
    79   $ary = [1, 2, 3]
    80   class ArrayChange
    81     def to_i
    82       $ary << 4
    83       4
     90assert('Array#sample') do
     91  100.times do
     92    assert_include([0, 1, 2], [2, 1, 0].sample)
     93    [2, 1, 0].sample(2).each { |sample| assert_include([0, 1, 2], sample) }
     94    h = {}
     95    (1..10).to_a.sample(7).each do |sample|
     96      assert_not_include(h, sample)
     97      h[sample] = true
    8498    end
    8599  end
    86100
    87   assert_equal [1, 2, 3, 4], $ary.sample(ArrayChange.new).sort
     101  assert_nil([].sample)
     102  assert_equal([], [].sample(1))
     103  assert_equal([], [2, 1].sample(0))
     104  assert_raise(TypeError) { [2, 1].sample(true) }
     105  assert_raise(ArgumentError) { [2, 1].sample(-1) }
    88106end
     107
     108assert('Array#sample(random)') do
     109  assert_raise(TypeError) do
     110    # this will cause an exception due to the wrong argument
     111    [1, 2].sample(2, "Not a Random instance")
     112  end
     113
     114  # verify that the same seed causes the same results
     115  ary = (1..10).to_a
     116  srand(15)
     117  samples1 = ary.sample(4)
     118  samples2 = ary.sample(4, Random.new(15))
     119  samples3 = ary.sample(4, Random.new(16))
     120  assert_equal(samples1, samples2)
     121  assert_not_equal(samples1, samples3)
     122end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-range-ext/mrblib/range.rb

    r331 r439  
    1616    raise ArgumentError, "wrong number of arguments (given #{args.length}, expected 1)" unless args.length == 1
    1717    nv = args[0]
    18     raise TypeError, "no implicit conversion from nil to integer" if nv.nil?
    19     raise TypeError, "no implicit conversion of #{nv.class} into Integer" unless nv.respond_to?(:to_int)
    20     n = nv.to_int
    21     raise TypeError, "no implicit conversion of #{nv.class} into Integer" unless n.kind_of?(Integer)
     18    n = nv.__to_int
    2219    raise ArgumentError, "negative array size (or size too big)" unless 0 <= n
    2320    ary = []
     
    2926    ary
    3027  end
     28
     29  def max(&block)
     30    val = self.first
     31    last = self.last
     32    return super if block
     33
     34    # fast path for numerics
     35    if val.kind_of?(Numeric) && last.kind_of?(Numeric)
     36      raise TypeError if exclude_end? && !last.kind_of?(Fixnum)
     37      return nil if val > last
     38      return nil if val == last && exclude_end?
     39
     40      max = last
     41      max -= 1 if exclude_end?
     42      return max
     43    end
     44
     45    # delegate to Enumerable
     46    super
     47  end
     48
     49  def min(&block)
     50    val = self.first
     51    last = self.last
     52    return super if block
     53
     54    # fast path for numerics
     55    if val.kind_of?(Numeric) && last.kind_of?(Numeric)
     56      return nil if val > last
     57      return nil if val == last && exclude_end?
     58
     59      min = val
     60      return min
     61    end
     62
     63    # delegate to Enumerable
     64    super
     65  end
    3166end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-range-ext/src/range.c

    r331 r439  
    22#include <mruby/range.h>
    33#include <math.h>
    4 #include <float.h>
    54
    65static mrb_bool
    76r_le(mrb_state *mrb, mrb_value a, mrb_value b)
    87{
    9   mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b); /* compare result */
    10   /* output :a < b => -1, a = b =>  0, a > b => +1 */
     8  mrb_int n = mrb_cmp(mrb, a, b);
    119
    12   if (mrb_fixnum_p(r)) {
    13     mrb_int c = mrb_fixnum(r);
    14     if (c == 0 || c == -1) return TRUE;
    15   }
    16 
     10  if (n == 0 || n == -1) return TRUE;
    1711  return FALSE;
    1812}
     
    2115r_lt(mrb_state *mrb, mrb_value a, mrb_value b)
    2216{
    23   mrb_value r = mrb_funcall(mrb, a, "<=>", 1, b);
    24   /* output :a < b => -1, a = b =>  0, a > b => +1 */
    25 
    26   return mrb_fixnum_p(r) && mrb_fixnum(r) == -1;
     17  return mrb_cmp(mrb, a, b) == -1;
    2718}
    2819
     
    4233 */
    4334static mrb_value
    44 mrb_range_cover(mrb_state *mrb, mrb_value range)
     35range_cover(mrb_state *mrb, mrb_value range)
    4536{
    4637  mrb_value val;
     
    5041  mrb_get_args(mrb, "o", &val);
    5142
    52   beg = r->edges->beg;
    53   end = r->edges->end;
     43  beg = RANGE_BEG(r);
     44  end = RANGE_END(r);
    5445
    5546  if (r_le(mrb, beg, val)) {
    56     if (r->excl) {
     47    if (RANGE_EXCL(r)) {
    5748      if (r_lt(mrb, val, end))
    5849        return mrb_true_value();
     
    8475 */
    8576static mrb_value
    86 mrb_range_last(mrb_state *mrb, mrb_value range)
     77range_last(mrb_state *mrb, mrb_value range)
    8778{
    8879  mrb_value num;
    8980  mrb_value array;
    90   struct RRange *r = mrb_range_ptr(mrb, range);
    9181
    9282  if (mrb_get_args(mrb, "|o", &num) == 0) {
    93     return r->edges->end;
     83    return mrb_range_end(mrb, range);
    9484  }
    9585
     
    10999 */
    110100
     101#ifndef MRB_WITHOUT_FLOAT
    111102static mrb_value
    112 mrb_range_size(mrb_state *mrb, mrb_value range)
     103range_size(mrb_state *mrb, mrb_value range)
    113104{
    114105  struct RRange *r = mrb_range_ptr(mrb, range);
     
    118109  mrb_bool excl;
    119110
    120   beg = r->edges->beg;
    121   end = r->edges->end;
    122   excl = r->excl;
     111  beg = RANGE_BEG(r);
     112  end = RANGE_END(r);
     113  excl = RANGE_EXCL(r);
    123114  if (mrb_fixnum_p(beg)) {
    124115    beg_f = (mrb_float)mrb_fixnum(beg);
     
    161152  return mrb_nil_value();
    162153}
     154#else
     155static mrb_value
     156range_size(mrb_state *mrb, mrb_value range)
     157{
     158  struct RRange *r = mrb_range_ptr(mrb, range);
     159  mrb_value beg, end;
     160  mrb_int excl;
     161
     162  beg = RANGE_BEG(r);
     163  end = RANGE_END(r);
     164  excl = RANGE_EXCL(r) ? 0 : 1;
     165
     166  if (mrb_fixnum_p(beg) && mrb_fixnum_p(end)) {
     167    mrb_int a = mrb_fixnum(beg);
     168    mrb_int b = mrb_fixnum(end);
     169    mrb_int c = b - a + excl;
     170
     171    return mrb_fixnum_value(c);
     172  }
     173  return mrb_nil_value();
     174}
     175#endif /* MRB_WITHOUT_FLOAT */
    163176
    164177void
     
    167180  struct RClass * s = mrb_class_get(mrb, "Range");
    168181
    169   mrb_define_method(mrb, s, "cover?", mrb_range_cover, MRB_ARGS_REQ(1));
    170   mrb_define_method(mrb, s, "last",   mrb_range_last,  MRB_ARGS_OPT(1));
    171   mrb_define_method(mrb, s, "size",   mrb_range_size,  MRB_ARGS_NONE());
     182  mrb_define_method(mrb, s, "cover?", range_cover, MRB_ARGS_REQ(1));
     183  mrb_define_method(mrb, s, "last",   range_last,  MRB_ARGS_OPT(1));
     184  mrb_define_method(mrb, s, "size",   range_size,  MRB_ARGS_NONE());
    172185}
    173186
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-range-ext/test/range.rb

    r331 r439  
    1111  assert_equal 10, (10..20).first
    1212  assert_equal [10, 11, 12], (10..20).first(3)
     13
     14  skip unless Object.const_defined?(:Float)
    1315  assert_equal [0, 1, 2], (0..Float::INFINITY).first(3)
    1416end
     
    2426  assert_equal 42, (1..42).size
    2527  assert_equal 41, (1...42).size
     28  assert_nil ('a'..'z').size
     29
     30  skip unless Object.const_defined?(:Float)
    2631  assert_equal 6, (1...6.3).size
    2732  assert_equal 5, (1...6.0).size
     
    2934  assert_equal 15, (1.0..15.9).size
    3035  assert_equal Float::INFINITY, (0..Float::INFINITY).size
    31   assert_nil ('a'..'z').size
    3236end
     37
     38assert('Range#max') do
     39  # returns the maximum value in the range when called with no arguments
     40  assert_equal 10, (1..10).max
     41  assert_equal 9, (1...10).max
     42  assert_equal 536870911, (0...2**29).max
     43
     44  # returns nil when the endpoint is less than the start point
     45  assert_equal nil, (100..10).max
     46
     47  # returns nil when the endpoint equals the start point and the range is exclusive
     48  assert_equal nil, (5...5).max
     49
     50  # returns the endpoint when the endpoint equals the start point and the range is inclusive
     51  assert_equal 5, (5..5).max
     52
     53  skip unless Object.const_defined?(:Float)
     54
     55  # returns the maximum value in the Float range when called with no arguments
     56  assert_equal 908.1111, (303.20..908.1111).max
     57
     58  # raises TypeError when called on an exclusive range and a non Integer value
     59  assert_raise(TypeError) { (303.20...908.1111).max }
     60
     61  # returns nil when the endpoint is less than the start point in a Float range
     62  assert_equal nil, (3003.20..908.1111).max
     63end
     64
     65assert('Range#max given a block') do
     66  # passes each pair of values in the range to the block
     67  acc = []
     68  (1..10).max do |a, b|
     69    acc << a
     70    acc << b
     71    a
     72  end
     73  (1..10).each do |value|
     74    assert_true acc.include?(value)
     75  end
     76
     77  # passes each pair of elements to the block in reversed order
     78  acc = []
     79  (1..5).max do |a, b|
     80    acc << [a, b]
     81    a
     82  end
     83  assert_equal [[2, 1], [3, 2], [4, 3], [5, 4]], acc
     84
     85  # returns the element the block determines to be the maximum
     86  assert_equal 1, ((1..3).max { |_a, _b| -3 })
     87
     88  # returns nil when the endpoint is less than the start point
     89  assert_equal nil, ((100..10).max { |x, y| x <=> y })
     90  assert_equal nil, ((5...5).max { |x, y| x <=> y })
     91end
     92
     93assert('Range#min') do
     94  # returns the minimum value in the range when called with no arguments
     95  assert_equal 1, (1..10).min
     96  assert_equal 1, (1...10).min
     97
     98  # returns nil when the start point is greater than the endpoint
     99  assert_equal nil, (100..10).min
     100
     101  # returns nil when the endpoint equals the start point and the range is exclusive
     102  assert_equal nil, (5...5).max
     103
     104  # returns the endpoint when the endpoint equals the start point and the range is inclusive
     105  assert_equal 5, (5..5).max
     106
     107  skip unless Object.const_defined?(:Float)
     108
     109  # returns the minimum value in the Float range when called with no arguments
     110  assert_equal 303.20, (303.20..908.1111).min
     111
     112  # returns nil when the start point is greater than the endpoint in a Float range
     113  assert_equal nil, (3003.20..908.1111).max
     114end
     115
     116assert('Range#min given a block') do
     117  # passes each pair of values in the range to the block
     118  acc = []
     119  (1..10).min do |a, b|
     120    acc << a
     121    acc << b
     122    a
     123  end
     124  (1..10).each do |value|
     125    assert_true acc.include?(value)
     126  end
     127
     128  # passes each pair of elements to the block in reversed order
     129  acc = []
     130  (1..5).min do |a, b|
     131    acc << [a, b]
     132    a
     133  end
     134  assert_equal [[2, 1], [3, 1], [4, 1], [5, 1]], acc
     135
     136  # returns the element the block determines to be the minimum
     137  assert_equal 3, ((1..3).min { |_a, _b| -3 })
     138
     139  # returns nil when the start point is greater than the endpoint
     140  assert_equal nil, ((100..10).min { |x, y| x <=> y })
     141  assert_equal nil, ((5...5).min { |x, y| x <=> y })
     142end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-sprintf/src/kernel.c

    r331 r439  
    1919  krn = mrb->kernel_module;
    2020
    21   mrb_define_method(mrb, krn, "sprintf", mrb_f_sprintf, MRB_ARGS_ANY());
    22   mrb_define_method(mrb, krn, "format",  mrb_f_sprintf, MRB_ARGS_ANY());
     21  mrb_define_method(mrb, krn, "sprintf", mrb_f_sprintf, MRB_ARGS_REQ(1)|MRB_ARGS_REST());
     22  mrb_define_method(mrb, krn, "format",  mrb_f_sprintf, MRB_ARGS_REQ(1)|MRB_ARGS_REST());
    2323}
    2424
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-sprintf/src/sprintf.c

    r331 r439  
    77#include <mruby.h>
    88
     9#ifdef MRB_DISABLE_STDIO
     10# error sprintf conflicts 'MRB_DISABLE_STDIO' configuration in your 'build_config.rb'
     11#endif
     12
    913#include <limits.h>
    10 #include <stdio.h>
    1114#include <string.h>
    1215#include <mruby/string.h>
    1316#include <mruby/hash.h>
    1417#include <mruby/numeric.h>
     18#ifndef MRB_WITHOUT_FLOAT
    1519#include <math.h>
     20#endif
    1621#include <ctype.h>
    1722
     
    2025#define EXTENDSIGN(n, l) (((~0U << (n)) >> (((n)*(l)) % BITSPERDIG)) & ~(~0U << (n)))
    2126
    22 mrb_value mrb_str_format(mrb_state *, int, const mrb_value *, mrb_value);
     27mrb_value mrb_str_format(mrb_state *, mrb_int, const mrb_value *, mrb_value);
     28#ifndef MRB_WITHOUT_FLOAT
    2329static void fmt_setup(char*,size_t,int,int,mrb_int,mrb_int);
     30#endif
    2431
    2532static char*
     
    7885
    7986  if (base != 2) {
    80     mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %S", mrb_fixnum_value(base));
     87    mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %d", base);
    8188  }
    8289  if (val == 0) {
     
    116123
    117124#define CHECK(l) do {\
    118 /*  int cr = ENC_CODERANGE(result);*/\
    119125  while ((l) >= bsiz - blen) {\
     126    if (bsiz > MRB_INT_MAX/2) mrb_raise(mrb, E_ARGUMENT_ERROR, "too big specifier"); \
    120127    bsiz*=2;\
    121     if (bsiz < 0) mrb_raise(mrb, E_ARGUMENT_ERROR, "too big specifier"); \
    122128  }\
    123129  mrb_str_resize(mrb, result, bsiz);\
    124 /*  ENC_CODERANGE_SET(result, cr);*/\
    125130  buf = RSTRING_PTR(result);\
    126131} while (0)
     
    129134  CHECK(l);\
    130135  memcpy(&buf[blen], s, l);\
    131   blen += (l);\
     136  blen += (mrb_int)(l);\
    132137} while (0)
    133138
     
    143148  switch (posarg) {
    144149  case -1:
    145     mrb_raisef(mrb, E_ARGUMENT_ERROR, "unnumbered(%S) mixed with numbered", mrb_fixnum_value(nextarg));
     150    mrb_raisef(mrb, E_ARGUMENT_ERROR, "unnumbered(%d) mixed with numbered", nextarg);
    146151    break;
    147152  case -2:
    148     mrb_raisef(mrb, E_ARGUMENT_ERROR, "unnumbered(%S) mixed with named", mrb_fixnum_value(nextarg));
     153    mrb_raisef(mrb, E_ARGUMENT_ERROR, "unnumbered(%d) mixed with named", nextarg);
    149154    break;
    150155  default:
     
    154159
    155160static void
    156 check_pos_arg(mrb_state *mrb, int posarg, int n)
     161check_pos_arg(mrb_state *mrb, int posarg, mrb_int n)
    157162{
    158163  if (posarg > 0) {
    159     mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%S) after unnumbered(%S)",
    160                mrb_fixnum_value(n), mrb_fixnum_value(posarg));
     164    mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%i) after unnumbered(%d)",
     165               n, posarg);
    161166  }
    162167  if (posarg == -2) {
    163     mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%S) after named", mrb_fixnum_value(n));
     168    mrb_raisef(mrb, E_ARGUMENT_ERROR, "numbered(%i) after named", n);
    164169  }
    165170  if (n < 1) {
    166     mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid index - %S$", mrb_fixnum_value(n));
     171    mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid index - %i$", n);
    167172  }
    168173}
    169174
    170175static void
    171 check_name_arg(mrb_state *mrb, int posarg, const char *name, int len)
     176check_name_arg(mrb_state *mrb, int posarg, const char *name, size_t len)
    172177{
    173178  if (posarg > 0) {
    174     mrb_raisef(mrb, E_ARGUMENT_ERROR, "named%S after unnumbered(%S)",
    175                mrb_str_new(mrb, (name), (len)), mrb_fixnum_value(posarg));
     179    mrb_raisef(mrb, E_ARGUMENT_ERROR, "named%l after unnumbered(%d)",
     180               name, len, posarg);
    176181  }
    177182  if (posarg == -1) {
    178     mrb_raisef(mrb, E_ARGUMENT_ERROR, "named%S after numbered", mrb_str_new(mrb, (name), (len)));
     183    mrb_raisef(mrb, E_ARGUMENT_ERROR, "named%l after numbered", name, len);
    179184  }
    180185}
     
    199204#define GETNUM(n, val) \
    200205  for (; p < end && ISDIGIT(*p); p++) {\
    201     int next_n = 10 * n + (*p - '0'); \
    202     if (next_n / 10 != n) {\
     206    if (n > (MRB_INT_MAX - (*p - '0'))/10) {\
    203207      mrb_raise(mrb, E_ARGUMENT_ERROR, #val " too big"); \
    204208    } \
    205     n = next_n; \
     209    n = 10 * n + (*p - '0'); \
    206210  } \
    207211  if (p >= end) { \
     
    225229
    226230static mrb_value
    227 get_hash(mrb_state *mrb, mrb_value *hash, int argc, const mrb_value *argv)
     231get_hash(mrb_state *mrb, mrb_value *hash, mrb_int argc, const mrb_value *argv)
    228232{
    229233  mrb_value tmp;
     
    233237    mrb_raise(mrb, E_ARGUMENT_ERROR, "one hash required");
    234238  }
    235   tmp = mrb_check_convert_type(mrb, argv[1], MRB_TT_HASH, "Hash", "to_hash");
     239  tmp = mrb_check_hash_type(mrb, argv[1]);
    236240  if (mrb_nil_p(tmp)) {
    237241    mrb_raise(mrb, E_ARGUMENT_ERROR, "one hash required");
     
    519523
    520524mrb_value
    521 mrb_str_format(mrb_state *mrb, int argc, const mrb_value *argv, mrb_value fmt)
     525mrb_str_format(mrb_state *mrb, mrb_int argc, const mrb_value *argv, mrb_value fmt)
    522526{
    523527  const char *p, *end;
     
    529533  mrb_int width;
    530534  mrb_int prec;
    531   int flags = FNONE;
    532535  int nextarg = 1;
    533536  int posarg = 0;
     
    553556  ++argc;
    554557  --argv;
    555   fmt = mrb_str_to_str(mrb, fmt);
     558  mrb_to_str(mrb, fmt);
    556559  p = RSTRING_PTR(fmt);
    557560  end = p + RSTRING_LEN(fmt);
    558561  blen = 0;
    559562  bsiz = 120;
    560   result = mrb_str_buf_new(mrb, bsiz);
     563  result = mrb_str_new_capa(mrb, bsiz);
    561564  buf = RSTRING_PTR(result);
    562565  memset(buf, 0, bsiz);
     
    565568    const char *t;
    566569    mrb_sym id = 0;
     570    int flags = FNONE;
    567571
    568572    for (t = p; t < end && *t != '%'; t++) ;
     
    580584    switch (*p) {
    581585      default:
    582         mrb_raisef(mrb, E_ARGUMENT_ERROR, "malformed format string - \\%%S", mrb_str_new(mrb, p, 1));
     586        mrb_raisef(mrb, E_ARGUMENT_ERROR, "malformed format string - %%%c", *p);
    583587        break;
    584588
     
    619623        if (*p == '$') {
    620624          if (!mrb_undef_p(nextvalue)) {
    621             mrb_raisef(mrb, E_ARGUMENT_ERROR, "value given twice - %S$", mrb_fixnum_value(n));
     625            mrb_raisef(mrb, E_ARGUMENT_ERROR, "value given twice - %i$", n);
    622626          }
    623627          nextvalue = GETPOSARG(n);
     
    639643          p++;
    640644        if (id) {
    641           mrb_raisef(mrb, E_ARGUMENT_ERROR, "name%S after <%S>",
    642                      mrb_str_new(mrb, start, p - start + 1), mrb_sym2str(mrb, id));
     645          mrb_raisef(mrb, E_ARGUMENT_ERROR, "name%l after <%n>",
     646                     start, p - start + 1, id);
    643647        }
    644648        symname = mrb_str_new(mrb, start + 1, p - start - 1);
    645649        id = mrb_intern_str(mrb, symname);
    646         nextvalue = GETNAMEARG(mrb_symbol_value(id), start, (int)(p - start + 1));
     650        nextvalue = GETNAMEARG(mrb_symbol_value(id), start, p - start + 1);
    647651        if (mrb_undef_p(nextvalue)) {
    648           mrb_raisef(mrb, E_KEY_ERROR, "key%S not found", mrb_str_new(mrb, start, p - start + 1));
     652          mrb_raisef(mrb, E_KEY_ERROR, "key%l not found", start, p - start + 1);
    649653        }
    650654        if (term == '}') goto format_s;
     
    702706        tmp = mrb_check_string_type(mrb, val);
    703707        if (!mrb_nil_p(tmp)) {
    704           if (mrb_fixnum(mrb_funcall(mrb, tmp, "size", 0)) != 1 ) {
     708          if (RSTRING_LEN(tmp) != 1) {
    705709            mrb_raise(mrb, E_ARGUMENT_ERROR, "%c requires a character");
    706710          }
    707711        }
    708712        else if (mrb_fixnum_p(val)) {
    709           tmp = mrb_funcall(mrb, val, "chr", 0);
     713          mrb_int n = mrb_fixnum(val);
     714
     715          if (n < 0x80) {
     716            char buf[1];
     717
     718            buf[0] = (char)n;
     719            tmp = mrb_str_new(mrb, buf, 1);
     720          }
     721          else {
     722            tmp = mrb_funcall(mrb, val, "chr", 0);
     723            mrb_check_type(mrb, tmp, MRB_TT_STRING);
     724          }
    710725        }
    711726        else {
    712727          mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid character");
    713728        }
    714         mrb_check_type(mrb, tmp, MRB_TT_STRING);
    715729        c = RSTRING_PTR(tmp);
    716730        n = RSTRING_LEN(tmp);
     
    756770            char *p = RSTRING_PTR(str) + prec;
    757771            slen = prec;
    758             len = p - RSTRING_PTR(str);
     772            len = (mrb_int)(p - RSTRING_PTR(str));
    759773          }
    760774          /* need to adjust multi-byte string pos */
     
    792806        mrb_int len;
    793807
    794         switch (*p) {
    795           case 'd':
    796           case 'i':
    797             sign = 1; break;
    798           default:
    799             break;
    800         }
    801808        if (flags & FSHARP) {
    802809          switch (*p) {
     
    812819  bin_retry:
    813820        switch (mrb_type(val)) {
     821#ifndef MRB_WITHOUT_FLOAT
    814822          case MRB_TT_FLOAT:
    815823            val = mrb_flo_to_fixnum(mrb, val);
    816824            if (mrb_fixnum_p(val)) goto bin_retry;
    817825            break;
     826#endif
    818827          case MRB_TT_STRING:
    819828            val = mrb_str_to_inum(mrb, val, 0, TRUE);
     
    839848          case 'd':
    840849          case 'i':
     850            sign = 1;
     851            /* fall through */
    841852          default:
    842853            base = 10; break;
    843854        }
    844855
    845         if (base == 2) {
    846           if (v < 0 && !sign) {
    847             val = mrb_fix2binstr(mrb, mrb_fixnum_value(v), base);
    848             dots = 1;
    849           }
    850           else {
    851             val = mrb_fixnum_to_str(mrb, mrb_fixnum_value(v), base);
    852           }
    853         }
    854856        if (sign) {
    855           if (v > 0) {
     857          if (v >= 0) {
    856858            if (flags & FPLUS) {
    857859              sc = '+';
     
    863865            }
    864866          }
     867          else {
     868            sc = '-';
     869            width--;
     870          }
     871          mrb_assert(base == 10);
     872          snprintf(nbuf, sizeof(nbuf), "%" MRB_PRId, v);
     873          s = nbuf;
     874          if (v < 0) s++;       /* skip minus sign */
     875        }
     876        else {
     877          s = nbuf;
     878          if (v < 0) {
     879            dots = 1;
     880          }
    865881          switch (base) {
    866882          case 2:
    867             strncpy(nbuf, RSTRING_PTR(val), sizeof(nbuf));
    868             break;
    869           case 8:
    870             snprintf(nbuf, sizeof(nbuf), "%" MRB_PRIo, v);
    871             break;
    872           case 10:
    873             snprintf(nbuf, sizeof(nbuf), "%" MRB_PRId, v);
    874             break;
    875           case 16:
    876             snprintf(nbuf, sizeof(nbuf), "%" MRB_PRIx, v);
    877             break;
    878           }
    879           s = nbuf;
    880         }
    881         else {
    882           s = nbuf;
    883           if (base != 10 && v < 0) {
    884             dots = 1;
    885           }
    886           switch (base) {
    887           case 2:
     883            if (v < 0) {
     884              val = mrb_fix2binstr(mrb, mrb_fixnum_value(v), base);
     885            }
     886            else {
     887              val = mrb_fixnum_to_str(mrb, mrb_fixnum_value(v), base);
     888            }
    888889            strncpy(++s, RSTRING_PTR(val), sizeof(nbuf)-1);
    889890            break;
    890891          case 8:
    891892            snprintf(++s, sizeof(nbuf)-1, "%" MRB_PRIo, v);
    892             break;
    893           case 10:
    894             snprintf(++s, sizeof(nbuf)-1, "%" MRB_PRId, v);
    895893            break;
    896894          case 16:
     
    921919        }
    922920
    923         if (dots) {
    924           prec -= 2;
    925           width -= 2;
    926         }
    927 
    928921        if (*p == 'X') {
    929922          char *pp = s;
     
    973966        if (!(flags&FMINUS) && width > 0) {
    974967          FILL(' ', width);
     968          width = 0;
    975969        }
    976970
     
    981975          PUSH(prefix, plen);
    982976        }
    983         if (dots) PUSH("..", 2);
     977        if (dots) {
     978          prec -= 2;
     979          width -= 2;
     980          PUSH("..", 2);
     981        }
    984982
    985983        if (prec > len) {
    986984          CHECK(prec - len);
    987           if (v < 0) {
     985          if ((flags & (FMINUS|FPREC)) != FMINUS) {
     986            char c = '0';
     987            FILL(c, prec - len);
     988          } else if (v < 0) {
    988989            char c = sign_bits(base, p);
    989             FILL(c, prec - len);
    990           }
    991           else if ((flags & (FMINUS|FPREC)) != FMINUS) {
    992             char c = '0';
    993990            FILL(c, prec - len);
    994991          }
     
    1001998      break;
    1002999
     1000#ifndef MRB_WITHOUT_FLOAT
    10031001      case 'f':
    10041002      case 'g':
     
    10101008        mrb_value val = GETARG();
    10111009        double fval;
    1012         int i, need = 6;
     1010        mrb_int need = 6;
    10131011        char fbuf[32];
    10141012
     
    10161014        if (!isfinite(fval)) {
    10171015          const char *expr;
    1018           const int elen = 3;
     1016          const mrb_int elen = 3;
    10191017          char sign = '\0';
    10201018
     
    10311029            sign = (flags & FPLUS) ? '+' : ' ';
    10321030          if (sign)
    1033             ++need;
     1031            ++need;
    10341032          if ((flags & FWIDTH) && need < width)
    10351033            need = width;
     
    10551053        need = 0;
    10561054        if (*p != 'e' && *p != 'E') {
    1057           i = INT_MIN;
     1055          int i;
    10581056          frexp(fval, &i);
    10591057          if (i > 0)
    10601058            need = BIT_DIGITS(i);
    10611059        }
     1060        if (need > MRB_INT_MAX - ((flags&FPREC) ? prec : 6)) {
     1061        too_big_width:
     1062          mrb_raise(mrb, E_ARGUMENT_ERROR,
     1063                    (width > prec ? "width too big" : "prec too big"));
     1064        }
    10621065        need += (flags&FPREC) ? prec : 6;
    10631066        if ((flags&FWIDTH) && need < width)
    10641067          need = width;
     1068        if (need > MRB_INT_MAX - 20) {
     1069          goto too_big_width;
     1070        }
    10651071        need += 20;
    1066         if (need <= 0) {
    1067           mrb_raise(mrb, E_ARGUMENT_ERROR,
    1068                     (width > prec ? "width too big" : "prec too big"));
    1069         }
    10701072
    10711073        CHECK(need);
    10721074        n = snprintf(&buf[blen], need, fbuf, fval);
    1073         if (n < 0) {
     1075        if (n < 0 || n >= need) {
    10741076          mrb_raise(mrb, E_RUNTIME_ERROR, "formatting error");
    10751077        }
     
    10771079      }
    10781080      break;
     1081#endif
    10791082    }
    10801083    flags = FNONE;
     
    10881091    const char *mesg = "too many arguments for format string";
    10891092    if (mrb_test(ruby_debug)) mrb_raise(mrb, E_ARGUMENT_ERROR, mesg);
    1090     if (mrb_test(ruby_verbose)) mrb_warn(mrb, "%S", mrb_str_new_cstr(mrb, mesg));
     1093    if (mrb_test(ruby_verbose)) mrb_warn(mrb, "%s", mesg);
    10911094  }
    10921095#endif
     
    10961099}
    10971100
     1101#ifndef MRB_WITHOUT_FLOAT
    10981102static void
    10991103fmt_setup(char *buf, size_t size, int c, int flags, mrb_int width, mrb_int prec)
     
    11221126  *buf = '\0';
    11231127}
     1128#endif
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-sprintf/test/sprintf.rb

    r331 r439  
    44assert('String#%') do
    55  assert_equal "one=1", "one=%d" % 1
    6   assert_equal "1 one 1.0", "%d %s %3.1f" % [ 1, "one", 1.01 ]
     6  assert_equal "1 one", "%d %s" % [ 1, "one" ]
    77  assert_equal "123 < 456", "%{num} < %<str>s" % { num: 123, str: "456" }
    88  assert_equal 15, ("%b" % (1<<14)).size
     9  skip unless Object.const_defined?(:Float)
     10  assert_equal "1.0", "%3.1f" % 1.01
    911end
    1012
    1113assert('String#% with inf') do
     14  skip unless Object.const_defined?(:Float)
    1215  inf = Float::INFINITY
    1316
     
    3841
    3942assert('String#% with nan') do
     43  skip unless Object.const_defined?(:Float)
    4044  nan = Float::NAN
    4145
     
    7680
    7781    assert_raise TypeError do
    78       "%c" % 0
     82      "%c" % 0x80
    7983    end
    8084  ensure
     
    9296end
    9397
     98assert("String#% %d") do
     99  assert_equal("  10",   "%4d" % 10)
     100  assert_equal("1000",   "%4d" % 1000)
     101  assert_equal("10000",  "%4d" % 10000)
     102end
     103
    94104assert("String#% invalid format") do
    95105  assert_raise ArgumentError do
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-string-ext/mrbgem.rake

    r331 r439  
    33  spec.author  = 'mruby developers'
    44  spec.summary = 'String class extension'
    5   spec.add_test_dependency 'mruby-enumerator', core: 'mruby-enumerator'
    65end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-string-ext/mrblib/string.rb

    r331 r439  
    11class String
    2 
    3   ##
    4   #  call-seq:
    5   #     String.try_convert(obj) -> string or nil
    6   #
    7   # Try to convert <i>obj</i> into a String, using to_str method.
    8   # Returns converted string or nil if <i>obj</i> cannot be converted
    9   # for any reason.
    10   #
    11   #     String.try_convert("str")     #=> "str"
    12   #     String.try_convert(/re/)      #=> nil
    13   #
    14   def self.try_convert(obj)
    15     if obj.respond_to?(:to_str)
    16       obj.to_str
    17     else
    18       nil
    19     end
    20   end
    212
    223  ##
     
    9677  #
    9778  def lstrip!
    98     raise RuntimeError, "can't modify frozen String" if frozen?
     79    raise FrozenError, "can't modify frozen String" if frozen?
    9980    s = self.lstrip
    10081    (s == self) ? nil : self.replace(s)
     
    11394  #
    11495  def rstrip!
    115     raise RuntimeError, "can't modify frozen String" if frozen?
     96    raise FrozenError, "can't modify frozen String" if frozen?
    11697    s = self.rstrip
    11798    (s == self) ? nil : self.replace(s)
     
    126107  #
    127108  def strip!
    128     raise RuntimeError, "can't modify frozen String" if frozen?
     109    raise FrozenError, "can't modify frozen String" if frozen?
    129110    s = self.strip
    130111    (s == self) ? nil : self.replace(s)
     
    143124  #
    144125  def casecmp(str)
    145     self.downcase <=> str.to_str.downcase
     126    self.downcase <=> str.__to_str.downcase
    146127  rescue NoMethodError
    147     raise TypeError, "no implicit conversion of #{str.class} into String"
     128    nil
     129  end
     130
     131  ##
     132  # call-seq:
     133  #   str.casecmp?(other)  -> true, false, or nil
     134  #
     135  # Returns true if str and other_str are equal after case folding,
     136  # false if they are not equal, and nil if other_str is not a string.
     137
     138  def casecmp?(str)
     139    c = self.casecmp(str)
     140    return nil if c.nil?
     141    return c == 0
    148142  end
    149143
     
    187181  #
    188182  def slice!(arg1, arg2=nil)
    189     raise RuntimeError, "can't modify frozen String" if frozen?
     183    raise FrozenError, "can't modify frozen String" if frozen?
    190184    raise "wrong number of arguments (for 1..2)" if arg1.nil? && arg2.nil?
    191185
     
    317311  end
    318312
     313  ##
     314  # Call the given block for each character of
     315  # +self+.
    319316  def each_char(&block)
    320317    return to_enum :each_char unless block
    321 
    322     split('').each do |i|
    323       block.call(i)
     318    pos = 0
     319    while pos < self.size
     320      block.call(self[pos])
     321      pos += 1
    324322    end
    325323    self
     
    353351    self
    354352  end
     353
     354  ##
     355  #  call-seq:
     356  #    string.lines                ->  array of string
     357  #    string.lines {|s| block}    ->  array of string
     358  #
     359  #  Returns strings per line;
     360  #
     361  #    a = "abc\ndef"
     362  #    a.lines    #=> ["abc\n", "def"]
     363  #
     364  #  If a block is given, it works the same as <code>each_line</code>.
     365  def lines(&blk)
     366    lines = self.__lines
     367    if blk
     368      lines.each do |line|
     369        blk.call(line)
     370      end
     371    end
     372    lines
     373  end
     374
     375  ##
     376  #  call-seq:
     377  #     str.upto(other_str, exclusive=false) {|s| block }   -> str
     378  #     str.upto(other_str, exclusive=false)                -> an_enumerator
     379  #
     380  #  Iterates through successive values, starting at <i>str</i> and
     381  #  ending at <i>other_str</i> inclusive, passing each value in turn to
     382  #  the block. The <code>String#succ</code> method is used to generate
     383  #  each value.  If optional second argument exclusive is omitted or is false,
     384  #  the last value will be included; otherwise it will be excluded.
     385  #
     386  #  If no block is given, an enumerator is returned instead.
     387  #
     388  #     "a8".upto("b6") {|s| print s, ' ' }
     389  #     for s in "a8".."b6"
     390  #       print s, ' '
     391  #     end
     392  #
     393  #  <em>produces:</em>
     394  #
     395  #     a8 a9 b0 b1 b2 b3 b4 b5 b6
     396  #     a8 a9 b0 b1 b2 b3 b4 b5 b6
     397  #
     398  #  If <i>str</i> and <i>other_str</i> contains only ascii numeric characters,
     399  #  both are recognized as decimal numbers. In addition, the width of
     400  #  string (e.g. leading zeros) is handled appropriately.
     401  #
     402  #     "9".upto("11").to_a   #=> ["9", "10", "11"]
     403  #     "25".upto("5").to_a   #=> []
     404  #     "07".upto("11").to_a  #=> ["07", "08", "09", "10", "11"]
     405  def upto(max, exclusive=false, &block)
     406    return to_enum(:upto, max, exclusive) unless block
     407    raise TypeError, "no implicit conversion of #{max.class} into String" unless max.kind_of? String
     408
     409    len = self.length
     410    maxlen = max.length
     411    # single character
     412    if len == 1 and maxlen == 1
     413      c = self.ord
     414      e = max.ord
     415      while c <= e
     416        break if exclusive and c == e
     417        yield c.chr(__ENCODING__)
     418        c += 1
     419      end
     420      return self
     421    end
     422    # both edges are all digits
     423    bi = self.to_i(10)
     424    ei = max.to_i(10)
     425    len = self.length
     426    if (bi > 0 or bi == "0"*len) and (ei > 0 or ei == "0"*maxlen)
     427      while bi <= ei
     428        break if exclusive and bi == ei
     429        s = bi.to_s
     430        s = s.rjust(len, "0") if s.length < len
     431        yield s
     432        bi += 1
     433      end
     434      return self
     435    end
     436    bs = self
     437    while true
     438      n = (bs <=> max)
     439      break if n > 0
     440      break if exclusive and n == 0
     441      yield bs
     442      break if n == 0
     443      bs = bs.succ
     444    end
     445    self
     446  end
    355447end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-string-ext/src/string.c

    r331 r439  
    66#include <mruby/range.h>
    77
    8 static mrb_value
    9 mrb_str_getbyte(mrb_state *mrb, mrb_value str)
    10 {
    11   mrb_int pos;
    12   mrb_get_args(mrb, "i", &pos);
    13 
    14   if (pos < 0)
    15     pos += RSTRING_LEN(str);
    16   if (pos < 0 ||  RSTRING_LEN(str) <= pos)
    17     return mrb_nil_value();
    18 
    19   return mrb_fixnum_value((unsigned char)RSTRING_PTR(str)[pos]);
    20 }
    21 
    22 static mrb_value
    23 mrb_str_setbyte(mrb_state *mrb, mrb_value str)
    24 {
    25   mrb_int pos, byte;
    26   long len;
    27 
    28   mrb_get_args(mrb, "ii", &pos, &byte);
    29 
    30   len = RSTRING_LEN(str);
    31   if (pos < -len || len <= pos)
    32     mrb_raisef(mrb, E_INDEX_ERROR, "index %S is out of array", mrb_fixnum_value(pos));
    33   if (pos < 0)
    34     pos += len;
    35 
    36   mrb_str_modify(mrb, mrb_str_ptr(str));
    37   byte &= 0xff;
    38   RSTRING_PTR(str)[pos] = byte;
    39   return mrb_fixnum_value((unsigned char)byte);
    40 }
    41 
    42 static mrb_value
    43 mrb_str_byteslice(mrb_state *mrb, mrb_value str)
    44 {
    45   mrb_value a1;
     8#define ENC_ASCII_8BIT "ASCII-8BIT"
     9#define ENC_BINARY     "BINARY"
     10#define ENC_UTF8       "UTF-8"
     11
     12#define ENC_COMP_P(enc, enc_lit) \
     13  str_casecmp_p(RSTRING_PTR(enc), RSTRING_LEN(enc), enc_lit, sizeof(enc_lit"")-1)
     14
     15#ifdef MRB_WITHOUT_FLOAT
     16# define mrb_float_p(o) FALSE
     17#endif
     18
     19static mrb_bool
     20str_casecmp_p(const char *s1, mrb_int len1, const char *s2, mrb_int len2)
     21{
     22  const char *e1, *e2;
     23
     24  if (len1 != len2) return FALSE;
     25  e1 = s1 + len1;
     26  e2 = s2 + len2;
     27  while (s1 < e1 && s2 < e2) {
     28    if (*s1 != *s2 && TOUPPER(*s1) != TOUPPER(*s2)) return FALSE;
     29    ++s1;
     30    ++s2;
     31  }
     32  return TRUE;
     33}
     34
     35static mrb_value
     36int_chr_binary(mrb_state *mrb, mrb_value num)
     37{
     38  mrb_int cp = mrb_int(mrb, num);
     39  char c;
     40  mrb_value str;
     41
     42  if (cp < 0 || 0xff < cp) {
     43    mrb_raisef(mrb, E_RANGE_ERROR, "%v out of char range", num);
     44  }
     45  c = (char)cp;
     46  str = mrb_str_new(mrb, &c, 1);
     47  RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
     48  return str;
     49}
     50
     51#ifdef MRB_UTF8_STRING
     52static mrb_value
     53int_chr_utf8(mrb_state *mrb, mrb_value num)
     54{
     55  mrb_int cp = mrb_int(mrb, num);
     56  char utf8[4];
    4657  mrb_int len;
    47   int argc;
    48 
    49   argc = mrb_get_args(mrb, "o|i", &a1, &len);
    50   if (argc == 2) {
    51     return mrb_str_substr(mrb, str, mrb_fixnum(a1), len);
    52   }
    53   switch (mrb_type(a1)) {
    54   case MRB_TT_RANGE:
    55     {
    56       mrb_int beg;
    57 
    58       len = RSTRING_LEN(str);
    59       switch (mrb_range_beg_len(mrb, a1, &beg, &len, len, TRUE)) {
    60       case 0:                   /* not range */
    61         break;
    62       case 1:                   /* range */
    63         return mrb_str_substr(mrb, str, beg, len);
    64       case 2:                   /* out of range */
    65         mrb_raisef(mrb, E_RANGE_ERROR, "%S out of range", a1);
    66         break;
    67       }
    68       return mrb_nil_value();
    69     }
    70   case MRB_TT_FLOAT:
    71     a1 = mrb_fixnum_value((mrb_int)mrb_float(a1));
    72     /* fall through */
    73   case MRB_TT_FIXNUM:
    74     return mrb_str_substr(mrb, str, mrb_fixnum(a1), 1);
    75   default:
    76     mrb_raise(mrb, E_TYPE_ERROR, "wrong type of argument");
    77   }
    78   /* not reached */
    79   return mrb_nil_value();
    80 }
     58  mrb_value str;
     59  uint32_t ascii_flag = 0;
     60
     61  if (cp < 0 || 0x10FFFF < cp) {
     62    mrb_raisef(mrb, E_RANGE_ERROR, "%v out of char range", num);
     63  }
     64  if (cp < 0x80) {
     65    utf8[0] = (char)cp;
     66    len = 1;
     67    ascii_flag = MRB_STR_ASCII;
     68  }
     69  else if (cp < 0x800) {
     70    utf8[0] = (char)(0xC0 | (cp >> 6));
     71    utf8[1] = (char)(0x80 | (cp & 0x3F));
     72    len = 2;
     73  }
     74  else if (cp < 0x10000) {
     75    utf8[0] = (char)(0xE0 |  (cp >> 12));
     76    utf8[1] = (char)(0x80 | ((cp >>  6) & 0x3F));
     77    utf8[2] = (char)(0x80 | ( cp        & 0x3F));
     78    len = 3;
     79  }
     80  else {
     81    utf8[0] = (char)(0xF0 |  (cp >> 18));
     82    utf8[1] = (char)(0x80 | ((cp >> 12) & 0x3F));
     83    utf8[2] = (char)(0x80 | ((cp >>  6) & 0x3F));
     84    utf8[3] = (char)(0x80 | ( cp        & 0x3F));
     85    len = 4;
     86  }
     87  str = mrb_str_new(mrb, utf8, len);
     88  mrb_str_ptr(str)->flags |= ascii_flag;
     89  return str;
     90}
     91#endif
    8192
    8293/*
     
    135146}
    136147
    137 static mrb_value mrb_fixnum_chr(mrb_state *mrb, mrb_value num);
    138 
    139148/*
    140149 *  call-seq:
     
    146155 *  Append---Concatenates the given object to <i>str</i>. If the object is a
    147156 *  <code>Integer</code>, it is considered as a codepoint, and is converted
    148  *  to a character before concatenation.
     157 *  to a character before concatenation
     158 *  (equivalent to <code>str.concat(integer.chr(__ENCODING__))</code>).
    149159 *
    150160 *     a = "hello "
     
    153163 */
    154164static mrb_value
    155 mrb_str_concat2(mrb_state *mrb, mrb_value self)
     165mrb_str_concat_m(mrb_state *mrb, mrb_value self)
    156166{
    157167  mrb_value str;
    158168
    159169  mrb_get_args(mrb, "o", &str);
    160   if (mrb_fixnum_p(str))
    161     str = mrb_fixnum_chr(mrb, str);
     170  if (mrb_fixnum_p(str) || mrb_float_p(str))
     171#ifdef MRB_UTF8_STRING
     172    str = int_chr_utf8(mrb, str);
     173#else
     174    str = int_chr_binary(mrb, str);
     175#endif
    162176  else
    163     str = mrb_string_type(mrb, str);
    164   mrb_str_concat(mrb, self, str);
     177    mrb_ensure_string_type(mrb, str);
     178  mrb_str_cat_str(mrb, self, str);
    165179  return self;
    166180}
     
    189203    size_t len_l, len_r;
    190204    int ai = mrb_gc_arena_save(mrb);
    191     sub = mrb_string_type(mrb, argv[i]);
     205    sub = mrb_ensure_string_type(mrb, argv[i]);
    192206    mrb_gc_arena_restore(mrb, ai);
    193207    len_l = RSTRING_LEN(self);
     
    218232    size_t len_l, len_r;
    219233    int ai = mrb_gc_arena_save(mrb);
    220     sub = mrb_string_type(mrb, argv[i]);
     234    sub = mrb_ensure_string_type(mrb, argv[i]);
    221235    mrb_gc_arena_restore(mrb, ai);
    222236    len_l = RSTRING_LEN(self);
     
    233247}
    234248
     249enum tr_pattern_type {
     250  TR_UNINITIALIZED = 0,
     251  TR_IN_ORDER  = 1,
     252  TR_RANGE = 2,
     253};
     254
     255/*
     256  #tr Pattern syntax
     257
     258  <syntax> ::= (<pattern>)* | '^' (<pattern>)*
     259  <pattern> ::= <in order> | <range>
     260  <in order> ::= (<ch>)+
     261  <range> ::= <ch> '-' <ch>
     262*/
     263struct tr_pattern {
     264  uint8_t type;         // 1:in-order, 2:range
     265  mrb_bool flag_reverse : 1;
     266  mrb_bool flag_on_heap : 1;
     267  uint16_t n;
     268  union {
     269    uint16_t start_pos;
     270    char ch[2];
     271  } val;
     272  struct tr_pattern *next;
     273};
     274
     275#define STATIC_TR_PATTERN { 0 }
     276
     277static inline void
     278tr_free_pattern(mrb_state *mrb, struct tr_pattern *pat)
     279{
     280  while (pat) {
     281    struct tr_pattern *p = pat->next;
     282    if (pat->flag_on_heap) {
     283      mrb_free(mrb, pat);
     284    }
     285    pat = p;
     286  }
     287}
     288
     289static struct tr_pattern*
     290tr_parse_pattern(mrb_state *mrb, struct tr_pattern *ret, const mrb_value v_pattern, mrb_bool flag_reverse_enable)
     291{
     292  const char *pattern = RSTRING_PTR(v_pattern);
     293  mrb_int pattern_length = RSTRING_LEN(v_pattern);
     294  mrb_bool flag_reverse = FALSE;
     295  struct tr_pattern *pat1;
     296  mrb_int i = 0;
     297
     298  if(flag_reverse_enable && pattern_length >= 2 && pattern[0] == '^') {
     299    flag_reverse = TRUE;
     300    i++;
     301  }
     302
     303  while (i < pattern_length) {
     304    /* is range pattern ? */
     305    mrb_bool const ret_uninit = (ret->type == TR_UNINITIALIZED);
     306    pat1 = ret_uninit
     307           ? ret
     308           : (struct tr_pattern*)mrb_malloc_simple(mrb, sizeof(struct tr_pattern));
     309    if ((i+2) < pattern_length && pattern[i] != '\\' && pattern[i+1] == '-') {
     310      if (pat1 == NULL && ret) {
     311      nomem:
     312        tr_free_pattern(mrb, ret);
     313        mrb_exc_raise(mrb, mrb_obj_value(mrb->nomem_err));
     314        return NULL;            /* not reached */
     315      }
     316      pat1->type = TR_RANGE;
     317      pat1->flag_reverse = flag_reverse;
     318      pat1->flag_on_heap = !ret_uninit;
     319      pat1->n = pattern[i+2] - pattern[i] + 1;
     320      pat1->next = NULL;
     321      pat1->val.ch[0] = pattern[i];
     322      pat1->val.ch[1] = pattern[i+2];
     323      i += 3;
     324    }
     325    else {
     326      /* in order pattern. */
     327      mrb_int start_pos = i++;
     328      mrb_int len;
     329
     330      while (i < pattern_length) {
     331        if ((i+2) < pattern_length && pattern[i] != '\\' && pattern[i+1] == '-')
     332          break;
     333        i++;
     334      }
     335
     336      len = i - start_pos;
     337      if (len > UINT16_MAX) {
     338        mrb_raise(mrb, E_ARGUMENT_ERROR, "tr pattern too long (max 65536)");
     339      }
     340      if (pat1 == NULL && ret) {
     341        goto nomem;
     342      }
     343      pat1->type = TR_IN_ORDER;
     344      pat1->flag_reverse = flag_reverse;
     345      pat1->flag_on_heap = !ret_uninit;
     346      pat1->n = len;
     347      pat1->next = NULL;
     348      pat1->val.start_pos = start_pos;
     349    }
     350
     351    if (ret == NULL || ret_uninit) {
     352      ret = pat1;
     353    }
     354    else {
     355      struct tr_pattern *p = ret;
     356      while (p->next != NULL) {
     357        p = p->next;
     358      }
     359      p->next = pat1;
     360    }
     361  }
     362
     363  return ret;
     364}
     365
     366static inline mrb_int
     367tr_find_character(const struct tr_pattern *pat, const char *pat_str, int ch)
     368{
     369  mrb_int ret = -1;
     370  mrb_int n_sum = 0;
     371  mrb_int flag_reverse = pat ? pat->flag_reverse : 0;
     372
     373  while (pat != NULL) {
     374    if (pat->type == TR_IN_ORDER) {
     375      int i;
     376      for (i = 0; i < pat->n; i++) {
     377        if (pat_str[pat->val.start_pos + i] == ch) ret = n_sum + i;
     378      }
     379    }
     380    else if (pat->type == TR_RANGE) {
     381      if (pat->val.ch[0] <= ch && ch <= pat->val.ch[1])
     382        ret = n_sum + ch - pat->val.ch[0];
     383    }
     384    else {
     385      mrb_assert(pat->type == TR_UNINITIALIZED);
     386    }
     387    n_sum += pat->n;
     388    pat = pat->next;
     389  }
     390
     391  if (flag_reverse) {
     392    return (ret < 0) ? MRB_INT_MAX : -1;
     393  }
     394  return ret;
     395}
     396
     397static inline mrb_int
     398tr_get_character(const struct tr_pattern *pat, const char *pat_str, mrb_int n_th)
     399{
     400  mrb_int n_sum = 0;
     401
     402  while (pat != NULL) {
     403    if (n_th < (n_sum + pat->n)) {
     404      mrb_int i = (n_th - n_sum);
     405
     406      switch (pat->type) {
     407      case TR_IN_ORDER:
     408        return pat_str[pat->val.start_pos + i];
     409      case TR_RANGE:
     410        return pat->val.ch[0]+i;
     411      case TR_UNINITIALIZED:
     412        return -1;
     413      }
     414    }
     415    if (pat->next == NULL) {
     416      switch (pat->type) {
     417      case TR_IN_ORDER:
     418        return pat_str[pat->val.start_pos + pat->n - 1];
     419      case TR_RANGE:
     420        return pat->val.ch[1];
     421      case TR_UNINITIALIZED:
     422        return -1;
     423      }
     424    }
     425    n_sum += pat->n;
     426    pat = pat->next;
     427  }
     428
     429  return -1;
     430}
     431
     432static inline void
     433tr_bitmap_set(uint8_t bitmap[32], uint8_t ch)
     434{
     435  uint8_t idx1 = ch / 8;
     436  uint8_t idx2 = ch % 8;
     437  bitmap[idx1] |= (1<<idx2);
     438}
     439
     440static inline mrb_bool
     441tr_bitmap_detect(uint8_t bitmap[32], uint8_t ch)
     442{
     443  uint8_t idx1 = ch / 8;
     444  uint8_t idx2 = ch % 8;
     445  if (bitmap[idx1] & (1<<idx2))
     446    return TRUE;
     447  return FALSE;
     448}
     449
     450/* compile patter to bitmap */
     451static void
     452tr_compile_pattern(const struct tr_pattern *pat, mrb_value pstr, uint8_t bitmap[32])
     453{
     454  const char *pattern = RSTRING_PTR(pstr);
     455  mrb_int flag_reverse = pat ? pat->flag_reverse : 0;
     456  int i;
     457
     458  for (i=0; i<32; i++) {
     459    bitmap[i] = 0;
     460  }
     461  while (pat != NULL) {
     462    if (pat->type == TR_IN_ORDER) {
     463      for (i = 0; i < pat->n; i++) {
     464        tr_bitmap_set(bitmap, pattern[pat->val.start_pos + i]);
     465      }
     466    }
     467    else if (pat->type == TR_RANGE) {
     468      for (i = pat->val.ch[0]; i < pat->val.ch[1]; i++) {
     469        tr_bitmap_set(bitmap, i);
     470      }
     471    }
     472    else {
     473      mrb_assert(pat->type == TR_UNINITIALIZED);
     474    }
     475    pat = pat->next;
     476  }
     477
     478  if (flag_reverse) {
     479    for (i=0; i<32; i++) {
     480      bitmap[i] ^= 0xff;
     481    }
     482  }
     483}
     484
     485static mrb_bool
     486str_tr(mrb_state *mrb, mrb_value str, mrb_value p1, mrb_value p2, mrb_bool squeeze)
     487{
     488  struct tr_pattern pat = STATIC_TR_PATTERN;
     489  struct tr_pattern rep_storage = STATIC_TR_PATTERN;
     490  char *s;
     491  mrb_int len;
     492  mrb_int i;
     493  mrb_int j;
     494  mrb_bool flag_changed = FALSE;
     495  mrb_int lastch = -1;
     496  struct tr_pattern *rep;
     497
     498  mrb_str_modify(mrb, mrb_str_ptr(str));
     499  tr_parse_pattern(mrb, &pat, p1, TRUE);
     500  rep = tr_parse_pattern(mrb, &rep_storage, p2, FALSE);
     501  s = RSTRING_PTR(str);
     502  len = RSTRING_LEN(str);
     503
     504  for (i=j=0; i<len; i++,j++) {
     505    mrb_int n = tr_find_character(&pat, RSTRING_PTR(p1), s[i]);
     506
     507    if (i>j) s[j] = s[i];
     508    if (n >= 0) {
     509      flag_changed = TRUE;
     510      if (rep == NULL) {
     511        j--;
     512      }
     513      else {
     514        mrb_int c = tr_get_character(rep, RSTRING_PTR(p2), n);
     515
     516        if (c < 0 || (squeeze && c == lastch)) {
     517          j--;
     518          continue;
     519        }
     520        if (c > 0x80) {
     521          mrb_raisef(mrb, E_ARGUMENT_ERROR, "character (%i) out of range", c);
     522        }
     523        lastch = c;
     524        s[i] = (char)c;
     525      }
     526    }
     527  }
     528
     529  tr_free_pattern(mrb, &pat);
     530  tr_free_pattern(mrb, rep);
     531
     532  if (flag_changed) {
     533    RSTR_SET_LEN(RSTRING(str), j);
     534    RSTRING_PTR(str)[j] = 0;
     535  }
     536  return flag_changed;
     537}
     538
     539/*
     540 * call-seq:
     541 *   str.tr(from_str, to_str)   => new_str
     542 *
     543 * Returns a copy of str with the characters in from_str replaced by the
     544 * corresponding characters in to_str.  If to_str is shorter than from_str,
     545 * it is padded with its last character in order to maintain the
     546 * correspondence.
     547 *
     548 *  "hello".tr('el', 'ip')      #=> "hippo"
     549 *  "hello".tr('aeiou', '*')    #=> "h*ll*"
     550 *  "hello".tr('aeiou', 'AA*')  #=> "hAll*"
     551 *
     552 * Both strings may use the c1-c2 notation to denote ranges of characters,
     553 * and from_str may start with a ^, which denotes all characters except
     554 * those listed.
     555 *
     556 *  "hello".tr('a-y', 'b-z')    #=> "ifmmp"
     557 *  "hello".tr('^aeiou', '*')   #=> "*e**o"
     558 *
     559 * The backslash character \ can be used to escape ^ or - and is otherwise
     560 * ignored unless it appears at the end of a range or the end of the
     561 * from_str or to_str:
     562 *
     563 *
     564 *  "hello^world".tr("\\^aeiou", "*") #=> "h*ll**w*rld"
     565 *  "hello-world".tr("a\\-eo", "*")   #=> "h*ll**w*rld"
     566 *
     567 *  "hello\r\nworld".tr("\r", "")   #=> "hello\nworld"
     568 *  "hello\r\nworld".tr("\\r", "")  #=> "hello\r\nwold"
     569 *  "hello\r\nworld".tr("\\\r", "") #=> "hello\nworld"
     570 *
     571 *  "X['\\b']".tr("X\\", "")   #=> "['b']"
     572 *  "X['\\b']".tr("X-\\]", "") #=> "'b'"
     573 *
     574 *  Note: conversion is effective only in ASCII region.
     575 */
     576static mrb_value
     577mrb_str_tr(mrb_state *mrb, mrb_value str)
     578{
     579  mrb_value dup;
     580  mrb_value p1, p2;
     581
     582  mrb_get_args(mrb, "SS", &p1, &p2);
     583  dup = mrb_str_dup(mrb, str);
     584  str_tr(mrb, dup, p1, p2, FALSE);
     585  return dup;
     586}
     587
     588/*
     589 * call-seq:
     590 *   str.tr!(from_str, to_str)   -> str or nil
     591 *
     592 * Translates str in place, using the same rules as String#tr.
     593 * Returns str, or nil if no changes were made.
     594 */
     595static mrb_value
     596mrb_str_tr_bang(mrb_state *mrb, mrb_value str)
     597{
     598  mrb_value p1, p2;
     599
     600  mrb_get_args(mrb, "SS", &p1, &p2);
     601  if (str_tr(mrb, str, p1, p2, FALSE)) {
     602    return str;
     603  }
     604  return mrb_nil_value();
     605}
     606
     607/*
     608 * call-seq:
     609 *   str.tr_s(from_str, to_str)   -> new_str
     610 *
     611 * Processes a copy of str as described under String#tr, then removes
     612 * duplicate characters in regions that were affected by the translation.
     613 *
     614 *  "hello".tr_s('l', 'r')     #=> "hero"
     615 *  "hello".tr_s('el', '*')    #=> "h*o"
     616 *  "hello".tr_s('el', 'hx')   #=> "hhxo"
     617 */
     618static mrb_value
     619mrb_str_tr_s(mrb_state *mrb, mrb_value str)
     620{
     621  mrb_value dup;
     622  mrb_value p1, p2;
     623
     624  mrb_get_args(mrb, "SS", &p1, &p2);
     625  dup = mrb_str_dup(mrb, str);
     626  str_tr(mrb, dup, p1, p2, TRUE);
     627  return dup;
     628}
     629
     630/*
     631 * call-seq:
     632 *   str.tr_s!(from_str, to_str)   -> str or nil
     633 *
     634 * Performs String#tr_s processing on str in place, returning
     635 * str, or nil if no changes were made.
     636 */
     637static mrb_value
     638mrb_str_tr_s_bang(mrb_state *mrb, mrb_value str)
     639{
     640  mrb_value p1, p2;
     641
     642  mrb_get_args(mrb, "SS", &p1, &p2);
     643  if (str_tr(mrb, str, p1, p2, TRUE)) {
     644    return str;
     645  }
     646  return mrb_nil_value();
     647}
     648
     649static mrb_bool
     650str_squeeze(mrb_state *mrb, mrb_value str, mrb_value v_pat)
     651{
     652  struct tr_pattern pat_storage = STATIC_TR_PATTERN;
     653  struct tr_pattern *pat = NULL;
     654  mrb_int i, j;
     655  char *s;
     656  mrb_int len;
     657  mrb_bool flag_changed = FALSE;
     658  mrb_int lastch = -1;
     659  uint8_t bitmap[32];
     660
     661  mrb_str_modify(mrb, mrb_str_ptr(str));
     662  if (!mrb_nil_p(v_pat)) {
     663    pat = tr_parse_pattern(mrb, &pat_storage, v_pat, TRUE);
     664    tr_compile_pattern(pat, v_pat, bitmap);
     665    tr_free_pattern(mrb, pat);
     666  }
     667  s = RSTRING_PTR(str);
     668  len = RSTRING_LEN(str);
     669
     670  if (pat) {
     671    for (i=j=0; i<len; i++,j++) {
     672      if (i>j) s[j] = s[i];
     673      if (tr_bitmap_detect(bitmap, s[i]) && s[i] == lastch) {
     674        flag_changed = TRUE;
     675        j--;
     676      }
     677      lastch = s[i];
     678    }
     679  }
     680  else {
     681    for (i=j=0; i<len; i++,j++) {
     682      if (i>j) s[j] = s[i];
     683      if (s[i] >= 0 && s[i] == lastch) {
     684        flag_changed = TRUE;
     685        j--;
     686      }
     687      lastch = s[i];
     688    }
     689  }
     690
     691  if (flag_changed) {
     692    RSTR_SET_LEN(RSTRING(str), j);
     693    RSTRING_PTR(str)[j] = 0;
     694  }
     695  return flag_changed;
     696}
     697
     698/*
     699 * call-seq:
     700 *   str.squeeze([other_str])    -> new_str
     701 *
     702 * Builds a set of characters from the other_str
     703 * parameter(s) using the procedure described for String#count. Returns a
     704 * new string where runs of the same character that occur in this set are
     705 * replaced by a single character. If no arguments are given, all runs of
     706 * identical characters are replaced by a single character.
     707 *
     708 *  "yellow moon".squeeze                  #=> "yelow mon"
     709 *  "  now   is  the".squeeze(" ")         #=> " now is the"
     710 *  "putters shoot balls".squeeze("m-z")   #=> "puters shot balls"
     711 */
     712static mrb_value
     713mrb_str_squeeze(mrb_state *mrb, mrb_value str)
     714{
     715  mrb_value pat = mrb_nil_value();
     716  mrb_value dup;
     717
     718  mrb_get_args(mrb, "|S", &pat);
     719  dup = mrb_str_dup(mrb, str);
     720  str_squeeze(mrb, dup, pat);
     721  return dup;
     722}
     723
     724/*
     725 * call-seq:
     726 *   str.squeeze!([other_str])   -> str or nil
     727 *
     728 * Squeezes str in place, returning either str, or nil if no
     729 * changes were made.
     730 */
     731static mrb_value
     732mrb_str_squeeze_bang(mrb_state *mrb, mrb_value str)
     733{
     734  mrb_value pat = mrb_nil_value();
     735
     736  mrb_get_args(mrb, "|S", &pat);
     737  if (str_squeeze(mrb, str, pat)) {
     738    return str;
     739  }
     740  return mrb_nil_value();
     741}
     742
     743static mrb_bool
     744str_delete(mrb_state *mrb, mrb_value str, mrb_value v_pat)
     745{
     746  struct tr_pattern pat = STATIC_TR_PATTERN;
     747  mrb_int i, j;
     748  char *s;
     749  mrb_int len;
     750  mrb_bool flag_changed = FALSE;
     751  uint8_t bitmap[32];
     752
     753  mrb_str_modify(mrb, mrb_str_ptr(str));
     754  tr_parse_pattern(mrb, &pat, v_pat, TRUE);
     755  tr_compile_pattern(&pat, v_pat, bitmap);
     756  tr_free_pattern(mrb, &pat);
     757
     758  s = RSTRING_PTR(str);
     759  len = RSTRING_LEN(str);
     760
     761  for (i=j=0; i<len; i++,j++) {
     762    if (i>j) s[j] = s[i];
     763    if (tr_bitmap_detect(bitmap, s[i])) {
     764      flag_changed = TRUE;
     765      j--;
     766    }
     767  }
     768  if (flag_changed) {
     769    RSTR_SET_LEN(RSTRING(str), j);
     770    RSTRING_PTR(str)[j] = 0;
     771  }
     772  return flag_changed;
     773}
     774
     775static mrb_value
     776mrb_str_delete(mrb_state *mrb, mrb_value str)
     777{
     778  mrb_value pat;
     779  mrb_value dup;
     780
     781  mrb_get_args(mrb, "S", &pat);
     782  dup = mrb_str_dup(mrb, str);
     783  str_delete(mrb, dup, pat);
     784  return dup;
     785}
     786
     787static mrb_value
     788mrb_str_delete_bang(mrb_state *mrb, mrb_value str)
     789{
     790  mrb_value pat;
     791
     792  mrb_get_args(mrb, "S", &pat);
     793  if (str_delete(mrb, str, pat)) {
     794    return str;
     795  }
     796  return mrb_nil_value();
     797}
     798
     799/*
     800 * call_seq:
     801 *   str.count([other_str])   -> integer
     802 *
     803 * Each other_str parameter defines a set of characters to count.  The
     804 * intersection of these sets defines the characters to count in str.  Any
     805 * other_str that starts with a caret ^ is negated.  The sequence c1-c2
     806 * means all characters between c1 and c2.  The backslash character \ can
     807 * be used to escape ^ or - and is otherwise ignored unless it appears at
     808 * the end of a sequence or the end of a other_str.
     809 */
     810static mrb_value
     811mrb_str_count(mrb_state *mrb, mrb_value str)
     812{
     813  mrb_value v_pat = mrb_nil_value();
     814  mrb_int i;
     815  char *s;
     816  mrb_int len;
     817  mrb_int count = 0;
     818  struct tr_pattern pat = STATIC_TR_PATTERN;
     819  uint8_t bitmap[32];
     820
     821  mrb_get_args(mrb, "S", &v_pat);
     822  tr_parse_pattern(mrb, &pat, v_pat, TRUE);
     823  tr_compile_pattern(&pat, v_pat, bitmap);
     824  tr_free_pattern(mrb, &pat);
     825
     826  s = RSTRING_PTR(str);
     827  len = RSTRING_LEN(str);
     828  for (i = 0; i < len; i++) {
     829    if (tr_bitmap_detect(bitmap, s[i])) count++;
     830  }
     831  return mrb_fixnum_value(count);
     832}
     833
    235834static mrb_value
    236835mrb_str_hex(mrb_state *mrb, mrb_value self)
     
    260859}
    261860
    262 static mrb_value
    263 mrb_fixnum_chr(mrb_state *mrb, mrb_value num)
    264 {
    265   mrb_int cp = mrb_fixnum(num);
     861/*
     862 *  call-seq:
     863 *     int.chr([encoding])  ->  string
     864 *
     865 *  Returns a string containing the character represented by the +int+'s value
     866 *  according to +encoding+. +"ASCII-8BIT"+ (+"BINARY"+) and +"UTF-8"+ (only
     867 *  with +MRB_UTF8_STRING+) can be specified as +encoding+ (default is
     868 *  +"ASCII-8BIT"+).
     869 *
     870 *     65.chr                  #=> "A"
     871 *     230.chr                 #=> "\xE6"
     872 *     230.chr("ASCII-8BIT")   #=> "\xE6"
     873 *     230.chr("UTF-8")        #=> "\u00E6"
     874 */
     875static mrb_value
     876mrb_int_chr(mrb_state *mrb, mrb_value num)
     877{
     878  mrb_value enc;
     879  mrb_bool enc_given;
     880
     881  mrb_get_args(mrb, "|S?", &enc, &enc_given);
     882  if (!enc_given ||
     883      ENC_COMP_P(enc, ENC_ASCII_8BIT) ||
     884      ENC_COMP_P(enc, ENC_BINARY)) {
     885    return int_chr_binary(mrb, num);
     886  }
    266887#ifdef MRB_UTF8_STRING
    267   char utf8[4];
    268   mrb_int len;
    269 
    270   if (cp < 0 || 0x10FFFF < cp) {
    271     mrb_raisef(mrb, E_RANGE_ERROR, "%S out of char range", num);
    272   }
    273   if (cp < 0x80) {
    274     utf8[0] = (char)cp;
    275     len = 1;
    276   }
    277   else if (cp < 0x800) {
    278     utf8[0] = (char)(0xC0 | (cp >> 6));
    279     utf8[1] = (char)(0x80 | (cp & 0x3F));
    280     len = 2;
    281   }
    282   else if (cp < 0x10000) {
    283     utf8[0] = (char)(0xE0 |  (cp >> 12));
    284     utf8[1] = (char)(0x80 | ((cp >>  6) & 0x3F));
    285     utf8[2] = (char)(0x80 | ( cp        & 0x3F));
    286     len = 3;
    287   }
     888  else if (ENC_COMP_P(enc, ENC_UTF8)) {
     889    return int_chr_utf8(mrb, num);
     890  }
     891#endif
    288892  else {
    289     utf8[0] = (char)(0xF0 |  (cp >> 18));
    290     utf8[1] = (char)(0x80 | ((cp >> 12) & 0x3F));
    291     utf8[2] = (char)(0x80 | ((cp >>  6) & 0x3F));
    292     utf8[3] = (char)(0x80 | ( cp        & 0x3F));
    293     len = 4;
    294   }
    295   return mrb_str_new(mrb, utf8, len);
    296 #else
    297   char c;
    298 
    299   if (cp < 0 || 0xff < cp) {
    300     mrb_raisef(mrb, E_RANGE_ERROR, "%S out of char range", num);
    301   }
    302   c = (char)cp;
    303   return mrb_str_new(mrb, &c, 1);
    304 #endif
    305 }
    306 
    307 /*
    308  *  call-seq:
    309  *     string.lines    ->  array of string
    310  *
    311  *  Returns strings per line;
    312  *
    313  *     a = "abc\ndef"
    314  *     a.lines    #=> ["abc\n", "def"]
    315  */
    316 static mrb_value
    317 mrb_str_lines(mrb_state *mrb, mrb_value self)
    318 {
    319   mrb_value result;
    320   mrb_value blk;
    321   int ai;
    322   mrb_int len;
    323   mrb_value arg;
    324   char *b = RSTRING_PTR(self);
    325   char *p = b, *t;
    326   char *e = b + RSTRING_LEN(self);
    327 
    328   mrb_get_args(mrb, "&", &blk);
    329 
    330   result = mrb_ary_new(mrb);
    331   ai = mrb_gc_arena_save(mrb);
    332   if (!mrb_nil_p(blk)) {
    333     while (p < e) {
    334       t = p;
    335       while (p < e && *p != '\n') p++;
    336       if (*p == '\n') p++;
    337       len = (mrb_int) (p - t);
    338       arg = mrb_str_new(mrb, t, len);
    339       mrb_yield_argv(mrb, blk, 1, &arg);
    340       mrb_gc_arena_restore(mrb, ai);
    341       if (b != RSTRING_PTR(self)) {
    342         ptrdiff_t diff = p - b;
    343         b = RSTRING_PTR(self);
    344         p = b + diff;
    345       }
    346       e = b + RSTRING_LEN(self);
    347     }
    348     return self;
    349   }
    350   while (p < e) {
    351     t = p;
    352     while (p < e && *p != '\n') p++;
    353     if (*p == '\n') p++;
    354     len = (mrb_int) (p - t);
    355     mrb_ary_push(mrb, result, mrb_str_new(mrb, t, len));
    356     mrb_gc_arena_restore(mrb, ai);
    357   }
    358   return result;
     893    mrb_raisef(mrb, E_ARGUMENT_ERROR, "unknown encoding name - %v", enc);
     894  }
     895  /* not reached */
     896  return mrb_nil_value();
    359897}
    360898
     
    5221060#endif
    5231061
    524 static mrb_bool
    525 all_digits_p(const char *s, mrb_int len)
    526 {
    527   while (len-- > 0) {
    528     if (!ISDIGIT(*s)) return FALSE;
    529     s++;
    530   }
    531   return TRUE;
    532 }
    533 
    5341062/*
    5351063 *  call-seq:
    536  *     str.upto(other_str, exclusive=false) {|s| block }   -> str
    537  *     str.upto(other_str, exclusive=false)                -> an_enumerator
    538  *
    539  *  Iterates through successive values, starting at <i>str</i> and
    540  *  ending at <i>other_str</i> inclusive, passing each value in turn to
    541  *  the block. The <code>String#succ</code> method is used to generate
    542  *  each value.  If optional second argument exclusive is omitted or is false,
    543  *  the last value will be included; otherwise it will be excluded.
    544  *
    545  *  If no block is given, an enumerator is returned instead.
    546  *
    547  *     "a8".upto("b6") {|s| print s, ' ' }
    548  *     for s in "a8".."b6"
    549  *       print s, ' '
    550  *     end
    551  *
    552  *  <em>produces:</em>
    553  *
    554  *     a8 a9 b0 b1 b2 b3 b4 b5 b6
    555  *     a8 a9 b0 b1 b2 b3 b4 b5 b6
    556  *
    557  *  If <i>str</i> and <i>other_str</i> contains only ascii numeric characters,
    558  *  both are recognized as decimal numbers. In addition, the width of
    559  *  string (e.g. leading zeros) is handled appropriately.
    560  *
    561  *     "9".upto("11").to_a   #=> ["9", "10", "11"]
    562  *     "25".upto("5").to_a   #=> []
    563  *     "07".upto("11").to_a  #=> ["07", "08", "09", "10", "11"]
    564  */
    565 static mrb_value
    566 mrb_str_upto(mrb_state *mrb, mrb_value beg)
    567 {
    568   mrb_value end;
    569   mrb_value exclusive = mrb_false_value();
    570   mrb_value block = mrb_nil_value();
    571   mrb_value current, after_end;
    572   mrb_int n;
    573   mrb_bool excl;
    574 
    575   mrb_get_args(mrb, "o|o&", &end, &exclusive, &block);
    576 
    577   if (mrb_nil_p(block)) {
    578     return mrb_funcall(mrb, beg, "to_enum", 3, mrb_symbol_value(mrb_intern_lit(mrb, "upto")), end, exclusive);
    579   }
    580   end = mrb_string_type(mrb, end);
    581   excl = mrb_test(exclusive);
    582 
    583   /* single character */
    584   if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1 &&
    585   ISASCII(RSTRING_PTR(beg)[0]) && ISASCII(RSTRING_PTR(end)[0])) {
    586     char c = RSTRING_PTR(beg)[0];
    587     char e = RSTRING_PTR(end)[0];
    588     int ai = mrb_gc_arena_save(mrb);
    589 
    590     if (c > e || (excl && c == e)) return beg;
    591     for (;;) {
    592       mrb_yield(mrb, block, mrb_str_new(mrb, &c, 1));
    593       mrb_gc_arena_restore(mrb, ai);
    594       if (!excl && c == e) break;
    595       c++;
    596       if (excl && c == e) break;
    597     }
    598     return beg;
    599   }
    600   /* both edges are all digits */
    601   if (ISDIGIT(RSTRING_PTR(beg)[0]) && ISDIGIT(RSTRING_PTR(end)[0]) &&
    602       all_digits_p(RSTRING_PTR(beg), RSTRING_LEN(beg)) &&
    603       all_digits_p(RSTRING_PTR(end), RSTRING_LEN(end))) {
    604     int ai = mrb_gc_arena_save(mrb);
    605     mrb_int min_width = RSTRING_LEN(beg);
    606     mrb_int max_width = RSTRING_LEN(end);
    607     mrb_int bi = mrb_int(mrb, mrb_str_to_inum(mrb, beg, 10, FALSE));
    608     mrb_int ei = mrb_int(mrb, mrb_str_to_inum(mrb, end, 10, FALSE));
    609     mrb_value str = mrb_str_new(mrb, NULL, max_width);
    610     char *buf = RSTRING_PTR(str);
    611 
    612     while (bi <= ei) {
    613       if (excl && bi == ei) break;
    614       snprintf(buf, max_width+1, "%.*" MRB_PRId, (int)min_width, bi);
    615       mrb_yield(mrb, block, mrb_str_new(mrb, buf, strlen(buf)));
    616       mrb_gc_arena_restore(mrb, ai);
    617       bi++;
    618     }
    619 
    620     return beg;
    621   }
    622   /* normal case */
    623   n = mrb_int(mrb, mrb_funcall(mrb, beg, "<=>", 1, end));
    624   if (n > 0 || (excl && n == 0)) return beg;
    625 
    626   after_end = mrb_funcall(mrb, end, "succ", 0);
    627   current = mrb_str_dup(mrb, beg);
    628   while (!mrb_str_equal(mrb, current, after_end)) {
    629     int ai = mrb_gc_arena_save(mrb);
    630     mrb_value next = mrb_nil_value();
    631     if (excl || !mrb_str_equal(mrb, current, end))
    632       next = mrb_funcall(mrb, current, "succ", 0);
    633     mrb_yield(mrb, block, current);
    634     if (mrb_nil_p(next)) break;
    635     current = mrb_str_to_str(mrb, next);
    636     if (excl && mrb_str_equal(mrb, current, end)) break;
    637     if (RSTRING_LEN(current) > RSTRING_LEN(end) || RSTRING_LEN(current) == 0)
    638       break;
     1064 *     str.delete_prefix!(prefix) -> self or nil
     1065 *
     1066 *  Deletes leading <code>prefix</code> from <i>str</i>, returning
     1067 *  <code>nil</code> if no change was made.
     1068 *
     1069 *     "hello".delete_prefix!("hel") #=> "lo"
     1070 *     "hello".delete_prefix!("llo") #=> nil
     1071 */
     1072static mrb_value
     1073mrb_str_del_prefix_bang(mrb_state *mrb, mrb_value self)
     1074{
     1075  mrb_int plen, slen;
     1076  char *ptr, *s;
     1077  struct RString *str = RSTRING(self);
     1078
     1079  mrb_get_args(mrb, "s", &ptr, &plen);
     1080  slen = RSTR_LEN(str);
     1081  if (plen > slen) return mrb_nil_value();
     1082  s = RSTR_PTR(str);
     1083  if (memcmp(s, ptr, plen) != 0) return mrb_nil_value();
     1084  if (!mrb_frozen_p(str) && (RSTR_SHARED_P(str) || RSTR_FSHARED_P(str))) {
     1085    str->as.heap.ptr += plen;
     1086  }
     1087  else {
     1088    mrb_str_modify(mrb, str);
     1089    s = RSTR_PTR(str);
     1090    memmove(s, s+plen, slen-plen);
     1091  }
     1092  RSTR_SET_LEN(str, slen-plen);
     1093  return self;
     1094}
     1095
     1096/*
     1097 *  call-seq:
     1098 *     str.delete_prefix(prefix) -> new_str
     1099 *
     1100 *  Returns a copy of <i>str</i> with leading <code>prefix</code> deleted.
     1101 *
     1102 *     "hello".delete_prefix("hel") #=> "lo"
     1103 *     "hello".delete_prefix("llo") #=> "hello"
     1104 */
     1105static mrb_value
     1106mrb_str_del_prefix(mrb_state *mrb, mrb_value self)
     1107{
     1108  mrb_int plen, slen;
     1109  char *ptr;
     1110
     1111  mrb_get_args(mrb, "s", &ptr, &plen);
     1112  slen = RSTRING_LEN(self);
     1113  if (plen > slen) return mrb_str_dup(mrb, self);
     1114  if (memcmp(RSTRING_PTR(self), ptr, plen) != 0)
     1115    return mrb_str_dup(mrb, self);
     1116  return mrb_str_substr(mrb, self, plen, slen-plen);
     1117}
     1118
     1119/*
     1120 *  call-seq:
     1121 *     str.delete_suffix!(suffix) -> self or nil
     1122 *
     1123 *  Deletes trailing <code>suffix</code> from <i>str</i>, returning
     1124 *  <code>nil</code> if no change was made.
     1125 *
     1126 *     "hello".delete_suffix!("llo") #=> "he"
     1127 *     "hello".delete_suffix!("hel") #=> nil
     1128 */
     1129static mrb_value
     1130mrb_str_del_suffix_bang(mrb_state *mrb, mrb_value self)
     1131{
     1132  mrb_int plen, slen;
     1133  char *ptr, *s;
     1134  struct RString *str = RSTRING(self);
     1135
     1136  mrb_get_args(mrb, "s", &ptr, &plen);
     1137  slen = RSTR_LEN(str);
     1138  if (plen > slen) return mrb_nil_value();
     1139  s = RSTR_PTR(str);
     1140  if (memcmp(s+slen-plen, ptr, plen) != 0) return mrb_nil_value();
     1141  if (!mrb_frozen_p(str) && (RSTR_SHARED_P(str) || RSTR_FSHARED_P(str))) {
     1142    /* no need to modify string */
     1143  }
     1144  else {
     1145    mrb_str_modify(mrb, str);
     1146  }
     1147  RSTR_SET_LEN(str, slen-plen);
     1148  return self;
     1149}
     1150
     1151/*
     1152 *  call-seq:
     1153 *     str.delete_suffix(suffix) -> new_str
     1154 *
     1155 *  Returns a copy of <i>str</i> with leading <code>suffix</code> deleted.
     1156 *
     1157 *     "hello".delete_suffix("hel") #=> "lo"
     1158 *     "hello".delete_suffix("llo") #=> "hello"
     1159 */
     1160static mrb_value
     1161mrb_str_del_suffix(mrb_state *mrb, mrb_value self)
     1162{
     1163  mrb_int plen, slen;
     1164  char *ptr;
     1165
     1166  mrb_get_args(mrb, "s", &ptr, &plen);
     1167  slen = RSTRING_LEN(self);
     1168  if (plen > slen) return mrb_str_dup(mrb, self);
     1169  if (memcmp(RSTRING_PTR(self)+slen-plen, ptr, plen) != 0)
     1170    return mrb_str_dup(mrb, self);
     1171  return mrb_str_substr(mrb, self, 0, slen-plen);
     1172}
     1173
     1174static mrb_value
     1175mrb_str_lines(mrb_state *mrb, mrb_value self)
     1176{
     1177  mrb_value result;
     1178  int ai;
     1179  mrb_int len;
     1180  char *b = RSTRING_PTR(self);
     1181  char *p = b, *t;
     1182  char *e = b + RSTRING_LEN(self);
     1183
     1184  result = mrb_ary_new(mrb);
     1185  ai = mrb_gc_arena_save(mrb);
     1186  while (p < e) {
     1187    t = p;
     1188    while (p < e && *p != '\n') p++;
     1189    if (*p == '\n') p++;
     1190    len = (mrb_int) (p - t);
     1191    mrb_ary_push(mrb, result, mrb_str_new(mrb, t, len));
    6391192    mrb_gc_arena_restore(mrb, ai);
    6401193  }
    641 
    642   return beg;
     1194  return result;
    6431195}
    6441196
     
    6491201
    6501202  mrb_define_method(mrb, s, "dump",            mrb_str_dump,            MRB_ARGS_NONE());
    651   mrb_define_method(mrb, s, "getbyte",         mrb_str_getbyte,         MRB_ARGS_REQ(1));
    652   mrb_define_method(mrb, s, "setbyte",         mrb_str_setbyte,         MRB_ARGS_REQ(2));
    653   mrb_define_method(mrb, s, "byteslice",       mrb_str_byteslice,       MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
    6541203  mrb_define_method(mrb, s, "swapcase!",       mrb_str_swapcase_bang,   MRB_ARGS_NONE());
    6551204  mrb_define_method(mrb, s, "swapcase",        mrb_str_swapcase,        MRB_ARGS_NONE());
    656   mrb_define_method(mrb, s, "concat",          mrb_str_concat2,         MRB_ARGS_REQ(1));
    657   mrb_define_method(mrb, s, "<<",              mrb_str_concat2,         MRB_ARGS_REQ(1));
     1205  mrb_define_method(mrb, s, "concat",          mrb_str_concat_m,        MRB_ARGS_REQ(1));
     1206  mrb_define_method(mrb, s, "<<",              mrb_str_concat_m,        MRB_ARGS_REQ(1));
     1207  mrb_define_method(mrb, s, "count",           mrb_str_count,           MRB_ARGS_REQ(1));
     1208  mrb_define_method(mrb, s, "tr",              mrb_str_tr,              MRB_ARGS_REQ(2));
     1209  mrb_define_method(mrb, s, "tr!",             mrb_str_tr_bang,         MRB_ARGS_REQ(2));
     1210  mrb_define_method(mrb, s, "tr_s",            mrb_str_tr_s,            MRB_ARGS_REQ(2));
     1211  mrb_define_method(mrb, s, "tr_s!",           mrb_str_tr_s_bang,       MRB_ARGS_REQ(2));
     1212  mrb_define_method(mrb, s, "squeeze",         mrb_str_squeeze,         MRB_ARGS_OPT(1));
     1213  mrb_define_method(mrb, s, "squeeze!",        mrb_str_squeeze_bang,    MRB_ARGS_OPT(1));
     1214  mrb_define_method(mrb, s, "delete",          mrb_str_delete,          MRB_ARGS_REQ(1));
     1215  mrb_define_method(mrb, s, "delete!",         mrb_str_delete_bang,     MRB_ARGS_REQ(1));
    6581216  mrb_define_method(mrb, s, "start_with?",     mrb_str_start_with,      MRB_ARGS_REST());
    6591217  mrb_define_method(mrb, s, "end_with?",       mrb_str_end_with,        MRB_ARGS_REST());
     
    6611219  mrb_define_method(mrb, s, "oct",             mrb_str_oct,             MRB_ARGS_NONE());
    6621220  mrb_define_method(mrb, s, "chr",             mrb_str_chr,             MRB_ARGS_NONE());
    663   mrb_define_method(mrb, s, "lines",           mrb_str_lines,           MRB_ARGS_NONE());
    6641221  mrb_define_method(mrb, s, "succ",            mrb_str_succ,            MRB_ARGS_NONE());
    6651222  mrb_define_method(mrb, s, "succ!",           mrb_str_succ_bang,       MRB_ARGS_NONE());
    666   mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next"), mrb_intern_lit(mrb, "succ"));
    667   mrb_alias_method(mrb, s, mrb_intern_lit(mrb, "next!"), mrb_intern_lit(mrb, "succ!"));
    668   mrb_define_method(mrb, s, "ord", mrb_str_ord, MRB_ARGS_NONE());
    669   mrb_define_method(mrb, s, "upto", mrb_str_upto, MRB_ARGS_ANY());
    670 
    671   mrb_define_method(mrb, mrb->fixnum_class, "chr", mrb_fixnum_chr, MRB_ARGS_NONE());
     1223  mrb_define_method(mrb, s, "next",            mrb_str_succ,            MRB_ARGS_NONE());
     1224  mrb_define_method(mrb, s, "next!",           mrb_str_succ_bang,       MRB_ARGS_NONE());
     1225  mrb_define_method(mrb, s, "ord",             mrb_str_ord,             MRB_ARGS_NONE());
     1226  mrb_define_method(mrb, s, "delete_prefix!",  mrb_str_del_prefix_bang, MRB_ARGS_REQ(1));
     1227  mrb_define_method(mrb, s, "delete_prefix",   mrb_str_del_prefix,      MRB_ARGS_REQ(1));
     1228  mrb_define_method(mrb, s, "delete_suffix!",  mrb_str_del_suffix_bang, MRB_ARGS_REQ(1));
     1229  mrb_define_method(mrb, s, "delete_suffix",   mrb_str_del_suffix,      MRB_ARGS_REQ(1));
     1230
     1231  mrb_define_method(mrb, s, "__lines",         mrb_str_lines,           MRB_ARGS_NONE());
     1232
     1233  mrb_define_method(mrb, mrb_module_get(mrb, "Integral"), "chr", mrb_int_chr, MRB_ARGS_OPT(1));
    6721234}
    6731235
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-string-ext/test/string.rb

    r331 r439  
     1# coding: utf-8
    12##
    23# String(Ext) Test
    34
    4 UTF8STRING = ("\343\201\202".size == 1)
    5 
    6 assert('String.try_convert') do
    7   assert_nil String.try_convert(nil)
    8   assert_nil String.try_convert(:foo)
    9   assert_equal "", String.try_convert("")
    10   assert_equal "1,2,3", String.try_convert("1,2,3")
    11 end
    12 
    13 assert('String#getbyte') do
    14   str1 = "hello"
    15   bytes1 = [104, 101, 108, 108, 111]
    16   assert_equal bytes1[0], str1.getbyte(0)
    17   assert_equal bytes1[-1], str1.getbyte(-1)
    18   assert_equal bytes1[6], str1.getbyte(6)
    19 
    20   str2 = "\xFF"
    21   bytes2 = [0xFF]
    22   assert_equal bytes2[0], str2.getbyte(0)
    23 end
    24 
    25 assert('String#setbyte') do
    26   str1 = "hello"
    27   h = "H".getbyte(0)
    28   str1.setbyte(0, h)
    29   assert_equal(h, str1.getbyte(0))
    30   assert_equal("Hello", str1)
    31 end
    32 
    33 assert("String#setbyte raises IndexError if arg conversion resizes String") do
    34   $s = "01234\n"
    35   class Tmp
    36       def to_i
    37           $s.chomp! ''
    38           95
    39       end
    40   end
    41   tmp = Tmp.new
    42   assert_raise(IndexError) { $s.setbyte(5, tmp) }
    43 end
    44 
    45 assert('String#byteslice') do
    46   str1 = "hello"
    47   assert_equal("e", str1.byteslice(1))
    48   assert_equal("o", str1.byteslice(-1))
    49   assert_equal("ell", str1.byteslice(1..3))
    50   assert_equal("el", str1.byteslice(1...3))
     5UTF8STRING = __ENCODING__ == "UTF-8"
     6
     7def assert_upto(exp, receiver, *args)
     8  act = []
     9  receiver.upto(*args) { |v| act << v }
     10  assert_equal exp, act
    5111end
    5212
    5313assert('String#dump') do
    54   ("\1" * 100).dump     # should not raise an exception - regress #1210
    55   "\0".inspect == "\"\\000\"" and
    56   "foo".dump == "\"foo\""
     14  assert_equal("\"\\x00\"", "\0".dump)
     15  assert_equal("\"foo\"", "foo".dump)
     16  assert_equal('"\xe3\x82\x8b"', "る".dump)
     17  assert_nothing_raised { ("\1" * 100).dump }   # regress #1210
    5718end
    5819
    5920assert('String#strip') do
    6021  s = "  abc  "
    61   "".strip == "" and " \t\r\n\f\v".strip == "" and
    62   "\0a\0".strip == "\0a" and
    63   "abc".strip     == "abc" and
    64   "  abc".strip   == "abc" and
    65   "abc  ".strip   == "abc" and
    66   "  abc  ".strip == "abc" and
    67   s == "  abc  "
     22  assert_equal("abc", s.strip)
     23  assert_equal("  abc  ", s)
     24  assert_equal("", "".strip)
     25  assert_equal("", " \t\r\n\f\v".strip)
     26  assert_equal("\0a", "\0a\0".strip)
     27  assert_equal("abc", "abc".strip)
     28  assert_equal("abc", "  abc".strip)
     29  assert_equal("abc", "abc  ".strip)
    6830end
    6931
    7032assert('String#lstrip') do
    7133  s = "  abc  "
    72   s.lstrip
    73   "".lstrip == "" and " \t\r\n\f\v".lstrip == "" and
    74   "\0a\0".lstrip == "\0a\0" and
    75   "abc".lstrip     == "abc"   and
    76   "  abc".lstrip   == "abc"   and
    77   "abc  ".lstrip   == "abc  " and
    78   "  abc  ".lstrip == "abc  " and
    79   s == "  abc  "
     34  assert_equal("abc  ", s.lstrip)
     35  assert_equal("  abc  ", s)
     36  assert_equal("", "".lstrip)
     37  assert_equal("", " \t\r\n\f\v".lstrip)
     38  assert_equal("\0a\0", "\0a\0".lstrip)
     39  assert_equal("abc", "abc".lstrip)
     40  assert_equal("abc", "  abc".lstrip)
     41  assert_equal("abc  ", "abc  ".lstrip)
    8042end
    8143
    8244assert('String#rstrip') do
    8345  s = "  abc  "
    84   s.rstrip
    85   "".rstrip == "" and " \t\r\n\f\v".rstrip == "" and
    86   "\0a\0".rstrip == "\0a" and
    87   "abc".rstrip     == "abc"   and
    88   "  abc".rstrip   == "  abc" and
    89   "abc  ".rstrip   == "abc"   and
    90   "  abc  ".rstrip == "  abc" and
    91   s == "  abc  "
     46  assert_equal("  abc", s.rstrip)
     47  assert_equal("  abc  ", s)
     48  assert_equal("", "".rstrip)
     49  assert_equal("", " \t\r\n\f\v".rstrip)
     50  assert_equal("\0a", "\0a\0".rstrip)
     51  assert_equal("abc", "abc".rstrip)
     52  assert_equal("  abc", "  abc".rstrip)
     53  assert_equal("abc", "abc  ".rstrip)
    9254end
    9355
     
    9557  s = "  abc  "
    9658  t = "abc"
    97   s.strip! == "abc" and s == "abc" and t.strip! == nil
     59  assert_equal("abc", s.strip!)
     60  assert_equal("abc", s)
     61  assert_nil(t.strip!)
     62  assert_equal("abc", t)
    9863end
    9964
     
    10166  s = "  abc  "
    10267  t = "abc  "
    103   s.lstrip! == "abc  " and s == "abc  " and t.lstrip! == nil
     68  assert_equal("abc  ", s.lstrip!)
     69  assert_equal("abc  ", s)
     70  assert_nil(t.lstrip!)
     71  assert_equal("abc  ", t)
    10472end
    10573
     
    10775  s = "  abc  "
    10876  t = "  abc"
    109   s.rstrip! == "  abc" and s == "  abc" and t.rstrip! == nil
     77  assert_equal("  abc", s.rstrip!)
     78  assert_equal("  abc", s)
     79  assert_nil(t.rstrip!)
     80  assert_equal("  abc", t)
    11081end
    11182
     
    12596  assert_equal "Hello World!", "Hello " << "World" << 33
    12697  assert_equal "Hello World!", "Hello ".concat("World").concat(33)
    127 
    128   o = Object.new
    129   def o.to_str
    130     "to_str"
    131   end
    132   assert_equal "hi to_str", "hi " << o
    133 
    13498  assert_raise(TypeError) { "".concat(Object.new) }
     99
     100  if UTF8STRING
     101    assert_equal "H«", "H" << 0xab
     102    assert_equal "Hは", "H" << 12399
     103  else
     104    assert_equal "H\xab", "H" << 0xab
     105    assert_raise(RangeError) { "H" << 12399 }
     106  end
    135107end
    136108
     
    140112  assert_equal(-1, "abcdef".casecmp("abcdefg"))
    141113  assert_equal 0, "abcdef".casecmp("ABCDEF")
    142   o = Object.new
    143   def o.to_str
    144     "ABCDEF"
    145   end
    146   assert_equal 0, "abcdef".casecmp(o)
     114end
     115
     116assert('String#count') do
     117  s = "abccdeff123"
     118  assert_equal 0, s.count("")
     119  assert_equal 1, s.count("a")
     120  assert_equal 2, s.count("ab")
     121  assert_equal 9, s.count("^c")
     122  assert_equal 8, s.count("a-z")
     123  assert_equal 4, s.count("a0-9")
     124end
     125
     126assert('String#tr') do
     127  assert_equal "ABC", "abc".tr('a-z', 'A-Z')
     128  assert_equal "hippo", "hello".tr('el', 'ip')
     129  assert_equal "Ruby", "Lisp".tr("Lisp", "Ruby")
     130  assert_equal "*e**o", "hello".tr('^aeiou', '*')
     131  assert_equal "heo", "hello".tr('l', '')
     132end
     133
     134assert('String#tr!') do
     135  s = "abcdefghijklmnopqR"
     136  assert_equal "ab12222hijklmnopqR", s.tr!("cdefg", "12")
     137  assert_equal "ab12222hijklmnopqR", s
     138end
     139
     140assert('String#tr_s') do
     141  assert_equal "hero", "hello".tr_s('l', 'r')
     142  assert_equal "h*o", "hello".tr_s('el', '*')
     143  assert_equal "hhxo", "hello".tr_s('el', 'hx')
     144end
     145
     146assert('String#tr_s!') do
     147  s = "hello"
     148  assert_equal "hero", s.tr_s!('l', 'r')
     149  assert_equal "hero", s
     150  assert_nil s.tr_s!('l', 'r')
     151end
     152
     153assert('String#squeeze') do
     154  assert_equal "yelow mon", "yellow moon".squeeze
     155  assert_equal " now is the", "  now   is  the".squeeze(" ")
     156  assert_equal "puters shot balls", "putters shoot balls".squeeze("m-z")
     157end
     158
     159assert('String#squeeze!') do
     160  s = "  now   is  the"
     161  assert_equal " now is the", s.squeeze!(" ")
     162  assert_equal " now is the", s
     163end
     164
     165assert('String#delete') do
     166  assert_equal "he", "hello".delete("lo")
     167  assert_equal "hll", "hello".delete("aeiou")
     168  assert_equal "ll", "hello".delete("^l")
     169  assert_equal "ho", "hello".delete("ej-m")
     170end
     171
     172assert('String#delete!') do
     173  s = "hello"
     174  assert_equal "he", s.delete!("lo")
     175  assert_equal "he", s
     176  assert_nil s.delete!("lz")
    147177end
    148178
     
    202232  assert_equal 8, "010".oct
    203233  assert_equal (-8), "-10".oct
    204 end
    205 
    206 assert('String#chr') do
    207   assert_equal "a", "abcde".chr
    208   # test Fixnum#chr as well
    209   assert_equal "a", 97.chr
    210234end
    211235
     
    496520
    497521assert('String#upto') do
    498   assert_equal %w(a8 a9 b0 b1 b2 b3 b4 b5 b6), "a8".upto("b6").to_a
    499   assert_equal ["9", "10", "11"], "9".upto("11").to_a
    500   assert_equal [], "25".upto("5").to_a
    501   assert_equal ["07", "08", "09", "10", "11"], "07".upto("11").to_a
    502 
    503 if UTF8STRING
    504   assert_equal ["あ", "ぃ", "い", "ぅ", "う", "ぇ", "え", "ぉ", "お"], "あ".upto("お").to_a
    505 end
    506 
    507   assert_equal ["9", ":", ";", "<", "=", ">", "?", "@", "A"], "9".upto("A").to_a
     522  assert_upto %w(a8 a9 b0 b1 b2 b3 b4 b5 b6), "a8", "b6"
     523  assert_upto ["9", "10", "11"], "9", "11"
     524  assert_upto [], "25", "5"
     525  assert_upto ["07", "08", "09", "10", "11"], "07", "11"
     526  assert_upto ["9", ":", ";", "<", "=", ">", "?", "@", "A"], "9", "A"
     527
     528  if UTF8STRING
     529    assert_upto %w(あ ぃ い ぅ う ぇ え ぉ お), "あ", "お"
     530  end
    508531
    509532  a     = "aa"
     
    587610
    588611assert('String#chr') do
     612  assert_equal "a", "abcde".chr
    589613  assert_equal "h", "hello!".chr
    590 end
     614  assert_equal "", "".chr
     615end
     616
    591617assert('String#chr(UTF-8)') do
    592618  assert_equal "こ", "こんにちは世界!".chr
     
    614640
    615641assert('String#each_char') do
    616   s = ""
     642  chars = []
    617643  "hello!".each_char do |x|
    618     s += x
    619   end
    620   assert_equal "hello!", s
     644    chars << x
     645  end
     646  assert_equal ["h", "e", "l", "l", "o", "!"], chars
    621647end
    622648
    623649assert('String#each_char(UTF-8)') do
    624   s = ""
     650  chars = []
    625651  "こんにちは世界!".each_char do |x|
    626     s += x
    627   end
    628   assert_equal "こんにちは世界!", s
     652    chars << x
     653  end
     654  assert_equal ["こ", "ん", "に", "ち", "は", "世", "界", "!"], chars
    629655end if UTF8STRING
    630656
     
    666692  assert_equal expect, cp
    667693end if UTF8STRING
     694
     695assert('String#delete_prefix') do
     696  assert_equal "llo", "hello".delete_prefix("he")
     697  assert_equal "hello", "hello".delete_prefix("llo")
     698  assert_equal "llo", "hello".delete_prefix!("he")
     699  assert_nil "hello".delete_prefix!("llo")
     700end
     701
     702assert('String#delete_suffix') do
     703  assert_equal "he", "hello".delete_suffix("llo")
     704  assert_equal "hello", "hello".delete_suffix("he")
     705  assert_equal "he", "hello".delete_suffix!("llo")
     706  assert_nil "hello".delete_suffix!("he")
     707end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-struct/mrblib/struct.rb

    r331 r439  
    4747    end
    4848
    49     def _inspect
     49    def _inspect(recur_list)
     50      return "#<struct #{self.class}:...>" if recur_list[self.object_id]
     51      recur_list[self.object_id] = true
    5052      name = self.class.to_s
    5153      if name[0] == "#"
     
    5658      buf = []
    5759      self.each_pair do |k,v|
    58         buf.push [k.to_s + "=" + v._inspect]
     60        buf.push k.to_s + "=" + v._inspect(recur_list)
    5961      end
    6062      str + buf.join(", ") + ">"
     
    7173    #
    7274    def inspect
    73       begin
    74         self._inspect
    75       rescue SystemStackError
    76         "#<struct #{self.class.to_s}:...>"
    77       end
     75      self._inspect({})
    7876    end
    7977
     
    8280    #
    8381    alias to_s inspect
    84   end
    8582
    86   ##
    87   # call-seq:
    88   #   hsh.dig(key,...)                 -> object
    89   #
    90   # Extracts the nested value specified by the sequence of <i>key</i>
    91   # objects by calling +dig+ at each step, returning +nil+ if any
    92   # intermediate step is +nil+.
    93   #
    94   def dig(idx,*args)
    95     n = self[idx]
    96     if args.size > 0
    97       n&.dig(*args)
    98     else
    99       n
     83    ##
     84    # call-seq:
     85    #   hsh.dig(key,...)                 -> object
     86    #
     87    # Extracts the nested value specified by the sequence of <i>key</i>
     88    # objects by calling +dig+ at each step, returning +nil+ if any
     89    # intermediate step is +nil+.
     90    #
     91    def dig(idx,*args)
     92      n = self[idx]
     93      if args.size > 0
     94        n&.dig(*args)
     95      else
     96        n
     97      end
    10098    end
    10199  end
    102100end
    103 
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-struct/src/struct.c

    r331 r439  
    1313#include <mruby/hash.h>
    1414#include <mruby/range.h>
    15 
    16 #define RSTRUCT_LEN(st) mrb_ary_ptr(st)->len
    17 #define RSTRUCT_PTR(st) mrb_ary_ptr(st)->ptr
     15#include <mruby/proc.h>
     16
     17#define RSTRUCT_LEN(st) RARRAY_LEN(st)
     18#define RSTRUCT_PTR(st) RARRAY_PTR(st)
    1819
    1920static struct RClass *
     
    2425
    2526static inline mrb_value
    26 struct_ivar_get(mrb_state *mrb, mrb_value c, mrb_sym id)
    27 {
    28   struct RClass* kclass;
     27struct_ivar_get(mrb_state *mrb, mrb_value cls, mrb_sym id)
     28{
     29  struct RClass* c = mrb_class_ptr(cls);
    2930  struct RClass* sclass = struct_class(mrb);
    3031  mrb_value ans;
    3132
    3233  for (;;) {
    33     ans = mrb_iv_get(mrb, c, id);
     34    ans = mrb_iv_get(mrb, mrb_obj_value(c), id);
    3435    if (!mrb_nil_p(ans)) return ans;
    35     kclass = RCLASS_SUPER(c);
    36     if (kclass == 0 || kclass == sclass)
     36    c = c->super;
     37    if (c == sclass || c == 0)
    3738      return mrb_nil_value();
    38     c = mrb_obj_value(kclass);
    3939  }
    4040}
     
    6767    else {
    6868      mrb_raisef(mrb, E_TYPE_ERROR,
    69                  "struct size differs (%S required %S given)",
    70                  mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s)));
     69                 "struct size differs (%i required %i given)",
     70                 RARRAY_LEN(members), RSTRUCT_LEN(s));
    7171    }
    7272  }
     
    8888mrb_struct_modify(mrb_state *mrb, mrb_value strct)
    8989{
    90   if (MRB_FROZEN_P(mrb_basic_ptr(strct))) {
    91     mrb_raise(mrb, E_RUNTIME_ERROR, "can't modify frozen struct");
    92   }
    93 
     90  mrb_check_frozen(mrb, mrb_basic_ptr(strct));
    9491  mrb_write_barrier(mrb, mrb_basic_ptr(strct));
    9592}
     
    114111}
    115112
    116 static mrb_value struct_aref_sym(mrb_state *mrb, mrb_value obj, mrb_sym id);
    117 
    118113static mrb_value
    119114mrb_struct_ref(mrb_state *mrb, mrb_value obj)
    120115{
    121   return struct_aref_sym(mrb, obj, mrb->c->ci->mid);
     116  mrb_int i = mrb_fixnum(mrb_proc_cfunc_env_get(mrb, 0));
     117  mrb_value *ptr = RSTRUCT_PTR(obj);
     118
     119  if (!ptr) return mrb_nil_value();
     120  return ptr[i];
    122121}
    123122
     
    125124mrb_id_attrset(mrb_state *mrb, mrb_sym id)
    126125{
     126#define ONSTACK_ALLOC_MAX 32
     127#define ONSTACK_STRLEN_MAX (ONSTACK_ALLOC_MAX - 1) /* '=' character */
     128
    127129  const char *name;
    128130  char *buf;
    129131  mrb_int len;
    130132  mrb_sym mid;
    131 
    132   name = mrb_sym2name_len(mrb, id, &len);
    133   buf = (char *)mrb_malloc(mrb, (size_t)len+2);
     133  char onstack[ONSTACK_ALLOC_MAX];
     134
     135  name = mrb_sym_name_len(mrb, id, &len);
     136  if (len > ONSTACK_STRLEN_MAX) {
     137    buf = (char *)mrb_malloc(mrb, (size_t)len+1);
     138  }
     139  else {
     140    buf = onstack;
     141  }
    134142  memcpy(buf, name, (size_t)len);
    135143  buf[len] = '=';
    136   buf[len+1] = '\0';
    137144
    138145  mid = mrb_intern(mrb, buf, len+1);
    139   mrb_free(mrb, buf);
     146  if (buf != onstack) {
     147    mrb_free(mrb, buf);
     148  }
    140149  return mid;
    141150}
    142151
    143 static mrb_value mrb_struct_aset_sym(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val);
    144 
    145152static mrb_value
    146153mrb_struct_set_m(mrb_state *mrb, mrb_value obj)
    147154{
     155  mrb_int i = mrb_fixnum(mrb_proc_cfunc_env_get(mrb, 0));
     156  mrb_value *ptr;
    148157  mrb_value val;
    149158
    150   const char *name;
    151   mrb_int slen;
    152   mrb_sym mid;
    153 
    154159  mrb_get_args(mrb, "o", &val);
    155 
    156   /* get base id */
    157   name = mrb_sym2name_len(mrb, mrb->c->ci->mid, &slen);
    158   mid = mrb_intern(mrb, name, slen-1); /* omit last "=" */
    159 
    160   return mrb_struct_aset_sym(mrb, obj, mid, val);
    161 }
    162 
    163 static mrb_bool
    164 is_local_id(mrb_state *mrb, const char *name)
    165 {
    166   if (!name) return FALSE;
    167   return !ISUPPER(name[0]);
    168 }
    169 
    170 static mrb_bool
    171 is_const_id(mrb_state *mrb, const char *name)
    172 {
    173   if (!name) return FALSE;
    174   return ISUPPER(name[0]);
     160  mrb_struct_modify(mrb, obj);
     161  ptr = RSTRUCT_PTR(obj);
     162  if (ptr == NULL || i >= RSTRUCT_LEN(obj)) {
     163    mrb_ary_set(mrb, obj, i, val);
     164  }
     165  else {
     166    ptr[i] = val;
     167  }
     168  return val;
    175169}
    176170
     
    185179  for (i=0; i<len; i++) {
    186180    mrb_sym id = mrb_symbol(ptr_members[i]);
    187     const char *name = mrb_sym2name_len(mrb, id, NULL);
    188 
    189     if (is_local_id(mrb, name) || is_const_id(mrb, name)) {
    190       mrb_define_method_id(mrb, c, id, mrb_struct_ref, MRB_ARGS_NONE());
    191       mrb_define_method_id(mrb, c, mrb_id_attrset(mrb, id), mrb_struct_set_m, MRB_ARGS_REQ(1));
    192       mrb_gc_arena_restore(mrb, ai);
    193     }
    194   }
    195 }
    196 
    197 static mrb_value
    198 make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * klass)
     181    mrb_method_t m;
     182    mrb_value at = mrb_fixnum_value(i);
     183    struct RProc *aref = mrb_proc_new_cfunc_with_env(mrb, mrb_struct_ref, 1, &at);
     184    struct RProc *aset = mrb_proc_new_cfunc_with_env(mrb, mrb_struct_set_m, 1, &at);
     185    MRB_METHOD_FROM_PROC(m, aref);
     186    mrb_define_method_raw(mrb, c, id, m);
     187    MRB_METHOD_FROM_PROC(m, aset);
     188    mrb_define_method_raw(mrb, c, mrb_id_attrset(mrb, id), m);
     189    mrb_gc_arena_restore(mrb, ai);
     190  }
     191}
     192
     193static mrb_value
     194make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass *klass)
    199195{
    200196  mrb_value nstr;
     
    207203  else {
    208204    /* old style: should we warn? */
    209     name = mrb_str_to_str(mrb, name);
     205    mrb_to_str(mrb, name);
    210206    id = mrb_obj_to_sym(mrb, name);
    211     if (!is_const_id(mrb, mrb_sym2name_len(mrb, id, NULL))) {
    212       mrb_name_error(mrb, id, "identifier %S needs to be constant", name);
     207    if (!mrb_const_name_p(mrb, RSTRING_PTR(name), RSTRING_LEN(name))) {
     208      mrb_name_error(mrb, id, "identifier %v needs to be constant", name);
    213209    }
    214210    if (mrb_const_defined_at(mrb, mrb_obj_value(klass), id)) {
    215       mrb_warn(mrb, "redefining constant Struct::%S", name);
     211      mrb_warn(mrb, "redefining constant Struct::%v", name);
    216212      mrb_const_remove(mrb, mrb_obj_value(klass), id);
    217213    }
     
    277273
    278274  name = mrb_nil_value();
    279   rest = mrb_nil_value();
    280275  mrb_get_args(mrb, "*&", &argv, &argc, &b);
    281276  if (argc == 0) { /* special case to avoid crash */
    282     rest = mrb_ary_new(mrb);
     277    mrb_argnum_error(mrb, argc, 1, -1);
    283278  }
    284279  else {
    285     if (argc > 0) name = argv[0];
    286     pargv = &argv[1];
    287     argcnt = argc-1;
    288     if (!mrb_nil_p(name) && mrb_symbol_p(name)) {
    289       /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */
    290       name = mrb_nil_value();
    291       pargv = &argv[0];
    292       argcnt++;
     280    pargv = argv;
     281    argcnt = argc;
     282    if (argc > 0) {
     283      name = argv[0];
     284      if (mrb_symbol_p(name)) {
     285        /* 1stArgument:symbol -> name=nil rest=argv[0..n] */
     286        name = mrb_nil_value();
     287      }
     288      else {
     289        pargv++;
     290        argcnt--;
     291      }
    293292    }
    294293    rest = mrb_ary_new_from_values(mrb, argcnt, pargv);
    295     for (i=0; i<RARRAY_LEN(rest); i++) {
     294    for (i=0; i<argcnt; i++) {
    296295      id = mrb_obj_to_sym(mrb, RARRAY_PTR(rest)[i]);
    297296      mrb_ary_set(mrb, rest, i, mrb_symbol_value(id));
    298297    }
    299   }
    300   st = make_struct(mrb, name, rest, mrb_class_ptr(klass));
    301   if (!mrb_nil_p(b)) {
    302     mrb_yield_with_class(mrb, b, 1, &st, st, mrb_class_ptr(st));
    303   }
    304 
    305   return st;
     298    st = make_struct(mrb, name, rest, mrb_class_ptr(klass));
     299    if (!mrb_nil_p(b)) {
     300      mrb_yield_with_class(mrb, b, 1, &st, st, mrb_class_ptr(st));
     301    }
     302
     303    return st;
     304  }
     305  /* not reached */
     306  return mrb_nil_value();
    306307}
    307308
     
    347348  mrb_int argc;
    348349
    349   mrb_get_args(mrb, "*", &argv, &argc);
     350  mrb_get_args(mrb, "*!", &argv, &argc);
    350351  return mrb_struct_initialize_withArg(mrb, argc, argv, self);
    351352}
     
    388389    }
    389390  }
    390   mrb_raisef(mrb, E_INDEX_ERROR, "'%S' is not a struct member", mrb_sym2str(mrb, id));
     391  mrb_name_error(mrb, id, "no member '%n' in struct", id);
    391392  return mrb_nil_value();       /* not reached */
    392393}
     
    395396struct_aref_int(mrb_state *mrb, mrb_value s, mrb_int i)
    396397{
    397   if (i < 0) i = RSTRUCT_LEN(s) + i;
    398   if (i < 0)
    399       mrb_raisef(mrb, E_INDEX_ERROR,
    400                  "offset %S too small for struct(size:%S)",
    401                  mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
    402   if (RSTRUCT_LEN(s) <= i)
     398  mrb_int idx = i < 0 ? RSTRUCT_LEN(s) + i : i;
     399
     400  if (idx < 0)
    403401    mrb_raisef(mrb, E_INDEX_ERROR,
    404                "offset %S too large for struct(size:%S)",
    405                mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
    406   return RSTRUCT_PTR(s)[i];
     402               "offset %i too small for struct(size:%i)", i, RSTRUCT_LEN(s));
     403  if (RSTRUCT_LEN(s) <= idx)
     404    mrb_raisef(mrb, E_INDEX_ERROR,
     405               "offset %i too large for struct(size:%i)", i, RSTRUCT_LEN(s));
     406  return RSTRUCT_PTR(s)[idx];
    407407}
    408408
     
    436436
    437437    if (mrb_nil_p(sym)) {
    438       mrb_name_error(mrb, mrb_intern_str(mrb, idx), "no member '%S' in struct", idx);
     438      mrb_name_error(mrb, mrb_intern_str(mrb, idx), "no member '%v' in struct", idx);
    439439    }
    440440    idx = sym;
     
    464464    }
    465465  }
    466   mrb_name_error(mrb, id, "no member '%S' in struct", mrb_sym2str(mrb, id));
     466  mrb_name_error(mrb, id, "no member '%n' in struct", id);
    467467  return val;                   /* not reach */
    468468}
     
    503503
    504504    if (mrb_nil_p(sym)) {
    505       mrb_name_error(mrb, mrb_intern_str(mrb, idx), "no member '%S' in struct", idx);
     505      mrb_name_error(mrb, mrb_intern_str(mrb, idx), "no member '%v' in struct", idx);
    506506    }
    507507    idx = sym;
     
    515515  if (i < 0) {
    516516    mrb_raisef(mrb, E_INDEX_ERROR,
    517                "offset %S too small for struct(size:%S)",
    518                mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
     517               "offset %i too small for struct(size:%i)", i, RSTRUCT_LEN(s));
    519518  }
    520519  if (RSTRUCT_LEN(s) <= i) {
    521520    mrb_raisef(mrb, E_INDEX_ERROR,
    522                "offset %S too large for struct(size:%S)",
    523                mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
     521               "offset %i too large for struct(size:%i)", i, RSTRUCT_LEN(s));
    524522  }
    525523  mrb_struct_modify(mrb, s);
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-struct/test/struct.rb

    r331 r439  
    1010  assert_equal Struct, c.superclass
    1111  assert_equal [:m1, :m2], c.members
    12 end
    13 
    14 # Check crash bug with Struc.new and no params.
    15 assert('Struct.new', '15.2.18.3.1') do
    16   c = Struct.new()
    17   assert_equal Struct, c.superclass
    18   assert_equal [], c.members
    1912end
    2013
     
    124117
    125118assert('struct inspect') do
    126   c = Struct.new(:m1, :m2, :m3, :m4, :m5)
    127   cc = c.new(1,2,3,4,5)
    128   assert_equal "#<struct m1=1, m2=2, m3=3, m4=4, m5=5>", cc.inspect
     119  c = Struct.new(:m1, :m2, :m3, :m4, :m5, :recur)
     120  cc = c.new(1,2,3,4,5,nil)
     121  cc.recur = cc
     122  assert_equal "#<struct m1=1, m2=2, m3=3, m4=4, m5=5, recur=#<struct #{cc.class}:...>>", cc.inspect
    129123end
    130124
     
    160154end
    161155
    162 assert("Struct.new removes existing constant") do
    163   skip "redefining Struct with same name cause warnings"
    164   begin
    165     assert_not_equal Struct.new("Test", :a), Struct.new("Test", :a, :b)
    166   ensure
    167     Struct.remove_const :Test
    168   end
    169 end
     156# TODO: suppress redefining Struct warning during test
     157# assert("Struct.new removes existing constant") do
     158#   begin
     159#     assert_not_equal Struct.new("Test", :a), Struct.new("Test", :a, :b)
     160#   ensure
     161#     Struct.remove_const :Test
     162#   end
     163# end
    170164
    171165assert("Struct#initialize_copy requires struct to be the same type") do
     
    189183end
    190184
     185assert("Struct.new does not allow invalid class name") do
     186  assert_raise(NameError) { Struct.new("Test-", :a) }
     187end
     188
    191189assert("Struct.new generates subclass of Struct") do
    192190  begin
    193191    original_struct = Struct
    194192    Struct = String
    195     assert_equal original_struct, original_struct.new.superclass
     193    assert_equal original_struct, original_struct.new(:foo).superclass
    196194  ensure
    197195    Struct = original_struct
     
    207205
    208206  o.freeze
    209   assert_raise(RuntimeError) { o.m = :modify }
    210   assert_raise(RuntimeError) { o[:m] = :modify }
     207  assert_raise(FrozenError) { o.m = :modify }
     208  assert_raise(FrozenError) { o[:m] = :modify }
    211209  assert_equal :test, o.m
    212210end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-symbol-ext/mrblib/symbol.rb

    r321 r439  
    33
    44  alias intern to_sym
    5 
    6   def to_proc
    7     ->(obj,*args,&block) do
    8       obj.__send__(self, *args, &block)
    9     end
    10   end
    115
    126  ##
     
    4943    return nil unless other.kind_of?(Symbol)
    5044    lhs =  self.to_s; lhs.upcase!
    51     rhs = other.to_s; rhs.upcase!
     45    rhs = other.to_s.upcase
    5246    lhs <=> rhs
     47  end
     48
     49  ##
     50  # call-seq:
     51  #   sym.casecmp?(other)  -> true, false, or nil
     52  #
     53  # Returns true if sym and other_sym are equal after case folding,
     54  # false if they are not equal, and nil if other_sym is not a string.
     55
     56  def casecmp?(sym)
     57    c = self.casecmp(sym)
     58    return nil if c.nil?
     59    return c == 0
    5360  end
    5461
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-symbol-ext/src/symbol.c

    r331 r439  
    22#include <mruby/khash.h>
    33#include <mruby/array.h>
    4 
    5 typedef struct symbol_name {
    6   size_t len;
    7   const char *name;
    8 } symbol_name;
     4#include <mruby/string.h>
    95
    106/*
     
    2319 *                                     :wait2, :$>]
    2420 */
     21#ifdef MRB_ENABLE_ALL_SYMBOLS
    2522static mrb_value
    2623mrb_sym_all_symbols(mrb_state *mrb, mrb_value self)
     
    3027
    3128  for (i=1, lim=mrb->symidx+1; i<lim; i++) {
    32     mrb_ary_push(mrb, ary, mrb_symbol_value(i));
     29    mrb_sym sym = i<<1;
     30    mrb_ary_push(mrb, ary, mrb_symbol_value(sym));
    3331  }
    3432
    3533  return ary;
    3634}
     35#endif
    3736
    3837/*
     
    4645{
    4746  mrb_int len;
    48   mrb_sym2name_len(mrb, mrb_symbol(self), &len);
     47#ifdef MRB_UTF8_STRING
     48  mrb_int byte_len;
     49  const char *name = mrb_sym_name_len(mrb, mrb_symbol(self), &byte_len);
     50  len = mrb_utf8_strlen(name, byte_len);
     51#else
     52  mrb_sym_name_len(mrb, mrb_symbol(self), &len);
     53#endif
    4954  return mrb_fixnum_value(len);
    5055}
     
    5459{
    5560  struct RClass *s = mrb->symbol_class;
     61#ifdef MRB_ENABLE_ALL_SYMBOLS
    5662  mrb_define_class_method(mrb, s, "all_symbols", mrb_sym_all_symbols, MRB_ARGS_NONE());
     63#endif
    5764  mrb_define_method(mrb, s, "length", mrb_sym_length, MRB_ARGS_NONE());
    5865  mrb_define_method(mrb, s, "size", mrb_sym_length, MRB_ARGS_NONE());
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-symbol-ext/test/symbol.rb

    r321 r439  
     1# coding: utf-8
    12##
    23# Symbol(Ext) Test
    34
    4 assert('Symbol#to_proc') do
    5   assert_equal 5, :abs.to_proc[-5]
     5if Symbol.respond_to?(:all_symbols)
     6  assert('Symbol.all_symbols') do
     7    foo = [:__symbol_test_1, :__symbol_test_2, :__symbol_test_3].sort
     8    symbols = Symbol.all_symbols.select{|sym|sym.to_s.include? '__symbol_test'}.sort
     9    assert_equal foo, symbols
     10  end
    611end
    712
    8 assert('Symbol.all_symbols') do
    9   foo = [:__symbol_test_1, :__symbol_test_2, :__symbol_test_3].sort
    10   symbols = Symbol.all_symbols.select{|sym|sym.to_s.include? '__symbol_test'}.sort
    11   assert_equal foo, symbols
    12 end
    13 
    14 assert("Symbol#length") do
    15   assert_equal 5, :hello.size
    16   assert_equal 5, :mruby.length
     13%w[size length].each do |n|
     14  assert("Symbol##{n}") do
     15    assert_equal 5, :hello.__send__(n)
     16    assert_equal 4, :"aA\0b".__send__(n)
     17    if __ENCODING__ == "UTF-8"
     18      assert_equal 8, :"こんにちは世界!".__send__(n)
     19      assert_equal 4, :"aあ\0b".__send__(n)
     20    else
     21      assert_equal 22, :"こんにちは世界!".__send__(n)
     22      assert_equal 6, :"aあ\0b".__send__(n)
     23    end
     24  end
    1725end
    1826
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-test/driver.c

    r331 r439  
    1919#include <mruby/array.h>
    2020
    21 void
    22 mrb_init_mrbtest(mrb_state *);
     21extern const uint8_t mrbtest_assert_irep[];
     22
     23void mrbgemtest_init(mrb_state* mrb);
     24void mrb_init_test_vformat(mrb_state* mrb);
    2325
    2426/* Print a short remark for the user */
     
    3032
    3133static int
    32 check_error(mrb_state *mrb)
    33 {
    34   /* Error check */
    35   /* $ko_test and $kill_test should be 0 */
    36   mrb_value ko_test = mrb_gv_get(mrb, mrb_intern_lit(mrb, "$ko_test"));
    37   mrb_value kill_test = mrb_gv_get(mrb, mrb_intern_lit(mrb, "$kill_test"));
    38 
    39   return mrb_fixnum_p(ko_test) && mrb_fixnum(ko_test) == 0 && mrb_fixnum_p(kill_test) && mrb_fixnum(kill_test) == 0;
    40 }
    41 
    42 static int
    4334eval_test(mrb_state *mrb)
    4435{
    4536  /* evaluate the test */
    46   mrb_funcall(mrb, mrb_top_self(mrb), "report", 0);
     37  mrb_value result = mrb_funcall(mrb, mrb_top_self(mrb), "report", 0);
    4738  /* did an exception occur? */
    4839  if (mrb->exc) {
     
    5142    return EXIT_FAILURE;
    5243  }
    53   else if (!check_error(mrb)) {
    54     return EXIT_FAILURE;
    55   }
    56   return EXIT_SUCCESS;
    57 }
    58 
    59 static void
    60 t_printstr(mrb_state *mrb, mrb_value obj)
    61 {
    62   char *s;
    63   int len;
    64 
    65   if (mrb_string_p(obj)) {
    66     s = RSTRING_PTR(obj);
    67     len = RSTRING_LEN(obj);
    68     fwrite(s, len, 1, stdout);
    69   }
    70 }
    71 
    72 mrb_value
    73 mrb_t_printstr(mrb_state *mrb, mrb_value self)
    74 {
    75   mrb_value argv;
    76 
    77   mrb_get_args(mrb, "o", &argv);
    78   t_printstr(mrb, argv);
    79 
    80   return argv;
     44  else {
     45    return mrb_bool(result) ? EXIT_SUCCESS : EXIT_FAILURE;
     46  }
     47}
     48
     49/* Implementation of print due to the reason that there might be no print */
     50static mrb_value
     51t_print(mrb_state *mrb, mrb_value self)
     52{
     53  mrb_value *argv;
     54  mrb_int argc;
     55  mrb_int i;
     56
     57  mrb_get_args(mrb, "*!", &argv, &argc);
     58  for (i = 0; i < argc; ++i) {
     59    mrb_value s = mrb_obj_as_string(mrb, argv[i]);
     60    fwrite(RSTRING_PTR(s), RSTRING_LEN(s), 1, stdout);
     61  }
     62  fflush(stdout);
     63
     64  return mrb_nil_value();
     65}
     66
     67#define UNESCAPE(p, endp) ((p) != (endp) && *(p) == '\\' ? (p)+1 : (p))
     68#define CHAR_CMP(c1, c2) ((unsigned char)(c1) - (unsigned char)(c2))
     69
     70static const char *
     71str_match_bracket(const char *p, const char *pat_end,
     72                  const char *s, const char *str_end)
     73{
     74  mrb_bool ok = FALSE, negated = FALSE;
     75
     76  if (p == pat_end) return NULL;
     77  if (*p == '!' || *p == '^') {
     78    negated = TRUE;
     79    ++p;
     80  }
     81
     82  while (*p != ']') {
     83    const char *t1 = p;
     84    if ((t1 = UNESCAPE(t1, pat_end)) == pat_end) return NULL;
     85    if ((p = t1 + 1) == pat_end) return NULL;
     86    if (p[0] == '-' && p[1] != ']') {
     87      const char *t2 = p + 1;
     88      if ((t2 = UNESCAPE(t2, pat_end)) == pat_end) return NULL;
     89      p = t2 + 1;
     90      if (!ok && CHAR_CMP(*t1, *s) <= 0 && CHAR_CMP(*s, *t2) <= 0) ok = TRUE;
     91    }
     92    else {
     93      if (!ok && CHAR_CMP(*t1, *s) == 0) ok = TRUE;
     94    }
     95  }
     96
     97  return ok == negated ? NULL : p + 1;
     98}
     99
     100static mrb_bool
     101str_match_no_brace_p(const char *pat, mrb_int pat_len,
     102                     const char *str, mrb_int str_len)
     103{
     104  const char *p = pat, *s = str;
     105  const char *pat_end = pat + pat_len, *str_end = str + str_len;
     106  const char *p_tmp = NULL, *s_tmp = NULL;
     107
     108  for (;;) {
     109    if (p == pat_end) return s == str_end;
     110    switch (*p) {
     111      case '*':
     112        do { ++p; } while (p != pat_end && *p == '*');
     113        if (UNESCAPE(p, pat_end) == pat_end) return TRUE;
     114        if (s == str_end) return FALSE;
     115        p_tmp = p;
     116        s_tmp = s;
     117        continue;
     118      case '?':
     119        if (s == str_end) return FALSE;
     120        ++p;
     121        ++s;
     122        continue;
     123      case '[': {
     124        const char *t;
     125        if (s == str_end) return FALSE;
     126        if ((t = str_match_bracket(p+1, pat_end, s, str_end))) {
     127          p = t;
     128          ++s;
     129          continue;
     130        }
     131        goto L_failed;
     132      }
     133    }
     134
     135    /* ordinary */
     136    p = UNESCAPE(p, pat_end);
     137    if (s == str_end) return p == pat_end;
     138    if (p == pat_end) goto L_failed;
     139    if (*p++ != *s++) goto L_failed;
     140    continue;
     141
     142    L_failed:
     143    if (p_tmp && s_tmp) {
     144      /* try next '*' position */
     145      p = p_tmp;
     146      s = ++s_tmp;
     147      continue;
     148    }
     149
     150    return FALSE;
     151  }
     152}
     153
     154#define COPY_AND_INC(dst, src, len) \
     155  do { memcpy(dst, src, len); dst += len; } while (0)
     156
     157static mrb_bool
     158str_match_p(mrb_state *mrb,
     159            const char *pat, mrb_int pat_len,
     160            const char *str, mrb_int str_len)
     161{
     162  const char *p = pat, *pat_end = pat + pat_len;
     163  const char *lbrace = NULL, *rbrace = NULL;
     164  int nest = 0;
     165  mrb_bool ret = FALSE;
     166
     167  for (; p != pat_end; ++p) {
     168    if (*p == '{' && nest++ == 0) lbrace = p;
     169    else if (*p == '}' && lbrace && --nest == 0) { rbrace = p; break; }
     170    else if (*p == '\\' && ++p == pat_end) break;
     171  }
     172
     173  if (lbrace && rbrace) {
     174    /* expand brace */
     175    char *ex_pat = (char *)mrb_malloc(mrb, pat_len-2);  /* expanded pattern */
     176    char *ex_p = ex_pat;
     177
     178    COPY_AND_INC(ex_p, pat, lbrace-pat);
     179    p = lbrace;
     180    while (p < rbrace) {
     181      char *orig_ex_p = ex_p;
     182      const char *t = ++p;
     183      for (nest = 0; p < rbrace && !(*p == ',' && nest == 0); ++p) {
     184        if (*p == '{') ++nest;
     185        else if (*p == '}') --nest;
     186        else if (*p == '\\' && ++p == rbrace) break;
     187      }
     188      COPY_AND_INC(ex_p, t, p-t);
     189      COPY_AND_INC(ex_p, rbrace+1, pat_end-rbrace-1);
     190      if ((ret = str_match_p(mrb, ex_pat, ex_p-ex_pat, str, str_len))) break;
     191      ex_p = orig_ex_p;
     192    }
     193    mrb_free(mrb, ex_pat);
     194  }
     195  else if (!lbrace && !rbrace) {
     196    ret = str_match_no_brace_p(pat, pat_len, str, str_len);
     197  }
     198
     199  return ret;
     200}
     201
     202static mrb_value
     203m_str_match_p(mrb_state *mrb, mrb_value self)
     204{
     205  const char *pat, *str;
     206  mrb_int pat_len, str_len;
     207
     208  mrb_get_args(mrb, "ss", &pat, &pat_len, &str, &str_len);
     209  return mrb_bool_value(str_match_p(mrb, pat, pat_len, str, str_len));
    81210}
    82211
     
    87216
    88217  krn = mrb->kernel_module;
    89   mrb_define_method(mrb, krn, "__t_printstr__", mrb_t_printstr, MRB_ARGS_REQ(1));
     218  mrb_define_method(mrb, krn, "t_print", t_print, MRB_ARGS_ANY());
     219  mrb_define_method(mrb, krn, "_str_match?", m_str_match_p, MRB_ARGS_REQ(2));
    90220
    91221  mrbtest = mrb_define_module(mrb, "Mrbtest");
     
    95225  mrb_define_const(mrb, mrbtest, "FIXNUM_BIT", mrb_fixnum_value(MRB_INT_BIT));
    96226
     227#ifndef MRB_WITHOUT_FLOAT
    97228#ifdef MRB_USE_FLOAT
    98229  mrb_define_const(mrb, mrbtest, "FLOAT_TOLERANCE", mrb_float_value(mrb, 1e-6));
     
    100231  mrb_define_const(mrb, mrbtest, "FLOAT_TOLERANCE", mrb_float_value(mrb, 1e-12));
    101232#endif
     233#endif
     234
     235  mrb_init_test_vformat(mrb);
    102236
    103237  if (verbose) {
     
    128262  TEST_COUNT_PASS(ko_test);
    129263  TEST_COUNT_PASS(kill_test);
     264  TEST_COUNT_PASS(warning_test);
     265  TEST_COUNT_PASS(skip_test);
    130266
    131267#undef TEST_COUNT_PASS
     
    165301
    166302  mrb_init_test_driver(mrb, verbose);
    167   mrb_init_mrbtest(mrb);
     303  mrb_load_irep(mrb, mrbtest_assert_irep);
     304  mrbgemtest_init(mrb);
    168305  ret = eval_test(mrb);
    169306  mrb_close(mrb);
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-test/mrbgem.rake

    r331 r439  
    1313  exec = exefile("#{build.build_dir}/bin/mrbtest")
    1414
    15   libmruby = libfile("#{build.build_dir}/lib/libmruby")
    16   libmruby_core = libfile("#{build.build_dir}/lib/libmruby_core")
    17 
    1815  mrbtest_lib = libfile("#{build_dir}/mrbtest")
    1916  mrbtest_objs = []
    2017
    21   driver_obj = objfile("#{build_dir}/driver")
    22   driver = "#{spec.dir}/driver.c"
     18  driver_objs = Dir.glob("#{dir}/*.{c,cpp,cxx,cc,m,asm,s,S}").map do |f|
     19    objfile(f.relative_path_from(dir).to_s.pathmap("#{build_dir}/%X"))
     20  end
    2321
    2422  assert_c = "#{build_dir}/assert.c"
     
    2826
    2927  file assert_lib => assert_c
    30   file assert_c => assert_rb do |t|
     28  file assert_c => [assert_rb, build.mrbcfile] do |t|
    3129    open(t.name, 'w') do |f|
    3230      mrbc.run f, assert_rb, 'mrbtest_assert_irep'
     
    4240
    4341    file test_rbobj => g.test_rbireps
    44     file g.test_rbireps => [g.test_rbfiles].flatten do |t|
    45       FileUtils.mkdir_p File.dirname(t.name)
     42    file g.test_rbireps => [g.test_rbfiles, build.mrbcfile].flatten do |t|
     43      mkdir_p File.dirname(t.name)
    4644      open(t.name, 'w') do |f|
    4745        g.print_gem_test_header(f)
     
    9896            f.puts %Q[  if (mrb2->exc) {]
    9997            f.puts %Q[    mrb_print_error(mrb2);]
     98            f.puts %Q[    mrb_close(mrb2);]
    10099            f.puts %Q[    exit(EXIT_FAILURE);]
    101100            f.puts %Q[  }]
     
    136135
    137136  unless build.build_mrbtest_lib_only?
    138     file exec => [driver_obj, mlib, mrbtest_lib, libmruby_core, libmruby] do |t|
     137    file exec => [*driver_objs, mlib, mrbtest_lib, build.libmruby_static] do |t|
    139138      gem_flags = build.gems.map { |g| g.linker.flags }
    140139      gem_flags_before_libraries = build.gems.map { |g| g.linker.flags_before_libraries }
     
    142141      gem_libraries = build.gems.map { |g| g.linker.libraries }
    143142      gem_library_paths = build.gems.map { |g| g.linker.library_paths }
    144       build.linker.run t.name, t.prerequisites, gem_libraries, gem_library_paths, gem_flags, gem_flags_before_libraries
     143      build.linker.run t.name, t.prerequisites, gem_libraries, gem_library_paths, gem_flags,
     144                       gem_flags_before_libraries, gem_flags_after_libraries
    145145    end
    146146  end
    147 
    148   init = "#{spec.dir}/init_mrbtest.c"
    149147
    150148  # store the last gem selection and make the re-build
    151149  # of the test gem depending on a change to the gem
    152150  # selection
    153   active_gems = "#{build_dir}/active_gems.lst"
    154   FileUtils.mkdir_p File.dirname(active_gems)
    155   open(active_gems, 'w+') do |f|
    156     build.gems.each do |g|
    157       f.puts g.name
    158     end
     151  active_gems_path = "#{build_dir}/active_gems_path.lst"
     152  active_gem_list = File.read active_gems_path if File.exist? active_gems_path
     153  current_gem_list = build.gems.map(&:name).join("\n")
     154  task active_gems_path do |_t|
     155    mkdir_p File.dirname(active_gems_path)
     156    File.write active_gems_path, current_gem_list
    159157  end
    160   file clib => active_gems
     158  file clib => active_gems_path if active_gem_list != current_gem_list
    161159
    162160  file mlib => clib
    163   file clib => init do |t|
     161  file clib => [build.mrbcfile, __FILE__] do |_t|
    164162    _pp "GEN", "*.rb", "#{clib.relative_path}"
    165     FileUtils.mkdir_p File.dirname(clib)
     163    mkdir_p File.dirname(clib)
    166164    open(clib, 'w') do |f|
    167165      f.puts %Q[/*]
     
    174172      f.puts %Q[ */]
    175173      f.puts %Q[]
    176       f.puts IO.read(init)
     174      f.puts %Q[struct mrb_state;]
     175      f.puts %Q[typedef struct mrb_state mrb_state;]
    177176      build.gems.each do |g|
    178177        f.puts %Q[void GENERATED_TMP_mrb_#{g.funcname}_gem_test(mrb_state *mrb);]
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-time/src/time.c

    r331 r439  
    55*/
    66
     7#ifndef MRB_WITHOUT_FLOAT
    78#include <math.h>
    8 #include <time.h>
     9#endif
     10
    911#include <mruby.h>
    1012#include <mruby/class.h>
    1113#include <mruby/data.h>
    12 
    13 #ifndef DISABLE_STDIO
    14 #include <stdio.h>
    15 #else
     14#include <mruby/numeric.h>
     15#include <mruby/time.h>
     16
     17#ifdef MRB_DISABLE_STDIO
    1618#include <string.h>
    1719#endif
    1820
     21#include <stdlib.h>
     22
    1923#define NDIV(x,y) (-(-((x)+1)/(y))-1)
    20 
    21 #if _MSC_VER < 1800
     24#define TO_S_FMT "%Y-%m-%d %H:%M:%S "
     25
     26#if defined(_MSC_VER) && _MSC_VER < 1800
    2227double round(double x) {
    23   if (x >= 0.0) {
    24     return (double)((int)(x + 0.5));
    25   }
    26   else {
    27     return (double)((int)(x - 0.5));
    28   }
    29 }
    30 #endif
    31 
    32 #if !defined(__MINGW64__) && defined(_WIN32)
    33 # define llround(x) round(x)
     28  return floor(x + 0.5);
     29}
     30#endif
     31
     32#ifndef MRB_WITHOUT_FLOAT
     33# if !defined(__MINGW64__) && defined(_WIN32)
     34#  define llround(x) round(x)
     35# endif
    3436#endif
    3537
     
    5254
    5355#ifdef _WIN32
    54 #if _MSC_VER
     56#ifdef _MSC_VER
    5557/* Win32 platform do not provide gmtime_r/localtime_r; emulate them using gmtime_s/localtime_s */
    5658#define gmtime_r(tp, tm)    ((gmtime_s((tm), (tp)) == 0) ? (tm) : NULL)
     
    144146  unsigned int *nday = (unsigned int*) ndays[is_leapyear(tm->tm_year+1900)];
    145147
    146   for (i = 70; i < tm->tm_year; ++i)
    147     r += is_leapyear(i+1900) ? 366*24*60*60 : 365*24*60*60;
     148  static const int epoch_year = 70;
     149  if(tm->tm_year >= epoch_year) {
     150    for (i = epoch_year; i < tm->tm_year; ++i)
     151      r += is_leapyear(i+1900) ? 366*24*60*60 : 365*24*60*60;
     152  } else {
     153    for (i = tm->tm_year; i < epoch_year; ++i)
     154      r -= is_leapyear(i+1900) ? 366*24*60*60 : 365*24*60*60;
     155  }
    148156  for (i = 0; i < tm->tm_mon; ++i)
    149157    r += nday[i] * 24 * 60 * 60;
     
    161169*/
    162170
    163 enum mrb_timezone {
    164   MRB_TIMEZONE_NONE   = 0,
    165   MRB_TIMEZONE_UTC    = 1,
    166   MRB_TIMEZONE_LOCAL  = 2,
    167   MRB_TIMEZONE_LAST   = 3
    168 };
    169 
    170171typedef struct mrb_timezone_name {
    171172  const char name[8];
     
    179180};
    180181
    181 #ifndef DISABLE_STDIO
     182#ifndef MRB_DISABLE_STDIO
    182183static const char mon_names[12][4] = {
    183184  "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
     
    198199static const struct mrb_data_type mrb_time_type = { "Time", mrb_free };
    199200
     201#ifndef MRB_WITHOUT_FLOAT
     202void mrb_check_num_exact(mrb_state *mrb, mrb_float num);
     203typedef mrb_float mrb_sec;
     204#define mrb_sec_value(mrb, sec) mrb_float_value(mrb, sec)
     205#else
     206typedef mrb_int mrb_sec;
     207#define mrb_sec_value(mrb, sec) mrb_fixnum_value(sec)
     208#endif
     209
     210#define MRB_TIME_T_UINT (~(time_t)0 > 0)
     211#define MRB_TIME_MIN (                                                      \
     212  MRB_TIME_T_UINT ? 0 :                                                     \
     213                    (sizeof(time_t) <= 4 ? INT32_MIN : INT64_MIN)           \
     214)
     215#define MRB_TIME_MAX (                                                      \
     216  MRB_TIME_T_UINT ? (sizeof(time_t) <= 4 ? UINT32_MAX : UINT64_MAX) :       \
     217                    (sizeof(time_t) <= 4 ? INT32_MAX : INT64_MAX)           \
     218)
     219
     220static mrb_bool
     221fixable_time_t_p(time_t v)
     222{
     223  if (MRB_INT_MIN <= MRB_TIME_MIN && MRB_TIME_MAX <= MRB_INT_MAX) return TRUE;
     224  return FIXABLE(v);
     225}
     226
     227static time_t
     228mrb_to_time_t(mrb_state *mrb, mrb_value obj, time_t *usec)
     229{
     230  time_t t;
     231
     232  switch (mrb_type(obj)) {
     233#ifndef MRB_WITHOUT_FLOAT
     234    case MRB_TT_FLOAT:
     235      {
     236        mrb_float f = mrb_float(obj);
     237
     238        mrb_check_num_exact(mrb, f);
     239        if (f >= ((mrb_float)MRB_TIME_MAX-1.0) || f < ((mrb_float)MRB_TIME_MIN+1.0)) {
     240          goto out_of_range;
     241        }
     242
     243        if (usec) {
     244          t = (time_t)f;
     245          *usec = (time_t)llround((f - t) * 1.0e+6);
     246        }
     247        else {
     248          t = (time_t)llround(f);
     249        }
     250      }
     251      break;
     252#endif /* MRB_WITHOUT_FLOAT */
     253    default:
     254    case MRB_TT_FIXNUM:
     255      {
     256        mrb_int i = mrb_int(mrb, obj);
     257
     258        if ((MRB_INT_MAX > MRB_TIME_MAX && i > 0 && i > (mrb_int)MRB_TIME_MAX) ||
     259            (MRB_TIME_MIN > MRB_INT_MIN && MRB_TIME_MIN > i)) {
     260          goto out_of_range;
     261        }
     262
     263        t = (time_t)i;
     264        if (usec) { *usec = 0; }
     265      }
     266      break;
     267  }
     268
     269  return t;
     270
     271out_of_range:
     272  mrb_raisef(mrb, E_ARGUMENT_ERROR, "%v out of Time range", obj);
     273
     274  /* not reached */
     275  if (usec) { *usec = 0; }
     276  return 0;
     277}
     278
    200279/** Updates the datetime of a mrb_time based on it's timezone and
    201 seconds setting. Returns self on success, NULL of failure. */
     280    seconds setting. Returns self on success, NULL of failure.
     281    if `dealloc` is set `true`, it frees `self` on error. */
    202282static struct mrb_time*
    203 time_update_datetime(mrb_state *mrb, struct mrb_time *self)
     283time_update_datetime(mrb_state *mrb, struct mrb_time *self, int dealloc)
    204284{
    205285  struct tm *aid;
     286  time_t t = self->sec;
    206287
    207288  if (self->timezone == MRB_TIMEZONE_UTC) {
    208     aid = gmtime_r(&self->sec, &self->datetime);
     289    aid = gmtime_r(&t, &self->datetime);
    209290  }
    210291  else {
    211     aid = localtime_r(&self->sec, &self->datetime);
     292    aid = localtime_r(&t, &self->datetime);
    212293  }
    213294  if (!aid) {
    214     mrb_raisef(mrb, E_ARGUMENT_ERROR, "%S out of Time range", mrb_float_value(mrb, (mrb_float)self->sec));
     295    mrb_sec sec = (mrb_sec)t;
     296
     297    if (dealloc) mrb_free(mrb, self);
     298    mrb_raisef(mrb, E_ARGUMENT_ERROR, "%v out of Time range", mrb_sec_value(mrb, sec));
    215299    /* not reached */
    216300    return NULL;
     
    229313}
    230314
    231 void mrb_check_num_exact(mrb_state *mrb, mrb_float num);
    232 
    233315/* Allocates a mrb_time object and initializes it. */
    234316static struct mrb_time*
    235 time_alloc(mrb_state *mrb, double sec, double usec, enum mrb_timezone timezone)
    236 {
    237   struct mrb_time *tm;
    238   time_t tsec = 0;
    239 
    240   mrb_check_num_exact(mrb, (mrb_float)sec);
    241   mrb_check_num_exact(mrb, (mrb_float)usec);
    242 
    243   if (sizeof(time_t) == 4 && (sec > (double)INT32_MAX || (double)INT32_MIN > sec)) {
    244     goto out_of_range;
    245   }
    246   if (sizeof(time_t) == 8 && (sec > (double)INT64_MAX || (double)INT64_MIN > sec)) {
    247     goto out_of_range;
    248   }
    249   tsec  = (time_t)sec;
    250   if ((sec > 0 && tsec < 0) || (sec < 0 && (double)tsec > sec)) {
    251   out_of_range:
    252     mrb_raisef(mrb, E_ARGUMENT_ERROR, "%S out of Time range", mrb_float_value(mrb, sec));
    253   }
     317time_alloc_time(mrb_state *mrb, time_t sec, time_t usec, enum mrb_timezone timezone)
     318{
     319  struct mrb_time *tm;
     320
    254321  tm = (struct mrb_time *)mrb_malloc(mrb, sizeof(struct mrb_time));
    255   tm->sec  = tsec;
    256   tm->usec = (time_t)llround((sec - tm->sec) * 1.0e6 + usec);
     322  tm->sec  = sec;
     323  tm->usec = usec;
    257324  if (tm->usec < 0) {
    258     long sec2 = (long)NDIV(usec,1000000); /* negative div */
     325    long sec2 = (long)NDIV(tm->usec,1000000); /* negative div */
    259326    tm->usec -= sec2 * 1000000;
    260327    tm->sec += sec2;
    261328  }
    262329  else if (tm->usec >= 1000000) {
    263     long sec2 = (long)(usec / 1000000);
     330    long sec2 = (long)(tm->usec / 1000000);
    264331    tm->usec -= sec2 * 1000000;
    265332    tm->sec += sec2;
    266333  }
    267334  tm->timezone = timezone;
    268   time_update_datetime(mrb, tm);
     335  time_update_datetime(mrb, tm, TRUE);
    269336
    270337  return tm;
    271338}
    272339
    273 static mrb_value
    274 mrb_time_make(mrb_state *mrb, struct RClass *c, double sec, double usec, enum mrb_timezone timezone)
     340static struct mrb_time*
     341time_alloc(mrb_state *mrb, mrb_value sec, mrb_value usec, enum mrb_timezone timezone)
     342{
     343  time_t tsec, tusec;
     344
     345  tsec = mrb_to_time_t(mrb, sec, &tusec);
     346  tusec += mrb_to_time_t(mrb, usec, NULL);
     347
     348  return time_alloc_time(mrb, tsec, tusec, timezone);
     349}
     350
     351static mrb_value
     352mrb_time_make_time(mrb_state *mrb, struct RClass *c, time_t sec, time_t usec, enum mrb_timezone timezone)
     353{
     354  return mrb_time_wrap(mrb, c, time_alloc_time(mrb, sec, usec, timezone));
     355}
     356
     357static mrb_value
     358mrb_time_make(mrb_state *mrb, struct RClass *c, mrb_value sec, mrb_value usec, enum mrb_timezone timezone)
    275359{
    276360  return mrb_time_wrap(mrb, c, time_alloc(mrb, sec, usec, timezone));
     
    280364current_mrb_time(mrb_state *mrb)
    281365{
    282   struct mrb_time *tm;
    283 
    284   tm = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm));
    285 #if defined(TIME_UTC)
     366  struct mrb_time tmzero = {0};
     367  struct mrb_time *tm;
     368  time_t sec, usec;
     369
     370#if defined(TIME_UTC) && !defined(__ANDROID__)
    286371  {
    287372    struct timespec ts;
    288373    if (timespec_get(&ts, TIME_UTC) == 0) {
    289       mrb_free(mrb, tm);
    290374      mrb_raise(mrb, E_RUNTIME_ERROR, "timespec_get() failed for unknown reasons");
    291375    }
    292     tm->sec = ts.tv_sec;
    293     tm->usec = ts.tv_nsec / 1000;
     376    sec = ts.tv_sec;
     377    usec = ts.tv_nsec / 1000;
    294378  }
    295379#elif defined(NO_GETTIMEOFDAY)
     
    297381    static time_t last_sec = 0, last_usec = 0;
    298382
    299     tm->sec = time(NULL);
    300     if (tm->sec != last_sec) {
    301       last_sec = tm->sec;
     383    sec = time(NULL);
     384    if (sec != last_sec) {
     385      last_sec = sec;
    302386      last_usec = 0;
    303387    }
     
    306390      last_usec += 1;
    307391    }
    308     tm->usec = last_usec;
     392    usec = last_usec;
    309393  }
    310394#else
     
    313397
    314398    gettimeofday(&tv, NULL);
    315     tm->sec = tv.tv_sec;
    316     tm->usec = tv.tv_usec;
    317   }
    318 #endif
     399    sec = tv.tv_sec;
     400    usec = tv.tv_usec;
     401  }
     402#endif
     403  tm = (struct mrb_time *)mrb_malloc(mrb, sizeof(*tm));
     404  *tm = tmzero;
     405  tm->sec = sec; tm->usec = usec;
    319406  tm->timezone = MRB_TIMEZONE_LOCAL;
    320   time_update_datetime(mrb, tm);
     407  time_update_datetime(mrb, tm, TRUE);
    321408
    322409  return tm;
     
    328415{
    329416  return mrb_time_wrap(mrb, mrb_class_ptr(self), current_mrb_time(mrb));
     417}
     418
     419MRB_API mrb_value
     420mrb_time_at(mrb_state *mrb, time_t sec, time_t usec, enum mrb_timezone zone)
     421{
     422  return mrb_time_make_time(mrb, mrb_class_get(mrb, "Time"), sec, usec, zone);
    330423}
    331424
     
    333426/* Creates an instance of time at the given time in seconds, etc. */
    334427static mrb_value
    335 mrb_time_at(mrb_state *mrb, mrb_value self)
    336 {
    337   mrb_float f, f2 = 0;
    338 
    339   mrb_get_args(mrb, "f|f", &f, &f2);
    340   return mrb_time_make(mrb, mrb_class_ptr(self), f, f2, MRB_TIMEZONE_LOCAL);
     428mrb_time_at_m(mrb_state *mrb, mrb_value self)
     429{
     430  mrb_value sec;
     431  mrb_value usec = mrb_fixnum_value(0);
     432
     433  mrb_get_args(mrb, "o|o", &sec, &usec);
     434
     435  return mrb_time_make(mrb, mrb_class_ptr(self), sec, usec, MRB_TIMEZONE_LOCAL);
    341436}
    342437
     
    375470  }
    376471
    377   return time_alloc(mrb, (double)nowsecs, ausec, timezone);
     472  return time_alloc_time(mrb, nowsecs, ausec, timezone);
    378473}
    379474
     
    461556mrb_time_plus(mrb_state *mrb, mrb_value self)
    462557{
    463   mrb_float f;
    464   struct mrb_time *tm;
    465 
    466   mrb_get_args(mrb, "f", &f);
    467   tm = time_get_ptr(mrb, self);
    468   return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec+f, (double)tm->usec, tm->timezone);
     558  mrb_value o;
     559  struct mrb_time *tm;
     560  time_t sec, usec;
     561
     562  mrb_get_args(mrb, "o", &o);
     563  tm = time_get_ptr(mrb, self);
     564  sec = mrb_to_time_t(mrb, o, &usec);
     565  return mrb_time_make_time(mrb, mrb_obj_class(mrb, self), tm->sec+sec, tm->usec+usec, tm->timezone);
    469566}
    470567
     
    472569mrb_time_minus(mrb_state *mrb, mrb_value self)
    473570{
    474   mrb_float f;
    475571  mrb_value other;
    476572  struct mrb_time *tm, *tm2;
     
    480576  tm2 = DATA_CHECK_GET_PTR(mrb, other, &mrb_time_type, struct mrb_time);
    481577  if (tm2) {
    482     f = (mrb_float)(tm->sec - tm2->sec)
    483       + (mrb_float)(tm->usec - tm2->usec) / 1.0e6;
     578#ifndef MRB_WITHOUT_FLOAT
     579    mrb_float f;
     580    f = (mrb_sec)(tm->sec - tm2->sec)
     581      + (mrb_sec)(tm->usec - tm2->usec) / 1.0e6;
    484582    return mrb_float_value(mrb, f);
     583#else
     584    mrb_int f;
     585    f = tm->sec - tm2->sec;
     586    if (tm->usec < tm2->usec) f--;
     587    return mrb_fixnum_value(f);
     588#endif
    485589  }
    486590  else {
    487     mrb_get_args(mrb, "f", &f);
    488     return mrb_time_make(mrb, mrb_obj_class(mrb, self), (double)tm->sec-f, (double)tm->usec, tm->timezone);
     591    time_t sec, usec;
     592    sec = mrb_to_time_t(mrb, other, &usec);
     593    return mrb_time_make_time(mrb, mrb_obj_class(mrb, self), tm->sec-sec, tm->usec-usec, tm->timezone);
    489594  }
    490595}
     
    547652  int len;
    548653
    549 #if defined(DISABLE_STDIO)
     654#if defined(MRB_DISABLE_STDIO)
    550655  char *s;
    551656# ifdef NO_ASCTIME_R
     
    559664  char buf[256];
    560665
    561   len = snprintf(buf, sizeof(buf), "%s %s %02d %02d:%02d:%02d %s%d",
     666  len = snprintf(buf, sizeof(buf), "%s %s %2d %02d:%02d:%02d %.4d",
    562667    wday_names[d->tm_wday], mon_names[d->tm_mon], d->tm_mday,
    563668    d->tm_hour, d->tm_min, d->tm_sec,
    564     tm->timezone == MRB_TIMEZONE_UTC ? "UTC " : "",
    565669    d->tm_year + 1900);
    566670#endif
     
    603707  *tm2 = *tm;
    604708  tm2->timezone = MRB_TIMEZONE_UTC;
    605   time_update_datetime(mrb, tm2);
     709  time_update_datetime(mrb, tm2, TRUE);
    606710  return mrb_time_wrap(mrb, mrb_obj_class(mrb, self), tm2);
    607711}
     
    618722  *tm2 = *tm;
    619723  tm2->timezone = MRB_TIMEZONE_LOCAL;
    620   time_update_datetime(mrb, tm2);
     724  time_update_datetime(mrb, tm2, TRUE);
    621725  return mrb_time_wrap(mrb, mrb_obj_class(mrb, self), tm2);
    622726}
     
    640744  mrb_int ayear = 0, amonth = 1, aday = 1, ahour = 0,
    641745  amin = 0, asec = 0, ausec = 0;
    642   int n;
     746  mrb_int n;
    643747  struct mrb_time *tm;
    644748
     
    696800  tm = time_get_ptr(mrb, self);
    697801  tm->timezone = MRB_TIMEZONE_LOCAL;
    698   time_update_datetime(mrb, tm);
     802  time_update_datetime(mrb, tm, FALSE);
    699803  return self;
    700804}
     
    744848}
    745849
    746 
     850#ifndef MRB_WITHOUT_FLOAT
    747851/* 15.2.19.7.24 */
    748852/* Returns a Float with the time since the epoch in seconds. */
     
    755859  return mrb_float_value(mrb, (mrb_float)tm->sec + (mrb_float)tm->usec/1.0e6);
    756860}
     861#endif
    757862
    758863/* 15.2.19.7.25 */
    759 /* Returns a Fixnum with the time since the epoch in seconds. */
     864/* Returns an Integer with the time since the epoch in seconds. */
    760865static mrb_value
    761866mrb_time_to_i(mrb_state *mrb, mrb_value self)
     
    764869
    765870  tm = time_get_ptr(mrb, self);
    766   if (tm->sec > MRB_INT_MAX || tm->sec < MRB_INT_MIN) {
     871#ifndef MRB_WITHOUT_FLOAT
     872  if (!fixable_time_t_p(tm->sec)) {
    767873    return mrb_float_value(mrb, (mrb_float)tm->sec);
    768874  }
     875#endif
    769876  return mrb_fixnum_value((mrb_int)tm->sec);
    770877}
    771878
    772879/* 15.2.19.7.26 */
    773 /* Returns a Float with the time since the epoch in microseconds. */
     880/* Returns an Integer with the time since the epoch in microseconds. */
    774881static mrb_value
    775882mrb_time_usec(mrb_state *mrb, mrb_value self)
     
    778885
    779886  tm = time_get_ptr(mrb, self);
    780   if (tm->usec > MRB_INT_MAX || tm->usec < MRB_INT_MIN) {
     887#ifndef MRB_WITHOUT_FLOAT
     888  if (!fixable_time_t_p(tm->usec)) {
    781889    return mrb_float_value(mrb, (mrb_float)tm->usec);
    782890  }
     891#endif
    783892  return mrb_fixnum_value((mrb_int)tm->usec);
    784893}
     
    793902  tm = time_get_ptr(mrb, self);
    794903  tm->timezone = MRB_TIMEZONE_UTC;
    795   time_update_datetime(mrb, tm);
     904  time_update_datetime(mrb, tm, FALSE);
    796905  return self;
    797906}
     
    808917}
    809918
     919static size_t
     920time_to_s_utc(mrb_state *mrb, struct mrb_time *tm, char *buf, size_t buf_len)
     921{
     922  return strftime(buf, buf_len, TO_S_FMT "UTC", &tm->datetime);
     923}
     924
     925static size_t
     926time_to_s_local(mrb_state *mrb, struct mrb_time *tm, char *buf, size_t buf_len)
     927{
     928#if defined(_MSC_VER) && _MSC_VER < 1900 || defined(__MINGW64__) || defined(__MINGW32__)
     929  struct tm datetime = {0};
     930  time_t utc_sec = timegm(&tm->datetime);
     931  size_t len;
     932  int offset;
     933
     934  if (utc_sec == (time_t)-1) {
     935    mrb_raise(mrb, E_ARGUMENT_ERROR, "Not a valid time.");
     936  }
     937  offset = abs((int)(utc_sec - tm->sec) / 60);
     938  datetime.tm_year = 100;
     939  datetime.tm_hour = offset / 60;
     940  datetime.tm_min = offset % 60;
     941  len = strftime(buf, buf_len, TO_S_FMT, &tm->datetime);
     942  buf[len++] = utc_sec < tm->sec ? '-' : '+';
     943
     944  return len + strftime(buf + len, buf_len - len, "%H%M", &datetime);
     945#else
     946  return strftime(buf, buf_len, TO_S_FMT "%z", &tm->datetime);
     947#endif
     948}
     949
     950static mrb_value
     951mrb_time_to_s(mrb_state *mrb, mrb_value self)
     952{
     953  char buf[64];
     954  struct mrb_time *tm = time_get_ptr(mrb, self);
     955  mrb_bool utc = tm->timezone == MRB_TIMEZONE_UTC;
     956  size_t len = (utc ? time_to_s_utc : time_to_s_local)(mrb, tm, buf, sizeof(buf));
     957  return mrb_str_new(mrb, buf, len);
     958}
    810959
    811960void
     
    817966  MRB_SET_INSTANCE_TT(tc, MRB_TT_DATA);
    818967  mrb_include_module(mrb, tc, mrb_module_get(mrb, "Comparable"));
    819   mrb_define_class_method(mrb, tc, "at", mrb_time_at, MRB_ARGS_ARG(1, 1));      /* 15.2.19.6.1 */
     968  mrb_define_class_method(mrb, tc, "at", mrb_time_at_m, MRB_ARGS_ARG(1, 1));      /* 15.2.19.6.1 */
    820969  mrb_define_class_method(mrb, tc, "gm", mrb_time_gm, MRB_ARGS_ARG(1,6));       /* 15.2.19.6.2 */
    821970  mrb_define_class_method(mrb, tc, "local", mrb_time_local, MRB_ARGS_ARG(1,6)); /* 15.2.19.6.3 */
     
    828977  mrb_define_method(mrb, tc, "+"      , mrb_time_plus   , MRB_ARGS_REQ(1)); /* 15.2.19.7.2 */
    829978  mrb_define_method(mrb, tc, "-"      , mrb_time_minus  , MRB_ARGS_REQ(1)); /* 15.2.19.7.3 */
    830   mrb_define_method(mrb, tc, "to_s"   , mrb_time_asctime, MRB_ARGS_NONE());
    831   mrb_define_method(mrb, tc, "inspect", mrb_time_asctime, MRB_ARGS_NONE());
     979  mrb_define_method(mrb, tc, "to_s"   , mrb_time_to_s   , MRB_ARGS_NONE());
     980  mrb_define_method(mrb, tc, "inspect", mrb_time_to_s   , MRB_ARGS_NONE());
    832981  mrb_define_method(mrb, tc, "asctime", mrb_time_asctime, MRB_ARGS_NONE()); /* 15.2.19.7.4 */
    833982  mrb_define_method(mrb, tc, "ctime"  , mrb_time_asctime, MRB_ARGS_NONE()); /* 15.2.19.7.5 */
     
    849998  mrb_define_method(mrb, tc, "sec" , mrb_time_sec, MRB_ARGS_NONE());        /* 15.2.19.7.23 */
    850999  mrb_define_method(mrb, tc, "to_i", mrb_time_to_i, MRB_ARGS_NONE());       /* 15.2.19.7.25 */
     1000#ifndef MRB_WITHOUT_FLOAT
    8511001  mrb_define_method(mrb, tc, "to_f", mrb_time_to_f, MRB_ARGS_NONE());       /* 15.2.19.7.24 */
     1002#endif
    8521003  mrb_define_method(mrb, tc, "usec", mrb_time_usec, MRB_ARGS_NONE());       /* 15.2.19.7.26 */
    8531004  mrb_define_method(mrb, tc, "utc" , mrb_time_utc, MRB_ARGS_NONE());        /* 15.2.19.7.27 */
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-time/test/time.rb

    r331 r439  
    33
    44assert('Time.new', '15.2.3.3.3') do
    5   Time.new.class == Time
     5  assert_equal(Time, Time.new.class)
    66end
    77
    88assert('Time', '15.2.19') do
    9   Time.class == Class
     9  assert_equal(Class, Time.class)
    1010end
    1111
     
    2222
    2323assert('Time.gm', '15.2.19.6.2') do
    24   Time.gm(2012, 12, 23)
     24  t = Time.gm(2012, 9, 23)
     25  assert_operator(2012, :eql?, t.year)
     26  assert_operator(   9, :eql?, t.month)
     27  assert_operator(  23, :eql?, t.day)
     28  assert_operator(   0, :eql?, t.hour)
     29  assert_operator(   0, :eql?, t.min)
     30  assert_operator(   0, :eql?, t.sec)
     31  assert_operator(   0, :eql?, t.usec)
    2532end
    2633
    2734assert('Time.local', '15.2.19.6.3') do
    28   Time.local(2012, 12, 23)
     35  t = Time.local(2014, 12, 27, 18)
     36  assert_operator(2014, :eql?, t.year)
     37  assert_operator(  12, :eql?, t.month)
     38  assert_operator(  27, :eql?, t.day)
     39  assert_operator(  18, :eql?, t.hour)
     40  assert_operator(   0, :eql?, t.min)
     41  assert_operator(   0, :eql?, t.sec)
     42  assert_operator(   0, :eql?, t.usec)
    2943end
    3044
    3145assert('Time.mktime', '15.2.19.6.4') do
    32   Time.mktime(2012, 12, 23)
     46  t = Time.mktime(2013, 10, 4, 6, 15, 58, 3485)
     47  assert_operator(2013, :eql?, t.year)
     48  assert_operator(  10, :eql?, t.month)
     49  assert_operator(   4, :eql?, t.day)
     50  assert_operator(   6, :eql?, t.hour)
     51  assert_operator(  15, :eql?, t.min)
     52  assert_operator(  58, :eql?, t.sec)
     53  assert_operator(3485, :eql?, t.usec)
    3354end
    3455
    3556assert('Time.now', '15.2.19.6.5') do
    36   Time.now.class == Time
     57  assert_equal(Time, Time.now.class)
    3758end
    3859
    3960assert('Time.utc', '15.2.19.6.6') do
    40   Time.utc(2012, 12, 23)
     61  t = Time.utc(2034)
     62  assert_operator(2034, :eql?, t.year)
     63  assert_operator(   1, :eql?, t.month)
     64  assert_operator(   1, :eql?, t.day)
     65  assert_operator(   0, :eql?, t.hour)
     66  assert_operator(   0, :eql?, t.min)
     67  assert_operator(   0, :eql?, t.sec)
     68  assert_operator(   0, :eql?, t.usec)
    4169end
    4270
     
    4573  t2 = t1.+(60)
    4674
    47   assert_equal(t2.utc.asctime, "Sun Mar 13 07:07:40 UTC 2011")
     75  assert_equal("Sun Mar 13 07:07:40 2011", t2.utc.asctime)
    4876
    4977  assert_raise(FloatDomainError) { Time.at(0) + Float::NAN }
     
    5684  t2 = t1.-(60)
    5785
    58   assert_equal(t2.utc.asctime, "Sun Mar 13 07:05:40 UTC 2011")
     86  assert_equal("Sun Mar 13 07:05:40 2011", t2.utc.asctime)
    5987
    6088  assert_raise(FloatDomainError) { Time.at(0) - Float::NAN }
     
    6896  t3 = Time.at(1500000000.0)
    6997
    70   t2.<=>(t1) == 1 and
    71     t2.<=>(t2) == 0 and
    72     t2.<=>(t3) == -1 and
    73     t2.<=>(nil) == nil
     98  assert_equal(1, t2 <=> t1)
     99  assert_equal(0, t2 <=> t2)
     100  assert_equal(-1, t2 <=> t3)
     101  assert_nil(t2 <=> nil)
    74102end
    75103
    76104assert('Time#asctime', '15.2.19.7.4') do
    77   Time.at(1300000000.0).utc.asctime == "Sun Mar 13 07:06:40 UTC 2011"
     105  assert_equal("Thu Mar  4 05:06:07 1982", Time.gm(1982,3,4,5,6,7).asctime)
    78106end
    79107
    80108assert('Time#ctime', '15.2.19.7.5') do
    81   Time.at(1300000000.0).utc.ctime == "Sun Mar 13 07:06:40 UTC 2011"
     109  assert_equal("Thu Oct 24 15:26:47 2013", Time.gm(2013,10,24,15,26,47).ctime)
    82110end
    83111
    84112assert('Time#day', '15.2.19.7.6') do
    85   Time.gm(2012, 12, 23).day == 23
     113  assert_equal(23, Time.gm(2012, 12, 23).day)
    86114end
    87115
    88116assert('Time#dst?', '15.2.19.7.7') do
    89   not Time.gm(2012, 12, 23).utc.dst?
     117  assert_not_predicate(Time.gm(2012, 12, 23).utc, :dst?)
    90118end
    91119
    92120assert('Time#getgm', '15.2.19.7.8') do
    93   Time.at(1300000000.0).getgm.asctime == "Sun Mar 13 07:06:40 UTC 2011"
     121  assert_equal("Sun Mar 13 07:06:40 2011", Time.at(1300000000.0).getgm.asctime)
    94122end
    95123
     
    99127  t3 = t1.getlocal
    100128
    101   t1 == t3 and t3 == t2.getlocal
     129  assert_equal(t1, t3)
     130  assert_equal(t3, t2.getlocal)
    102131end
    103132
    104133assert('Time#getutc', '15.2.19.7.10') do
    105   Time.at(1300000000.0).getutc.asctime == "Sun Mar 13 07:06:40 UTC 2011"
     134  assert_equal("Sun Mar 13 07:06:40 2011", Time.at(1300000000.0).getutc.asctime)
    106135end
    107136
    108137assert('Time#gmt?', '15.2.19.7.11') do
    109   Time.at(1300000000.0).utc.gmt?
     138  assert_predicate(Time.at(1300000000.0).utc, :gmt?)
    110139end
    111140
     
    114143
    115144assert('Time#gmtime', '15.2.19.7.13') do
    116   Time.at(1300000000.0).gmtime
     145  t = Time.now
     146  assert_predicate(t.gmtime, :gmt?)
     147  assert_predicate(t, :gmt?)
    117148end
    118149
     
    121152
    122153assert('Time#hour', '15.2.19.7.15') do
    123   Time.gm(2012, 12, 23, 7, 6).hour == 7
     154  assert_equal(7, Time.gm(2012, 12, 23, 7, 6).hour)
    124155end
    125156
     
    128159
    129160assert('Time#initialize_copy', '15.2.19.7.17') do
    130   time_tmp_2 = Time.at(7.0e6)
    131   time_tmp_2.clone == time_tmp_2
     161  t = Time.at(7.0e6)
     162  assert_equal(t, t.clone)
    132163end
    133164
    134165assert('Time#localtime', '15.2.19.7.18') do
    135   t1 = Time.at(1300000000.0)
    136   t2 = Time.at(1300000000.0)
    137 
    138   t1.localtime
    139   t1 == t2.getlocal
     166  t1 = Time.utc(2014, 5 ,6)
     167  t2 = Time.utc(2014, 5 ,6)
     168  t3 = t2.getlocal
     169
     170  assert_equal(t3, t1.localtime)
     171  assert_equal(t3, t1)
    140172end
    141173
    142174assert('Time#mday', '15.2.19.7.19') do
    143   Time.gm(2012, 12, 23).mday == 23
     175  assert_equal(23, Time.gm(2012, 12, 23).mday)
    144176end
    145177
    146178assert('Time#min', '15.2.19.7.20') do
    147   Time.gm(2012, 12, 23, 7, 6).min == 6
     179  assert_equal(6, Time.gm(2012, 12, 23, 7, 6).min)
    148180end
    149181
    150182assert('Time#mon', '15.2.19.7.21') do
    151   Time.gm(2012, 12, 23).mon == 12
     183  assert_equal(12, Time.gm(2012, 12, 23).mon)
    152184end
    153185
    154186assert('Time#month', '15.2.19.7.22') do
    155   Time.gm(2012, 12, 23).month == 12
     187  assert_equal(12, Time.gm(2012, 12, 23).month)
    156188end
    157189
    158190assert('Times#sec', '15.2.19.7.23') do
    159   Time.gm(2012, 12, 23, 7, 6, 40).sec == 40
     191  assert_equal(40, Time.gm(2012, 12, 23, 7, 6, 40).sec)
    160192end
    161193
    162194assert('Time#to_f', '15.2.19.7.24') do
    163   Time.at(1300000000.0).to_f == 1300000000.0
     195  assert_operator(2.0, :eql?, Time.at(2).to_f)
    164196end
    165197
    166198assert('Time#to_i', '15.2.19.7.25') do
    167   Time.at(1300000000.0).to_i == 1300000000
     199  assert_operator(2, :eql?, Time.at(2.0).to_i)
    168200end
    169201
    170202assert('Time#usec', '15.2.19.7.26') do
    171   Time.at(1300000000.0).usec == 0
     203  assert_equal(0, Time.at(1300000000.0).usec)
    172204end
    173205
    174206assert('Time#utc', '15.2.19.7.27') do
    175   Time.at(1300000000.0).utc
     207  t = Time.now
     208  assert_predicate(t.utc, :gmt?)
     209  assert_predicate(t, :gmt?)
    176210end
    177211
    178212assert('Time#utc?', '15.2.19.7.28') do
    179   Time.at(1300000000.0).utc.utc?
     213  assert_predicate(Time.at(1300000000.0).utc, :utc?)
    180214end
    181215
     
    184218
    185219assert('Time#wday', '15.2.19.7.30') do
    186   Time.gm(2012, 12, 23).wday == 0
     220  assert_equal(0, Time.gm(2012, 12, 23).wday)
    187221end
    188222
    189223assert('Time#yday', '15.2.19.7.31') do
    190   Time.gm(2012, 12, 23).yday == 358
     224  assert_equal(358, Time.gm(2012, 12, 23).yday)
    191225end
    192226
    193227assert('Time#year', '15.2.19.7.32') do
    194   Time.gm(2012, 12, 23).year == 2012
     228  assert_equal(2012, Time.gm(2012, 12, 23).year)
    195229end
    196230
    197231assert('Time#zone', '15.2.19.7.33') do
    198   Time.at(1300000000.0).utc.zone == 'UTC'
     232  assert_equal('UTC', Time.at(1300000000.0).utc.zone)
    199233end
    200234
     
    202236
    203237assert('Time#to_s') do
    204   Time.at(1300000000.0).utc.to_s == "Sun Mar 13 07:06:40 UTC 2011"
     238  assert_equal("2003-04-05 06:07:08 UTC", Time.gm(2003,4,5,6,7,8,9).to_s)
    205239end
    206240
    207241assert('Time#inspect') do
    208   Time.at(1300000000.0).utc.inspect == "Sun Mar 13 07:06:40 UTC 2011"
     242  assert_match("2013-10-28 16:27:48 [+-][0-9][0-9][0-9][0-9]",
     243               Time.local(2013,10,28,16,27,48).inspect)
    209244end
    210245
     
    225260    t += 0.0005
    226261  end
    227   t.usec == 0
    228 end
     262  assert_equal(0, t.usec)
     263end
     264
     265assert('Time.gm with Dec 31 23:59:59 1969 raise ArgumentError') do
     266  assert_raise(ArgumentError) {Time.gm(1969, 12, 31, 23, 59, 59)}
     267end
  • EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-toplevel-ext/test/toplevel.rb

    r321 r439  
    1717  self.include ToplevelTestModule2, ToplevelTestModule1
    1818
    19   assert_true self.class.included_modules.include?( ToplevelTestModule1 )
    20   assert_true self.class.included_modules.include?( ToplevelTestModule2 )
     19  assert_true self.class.ancestors.include?( ToplevelTestModule1 )
     20  assert_true self.class.ancestors.include?( ToplevelTestModule2 )
    2121  assert_equal :foo, method_foo
    2222  assert_equal :bar2, CONST_BAR
Note: See TracChangeset for help on using the changeset viewer.