Skip to content

Commit ad9e841

Browse files
committed
made mrb_get_args() better (optinal args, type checks); close mruby#173 mruby#176
1 parent 4f012f5 commit ad9e841

17 files changed

Lines changed: 248 additions & 161 deletions

File tree

include/mruby.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ int mrb_get_args(mrb_state *mrb, const char *format, ...);
329329

330330
mrb_value mrb_funcall(mrb_state*, mrb_value, const char*, int,...);
331331
mrb_value mrb_funcall_argv(mrb_state*, mrb_value, const char*, int, mrb_value*);
332-
mrb_value mrb_funcall_with_block(mrb_state*, mrb_value, const char*, int, mrb_value*, struct RProc*);
332+
mrb_value mrb_funcall_with_block(mrb_state*, mrb_value, const char*, int, mrb_value*, mrb_value);
333333
mrb_sym mrb_intern(mrb_state*,const char*);
334334
const char *mrb_sym2name(mrb_state*,mrb_sym);
335335
mrb_value mrb_str_format(mrb_state *, int, const mrb_value *, mrb_value);

include/mruby/hash.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key);
3131
mrb_value mrb_hash_getWithDef(mrb_state *mrb, mrb_value hash, mrb_value vkey, mrb_value def);
3232
mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key);
3333
mrb_value mrb_hash(mrb_state *mrb, mrb_value obj);
34-
void ruby_setenv(mrb_state *mrb, const char *name, const char *value);
34+
mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value self);
3535

3636
/* RHASH_TBL allocates st_table if not available. */
3737
#define RHASH(obj) ((struct RHash*)((obj).value.p))

src/array.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -177,10 +177,7 @@ mrb_ary_concat_m(mrb_state *mrb, mrb_value self)
177177
{
178178
mrb_value other;
179179

180-
mrb_get_args(mrb, "o", &other);
181-
if (mrb_type(other) != MRB_TT_ARRAY) {
182-
mrb_raise(mrb, E_ARGUMENT_ERROR, "expected Array");
183-
}
180+
mrb_get_args(mrb, "A", &other);
184181
mrb_ary_concat(mrb, self, other);
185182
return self;
186183
}
@@ -193,11 +190,7 @@ mrb_ary_plus(mrb_state *mrb, mrb_value self)
193190
mrb_value other;
194191
mrb_value ary;
195192

196-
mrb_get_args(mrb, "o", &other);
197-
if (mrb_type(other) != MRB_TT_ARRAY) {
198-
mrb_raise(mrb, E_ARGUMENT_ERROR, "expected Array");
199-
}
200-
193+
mrb_get_args(mrb, "A", &other);
201194
ary = mrb_ary_new_capa(mrb, a1->len + RARRAY_LEN(other));
202195
a2 = mrb_ary_ptr(ary);
203196
memcpy(a2->buf, a1->buf, sizeof(mrb_value)*a1->len);

src/class.c

Lines changed: 169 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -328,15 +328,67 @@ mrb_define_method_vm(mrb_state *mrb, struct RClass *c, mrb_sym name, mrb_value b
328328
kh_value(h, k) = mrb_proc_ptr(body);
329329
}
330330

