[#30722] JSON ライブラリの取り込み — "NARUSE, Yui" <naruse@...>

naruseです。

20 messages 2007/04/21

[ruby-dev:30741] Re: ObjectC style keyword argument

From: Nobuyoshi Nakada <nobu@...>
Date: 2007-04-28 15:26:47 UTC
List: ruby-dev #30741
なかだです。

At Fri, 27 Apr 2007 01:12:18 +0900,
Yukihiro Matsumoto wrote in [ruby-dev:30737]:
> |おととい電車の中で大体できちゃったのでなんとなく(謎)。
> 
> あ、先を越された。私はずっとreduce/reduce conflictに悩まされ
> てました。いや、もっとObjective-Cに似せようと思ったのが敗因
> なんですが([x copy: y from: z]と書けるようにしたかった)。

式の先頭に[が来ることのないCならともかく、配列があるのでrubyじゃ
無理っぽい気がします。あと引数間のカンマの省略も、かなりきつい
制限がつくことになりそうです。

> メソッド定義は
> 
>   def copy:from:(x,y) p [x, y] end
> 
> か、あるいは
> 
>   def copy: x from: y; p [x, y] end
> 
> の方が良くないですかね? (前者で十分だけど)。
> キーワードの重複もありえますし。「do:value:value:」とか。

重複を忘れてました。とりあえず通常メソッドだけですが、後者で。


Index: parse.y
===================================================================
--- parse.y	(revision 12223)
+++ parse.y	(working copy)
@@ -520,4 +520,13 @@ static void ripper_compile_error(struct 
 #endif
 
+#ifdef RIPPER
+#define MUST_ASSOC(cons, car, cdr) do {			      \
+	if ((cons) == (car) || (cons) == (cdr) ||	      \
+	    TYPE(cons) != T_ARRAY || RARRAY_LEN(cons) != 2) { \
+	    (cons) = rb_assoc_new((car), (cdr));	      \
+	}						      \
+    } while (0)
+#endif
+
 /* Older versions of Yacc set YYMAXDEPTH to a very low value by default (150,
    for instance).  This is too low for Ruby to parse some files, such as
@@ -529,4 +538,9 @@ static void ripper_compile_error(struct 
 #endif
 
+ID rb_alist_id(VALUE);
+#ifndef RIPPER
+static void assoc_arg_vars(struct parser_params *, NODE *);
+#endif
+
 %}
 
@@ -613,4 +627,5 @@ static void ripper_compile_error(struct 
 %type <node> f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_head f_margs
 %type <node> assoc_list assocs assoc undef_list backref string_dvar for_var
+%type <node> assoc_call assoc_arg assoc_fargs assoc_farg
 %type <node> block_param opt_block_param block_param_def f_opt
 %type <node> bv_decls opt_bv_decl bvar
@@ -1040,4 +1055,17 @@ stmt		: keyword_alias fitem {lex_state =
 		    %*/
 		    }
+		| primary_value '.' assoc_call
+		    {
+		    /*%%%*/
+			ID associd = rb_alist_id($3->nd_lit);
+			$3->nd_next->nd_alen = $3->nd_alen - 1;
+			$$ = NEW_CALL($1, associd, $3->nd_next);
+			fixpos($$, $1);
+		    /*%
+			$$ = dispatch3(call, $1, ripper_id2sym('.'),
+				       ID2SYM(rb_alist_id(rb_ary_shift($3))));
+		        $$ = method_arg($$, $3);
+		    %*/
+		    }
 		| primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
 		    {
@@ -2830,4 +2858,35 @@ primary		: literal
 		    %*/
 		    }
+		| keyword_def assoc_fargs
+		    {
+		    /*%%%*/
+			$<id>$ = cur_mid;
+			cur_mid = rb_alist_id($2->nd_tval);
+			in_def++;
+			local_push(0);
+			assoc_arg_vars(parser, $2->nd_var);
+			$2->nd_var = 0;
+		    /*%
+		    %*/
+		    }
+		  bodystmt
+		  keyword_end
+		    {
+		    /*%%%*/
+			NODE *body = remove_begin($4);
+			reduce_nodes(&body);
+			$$ = NEW_DEFN(cur_mid, NEW_ARGS(RARRAY_LEN($2->nd_tval), 0),
+				      body, NOEX_PRIVATE);
+		        fixpos($$, $2);
+		        local_pop();
+			in_def--;
+			cur_mid = $<id>3;
+		    /*%
+			$$ = dispatch3(def, rb_alist_id(RARRAY_PTR($2)[0]),
+				       RARRAY_PTR($2)[1], $5);
+			in_def--;
+			cur_mid = $<id>3;
+		    %*/
+		    }
 		| keyword_break
 		    {
@@ -4315,5 +4374,5 @@ assoc		: arg_value tASSOC arg_value
 		    /*%
 			$$ = dispatch2(assoc_new, $1, $3);
-			if ($$ == $1) $$ = rb_assoc_new($1, $3);
+			MUST_ASSOC($$, $1, $3);
 		    %*/
 		    }
@@ -4324,5 +4383,69 @@ assoc		: arg_value tASSOC arg_value
 		    /*%
 			$$ = dispatch2(assoc_new, $1, $2);
-			if ($$ == $1) $$ = rb_assoc_new($1, $2);
+			MUST_ASSOC($$, $1, $2);
+		    %*/
+		    }
+		;
+
+assoc_call	: assoc_arg
+		| assoc_call ',' assoc_arg
+		    {
+		    /*%%%*/
+			rb_ary_concat($1->nd_lit, $3->nd_lit);
+			$$ = list_concat($1, $3->nd_next);
+		    /*%
+			rb_ary_push(rb_ary_entry($1, 0), rb_ary_entry($3, 0));
+			rb_ary_push($1, rb_ary_entry($3, 1));
+		    %*/
+		    }
+
+assoc_arg	: tLABEL arg_value
+		    {
+		    /*%%%*/
+			$$ = list_append(NEW_LIST(rb_ary_new3(1, ID2SYM($1))), $2);
+		    /*%
+		    	$$ = rb_assoc_new(rb_ary_new3(1, $1), $2);
+		    %*/
+		    }
+		;
+
+assoc_fargs	: assoc_farg
+		    {
+		    /*%%%*/
+			ID pid = $1->nd_pid, mid = $1->nd_mid;
+			rb_gc_force_recycle((VALUE)$1);
+			$$ = NEW_ARGS(rb_ary_new3(1, ID2SYM(pid)),
+				      NEW_LIST((NODE *)mid));
+			/* nd_tval, nd_var */
+		    /*%
+			$$ = $1;
+			RARRAY_PTR($$)[0] = rb_ary_new3(1, RARRAY_PTR($1)[0]);
+			RARRAY_PTR($$)[1] = rb_ary_new3(1, RARRAY_PTR($1)[1]);
+		    %*/
+		    }
+		| assoc_fargs assoc_farg
+		    {
+		    /*%%%*/
+			ID pid = $2->nd_pid, mid = $2->nd_mid;
+			rb_gc_force_recycle((VALUE)$2);
+			$$ = $1;
+			rb_ary_push($$->nd_tval, ID2SYM(pid));
+			$$->nd_var = list_append($$->nd_var, (NODE *)mid);
+		    /*%
+			$$ = $1;
+			rb_ary_push(RARRAY_PTR($$)[0], RARRAY_PTR($2)[0]);
+			rb_ary_push(RARRAY_PTR($$)[1], RARRAY_PTR($2)[1]);
+		    %*/
+		    }
+		;
+assoc_farg	: tLABEL f_norm_arg
+		    {
+		    /*%%%*/
+			if (!is_local_id($2))
+			    yyerror("formal argument must be local variable");
+			$$ = NEW_ARGS_AUX($1, $2);
+		    /*%
+		        $$ = dispatch2(assoc_farg, $1, $2);
+			MUST_ASSOC($$, $1, $2);
 		    %*/
 		    }
