Project

General

Profile

Feature #10287 » colon2head-20141103a.patch

arimay (yasuhiro arima), 11/02/2014 05:12 PM

View differences:

bootstraptest/test_class.rb
assert_equal '1', %q( C = 1 # [yarv-dev:800]
begin module C; end; rescue TypeError; 1 end )
# colon2, colon3
# colon2, colon2_head
assert_equal '1', %q( class A; end; A::C = 1; A::C )
assert_equal '1', %q( A = 7; begin A::C = 7; rescue TypeError; 1 end )
assert_equal '1', %q( begin 7::C = 7; rescue TypeError; 1 end )
compile.c
debugi("compile_colon2 - colon", node->nd_vid);
ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_vid));
break;
case NODE_COLON3:
debugi("compile_colon2 - colon3", node->nd_mid);
case NODE_COLON2_HEAD:
debugi("compile_colon2 - colon2_head", node->nd_mid);
ADD_INSN(body, nd_line(node), pop);
ADD_INSN1(body, nd_line(node), putobject, rb_cObject);
ADD_INSN1(body, nd_line(node), getconstant, ID2SYM(node->nd_mid));
......
static VALUE
compile_cpath(LINK_ANCHOR *ret, rb_iseq_t *iseq, NODE *cpath)
{
if (nd_type(cpath) == NODE_COLON3) {
if (nd_type(cpath) == NODE_COLON2_HEAD) {
/* toplevel class ::Foo */
ADD_INSN1(ret, nd_line(cpath), putobject, rb_cObject);
return Qfalse;
......
ID2SYM(node->nd_mid), needstr);
}
return 1;
case NODE_COLON3:
case NODE_COLON2_HEAD:
ADD_INSN1(ret, nd_line(node), putobject, rb_cObject);
ADD_INSN3(ret, nd_line(node), defined,
INT2FIX(DEFINED_CONST), ID2SYM(node->nd_mid), needstr);
......
ID mid;
switch (nd_type(node->nd_head)) {
case NODE_COLON3:
case NODE_COLON2_HEAD:
ADD_INSN1(ret, line, putobject, rb_cObject);
break;
case NODE_COLON2:
......
}
break;
}
case NODE_COLON3:{
case NODE_COLON2_HEAD:{
LABEL *lend = NEW_LABEL(line);
int ic_index = iseq->is_size++;
debugi("colon3#nd_mid", node->nd_mid);
debugi("colon2_head#nd_mid", node->nd_mid);
/* add cache insn */
if (iseq->compile_data->option->inline_const_cache) {
ext/objspace/objspace.c
COUNT_NODE(NODE_MODULE);
COUNT_NODE(NODE_SCLASS);
COUNT_NODE(NODE_COLON2);
COUNT_NODE(NODE_COLON3);
COUNT_NODE(NODE_COLON2_HEAD);
COUNT_NODE(NODE_CREF);
COUNT_NODE(NODE_DOT2);
COUNT_NODE(NODE_DOT3);
ext/ripper/eventids2.c
{tCHAR, O(CHAR)},
{tCMP, O(op)},
{tCOLON2, O(op)},
{tCOLON3, O(op)},
{tCOLON2_HEAD, O(op)},
{tCONSTANT, O(const)},
{tCVAR, O(cvar)},
{tDOT2, O(op)},
lib/irb/ruby-lex.rb
|op, io|
if @lex_state == EXPR_BEG or @lex_state == EXPR_ARG && @space_seen
@lex_state = EXPR_BEG
Token(TkCOLON3)
Token(TkCOLON2_HEAD)
else
@lex_state = EXPR_DOT
Token(TkCOLON2)
lib/irb/ruby-token.rb
[:TkLSHFT, TkOp, "<<"],
[:TkRSHFT, TkOp, ">>"],
[:TkCOLON2, TkOp],
[:TkCOLON3, TkOp],
[:TkCOLON2_HEAD,TkOp],
[:TkASSOC, TkOp, "=>"],
[:TkQUESTION, TkOp, "?"], #?
[:TkCOLON, TkOp, ":"], #:
lib/rdoc/parser/ruby.rb
# class ::A -> A is in the top level
case name_t
when TkCOLON2, TkCOLON3 then # bug
when TkCOLON2, TkCOLON2_HEAD then # bug
name_t = get_tk
container = @top_level
given_name << '::'
......
skip_tkspace false
tk = get_tk
while TkCOLON2 === tk or TkCOLON3 === tk or TkCONSTANT === tk do
while TkCOLON2 === tk or TkCOLON2_HEAD === tk or TkCONSTANT === tk do
res += tk.name
tk = get_tk
end
......
unget_tk tk
break
end
when TkCOLON2, TkCOLON3 then
when TkCOLON2, TkCOLON2_HEAD then
rhs_name << '::'
when nil then
break
lib/rdoc/ruby_lex.rb
# p @lex_state.id2name, @space_seen
if @lex_state == :EXPR_BEG or @lex_state == :EXPR_ARG && @space_seen
@lex_state = :EXPR_BEG
Token(TkCOLON3)
Token(TkCOLON2_HEAD)
else
@lex_state = :EXPR_DOT
Token(TkCOLON2)
lib/rdoc/ruby_token.rb
[:TkLSHFT, TkOp, "<<"],
[:TkRSHFT, TkOp, ">>"],
[:TkCOLON2, TkOp, '::'],
[:TkCOLON3, TkOp, '::'],
[:TkCOLON2_HEAD,TkOp, '::'],
#[:OPASGN, TkOp], # +=, -= etc. #
[:TkASSOC, TkOp, "=>"],
[:TkQUESTION, TkOp, "?"], #?
node.c
F_NODE(nd_head, "receiver");
break;
case NODE_COLON3:
case NODE_COLON2_HEAD:
ANN("top-level constant reference");
ANN("format: ::[nd_mid]");
ANN("example: ::Object");
......
case NODE_IASGN:
case NODE_IASGN2:
case NODE_CVASGN:
case NODE_COLON3:
case NODE_COLON2_HEAD:
case NODE_OPT_N:
case NODE_EVSTR:
case NODE_UNDEF:
node.h
#define NODE_SCLASS NODE_SCLASS
NODE_COLON2,
#define NODE_COLON2 NODE_COLON2
NODE_COLON3,
#define NODE_COLON3 NODE_COLON3
NODE_COLON2_HEAD,
#define NODE_COLON2_HEAD NODE_COLON2_HEAD
NODE_CREF,
#define NODE_CREF NODE_CREF
NODE_DOT2,
......
#define NEW_SCLASS(r,b) NEW_NODE(NODE_SCLASS,r,NEW_SCOPE(0,b),0)
#define NEW_MODULE(n,b) NEW_NODE(NODE_MODULE,n,NEW_SCOPE(0,b),0)
#define NEW_COLON2(c,i) NEW_NODE(NODE_COLON2,c,i,0)
#define NEW_COLON3(i) NEW_NODE(NODE_COLON3,0,i,0)
#define NEW_COLON2_HEAD(i) NEW_NODE(NODE_COLON2_HEAD,0,i,0)
#define NEW_CREF(a) NEW_NODE(NODE_CREF,a,0,0)
#define NEW_DOT2(b,e) NEW_NODE(NODE_DOT2,b,e,0)
#define NEW_DOT3(b,e) NEW_NODE(NODE_DOT3,b,e,0)
parse.y
%token tLSHFT RUBY_TOKEN(LSHFT) "<<"
%token tRSHFT RUBY_TOKEN(RSHFT) ">>"
%token tCOLON2 "::"
%token tCOLON3 ":: at EXPR_BEG"
%token tCOLON2_HEAD ":: at EXPR_BEG"
%token <id> tOP_ASGN /* +=, -= etc. */
%token tASSOC "=>"
%token tLPAREN "("
......
}
%*/
}
| tCOLON3 tCONSTANT
| tCOLON2_HEAD tCONSTANT
{
/*%%%*/
if (in_def || in_single)
yyerror("dynamic constant assignment");
$$ = NEW_CDECL(0, 0, NEW_COLON3($2));
$$ = NEW_CDECL(0, 0, NEW_COLON2_HEAD($2));
/*%
$$ = dispatch1(top_const_field, $2);
if (in_def || in_single) {
......
}
%*/
}
| tCOLON3 tCONSTANT
| tCOLON2_HEAD tCONSTANT
{
/*%%%*/
if (in_def || in_single)
yyerror("dynamic constant assignment");
$$ = NEW_CDECL(0, 0, NEW_COLON3($2));
$$ = NEW_CDECL(0, 0, NEW_COLON2_HEAD($2));
/*%
$$ = dispatch1(top_const_field, $2);
if (in_def || in_single) {
......
| tCONSTANT
;
cpath : tCOLON3 cname
cpath : tCOLON2_HEAD cname
{
/*%%%*/
$$ = NEW_COLON3($2);
$$ = NEW_COLON2_HEAD($2);
/*%
$$ = dispatch1(top_const_ref, $2);
%*/
......
$$ = dispatch3(opassign, $$, $4, $5);
%*/
}
| tCOLON3 tCONSTANT tOP_ASGN arg
| tCOLON2_HEAD tCONSTANT tOP_ASGN arg
{
/*%%%*/
$$ = NEW_COLON3($2);
$$ = NEW_COLON2_HEAD($2);
$$ = new_const_op_assign($$, $3, $4);
/*%
$$ = dispatch1(top_const_field, $2);
......
$$ = dispatch2(const_path_ref, $1, $3);
%*/
}
| tCOLON3 tCONSTANT
| tCOLON2_HEAD tCONSTANT
{
/*%%%*/
$$ = NEW_COLON3($2);
$$ = NEW_COLON2_HEAD($2);
/*%
$$ = dispatch1(top_const_ref, $2);
%*/
......
if (c == ':') {
if (IS_BEG() || IS_lex_state(EXPR_CLASS) || IS_SPCARG(-1)) {
lex_state = EXPR_BEG;
return tCOLON3;
return tCOLON2_HEAD;
}
lex_state = EXPR_DOT;
return tCOLON2;
......
useless = "a literal";
break;
case NODE_COLON2:
case NODE_COLON3:
case NODE_COLON2_HEAD:
useless = "::";
break;
case NODE_DOT2:
template/id.h.tmpl
token_op_ids = %w[
tDOT2 tDOT3 tUPLUS tUMINUS tPOW tDSTAR tCMP tLSHFT tRSHFT
tLEQ tGEQ tEQ tEQQ tNEQ tMATCH tNMATCH tAREF tASET
tCOLON2 tCOLON3 tANDOP tOROP
tCOLON2 tCOLON2_HEAD tANDOP tOROP
]
defs = File.join(File.dirname(File.dirname(erb.filename)), "defs/id.def")
test/rdoc/test_rdoc_parser_ruby.rb
assert_empty foo.comment
end
def test_parse_class_colon3
def test_parse_class_colon2_head
code = <<-CODE
class A
class ::B
......
assert_equal %w[A B], @store.all_classes.map { |c| c.full_name }.sort
end
def test_parse_class_colon3_self_reference
def test_parse_class_colon2_head_self_reference
code = <<-CODE
class A::B
class ::A
(2-2/2)