Skip to content

Commit a47d058

Browse files
committed
use builtin for RubyVM::AbstractSyntaxTree.
Define RubyVM::AbstractSyntaxTree in ast.rb with __builtin functions.
1 parent e2a45cb commit a47d058

File tree

5 files changed

+157
-129
lines changed

5 files changed

+157
-129
lines changed

.document

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ prelude.rb
1212
rbconfig.rb
1313

1414
trace_point.rb
15+
ast.rb
1516

1617
# the lib/ directory (which has its own .document file)
1718
lib

ast.c

Lines changed: 15 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "node.h"
77
#include "vm_core.h"
88
#include "iseq.h"
9+
#include "builtin.h"
910

1011
static VALUE rb_mAST;
1112
static VALUE rb_cNode;
@@ -80,20 +81,8 @@ ast_parse_done(rb_ast_t *ast)
8081
return ast_new_internal(ast, (NODE *)ast->body.root);
8182
}
8283

83-
/*
84-
* call-seq:
85-
* RubyVM::AbstractSyntaxTree.parse(string) -> RubyVM::AbstractSyntaxTree::Node
86-
*
87-
* Parses the given _string_ into an abstract syntax tree,
88-
* returning the root node of that tree.
89-
*
90-
* SyntaxError is raised if the given _string_ is invalid syntax.
91-
*
92-
* RubyVM::AbstractSyntaxTree.parse("x = 1 + 2")
93-
* # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-1:9>
94-
*/
9584
static VALUE
96-
rb_ast_s_parse(VALUE module, VALUE str)
85+
ast_s_parse(rb_execution_context_t *ec, VALUE module, VALUE str)
9786
{
9887
return rb_ast_parse_str(str);
9988
}
@@ -108,21 +97,8 @@ rb_ast_parse_str(VALUE str)
10897
return ast_parse_done(ast);
10998
}
11099

111-
/*
112-
* call-seq:
113-
* RubyVM::AbstractSyntaxTree.parse_file(pathname) -> RubyVM::AbstractSyntaxTree::Node
114-
*
115-
* Reads the file from _pathname_, then parses it like ::parse,
116-
* returning the root node of the abstract syntax tree.
117-
*
118-
* SyntaxError is raised if _pathname_'s contents are not
119-
* valid Ruby syntax.
120-
*
121-
* RubyVM::AbstractSyntaxTree.parse_file("my-app/app.rb")
122-
* # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-31:3>
123-
*/
124100
static VALUE
125-
rb_ast_s_parse_file(VALUE module, VALUE path)
101+
ast_s_parse_file(rb_execution_context_t *ec, VALUE module, VALUE path)
126102
{
127103
return rb_ast_parse_file(path);
128104
}
@@ -207,25 +183,8 @@ script_lines(VALUE path)
207183
return lines;
208184
}
209185

210-
/*
211-
* call-seq:
212-
* RubyVM::AbstractSyntaxTree.of(proc) -> RubyVM::AbstractSyntaxTree::Node
213-
* RubyVM::AbstractSyntaxTree.of(method) -> RubyVM::AbstractSyntaxTree::Node
214-
*
215-
* Returns AST nodes of the given _proc_ or _method_.
216-
*
217-
* RubyVM::AbstractSyntaxTree.of(proc {1 + 2})
218-
* # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:35-1:42>
219-
*
220-
* def hello
221-
* puts "hello, world"
222-
* end
223-
*
224-
* RubyVM::AbstractSyntaxTree.of(method(:hello))
225-
* # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-3:3>
226-
*/
227186
static VALUE
228-
rb_ast_s_of(VALUE module, VALUE body)
187+
ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body)
229188
{
230189
VALUE path, node, lines;
231190
int node_id;
@@ -274,19 +233,8 @@ node_type_to_str(const NODE *node)
274233
return (ruby_node_name(nd_type(node)) + rb_strlen_lit("NODE_"));
275234
}
276235

277-
/*
278-
* call-seq:
279-
* node.type -> symbol
280-
*
281-
* Returns the type of this node as a symbol.
282-
*
283-
* root = RubyVM::AbstractSyntaxTree.parse("x = 1 + 2")
284-
* root.type # => :SCOPE
285-
* call = root.children[2]
286-
* call.type # => :OPCALL
287-
*/
288236
static VALUE
289-
rb_ast_node_type(VALUE self)
237+
ast_node_type(rb_execution_context_t *ec, VALUE self)
290238
{
291239
struct ASTNodeData *data;
292240
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
@@ -668,92 +616,53 @@ node_children(rb_ast_t *ast, NODE *node)
668616
rb_bug("node_children: unknown node: %s", ruby_node_name(type));
669617
}
670618

