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 )