3 Commits

Author SHA1 Message Date
809a9bf64d Fix Doxygen gate failures on main
Some checks failed
akbasic CI Build / cmake_build (push) Failing after 3m41s
akbasic CI Build / sanitizers (push) Failing after 5m59s
akbasic CI Build / coverage (push) Failing after 4m38s
akbasic CI Build / akgl_build (push) Failing after 8m20s
akbasic CI Build / mutation_test (push) Failing after 3m56s
Four independent defects that made 'doxygen Doxyfile' exit 1:

- runtime.h: a stacked doc block above akbasic_runtime_new_function
  was left directly above akbasic_runtime_call_function's declaration
  with no function in between, so Doxygen glommed both blocks onto
  call_function and duplicated the @param obj/@param dest entries.
  Moved the block back to sit directly above new_function.
- sprite.h/akgl.h/sprite_akgl.c: three #AKGL_*/#AKBASIC_SHAPE_* Doxygen
  autolinks pointed at libakgl symbols outside this Doxyfile's INPUT,
  so they could never resolve. Converted them to plain code spans.
- scanner.c: peek(), peek_next() and match_next_char() were each
  missing @param obj (and match_next_char also cm/truetype/falsetype).
  Filled in the missing entries.
- Doxyfile: the error.h include graph hit DOT_GRAPH_MAX_NODES at
  exactly the default of 50. Raised it to 100.

Verified 'doxygen Doxyfile' now exits 0 with graphviz installed.

