-module(viva_tensor@core@error). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/viva_tensor/core/error.gleam"). -export([shape_to_string/1, to_string/1]). -export_type([tensor_error/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC( " Centralized error types for tensor operations.\n" "\n" " Philosophy: fail fast, fail loud, fail informatively.\n" "\n" " Each error variant carries enough context to debug the issue without\n" " printf-debugging. ShapeMismatch tells you both shapes. IndexOutOfBounds\n" " tells you the index AND the size. No more \"index out of bounds\" with no context.\n" "\n" " Why a single error type instead of operation-specific ones?\n" " - Simpler API (one Result type everywhere)\n" " - Easy to convert to user-facing messages\n" " - Pattern matching still works for specific handling\n" ). -type tensor_error() :: {shape_mismatch, list(integer()), list(integer())} | {invalid_shape, binary()} | {dimension_error, binary()} | {broadcast_error, list(integer()), list(integer())} | {index_out_of_bounds, integer(), integer()} | {dtype_error, binary()}. -file("src/viva_tensor/core/error.gleam", 90). ?DOC(" Pretty-print a shape like [2, 3, 4].\n"). -spec shape_to_string(list(integer())) -> binary(). shape_to_string(Shape) -> <<<<"["/utf8, (gleam@string:join( gleam@list:map(Shape, fun erlang:integer_to_binary/1), <<", "/utf8>> ))/binary>>/binary, "]"/utf8>>. -file("src/viva_tensor/core/error.gleam", 61). ?DOC(" Human-readable error message. Useful for debugging.\n"). -spec to_string(tensor_error()) -> binary(). to_string(Error) -> case Error of {shape_mismatch, Expected, Got} -> <<<<<<"Shape mismatch: expected "/utf8, (shape_to_string(Expected))/binary>>/binary, ", got "/utf8>>/binary, (shape_to_string(Got))/binary>>; {invalid_shape, Reason} -> <<"Invalid shape: "/utf8, Reason/binary>>; {dimension_error, Reason@1} -> <<"Dimension error: "/utf8, Reason@1/binary>>; {broadcast_error, A, B} -> <<<<<<"Cannot broadcast shapes "/utf8, (shape_to_string(A))/binary>>/binary, " and "/utf8>>/binary, (shape_to_string(B))/binary>>; {index_out_of_bounds, Index, Size} -> <<<<<<"Index "/utf8, (erlang:integer_to_binary(Index))/binary>>/binary, " out of bounds for size "/utf8>>/binary, (erlang:integer_to_binary(Size))/binary>>; {dtype_error, Reason@2} -> <<"Dtype error: "/utf8, Reason@2/binary>> end.