/** * @file verbs.h * @brief Declares the one dispatch table that replaces the reference's reflection. * * The Go runtime resolves a verb with reflect.MethodByName("Command" + NAME), a * function with "Function" + NAME, and a special parse path with "ParseCommand" + * NAME. C has no reflection and none is being added. All three collapse into the * table in src/verbs.c: sorted by name, searched with bsearch, one row per verb. * * Adding a verb is adding one row and up to two functions. A NULL parse handler * means "parse the rval as a plain expression", which is exactly what * commandByReflection returning (nil, nil) means in the reference. A NULL exec * handler means the token is consumed by another verb's parser and never * evaluated on its own -- THEN, ELSE, TO and STEP are all like that. */ #ifndef _AKBASIC_VERBS_H_ #define _AKBASIC_VERBS_H_ #include #include #include struct akbasic_Parser; struct akbasic_Runtime; typedef akerr_ErrorContext AKERR_NOIGNORE *(*akbasic_ParseHandler)(struct akbasic_Parser *parser, akbasic_ASTLeaf **dest); typedef akerr_ErrorContext AKERR_NOIGNORE *(*akbasic_ExecHandler)(struct akbasic_Runtime *obj, akbasic_ASTLeaf *expr, akbasic_Value *lval, akbasic_Value *rval, akbasic_Value **dest); typedef struct { const char *name; akbasic_TokenType tokentype; int arity; /** Argument count for a function; -1 when not applicable */ akbasic_ParseHandler parse; akbasic_ExecHandler exec; } akbasic_Verb; /** * @brief Find a verb, function or reserved word by name, case-insensitively. * * Verbs and function names are case-insensitive in this dialect; variable names * are not. That asymmetry lives here. * * @param name Name to look up; matched without regard to case. * @param dest Output destination populated by the function; set to NULL on a miss. * @return `NULL` on success, otherwise an error context owned by the caller. * @throws AKERR_NULLPOINTER When `name` or `dest` is NULL. */ akerr_ErrorContext AKERR_NOIGNORE *akbasic_verb_lookup(const char *name, const akbasic_Verb **dest); /** @brief The table itself, exposed so tests can assert it is sorted. */ const akbasic_Verb *akbasic_verb_table(int *count); #endif // _AKBASIC_VERBS_H_