@@ -6795,4 +6918,6 @@ parser_yylex(struct parser_params *parse
 	    if ((lex_state == EXPR_BEG && !cmd_state) ||
 		lex_state == EXPR_ARG ||
+		lex_state == EXPR_DOT ||
+		lex_state == EXPR_FNAME ||
 		lex_state == EXPR_CMDARG) {
 		if (peek(':') && !(lex_p + 1 < lex_pend && lex_p[1] == ':')) {
@@ -8501,4 +8626,28 @@ rb_id2name(ID id)
 }
 
+ID
+rb_alist_id(VALUE names)
+{
+    VALUE name = rb_str_cat(rb_ary_join(names, rb_str_new2(":")), ":", 1);
+    return rb_intern2(RSTRING_PTR(name), RSTRING_LEN(name));
+}
+
+#ifndef RIPPER
+static void
+assoc_arg_vars(struct parser_params *parser, NODE *var)
+{
+    NODE *next;
+
+    while (var) {
+	ID id = var->nd_pid;
+	shadowing_lvar(id);
+	arg_var(id);
+	next = var->nd_next;
+	rb_gc_force_recycle((VALUE)var);
+	var = next;
+    }
+}
+#endif
+
 static int
 symbols_i(VALUE sym, ID value, VALUE ary)


-- 
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
    中田 伸悦

In This Thread