1 /**********************************************************************
3 node.c - ruby node tree
6 created at: 09/12/06 21:23:44 JST
8 Copyright (C) 2009 Yusuke Endoh
10 **********************************************************************/
12 #ifdef UNIVERSAL_PARSER
15 #include "rubyparser.h"
18 #include "internal/variable.h"
20 #define NODE_BUF_DEFAULT_SIZE (sizeof(struct RNode) * 16)
23 init_node_buffer_elem(node_buffer_elem_t
*nbe
, size_t allocated
, void *xmalloc(size_t))
25 nbe
->allocated
= allocated
;
28 nbe
->nodes
= xmalloc(allocated
/ sizeof(struct RNode
) * sizeof(struct RNode
*)); /* All node requires at least RNode */
32 init_node_buffer_list(node_buffer_list_t
*nb
, node_buffer_elem_t
*head
, void *xmalloc(size_t))
34 init_node_buffer_elem(head
, NODE_BUF_DEFAULT_SIZE
, xmalloc
);
35 nb
->head
= nb
->last
= head
;
36 nb
->head
->next
= NULL
;
39 #ifdef UNIVERSAL_PARSER
40 #define ruby_xmalloc config->malloc
43 #ifdef UNIVERSAL_PARSER
44 static node_buffer_t
*
45 rb_node_buffer_new(const rb_parser_config_t
*config
)
47 static node_buffer_t
*
48 rb_node_buffer_new(void)
51 const size_t bucket_size
= offsetof(node_buffer_elem_t
, buf
) + NODE_BUF_DEFAULT_SIZE
;
52 const size_t alloc_size
= sizeof(node_buffer_t
) + (bucket_size
);
55 offsetof(node_buffer_elem_t
, buf
) + NODE_BUF_DEFAULT_SIZE
56 > sizeof(node_buffer_t
) + sizeof(node_buffer_elem_t
));
57 node_buffer_t
*nb
= ruby_xmalloc(alloc_size
);
58 init_node_buffer_list(&nb
->buffer_list
, (node_buffer_elem_t
*)&nb
[1], ruby_xmalloc
);
64 #ifdef UNIVERSAL_PARSER
66 #define ruby_xmalloc ast->config->malloc
68 #define xfree ast->config->free
69 #define rb_xmalloc_mul_add ast->config->xmalloc_mul_add
70 #define ruby_xrealloc(var,size) (ast->config->realloc_n((void *)var, 1, size))
73 typedef void node_itr_t(rb_ast_t
*ast
, void *ctx
, NODE
*node
);
74 static void iterate_node_values(rb_ast_t
*ast
, node_buffer_list_t
*nb
, node_itr_t
* func
, void *ctx
);
77 rb_node_init(NODE
*n
, enum node_type type
)
80 nd_init_type(RNODE(n
), type
);
81 RNODE(n
)->nd_loc
.beg_pos
.lineno
= 0;
82 RNODE(n
)->nd_loc
.beg_pos
.column
= 0;
83 RNODE(n
)->nd_loc
.end_pos
.lineno
= 0;
84 RNODE(n
)->nd_loc
.end_pos
.column
= 0;
85 RNODE(n
)->node_id
= -1;
89 rb_node_name(int node
)
92 #include "node_name.inc"
98 #ifdef UNIVERSAL_PARSER
100 ruby_node_name(int node
)
102 return rb_node_name(node
);
106 ruby_node_name(int node
)
108 const char *name
= rb_node_name(node
);
110 if (!name
) rb_bug("unknown node: %d", node
);
116 node_buffer_list_free(rb_ast_t
*ast
, node_buffer_list_t
* nb
)
118 node_buffer_elem_t
*nbe
= nb
->head
;
119 while (nbe
!= nb
->last
) {
126 /* The last node_buffer_elem_t is allocated in the node_buffer_t, so we
127 * only need to free the nodes. */
131 struct rb_ast_local_table_link
{
132 struct rb_ast_local_table_link
*next
;
133 // struct rb_ast_id_table {
135 ID ids
[FLEX_ARY_LEN
];
140 parser_string_free(rb_ast_t
*ast
, rb_parser_string_t
*str
)
148 parser_ast_token_free(rb_ast_t
*ast
, rb_parser_ast_token_t
*token
)
151 parser_string_free(ast
, token
->str
);
156 parser_tokens_free(rb_ast_t
*ast
, rb_parser_ary_t
*tokens
)
158 for (long i
= 0; i
< tokens
->len
; i
++) {
159 parser_ast_token_free(ast
, tokens
->data
[i
]);
166 parser_nodes_free(rb_ast_t
*ast
, rb_parser_ary_t
*nodes
)
168 /* Do nothing for nodes because nodes are freed when rb_ast_t is freed */
174 free_ast_value(rb_ast_t
*ast
, void *ctx
, NODE
*node
)
176 switch (nd_type(node
)) {
178 parser_string_free(ast
, RNODE_STR(node
)->string
);
181 parser_string_free(ast
, RNODE_DSTR(node
)->string
);
184 parser_string_free(ast
, RNODE_XSTR(node
)->string
);
187 parser_string_free(ast
, RNODE_DXSTR(node
)->string
);
190 parser_string_free(ast
, RNODE_SYM(node
)->string
);
194 parser_string_free(ast
, RNODE_REGX(node
)->string
);
197 parser_string_free(ast
, RNODE_DSYM(node
)->string
);
200 parser_string_free(ast
, RNODE_DREGX(node
)->string
);
203 parser_string_free(ast
, RNODE_FILE(node
)->path
);
206 xfree(RNODE_INTEGER(node
)->val
);
209 xfree(RNODE_FLOAT(node
)->val
);
212 xfree(RNODE_RATIONAL(node
)->val
);
215 xfree(RNODE_IMAGINARY(node
)->val
);
218 parser_nodes_free(ast
, RNODE_UNDEF(node
)->nd_undefs
);
226 rb_node_buffer_free(rb_ast_t
*ast
, node_buffer_t
*nb
)
229 parser_tokens_free(ast
, nb
->tokens
);
231 iterate_node_values(ast
, &nb
->buffer_list
, free_ast_value
, NULL
);
232 node_buffer_list_free(ast
, &nb
->buffer_list
);
233 struct rb_ast_local_table_link
*local_table
= nb
->local_tables
;
234 while (local_table
) {
235 struct rb_ast_local_table_link
*next_table
= local_table
->next
;
237 local_table
= next_table
;
242 #define buf_add_offset(nbe, offset) ((char *)(nbe->buf) + (offset))
245 ast_newnode_in_bucket(rb_ast_t
*ast
, node_buffer_list_t
*nb
, size_t size
, size_t alignment
)
250 padding
= alignment
- (size_t)buf_add_offset(nb
->head
, nb
->head
->used
) % alignment
;
251 padding
= padding
== alignment
? 0 : padding
;
253 if (nb
->head
->used
+ size
+ padding
> nb
->head
->allocated
) {
254 size_t n
= nb
->head
->allocated
* 2;
255 node_buffer_elem_t
*nbe
;
256 nbe
= rb_xmalloc_mul_add(n
, sizeof(char *), offsetof(node_buffer_elem_t
, buf
));
257 init_node_buffer_elem(nbe
, n
, ruby_xmalloc
);
258 nbe
->next
= nb
->head
;
260 padding
= 0; /* malloc returns aligned address then no need to add padding */
263 ptr
= (NODE
*)buf_add_offset(nb
->head
, nb
->head
->used
+ padding
);
264 nb
->head
->used
+= (size
+ padding
);
265 nb
->head
->nodes
[nb
->head
->len
++] = ptr
;
270 rb_ast_newnode(rb_ast_t
*ast
, enum node_type type
, size_t size
, size_t alignment
)
272 node_buffer_t
*nb
= ast
->node_buffer
;
273 node_buffer_list_t
*bucket
= &nb
->buffer_list
;
274 return ast_newnode_in_bucket(ast
, bucket
, size
, alignment
);
278 rb_ast_new_local_table(rb_ast_t
*ast
, int size
)
280 size_t alloc_size
= sizeof(struct rb_ast_local_table_link
) + size
* sizeof(ID
);
281 struct rb_ast_local_table_link
*link
= ruby_xmalloc(alloc_size
);
282 link
->next
= ast
->node_buffer
->local_tables
;
283 ast
->node_buffer
->local_tables
= link
;
286 return (rb_ast_id_table_t
*) &link
->size
;
290 rb_ast_resize_latest_local_table(rb_ast_t
*ast
, int size
)
292 struct rb_ast_local_table_link
*link
= ast
->node_buffer
->local_tables
;
293 size_t alloc_size
= sizeof(struct rb_ast_local_table_link
) + size
* sizeof(ID
);
294 link
= ruby_xrealloc(link
, alloc_size
);
295 ast
->node_buffer
->local_tables
= link
;
298 return (rb_ast_id_table_t
*) &link
->size
;
302 rb_ast_delete_node(rb_ast_t
*ast
, NODE
*n
)
306 /* should we implement freelist? */
309 #ifdef UNIVERSAL_PARSER
311 rb_ast_new(const rb_parser_config_t
*config
)
313 node_buffer_t
*nb
= rb_node_buffer_new(config
);
314 rb_ast_t
*ast
= (rb_ast_t
*)config
->calloc(1, sizeof(rb_ast_t
));
315 ast
->config
= config
;
316 ast
->node_buffer
= nb
;
323 node_buffer_t
*nb
= rb_node_buffer_new();
324 rb_ast_t
*ast
= ruby_xcalloc(1, sizeof(rb_ast_t
));
325 ast
->node_buffer
= nb
;
331 iterate_buffer_elements(rb_ast_t
*ast
, node_buffer_elem_t
*nbe
, long len
, node_itr_t
*func
, void *ctx
)
334 for (cursor
= 0; cursor
< len
; cursor
++) {
335 func(ast
, ctx
, nbe
->nodes
[cursor
]);
340 iterate_node_values(rb_ast_t
*ast
, node_buffer_list_t
*nb
, node_itr_t
* func
, void *ctx
)
342 node_buffer_elem_t
*nbe
= nb
->head
;
345 iterate_buffer_elements(ast
, nbe
, nbe
->len
, func
, ctx
);
351 script_lines_free(rb_ast_t
*ast
, rb_parser_ary_t
*script_lines
)
353 if (!script_lines
) return;
354 for (long i
= 0; i
< script_lines
->len
; i
++) {
355 parser_string_free(ast
, (rb_parser_string_t
*)script_lines
->data
[i
]);
357 xfree(script_lines
->data
);
362 rb_ast_free(rb_ast_t
*ast
)
369 buffer_list_size(node_buffer_list_t
*nb
)
372 node_buffer_elem_t
*nbe
= nb
->head
;
373 while (nbe
!= nb
->last
) {
374 size
+= offsetof(node_buffer_elem_t
, buf
) + nbe
->used
;
381 rb_ast_memsize(const rb_ast_t
*ast
)
383 size_t size
= sizeof(rb_ast_t
);
384 node_buffer_t
*nb
= ast
->node_buffer
;
385 rb_parser_ary_t
*tokens
= NULL
;
386 struct rb_ast_local_table_link
*link
= NULL
;
387 rb_parser_ary_t
*script_lines
= ast
->body
.script_lines
;
392 size
+= sizeof(node_buffer_t
);
393 size
+= buffer_list_size(&nb
->buffer_list
);
394 link
= nb
->local_tables
;
399 size
+= sizeof(struct rb_ast_local_table_link
);
400 size
+= link
->size
* sizeof(ID
);
405 size
+= sizeof(rb_parser_ary_t
);
406 for (i
= 0; i
< tokens
->len
; i
++) {
407 size
+= sizeof(rb_parser_ast_token_t
);
408 rb_parser_ast_token_t
*token
= tokens
->data
[i
];
409 size
+= sizeof(rb_parser_string_t
);
410 size
+= token
->str
->len
+ 1;
415 size
+= sizeof(rb_parser_ary_t
);
416 for (i
= 0; i
< script_lines
->len
; i
++) {
417 size
+= sizeof(rb_parser_string_t
);
418 size
+= ((rb_parser_string_t
*)script_lines
->data
[i
])->len
+ 1;
426 rb_ast_dispose(rb_ast_t
*ast
)
428 if (ast
&& ast
->node_buffer
) {
429 script_lines_free(ast
, ast
->body
.script_lines
);
430 ast
->body
.script_lines
= NULL
;
431 rb_node_buffer_free(ast
, ast
->node_buffer
);
432 ast
->node_buffer
= 0;
437 rb_node_set_type(NODE
*n
, enum node_type t
)
439 return nd_init_type(n
, t
);
443 rb_node_get_type(const NODE
*n
)
445 return (enum node_type
)nd_type(n
);