[RFC PATCH 14/28] cli: lil: Document structures

Sean Anderson
2021-07-01T06:18:50Z

This documents the major structures of LIL.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---

common/cli_lil.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++
include/cli_lil.h | 57 ++++++++++++++++++++++++++
2 files changed, 157 insertions(+)

diff --git a/common/cli_lil.c b/common/cli_lil.c
index 66ee62bf33..7fbae1964a 100644
--- a/common/cli_lil.c
+++ b/common/cli_lil.c
@@ -29,20 +29,44 @@
#define HASHMAP_CELLS 256
#define HASHMAP_CELLMASK 0xFF

+/**
+ * struct hashentry - An entry in a cell
+ * @k: The key
+ * @v: The value
+ */
struct hashentry {
char *k;
void *v;
};

+/**
+ * struct hashcell - A list of entries with the same hash
+ * @e: An array of entries
+ * @c: The capacity of this cell
+ */
struct hashcell {
struct hashentry *e;
size_t c;
};

+/**
+ * struct hashmap - An array-based hash map
+ * @cell: An array of cells
+ *
+ * This hash map uses separate chaining with an array for each cell. We cannot
+ * use the existing hash map functions (hsearch_r et al.) because they assume
+ * that the value is a string.
+ */
struct hashmap {
struct hashcell cell[HASHMAP_CELLS];
};