331+
static mrb_value
332+
check_type(mrb_state *mrb, mrb_value val, enum mrb_vtype t, const char *c, const char *m)
333+
{
334+
mrb_value tmp;
335+
336+
tmp = mrb_check_convert_type(mrb, val, t, c, m);
337+
if (mrb_nil_p(tmp)) {
338+
mrb_raise(mrb, E_TYPE_ERROR, "expected %s", c);
339+
}
340+
return tmp;
341+
}
342+
343+
static mrb_value
344+
to_str(mrb_state *mrb, mrb_value val)
345+
{
346+
return check_type(mrb, val, MRB_TT_STRING, "String", "to_str");
347+
}
348+
349+
static mrb_value
350+
to_ary(mrb_state *mrb, mrb_value val)
351+
{
352+
return check_type(mrb, val, MRB_TT_ARRAY, "Array", "to_ary");
353+
}
354+
355+
static mrb_value
356+
to_hash(mrb_state *mrb, mrb_value val)
357+
{
358+
return check_type(mrb, val, MRB_TT_HASH, "Hash", "to_hash");
359+
}
360+
361+
/*
362+
retrieve arguments from mrb_state.
363+
364+
mrb_get_args(mrb, format, ...)
365+
366+
returns number of arguments parsed.
367+
368+
fortmat specifiers:
369+
370+
o: Object [mrb_value]
371+
S: String [mrb_value]
372+
A: Array [mrb_value]
373+
H: Hash [mrb_value]
374+
s: String [char*,int]
375+
z: String [char*]
376+
a: Array [mrb_value*,int]
377+
f: Float [mrb_float]
378+
i: Integer [mrb_int]
379+
&: Block [mrb_value]
380+
*: rest argument [mrb_value*,int]
381+
|: optional
382+
*/
331383
int
332384
mrb_get_args(mrb_state *mrb, const char *format, ...)
333385
{
334386
char c;
335-
int i=0;
387+
int i = 0;
336388
mrb_value *sp = mrb->stack + 1;
337389
va_list ap;
338390
int argc = mrb->ci->argc;
339-
int *argcp;
391+
int opt = 0;
340392

341393
va_start(ap, format);
342394
if (argc < 0) {
@@ -346,39 +398,92 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
346398
sp = a->buf;
347399
}
348400
while ((c = *format++)) {
401+
if (argc < i) {
402+
if (opt) continue;
403+
mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
404+
}
349405
switch (c) {
350406
case 'o':
351407
{
352408
mrb_value *p;
409+
353410
p = va_arg(ap, mrb_value*);
354411
*p = *sp;
355412
i++; sp++;
356413
}
357414
break;
358-
case 'i':
415+
case 'S':
359416
{
360-
mrb_int *p;
417+
mrb_value *p;
361418

362-
p = va_arg(ap, mrb_int*);
363-
switch (sp->tt) {
364-
case MRB_TT_FIXNUM:
365-
*p = mrb_fixnum(*sp);
366-
break;
367-
case MRB_TT_FLOAT:
368-
*p = (mrb_int)mrb_float(*sp);
369-
break;
370-
case MRB_TT_FALSE:
371-
*p = 0;
372-
break;
373-
default:
374-
{
375-
mrb_value tmp;
419+
p = va_arg(ap, mrb_value*);
420+
*p = to_str(mrb, *sp);
421+
i++; sp++;
422+
}
423+
break;
424+
case 'A':
425+
{
426+
mrb_value *p;
376427

377-
tmp = mrb_convert_type(mrb, *sp, MRB_TT_FIXNUM, "Integer", "to_int");
378-
*p = mrb_fixnum(tmp);
379-
}
380-
break;
381-
}
428+
p = va_arg(ap, mrb_value*);
429+
*p = to_ary(mrb, *sp);
430+
i++; sp++;
431+
}
432+
break;
433+
case 'H':
434+
{
435+
mrb_value *p;
436+
437+
p = va_arg(ap, mrb_value*);
438+
*p = to_hash(mrb, *sp);
439+
i++; sp++;
440+
}
441+
break;
442+
case 's':
443+
{
444+
mrb_value ss;
445+
struct RString *s;
446+
char **ps = 0;
447+
int *pl = 0;
448+
449+
ss = to_str(mrb, *sp);
450+
s = mrb_str_ptr(ss);
451+
ps = va_arg(ap, char**);
452+
*ps = s->buf;
453+
pl = va_arg(ap, int*);
454+
*pl = s->len;
455+
i++; sp++;
456+
}
457+
break;
458+
case 'z':
459+
{
460+
mrb_value ss;
461+
struct RString *s;
462+
char **ps;
463+
464+
ss = to_str(mrb, *sp);
465+
s = mrb_str_ptr(ss);
466+
if (strlen(s->buf) != s->len) {
467+
mrb_raise(mrb, E_ARGUMENT_ERROR, "String contains NUL");
468+
}
469+
ps = va_arg(ap, char**);
470+
*ps = s->buf;
471+
i++; sp++;
472+
}
473+
break;
474+
case 'a':
475+
{
476+
mrb_value aa;
477+
struct RArray *a;
478+
mrb_value **pb;
479+
int *pl;
480+
481+
aa = to_ary(mrb, *sp);
482+
a = mrb_ary_ptr(aa);
483+
pb = va_arg(ap, mrb_value**);
484+
*pb = a->buf;
485+
pl = va_arg(ap, int*);
486+
*pl = a->len;
382487
i++; sp++;
383488
}
384489
break;
@@ -409,53 +514,34 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
409514
i++; sp++;
410515
}
411516
break;
412-
case 's':
517+
case 'i':
413518
{
414-
char **ps = 0;
415-
size_t *pl = 0;
416-
struct RString *s;
519+
mrb_int *p;
417520

418-
if (argc > i) {
419-
s = mrb_str_ptr(*sp);
420-
ps = va_arg(ap, char**);
421-
*ps = s->buf;
422-
pl = va_arg(ap, size_t*);
423-
*pl = s->len;
521+
p = va_arg(ap, mrb_int*);
522+
switch (sp->tt) {
523+
case MRB_TT_FIXNUM:
524+
*p = mrb_fixnum(*sp);
525+
break;
526+
case MRB_TT_FLOAT:
527+
*p = (mrb_int)mrb_float(*sp);
528+
break;
529+
case MRB_TT_FALSE:
530+
*p = 0;
531+
break;
532+
default:
533+
{
534+
mrb_value tmp;
535+
536+
tmp = mrb_convert_type(mrb, *sp, MRB_TT_FIXNUM, "Integer", "to_int");
537+
*p = mrb_fixnum(tmp);
538+
}
539+
break;
424540
}
425541
i++; sp++;
426542
}
427543
break;
428-
case 'a':
429-
{
430-
mrb_value *var;
431-
var = va_arg(ap, mrb_value*);
432-
if (argc > i) {
433-
if (var) {
434-
memcpy(var, sp, sizeof(mrb_value)*(argc-i));
435-
}
436-
//i = mrb->argc;
437-
}
438-
else {
439-
if (var) *var = mrb_ary_new(mrb);
440-
}
441-
argcp = va_arg(ap, int*);
442-
*argcp = argc-i;
443-
goto last_var;
444-
}
445-
break;
446-
case 'b':
447-
{
448-
struct RProc **p;
449-
mrb_value *bp = mrb->stack + 1;
450544

451-
p = va_arg(ap, struct RProc**);
452-
if (mrb->ci->argc > 0) {
453-
bp += mrb->ci->argc;
454-
}
455-
if (mrb_nil_p(*bp)) *p = 0;
456-
else *p = mrb_proc_ptr(*bp);
457-
}
458-
break;
459545
case '&':
460546
{
461547
mrb_value *p, *bp = mrb->stack + 1;
@@ -467,30 +553,34 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
467553
*p = *bp;
468554
}
469555
break;
556+
case '|':
557+
opt = 1;
558+
break;
470559
case '*':
471560
{
472561
mrb_value **var;
562+
int *pl;
563+
473564
var = va_arg(ap, mrb_value**);
474-
argcp = va_arg(ap, int*);
565+
pl = va_arg(ap, int*);
475566
if (argc > i) {
476-
*argcp = argc-i;
477-
if (*argcp > 0) {
478-
if (var) {
479-
*var = sp;
480-
}
481-
i += *argcp;
567+
*pl = argc-i;
568+
if (*pl > 0) {
569+
*var = sp;
570+
i = argc;
482571
}
483572
}
484573
else {
485-
*argcp = 0;
574+
*pl = 0;
486575
*var = NULL;
487576
}
488-
goto last_var;
489577
}
490578
break;
491579
}
492580
}
493-
last_var:
581+
if (!*format && argc > i) {
582+
mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
583+
}
494584
va_end(ap);
495585
return 0;
496586
}
@@ -679,17 +769,17 @@ mrb_value
679769
mrb_class_new_instance_m(mrb_state *mrb, mrb_value klass)
680770
{
681771
mrb_value *argv;
682-
struct RProc *b;
772+
mrb_value blk;
683773
struct RClass *k = mrb_class_ptr(klass);
684774
struct RClass *c;
685775
int argc;
686776
mrb_value obj;
687777

688-
mrb_get_args(mrb, "b*", &b, &argv, &argc);
778+
mrb_get_args(mrb, "*&", &argv, &argc, &blk);
689779
c = (struct RClass*)mrb_obj_alloc(mrb, k->tt, k);
690780
c->super = k;
691781
obj = mrb_obj_value(c);
692-
mrb_funcall_with_block(mrb, obj, "initialize", argc, argv, b);
782+
mrb_funcall_with_block(mrb, obj, "initialize", argc, argv, blk);
693783

694784
return obj;
695785
}
@@ -698,18 +788,17 @@ mrb_value
698788
mrb_instance_new(mrb_state *mrb, mrb_value cv)
699789
{
700790
struct RClass *c = mrb_class_ptr(cv);
701-
struct RProc *b;
702791
struct RObject *o;
703792
enum mrb_vtype ttype = MRB_INSTANCE_TT(c);
704-
mrb_value obj;
793+
mrb_value obj, blk;
705794
mrb_value *argv;
706795
int argc;
707796

708797
if (ttype == 0) ttype = MRB_TT_OBJECT;
709798
o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c);
710799
obj = mrb_obj_value(o);
711-
mrb_get_args(mrb, "b*", &b, &argv, &argc);
712-
mrb_funcall_with_block(mrb, obj, "initialize", argc, argv, b);
800+
mrb_get_args(mrb, "*&", &argv, &argc, &blk);
801+
mrb_funcall_with_block(mrb, obj, "initialize", argc, argv, blk);
713802

714803
return obj;
715804
}

0 commit comments

Comments
 (0)