mirror of
https://github.com/neovim/neovim.git
synced 2024-12-29 14:41:06 -07:00
Merge pull request #27541 from bfredl/exprarena
refactor(api): use an arena for nvim_parse_expression
This commit is contained in:
commit
eb1e8c12e2
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user