671-
/*
672-
* call-seq:
673-
* node.children -> array
674-
*
675-
* Returns AST nodes under this one. Each kind of node
676-
* has different children, depending on what kind of node it is.
677-
*
678-
* The returned array may contain other nodes or <code>nil</code>.
679-
*/
680619
static VALUE
681-
rb_ast_node_children(VALUE self)
620+
ast_node_children(rb_execution_context_t *ec, VALUE self)
682621
{
683622
struct ASTNodeData *data;
684623
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
685624

686625
return node_children(data->ast, data->node);
687626
}
688627

689-
/*
690-
* call-seq:
691-
* node.first_lineno -> integer
692-
*
693-
* The line number in the source code where this AST's text began.
694-
*/
695628
static VALUE
696-
rb_ast_node_first_lineno(VALUE self)
629+
ast_node_first_lineno(rb_execution_context_t *ec, VALUE self)
697630
{
698631
struct ASTNodeData *data;
699632
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
700633

701634
return INT2NUM(nd_first_lineno(data->node));
702635
}
703636

704-
/*
705-
* call-seq:
706-
* node.first_column -> integer
707-
*
708-
* The column number in the source code where this AST's text began.
709-
*/
710637
static VALUE
711-
rb_ast_node_first_column(VALUE self)
638+
ast_node_first_column(rb_execution_context_t *ec, VALUE self)
712639
{
713640
struct ASTNodeData *data;
714641
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
715642

716643
return INT2NUM(nd_first_column(data->node));
717644
}
718645

719-
/*
720-
* call-seq:
721-
* node.last_lineno -> integer
722-
*
723-
* The line number in the source code where this AST's text ended.
724-
*/
725646
static VALUE
726-
rb_ast_node_last_lineno(VALUE self)
647+
ast_node_last_lineno(rb_execution_context_t *ec, VALUE self)
727648
{
728649
struct ASTNodeData *data;
729650
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
730651

731652
return INT2NUM(nd_last_lineno(data->node));
732653
}
733654

734-
/*
735-
* call-seq:
736-
* node.last_column -> integer
737-
*
738-
* The column number in the source code where this AST's text ended.
739-
*/
740655
static VALUE
741-
rb_ast_node_last_column(VALUE self)
656+
ast_node_last_column(rb_execution_context_t *ec, VALUE self)
742657
{
743658
struct ASTNodeData *data;
744659
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
745660

746661
return INT2NUM(nd_last_column(data->node));
747662
}
748663

749-
/*
750-
* call-seq:
751-
* node.inspect -> string
752-
*
753-
* Returns debugging information about this node as a string.
754-
*/
755664
static VALUE
756-
rb_ast_node_inspect(VALUE self)
665+
ast_node_inspect(rb_execution_context_t *ec, VALUE self)
757666
{
758667
VALUE str;
759668
VALUE cname;
@@ -772,35 +681,14 @@ rb_ast_node_inspect(VALUE self)
772681
return str;
773682
}
774683

684+
#include "load_ast.inc"
685+
775686
void
776687
Init_ast(void)
777688
{
778-
/*
779-
* AbstractSyntaxTree provides methods to parse Ruby code into
780-
* abstract syntax trees. The nodes in the tree
781-
* are instances of RubyVM::AbstractSyntaxTree::Node.
782-
*
783-
* This class is MRI specific as it exposes implementation details
784-
* of the MRI abstract syntax tree.
785-
*/
786689
rb_mAST = rb_define_module_under(rb_cRubyVM, "AbstractSyntaxTree");
787-
/*
788-
* RubyVM::AbstractSyntaxTree::Node instances are created by parse methods in
789-
* RubyVM::AbstractSyntaxTree.
790-
*
791-
* This class is MRI specific.
792-
*/
793690
rb_cNode = rb_define_class_under(rb_mAST, "Node", rb_cObject);
794-
795691
rb_undef_alloc_func(rb_cNode);
796-
rb_define_singleton_method(rb_mAST, "parse", rb_ast_s_parse, 1);
797-
rb_define_singleton_method(rb_mAST, "parse_file", rb_ast_s_parse_file, 1);
798-
rb_define_singleton_method(rb_mAST, "of", rb_ast_s_of, 1);
799-
rb_define_method(rb_cNode, "type", rb_ast_node_type, 0);
800-
rb_define_method(rb_cNode, "first_lineno", rb_ast_node_first_lineno, 0);
801-
rb_define_method(rb_cNode, "first_column", rb_ast_node_first_column, 0);
802-
rb_define_method(rb_cNode, "last_lineno", rb_ast_node_last_lineno, 0);
803-
rb_define_method(rb_cNode, "last_column", rb_ast_node_last_column, 0);
804-
rb_define_method(rb_cNode, "children", rb_ast_node_children, 0);
805-
rb_define_method(rb_cNode, "inspect", rb_ast_node_inspect, 0);
692+
693+
load_ast();
806694
}

