12#ifdef UNIVERSAL_PARSER
16#include "rubyparser.h"
17#include "internal/parse.h"
23#include "internal/hash.h"
24#include "internal/variable.h"
30#define NODE_BUF_DEFAULT_SIZE (sizeof(struct RNode) * 16)
33init_node_buffer_elem(node_buffer_elem_t *nbe,
size_t allocated,
void *
xmalloc(
size_t))
35 nbe->allocated = allocated;
44 init_node_buffer_elem(head, NODE_BUF_DEFAULT_SIZE,
xmalloc);
45 nb->head = nb->last = head;
46 nb->head->next = NULL;
49#ifdef UNIVERSAL_PARSER
50#define ruby_xmalloc config->malloc
51#define Qnil config->qnil
54#ifdef UNIVERSAL_PARSER
56rb_node_buffer_new(rb_parser_config_t *config)
59rb_node_buffer_new(
void)
62 const size_t bucket_size = offsetof(node_buffer_elem_t, buf) + NODE_BUF_DEFAULT_SIZE;
63 const size_t alloc_size =
sizeof(node_buffer_t) + (bucket_size * 2);
66 offsetof(node_buffer_elem_t, buf) + NODE_BUF_DEFAULT_SIZE
67 >
sizeof(node_buffer_t) + 2 *
sizeof(node_buffer_elem_t));
68 node_buffer_t *nb = ruby_xmalloc(alloc_size);
69 init_node_buffer_list(&nb->unmarkable, (node_buffer_elem_t*)&nb[1], ruby_xmalloc);
70 init_node_buffer_list(&nb->markable, (node_buffer_elem_t*)((
size_t)nb->unmarkable.head + bucket_size), ruby_xmalloc);
74#ifdef UNIVERSAL_PARSER
80#ifdef UNIVERSAL_PARSER
82#define ruby_xmalloc ast->node_buffer->config->malloc
84#define xfree ast->node_buffer->config->free
85#define rb_ident_hash_new ast->node_buffer->config->ident_hash_new
86#define rb_xmalloc_mul_add ast->node_buffer->config->xmalloc_mul_add
87#define ruby_xrealloc(var,size) (ast->node_buffer->config->realloc_n((void *)var, 1, size))
88#define rb_gc_mark ast->node_buffer->config->gc_mark
89#define rb_gc_location ast->node_buffer->config->gc_location
90#define rb_gc_mark_movable ast->node_buffer->config->gc_mark_movable
92#define Qnil ast->node_buffer->config->qnil
93#define Qtrue ast->node_buffer->config->qtrue
94#define NIL_P ast->node_buffer->config->nil_p
95#define rb_hash_aset ast->node_buffer->config->hash_aset
96#define rb_hash_delete ast->node_buffer->config->hash_delete
97#define RB_OBJ_WRITE(old, slot, young) ast->node_buffer->config->obj_write((VALUE)(old), (VALUE *)(slot), (VALUE)(young))
100typedef void node_itr_t(rb_ast_t *ast,
void *ctx, NODE *node);
101static void iterate_node_values(rb_ast_t *ast,
node_buffer_list_t *nb, node_itr_t * func,
void *ctx);
110rb_node_init(NODE *n,
enum node_type
type)
113 nd_init_type(RNODE(n),
type);
114 RNODE(n)->nd_loc.beg_pos.lineno = 0;
115 RNODE(n)->nd_loc.beg_pos.column = 0;
116 RNODE(n)->nd_loc.end_pos.lineno = 0;
117 RNODE(n)->nd_loc.end_pos.column = 0;
118 RNODE(n)->node_id = -1;
122rb_node_name(
int node)
125#include "node_name.inc"
131#ifdef UNIVERSAL_PARSER
133ruby_node_name(
int node)
135 return rb_node_name(node);
139ruby_node_name(
int node)
141 const char *name = rb_node_name(node);
143 if (!name) rb_bug(
"unknown node: %d", node);
151 node_buffer_elem_t *nbe = nb->head;
152 while (nbe != nb->last) {
168 ID ids[FLEX_ARY_LEN];
173free_ast_value(rb_ast_t *ast,
void *ctx, NODE *node)
175 switch (nd_type(node)) {
182rb_node_buffer_free(rb_ast_t *ast, node_buffer_t *nb)
184 iterate_node_values(ast, &nb->unmarkable, free_ast_value, NULL);
185 node_buffer_list_free(ast, &nb->unmarkable);
186 node_buffer_list_free(ast, &nb->markable);
188 while (local_table) {
191 local_table = next_table;
196#define buf_add_offset(nbe, offset) ((char *)(nbe->buf) + (offset))
199ast_newnode_in_bucket(rb_ast_t *ast,
node_buffer_list_t *nb,
size_t size,
size_t alignment)
204 padding = alignment - (size_t)buf_add_offset(nb->head, nb->head->used) % alignment;
205 padding = padding == alignment ? 0 : padding;
207 if (nb->head->used + size + padding > nb->head->allocated) {
208 size_t n = nb->head->allocated * 2;
209 node_buffer_elem_t *nbe;
210 nbe = rb_xmalloc_mul_add(n,
sizeof(
char *), offsetof(node_buffer_elem_t, buf));
211 init_node_buffer_elem(nbe, n, ruby_xmalloc);
212 nbe->next = nb->head;
217 ptr = (NODE *)buf_add_offset(nb->head, nb->head->used + padding);
218 nb->head->used += (size + padding);
219 nb->head->nodes[nb->head->len++] = ptr;
225nodetype_markable_p(enum node_type
type)
243rb_ast_newnode(rb_ast_t *ast,
enum node_type
type,
size_t size,
size_t alignment)
245 node_buffer_t *nb = ast->node_buffer;
247 (nodetype_markable_p(
type) ? &nb->markable : &nb->unmarkable);
248 return ast_newnode_in_bucket(ast, bucket, size, alignment);
253rb_ast_node_type_change(NODE *n,
enum node_type
type)
255 enum node_type old_type = nd_type(n);
256 if (nodetype_markable_p(old_type) != nodetype_markable_p(
type)) {
257 rb_bug(
"node type changed: %s -> %s",
258 ruby_node_name(old_type), ruby_node_name(
type));
264rb_ast_new_local_table(rb_ast_t *ast,
int size)
268 link->next = ast->node_buffer->local_tables;
269 ast->node_buffer->local_tables = link;
272 return (rb_ast_id_table_t *) &link->size;
276rb_ast_resize_latest_local_table(rb_ast_t *ast,
int size)
280 link = ruby_xrealloc(link, alloc_size);
281 ast->node_buffer->local_tables = link;
284 return (rb_ast_id_table_t *) &link->size;
288rb_ast_delete_node(rb_ast_t *ast, NODE *n)
295#ifdef UNIVERSAL_PARSER
297rb_ast_new(rb_parser_config_t *config)
299 node_buffer_t *nb = rb_node_buffer_new(config);
301 return config->ast_new((
VALUE)nb);
307 node_buffer_t *nb = rb_node_buffer_new();
308 rb_ast_t *ast = (rb_ast_t *)rb_imemo_new(imemo_ast, 0, 0, 0, (
VALUE)nb);
314iterate_buffer_elements(rb_ast_t *ast, node_buffer_elem_t *nbe,
long len, node_itr_t *func,
void *ctx)
317 for (cursor = 0; cursor <
len; cursor++) {
318 func(ast, ctx, nbe->nodes[cursor]);
323iterate_node_values(rb_ast_t *ast,
node_buffer_list_t *nb, node_itr_t * func,
void *ctx)
325 node_buffer_elem_t *nbe = nb->head;
328 iterate_buffer_elements(ast, nbe, nbe->len, func, ctx);
334mark_ast_value(rb_ast_t *ast,
void *ctx, NODE *node)
336#ifdef UNIVERSAL_PARSER
337 bug_report_func rb_bug = ast->node_buffer->config->bug;
340 switch (nd_type(node)) {
349 rb_gc_mark_movable(RNODE_LIT(node)->nd_lit);
352 rb_bug(
"unreachable node %s", ruby_node_name(nd_type(node)));
357update_ast_value(rb_ast_t *ast,
void *ctx, NODE *node)
359#ifdef UNIVERSAL_PARSER
360 bug_report_func rb_bug = ast->node_buffer->config->bug;
363 switch (nd_type(node)) {
372 RNODE_LIT(node)->nd_lit = rb_gc_location(RNODE_LIT(node)->nd_lit);
375 rb_bug(
"unreachable");
380rb_ast_update_references(rb_ast_t *ast)
382 if (ast->node_buffer) {
383 node_buffer_t *nb = ast->node_buffer;
385 iterate_node_values(ast, &nb->markable, update_ast_value, NULL);
390rb_ast_mark(rb_ast_t *ast)
392 if (ast->node_buffer) {
393 rb_gc_mark(ast->node_buffer->mark_hash);
394 rb_gc_mark(ast->node_buffer->tokens);
395 node_buffer_t *nb = ast->node_buffer;
396 iterate_node_values(ast, &nb->markable, mark_ast_value, NULL);
397 if (ast->body.script_lines) rb_gc_mark(ast->body.script_lines);
402rb_ast_free(rb_ast_t *ast)
404 if (ast->node_buffer) {
405#ifdef UNIVERSAL_PARSER
406 rb_parser_config_t *config = ast->node_buffer->config;
409 rb_node_buffer_free(ast, ast->node_buffer);
410 ast->node_buffer = 0;
411#ifdef UNIVERSAL_PARSER
413 if (config->counter <= 0) {
414 rb_ruby_parser_config_free(config);
424 node_buffer_elem_t *nbe = nb->head;
425 while (nbe != nb->last) {
426 size += offsetof(node_buffer_elem_t, buf) + nbe->used;
433rb_ast_memsize(
const rb_ast_t *ast)
436 node_buffer_t *nb = ast->node_buffer;
439 size +=
sizeof(node_buffer_t);
440 size += buffer_list_size(&nb->unmarkable);
441 size += buffer_list_size(&nb->markable);
447rb_ast_dispose(rb_ast_t *ast)
453rb_ast_add_mark_object(rb_ast_t *ast,
VALUE obj)
455 if (
NIL_P(ast->node_buffer->mark_hash)) {
456 RB_OBJ_WRITE(ast, &ast->node_buffer->mark_hash, rb_ident_hash_new());
458 rb_hash_aset(ast->node_buffer->mark_hash, obj,
Qtrue);
462rb_ast_delete_mark_object(rb_ast_t *ast,
VALUE obj)
464 if (
NIL_P(ast->node_buffer->mark_hash))
return;
465 rb_hash_delete(ast->node_buffer->mark_hash, obj);
469rb_ast_tokens(rb_ast_t *ast)
471 return ast->node_buffer->tokens;
475rb_ast_set_tokens(rb_ast_t *ast,
VALUE tokens)
481rb_node_set_type(NODE *n,
enum node_type t)
484 rb_ast_node_type_change(n, t);
486 return nd_init_type(n, t);
#define xfree
Old name of ruby_xfree.
#define T_NODE
Old name of RUBY_T_NODE.
#define xmalloc
Old name of ruby_xmalloc.
#define Qtrue
Old name of RUBY_Qtrue.
#define Qnil
Old name of RUBY_Qnil.
#define NIL_P
Old name of RB_NIL_P.
#define RB_OBJ_WRITE(old, slot, young)
Declaration of a "back" pointer.
int len
Length of the buffer.
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define RBIMPL_ATTR_PURE()
Wraps (or simulates) __attribute__((pure))
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
uintptr_t VALUE
Type that represents a Ruby object.