[macruby-changes] [924] MacRuby/branches/experimental
source_changes at macosforge.org
source_changes at macosforge.org
Sun Mar 15 00:08:30 PDT 2009
Revision: 924
http://trac.macosforge.org/projects/ruby/changeset/924
Author: vincent.isambart at gmail.com
Date: 2009-03-15 00:08:29 -0700 (Sun, 15 Mar 2009)
Log Message:
-----------
support for req args after opt args and *rest args
(note: this breaks for, but probably because of a bug in for's code)
Modified Paths:
--------------
MacRuby/branches/experimental/parse.y
MacRuby/branches/experimental/roxor.cpp
Modified: MacRuby/branches/experimental/parse.y
===================================================================
--- MacRuby/branches/experimental/parse.y 2009-03-15 00:44:34 UTC (rev 923)
+++ MacRuby/branches/experimental/parse.y 2009-03-15 07:08:29 UTC (rev 924)
@@ -2892,7 +2892,6 @@
// passed to 'for'.
args = new_args(m, 0, id, 0, 0);
- args->nd_alen = 1;
NODE *block = $8;
if (nd_type(block) != NODE_BLOCK) {
Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp 2009-03-15 00:44:34 UTC (rev 923)
+++ MacRuby/branches/experimental/roxor.cpp 2009-03-15 07:08:29 UTC (rev 924)
@@ -1705,41 +1705,80 @@
return NULL;
}
-static inline int
-rb_vm_node_arity(NODE *node, bool negative_arity=true)
+struct node_arity {
+ short min;
+ short max;
+ short left_req;
+ short real;
+};
+
+static inline node_arity
+rb_vm_node_arity(NODE *node)
{
const int type = nd_type(node);
+ struct node_arity arity;
if (type == NODE_SCOPE) {
NODE *n = node->nd_args;
- int arity = 0;
- bool opt_or_splat = false;
- if (n != NULL) {
- arity = n->nd_frml;
+ short opt_args = 0, req_args = 0;
+ bool has_rest = false;
+ if (n == NULL) {
+ arity.left_req = 0;
+ }
+ else {
+ req_args = n->nd_frml;
+ arity.left_req = req_args;
NODE *n_opt = n->nd_opt;
if (n_opt != NULL) {
NODE *ni = n_opt;
- opt_or_splat = true;
while (ni != NULL) {
- arity++;
+ opt_args++;
ni = ni->nd_next;
}
}
-#if 0
- NODE *n_aux = n->nd_next;
- if (n_aux != NULL) {
- opt_or_splat = true;
- arity++;
+ if (n->nd_next != NULL) {
+ NODE *rest_node = n->nd_next;
+ if (rest_node->nd_rest) {
+ has_rest = true;
+ }
+ if (rest_node->nd_next) {
+ req_args += rest_node->nd_next->nd_frml;
+ }
}
-#endif
}
- return opt_or_splat && negative_arity ? -arity : arity;
+ arity.min = req_args;
+ if (has_rest) {
+ arity.max = -1;
+ arity.real = req_args + opt_args + 1;
+ }
+ else {
+ arity.max = arity.real = req_args + opt_args;
+ }
+ return arity;
}
if (type == NODE_FBODY) {
assert(node->nd_body != NULL);
assert(node->nd_body->nd_body != NULL);
- return node->nd_body->nd_body->nd_argc;
+ int argc = node->nd_body->nd_body->nd_argc;
+ if (argc >= 0) {
+ arity.left_req = arity.real = arity.min = arity.max = argc;
+ }
+ else {
+ arity.left_req = arity.min = 0;
+ arity.max = -1;
+ if (argc == -1) {
+ arity.real = 2;
+ }
+ else if (argc == -2) {
+ arity.real = 1;
+ }
+ else {
+ printf("invalid FBODY arity: %d\n", argc);
+ abort();
+ }
+ }
+ return arity;
}
printf("invalid node %p type %d\n", node, type);
@@ -2039,7 +2078,8 @@
switch (nd_type(node)) {
case NODE_SCOPE:
{
- const int nargs = bb == NULL ? 0 : rb_vm_node_arity(node, false);
+ node_arity arity = rb_vm_node_arity(node);
+ const int nargs = bb == NULL ? 0 : arity.real;
// Get dynamic vars.
if (current_block && node->nd_tbl != NULL) {
@@ -3229,7 +3269,8 @@
params.push_back(compile_current_class());
- const SEL sel = mid_to_sel(mid, rb_vm_node_arity(body));
+ node_arity arity = rb_vm_node_arity(body);
+ const SEL sel = mid_to_sel(mid, arity.real);
params.push_back(compile_const_pointer((void *)sel));
params.push_back(compile_const_pointer(new_function));
@@ -4083,19 +4124,18 @@
{
assert(node != NULL);
- const int arity = rb_vm_node_arity(node);
- assert(arity < MAX_ARITY);
+ const node_arity arity = rb_vm_node_arity(node);
+ assert(arity.real < MAX_ARITY);
assert(klass != NULL);
const char *sel_name = sel_getName(sel);
const bool genuine_selector = sel_name[strlen(sel_name) - 1] == ':';
- int oc_arity = genuine_selector ? (arity < 0 ? -arity : arity) : 0;
+ int oc_arity = genuine_selector ? arity.real : 0;
bool redefined = false;
define_method:
-
char *types;
Method method = class_getInstanceMethod(klass, sel);
if (method != NULL) {
@@ -4115,14 +4155,26 @@
GET_VM()->add_method(klass, sel, imp, node, types);
- if (!redefined && !genuine_selector && arity < 0) {
- char buf[100];
- snprintf(buf, sizeof buf, "%s:", sel_name);
- sel = sel_registerName(buf);
- oc_arity = 1;
- redefined = true;
+ if (!redefined) {
+ if (!genuine_selector && arity.max != arity.min) {
+ char buf[100];
+ snprintf(buf, sizeof buf, "%s:", sel_name);
+ sel = sel_registerName(buf);
+ oc_arity = arity.real;
+ redefined = true;
- goto define_method;
+ goto define_method;
+ }
+ else if (genuine_selector && arity.min == 0) {
+ char buf[100];
+ strlcpy(buf, sel_name, sizeof buf);
+ buf[strlen(buf) - 1] = 0; // remove the ending ':'
+ sel = sel_registerName(buf);
+ oc_arity = 0;
+ redefined = true;
+
+ goto define_method;
+ }
}
}
@@ -4134,26 +4186,54 @@
}
static inline VALUE
-__rb_vm_rcall(VALUE self, NODE *node, IMP pimp, int arity, int argc, const VALUE *argv)
+__rb_vm_rcall(VALUE self, NODE *node, IMP pimp, const node_arity &arity, int argc, const VALUE *argv)
{
- if (arity < 0 && -arity != argc) {
- VALUE *new_argv = (VALUE *)alloca(sizeof(VALUE) * -arity);
- assert(node->nd_args != NULL);
- assert(node->nd_args->nd_frml < -arity);
- if (node->nd_args->nd_frml > argc) {
- // TODO this should be an exception
- printf("bad arity\n");
- abort();
+ if ((arity.real != argc) || (arity.max == -1)) {
+ VALUE *new_argv = (VALUE *)alloca(sizeof(VALUE) * arity.real);
+ assert(argc >= arity.min);
+ assert((arity.max == -1) || (argc <= arity.max));
+ int used_opt_args = argc - arity.min;
+ int opt_args, rest_pos;
+ if (arity.max == -1) {
+ opt_args = arity.real - arity.min - 1;
+ rest_pos = arity.left_req + opt_args;
}
- for (int i = 0; i < -arity; i++) {
- if (i < argc) {
+ else {
+ opt_args = arity.real - arity.min;
+ rest_pos = -1;
+ }
+ for (int i = 0; i < arity.real; ++i) {
+ if (i < arity.left_req) {
+ // required args before optional args
new_argv[i] = argv[i];
}
+ else if (i < arity.left_req + opt_args) {
+ // optional args
+ int opt_arg_index = i - arity.left_req;
+ if (opt_arg_index >= used_opt_args) {
+ new_argv[i] = Qundef;
+ }
+ else {
+ new_argv[i] = argv[i];
+ }
+ }
+ else if (i == rest_pos) {
+ // rest
+ int rest_size = argc - arity.real + 1;
+ if (rest_size <= 0) {
+ new_argv[i] = rb_ary_new();
+ }
+ else {
+ new_argv[i] = rb_ary_new4(rest_size, &argv[i]);
+ }
+ }
else {
- new_argv[i] = Qundef;
+ // required args after optional args
+ new_argv[i] = argv[argc-(arity.real - i)];
}
}
- return __rb_vm_rcall(self, node, pimp, -arity, -arity, new_argv);
+ argv = new_argv;
+ argc = arity.real;
}
assert(pimp != NULL);
@@ -4182,7 +4262,7 @@
case 9:
return (*imp)(self, 0, argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8]);
}
- printf("invalid arity %d\n", arity);
+ printf("invalid argc %d\n", argc);
abort();
return Qnil;
}
@@ -4389,10 +4469,10 @@
}
// TODO we should cache the arity
- const int arity = rb_vm_node_arity(cache->as.rcall.node);
- if (arity >= 0 && argc != arity) {
+ const node_arity arity = rb_vm_node_arity(cache->as.rcall.node);
+ if ((argc < arity.min) || ((arity.max != -1) && (argc > arity.max))) {
// TODO this should be an exception
- printf("bad arity given %d expected %d\n", argc, arity);
+ printf("bad arity given %d expected %d\n", argc, arity.min);
abort();
}
@@ -4413,17 +4493,19 @@
// Calling an empty method, let's just return nil!
return Qnil;
}
- if (node_type == NODE_FBODY && arity < 0) {
+ if (node_type == NODE_FBODY && arity.max != arity.min) {
// Calling a function defined with rb_objc_define_method with
// a negative arity, which means a different calling convention.
- if (arity == -1) {
+ if (arity.real == 2) {
return ((VALUE (*)(VALUE, SEL, int, const VALUE *))cache->as.rcall.imp)(self, 0, argc, argv);
}
- if (arity == -2) {
+ else if (arity.real == 1) {
return ((VALUE (*)(VALUE, SEL, ...))cache->as.rcall.imp)(self, 0, rb_ary_new4(argc, argv));
}
- printf("invalid negative arity for C function %d\n", arity);
- abort();
+ else {
+ printf("invalid negative arity for C function %d\n", arity.real);
+ abort();
+ }
}
return __rb_vm_rcall(self, cache->as.rcall.node, cache->as.rcall.imp, arity, argc, argv);
@@ -4742,7 +4824,11 @@
arity = method_getNumberOfArguments(m) - 2;
}
else {
- arity = rb_vm_node_arity(node);
+ node_arity n_arity = rb_vm_node_arity(node);
+ arity = n_arity.min;
+ if (n_arity.min != n_arity.max) {
+ arity = -arity - 1;
+ }
}
rb_vm_method_t *m = (rb_vm_method_t *)xmalloc(sizeof(rb_vm_method_t));
@@ -4766,30 +4852,30 @@
// Trying to call an empty block!
return Qnil;
}
- int arity = rb_vm_node_arity(b->node);
- if (arity != argc || b->dvars_size > 0) {
- VALUE *new_argv = (VALUE *)alloca(sizeof(VALUE) * (arity + b->dvars_size));
+ node_arity arity = rb_vm_node_arity(b->node);
+ if (arity.real != argc || b->dvars_size > 0) {
+ VALUE *new_argv = (VALUE *)alloca(sizeof(VALUE) * (arity.real + b->dvars_size));
for (int i = 0; i < b->dvars_size; i++) {
new_argv[i] = (VALUE)b->dvars[i];
}
- if (argc == 1 && TYPE(argv[0]) == T_ARRAY && arity > 1) {
+ if (argc == 1 && TYPE(argv[0]) == T_ARRAY && arity.real > 1) {
// Expand the array
long ary_len = RARRAY_LEN(argv[0]);
- for (int i = 0; i < arity; i++) {
+ for (int i = 0; i < arity.real; i++) {
new_argv[b->dvars_size + i] = i < ary_len ? RARRAY_AT(argv[0], i) : Qnil;
}
}
else {
- for (int i = 0; i < arity; i++) {
+ for (int i = 0; i < arity.real; i++) {
new_argv[b->dvars_size + i] = i < argc ? argv[i] : Qnil;
}
}
- argc = b->dvars_size + arity;
+ argc = b->dvars_size + arity.real;
argv = new_argv;
- arity = argc;
+ arity.real = argc;
}
#if ROXOR_DEBUG
- printf("yield block %p argc %d arity %d dvars %d\n", b, argc, arity, b->dvars_size);
+ printf("yield block %p argc %d arity %d dvars %d\n", b, argc, arity.real, b->dvars_size);
#endif
return __rb_vm_rcall(b->self, b->node, b->imp, arity, argc, argv);
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090315/5ac7bc12/attachment-0001.html>
More information about the macruby-changes
mailing list