ast.rb

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# for ast.c
2+
3+
class RubyVM
4+
5+
# AbstractSyntaxTree provides methods to parse Ruby code into
6+
# abstract syntax trees. The nodes in the tree
7+
# are instances of RubyVM::AbstractSyntaxTree::Node.
8+
#
9+
# This class is MRI specific as it exposes implementation details
10+
# of the MRI abstract syntax tree.
11+
#
12+
module AbstractSyntaxTree
13+
14+
# call-seq:
15+
# RubyVM::AbstractSyntaxTree.parse(string) -> RubyVM::AbstractSyntaxTree::Node
16+
#
17+
# Parses the given _string_ into an abstract syntax tree,
18+
# returning the root node of that tree.
19+
#
20+
# SyntaxError is raised if the given _string_ is invalid syntax.
21+
#
22+
# RubyVM::AbstractSyntaxTree.parse("x = 1 + 2")
23+
# # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-1:9>
24+
def self.parse string
25+
__builtin_ast_s_parse string
26+
end
27+
28+
# call-seq:
29+
# RubyVM::AbstractSyntaxTree.parse_file(pathname) -> RubyVM::AbstractSyntaxTree::Node
30+
#
31+
# Reads the file from _pathname_, then parses it like ::parse,
32+
# returning the root node of the abstract syntax tree.
33+
#
34+
# SyntaxError is raised if _pathname_'s contents are not
35+
# valid Ruby syntax.
36+
#
37+
# RubyVM::AbstractSyntaxTree.parse_file("my-app/app.rb")
38+
# # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-31:3>
39+
def self.parse_file pathname
40+
__builtin_ast_s_parse_file pathname
41+
end
42+
43+
# call-seq:
44+
# RubyVM::AbstractSyntaxTree.of(proc) -> RubyVM::AbstractSyntaxTree::Node
45+
# RubyVM::AbstractSyntaxTree.of(method) -> RubyVM::AbstractSyntaxTree::Node
46+
#
47+
# Returns AST nodes of the given _proc_ or _method_.
48+
#
49+
# RubyVM::AbstractSyntaxTree.of(proc {1 + 2})
50+
# # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:35-1:42>
51+
#
52+
# def hello
53+
# puts "hello, world"
54+
# end
55+
#
56+
# RubyVM::AbstractSyntaxTree.of(method(:hello))
57+
# # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-3:3>
58+
def self.of body
59+
__builtin_ast_s_of body
60+
end
61+
62+
# RubyVM::AbstractSyntaxTree::Node instances are created by parse methods in
63+
# RubyVM::AbstractSyntaxTree.
64+
#
65+
# This class is MRI specific.
66+
#
67+
class Node
68+
69+
# call-seq:
70+
# node.type -> symbol
71+
#
72+
# Returns the type of this node as a symbol.
73+
#
74+
# root = RubyVM::AbstractSyntaxTree.parse("x = 1 + 2")
75+
# root.type # => :SCOPE
76+
# call = root.children[2]
77+
# call.type # => :OPCALL
78+
def type
79+
__builtin_ast_node_type
80+
end
81+
82+
# call-seq:
83+
# node.first_lineno -> integer
84+
#
85+
# The line number in the source code where this AST's text began.
86+
def first_lineno
87+
__builtin_ast_node_first_lineno
88+
end
89+
90+
# call-seq:
91+
# node.first_column -> integer
92+
#
93+
# The column number in the source code where this AST's text began.
94+
def first_column
95+
__builtin_ast_node_first_column
96+
end
97+
98+
# call-seq:
99+
# node.last_lineno -> integer
100+
#
101+
# The line number in the source code where this AST's text ended.
102+
def last_lineno
103+
__builtin_ast_node_last_lineno
104+
end
105+
106+
# call-seq:
107+
# node.last_column -> integer
108+
#
109+
# The column number in the source code where this AST's text ended.
110+
def last_column
111+
__builtin_ast_node_last_column
112+
end
113+
114+
# call-seq:
115+
# node.children -> array
116+
#
117+
# Returns AST nodes under this one. Each kind of node
118+
# has different children, depending on what kind of node it is.
119+
#
120+
# The returned array may contain other nodes or <code>nil</code>.
121+
def children
122+
__builtin_ast_node_children
123+
end
124+
125+
# call-seq:
126+
# node.inspect -> string
127+
#
128+
# Returns debugging information about this node as a string.
129+
def inspect
130+
__builtin_ast_node_inspect
131+
end
132+
end
133+
end
134+
end

0 commit comments

Comments
 (0)