+/**
+ * struct lil_value - A string and its length
+ * @l: The length of the value.
+ * @c: The capacity of this value (maximum of @l before requiring reallocation).
+ * @d: The contents of the value, as a nul-terminated string.
+ */
struct lil_value {
size_t l;
#ifdef LIL_ENABLE_POOLS
@@ -51,12 +75,34 @@ struct lil_value {
char *d;
};

+/**
+ * struct lil_var - A variable
+ * @n: The name of this variable
+ * @env: The environment containing this variable
+ * @v: The value of this variable
+ */
struct lil_var {
char *n;
struct lil_env *env;
struct lil_value *v;
};

+/**
+ * struct lil_env - A function call's execution environment
+ * @parent: The parent of this environment. This is %NULL for the root
+ * environment.
+ * @func: The currently-executing function
+ * @proc: The name of the currently-executing built-in procedure
+ * @var: A list of the variables in this environment
+ * @vars: The number of variables in @var
+ * @varmap: A hash map mapping variable names to pointers to variables in @var
+ * @retval: The value set by "return" or "result"
+ * @retval_set: Whether @retval has been set
+ * @breakrun: Whether to immediately break out the current run of execution.
+ * This is set by "return"
+ *
+ * Variables are inherited from @parent.
+ */
struct lil_env {
struct lil_env *parent;
struct lil_func *func;
@@ -69,12 +115,28 @@ struct lil_env {
int breakrun;
};

+/**
+ * struct list - A list of values
+ * @v: A list of pointers to &struct lil_value
+ * @c: The number of values in this list
+ * @cap: The space allocated for @v
+ */
struct lil_list {
struct lil_value **v;
size_t c;
size_t cap;
};

+/**
+ * struct lil_func - A function which may be evaluated with a list of arguments
+ * @name: The name of the function
+ * @code: A value containing LIL code to be evaluated
+ * @argnames: The names of variables to assign to the passed-in arguments
+ * @proc: A C function to use to evaluate this function
+ *
+ * @code and @argnames are only used to evaluate the function if @proc is %NULL.
+ * If @argnames is empty, then the arguments are assigned to a variable "args".
+ */
struct lil_func {
char *name;
struct lil_value *code;
@@ -82,6 +144,31 @@ struct lil_func {
lil_func_proc_t proc;
};

+/**
+ * struct lil - The current state of the interpreter
+ * @code: The code which is being interpreted
+ * @rootcode: The top-level code (e.g. the code for the initial call to
+ * lil_parse())
+ * @clen: The length of @code
+ * @head: The first uninterpreted part of this code, as an index of @code
+ * @ignoreeol: Whether to treat newlines as whitespace or command terminators
+ * @cmd: A list of the current commands
+ * @cmds: The number of commands in @cmd
+ * @cmdmap: A hash map mapping command names to pointers to commands in @cmd
+ * @env: The current environment to evaluate commands in
+ * @rootenv: The top-level "root" environment
+ * @downenv: The original environment after a call to "topeval" or "upeval"
+ * @empty: An empty value, allocated once
+ * @ERROR_NOERROR: There is no error.
+ * @ERROR_DEFAULT: There was an error.
+ * @ERROR_FIXHEAD: There was an error, but @err_head needs to be fixed.
+ * @ERROR_UNBALANCED: An opening quote or bracket lacks a balancing closing
+ * quote or bracket.
+ * @error: The current error status
+ * @err_head: The offset in @code which caused the @error
+ * @err_msg: An optional string describing the current @error
+ * @parse_depth: The depth of recursive function calls
+ */
struct lil {
const char *code; /* need save on parse */
const char *rootcode;
@@ -101,6 +188,19 @@ struct lil {
size_t parse_depth;
};

+/**
+ * struct expreval - A (mathematical) expression being evaluated
+ * @code: The complete code for this expression
+ * @len: The length of @code
+ * @head: The first unevaluated part of this expression, as an index of @code
+ * @ival: The integer value of this expression
+ * @EERR_NO_ERROR: There is no error
+ * @EERR_SYNTAX_ERROR: Syntax error. For now this is just mismatched
+ * parentheses.
+ * @EERR_DIVISION_BY_ZERO: Attempted division by zero
+ * @EERR_INVALID_EXPRESSION: A non-number was present
+ * @error: The error of this expression (if any)
+ */
struct expreval {
const char *code;
size_t len, head;
diff --git a/include/cli_lil.h b/include/cli_lil.h
index cdaa79fd15..91e79c12f4 100644
--- a/include/cli_lil.h
+++ b/include/cli_lil.h
@@ -13,10 +13,35 @@

#define LIL_VERSION_STRING "0.1"

+/**
+ * enum lil_setvar - The strategy to use when creating new variables
+ */
enum lil_setvar {
+ /**
+ * @LIL_SETVAR_GLOBAL: Set in the root environment
+ */
LIL_SETVAR_GLOBAL = 0,
+ /**
+ * @LIL_SETVAR_LOCAL: Set, starting with the local environment
+ *
+ * Search for a variable. If one is found, overwrite it. Otherwise,
+ * create a new variable in the local environment.
+ */
LIL_SETVAR_LOCAL,
+ /**
+ * @LIL_SETVAR_LOCAL_NEW: Create in the local environment
+ *
+ * Create a new variable in the local environment. This never overrides
+ * existing variables (even if one exists in the local environment).
+ */
LIL_SETVAR_LOCAL_NEW,
+ /**
+ * @LIL_SETVAR_LOCAL_ONLY: Set in a local environment only
+ *
+ * Search for a variable in the local environment. If one is found,
+ * overwrite it. Otherwise, create a new variable in the local
+ * environment.
+ */
LIL_SETVAR_LOCAL_ONLY,
};

@@ -32,9 +57,41 @@ struct lil;
typedef struct lil_value *(*lil_func_proc_t)(struct lil *lil, size_t argc,
struct lil_value **argv);

+/**
+ * struct lil_callbacks - Functions called by LIL to allow overriding behavior
+ */
struct lil_callbacks {
+ /**
+ * @setvar: Called when a non-existent global variable is assigned
+ *
+ * @lil: The LIL interpreter
+ *
+ * @name: The name of the variable
+ *
+ * @value: A pointer to the value which would be assigned. This may be
+ * modified to assign a different value.
+ *
+ * This can be used to override or cancel the assignment of a variable
+ *
+ * @Return: A negative value to prevent the assignment, %0 to assign the
+ * original value, or a positive value to assign @value.
+ */
int (*setvar)(struct lil *lil, const char *name,
struct lil_value **value);
+ /**
+ * @getvar: Called when a global variable is read
+ *
+ * @lil: The LIL interpreter
+ *
+ * @name The name of the variable
+ *
+ * @value: The pointer to the value which would be read. This may be
+ * modified to read a different value.
+ *
+ * @Return: A non-zero value to read the value pointed to by @value
+ * instead of the original value, or anything else to use the
+ * original value
+ */
int (*getvar)(struct lil *lil, const char *name,
struct lil_value **value);
};
--
2.32.0