Refs #56

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-05 23:48:07 -04:00
ae2c702c2b Merge pull request 'Add native RND and ASC functions' (#45) from 16 into main
Some checks failed
akbasic CI Build / cmake_build (push) Failing after 3m29s
akbasic CI Build / sanitizers (push) Failing after 4m43s
akbasic CI Build / coverage (push) Failing after 3m53s
akbasic CI Build / mutation_test (push) Failing after 3m38s
akbasic CI Build / akgl_build (push) Failing after 8m57s
Reviewed-on: #45
Reviewed-by: andrew <andrew@aklabs.net>
2026-08-05 21:24:35 -04:00
5c58f4c16d Add native RND and ASC functions
Some checks failed
akbasic CI Build / cmake_build (push) Failing after 3m41s
akbasic CI Build / coverage (push) Failing after 3m54s
akbasic CI Build / sanitizers (push) Failing after 4m52s
akbasic CI Build / mutation_test (push) Failing after 3m47s
akbasic CI Build / akgl_build (push) Failing after 8m41s
Implement bounded random integers with lazy clock seeding and add ASC as the inverse of CHR. Cover dispatch, validation, deterministic LCG output, UTF-8 round trips, function reference, and the breakout tutorial.

Closes #16.

Co-authored-by: andrew <andrew@aklabs.net>
2026-08-05 21:17:47 -04:00
6 changed files with 18 additions and 11 deletions

View File

@@ -12,3 +12,4 @@ WARN_AS_ERROR = FAIL_ON_WARNINGS
GENERATE_HTML = YES GENERATE_HTML = YES
GENERATE_LATEX = NO GENERATE_LATEX = NO
QUIET = YES QUIET = YES
DOT_GRAPH_MAX_NODES = 100

View File

@@ -296,7 +296,7 @@ typedef struct
* *
* Claimed up front rather than per scan for two reasons. The pool is shared * Claimed up front rather than per scan for two reasons. The pool is shared
* with whatever host this interpreter is embedded in -- a game with its own * with whatever host this interpreter is embedded in -- a game with its own
* shaped actors draws from the same #AKGL_MAX_HEAP_COLLISION_PROXY -- so * shaped actors draws from the same `AKGL_MAX_HEAP_COLLISION_PROXY` -- so
* running out is a real possibility, and it should be an init-time failure * running out is a real possibility, and it should be an init-time failure
* naming the pool rather than a collision scan that starts refusing halfway * naming the pool rather than a collision scan that starts refusing halfway
* through a game. And a proxy carries a *copy* of its shape, so there is * through a game. And a proxy carries a *copy* of its shape, so there is

View File

@@ -832,13 +832,6 @@ akerr_ErrorContext AKERR_NOIGNORE *akbasic_runtime_reserve_globals(akbasic_Runti
* @throws AKBASIC_ERR_BOUNDS When every variable slot is in use. * @throws AKBASIC_ERR_BOUNDS When every variable slot is in use.
*/ */
akerr_ErrorContext AKERR_NOIGNORE *akbasic_runtime_new_variable(akbasic_Runtime *obj, akbasic_Variable **dest); akerr_ErrorContext AKERR_NOIGNORE *akbasic_runtime_new_variable(akbasic_Runtime *obj, akbasic_Variable **dest);
/**
* @brief Take an unused function definition from the runtime's pool.
* @param obj Object to initialize, inspect, or modify.
* @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 every function slot is in use.
*/
/** /**
* @brief Call a user-defined function with values a caller already has. * @brief Call a user-defined function with values a caller already has.
* *
@@ -865,6 +858,13 @@ akerr_ErrorContext AKERR_NOIGNORE *akbasic_runtime_new_variable(akbasic_Runtime
*/ */
akerr_ErrorContext AKERR_NOIGNORE *akbasic_runtime_call_function(struct akbasic_Runtime *obj, const char *name, akbasic_Value **args, int nargs, akbasic_Value **dest); akerr_ErrorContext AKERR_NOIGNORE *akbasic_runtime_call_function(struct akbasic_Runtime *obj, const char *name, akbasic_Value **args, int nargs, akbasic_Value **dest);
/**
* @brief Take an unused function definition from the runtime's pool.
* @param obj Object to initialize, inspect, or modify.
* @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 every function slot is in use.
*/
akerr_ErrorContext AKERR_NOIGNORE *akbasic_runtime_new_function(akbasic_Runtime *obj, akbasic_FunctionDef **dest); akerr_ErrorContext AKERR_NOIGNORE *akbasic_runtime_new_function(akbasic_Runtime *obj, akbasic_FunctionDef **dest);
/** /**
* @brief File one already-scanned source line under its line number. * @brief File one already-scanned source line under its line number.

View File

@@ -59,7 +59,7 @@
* with headroom. The ceiling matters because these come out of libakgl's * with headroom. The ceiling matters because these come out of libakgl's
* collision proxy pool, which is shared with whatever host this interpreter is * collision proxy pool, which is shared with whatever host this interpreter is
* embedded in: eight sprites plus sixty-four solids is seventy-two of * embedded in: eight sprites plus sixty-four solids is seventy-two of
* #AKGL_MAX_HEAP_COLLISION_PROXY, and the rest is the host's. * `AKGL_MAX_HEAP_COLLISION_PROXY`, and the rest is the host's.
*/ */
#ifndef AKBASIC_MAX_SOLIDS #ifndef AKBASIC_MAX_SOLIDS
#define AKBASIC_MAX_SOLIDS 64 #define AKBASIC_MAX_SOLIDS 64
@@ -117,7 +117,7 @@ typedef struct
int speed; /* clockwise from vertical, and 0-15 */ int speed; /* clockwise from vertical, and 0-15 */
/** /**
* SPRHIT's collision shape: one of the #AKBASIC_SHAPE_* kinds, and a * SPRHIT's collision shape: one of the `AKBASIC_SHAPE_*` kinds, and a
* rectangle measured from the sprite's top-left corner. * rectangle measured from the sprite's top-left corner.
* *
* `shapeexplicit` is what separates "the program asked for the whole frame" * `shapeexplicit` is what separates "the program asked for the whole frame"

View File

@@ -48,6 +48,7 @@ static akerr_ErrorContext *is_at_end(akbasic_Runtime *obj, bool *dest)
/** /**
* @brief The character under the cursor. * @brief The character under the cursor.
* @param obj The runtime whose scan cursor is being read.
* @param[out] dest The character. Untouched when there is none. * @param[out] dest The character. Untouched when there is none.
* @param[out] got Whether there was one. The old `bool` return. * @param[out] got Whether there was one. The old `bool` return.
*/ */
@@ -70,6 +71,7 @@ static akerr_ErrorContext *peek(akbasic_Runtime *obj, char *dest, bool *got)
/** /**
* @brief The character one past the cursor. * @brief The character one past the cursor.
* @param obj The runtime whose scan cursor is being read.
* @param[out] dest The character. Untouched when there is none. * @param[out] dest The character. Untouched when there is none.
* @param[out] got Whether there was one. The old `bool` return. * @param[out] got Whether there was one. The old `bool` return.
*/ */
@@ -145,6 +147,10 @@ static akerr_ErrorContext *add_token(akbasic_Runtime *obj, akbasic_TokenType tok
/** /**
* @brief Consume one more character when it matches, choosing between two token types. * @brief Consume one more character when it matches, choosing between two token types.
* @param obj The runtime whose scan cursor is being advanced.
* @param cm The character that must be next for the match to succeed.
* @param truetype The token type to report when @p cm matches.
* @param falsetype The token type to report when it does not.
* @param[out] matched Whether the character was consumed. The old `bool` return. * @param[out] matched Whether the character was consumed. The old `bool` return.
* *
* On the chain below `peek`, so it reports the same way. See libakstdlib #38. * On the chain below `peek`, so it reports the same way. See libakstdlib #38.

View File

@@ -875,7 +875,7 @@ static akerr_ErrorContext AKERR_NOIGNORE *run_scan(akbasic_AkglSprites *state)
* proxy carries the owner only so a resolver can push something. Nothing here * proxy carries the owner only so a resolver can push something. Nothing here
* resolves anything, so the field stays empty and the shape is what matters. * resolves anything, so the field stays empty and the shape is what matters.
* *
* Layers are the other half. A wall sits on #AKGL_COLLISION_LAYER_STATIC and * Layers are the other half. A wall sits on `AKGL_COLLISION_LAYER_STATIC` and
* responds to nothing, which is the asymmetry libakgl's masks exist for: the * responds to nothing, which is the asymmetry libakgl's masks exist for: the
* sprite's own `collidemask` includes STATIC, so a sprite finds a wall and two * sprite's own `collidemask` includes STATIC, so a sprite finds a wall and two
* walls never test against each other. Sixty-four motionless rectangles * walls never test against each other. Sixty-four motionless rectangles