Permalink
Browse files

made mrb_get_args() better (optinal args, type checks); close #173 #176

  • Loading branch information...
1 parent 4f012f5 commit ad9e841c5359efdd37a132767e03ad7a2d5ae72e @matz matz committed May 23, 2012
Showing with 248 additions and 161 deletions.
  1. +1 −1 include/mruby.h
  2. +1 −1 include/mruby/hash.h
  3. +2 −9 src/array.c
  4. +169 −80 src/class.c
  5. +5 −1 src/encoding.c
  6. +0 −2 src/error.c
  7. +1 −0 src/etc.c
  8. +8 −6 src/gc.c
  9. +4 −7 src/hash.c
  10. +1 −1 src/kernel.c
  11. +4 −3 src/numeric.c
  12. +9 −8 src/range.c
  13. +3 −1 src/re.c
  14. +7 −4 src/string.c
  15. +27 −25 src/struct.c
  16. +3 −4 src/time.c
  17. +3 −8 src/vm.c
View
@@ -329,7 +329,7 @@ int mrb_get_args(mrb_state *mrb, const char *format, ...);
mrb_value mrb_funcall(mrb_state*, mrb_value, const char*, int,...);
mrb_value mrb_funcall_argv(mrb_state*, mrb_value, const char*, int, mrb_value*);
-mrb_value mrb_funcall_with_block(mrb_state*, mrb_value, const char*, int, mrb_value*, struct RProc*);
+mrb_value mrb_funcall_with_block(mrb_state*, mrb_value, const char*, int, mrb_value*, mrb_value);
mrb_sym mrb_intern(mrb_state*,const char*);
const char *mrb_sym2name(mrb_state*,mrb_sym);
mrb_value mrb_str_format(mrb_state *, int, const mrb_value *, mrb_value);
View
@@ -31,7 +31,7 @@ mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key);
mrb_value mrb_hash_getWithDef(mrb_state *mrb, mrb_value hash, mrb_value vkey, mrb_value def);
mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value key);
mrb_value mrb_hash(mrb_state *mrb, mrb_value obj);
-void ruby_setenv(mrb_state *mrb, const char *name, const char *value);
+mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value self);
/* RHASH_TBL allocates st_table if not available. */
#define RHASH(obj) ((struct RHash*)((obj).value.p))
View
@@ -177,10 +177,7 @@ mrb_ary_concat_m(mrb_state *mrb, mrb_value self)
{
mrb_value other;
- mrb_get_args(mrb, "o", &other);
- if (mrb_type(other) != MRB_TT_ARRAY) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "expected Array");
- }
+ mrb_get_args(mrb, "A", &other);
mrb_ary_concat(mrb, self, other);
return self;
}
@@ -193,11 +190,7 @@ mrb_ary_plus(mrb_state *mrb, mrb_value self)
mrb_value other;
mrb_value ary;
- mrb_get_args(mrb, "o", &other);
- if (mrb_type(other) != MRB_TT_ARRAY) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "expected Array");
- }
-
+ mrb_get_args(mrb, "A", &other);
ary = mrb_ary_new_capa(mrb, a1->len + RARRAY_LEN(other));
a2 = mrb_ary_ptr(ary);
memcpy(a2->buf, a1->buf, sizeof(mrb_value)*a1->len);
View
@@ -328,15 +328,67 @@ mrb_define_method_vm(mrb_state *mrb, struct RClass *c, mrb_sym name, mrb_value b
kh_value(h, k) = mrb_proc_ptr(body);
}
+static mrb_value
+check_type(mrb_state *mrb, mrb_value val, enum mrb_vtype t, const char *c, const char *m)
+{
+ mrb_value tmp;
+
+ tmp = mrb_check_convert_type(mrb, val, t, c, m);
+ if (mrb_nil_p(tmp)) {
+ mrb_raise(mrb, E_TYPE_ERROR, "expected %s", c);
+ }
+ return tmp;
+}
+
+static mrb_value
+to_str(mrb_state *mrb, mrb_value val)
+{
+ return check_type(mrb, val, MRB_TT_STRING, "String", "to_str");
+}
+
+static mrb_value
+to_ary(mrb_state *mrb, mrb_value val)
+{
+ return check_type(mrb, val, MRB_TT_ARRAY, "Array", "to_ary");
+}
+
+static mrb_value
+to_hash(mrb_state *mrb, mrb_value val)
+{
+ return check_type(mrb, val, MRB_TT_HASH, "Hash", "to_hash");
+}
+
+/*
+ retrieve arguments from mrb_state.
+
+ mrb_get_args(mrb, format, ...)
+
+ returns number of arguments parsed.
+
+ fortmat specifiers:
+
+ o: Object [mrb_value]
+ S: String [mrb_value]
+ A: Array [mrb_value]
+ H: Hash [mrb_value]
+ s: String [char*,int]
+ z: String [char*]
+ a: Array [mrb_value*,int]
+ f: Float [mrb_float]
+ i: Integer [mrb_int]
+ &: Block [mrb_value]
+ *: rest argument [mrb_value*,int]
+ |: optional
+ */
int
mrb_get_args(mrb_state *mrb, const char *format, ...)
{
char c;
- int i=0;
+ int i = 0;
mrb_value *sp = mrb->stack + 1;
va_list ap;
int argc = mrb->ci->argc;
- int *argcp;
+ int opt = 0;
va_start(ap, format);
if (argc < 0) {
@@ -346,39 +398,92 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
sp = a->buf;
}
while ((c = *format++)) {
+ if (argc < i) {
+ if (opt) continue;
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
+ }
switch (c) {
case 'o':
{
mrb_value *p;
+
p = va_arg(ap, mrb_value*);
*p = *sp;
i++; sp++;
}
break;
- case 'i':
+ case 'S':
{
- mrb_int *p;
+ mrb_value *p;
- p = va_arg(ap, mrb_int*);
- switch (sp->tt) {
- case MRB_TT_FIXNUM:
- *p = mrb_fixnum(*sp);
- break;
- case MRB_TT_FLOAT:
- *p = (mrb_int)mrb_float(*sp);
- break;
- case MRB_TT_FALSE:
- *p = 0;
- break;
- default:
- {
- mrb_value tmp;
+ p = va_arg(ap, mrb_value*);
+ *p = to_str(mrb, *sp);
+ i++; sp++;
+ }
+ break;
+ case 'A':
+ {
+ mrb_value *p;
- tmp = mrb_convert_type(mrb, *sp, MRB_TT_FIXNUM, "Integer", "to_int");
- *p = mrb_fixnum(tmp);
- }
- break;
- }
+ p = va_arg(ap, mrb_value*);
+ *p = to_ary(mrb, *sp);
+ i++; sp++;
+ }
+ break;
+ case 'H':
+ {
+ mrb_value *p;
+
+ p = va_arg(ap, mrb_value*);
+ *p = to_hash(mrb, *sp);
+ i++; sp++;
+ }
+ break;
+ case 's':
+ {
+ mrb_value ss;
+ struct RString *s;
+ char **ps = 0;
+ int *pl = 0;
+
+ ss = to_str(mrb, *sp);
+ s = mrb_str_ptr(ss);
+ ps = va_arg(ap, char**);
+ *ps = s->buf;
+ pl = va_arg(ap, int*);
+ *pl = s->len;
+ i++; sp++;
+ }
+ break;
+ case 'z':
+ {
+ mrb_value ss;
+ struct RString *s;
+ char **ps;
+
+ ss = to_str(mrb, *sp);
+ s = mrb_str_ptr(ss);
+ if (strlen(s->buf) != s->len) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "String contains NUL");
+ }
+ ps = va_arg(ap, char**);
+ *ps = s->buf;
+ i++; sp++;
+ }
+ break;
+ case 'a':
+ {
+ mrb_value aa;
+ struct RArray *a;
+ mrb_value **pb;
+ int *pl;
+
+ aa = to_ary(mrb, *sp);
+ a = mrb_ary_ptr(aa);
+ pb = va_arg(ap, mrb_value**);
+ *pb = a->buf;
+ pl = va_arg(ap, int*);
+ *pl = a->len;
i++; sp++;
}
break;
@@ -409,53 +514,34 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
i++; sp++;
}
break;
- case 's':
+ case 'i':
{
- char **ps = 0;
- size_t *pl = 0;
- struct RString *s;
+ mrb_int *p;
- if (argc > i) {
- s = mrb_str_ptr(*sp);
- ps = va_arg(ap, char**);
- *ps = s->buf;
- pl = va_arg(ap, size_t*);
- *pl = s->len;
+ p = va_arg(ap, mrb_int*);
+ switch (sp->tt) {
+ case MRB_TT_FIXNUM:
+ *p = mrb_fixnum(*sp);
+ break;
+ case MRB_TT_FLOAT:
+ *p = (mrb_int)mrb_float(*sp);
+ break;
+ case MRB_TT_FALSE:
+ *p = 0;
+ break;
+ default:
+ {
+ mrb_value tmp;
+
+ tmp = mrb_convert_type(mrb, *sp, MRB_TT_FIXNUM, "Integer", "to_int");
+ *p = mrb_fixnum(tmp);
+ }
+ break;
}
i++; sp++;
}
break;
- case 'a':
- {
- mrb_value *var;
- var = va_arg(ap, mrb_value*);
- if (argc > i) {
- if (var) {
- memcpy(var, sp, sizeof(mrb_value)*(argc-i));
- }
- //i = mrb->argc;
- }
- else {
- if (var) *var = mrb_ary_new(mrb);
- }
- argcp = va_arg(ap, int*);
- *argcp = argc-i;
- goto last_var;
- }
- break;
- case 'b':
- {
- struct RProc **p;
- mrb_value *bp = mrb->stack + 1;
- p = va_arg(ap, struct RProc**);
- if (mrb->ci->argc > 0) {
- bp += mrb->ci->argc;
- }
- if (mrb_nil_p(*bp)) *p = 0;
- else *p = mrb_proc_ptr(*bp);
- }
- break;
case '&':
{
mrb_value *p, *bp = mrb->stack + 1;
@@ -467,30 +553,34 @@ mrb_get_args(mrb_state *mrb, const char *format, ...)
*p = *bp;
}
break;
+ case '|':
+ opt = 1;
+ break;
case '*':
{
mrb_value **var;
+ int *pl;
+
var = va_arg(ap, mrb_value**);
- argcp = va_arg(ap, int*);
+ pl = va_arg(ap, int*);
if (argc > i) {
- *argcp = argc-i;
- if (*argcp > 0) {
- if (var) {
- *var = sp;
- }
- i += *argcp;
+ *pl = argc-i;
+ if (*pl > 0) {
+ *var = sp;
+ i = argc;
}
}
else {
- *argcp = 0;
+ *pl = 0;
*var = NULL;
}
- goto last_var;
}
break;
}
}
-last_var:
+ if (!*format && argc > i) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arguments");
+ }
va_end(ap);
return 0;
}
@@ -679,17 +769,17 @@ mrb_value
mrb_class_new_instance_m(mrb_state *mrb, mrb_value klass)
{
mrb_value *argv;
- struct RProc *b;
+ mrb_value blk;
struct RClass *k = mrb_class_ptr(klass);
struct RClass *c;
int argc;
mrb_value obj;
- mrb_get_args(mrb, "b*", &b, &argv, &argc);
+ mrb_get_args(mrb, "*&", &argv, &argc, &blk);
c = (struct RClass*)mrb_obj_alloc(mrb, k->tt, k);
c->super = k;
obj = mrb_obj_value(c);
- mrb_funcall_with_block(mrb, obj, "initialize", argc, argv, b);
+ mrb_funcall_with_block(mrb, obj, "initialize", argc, argv, blk);
return obj;
}
@@ -698,18 +788,17 @@ mrb_value
mrb_instance_new(mrb_state *mrb, mrb_value cv)
{
struct RClass *c = mrb_class_ptr(cv);
- struct RProc *b;
struct RObject *o;
enum mrb_vtype ttype = MRB_INSTANCE_TT(c);
- mrb_value obj;
+ mrb_value obj, blk;
mrb_value *argv;
int argc;
if (ttype == 0) ttype = MRB_TT_OBJECT;
o = (struct RObject*)mrb_obj_alloc(mrb, ttype, c);
obj = mrb_obj_value(o);
- mrb_get_args(mrb, "b*", &b, &argv, &argc);
- mrb_funcall_with_block(mrb, obj, "initialize", argc, argv, b);
+ mrb_get_args(mrb, "*&", &argv, &argc, &blk);
+ mrb_funcall_with_block(mrb, obj, "initialize", argc, argv, blk);
return obj;
}
Oops, something went wrong.

0 comments on commit ad9e841

Please sign in to comment.