From acd9b54f08453bdaa324e95232e166545c04160f Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 19 Feb 2024 14:54:20 +0100 Subject: [PATCH] refactor(api): use an arena for nvim_parse_expression --- src/nvim/api/vimscript.c | 237 ++++++++++----------------------------- 1 file changed, 60 insertions(+), 177 deletions(-) diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c index 949356acc6..db32eac3d1 100644 --- a/src/nvim/api/vimscript.c +++ b/src/nvim/api/vimscript.c @@ -429,7 +429,8 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack; /// - "svalue": String, value for "SingleQuotedString" and /// "DoubleQuotedString" nodes. /// @param[out] err Error details, if any -Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, Error *err) +Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, Arena *arena, + Error *err) FUNC_API_SINCE(4) FUNC_API_FAST { int pflags = 0; @@ -471,82 +472,40 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E + (size_t)(east.err.msg != NULL) // "error" + (size_t)highlight // "highlight" + 0); - Dictionary ret = { - .items = xmalloc(ret_size * sizeof(ret.items[0])), - .size = 0, - .capacity = ret_size, - }; - ret.items[ret.size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ast"), - .value = NIL, - }; - ret.items[ret.size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("len"), - .value = INTEGER_OBJ((Integer)(pstate.pos.line == 1 - ? parser_lines[0].size - : pstate.pos.col)), - }; + + Dictionary ret = arena_dict(arena, ret_size); + PUT_C(ret, "len", INTEGER_OBJ((Integer)(pstate.pos.line == 1 + ? parser_lines[0].size + : pstate.pos.col))); if (east.err.msg != NULL) { - Dictionary err_dict = { - .items = xmalloc(2 * sizeof(err_dict.items[0])), - .size = 2, - .capacity = 2, - }; - err_dict.items[0] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("message"), - .value = CSTR_TO_OBJ(east.err.msg), - }; - if (east.err.arg == NULL) { - err_dict.items[1] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("arg"), - .value = STRING_OBJ(STRING_INIT), - }; - } else { - err_dict.items[1] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("arg"), - .value = STRING_OBJ(((String) { - .data = xmemdupz(east.err.arg, (size_t)east.err.arg_len), - .size = (size_t)east.err.arg_len, - })), - }; - } - ret.items[ret.size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("error"), - .value = DICTIONARY_OBJ(err_dict), - }; + Dictionary err_dict = arena_dict(arena, 2); + PUT_C(err_dict, "message", CSTR_TO_ARENA_OBJ(arena, east.err.msg)); + PUT_C(err_dict, "arg", CBUF_TO_ARENA_OBJ(arena, east.err.arg, (size_t)east.err.arg_len)); + PUT_C(ret, "error", DICTIONARY_OBJ(err_dict)); } if (highlight) { - Array hl = (Array) { - .items = xmalloc(kv_size(colors) * sizeof(hl.items[0])), - .capacity = kv_size(colors), - .size = kv_size(colors), - }; + Array hl = arena_array(arena, kv_size(colors)); for (size_t i = 0; i < kv_size(colors); i++) { const ParserHighlightChunk chunk = kv_A(colors, i); - Array chunk_arr = (Array) { - .items = xmalloc(4 * sizeof(chunk_arr.items[0])), - .capacity = 4, - .size = 4, - }; - chunk_arr.items[0] = INTEGER_OBJ((Integer)chunk.start.line); - chunk_arr.items[1] = INTEGER_OBJ((Integer)chunk.start.col); - chunk_arr.items[2] = INTEGER_OBJ((Integer)chunk.end_col); - chunk_arr.items[3] = CSTR_TO_OBJ(chunk.group); - hl.items[i] = ARRAY_OBJ(chunk_arr); + Array chunk_arr = arena_array(arena, 4); + ADD_C(chunk_arr, INTEGER_OBJ((Integer)chunk.start.line)); + ADD_C(chunk_arr, INTEGER_OBJ((Integer)chunk.start.col)); + ADD_C(chunk_arr, INTEGER_OBJ((Integer)chunk.end_col)); + ADD_C(chunk_arr, CSTR_AS_OBJ(chunk.group)); + + ADD_C(hl, ARRAY_OBJ(chunk_arr)); } - ret.items[ret.size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("highlight"), - .value = ARRAY_OBJ(hl), - }; + PUT_C(ret, "highlight", ARRAY_OBJ(hl)); } kvi_destroy(colors); // Walk over the AST, freeing nodes in process. ExprASTConvStack ast_conv_stack; kvi_init(ast_conv_stack); + Object ast = NIL; kvi_push(ast_conv_stack, ((ExprASTConvStackItem) { .node_p = &east.root, - .ret_node_p = &ret.items[0].value, + .ret_node_p = &ast, })); while (kv_size(ast_conv_stack)) { ExprASTConvStackItem cur_item = kv_last(ast_conv_stack); @@ -573,28 +532,17 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E || node->type == kExprNodeSingleQuotedString) // "svalue" + (node->type == kExprNodeAssignment) // "augmentation" + 0); - Dictionary ret_node = { - .items = xmalloc(items_size * sizeof(ret_node.items[0])), - .capacity = items_size, - .size = 0, - }; + Dictionary ret_node = arena_dict(arena, items_size); *cur_item.ret_node_p = DICTIONARY_OBJ(ret_node); } Dictionary *ret_node = &cur_item.ret_node_p->data.dictionary; if (node->children != NULL) { const size_t num_children = 1 + (node->children->next != NULL); - Array children_array = { - .items = xmalloc(num_children * sizeof(children_array.items[0])), - .capacity = num_children, - .size = num_children, - }; + Array children_array = arena_array(arena, num_children); for (size_t i = 0; i < num_children; i++) { - children_array.items[i] = NIL; + ADD_C(children_array, NIL); } - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("children"), - .value = ARRAY_OBJ(children_array), - }; + PUT_C(*ret_node, "children", ARRAY_OBJ(children_array)); kvi_push(ast_conv_stack, ((ExprASTConvStackItem) { .node_p = &node->children, .ret_node_p = &children_array.items[0], @@ -606,126 +554,60 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E })); } else { kv_drop(ast_conv_stack, 1); - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("type"), - .value = CSTR_TO_OBJ(east_node_type_tab[node->type]), - }; - Array start_array = { - .items = xmalloc(2 * sizeof(start_array.items[0])), - .capacity = 2, - .size = 2, - }; - start_array.items[0] = INTEGER_OBJ((Integer)node->start.line); - start_array.items[1] = INTEGER_OBJ((Integer)node->start.col); - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("start"), - .value = ARRAY_OBJ(start_array), - }; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("len"), - .value = INTEGER_OBJ((Integer)node->len), - }; + PUT_C(*ret_node, "type", CSTR_AS_OBJ(east_node_type_tab[node->type])); + Array start_array = arena_array(arena, 2); + ADD_C(start_array, INTEGER_OBJ((Integer)node->start.line)); + ADD_C(start_array, INTEGER_OBJ((Integer)node->start.col)); + PUT_C(*ret_node, "start", ARRAY_OBJ(start_array)); + + PUT_C(*ret_node, "len", INTEGER_OBJ((Integer)node->len)); switch (node->type) { case kExprNodeDoubleQuotedString: - case kExprNodeSingleQuotedString: - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("svalue"), - .value = STRING_OBJ(((String) { - .data = node->data.str.value, - .size = node->data.str.size, - })), - }; + case kExprNodeSingleQuotedString: { + Object str = CBUF_TO_ARENA_OBJ(arena, node->data.str.value, node->data.str.size); + PUT_C(*ret_node, "svalue", str); + xfree(node->data.str.value); break; + } case kExprNodeOption: - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("scope"), - .value = INTEGER_OBJ(node->data.opt.scope), - }; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ident"), - .value = STRING_OBJ(((String) { - .data = xmemdupz(node->data.opt.ident, - node->data.opt.ident_len), - .size = node->data.opt.ident_len, - })), - }; + PUT_C(*ret_node, "scope", INTEGER_OBJ(node->data.opt.scope)); + PUT_C(*ret_node, "ident", CBUF_TO_ARENA_OBJ(arena, node->data.opt.ident, + node->data.opt.ident_len)); break; case kExprNodePlainIdentifier: - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("scope"), - .value = INTEGER_OBJ(node->data.var.scope), - }; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ident"), - .value = STRING_OBJ(((String) { - .data = xmemdupz(node->data.var.ident, - node->data.var.ident_len), - .size = node->data.var.ident_len, - })), - }; + PUT_C(*ret_node, "scope", INTEGER_OBJ(node->data.var.scope)); + PUT_C(*ret_node, "ident", CBUF_TO_ARENA_OBJ(arena, node->data.var.ident, + node->data.var.ident_len)); break; case kExprNodePlainKey: - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ident"), - .value = STRING_OBJ(((String) { - .data = xmemdupz(node->data.var.ident, - node->data.var.ident_len), - .size = node->data.var.ident_len, - })), - }; + PUT_C(*ret_node, "ident", CBUF_TO_ARENA_OBJ(arena, node->data.var.ident, + node->data.var.ident_len)); break; case kExprNodeEnvironment: - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ident"), - .value = STRING_OBJ(((String) { - .data = xmemdupz(node->data.env.ident, - node->data.env.ident_len), - .size = node->data.env.ident_len, - })), - }; + PUT_C(*ret_node, "ident", CBUF_TO_ARENA_OBJ(arena, node->data.env.ident, + node->data.env.ident_len)); break; case kExprNodeRegister: - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("name"), - .value = INTEGER_OBJ(node->data.reg.name), - }; + PUT_C(*ret_node, "name", INTEGER_OBJ(node->data.reg.name)); break; case kExprNodeComparison: - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("cmp_type"), - .value = CSTR_TO_OBJ(eltkn_cmp_type_tab[node->data.cmp.type]), - }; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ccs_strategy"), - .value = CSTR_TO_OBJ(ccs_tab[node->data.cmp.ccs]), - }; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("invert"), - .value = BOOLEAN_OBJ(node->data.cmp.inv), - }; + PUT_C(*ret_node, "cmp_type", CSTR_AS_OBJ(eltkn_cmp_type_tab[node->data.cmp.type])); + PUT_C(*ret_node, "ccs_strategy", CSTR_AS_OBJ(ccs_tab[node->data.cmp.ccs])); + PUT_C(*ret_node, "invert", BOOLEAN_OBJ(node->data.cmp.inv)); break; case kExprNodeFloat: - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("fvalue"), - .value = FLOAT_OBJ(node->data.flt.value), - }; + PUT_C(*ret_node, "fvalue", FLOAT_OBJ(node->data.flt.value)); break; case kExprNodeInteger: - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("ivalue"), - .value = INTEGER_OBJ((Integer)(node->data.num.value > API_INTEGER_MAX - ? API_INTEGER_MAX - : (Integer)node->data.num.value)), - }; + PUT_C(*ret_node, "ivalue", INTEGER_OBJ((Integer)(node->data.num.value > API_INTEGER_MAX + ? API_INTEGER_MAX + : (Integer)node->data.num.value))); break; case kExprNodeAssignment: { const ExprAssignmentType asgn_type = node->data.ass.type; - ret_node->items[ret_node->size++] = (KeyValuePair) { - .key = STATIC_CSTR_TO_STRING("augmentation"), - .value = STRING_OBJ(asgn_type == kExprAsgnPlain - ? (String)STRING_INIT - : cstr_to_string(expr_asgn_type_tab[asgn_type])), - }; + String str = (asgn_type == kExprAsgnPlain + ? (String)STRING_INIT : cstr_as_string(expr_asgn_type_tab[asgn_type])); + PUT_C(*ret_node, "augmentation", STRING_OBJ(str)); break; } case kExprNodeMissing: @@ -766,6 +648,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E } } kvi_destroy(ast_conv_stack); + PUT_C(ret, "ast", ast); assert(ret.size == ret.capacity); // Should be a no-op actually, leaving it in case non-nodes will need to be