summaryrefslogtreecommitdiffhomepage
path: root/src/etc.c
blob: eac71459c7c2e498404fd2df0ba27c705b037ebf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
/*
** etc.c -
**
** See Copyright Notice in mruby.h
*/

#include "mruby.h"
#include "mruby/string.h"
#include "error.h"
#include "mruby/numeric.h"
#include "mruby/data.h"

#ifndef FALSE
#define FALSE   0
#endif

#ifndef TRUE
#define TRUE    1
#endif

struct RData*
mrb_data_object_alloc(mrb_state *mrb, struct RClass *klass, void *ptr, const struct mrb_data_type *type)
{
  struct RData *data;

  data = mrb_obj_alloc(mrb, MRB_TT_DATA, klass);
  data->data = ptr;
  data->type = (struct mrb_data_type *) type;

  return data;
}

void *
mrb_get_datatype(mrb_state *mrb, mrb_value obj, const struct mrb_data_type *type)
{
  if (SPECIAL_CONST_P(obj) || (mrb_type(obj) != MRB_TT_DATA)) {
    return NULL;
  }
  if (DATA_TYPE(obj) != type) {
    return NULL;
  }
  return DATA_PTR(obj);
}

void *
mrb_check_datatype(mrb_state *mrb, mrb_value obj, const struct mrb_data_type *type)
{
  static const char mesg[] = "wrong argument type %s (expected %s)";

  if (SPECIAL_CONST_P(obj) || (mrb_type(obj) != MRB_TT_DATA)) {
    mrb_check_type(mrb, obj, MRB_TT_DATA);
  }
  if (DATA_TYPE(obj) != type) {
    const char *etype = DATA_TYPE(obj)->struct_name;
    mrb_raise(mrb, E_TYPE_ERROR, mesg, etype, type->struct_name);
  }
  return DATA_PTR(obj);
}

mrb_value
mrb_lastline_get(mrb_state *mrb)
{
  //mrb_value *var = mrb_svar(0);
  //if (var) {
  //  return *var;
  //}
  //return mrb_nil_value();
  mrb_value *argv;
  int argc;
  mrb_get_args(mrb, "*", &argv, &argc);
  if (argc < 1) {
    return mrb_nil_value();
  }
  else
  {
    return argv[0];
  }
}

mrb_value
mrb_rescue2(mrb_state *mrb, mrb_value (* b_proc) (ANYARGS), mrb_value *data1,
                           mrb_value (* r_proc) (ANYARGS), mrb_value *data2, ...)
{
    mrb_value result = (*b_proc) (mrb, data1);
    return result;
}

mrb_value
mrb_rescue(mrb_state *mrb, mrb_value (* b_proc)(ANYARGS), mrb_value *data1,
                          mrb_value (* r_proc)(ANYARGS), mrb_value *data2)
{
  return mrb_rescue2(mrb, b_proc, data1, r_proc, data2, mrb->eStandardError_class,
                         mrb_fixnum_value(0));
}
/* ------------------------------------------------ */
/*
 * Calls func(obj, arg, recursive), where recursive is non-zero if the
 * current method is called recursively on obj
 */

mrb_value
mrb_exec_recursive(mrb_state *mrb, mrb_value (*func) (mrb_state *, mrb_value, mrb_value, int), mrb_value obj, void *arg)
{
  //  return mrb_exec_recursive(mrb, io_puts_ary, line, &out);
  return func(mrb, obj, *(mrb_value*)arg, 0);
}

/*
 * Calls func(obj, arg, recursive), where recursive is non-zero if the
 * current method is called recursively on the ordered pair <obj, paired_obj>
 */

mrb_value
mrb_exec_recursive_paired(mrb_state *mrb, mrb_value (*func) (mrb_state *, mrb_value, mrb_value, int),
                                             mrb_value obj, mrb_value paired_obj, void* arg)
{
  //  return mrb_exec_recursive_paired(mrb, recursive_eql, hash1, hash2, mrb_fixnum_value((int)&data));
  return func(mrb, obj, paired_obj, 0);
}

mrb_sym
mrb_to_id(mrb_state *mrb, mrb_value name)
{
  mrb_value tmp;
  mrb_sym id;

  switch (mrb_type(name)) {
    default:
      tmp = mrb_check_string_type(mrb, name);
      if (mrb_nil_p(tmp)) {
        tmp = mrb_inspect(mrb, name);
        mrb_raise(mrb, E_TYPE_ERROR, "%s is not a symbol",
             RSTRING_PTR(tmp));
      }
      name = tmp;
      /* fall through */
    case MRB_TT_STRING:
      name = mrb_str_intern(mrb, name);
      /* fall through */
    case MRB_TT_SYMBOL:
      return SYM2ID(name);
  }
  return id;
}

/*
 * call-seq:
 *   proc   { |...| block }  -> a_proc
 *
 * Equivalent to <code>Proc.new</code>.
 */

mrb_value
mrb_block_proc(void)
{
  return mrb_nil_value();//proc_new(mrb_cProc, FALSE);
}

/*
 *  Document-method: __id__
 *  Document-method: object_id
 *
 *  call-seq:
 *     obj.__id__       -> fixnum
 *     obj.object_id    -> fixnum
 *
 *  Returns an integer identifier for <i>obj</i>. The same number will
 *  be returned on all calls to <code>id</code> for a given object, and
 *  no two active objects will share an id.
 *  <code>Object#object_id</code> is a different concept from the
 *  <code>:name</code> notation, which returns the symbol id of
 *  <code>name</code>. Replaces the deprecated <code>Object#id</code>.
 */

