¿Cómo usar @src().line?

¿Cómo usar @src().line?




Uso de @src().line en Zig


Uso de @src().line en Zig

El macro @src() proporciona información de depuración en tiempo de compilación sobre el lugar exacto del código fuente donde se invoca. Entre sus campos se encuentra .line, que devuelve el número de línea (comenzando en 1) donde se encuentra el @src(). Este valor es muy útil cuando se desea incluir la ubicación de una llamada de función, de una aserción, de un error personalizado o de cualquier otra operación que requiera trazabilidad.

Conceptos básicos de @src()

  • file – ruta del fichero fuente.
  • line – número de línea donde se ejecuta el macro.
  • column – número de columna (columna de código).
  • También se puede usar @src().offset para obtener la posición absoluta del byte en el fichero.

La sintaxis se escribe siempre dentro de una expresión Zig: @src().line. Zig sustituye esto durante la compilación por un literal entero con el número de línea correspondiente.

Cómo acceder a la línea actual

A continuación se muestra un ejemplo mínimo que ilustra cómo obtener el número de línea y mostrarlo en la consola:

// main.zig
const std = @import("std");

pub fn main() void {
    // Declaramos una variable para almacenar la línea donde se invoca @src()
    const lineNum = @src().line;
    // Imprimimos el número de línea utilizando la función writeln
    std.debug.print("Estoy en la línea {d}\n", .{lineNum});
}

Comentarios línea por línea:

// main.zig
// Importamos el módulo estándar de Zig para acceder a funciones de I/O
const std = @import("std");

// Declaramos la función principal del programa (punto de entrada)
pub fn main() void {
    // @src().line devuelve el número de línea actual (en este caso 5)
    const lineNum = @src().line;
    // std.debug.print imprime un formato con un placeholder {d}
    // y sustituye por el valor de lineNum
    std.debug.print("Estoy en la línea {d}\n", .{lineNum});
}

Ejemplo práctico: registro de errores con ubicación

En proyectos reales es común generar mensajes de error que incluyan la ubicación exacta del problema. El siguiente código define una macro logError que imprime un mensaje con el fichero y la línea donde se llamó.

// logger.zig
const std = @import("std");

// Macro que recibe un mensaje y lo imprime con la ubicación de origen
fn logError(msg: []const u8, src: @SourceLocation) void {
    // Imprime el nombre del fichero y la línea donde se llamó a logError
    std.debug.print("[{s}:{d}] ERROR: {s}\n", .{ src.file, src.line, msg });
}

// Función que genera un error de ejemplo
pub fn divide(a: i32, b: i32) !i32 {
    if (b == 0) {
        // @src() captura la ubicación de esta llamada
        // Pasamos esa ubicación al logger para que incluya la línea del error
        logError("División por cero", @src());
        return error.DivisionByZero;
    }
    return a / b;
}

Desglose comentado:

// logger.zig
const std = @import("std");

// Definimos una función que recibirá el mensaje y la ubicación de origen
fn logError(msg: []const u8, src: @SourceLocation) void {
    // std.debug.print recibe una cadena con placeholders:
    // {s} para string, {d} para entero decimal.
    // La ubicación se desglosa en file y line.
    std.debug.print("[{s}:{d}] ERROR: {s}\n", .{ src.file, src.line, msg });
}

// Función que intenta dividir y lanza un error si el divisor es cero
pub fn divide(a: i32, b: i32) !i32 {
    if (b == 0) {
        // @src() devuelve la ubicación de la siguiente línea
        logError("División por cero", @src());
        return error.DivisionByZero;
    }
    return a / b;
}

Explicación paso a paso del flujo de ejecución

  • El programador llama a divide(10, 0) en algún punto del código.
  • La función divide detecta que b == 0 y ejecuta la rama if.
  • Dentro de la rama, @src() captura la línea donde se llama a logError (por ejemplo, línea 11).
  • El logError imprime: [main.zig:11] ERROR: División por cero.
  • Finalmente, divide devuelve el error DivisionByZero.

Situaciones donde @src().line es especialmente útil

Comments

No comments yet. Why don’t you start the discussion?

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *