Files
akbasic/include/akbasic/variable.h
Andrew Kesterson 134ade9392 Document the public API in libakgl's Doxygen style
Adds a Doxyfile in the shape libakgl uses -- fifteen deliberate lines, including
WARN_IF_UNDOCUMENTED and WARN_AS_ERROR=FAIL_ON_WARNINGS -- and fills in the 70
public declarations that had no doc block, bringing include/akbasic to 114 of
114.

libakgl is the model rather than libakstdlib. Measured before starting: libakgl
documents 122 of 122 public declarations and libakstdlib 3 of 25, and
libakstdlib's Doxyfile is the unedited doxygen default, PROJECT_NAME = "My
Project" and an empty INPUT. So the house standard is libakgl's, down to the
boilerplate phrasing for the recurring parameters -- "Object to initialize,
inspect, or modify", "Output destination populated by the function", "`NULL` on
success, otherwise an error context owned by the caller".

Worth knowing what the gate actually gates. EXTRACT_ALL=YES suppresses
doxygen's undocumented-entity warnings, so the rule it enforces is that a
*partial* block is an error: document one @param and you must document them all.
Verified by deleting a @param and confirming a non-zero exit, then restoring it.
Full coverage is therefore a convention this commit adopts rather than something
the tool made me do.

Where a contract is non-obvious the block says so rather than restating the
signature: math_plus explains why it alone mutates its left operand, new_unary
notes that hanging the operand on .right is what makes the parser miscount a
negative literal argument, leaf_to_string warns that an assignment renders with
an empty operator, and stop_waiting records that a verb nobody is waiting for is
tolerated. Each cross-references its TODO.md section 6 item.

Also records in TODO.md that this repository has no CI, which libakgl and
libakstdlib both have -- so ctest, the sanitizer build, coverage and this new
doxygen gate are all run by hand today.

ctest 61/61; doxygen Doxyfile exits 0; no warnings under -Wall -Wextra.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 07:00:16 -04:00

109 lines
5.1 KiB
C

/**
* @file variable.h
* @brief Declares a named, strongly-typed, optionally multi-dimensional slot.
*
* Ported from basicvariable.go. Type comes from the identifier's last character:
* `$` string, `#` integer, `%` float. Note that `%` meaning *float* inverts the
* Commodore convention where `%` is integer; the reference does it that way and
* its README documents it, so it is kept.
*/
#ifndef _AKBASIC_VARIABLE_H_
#define _AKBASIC_VARIABLE_H_
#include <akerror.h>
#include <akbasic/types.h>
#include <akbasic/value.h>
typedef struct
{
char name[AKBASIC_MAX_STRING_LENGTH];
akbasic_Type valuetype;
akbasic_Value *values; /** Points into the runtime's value pool */
int valuecount;
int64_t dimensions[AKBASIC_MAX_ARRAY_DEPTH];
int dimensioncount;
bool mutable_;
bool used; /** Pool bookkeeping */
} akbasic_Variable;
/**
* @brief Give a variable storage and a type.
* @param obj Object to initialize, inspect, or modify.
* @param pool Backing store the elements are drawn from.
* @param sizes Dimension sizes; every one must be positive.
* @param sizecount Number of dimensions.
* @return `NULL` on success, otherwise an error context owned by the caller.
* @throws AKERR_NULLPOINTER When `obj` or `pool` is NULL.
* @throws AKBASIC_ERR_VALUE When the name is empty or a dimension is not positive.
* @throws AKBASIC_ERR_BOUNDS When the array is larger than the pool can serve.
*/
akerr_ErrorContext AKERR_NOIGNORE *akbasic_variable_init(akbasic_Variable *obj, akbasic_ValuePool *pool, int64_t *sizes, int sizecount);
/**
* @brief Mark the variable undefined and mutable without touching its storage.
* @param obj Object to initialize, inspect, or modify.
* @return `NULL` on success, otherwise an error context owned by the caller.
* @throws AKERR_NULLPOINTER When `obj` is NULL.
*/
akerr_ErrorContext AKERR_NOIGNORE *akbasic_variable_zero(akbasic_Variable *obj);
/**
* @brief Resolve a subscript list to the value it addresses.
* @param obj Object to initialize, inspect, or modify.
* @param subscripts Index per dimension.
* @param subscriptcount Number of indices supplied; must equal the dimension count.
* @param dest Output destination populated by the function.
* @return `NULL` on success, otherwise an error context owned by the caller.
* @throws AKBASIC_ERR_BOUNDS When the count is wrong or an index is out of range.
*/
akerr_ErrorContext AKERR_NOIGNORE *akbasic_variable_get_subscript(akbasic_Variable *obj, int64_t *subscripts, int subscriptcount, akbasic_Value **dest);
/**
* @brief Copy a value into the slot a subscript list addresses.
* @param obj Object to initialize, inspect, or modify.
* @param value Source value; cloned into the slot, not aliased.
* @param subscripts Index per dimension.
* @param subscriptcount Number of indices supplied; must equal the dimension count.
* @return `NULL` on success, otherwise an error context owned by the caller.
* @throws AKERR_NULLPOINTER When `value` is NULL.
* @throws AKBASIC_ERR_BOUNDS When the count is wrong or an index is out of range.
*/
akerr_ErrorContext AKERR_NOIGNORE *akbasic_variable_set_subscript(akbasic_Variable *obj, akbasic_Value *value, int64_t *subscripts, int subscriptcount);
/**
* @brief Store an integer into the slot a subscript list addresses.
* @param obj Object to initialize, inspect, or modify.
* @param value Value to store.
* @param subscripts Index per dimension.
* @param subscriptcount Number of indices supplied; must equal the dimension count.
* @return `NULL` on success, otherwise an error context owned by the caller.
* @throws AKBASIC_ERR_BOUNDS When the count is wrong or an index is out of range.
*/
akerr_ErrorContext AKERR_NOIGNORE *akbasic_variable_set_integer(akbasic_Variable *obj, int64_t value, int64_t *subscripts, int subscriptcount);
/**
* @brief Store a float into the slot a subscript list addresses.
* @param obj Object to initialize, inspect, or modify.
* @param value Value to store.
* @param subscripts Index per dimension.
* @param subscriptcount Number of indices supplied; must equal the dimension count.
* @return `NULL` on success, otherwise an error context owned by the caller.
* @throws AKBASIC_ERR_BOUNDS When the count is wrong or an index is out of range.
*/
akerr_ErrorContext AKERR_NOIGNORE *akbasic_variable_set_float(akbasic_Variable *obj, double value, int64_t *subscripts, int subscriptcount);
/**
* @brief Store a string into the slot a subscript list addresses.
* @param obj Object to initialize, inspect, or modify.
* @param value Value to store.
* @param subscripts Index per dimension.
* @param subscriptcount Number of indices supplied; must equal the dimension count.
* @return `NULL` on success, otherwise an error context owned by the caller.
* @throws AKERR_NULLPOINTER When `value` is NULL.
* @throws AKBASIC_ERR_VALUE When the string exceeds the length limit.
* @throws AKBASIC_ERR_BOUNDS When the count is wrong or an index is out of range.
*/
akerr_ErrorContext AKERR_NOIGNORE *akbasic_variable_set_string(akbasic_Variable *obj, const char *value, int64_t *subscripts, int subscriptcount);
#endif // _AKBASIC_VARIABLE_H_