/*
 *  call-seq:
 *     obj.hash    -> fixnum
 *
 *  Generates a <code>Fixnum</code> hash value for this object. This
 *  function must have the property that <code>a.eql?(b)</code> implies
 *  <code>a.hash == b.hash</code>. The hash value is used by class
 *  <code>Hash</code>. Any hash value that exceeds the capacity of a
 *  <code>Fixnum</code> will be truncated before being used.
 */

int
mrb_obj_id(mrb_value obj)
{
    /*
     *                32-bit mrb_value space
     *          MSB ------------------------ LSB
     *  false   00000000000000000000000000000000
     *  true    00000000000000000000000000000010
     *  nil     00000000000000000000000000000100
     *  undef   00000000000000000000000000000110
     *  symbol  ssssssssssssssssssssssss00001110
     *  object  oooooooooooooooooooooooooooooo00        = 0 (mod sizeof(RVALUE))
     *  fixnum  fffffffffffffffffffffffffffffff1
     *
     *                    object_id space
     *                                       LSB
     *  false   00000000000000000000000000000000
     *  true    00000000000000000000000000000010
     *  nil     00000000000000000000000000000100
     *  undef   00000000000000000000000000000110
     *  symbol   000SSSSSSSSSSSSSSSSSSSSSSSSSSS0        S...S % A = 4 (S...S = s...s * A + 4)
     *  object   oooooooooooooooooooooooooooooo0        o...o % A = 0
     *  fixnum  fffffffffffffffffffffffffffffff1        bignum if required
     *
     *  where A = sizeof(RVALUE)/4
     *
     *  sizeof(RVALUE) is
     *  20 if 32-bit, double is 4-byte aligned
     *  24 if 32-bit, double is 8-byte aligned
     *  40 if 64-bit
     */
    /*
     *                128-bit mrb_value space
     *          MSB -------- LSB
     *  x86           [0,1]             [2,3]            [4,5]            [6,7]            [8,9]            [A,B]            [C,D]            [E,F]
     *          7                6                5                4                3                2                1                0
     *          0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF 0123456789ABCDEF
     *          FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210 FEDCBA9876543210
     *  false   0000000000000000 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000001 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
     *  true    0000000000000001 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000010 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
     *  nil     0000000000000001 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000001 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
     *  undef   0000000000000000 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000101 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
     *  symbol  ssssssssssssssss ssssssssssssssss xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000100 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
     *  object  oooooooooooooooo oooooooooooooo00        = 0 (mod sizeof(RVALUE))
     (1)fixnum  0000000000000001 0000000000000000 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxx00000011 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
     *  float   0000000000000001 0000000000000000 0000000000000000 0000000000000000 xxxxxxxx00000011 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
     *          <--                          mrb_float                          --> xxxxxxxx00001101 xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
     *
     *                    object_id space
     *                                       LSB
     *  false   0000000000000000 0000000000000000
     *  true    0000000000000000 0000000000000010
     *  nil     0000000000000000 0000000000000100
     *  undef   0000000000000000 0000000000000110
     *  symbol  000SSSSSSSSSSSS SSSSSSSSSSSSSSS0        S...S % A = 4 (S...S = s...s * A + 4)
     *  object  ooooooooooooooo ooooooooooooooo0        o...o % A = 0
     *  fixnum  ffffffffffffffff fffffffffffffff1        bignum if required
     *
     *  where A = sizeof(RVALUE)/4
     *
     *  sizeof(RVALUE) is
     *  20 if 32-bit, double is 4-byte aligned
     *  24 if 32-bit, double is 8-byte aligned
     *  40 if 64-bit
     */
    /* tt:0_27 */
  switch (mrb_type(obj)) {
    case  MRB_TT_FREE:
      return 0; /* not define */
    case  MRB_TT_FALSE:
      if (mrb_nil_p(obj))
        return 4;
      return 0;
    case  MRB_TT_TRUE:
      return 2;
    case  MRB_TT_FIXNUM:
      return mrb_fixnum(obj)*2+1; /* odd number */
    case  MRB_TT_SYMBOL:
      return SYM2ID(obj) * 2;
    case  MRB_TT_UNDEF:
      return 0; /* not define */
    case  MRB_TT_FLOAT:
      return (int)mrb_float(obj)*2; /* even number */
    case  MRB_TT_OBJECT:
    case  MRB_TT_CLASS:
    case  MRB_TT_MODULE:
    case  MRB_TT_ICLASS:
    case  MRB_TT_SCLASS:
    case  MRB_TT_PROC:
    case  MRB_TT_ARRAY:
    case  MRB_TT_HASH:
    case  MRB_TT_STRING:
    case  MRB_TT_RANGE:
    case  MRB_TT_REGEX:
    case  MRB_TT_STRUCT:
    case  MRB_TT_EXCEPTION:
    case  MRB_TT_MATCH:
    case  MRB_TT_FILE:
    case  MRB_TT_DATA:
    case  MRB_TT_THREAD:
    case  MRB_TT_THREADGRP:
    default:
      return mrb_fixnum(obj); /* even number */
  }
}