2018-06-07 17:40:39 +03:00
|
|
|
/* indent-tabs-mode: nil */
|
2019-12-04 11:16:30 +03:00
|
|
|
#include "internal.h"
|
2023-05-28 14:00:20 +03:00
|
|
|
#include "internal/ruby_parser.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
#include "internal/symbol.h"
|
|
|
|
#include "internal/warnings.h"
|
|
|
|
#include "iseq.h"
|
|
|
|
#include "node.h"
|
2018-01-16 02:43:17 +03:00
|
|
|
#include "ruby.h"
|
|
|
|
#include "ruby/encoding.h"
|
2018-06-07 17:46:25 +03:00
|
|
|
#include "ruby/util.h"
|
2018-01-16 02:43:17 +03:00
|
|
|
#include "vm_core.h"
|
2019-12-04 11:16:30 +03:00
|
|
|
|
2019-11-07 12:29:20 +03:00
|
|
|
#include "builtin.h"
|
2018-01-16 02:43:17 +03:00
|
|
|
|
|
|
|
static VALUE rb_mAST;
|
|
|
|
static VALUE rb_cNode;
|
2024-07-10 16:28:22 +03:00
|
|
|
static VALUE rb_cLocation;
|
2018-01-16 02:43:17 +03:00
|
|
|
|
|
|
|
struct ASTNodeData {
|
2024-05-03 02:57:55 +03:00
|
|
|
VALUE ast_value;
|
2020-07-08 12:07:30 +03:00
|
|
|
const NODE *node;
|
2018-01-16 02:43:17 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
node_gc_mark(void *ptr)
|
|
|
|
{
|
|
|
|
struct ASTNodeData *data = (struct ASTNodeData *)ptr;
|
2024-05-03 02:57:55 +03:00
|
|
|
rb_gc_mark(data->ast_value);
|
2018-01-16 02:43:17 +03:00
|
|
|
}
|
|
|
|
|
2019-07-23 10:18:40 +03:00
|
|
|
static size_t
|
|
|
|
node_memsize(const void *ptr)
|
|
|
|
{
|
|
|
|
struct ASTNodeData *data = (struct ASTNodeData *)ptr;
|
2024-05-03 02:57:55 +03:00
|
|
|
rb_ast_t *ast = rb_ruby_ast_data_get(data->ast_value);
|
[Universal parser] Decouple IMEMO from rb_ast_t
This patch removes the `VALUE flags` member from the `rb_ast_t` structure making `rb_ast_t` no longer an IMEMO object.
## Background
We are trying to make the Ruby parser generated from parse.y a universal parser that can be used by other implementations such as mruby.
To achieve this, it is necessary to exclude VALUE and IMEMO from parse.y, AST, and NODE.
## Summary (file by file)
- `rubyparser.h`
- Remove the `VALUE flags` member from `rb_ast_t`
- `ruby_parser.c` and `internal/ruby_parser.h`
- Use TypedData_Make_Struct VALUE which wraps `rb_ast_t` `in ast_alloc()` so that GC can manage it
- You can retrieve `rb_ast_t` from the VALUE by `rb_ruby_ast_data_get()`
- Change the return type of `rb_parser_compile_XXXX()` functions from `rb_ast_t *` to `VALUE`
- rb_ruby_ast_new() which internally `calls ast_alloc()` is to create VALUE vast outside ruby_parser.c
- `iseq.c` and `vm_core.h`
- Amend the first parameter of `rb_iseq_new_XXXX()` functions from `rb_ast_body_t *` to `VALUE`
- This keeps the VALUE of AST on the machine stack to prevent being removed by GC
- `ast.c`
- Almost all change is replacement `rb_ast_t *ast` with `VALUE vast` (sorry for the big diff)
- Fix `node_memsize()`
- Now it includes `rb_ast_local_table_link`, `tokens` and script_lines
- `compile.c`, `load.c`, `node.c`, `parse.y`, `proc.c`, `ruby.c`, `template/prelude.c.tmpl`, `vm.c` and `vm_eval.c`
- Follow-up due to the above changes
- `imemo.{c|h}`
- If an object with `imemo_ast` appears, considers it a bug
Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
2024-04-16 12:42:42 +03:00
|
|
|
|
|
|
|
return sizeof(struct ASTNodeData) + rb_ast_memsize(ast);
|
2019-07-23 10:18:40 +03:00
|
|
|
}
|
|
|
|
|
2018-01-16 02:43:17 +03:00
|
|
|
static const rb_data_type_t rb_node_type = {
|
|
|
|
"AST/node",
|
2019-07-23 10:18:40 +03:00
|
|
|
{node_gc_mark, RUBY_TYPED_DEFAULT_FREE, node_memsize,},
|
2018-01-16 02:43:17 +03:00
|
|
|
0, 0,
|
|
|
|
RUBY_TYPED_FREE_IMMEDIATELY,
|
|
|
|
};
|
|
|
|
|
2024-07-10 16:28:22 +03:00
|
|
|
struct ASTLocationData {
|
|
|
|
int first_lineno;
|
|
|
|
int first_column;
|
|
|
|
int last_lineno;
|
|
|
|
int last_column;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
location_gc_mark(void *ptr)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static size_t
|
|
|
|
location_memsize(const void *ptr)
|
|
|
|
{
|
|
|
|
return sizeof(struct ASTLocationData);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const rb_data_type_t rb_location_type = {
|
|
|
|
"AST/location",
|
|
|
|
{location_gc_mark, RUBY_TYPED_DEFAULT_FREE, location_memsize,},
|
|
|
|
0, 0,
|
|
|
|
RUBY_TYPED_FREE_IMMEDIATELY,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2018-01-16 02:43:17 +03:00
|
|
|
static VALUE rb_ast_node_alloc(VALUE klass);
|
|
|
|
|
|
|
|
static void
|
2024-05-03 02:57:55 +03:00
|
|
|
setup_node(VALUE obj, VALUE ast_value, const NODE *node)
|
2018-01-16 02:43:17 +03:00
|
|
|
{
|
|
|
|
struct ASTNodeData *data;
|
|
|
|
|
|
|
|
TypedData_Get_Struct(obj, struct ASTNodeData, &rb_node_type, data);
|
2024-05-03 02:57:55 +03:00
|
|
|
data->ast_value = ast_value;
|
2018-01-16 02:43:17 +03:00
|
|
|
data->node = node;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2024-05-03 02:57:55 +03:00
|
|
|
ast_new_internal(VALUE ast_value, const NODE *node)
|
2018-01-16 02:43:17 +03:00
|
|
|
{
|
|
|
|
VALUE obj;
|
|
|
|
|
|
|
|
obj = rb_ast_node_alloc(rb_cNode);
|
2024-05-03 02:57:55 +03:00
|
|
|
setup_node(obj, ast_value, node);
|
2018-01-16 02:43:17 +03:00
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2022-09-23 16:40:02 +03:00
|
|
|
static VALUE rb_ast_parse_str(VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens);
|
|
|
|
static VALUE rb_ast_parse_file(VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens);
|
2018-11-09 16:39:35 +03:00
|
|
|
|
2018-11-10 14:16:36 +03:00
|
|
|
static VALUE
|
|
|
|
ast_parse_new(void)
|
|
|
|
{
|
|
|
|
return rb_parser_set_context(rb_parser_new(), NULL, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2024-05-03 02:57:55 +03:00
|
|
|
ast_parse_done(VALUE ast_value)
|
2018-11-10 14:16:36 +03:00
|
|
|
{
|
2024-05-03 02:57:55 +03:00
|
|
|
rb_ast_t *ast = rb_ruby_ast_data_get(ast_value);
|
[Universal parser] Decouple IMEMO from rb_ast_t
This patch removes the `VALUE flags` member from the `rb_ast_t` structure making `rb_ast_t` no longer an IMEMO object.
## Background
We are trying to make the Ruby parser generated from parse.y a universal parser that can be used by other implementations such as mruby.
To achieve this, it is necessary to exclude VALUE and IMEMO from parse.y, AST, and NODE.
## Summary (file by file)
- `rubyparser.h`
- Remove the `VALUE flags` member from `rb_ast_t`
- `ruby_parser.c` and `internal/ruby_parser.h`
- Use TypedData_Make_Struct VALUE which wraps `rb_ast_t` `in ast_alloc()` so that GC can manage it
- You can retrieve `rb_ast_t` from the VALUE by `rb_ruby_ast_data_get()`
- Change the return type of `rb_parser_compile_XXXX()` functions from `rb_ast_t *` to `VALUE`
- rb_ruby_ast_new() which internally `calls ast_alloc()` is to create VALUE vast outside ruby_parser.c
- `iseq.c` and `vm_core.h`
- Amend the first parameter of `rb_iseq_new_XXXX()` functions from `rb_ast_body_t *` to `VALUE`
- This keeps the VALUE of AST on the machine stack to prevent being removed by GC
- `ast.c`
- Almost all change is replacement `rb_ast_t *ast` with `VALUE vast` (sorry for the big diff)
- Fix `node_memsize()`
- Now it includes `rb_ast_local_table_link`, `tokens` and script_lines
- `compile.c`, `load.c`, `node.c`, `parse.y`, `proc.c`, `ruby.c`, `template/prelude.c.tmpl`, `vm.c` and `vm_eval.c`
- Follow-up due to the above changes
- `imemo.{c|h}`
- If an object with `imemo_ast` appears, considers it a bug
Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
2024-04-16 12:42:42 +03:00
|
|
|
|
2018-11-10 14:16:36 +03:00
|
|
|
if (!ast->body.root) {
|
|
|
|
rb_ast_dispose(ast);
|
|
|
|
rb_exc_raise(GET_EC()->errinfo);
|
|
|
|
}
|
|
|
|
|
2024-05-03 02:57:55 +03:00
|
|
|
return ast_new_internal(ast_value, (NODE *)ast->body.root);
|
2018-11-10 14:16:36 +03:00
|
|
|
}
|
|
|
|
|
2018-01-16 02:43:17 +03:00
|
|
|
static VALUE
|
2022-09-23 16:40:02 +03:00
|
|
|
ast_s_parse(rb_execution_context_t *ec, VALUE module, VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
|
2018-11-09 16:39:35 +03:00
|
|
|
{
|
2022-09-23 16:40:02 +03:00
|
|
|
return rb_ast_parse_str(str, keep_script_lines, error_tolerant, keep_tokens);
|
2018-11-09 16:39:35 +03:00
|
|
|
}
|
|
|
|
|
2018-11-11 03:55:19 +03:00
|
|
|
static VALUE
|
2022-09-23 16:40:02 +03:00
|
|
|
rb_ast_parse_str(VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
|
2018-01-16 02:43:17 +03:00
|
|
|
{
|
2024-05-03 02:57:55 +03:00
|
|
|
VALUE ast_value;
|
2018-01-16 02:43:17 +03:00
|
|
|
|
2019-01-06 08:07:10 +03:00
|
|
|
StringValue(str);
|
2021-06-17 17:43:08 +03:00
|
|
|
VALUE vparser = ast_parse_new();
|
2024-03-28 04:26:42 +03:00
|
|
|
if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser);
|
2022-09-25 11:53:44 +03:00
|
|
|
if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
|
2022-09-23 16:40:02 +03:00
|
|
|
if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
|
2024-05-03 02:57:55 +03:00
|
|
|
ast_value = rb_parser_compile_string_path(vparser, Qnil, str, 1);
|
|
|
|
return ast_parse_done(ast_value);
|
2018-01-16 02:43:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2022-09-23 16:40:02 +03:00
|
|
|
ast_s_parse_file(rb_execution_context_t *ec, VALUE module, VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
|
2018-11-09 16:39:35 +03:00
|
|
|
{
|
2022-09-23 16:40:02 +03:00
|
|
|
return rb_ast_parse_file(path, keep_script_lines, error_tolerant, keep_tokens);
|
2018-11-09 16:39:35 +03:00
|
|
|
}
|
|
|
|
|
2018-11-11 03:55:19 +03:00
|
|
|
static VALUE
|
2022-09-23 16:40:02 +03:00
|
|
|
rb_ast_parse_file(VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
|
2018-01-16 02:43:17 +03:00
|
|
|
{
|
2018-11-10 14:16:36 +03:00
|
|
|
VALUE f;
|
2024-05-03 02:57:55 +03:00
|
|
|
VALUE ast_value = Qnil;
|
2018-01-16 02:43:17 +03:00
|
|
|
rb_encoding *enc = rb_utf8_encoding();
|
|
|
|
|
|
|
|
f = rb_file_open_str(path, "r");
|
|
|
|
rb_funcall(f, rb_intern("set_encoding"), 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-"));
|
2021-06-17 17:43:08 +03:00
|
|
|
VALUE vparser = ast_parse_new();
|
2024-03-28 04:26:42 +03:00
|
|
|
if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser);
|
2022-09-25 11:53:44 +03:00
|
|
|
if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
|
2022-09-23 16:40:02 +03:00
|
|
|
if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
|
2024-05-03 02:57:55 +03:00
|
|
|
ast_value = rb_parser_compile_file_path(vparser, Qnil, f, 1);
|
2018-01-16 02:43:17 +03:00
|
|
|
rb_io_close(f);
|
2024-05-03 02:57:55 +03:00
|
|
|
return ast_parse_done(ast_value);
|
2018-01-16 02:43:17 +03:00
|
|
|
}
|
|
|
|
|
2018-11-11 03:55:19 +03:00
|
|
|
static VALUE
|
2022-09-23 16:40:02 +03:00
|
|
|
rb_ast_parse_array(VALUE array, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
|
2018-11-10 14:40:33 +03:00
|
|
|
{
|
2024-05-03 02:57:55 +03:00
|
|
|
VALUE ast_value = Qnil;
|
2018-11-10 14:40:33 +03:00
|
|
|
|
|
|
|
array = rb_check_array_type(array);
|
2021-06-17 17:43:08 +03:00
|
|
|
VALUE vparser = ast_parse_new();
|
2024-03-28 04:26:42 +03:00
|
|
|
if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser);
|
2022-09-25 11:53:44 +03:00
|
|
|
if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
|
2022-09-23 16:40:02 +03:00
|
|
|
if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
|
2024-05-03 02:57:55 +03:00
|
|
|
ast_value = rb_parser_compile_array(vparser, Qnil, array, 1);
|
|
|
|
return ast_parse_done(ast_value);
|
2018-11-10 14:40:33 +03:00
|
|
|
}
|
|
|
|
|
[Universal parser] Decouple IMEMO from rb_ast_t
This patch removes the `VALUE flags` member from the `rb_ast_t` structure making `rb_ast_t` no longer an IMEMO object.
## Background
We are trying to make the Ruby parser generated from parse.y a universal parser that can be used by other implementations such as mruby.
To achieve this, it is necessary to exclude VALUE and IMEMO from parse.y, AST, and NODE.
## Summary (file by file)
- `rubyparser.h`
- Remove the `VALUE flags` member from `rb_ast_t`
- `ruby_parser.c` and `internal/ruby_parser.h`
- Use TypedData_Make_Struct VALUE which wraps `rb_ast_t` `in ast_alloc()` so that GC can manage it
- You can retrieve `rb_ast_t` from the VALUE by `rb_ruby_ast_data_get()`
- Change the return type of `rb_parser_compile_XXXX()` functions from `rb_ast_t *` to `VALUE`
- rb_ruby_ast_new() which internally `calls ast_alloc()` is to create VALUE vast outside ruby_parser.c
- `iseq.c` and `vm_core.h`
- Amend the first parameter of `rb_iseq_new_XXXX()` functions from `rb_ast_body_t *` to `VALUE`
- This keeps the VALUE of AST on the machine stack to prevent being removed by GC
- `ast.c`
- Almost all change is replacement `rb_ast_t *ast` with `VALUE vast` (sorry for the big diff)
- Fix `node_memsize()`
- Now it includes `rb_ast_local_table_link`, `tokens` and script_lines
- `compile.c`, `load.c`, `node.c`, `parse.y`, `proc.c`, `ruby.c`, `template/prelude.c.tmpl`, `vm.c` and `vm_eval.c`
- Follow-up due to the above changes
- `imemo.{c|h}`
- If an object with `imemo_ast` appears, considers it a bug
Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
2024-04-16 12:42:42 +03:00
|
|
|
static VALUE node_children(VALUE, const NODE*);
|
2018-11-05 05:13:45 +03:00
|
|
|
|
|
|
|
static VALUE
|
|
|
|
node_find(VALUE self, const int node_id)
|
|
|
|
{
|
|
|
|
VALUE ary;
|
|
|
|
long i;
|
|
|
|
struct ASTNodeData *data;
|
|
|
|
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
|
|
|
|
|
|
|
|
if (nd_node_id(data->node) == node_id) return self;
|
|
|
|
|
2024-05-03 02:57:55 +03:00
|
|
|
ary = node_children(data->ast_value, data->node);
|
2018-11-05 05:13:45 +03:00
|
|
|
|
|
|
|
for (i = 0; i < RARRAY_LEN(ary); i++) {
|
|
|
|
VALUE child = RARRAY_AREF(ary, i);
|
|
|
|
|
|
|
|
if (CLASS_OF(child) == rb_cNode) {
|
|
|
|
VALUE result = node_find(child, node_id);
|
|
|
|
if (RTEST(result)) return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
2018-11-10 14:43:02 +03:00
|
|
|
extern VALUE rb_e_script;
|
|
|
|
|
2022-10-19 20:23:53 +03:00
|
|
|
static VALUE
|
|
|
|
node_id_for_backtrace_location(rb_execution_context_t *ec, VALUE module, VALUE location)
|
|
|
|
{
|
|
|
|
int node_id;
|
2022-12-26 11:45:44 +03:00
|
|
|
|
|
|
|
if (!rb_frame_info_p(location)) {
|
|
|
|
rb_raise(rb_eTypeError, "Thread::Backtrace::Location object expected");
|
|
|
|
}
|
|
|
|
|
2022-10-19 20:23:53 +03:00
|
|
|
node_id = rb_get_node_id_from_frame_info(location);
|
|
|
|
if (node_id == -1) {
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
return INT2NUM(node_id);
|
|
|
|
}
|
|
|
|
|
2018-11-05 05:13:45 +03:00
|
|
|
static VALUE
|
2022-09-23 16:40:02 +03:00
|
|
|
ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
|
2018-11-05 05:13:45 +03:00
|
|
|
{
|
2021-12-26 13:41:42 +03:00
|
|
|
VALUE node, lines = Qnil;
|
2021-12-18 21:40:44 +03:00
|
|
|
const rb_iseq_t *iseq;
|
2018-11-05 05:13:45 +03:00
|
|
|
int node_id;
|
|
|
|
|
2021-06-08 11:34:08 +03:00
|
|
|
if (rb_frame_info_p(body)) {
|
2021-12-18 21:40:44 +03:00
|
|
|
iseq = rb_get_iseq_from_frame_info(body);
|
|
|
|
node_id = rb_get_node_id_from_frame_info(body);
|
2018-11-05 05:13:45 +03:00
|
|
|
}
|
|
|
|
else {
|
2021-12-18 21:40:44 +03:00
|
|
|
iseq = NULL;
|
2021-06-08 11:34:08 +03:00
|
|
|
|
|
|
|
if (rb_obj_is_proc(body)) {
|
|
|
|
iseq = vm_proc_iseq(body);
|
2018-11-05 05:13:45 +03:00
|
|
|
|
2021-06-08 11:34:08 +03:00
|
|
|
if (!rb_obj_is_iseq((VALUE)iseq)) return Qnil;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
iseq = rb_method_iseq(body);
|
|
|
|
}
|
2021-12-18 21:40:44 +03:00
|
|
|
if (iseq) {
|
2022-03-23 22:19:48 +03:00
|
|
|
node_id = ISEQ_BODY(iseq)->location.node_id;
|
2021-09-18 15:28:35 +03:00
|
|
|
}
|
2021-06-08 11:34:08 +03:00
|
|
|
}
|
2018-11-05 05:13:45 +03:00
|
|
|
|
2021-12-18 21:40:44 +03:00
|
|
|
if (!iseq) {
|
|
|
|
return Qnil;
|
|
|
|
}
|
2024-02-14 18:58:20 +03:00
|
|
|
|
|
|
|
if (ISEQ_BODY(iseq)->prism) {
|
|
|
|
rb_raise(rb_eRuntimeError, "cannot get AST for ISEQ compiled by prism");
|
|
|
|
}
|
|
|
|
|
2022-03-23 22:19:48 +03:00
|
|
|
lines = ISEQ_BODY(iseq)->variable.script_lines;
|
2021-12-26 13:41:42 +03:00
|
|
|
|
|
|
|
VALUE path = rb_iseq_path(iseq);
|
|
|
|
int e_option = RSTRING_LEN(path) == 2 && memcmp(RSTRING_PTR(path), "-e", 2) == 0;
|
|
|
|
|
|
|
|
if (NIL_P(lines) && rb_iseq_from_eval_p(iseq) && !e_option) {
|
2021-12-18 21:40:44 +03:00
|
|
|
rb_raise(rb_eArgError, "cannot get AST for method defined in eval");
|
|
|
|
}
|
|
|
|
|
2024-03-29 10:18:14 +03:00
|
|
|
if (!NIL_P(lines)) {
|
2022-09-23 16:40:02 +03:00
|
|
|
node = rb_ast_parse_array(lines, keep_script_lines, error_tolerant, keep_tokens);
|
2018-11-10 13:39:58 +03:00
|
|
|
}
|
2021-12-26 13:41:42 +03:00
|
|
|
else if (e_option) {
|
2022-09-23 16:40:02 +03:00
|
|
|
node = rb_ast_parse_str(rb_e_script, keep_script_lines, error_tolerant, keep_tokens);
|
2018-11-10 14:43:02 +03:00
|
|
|
}
|
2018-11-10 13:39:58 +03:00
|
|
|
else {
|
2022-09-23 16:40:02 +03:00
|
|
|
node = rb_ast_parse_file(path, keep_script_lines, error_tolerant, keep_tokens);
|
2018-11-10 13:39:58 +03:00
|
|
|
}
|
2018-11-05 05:13:45 +03:00
|
|
|
|
|
|
|
return node_find(node, node_id);
|
|
|
|
}
|
|
|
|
|
2018-01-16 02:43:17 +03:00
|
|
|
static VALUE
|
|
|
|
rb_ast_node_alloc(VALUE klass)
|
|
|
|
{
|
|
|
|
struct ASTNodeData *data;
|
|
|
|
VALUE obj = TypedData_Make_Struct(klass, struct ASTNodeData, &rb_node_type, data);
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char*
|
2018-12-03 04:06:34 +03:00
|
|
|
node_type_to_str(const NODE *node)
|
2018-01-16 02:43:17 +03:00
|
|
|
{
|
2023-05-24 11:24:41 +03:00
|
|
|
return (ruby_node_name(nd_type(node)) + rb_strlen_lit("NODE_"));
|
2018-01-16 02:43:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2019-11-07 12:29:20 +03:00
|
|
|
ast_node_type(rb_execution_context_t *ec, VALUE self)
|
2018-01-16 02:43:17 +03:00
|
|
|
{
|
|
|
|
struct ASTNodeData *data;
|
|
|
|
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
|
|
|
|
|
2018-12-03 04:06:34 +03:00
|
|
|
return rb_sym_intern_ascii_cstr(node_type_to_str(data->node));
|
2018-01-16 02:43:17 +03:00
|
|
|
}
|
|
|
|
|
2021-04-30 12:54:46 +03:00
|
|
|
static VALUE
|
2021-06-21 15:15:25 +03:00
|
|
|
ast_node_node_id(rb_execution_context_t *ec, VALUE self)
|
2021-04-30 12:54:46 +03:00
|
|
|
{
|
|
|
|
struct ASTNodeData *data;
|
|
|
|
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
|
|
|
|
|
|
|
|
return INT2FIX(nd_node_id(data->node));
|
|
|
|
}
|
|
|
|
|
2024-05-03 02:57:55 +03:00
|
|
|
#define NEW_CHILD(ast_value, node) (node ? ast_new_internal(ast_value, node) : Qnil)
|
2018-01-16 02:43:17 +03:00
|
|
|
|
|
|
|
static VALUE
|
2024-05-03 02:57:55 +03:00
|
|
|
rb_ary_new_from_node_args(VALUE ast_value, long n, ...)
|
2018-01-16 02:43:17 +03:00
|
|
|
{
|
|
|
|
va_list ar;
|
|
|
|
VALUE ary;
|
|
|
|
long i;
|
|
|
|
|
|
|
|
ary = rb_ary_new2(n);
|
|
|
|
|
|
|
|
va_start(ar, n);
|
|
|
|
for (i=0; i<n; i++) {
|
2018-06-06 09:14:21 +03:00
|
|
|
NODE *node;
|
|
|
|
node = va_arg(ar, NODE *);
|
2024-05-03 02:57:55 +03:00
|
|
|
rb_ary_push(ary, NEW_CHILD(ast_value, node));
|
2018-01-16 02:43:17 +03:00
|
|
|
}
|
|
|
|
va_end(ar);
|
|
|
|
return ary;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2024-05-03 02:57:55 +03:00
|
|
|
dump_block(VALUE ast_value, const struct RNode_BLOCK *node)
|
2018-01-16 02:43:17 +03:00
|
|
|
{
|
|
|
|
VALUE ary = rb_ary_new();
|
|
|
|
do {
|
2024-05-03 02:57:55 +03:00
|
|
|
rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_head));
|
2018-01-16 02:43:17 +03:00
|
|
|
} while (node->nd_next &&
|
2021-12-03 18:01:24 +03:00
|
|
|
nd_type_p(node->nd_next, NODE_BLOCK) &&
|
2023-08-22 04:26:38 +03:00
|
|
|
(node = RNODE_BLOCK(node->nd_next), 1));
|
2018-01-16 02:43:17 +03:00
|
|
|
if (node->nd_next) {
|
2024-05-03 02:57:55 +03:00
|
|
|
rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_next));
|
2018-01-16 02:43:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return ary;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2024-05-03 02:57:55 +03:00
|
|
|
dump_array(VALUE ast_value, const struct RNode_LIST *node)
|
2018-01-16 02:43:17 +03:00
|
|
|
{
|
|
|
|
VALUE ary = rb_ary_new();
|
2024-05-03 02:57:55 +03:00
|
|
|
rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_head));
|
2018-01-16 02:43:17 +03:00
|
|
|
|
2021-12-03 18:01:24 +03:00
|
|
|
while (node->nd_next && nd_type_p(node->nd_next, NODE_LIST)) {
|
2023-08-22 04:26:38 +03:00
|
|
|
node = RNODE_LIST(node->nd_next);
|
2024-05-03 02:57:55 +03:00
|
|
|
rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_head));
|
2018-01-16 02:43:17 +03:00
|
|
|
}
|
2024-05-03 02:57:55 +03:00
|
|
|
rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_next));
|
2018-01-16 02:43:17 +03:00
|
|
|
|
|
|
|
return ary;
|
|
|
|
}
|
|
|
|
|
Change UNDEF Node structure
Change UNDEF Node to hold their items to keep the original grammar
structure.
For example:
```
undef a, b
```
Before:
```
@ NODE_BLOCK (id: 4, line: 1, location: (1,6)-(1,10))*
+- nd_head (1):
| @ NODE_UNDEF (id: 1, line: 1, location: (1,6)-(1,7))
| +- nd_undef:
| @ NODE_SYM (id: 0, line: 1, location: (1,6)-(1,7))
| +- string: :a
+- nd_head (2):
@ NODE_UNDEF (id: 3, line: 1, location: (1,9)-(1,10))
+- nd_undef:
@ NODE_SYM (id: 2, line: 1, location: (1,9)-(1,10))
+- string: :b
```
After:
```
@ NODE_UNDEF (id: 1, line: 1, location: (1,6)-(1,10))*
+- nd_undefs:
+- length: 2
+- element (0):
| @ NODE_SYM (id: 0, line: 1, location: (1,6)-(1,7))
| +- string: :a
+- element (1):
@ NODE_SYM (id: 2, line: 1, location: (1,9)-(1,10))
+- string: :b
```
2024-07-18 07:47:13 +03:00
|
|
|
static VALUE
|
|
|
|
dump_parser_array(VALUE ast_value, rb_parser_ary_t *p_ary)
|
|
|
|
{
|
|
|
|
VALUE ary;
|
|
|
|
|
|
|
|
if (p_ary->data_type != PARSER_ARY_DATA_NODE) {
|
|
|
|
rb_bug("unexpected rb_parser_ary_data_type: %d", p_ary->data_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
ary = rb_ary_new();
|
|
|
|
|
|
|
|
for (long i = 0; i < p_ary->len; i++) {
|
|
|
|
rb_ary_push(ary, NEW_CHILD(ast_value, p_ary->data[i]));
|
|
|
|
}
|
|
|
|
|
|
|
|
return ary;
|
|
|
|
}
|
|
|
|
|
2018-06-07 17:46:25 +03:00
|
|
|
static VALUE
|
|
|
|
var_name(ID id)
|
|
|
|
{
|
|
|
|
if (!id) return Qnil;
|
|
|
|
if (!rb_id2str(id)) return Qnil;
|
|
|
|
return ID2SYM(id);
|
|
|
|
}
|
|
|
|
|
2020-07-08 12:26:57 +03:00
|
|
|
static VALUE
|
|
|
|
no_name_rest(void)
|
|
|
|
{
|
|
|
|
ID rest;
|
|
|
|
CONST_ID(rest, "NODE_SPECIAL_NO_NAME_REST");
|
|
|
|
return ID2SYM(rest);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2024-05-03 02:57:55 +03:00
|
|
|
rest_arg(VALUE ast_value, const NODE *rest_arg)
|
2020-07-08 12:26:57 +03:00
|
|
|
{
|
2024-05-03 02:57:55 +03:00
|
|
|
return NODE_NAMED_REST_P(rest_arg) ? NEW_CHILD(ast_value, rest_arg) : no_name_rest();
|
2020-07-08 12:26:57 +03:00
|
|
|
}
|
|
|
|
|
2018-01-16 02:43:17 +03:00
|
|
|
static VALUE
|
2024-05-03 02:57:55 +03:00
|
|
|
node_children(VALUE ast_value, const NODE *node)
|
2018-01-16 02:43:17 +03:00
|
|
|
{
|
2023-02-03 19:31:56 +03:00
|
|
|
char name[sizeof("$") + DECIMAL_SIZE_OF(long)];
|
2018-06-07 17:46:25 +03:00
|
|
|
|
2018-05-01 09:55:43 +03:00
|
|
|
enum node_type type = nd_type(node);
|
|
|
|
switch (type) {
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_BLOCK:
|
2024-05-03 02:57:55 +03:00
|
|
|
return dump_block(ast_value, RNODE_BLOCK(node));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_IF:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 3, RNODE_IF(node)->nd_cond, RNODE_IF(node)->nd_body, RNODE_IF(node)->nd_else);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_UNLESS:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 3, RNODE_UNLESS(node)->nd_cond, RNODE_UNLESS(node)->nd_body, RNODE_UNLESS(node)->nd_else);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_CASE:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 2, RNODE_CASE(node)->nd_head, RNODE_CASE(node)->nd_body);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_CASE2:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 2, RNODE_CASE2(node)->nd_head, RNODE_CASE2(node)->nd_body);
|
2019-04-17 09:48:03 +03:00
|
|
|
case NODE_CASE3:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 2, RNODE_CASE3(node)->nd_head, RNODE_CASE3(node)->nd_body);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_WHEN:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 3, RNODE_WHEN(node)->nd_head, RNODE_WHEN(node)->nd_body, RNODE_WHEN(node)->nd_next);
|
2019-04-17 09:48:03 +03:00
|
|
|
case NODE_IN:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 3, RNODE_IN(node)->nd_head, RNODE_IN(node)->nd_body, RNODE_IN(node)->nd_next);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_WHILE:
|
|
|
|
case NODE_UNTIL:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_push(rb_ary_new_from_node_args(ast_value, 2, RNODE_WHILE(node)->nd_cond, RNODE_WHILE(node)->nd_body),
|
2023-08-22 04:26:38 +03:00
|
|
|
RBOOL(RNODE_WHILE(node)->nd_state));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_ITER:
|
|
|
|
case NODE_FOR:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 2, RNODE_ITER(node)->nd_iter, RNODE_ITER(node)->nd_body);
|
2018-01-16 10:24:53 +03:00
|
|
|
case NODE_FOR_MASGN:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 1, RNODE_FOR_MASGN(node)->nd_var);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_BREAK:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 1, RNODE_BREAK(node)->nd_stts);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_NEXT:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 1, RNODE_NEXT(node)->nd_stts);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_RETURN:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 1, RNODE_RETURN(node)->nd_stts);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_REDO:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 0);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_RETRY:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 0);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_BEGIN:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 1, RNODE_BEGIN(node)->nd_body);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_RESCUE:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 3, RNODE_RESCUE(node)->nd_head, RNODE_RESCUE(node)->nd_resq, RNODE_RESCUE(node)->nd_else);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_RESBODY:
|
Change RESBODY Node structure
Extracrt exception variable into `nd_exc_var` field
to keep the original grammar structure.
For example:
```
begin
rescue Error => e1
end
```
Before:
```
@ NODE_RESBODY (id: 8, line: 2, location: (2,0)-(2,18))
+- nd_args:
| @ NODE_LIST (id: 2, line: 2, location: (2,7)-(2,12))
| +- as.nd_alen: 1
| +- nd_head:
| | @ NODE_CONST (id: 1, line: 2, location: (2,7)-(2,12))
| | +- nd_vid: :Error
| +- nd_next:
| (null node)
+- nd_body:
| @ NODE_BLOCK (id: 6, line: 2, location: (2,13)-(2,18))
| +- nd_head (1):
| | @ NODE_LASGN (id: 3, line: 2, location: (2,13)-(2,18))
| | +- nd_vid: :e1
| | +- nd_value:
| | @ NODE_ERRINFO (id: 5, line: 2, location: (2,13)-(2,18))
| +- nd_head (2):
| @ NODE_BEGIN (id: 4, line: 2, location: (2,18)-(2,18))
| +- nd_body:
| (null node)
+- nd_next:
(null node)
```
After:
```
@ NODE_RESBODY (id: 6, line: 2, location: (2,0)-(2,18))
+- nd_args:
| @ NODE_LIST (id: 2, line: 2, location: (2,7)-(2,12))
| +- as.nd_alen: 1
| +- nd_head:
| | @ NODE_CONST (id: 1, line: 2, location: (2,7)-(2,12))
| | +- nd_vid: :Error
| +- nd_next:
| (null node)
+- nd_exc_var:
| @ NODE_LASGN (id: 3, line: 2, location: (2,13)-(2,18))
| +- nd_vid: :e1
| +- nd_value:
| @ NODE_ERRINFO (id: 5, line: 2, location: (2,13)-(2,18))
+- nd_body:
| @ NODE_BEGIN (id: 4, line: 2, location: (2,18)-(2,18))
| +- nd_body:
| (null node)
+- nd_next:
(null node)
```
2024-07-25 08:57:14 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 4, RNODE_RESBODY(node)->nd_args, RNODE_RESBODY(node)->nd_exc_var, RNODE_RESBODY(node)->nd_body, RNODE_RESBODY(node)->nd_next);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_ENSURE:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 2, RNODE_ENSURE(node)->nd_head, RNODE_ENSURE(node)->nd_ensr);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_AND:
|
|
|
|
case NODE_OR:
|
2018-06-06 09:14:21 +03:00
|
|
|
{
|
|
|
|
VALUE ary = rb_ary_new();
|
|
|
|
|
|
|
|
while (1) {
|
2024-05-03 02:57:55 +03:00
|
|
|
rb_ary_push(ary, NEW_CHILD(ast_value, RNODE_AND(node)->nd_1st));
|
2023-08-22 04:26:38 +03:00
|
|
|
if (!RNODE_AND(node)->nd_2nd || !nd_type_p(RNODE_AND(node)->nd_2nd, type))
|
2018-06-06 09:14:21 +03:00
|
|
|
break;
|
2023-08-22 04:26:38 +03:00
|
|
|
node = RNODE_AND(node)->nd_2nd;
|
2018-06-06 09:14:21 +03:00
|
|
|
}
|
2024-05-03 02:57:55 +03:00
|
|
|
rb_ary_push(ary, NEW_CHILD(ast_value, RNODE_AND(node)->nd_2nd));
|
2018-06-06 09:14:21 +03:00
|
|
|
return ary;
|
|
|
|
}
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_MASGN:
|
2023-08-22 04:26:38 +03:00
|
|
|
if (NODE_NAMED_REST_P(RNODE_MASGN(node)->nd_args)) {
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 3, RNODE_MASGN(node)->nd_value, RNODE_MASGN(node)->nd_head, RNODE_MASGN(node)->nd_args);
|
2018-01-16 02:43:17 +03:00
|
|
|
}
|
2019-04-20 06:25:36 +03:00
|
|
|
else {
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_MASGN(node)->nd_value),
|
|
|
|
NEW_CHILD(ast_value, RNODE_MASGN(node)->nd_head),
|
2020-07-08 12:26:57 +03:00
|
|
|
no_name_rest());
|
2019-04-20 06:25:36 +03:00
|
|
|
}
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_LASGN:
|
2023-10-07 03:52:06 +03:00
|
|
|
if (NODE_REQUIRED_KEYWORD_P(RNODE_LASGN(node)->nd_value)) {
|
2023-08-22 04:26:38 +03:00
|
|
|
return rb_ary_new_from_args(2, var_name(RNODE_LASGN(node)->nd_vid), ID2SYM(rb_intern("NODE_SPECIAL_REQUIRED_KEYWORD")));
|
2018-01-16 02:43:17 +03:00
|
|
|
}
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(2, var_name(RNODE_LASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_LASGN(node)->nd_value));
|
2023-10-07 04:37:33 +03:00
|
|
|
case NODE_DASGN:
|
|
|
|
if (NODE_REQUIRED_KEYWORD_P(RNODE_DASGN(node)->nd_value)) {
|
|
|
|
return rb_ary_new_from_args(2, var_name(RNODE_DASGN(node)->nd_vid), ID2SYM(rb_intern("NODE_SPECIAL_REQUIRED_KEYWORD")));
|
|
|
|
}
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(2, var_name(RNODE_DASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_DASGN(node)->nd_value));
|
2023-10-07 04:37:33 +03:00
|
|
|
case NODE_IASGN:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(2, var_name(RNODE_IASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_IASGN(node)->nd_value));
|
2023-10-07 04:37:33 +03:00
|
|
|
case NODE_CVASGN:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(2, var_name(RNODE_CVASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_CVASGN(node)->nd_value));
|
2023-10-07 04:37:33 +03:00
|
|
|
case NODE_GASGN:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(2, var_name(RNODE_GASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_GASGN(node)->nd_value));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_CDECL:
|
2023-08-22 04:26:38 +03:00
|
|
|
if (RNODE_CDECL(node)->nd_vid) {
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(2, ID2SYM(RNODE_CDECL(node)->nd_vid), NEW_CHILD(ast_value, RNODE_CDECL(node)->nd_value));
|
2018-01-16 02:43:17 +03:00
|
|
|
}
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_CDECL(node)->nd_else), ID2SYM(RNODE_COLON2(RNODE_CDECL(node)->nd_else)->nd_mid), NEW_CHILD(ast_value, RNODE_CDECL(node)->nd_value));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_OP_ASGN1:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(4, NEW_CHILD(ast_value, RNODE_OP_ASGN1(node)->nd_recv),
|
2023-08-22 04:26:38 +03:00
|
|
|
ID2SYM(RNODE_OP_ASGN1(node)->nd_mid),
|
2024-05-03 02:57:55 +03:00
|
|
|
NEW_CHILD(ast_value, RNODE_OP_ASGN1(node)->nd_index),
|
|
|
|
NEW_CHILD(ast_value, RNODE_OP_ASGN1(node)->nd_rvalue));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_OP_ASGN2:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(5, NEW_CHILD(ast_value, RNODE_OP_ASGN2(node)->nd_recv),
|
2023-09-27 15:58:16 +03:00
|
|
|
RBOOL(RNODE_OP_ASGN2(node)->nd_aid),
|
|
|
|
ID2SYM(RNODE_OP_ASGN2(node)->nd_vid),
|
|
|
|
ID2SYM(RNODE_OP_ASGN2(node)->nd_mid),
|
2024-05-03 02:57:55 +03:00
|
|
|
NEW_CHILD(ast_value, RNODE_OP_ASGN2(node)->nd_value));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_OP_ASGN_AND:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_OP_ASGN_AND(node)->nd_head), ID2SYM(idANDOP),
|
|
|
|
NEW_CHILD(ast_value, RNODE_OP_ASGN_AND(node)->nd_value));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_OP_ASGN_OR:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_OP_ASGN_OR(node)->nd_head), ID2SYM(idOROP),
|
|
|
|
NEW_CHILD(ast_value, RNODE_OP_ASGN_OR(node)->nd_value));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_OP_CDECL:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_OP_CDECL(node)->nd_head),
|
2023-08-22 04:26:38 +03:00
|
|
|
ID2SYM(RNODE_OP_CDECL(node)->nd_aid),
|
2024-05-03 02:57:55 +03:00
|
|
|
NEW_CHILD(ast_value, RNODE_OP_CDECL(node)->nd_value));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_CALL:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_CALL(node)->nd_recv),
|
2023-08-22 04:26:38 +03:00
|
|
|
ID2SYM(RNODE_CALL(node)->nd_mid),
|
2024-05-03 02:57:55 +03:00
|
|
|
NEW_CHILD(ast_value, RNODE_CALL(node)->nd_args));
|
2023-10-09 03:20:53 +03:00
|
|
|
case NODE_OPCALL:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_OPCALL(node)->nd_recv),
|
2023-10-09 03:20:53 +03:00
|
|
|
ID2SYM(RNODE_OPCALL(node)->nd_mid),
|
2024-05-03 02:57:55 +03:00
|
|
|
NEW_CHILD(ast_value, RNODE_OPCALL(node)->nd_args));
|
2023-10-09 03:20:53 +03:00
|
|
|
case NODE_QCALL:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_QCALL(node)->nd_recv),
|
2023-10-09 03:20:53 +03:00
|
|
|
ID2SYM(RNODE_QCALL(node)->nd_mid),
|
2024-05-03 02:57:55 +03:00
|
|
|
NEW_CHILD(ast_value, RNODE_QCALL(node)->nd_args));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_FCALL:
|
2023-08-22 04:26:38 +03:00
|
|
|
return rb_ary_new_from_args(2, ID2SYM(RNODE_FCALL(node)->nd_mid),
|
2024-05-03 02:57:55 +03:00
|
|
|
NEW_CHILD(ast_value, RNODE_FCALL(node)->nd_args));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_VCALL:
|
2023-08-22 04:26:38 +03:00
|
|
|
return rb_ary_new_from_args(1, ID2SYM(RNODE_VCALL(node)->nd_mid));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_SUPER:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 1, RNODE_SUPER(node)->nd_args);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_ZSUPER:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 0);
|
2019-09-07 04:42:00 +03:00
|
|
|
case NODE_LIST:
|
2024-05-03 02:57:55 +03:00
|
|
|
return dump_array(ast_value, RNODE_LIST(node));
|
2019-09-07 04:42:00 +03:00
|
|
|
case NODE_ZLIST:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 0);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_HASH:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 1, RNODE_HASH(node)->nd_head);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_YIELD:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 1, RNODE_YIELD(node)->nd_head);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_LVAR:
|
2023-08-22 04:26:38 +03:00
|
|
|
return rb_ary_new_from_args(1, var_name(RNODE_LVAR(node)->nd_vid));
|
2023-10-09 03:27:24 +03:00
|
|
|
case NODE_DVAR:
|
|
|
|
return rb_ary_new_from_args(1, var_name(RNODE_DVAR(node)->nd_vid));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_IVAR:
|
2023-10-09 03:27:24 +03:00
|
|
|
return rb_ary_new_from_args(1, ID2SYM(RNODE_IVAR(node)->nd_vid));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_CONST:
|
2023-10-09 03:27:24 +03:00
|
|
|
return rb_ary_new_from_args(1, ID2SYM(RNODE_CONST(node)->nd_vid));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_CVAR:
|
2023-10-09 03:27:24 +03:00
|
|
|
return rb_ary_new_from_args(1, ID2SYM(RNODE_CVAR(node)->nd_vid));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_GVAR:
|
2023-10-09 03:27:24 +03:00
|
|
|
return rb_ary_new_from_args(1, ID2SYM(RNODE_GVAR(node)->nd_vid));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_NTH_REF:
|
2023-08-22 04:26:38 +03:00
|
|
|
snprintf(name, sizeof(name), "$%ld", RNODE_NTH_REF(node)->nd_nth);
|
2018-06-07 17:46:25 +03:00
|
|
|
return rb_ary_new_from_args(1, ID2SYM(rb_intern(name)));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_BACK_REF:
|
2018-06-07 17:46:25 +03:00
|
|
|
name[0] = '$';
|
2023-08-22 04:26:38 +03:00
|
|
|
name[1] = (char)RNODE_BACK_REF(node)->nd_nth;
|
2018-06-07 17:46:25 +03:00
|
|
|
name[2] = '\0';
|
|
|
|
return rb_ary_new_from_args(1, ID2SYM(rb_intern(name)));
|
2024-04-04 01:46:28 +03:00
|
|
|
case NODE_MATCH:
|
|
|
|
return rb_ary_new_from_args(1, rb_node_regx_string_val(node));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_MATCH2:
|
2023-08-22 04:26:38 +03:00
|
|
|
if (RNODE_MATCH2(node)->nd_args) {
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 3, RNODE_MATCH2(node)->nd_recv, RNODE_MATCH2(node)->nd_value, RNODE_MATCH2(node)->nd_args);
|
2018-06-06 09:14:21 +03:00
|
|
|
}
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 2, RNODE_MATCH2(node)->nd_recv, RNODE_MATCH2(node)->nd_value);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_MATCH3:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 2, RNODE_MATCH3(node)->nd_recv, RNODE_MATCH3(node)->nd_value);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_STR:
|
|
|
|
case NODE_XSTR:
|
2024-02-02 18:50:02 +03:00
|
|
|
return rb_ary_new_from_args(1, rb_node_str_string_val(node));
|
2024-01-05 06:03:11 +03:00
|
|
|
case NODE_INTEGER:
|
2024-01-08 06:20:03 +03:00
|
|
|
return rb_ary_new_from_args(1, rb_node_integer_literal_val(node));
|
2024-01-05 06:03:11 +03:00
|
|
|
case NODE_FLOAT:
|
2024-01-08 06:20:03 +03:00
|
|
|
return rb_ary_new_from_args(1, rb_node_float_literal_val(node));
|
2024-01-05 06:03:11 +03:00
|
|
|
case NODE_RATIONAL:
|
2024-01-08 06:20:03 +03:00
|
|
|
return rb_ary_new_from_args(1, rb_node_rational_literal_val(node));
|
2024-01-05 06:03:11 +03:00
|
|
|
case NODE_IMAGINARY:
|
2024-01-08 06:20:03 +03:00
|
|
|
return rb_ary_new_from_args(1, rb_node_imaginary_literal_val(node));
|
2024-02-10 04:05:18 +03:00
|
|
|
case NODE_REGX:
|
|
|
|
return rb_ary_new_from_args(1, rb_node_regx_string_val(node));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_ONCE:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 1, RNODE_ONCE(node)->nd_body);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_DSTR:
|
|
|
|
case NODE_DXSTR:
|
|
|
|
case NODE_DREGX:
|
|
|
|
case NODE_DSYM:
|
2020-09-02 17:12:22 +03:00
|
|
|
{
|
2023-08-22 04:26:38 +03:00
|
|
|
struct RNode_LIST *n = RNODE_DSTR(node)->nd_next;
|
2020-09-02 17:12:22 +03:00
|
|
|
VALUE head = Qnil, next = Qnil;
|
|
|
|
if (n) {
|
2024-05-03 02:57:55 +03:00
|
|
|
head = NEW_CHILD(ast_value, n->nd_head);
|
|
|
|
next = NEW_CHILD(ast_value, n->nd_next);
|
2020-09-02 17:12:22 +03:00
|
|
|
}
|
2024-02-02 18:50:02 +03:00
|
|
|
return rb_ary_new_from_args(3, rb_node_dstr_string_val(node), head, next);
|
2020-09-02 17:12:22 +03:00
|
|
|
}
|
2023-12-31 19:31:28 +03:00
|
|
|
case NODE_SYM:
|
|
|
|
return rb_ary_new_from_args(1, rb_node_sym_string_val(node));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_EVSTR:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 1, RNODE_EVSTR(node)->nd_body);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_ARGSCAT:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 2, RNODE_ARGSCAT(node)->nd_head, RNODE_ARGSCAT(node)->nd_body);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_ARGSPUSH:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 2, RNODE_ARGSPUSH(node)->nd_head, RNODE_ARGSPUSH(node)->nd_body);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_SPLAT:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 1, RNODE_SPLAT(node)->nd_head);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_BLOCK_PASS:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 2, RNODE_BLOCK_PASS(node)->nd_head, RNODE_BLOCK_PASS(node)->nd_body);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_DEFN:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(2, ID2SYM(RNODE_DEFN(node)->nd_mid), NEW_CHILD(ast_value, RNODE_DEFN(node)->nd_defn));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_DEFS:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_DEFS(node)->nd_recv), ID2SYM(RNODE_DEFS(node)->nd_mid), NEW_CHILD(ast_value, RNODE_DEFS(node)->nd_defn));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_ALIAS:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 2, RNODE_ALIAS(node)->nd_1st, RNODE_ALIAS(node)->nd_2nd);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_VALIAS:
|
2023-08-22 04:26:38 +03:00
|
|
|
return rb_ary_new_from_args(2, ID2SYM(RNODE_VALIAS(node)->nd_alias), ID2SYM(RNODE_VALIAS(node)->nd_orig));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_UNDEF:
|
Change UNDEF Node structure
Change UNDEF Node to hold their items to keep the original grammar
structure.
For example:
```
undef a, b
```
Before:
```
@ NODE_BLOCK (id: 4, line: 1, location: (1,6)-(1,10))*
+- nd_head (1):
| @ NODE_UNDEF (id: 1, line: 1, location: (1,6)-(1,7))
| +- nd_undef:
| @ NODE_SYM (id: 0, line: 1, location: (1,6)-(1,7))
| +- string: :a
+- nd_head (2):
@ NODE_UNDEF (id: 3, line: 1, location: (1,9)-(1,10))
+- nd_undef:
@ NODE_SYM (id: 2, line: 1, location: (1,9)-(1,10))
+- string: :b
```
After:
```
@ NODE_UNDEF (id: 1, line: 1, location: (1,6)-(1,10))*
+- nd_undefs:
+- length: 2
+- element (0):
| @ NODE_SYM (id: 0, line: 1, location: (1,6)-(1,7))
| +- string: :a
+- element (1):
@ NODE_SYM (id: 2, line: 1, location: (1,9)-(1,10))
+- string: :b
```
2024-07-18 07:47:13 +03:00
|
|
|
return rb_ary_new_from_args(1, dump_parser_array(ast_value, RNODE_UNDEF(node)->nd_undefs));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_CLASS:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 3, RNODE_CLASS(node)->nd_cpath, RNODE_CLASS(node)->nd_super, RNODE_CLASS(node)->nd_body);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_MODULE:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 2, RNODE_MODULE(node)->nd_cpath, RNODE_MODULE(node)->nd_body);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_SCLASS:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 2, RNODE_SCLASS(node)->nd_recv, RNODE_SCLASS(node)->nd_body);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_COLON2:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(2, NEW_CHILD(ast_value, RNODE_COLON2(node)->nd_head), ID2SYM(RNODE_COLON2(node)->nd_mid));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_COLON3:
|
2023-08-22 04:26:38 +03:00
|
|
|
return rb_ary_new_from_args(1, ID2SYM(RNODE_COLON3(node)->nd_mid));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_DOT2:
|
|
|
|
case NODE_DOT3:
|
|
|
|
case NODE_FLIP2:
|
|
|
|
case NODE_FLIP3:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 2, RNODE_DOT2(node)->nd_beg, RNODE_DOT2(node)->nd_end);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_SELF:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 0);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_NIL:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 0);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_TRUE:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 0);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_FALSE:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 0);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_ERRINFO:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 0);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_DEFINED:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 1, RNODE_DEFINED(node)->nd_head);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_POSTEXE:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 1, RNODE_POSTEXE(node)->nd_body);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_ATTRASGN:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_ATTRASGN(node)->nd_recv), ID2SYM(RNODE_ATTRASGN(node)->nd_mid), NEW_CHILD(ast_value, RNODE_ATTRASGN(node)->nd_args));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_LAMBDA:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 1, RNODE_LAMBDA(node)->nd_body);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_OPT_ARG:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 2, RNODE_OPT_ARG(node)->nd_body, RNODE_OPT_ARG(node)->nd_next);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_KW_ARG:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 2, RNODE_KW_ARG(node)->nd_body, RNODE_KW_ARG(node)->nd_next);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_POSTARG:
|
2023-08-22 04:26:38 +03:00
|
|
|
if (NODE_NAMED_REST_P(RNODE_POSTARG(node)->nd_1st)) {
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 2, RNODE_POSTARG(node)->nd_1st, RNODE_POSTARG(node)->nd_2nd);
|
2018-06-06 09:14:21 +03:00
|
|
|
}
|
2020-07-08 12:26:57 +03:00
|
|
|
return rb_ary_new_from_args(2, no_name_rest(),
|
2024-05-03 02:57:55 +03:00
|
|
|
NEW_CHILD(ast_value, RNODE_POSTARG(node)->nd_2nd));
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_ARGS:
|
2018-06-07 17:46:25 +03:00
|
|
|
{
|
2023-10-29 18:19:43 +03:00
|
|
|
struct rb_args_info *ainfo = &RNODE_ARGS(node)->nd_ainfo;
|
2018-06-07 17:46:25 +03:00
|
|
|
return rb_ary_new_from_args(10,
|
|
|
|
INT2NUM(ainfo->pre_args_num),
|
2024-05-03 02:57:55 +03:00
|
|
|
NEW_CHILD(ast_value, ainfo->pre_init),
|
|
|
|
NEW_CHILD(ast_value, (NODE *)ainfo->opt_args),
|
2018-06-07 17:46:25 +03:00
|
|
|
var_name(ainfo->first_post_arg),
|
|
|
|
INT2NUM(ainfo->post_args_num),
|
2024-05-03 02:57:55 +03:00
|
|
|
NEW_CHILD(ast_value, ainfo->post_init),
|
2020-07-07 14:18:18 +03:00
|
|
|
(ainfo->rest_arg == NODE_SPECIAL_EXCESSIVE_COMMA
|
|
|
|
? ID2SYM(rb_intern("NODE_SPECIAL_EXCESSIVE_COMMA"))
|
|
|
|
: var_name(ainfo->rest_arg)),
|
2024-05-03 02:57:55 +03:00
|
|
|
(ainfo->no_kwarg ? Qfalse : NEW_CHILD(ast_value, (NODE *)ainfo->kw_args)),
|
|
|
|
(ainfo->no_kwarg ? Qfalse : NEW_CHILD(ast_value, ainfo->kw_rest_arg)),
|
2018-06-07 17:46:25 +03:00
|
|
|
var_name(ainfo->block_arg));
|
|
|
|
}
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_SCOPE:
|
2018-06-07 17:46:25 +03:00
|
|
|
{
|
2023-08-22 04:26:38 +03:00
|
|
|
rb_ast_id_table_t *tbl = RNODE_SCOPE(node)->nd_tbl;
|
2021-11-17 21:40:49 +03:00
|
|
|
int i, size = tbl ? tbl->size : 0;
|
2018-06-07 17:46:25 +03:00
|
|
|
VALUE locals = rb_ary_new_capa(size);
|
|
|
|
for (i = 0; i < size; i++) {
|
2021-11-17 21:40:49 +03:00
|
|
|
rb_ary_push(locals, var_name(tbl->ids[i]));
|
2018-06-07 17:46:25 +03:00
|
|
|
}
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_args(3, locals, NEW_CHILD(ast_value, (NODE *)RNODE_SCOPE(node)->nd_args), NEW_CHILD(ast_value, RNODE_SCOPE(node)->nd_body));
|
2018-06-07 17:46:25 +03:00
|
|
|
}
|
2019-04-17 09:48:03 +03:00
|
|
|
case NODE_ARYPTN:
|
|
|
|
{
|
2024-05-03 02:57:55 +03:00
|
|
|
VALUE rest = rest_arg(ast_value, RNODE_ARYPTN(node)->rest_arg);
|
2019-04-17 09:48:03 +03:00
|
|
|
return rb_ary_new_from_args(4,
|
2024-05-03 02:57:55 +03:00
|
|
|
NEW_CHILD(ast_value, RNODE_ARYPTN(node)->nd_pconst),
|
|
|
|
NEW_CHILD(ast_value, RNODE_ARYPTN(node)->pre_args),
|
2019-04-20 06:37:22 +03:00
|
|
|
rest,
|
2024-05-03 02:57:55 +03:00
|
|
|
NEW_CHILD(ast_value, RNODE_ARYPTN(node)->post_args));
|
2019-04-17 09:48:03 +03:00
|
|
|
}
|
2020-06-14 03:24:36 +03:00
|
|
|
case NODE_FNDPTN:
|
|
|
|
{
|
2024-05-03 02:57:55 +03:00
|
|
|
VALUE pre_rest = rest_arg(ast_value, RNODE_FNDPTN(node)->pre_rest_arg);
|
|
|
|
VALUE post_rest = rest_arg(ast_value, RNODE_FNDPTN(node)->post_rest_arg);
|
2020-06-14 03:24:36 +03:00
|
|
|
return rb_ary_new_from_args(4,
|
2024-05-03 02:57:55 +03:00
|
|
|
NEW_CHILD(ast_value, RNODE_FNDPTN(node)->nd_pconst),
|
2020-06-14 03:24:36 +03:00
|
|
|
pre_rest,
|
2024-05-03 02:57:55 +03:00
|
|
|
NEW_CHILD(ast_value, RNODE_FNDPTN(node)->args),
|
2020-06-14 03:24:36 +03:00
|
|
|
post_rest);
|
|
|
|
}
|
2019-04-17 09:48:03 +03:00
|
|
|
case NODE_HSHPTN:
|
|
|
|
{
|
2023-08-22 04:26:38 +03:00
|
|
|
VALUE kwrest = RNODE_HSHPTN(node)->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD ? ID2SYM(rb_intern("NODE_SPECIAL_NO_REST_KEYWORD")) :
|
2024-05-03 02:57:55 +03:00
|
|
|
NEW_CHILD(ast_value, RNODE_HSHPTN(node)->nd_pkwrestarg);
|
2019-09-01 10:39:34 +03:00
|
|
|
|
2019-04-17 09:48:03 +03:00
|
|
|
return rb_ary_new_from_args(3,
|
2024-05-03 02:57:55 +03:00
|
|
|
NEW_CHILD(ast_value, RNODE_HSHPTN(node)->nd_pconst),
|
|
|
|
NEW_CHILD(ast_value, RNODE_HSHPTN(node)->nd_pkwargs),
|
2019-09-01 10:39:34 +03:00
|
|
|
kwrest);
|
2019-04-17 09:48:03 +03:00
|
|
|
}
|
2023-12-28 06:38:24 +03:00
|
|
|
case NODE_LINE:
|
|
|
|
return rb_ary_new_from_args(1, rb_node_line_lineno_val(node));
|
2023-12-29 16:34:35 +03:00
|
|
|
case NODE_FILE:
|
|
|
|
return rb_ary_new_from_args(1, rb_node_file_path_val(node));
|
2024-01-27 11:11:10 +03:00
|
|
|
case NODE_ENCODING:
|
|
|
|
return rb_ary_new_from_args(1, rb_node_encoding_val(node));
|
2022-10-01 11:44:28 +03:00
|
|
|
case NODE_ERROR:
|
2024-05-03 02:57:55 +03:00
|
|
|
return rb_ary_new_from_node_args(ast_value, 0);
|
2018-01-16 02:43:17 +03:00
|
|
|
case NODE_ARGS_AUX:
|
|
|
|
case NODE_LAST:
|
2018-06-06 09:14:21 +03:00
|
|
|
break;
|
2018-01-16 02:43:17 +03:00
|
|
|
}
|
|
|
|
|
2023-05-24 11:24:41 +03:00
|
|
|
rb_bug("node_children: unknown node: %s", ruby_node_name(type));
|
2018-01-16 02:43:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2019-11-07 12:29:20 +03:00
|
|
|
ast_node_children(rb_execution_context_t *ec, VALUE self)
|
2018-01-16 02:43:17 +03:00
|
|
|
{
|
|
|
|
struct ASTNodeData *data;
|
|
|
|
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
|
|
|
|
|
2024-05-03 02:57:55 +03:00
|
|
|
return node_children(data->ast_value, data->node);
|
2018-01-16 02:43:17 +03:00
|
|
|
}
|
|
|
|
|
2024-07-22 10:28:00 +03:00
|
|
|
static int
|
|
|
|
null_loc_p(rb_code_location_t *loc)
|
|
|
|
{
|
|
|
|
return (loc->beg_pos.lineno == 0 && loc->beg_pos.column == -1 && loc->end_pos.lineno == 0 && loc->end_pos.column == -1);
|
|
|
|
}
|
|
|
|
|
2024-07-10 16:28:22 +03:00
|
|
|
static VALUE
|
|
|
|
location_new(rb_code_location_t *loc)
|
|
|
|
{
|
|
|
|
VALUE obj;
|
|
|
|
struct ASTLocationData *data;
|
|
|
|
|
2024-07-22 10:28:00 +03:00
|
|
|
if (null_loc_p(loc)) return Qnil;
|
|
|
|
|
2024-07-10 16:28:22 +03:00
|
|
|
obj = TypedData_Make_Struct(rb_cLocation, struct ASTLocationData, &rb_location_type, data);
|
|
|
|
data->first_lineno = loc->beg_pos.lineno;
|
|
|
|
data->first_column = loc->beg_pos.column;
|
|
|
|
data->last_lineno = loc->end_pos.lineno;
|
|
|
|
data->last_column = loc->end_pos.column;
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
node_locations(VALUE ast_value, const NODE *node)
|
|
|
|
{
|
|
|
|
enum node_type type = nd_type(node);
|
|
|
|
switch (type) {
|
2024-09-03 10:12:30 +03:00
|
|
|
case NODE_ALIAS:
|
|
|
|
return rb_ary_new_from_args(2,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_ALIAS(node)->keyword_loc));
|
2024-09-05 05:07:13 +03:00
|
|
|
case NODE_AND:
|
|
|
|
return rb_ary_new_from_args(2,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_AND(node)->operator_loc));
|
2024-09-24 08:49:00 +03:00
|
|
|
case NODE_BLOCK_PASS:
|
|
|
|
return rb_ary_new_from_args(2,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_BLOCK_PASS(node)->operator_loc));
|
|
|
|
|
2024-09-10 10:41:27 +03:00
|
|
|
case NODE_BREAK:
|
|
|
|
return rb_ary_new_from_args(2,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_BREAK(node)->keyword_loc));
|
2024-09-21 18:13:16 +03:00
|
|
|
case NODE_CASE:
|
|
|
|
return rb_ary_new_from_args(3,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_CASE(node)->case_keyword_loc),
|
|
|
|
location_new(&RNODE_CASE(node)->end_keyword_loc));
|
2024-09-21 18:17:52 +03:00
|
|
|
case NODE_CASE2:
|
|
|
|
return rb_ary_new_from_args(3,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_CASE2(node)->case_keyword_loc),
|
|
|
|
location_new(&RNODE_CASE2(node)->end_keyword_loc));
|
2024-09-21 18:22:59 +03:00
|
|
|
case NODE_CASE3:
|
|
|
|
return rb_ary_new_from_args(3,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_CASE3(node)->case_keyword_loc),
|
|
|
|
location_new(&RNODE_CASE3(node)->end_keyword_loc));
|
2024-09-10 10:41:27 +03:00
|
|
|
case NODE_NEXT:
|
|
|
|
return rb_ary_new_from_args(2,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_NEXT(node)->keyword_loc));
|
2024-09-05 05:07:13 +03:00
|
|
|
case NODE_OR:
|
|
|
|
return rb_ary_new_from_args(2,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_OR(node)->operator_loc));
|
2024-09-26 20:01:08 +03:00
|
|
|
case NODE_OP_ASGN1:
|
|
|
|
return rb_ary_new_from_args(5,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_OP_ASGN1(node)->call_operator_loc),
|
|
|
|
location_new(&RNODE_OP_ASGN1(node)->opening_loc),
|
|
|
|
location_new(&RNODE_OP_ASGN1(node)->closing_loc),
|
|
|
|
location_new(&RNODE_OP_ASGN1(node)->binary_operator_loc));
|
2024-09-26 20:32:27 +03:00
|
|
|
case NODE_OP_ASGN2:
|
|
|
|
return rb_ary_new_from_args(4,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_OP_ASGN2(node)->call_operator_loc),
|
|
|
|
location_new(&RNODE_OP_ASGN2(node)->message_loc),
|
|
|
|
location_new(&RNODE_OP_ASGN2(node)->binary_operator_loc));
|
2024-09-10 10:41:27 +03:00
|
|
|
case NODE_REDO:
|
|
|
|
return rb_ary_new_from_args(2,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_REDO(node)->keyword_loc));
|
2024-09-11 10:17:15 +03:00
|
|
|
case NODE_RETURN:
|
|
|
|
return rb_ary_new_from_args(2,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_RETURN(node)->keyword_loc));
|
2024-09-24 14:05:12 +03:00
|
|
|
case NODE_SPLAT:
|
|
|
|
return rb_ary_new_from_args(2,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_SPLAT(node)->operator_loc));
|
2024-09-03 11:53:55 +03:00
|
|
|
case NODE_UNDEF:
|
|
|
|
return rb_ary_new_from_args(2,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_UNDEF(node)->keyword_loc));
|
2024-07-22 10:28:00 +03:00
|
|
|
case NODE_UNLESS:
|
|
|
|
return rb_ary_new_from_args(4,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_UNLESS(node)->keyword_loc),
|
|
|
|
location_new(&RNODE_UNLESS(node)->then_keyword_loc),
|
|
|
|
location_new(&RNODE_UNLESS(node)->end_keyword_loc));
|
2024-09-03 10:20:52 +03:00
|
|
|
case NODE_VALIAS:
|
|
|
|
return rb_ary_new_from_args(2,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_VALIAS(node)->keyword_loc));
|
2024-09-05 12:41:10 +03:00
|
|
|
case NODE_WHEN:
|
|
|
|
return rb_ary_new_from_args(3,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_WHEN(node)->keyword_loc),
|
|
|
|
location_new(&RNODE_WHEN(node)->then_keyword_loc));
|
2024-09-09 18:13:24 +03:00
|
|
|
case NODE_WHILE:
|
|
|
|
return rb_ary_new_from_args(3,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_WHILE(node)->keyword_loc),
|
|
|
|
location_new(&RNODE_WHILE(node)->closing_loc));
|
|
|
|
case NODE_UNTIL:
|
|
|
|
return rb_ary_new_from_args(3,
|
|
|
|
location_new(nd_code_loc(node)),
|
|
|
|
location_new(&RNODE_UNTIL(node)->keyword_loc),
|
|
|
|
location_new(&RNODE_UNTIL(node)->closing_loc));
|
2024-07-10 16:28:22 +03:00
|
|
|
case NODE_ARGS_AUX:
|
|
|
|
case NODE_LAST:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return rb_ary_new_from_args(1, location_new(nd_code_loc(node)));
|
|
|
|
}
|
|
|
|
|
|
|
|
rb_bug("node_locations: unknown node: %s", ruby_node_name(type));
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ast_node_locations(rb_execution_context_t *ec, VALUE self)
|
|
|
|
{
|
|
|
|
struct ASTNodeData *data;
|
|
|
|
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
|
|
|
|
|
|
|
|
return node_locations(data->ast_value, data->node);
|
|
|
|
}
|
|
|
|
|
2018-01-16 02:43:17 +03:00
|
|
|
static VALUE
|
2019-11-07 12:29:20 +03:00
|
|
|
ast_node_first_lineno(rb_execution_context_t *ec, VALUE self)
|
2018-01-16 02:43:17 +03:00
|
|
|
{
|
|
|
|
struct ASTNodeData *data;
|
|
|
|
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
|
|
|
|
|
|
|
|
return INT2NUM(nd_first_lineno(data->node));
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2019-11-07 12:29:20 +03:00
|
|
|
ast_node_first_column(rb_execution_context_t *ec, VALUE self)
|
2018-01-16 02:43:17 +03:00
|
|
|
{
|
|
|
|
struct ASTNodeData *data;
|
|
|
|
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
|
|
|
|
|
|
|
|
return INT2NUM(nd_first_column(data->node));
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2019-11-07 12:29:20 +03:00
|
|
|
ast_node_last_lineno(rb_execution_context_t *ec, VALUE self)
|
2018-01-16 02:43:17 +03:00
|
|
|
{
|
|
|
|
struct ASTNodeData *data;
|
|
|
|
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
|
|
|
|
|
|
|
|
return INT2NUM(nd_last_lineno(data->node));
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2019-11-07 12:29:20 +03:00
|
|
|
ast_node_last_column(rb_execution_context_t *ec, VALUE self)
|
2018-01-16 02:43:17 +03:00
|
|
|
{
|
|
|
|
struct ASTNodeData *data;
|
|
|
|
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
|
|
|
|
|
|
|
|
return INT2NUM(nd_last_column(data->node));
|
|
|
|
}
|
|
|
|
|
2022-09-23 16:40:02 +03:00
|
|
|
static VALUE
|
|
|
|
ast_node_all_tokens(rb_execution_context_t *ec, VALUE self)
|
|
|
|
{
|
2024-02-16 11:45:22 +03:00
|
|
|
long i;
|
2022-09-23 16:40:02 +03:00
|
|
|
struct ASTNodeData *data;
|
[Universal parser] Decouple IMEMO from rb_ast_t
This patch removes the `VALUE flags` member from the `rb_ast_t` structure making `rb_ast_t` no longer an IMEMO object.
## Background
We are trying to make the Ruby parser generated from parse.y a universal parser that can be used by other implementations such as mruby.
To achieve this, it is necessary to exclude VALUE and IMEMO from parse.y, AST, and NODE.
## Summary (file by file)
- `rubyparser.h`
- Remove the `VALUE flags` member from `rb_ast_t`
- `ruby_parser.c` and `internal/ruby_parser.h`
- Use TypedData_Make_Struct VALUE which wraps `rb_ast_t` `in ast_alloc()` so that GC can manage it
- You can retrieve `rb_ast_t` from the VALUE by `rb_ruby_ast_data_get()`
- Change the return type of `rb_parser_compile_XXXX()` functions from `rb_ast_t *` to `VALUE`
- rb_ruby_ast_new() which internally `calls ast_alloc()` is to create VALUE vast outside ruby_parser.c
- `iseq.c` and `vm_core.h`
- Amend the first parameter of `rb_iseq_new_XXXX()` functions from `rb_ast_body_t *` to `VALUE`
- This keeps the VALUE of AST on the machine stack to prevent being removed by GC
- `ast.c`
- Almost all change is replacement `rb_ast_t *ast` with `VALUE vast` (sorry for the big diff)
- Fix `node_memsize()`
- Now it includes `rb_ast_local_table_link`, `tokens` and script_lines
- `compile.c`, `load.c`, `node.c`, `parse.y`, `proc.c`, `ruby.c`, `template/prelude.c.tmpl`, `vm.c` and `vm_eval.c`
- Follow-up due to the above changes
- `imemo.{c|h}`
- If an object with `imemo_ast` appears, considers it a bug
Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
2024-04-16 12:42:42 +03:00
|
|
|
rb_ast_t *ast;
|
2024-02-16 11:45:22 +03:00
|
|
|
rb_parser_ary_t *parser_tokens;
|
|
|
|
rb_parser_ast_token_t *parser_token;
|
|
|
|
VALUE str, loc, token, all_tokens;
|
|
|
|
|
2022-09-23 16:40:02 +03:00
|
|
|
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
|
2024-05-03 02:57:55 +03:00
|
|
|
ast = rb_ruby_ast_data_get(data->ast_value);
|
2022-09-23 16:40:02 +03:00
|
|
|
|
[Universal parser] Decouple IMEMO from rb_ast_t
This patch removes the `VALUE flags` member from the `rb_ast_t` structure making `rb_ast_t` no longer an IMEMO object.
## Background
We are trying to make the Ruby parser generated from parse.y a universal parser that can be used by other implementations such as mruby.
To achieve this, it is necessary to exclude VALUE and IMEMO from parse.y, AST, and NODE.
## Summary (file by file)
- `rubyparser.h`
- Remove the `VALUE flags` member from `rb_ast_t`
- `ruby_parser.c` and `internal/ruby_parser.h`
- Use TypedData_Make_Struct VALUE which wraps `rb_ast_t` `in ast_alloc()` so that GC can manage it
- You can retrieve `rb_ast_t` from the VALUE by `rb_ruby_ast_data_get()`
- Change the return type of `rb_parser_compile_XXXX()` functions from `rb_ast_t *` to `VALUE`
- rb_ruby_ast_new() which internally `calls ast_alloc()` is to create VALUE vast outside ruby_parser.c
- `iseq.c` and `vm_core.h`
- Amend the first parameter of `rb_iseq_new_XXXX()` functions from `rb_ast_body_t *` to `VALUE`
- This keeps the VALUE of AST on the machine stack to prevent being removed by GC
- `ast.c`
- Almost all change is replacement `rb_ast_t *ast` with `VALUE vast` (sorry for the big diff)
- Fix `node_memsize()`
- Now it includes `rb_ast_local_table_link`, `tokens` and script_lines
- `compile.c`, `load.c`, `node.c`, `parse.y`, `proc.c`, `ruby.c`, `template/prelude.c.tmpl`, `vm.c` and `vm_eval.c`
- Follow-up due to the above changes
- `imemo.{c|h}`
- If an object with `imemo_ast` appears, considers it a bug
Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
2024-04-16 12:42:42 +03:00
|
|
|
parser_tokens = ast->node_buffer->tokens;
|
2024-02-16 11:45:22 +03:00
|
|
|
if (parser_tokens == NULL) {
|
|
|
|
return Qnil;
|
|
|
|
}
|
|
|
|
|
|
|
|
all_tokens = rb_ary_new2(parser_tokens->len);
|
|
|
|
for (i = 0; i < parser_tokens->len; i++) {
|
|
|
|
parser_token = parser_tokens->data[i];
|
|
|
|
str = rb_str_new(parser_token->str->ptr, parser_token->str->len);
|
|
|
|
loc = rb_ary_new_from_args(4,
|
|
|
|
INT2FIX(parser_token->loc.beg_pos.lineno),
|
|
|
|
INT2FIX(parser_token->loc.beg_pos.column),
|
|
|
|
INT2FIX(parser_token->loc.end_pos.lineno),
|
|
|
|
INT2FIX(parser_token->loc.end_pos.column)
|
|
|
|
);
|
|
|
|
token = rb_ary_new_from_args(4, INT2FIX(parser_token->id), ID2SYM(rb_intern(parser_token->type_name)), str, loc);
|
|
|
|
rb_ary_push(all_tokens, token);
|
|
|
|
}
|
Resize arrays in `rb_ary_freeze` and use it for freezing arrays
While working on a separate issue we found that in some cases
`ary_heap_realloc` was being called on frozen arrays. To fix this, this
change does the following:
1) Updates `rb_ary_freeze` to assert the type is an array, return if
already frozen, and shrink the capacity if it is not embedded, shared
or a shared root.
2) Replaces `rb_obj_freeze` with `rb_ary_freeze` when the object is
always an array.
3) In `ary_heap_realloc`, ensure the new capa is set with
`ARY_SET_CAPA`. Previously the change in capa was not set.
4) Adds an assertion to `ary_heap_realloc` that the array is not frozen.
Some of this work was originally done in
https://github.com/ruby/ruby/pull/2640, referencing this issue
https://bugs.ruby-lang.org/issues/16291. There didn't appear to be any
objections to this PR, it appears to have simply lost traction.
The original PR made changes to arrays and strings at the same time,
this PR only does arrays. Also it was old enough that rather than revive
that branch I've made a new one. I added Lourens as co-author in addtion
to Aaron who helped me with this patch.
The original PR made this change for performance reasons, and while
that's still true for this PR, the goal of this PR is to avoid
calling `ary_heap_realloc` on frozen arrays. The capacity should be
shrunk _before_ the array is frozen, not after.
Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
Co-Authored-By: methodmissing <lourens@methodmissing.com>
2024-06-18 21:52:18 +03:00
|
|
|
rb_ary_freeze(all_tokens);
|
2024-02-16 11:45:22 +03:00
|
|
|
|
|
|
|
return all_tokens;
|
2022-09-23 16:40:02 +03:00
|
|
|
}
|
|
|
|
|
2018-01-16 02:43:17 +03:00
|
|
|
static VALUE
|
2019-11-07 12:29:20 +03:00
|
|
|
ast_node_inspect(rb_execution_context_t *ec, VALUE self)
|
2018-01-16 02:43:17 +03:00
|
|
|
{
|
|
|
|
VALUE str;
|
|
|
|
VALUE cname;
|
|
|
|
struct ASTNodeData *data;
|
|
|
|
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
|
|
|
|
|
|
|
|
cname = rb_class_path(rb_obj_class(self));
|
|
|
|
str = rb_str_new2("#<");
|
|
|
|
|
|
|
|
rb_str_append(str, cname);
|
2018-12-24 04:56:21 +03:00
|
|
|
rb_str_catf(str, ":%s@%d:%d-%d:%d>",
|
|
|
|
node_type_to_str(data->node),
|
|
|
|
nd_first_lineno(data->node), nd_first_column(data->node),
|
|
|
|
nd_last_lineno(data->node), nd_last_column(data->node));
|
2018-01-16 02:43:17 +03:00
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2021-06-17 17:43:08 +03:00
|
|
|
static VALUE
|
|
|
|
ast_node_script_lines(rb_execution_context_t *ec, VALUE self)
|
|
|
|
{
|
|
|
|
struct ASTNodeData *data;
|
[Universal parser] Decouple IMEMO from rb_ast_t
This patch removes the `VALUE flags` member from the `rb_ast_t` structure making `rb_ast_t` no longer an IMEMO object.
## Background
We are trying to make the Ruby parser generated from parse.y a universal parser that can be used by other implementations such as mruby.
To achieve this, it is necessary to exclude VALUE and IMEMO from parse.y, AST, and NODE.
## Summary (file by file)
- `rubyparser.h`
- Remove the `VALUE flags` member from `rb_ast_t`
- `ruby_parser.c` and `internal/ruby_parser.h`
- Use TypedData_Make_Struct VALUE which wraps `rb_ast_t` `in ast_alloc()` so that GC can manage it
- You can retrieve `rb_ast_t` from the VALUE by `rb_ruby_ast_data_get()`
- Change the return type of `rb_parser_compile_XXXX()` functions from `rb_ast_t *` to `VALUE`
- rb_ruby_ast_new() which internally `calls ast_alloc()` is to create VALUE vast outside ruby_parser.c
- `iseq.c` and `vm_core.h`
- Amend the first parameter of `rb_iseq_new_XXXX()` functions from `rb_ast_body_t *` to `VALUE`
- This keeps the VALUE of AST on the machine stack to prevent being removed by GC
- `ast.c`
- Almost all change is replacement `rb_ast_t *ast` with `VALUE vast` (sorry for the big diff)
- Fix `node_memsize()`
- Now it includes `rb_ast_local_table_link`, `tokens` and script_lines
- `compile.c`, `load.c`, `node.c`, `parse.y`, `proc.c`, `ruby.c`, `template/prelude.c.tmpl`, `vm.c` and `vm_eval.c`
- Follow-up due to the above changes
- `imemo.{c|h}`
- If an object with `imemo_ast` appears, considers it a bug
Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
2024-04-16 12:42:42 +03:00
|
|
|
rb_ast_t *ast;
|
2021-06-17 17:43:08 +03:00
|
|
|
TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
|
2024-05-03 02:57:55 +03:00
|
|
|
ast = rb_ruby_ast_data_get(data->ast_value);
|
[Universal parser] Decouple IMEMO from rb_ast_t
This patch removes the `VALUE flags` member from the `rb_ast_t` structure making `rb_ast_t` no longer an IMEMO object.
## Background
We are trying to make the Ruby parser generated from parse.y a universal parser that can be used by other implementations such as mruby.
To achieve this, it is necessary to exclude VALUE and IMEMO from parse.y, AST, and NODE.
## Summary (file by file)
- `rubyparser.h`
- Remove the `VALUE flags` member from `rb_ast_t`
- `ruby_parser.c` and `internal/ruby_parser.h`
- Use TypedData_Make_Struct VALUE which wraps `rb_ast_t` `in ast_alloc()` so that GC can manage it
- You can retrieve `rb_ast_t` from the VALUE by `rb_ruby_ast_data_get()`
- Change the return type of `rb_parser_compile_XXXX()` functions from `rb_ast_t *` to `VALUE`
- rb_ruby_ast_new() which internally `calls ast_alloc()` is to create VALUE vast outside ruby_parser.c
- `iseq.c` and `vm_core.h`
- Amend the first parameter of `rb_iseq_new_XXXX()` functions from `rb_ast_body_t *` to `VALUE`
- This keeps the VALUE of AST on the machine stack to prevent being removed by GC
- `ast.c`
- Almost all change is replacement `rb_ast_t *ast` with `VALUE vast` (sorry for the big diff)
- Fix `node_memsize()`
- Now it includes `rb_ast_local_table_link`, `tokens` and script_lines
- `compile.c`, `load.c`, `node.c`, `parse.y`, `proc.c`, `ruby.c`, `template/prelude.c.tmpl`, `vm.c` and `vm_eval.c`
- Follow-up due to the above changes
- `imemo.{c|h}`
- If an object with `imemo_ast` appears, considers it a bug
Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org>
2024-04-16 12:42:42 +03:00
|
|
|
rb_parser_ary_t *ret = ast->body.script_lines;
|
2024-03-28 04:26:42 +03:00
|
|
|
return rb_parser_build_script_lines_from(ret);
|
2021-06-17 17:43:08 +03:00
|
|
|
}
|
|
|
|
|
2024-07-10 16:28:22 +03:00
|
|
|
static VALUE
|
|
|
|
ast_location_first_lineno(rb_execution_context_t *ec, VALUE self)
|
|
|
|
{
|
|
|
|
struct ASTLocationData *data;
|
|
|
|
TypedData_Get_Struct(self, struct ASTLocationData, &rb_location_type, data);
|
|
|
|
|
|
|
|
return INT2NUM(data->first_lineno);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ast_location_first_column(rb_execution_context_t *ec, VALUE self)
|
|
|
|
{
|
|
|
|
struct ASTLocationData *data;
|
|
|
|
TypedData_Get_Struct(self, struct ASTLocationData, &rb_location_type, data);
|
|
|
|
|
|
|
|
return INT2NUM(data->first_column);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ast_location_last_lineno(rb_execution_context_t *ec, VALUE self)
|
|
|
|
{
|
|
|
|
struct ASTLocationData *data;
|
|
|
|
TypedData_Get_Struct(self, struct ASTLocationData, &rb_location_type, data);
|
|
|
|
|
|
|
|
return INT2NUM(data->last_lineno);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ast_location_last_column(rb_execution_context_t *ec, VALUE self)
|
|
|
|
{
|
|
|
|
struct ASTLocationData *data;
|
|
|
|
TypedData_Get_Struct(self, struct ASTLocationData, &rb_location_type, data);
|
|
|
|
|
|
|
|
return INT2NUM(data->last_column);
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
ast_location_inspect(rb_execution_context_t *ec, VALUE self)
|
|
|
|
{
|
|
|
|
VALUE str;
|
|
|
|
VALUE cname;
|
|
|
|
struct ASTLocationData *data;
|
|
|
|
TypedData_Get_Struct(self, struct ASTLocationData, &rb_location_type, data);
|
|
|
|
|
|
|
|
cname = rb_class_path(rb_obj_class(self));
|
|
|
|
str = rb_str_new2("#<");
|
|
|
|
|
|
|
|
rb_str_append(str, cname);
|
|
|
|
rb_str_catf(str, ":@%d:%d-%d:%d>",
|
|
|
|
data->first_lineno, data->first_column,
|
|
|
|
data->last_lineno, data->last_column);
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2019-11-08 10:24:24 +03:00
|
|
|
#include "ast.rbinc"
|
2019-11-07 12:29:20 +03:00
|
|
|
|
2018-01-16 02:43:17 +03:00
|
|
|
void
|
|
|
|
Init_ast(void)
|
|
|
|
{
|
2018-11-09 04:37:41 +03:00
|
|
|
rb_mAST = rb_define_module_under(rb_cRubyVM, "AbstractSyntaxTree");
|
2018-01-16 02:43:17 +03:00
|
|
|
rb_cNode = rb_define_class_under(rb_mAST, "Node", rb_cObject);
|
2024-07-10 16:28:22 +03:00
|
|
|
rb_cLocation = rb_define_class_under(rb_mAST, "Location", rb_cObject);
|
2018-08-03 09:53:14 +03:00
|
|
|
rb_undef_alloc_func(rb_cNode);
|
2024-07-10 16:28:22 +03:00
|
|
|
rb_undef_alloc_func(rb_cLocation);
|
2018-01-16 02:43:17 +03:00
|
|
|
}
|