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 free_ast_value(rb_ast_t
*ast
, void *ctx
, NODE
*node
)
168 switch (nd_type(node
)) {
170 parser_string_free(ast
, RNODE_STR(node
)->string
);
173 parser_string_free(ast
, RNODE_DSTR(node
)->string
);
176 parser_string_free(ast
, RNODE_XSTR(node
)->string
);
179 parser_string_free(ast
, RNODE_DXSTR(node
)->string
);
182 parser_string_free(ast
, RNODE_SYM(node
)->string
);
186 parser_string_free(ast
, RNODE_REGX(node
)->string
);
189 parser_string_free(ast
, RNODE_DSYM(node
)->string
);
192 parser_string_free(ast
, RNODE_DREGX(node
)->string
);
195 parser_string_free(ast
, RNODE_FILE(node
)->path
);
198 xfree(RNODE_INTEGER(node
)->val
);
201 xfree(RNODE_FLOAT(node
)->val
);
204 xfree(RNODE_RATIONAL(node
)->val
);
207 xfree(RNODE_IMAGINARY(node
)->val
);
215 rb_node_buffer_free(rb_ast_t
*ast
, node_buffer_t
*nb
)
217 if (nb
&& nb
->tokens
) {
218 parser_tokens_free(ast
, nb
->tokens
);
220 iterate_node_values(ast
, &nb
->buffer_list
, free_ast_value
, NULL
);
221 node_buffer_list_free(ast
, &nb
->buffer_list
);
222 struct rb_ast_local_table_link
*local_table
= nb
->local_tables
;
223 while (local_table
) {
224 struct rb_ast_local_table_link
*next_table
= local_table
->next
;
226 local_table
= next_table
;
231 #define buf_add_offset(nbe, offset) ((char *)(nbe->buf) + (offset))
234 ast_newnode_in_bucket(rb_ast_t
*ast
, node_buffer_list_t
*nb
, size_t size
, size_t alignment
)
239 padding
= alignment
- (size_t)buf_add_offset(nb
->head
, nb
->head
->used
) % alignment
;
240 padding
= padding
== alignment
? 0 : padding
;
242 if (nb
->head
->used
+ size
+ padding
> nb
->head
->allocated
) {
243 size_t n
= nb
->head
->allocated
* 2;
244 node_buffer_elem_t
*nbe
;
245 nbe
= rb_xmalloc_mul_add(n
, sizeof(char *), offsetof(node_buffer_elem_t
, buf
));
246 init_node_buffer_elem(nbe
, n
, ruby_xmalloc
);
247 nbe
->next
= nb
->head
;
249 padding
= 0; /* malloc returns aligned address then no need to add padding */
252 ptr
= (NODE
*)buf_add_offset(nb
->head
, nb
->head
->used
+ padding
);
253 nb
->head
->used
+= (size
+ padding
);
254 nb
->head
->nodes
[nb
->head
->len
++] = ptr
;
259 rb_ast_newnode(rb_ast_t
*ast
, enum node_type type
, size_t size
, size_t alignment
)
261 node_buffer_t
*nb
= ast
->node_buffer
;
262 node_buffer_list_t
*bucket
= &nb
->buffer_list
;
263 return ast_newnode_in_bucket(ast
, bucket
, size
, alignment
);
267 rb_ast_new_local_table(rb_ast_t
*ast
, int size
)
269 size_t alloc_size
= sizeof(struct rb_ast_local_table_link
) + size
* sizeof(ID
);
270 struct rb_ast_local_table_link
*link
= ruby_xmalloc(alloc_size
);
271 link
->next
= ast
->node_buffer
->local_tables
;
272 ast
->node_buffer
->local_tables
= link
;
275 return (rb_ast_id_table_t
*) &link
->size
;
279 rb_ast_resize_latest_local_table(rb_ast_t
*ast
, int size
)
281 struct rb_ast_local_table_link
*link
= ast
->node_buffer
->local_tables
;
282 size_t alloc_size
= sizeof(struct rb_ast_local_table_link
) + size
* sizeof(ID
);
283 link
= ruby_xrealloc(link
, alloc_size
);
284 ast
->node_buffer
->local_tables
= link
;
287 return (rb_ast_id_table_t
*) &link
->size
;
291 rb_ast_delete_node(rb_ast_t
*ast
, NODE
*n
)
295 /* should we implement freelist? */
298 #ifdef UNIVERSAL_PARSER
300 rb_ast_new(const rb_parser_config_t
*config
)
302 node_buffer_t
*nb
= rb_node_buffer_new(config
);
303 rb_ast_t
*ast
= (rb_ast_t
*)config
->calloc(1, sizeof(rb_ast_t
));
304 ast
->config
= config
;
305 ast
->node_buffer
= nb
;
312 node_buffer_t
*nb
= rb_node_buffer_new();
313 rb_ast_t
*ast
= ruby_xcalloc(1, sizeof(rb_ast_t
));
314 ast
->node_buffer
= nb
;
320 iterate_buffer_elements(rb_ast_t
*ast
, node_buffer_elem_t
*nbe
, long len
, node_itr_t
*func
, void *ctx
)
323 for (cursor
= 0; cursor
< len
; cursor
++) {
324 func(ast
, ctx
, nbe
->nodes
[cursor
]);
329 iterate_node_values(rb_ast_t
*ast
, node_buffer_list_t
*nb
, node_itr_t
* func
, void *ctx
)
331 node_buffer_elem_t
*nbe
= nb
->head
;
334 iterate_buffer_elements(ast
, nbe
, nbe
->len
, func
, ctx
);
340 script_lines_free(rb_ast_t
*ast
, rb_parser_ary_t
*script_lines
)
342 if (!script_lines
) return;
343 for (long i
= 0; i
< script_lines
->len
; i
++) {
344 parser_string_free(ast
, (rb_parser_string_t
*)script_lines
->data
[i
]);
346 xfree(script_lines
->data
);
351 rb_ast_free(rb_ast_t
*ast
)
358 buffer_list_size(node_buffer_list_t
*nb
)
361 node_buffer_elem_t
*nbe
= nb
->head
;
362 while (nbe
!= nb
->last
) {
363 size
+= offsetof(node_buffer_elem_t
, buf
) + nbe
->used
;
370 rb_ast_memsize(const rb_ast_t
*ast
)
372 size_t size
= sizeof(rb_ast_t
);
373 node_buffer_t
*nb
= ast
->node_buffer
;
374 rb_parser_ary_t
*tokens
= NULL
;
375 struct rb_ast_local_table_link
*link
= NULL
;
376 rb_parser_ary_t
*script_lines
= ast
->body
.script_lines
;
381 size
+= sizeof(node_buffer_t
);
382 size
+= buffer_list_size(&nb
->buffer_list
);
383 link
= nb
->local_tables
;
388 size
+= sizeof(struct rb_ast_local_table_link
);
389 size
+= link
->size
* sizeof(ID
);
394 size
+= sizeof(rb_parser_ary_t
);
395 for (i
= 0; i
< tokens
->len
; i
++) {
396 size
+= sizeof(rb_parser_ast_token_t
);
397 rb_parser_ast_token_t
*token
= tokens
->data
[i
];
398 size
+= sizeof(rb_parser_string_t
);
399 size
+= token
->str
->len
+ 1;
404 size
+= sizeof(rb_parser_ary_t
);
405 for (i
= 0; i
< script_lines
->len
; i
++) {
406 size
+= sizeof(rb_parser_string_t
);
407 size
+= ((rb_parser_string_t
*)script_lines
->data
[i
])->len
+ 1;
415 rb_ast_dispose(rb_ast_t
*ast
)
417 if (ast
&& ast
->node_buffer
) {
418 script_lines_free(ast
, ast
->body
.script_lines
);
419 ast
->body
.script_lines
= NULL
;
420 rb_node_buffer_free(ast
, ast
->node_buffer
);
421 ast
->node_buffer
= 0;
426 rb_node_set_type(NODE
*n
, enum node_type t
)
428 return nd_init_type(n
, t
);