Affix
view release on metacpan or search on metacpan
infix/src/core/signature.c view on Meta::CPAN
num_args++;
skip_whitespace(state);
if (*state->p == ',') {
state->p++;
skip_whitespace(state);
if (*state->p == ')') { // Trailing comma error.
_infix_set_parser_error(state, INFIX_CODE_UNEXPECTED_TOKEN);
return INFIX_ERROR_INVALID_ARGUMENT;
}
}
else if (*state->p != ')') {
_infix_set_parser_error(state, INFIX_CODE_UNEXPECTED_TOKEN);
return INFIX_ERROR_INVALID_ARGUMENT;
}
else
break;
}
}
}
skip_whitespace(state);
if (*state->p != ')') {
_infix_set_parser_error(state, INFIX_CODE_UNTERMINATED_AGGREGATE);
return INFIX_ERROR_INVALID_ARGUMENT;
}
state->p++;
// Parse Return Type
skip_whitespace(state);
if (state->p[0] != '-' || state->p[1] != '>') {
_infix_set_parser_error(state, INFIX_CODE_MISSING_RETURN_TYPE);
return INFIX_ERROR_INVALID_ARGUMENT;
}
state->p += 2;
*out_ret_type = parse_type(state);
if (!*out_ret_type)
return INFIX_ERROR_INVALID_ARGUMENT;
// Convert linked list of args to a flat array.
infix_function_argument * args = (num_args > 0)
? infix_arena_calloc(state->arena, num_args, sizeof(infix_function_argument), _Alignof(infix_function_argument))
: nullptr;
if (num_args > 0 && !args) {
_infix_set_error(INFIX_CATEGORY_ALLOCATION, INFIX_CODE_OUT_OF_MEMORY, (size_t)(state->p - state->start));
return INFIX_ERROR_ALLOCATION_FAILED;
}
arg_node * current = head;
for (size_t i = 0; i < num_args; i++) {
args[i] = current->arg;
current = current->next;
}
*out_args = args;
*out_num_args = num_args;
return INFIX_SUCCESS;
}
// High-Level API Implementation
/**
* @internal
* @brief The internal entry point for the signature parser (the "Parse" stage).
*
* This function takes a signature string and produces a raw, unresolved type
* graph in a new, temporary arena. It is the core parsing logic, separated from the
* higher-level functions that manage the full data pipeline. It is careful not to
* modify the global error context string (`g_infix_last_signature_context`), which
* is the responsibility of its public API callers.
*
* @param[out] out_type On success, receives the parsed type graph.
* @param[out] out_arena On success, receives the temporary arena holding the graph. The caller is responsible for
* destroying it.
* @param[in] signature The signature string to parse.
* @return `INFIX_SUCCESS` on success.
*/
c23_nodiscard infix_status _infix_parse_type_internal(infix_type ** out_type,
infix_arena_t ** out_arena,
const char * signature) {
if (!out_type || !out_arena) {
_infix_set_error(INFIX_CATEGORY_GENERAL, INFIX_CODE_NULL_POINTER, 0);
return INFIX_ERROR_INVALID_ARGUMENT;
}
if (!signature || *signature == '\0') {
_infix_set_error(INFIX_CATEGORY_PARSER, INFIX_CODE_EMPTY_SIGNATURE, 0);
return INFIX_ERROR_INVALID_ARGUMENT;
}
// The top-level public API is responsible for setting g_infix_last_signature_context.
*out_arena = infix_arena_create(4096);
if (!*out_arena) {
_infix_set_error(INFIX_CATEGORY_ALLOCATION, INFIX_CODE_OUT_OF_MEMORY, 0);
return INFIX_ERROR_ALLOCATION_FAILED;
}
parser_state state = {.p = signature, .start = signature, .arena = *out_arena, .depth = 0};
infix_type * type = parse_type(&state);
if (type) {
skip_whitespace(&state);
// After successfully parsing a type, ensure there is no trailing junk.
if (state.p[0] != '\0') {
_infix_set_parser_error(&state, INFIX_CODE_UNEXPECTED_TOKEN);
type = nullptr;
}
}
if (!type) {
// If parsing failed at any point, clean up the temporary arena.
infix_arena_destroy(*out_arena);
*out_arena = nullptr;
*out_type = nullptr;
return INFIX_ERROR_INVALID_ARGUMENT;
}
*out_type = type;
return INFIX_SUCCESS;
}
/**
* @brief Parses a signature string representing a single data type.
*
* This function orchestrates the full **"Parse -> Estimate -> Copy -> Resolve -> Layout"** pipeline
* for a single type, resulting in a fully resolved and laid-out `infix_type` object graph.
*
* @param[out] out_type On success, receives a pointer to the parsed type object.
* @param[out] out_arena On success, receives a pointer to the arena holding the type. The caller is responsible for
* freeing this with `infix_arena_destroy`.
* @param[in] signature The signature string of the data type (e.g., `"{id:int, name:*char}"`).
* @param[in] registry An optional type registry for resolving named types. Can be `nullptr`.
* @return `INFIX_SUCCESS` on success.
*/
c23_nodiscard infix_status infix_type_from_signature(infix_type ** out_type,
infix_arena_t ** out_arena,
( run in 0.984 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )