From: Yukihiro Matsumoto Date: 2009-07-22T07:08:24+09:00 Subject: [ruby-dev:38843] 複素数リテラルについて まつもと ゆきひろです RubyKaigiのキーノートでも話しましたが、複素数リテラルを実現 するパッチを書きました。これを当てると、 2i 2.0i のような表現が可能になります。さて、これを取り込もうかどうか 考えているのですが、検討を手伝っていただける方はいらっしゃい ますか? 検討すべきこと * 互換性はどうか。大丈夫のはずだが、見落としは * iでいいのか。Pythonはなぜかjだが。 * 複素数化するメソッドNumeric#iは要らないか * 要るなら、虚数.iの値は何か? 複素数.iの値は? diff --git a/parse.y b/parse.y index d311e13..3630c60 100644 --- a/parse.y +++ b/parse.y @@ -655,14 +655,14 @@ static void token_info_pop(struct parser_params*, const char *token); keyword__ENCODING__ %token tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL -%token tINTEGER tFLOAT tSTRING_CONTENT tCHAR +%token tINTEGER tFLOAT tCOMPLEX tSTRING_CONTENT tCHAR %token tNTH_REF tBACK_REF %token tREGEXP_END %type singleton strings string string1 xstring regexp %type string_contents xstring_contents string_content %type words qwords word_list qword_list word -%type literal numeric dsym cpath +%type literal numeric num_lit dsym cpath %type bodystmt compstmt stmts stmt expr arg primary command command_call method_call %type expr_value arg_value primary_value %type if_tail opt_else case_body cases opt_rescue exc_list exc_var opt_ensure @@ -2063,16 +2063,7 @@ arg : lhs '=' arg $$ = dispatch3(binary, $1, ripper_intern("**"), $3); %*/ } - | tUMINUS_NUM tINTEGER tPOW arg - { - /*%%%*/ - $$ = NEW_CALL(call_bin_op($2, tPOW, $4), tUMINUS, 0); - /*% - $$ = dispatch3(binary, $2, ripper_intern("**"), $4); - $$ = dispatch2(unary, ripper_intern("-@"), $$); - %*/ - } - | tUMINUS_NUM tFLOAT tPOW arg + | tUMINUS_NUM num_lit tPOW arg { /*%%%*/ $$ = NEW_CALL(call_bin_op($2, tPOW, $4), tUMINUS, 0); @@ -4092,17 +4083,13 @@ dsym : tSYMBEG xstring_contents tSTRING_END } ; -numeric : tINTEGER +num_lit : tINTEGER | tFLOAT - | tUMINUS_NUM tINTEGER %prec tLOWEST - { - /*%%%*/ - $$ = negate_lit($2); - /*% - $$ = dispatch2(unary, ripper_intern("-@"), $2); - %*/ - } - | tUMINUS_NUM tFLOAT %prec tLOWEST + | tCOMPLEX + ; + +numeric : num_lit + | tUMINUS_NUM num_lit %prec tLOWEST { /*%%%*/ $$ = negate_lit($2); @@ -6858,9 +6845,9 @@ parser_yylex(struct parser_params *parser) case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { - int is_float, seen_point, seen_e, nondigit; + int is_float, seen_point, seen_e, nondigit, is_complex; - is_float = seen_point = seen_e = nondigit = 0; + is_float = seen_point = seen_e = nondigit = is_complex = 0; lex_state = EXPR_END; newtok(); if (c == '-' || c == '+') { @@ -7046,6 +7033,10 @@ parser_yylex(struct parser_params *parser) nondigit = c; break; + case 'i': + is_complex++; + goto decode_complex; + default: goto decode_num; } @@ -7054,6 +7045,7 @@ parser_yylex(struct parser_params *parser) decode_num: pushback(c); + decode_complex: tokfix(); if (nondigit) { char tmp[30]; @@ -7067,9 +7059,18 @@ parser_yylex(struct parser_params *parser) rb_warningS("Float %s out of range", tok()); errno = 0; } + if (is_complex) { + set_yylval_literal(rb_complex_new(INT2FIX(0), DBL2NUM(d))); + return tCOMPLEX; + } set_yylval_literal(DBL2NUM(d)); return tFLOAT; } + if (is_complex) { + set_yylval_literal(rb_complex_new(INT2FIX(0), + rb_cstr_to_inum(tok(), 10, Qfalse))); + return tCOMPLEX; + } set_yylval_literal(rb_cstr_to_inum(tok(), 10, Qfalse)); return tINTEGER; } @@ -8677,6 +8678,7 @@ negate_lit(NODE *node) node->nd_lit = LONG2FIX(-FIX2LONG(node->nd_lit)); break; case T_BIGNUM: + case T_COMPLEX: node->nd_lit = rb_funcall(node->nd_lit,tUMINUS,0,0); break; case T_FLOAT: