Documentar Odin¶
El dominio Odin da destinos con nombre a paquetes, procedimientos, tipos y miembros. Guidedog también genera páginas API analizando Odin, sin ejecutar el compilador ni el paquete. Las firmas generadas aún necesitan un contrato útil.
Describir objetos¶
Un paquete establece el contexto de lo que sigue, como un módulo Python:
.. odin:package:: core:strings
:synopsis: Procedures to manipulate UTF-8 encoded strings.
:imports: rt=base:runtime
.. odin:procedure:: @(require_results) clone :: proc(s: string, allocator := context.allocator) -> (res: string, err: rt.Allocator_Error) #optional_allocator_error
Clones a string.
:param s: The string to be cloned.
:result res: The cloned string.
:result err: An allocator error, or ``nil``.
.. odin:struct:: Builder :: struct
A dynamic byte buffer.
.. odin:field:: buf: [dynamic]byte
Las firmas se escriben en una línea como las declaraciones Odin y se muestran igual. Los ejemplos siguientes se ven así:
- shapes.Kind :: enum u8
-
- Circle = 1
- @(require_results) shapes.area :: proc(side: f32, scale: f32 = 1) -> (a: f32, ok: bool) #optional_ok
-
Mide un cuadrado.
- Parámetros:
side – Su lado.
- Devuelve:
a – Su área.
ok – Si se conoce su tipo.
Directivas y firmas que aceptan:
odin:packageyodin:currentpackage-
Acepta
core:fmto una ruta bajo las raíces, comoreaders/sphinx. Los objetos usan la ruta importada:core:fmt.println.odin:currentpackagecambia el contexto sin destino;Nonelo limpia. Opciones::synopsis:,:platform:,:deprecated:,:no-index:y:imports:, que declara alias como paresalias=package(gd=core rst=readers/rst), enlazandogd.Node_Idconcore.Node_Id.:private:enumera tipos y miembros privados de grupos (State Rules catalog_text), mostrados como texto al no tener descripción enlazable. Las páginas generadas los enumeran automáticamente. odin:procedure(oodin:proc)-
name :: proc(params) -> resultsadmite atributos previos (@(require_results)),#force_inlineantes deproc, convención (proc "c" (...)), valores por defecto (x := 1,x: int = 1), parámetros polimórficos$T, variádicos..,using,#c_vararg, resultados con nombre, etiquetas (#optional_ok) ywhere.name(params) -> resultses la abreviatura. odin:procgroup-
name :: proc{a, b}: cada miembro enlaza a su procedimiento. odin:struct,odin:union,odin:enum,odin:bitset,odin:bitfield,odin:type-
Name :: struct($T: typeid) #packed,Name :: union #no_nil {A, B},Name :: enum u8,Name :: bit_set[Flag; u8],Name :: bit_field u32;odin:typeadmite tipos distintos y alias (Handle :: distinct uintptr,Callback :: proc(x: int) -> bool). El contenido del tipo incluye sus miembros. odin:fieldyodin:enumerator-
Dentro de un tipo:
name: Typecon etiqueta (name: string `json:"n"`) o tamaño en bits (low: u8 | 3), yNameoName = 3. Sus nombres sonType.member. odin:const,odin:var,odin:foreign-
NAME :: 64oNAME : int : 64;name: Type,name := valueoname: Type = value;libc "system:c"para una importación externa.
Todos aceptan :no-index:, :no-index-entry:, :no-contents-entry: y :no-typesetting: de Sphinx. Añaden :package: (otro paquete), :private: y :deprecated: message (muestran @(private) y @(deprecated="message") si faltan en la firma), :availability: Windows, Linux (primera línea con plataformas) y :foreign: libc (procedimiento externo). Varias firmas describen el mismo objeto para distintos destinos; solo la primera recibe identificador y entrada de índice.
Los nombres de tipos se buscan primero en el paquete y tipo de la firma y luego tal como están escritos. Tipos integrados (int, string, rawptr, typeid, any…), palabras clave, nombres polimórficos ($T y posteriores T, incluidos los del tipo contenedor), longitudes, valores predeterminados, constantes, etiquetas y where se muestran sin enlaces.
Roles e identificadores¶
Enlazan :odin:pkg:, :odin:proc:, :odin:type: (estructuras, uniones, enumeraciones, conjuntos y campos de bits, etc.), :odin:const:, :odin:var:, :odin:field:, :odin:enumerator: y :odin:obj: (cualquiera). Como en Python, ~ muestra el final (:odin:proc:`~core:fmt.println` muestra println) y . inicial busca sufijos. Se consulta tipo y paquete del contexto, el nombre literal y el tramo tras : o /: fmt.println encuentra core:fmt.println y sphinx.Config encuentra readers/sphinx.Config, como Odin. Los alias de :imports: tienen prioridad. Con default-domain:: odin o primary_domain = "odin" se omite odin:.
El ID aplica make_id de Sphinx a odin- y el nombre completo: odin-core-fmt.println, odin-readers-sphinx.Config.docname. Conserva mayúsculas y puntos; : y / pasan a guiones. Son legibles, estables y distinguen paquetes con igual nombre final. Un paquete usa odin-package- y su ruta. El índice muestra «println (procedure in core:fmt)». objects.inv enumera todo con dominio odin y tipo (odin:procedure, odin:struct, odin:field…), paquetes primero, como los módulos de Sphinx.
Los campos se agrupan como en otros dominios: :param name: (con :type name:), :result name: para resultados con nombre, :returns: y :rtype:.
Generar desde el código fuente¶
Indica dónde están los paquetes, respecto a las fuentes:
odin_autoapi_dirs = ["../src"]
odin_collections = {core = "/usr/local/lib/odin/core"} # optional
Bajo odin_autoapi_dirs, el nombre es la ruta relativa (src/shapes/round es shapes/round); en una colección es el importado por Odin (core:strings). Las directivas funcionan como autodoc:
.. odin:autopackage:: shapes
:members:
:undoc-members:
:member-order: groupwise
.. odin:autoproc:: shapes.area
.. odin:autotype:: Shape
odin:autopackage escribe el paquete, su comentario y, con :members:, todas las declaraciones o las indicadas. odin:autoproc, odin:autoprocgroup, odin:autotype, odin:autoconst y odin:autovar escriben una declaración del contexto o package.name. Opciones: :members:, :undoc-members:, :private-members: (@(private), omitidas normalmente), :exclude-members:, :member-order: (source por archivo y posición, predeterminado; alphabetical; groupwise con «Types», «Procedures», «Procedure groups», «Constants», «Variables», «Foreign imports») y :no-index:.
Los comentarios son líneas // o un bloque /* */ justo encima de una declaración, o al final de un campo o enumerador. Su texto plano se convierte a reStructuredText así:
- Los párrafos siguen siendo párrafos; las líneas
- itemsiguen siendo listas. - Un bloque indentado tras una línea vacía o acabada en dos puntos (
Example:) se convierte encode-block:: odin, otexttrasOutput:. Una línea más indentada que el texto inmediatamente posterior a una línea de párrafo lo continúa. Inputs:con elementos- name: textproduce campos:param name:;Returns:produce:result name:o:returns:sin nombre, según el estilo de la biblioteca principal de Odin.- Una línea que empieza por
NOTE:oWARNING:se convierte en nota o advertencia. `code`es texto literal. Los demás caracteres de marcado (*,|,_al final de palabra, etc.) se escapan para mostrar el comentario tal como se escribió y sin advertencias.
Páginas de la API¶
Con odin_autoapi_dirs, cada paquete obtiene una página al leerse, como sphinx-autoapi. api/shapes contiene odin:autopackage:: shapes con odin_autoapi_options; api/index lista paquetes y sinopsis. Son documentos del proyecto en toctree, búsqueda, índice, singlehtml y PDF, pero nunca se escriben en las fuentes. Opciones:
odin_autoapi_dirs-
Carpetas de paquetes que obtendrán páginas, relativas a las fuentes. Solo se leen archivos bajo ellas y
odin_collections; se rechazan enlaces hacia fuera. odin_collections-
Tabla de nombres de colecciones y carpetas, para argumentos como
core:strings. Estos paquetes no obtienen páginas. odin_autoapi_root-
Carpeta de las páginas,
"api"por defecto. Un documento fuente con el mismo nombre lo conserva y se emite una advertencia. odin_autoapi_options-
Por defecto
["members", "undoc-members"]; puede añadirseprivate-members. odin_autoapi_member_order-
"source"(predeterminado),"alphabetical"o"groupwise". odin_autoapi_add_toctree_entry-
true(predeterminado):api/indexse añade al primer toctree del documento raíz. odin_autoapi_generate_api_docs-
true(predeterminado);falselee las carpetas solo para las directivas.
No se enlazan tipos de paquetes no documentados (core:io.Writer). Con -n, siléncialos mediante nitpick_ignore_regex = [["odin:type", "(core|base):.*"]]. Así se construye docs/api de Guidedog.
Plataformas¶
Se documentan los destinos según las reglas de Odin: *_windows.odin, *_linux_arm64.odin y *_amd64.odin solo corresponden a esos destinos; #+build linux, darwin y #+build !windows (también //+build antiguo) restringen más. Un when ODIN_OS == .Windows de archivo se divide por destino, incluido else, si solo compara ODIN_OS y ODIN_ARCH. Se omiten *_test.odin y #+ignore. Las declaraciones comunes aparecen una vez; las parciales indican «Availability: Windows». Cada firma distinta aparece con sus destinos, solo la primera con ID. Un paquete limitado indica :platform:.
Reconstrucción¶
Cada archivo Odin leído es una dependencia de su página. Tras editarlo, solo se releen las páginas de ese paquete. El índice se relee al añadir o quitar un paquete o cambiar su sinopsis. guidedog serve comprueba las fechas de odin_autoapi_dirs y odin_collections antes de servir HTML. Actualiza el navegador tras editar.
Limitaciones¶
- Solo se analiza, sin compilar ni comprobar tipos: tipos y constantes se muestran tal como están, omitiendo valores de más de 100 caracteres, sin inferencia.
A :: Bse clasifica por nombres: uno que empiece en mayúscula sin ser todo mayúsculas, o un tipo integrado, se considera tipo. - Las condiciones
whendistintas de comparaciones deODIN_OSyODIN_ARCHno se evalúan: se documentan ambas ramas. - Los tipos privados se muestran como texto, pues no tienen entrada sin
:private-members:. El paquete generado los enumera en:private:, así que-nno los denuncia. core:odin/parserrechaza un procedimiento que combine#optional_okywhere. Se informa del archivo y se documenta lo que pudo leerse.- El parser Odin consume mucha pila al anidar: cientos de paréntesis pueden desbordar un hilo. Se omiten archivos muy por encima del código real (unos 50 niveles de paréntesis o tipos, o mil
elseencadenados), conodin.autodoc.nesting; se documenta el resto.whenevalúa hasta 64 niveles de&&,||y!; más se considera no evaluado.