Mercurial > lbo > hg > ylisp
changeset 58:06aa18744cb3
doc, expr: Define builtin enum and describe symbol resolution.
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Sat, 24 Aug 2019 19:38:11 +0200 |
parents | aff8b46c1fb9 |
children | f05f6a7896a3 |
files | doc/execution.md src/expr.h |
diffstat | 2 files changed, 59 insertions(+), 11 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/execution.md Sat Aug 24 10:12:56 2019 +0200 +++ b/doc/execution.md Sat Aug 24 19:38:11 2019 +0200 @@ -41,6 +41,10 @@ (print "The result is" (f1 5 x)) ``` +## Preprocessing + +This section describes how the parsed syntax tree is processed before +evaluation. ### Variable/reference resolution @@ -54,7 +58,7 @@ implementation doesn't support recycling. **Value allocation algorithm**: For uniquely allocating references using -`yvalue_create()/yvalue_resolve_or_create_symbol()`. +`yvalue_create()`. The algorithm uses a stack of lists, each list represents the list of already-allocated values in a scope, and for each new scope, a new list is @@ -69,20 +73,47 @@ * Scan program tree * Encounter symbolic reference (an ID)? -> Look up in stack of scope-lists by - walking each list in the stack until one is found. If none is found, this is - an error. + walking each list in the stack until one is found. If none is found, this is + an error. * Encounter one of `defn`, `for`, `let`: Push a new scope list onto the stack. If `defn`, `let`: Push definition of the following function/value into the list of the parent scope. + * Leave scope: Pop scope list from stack. + +Function definitions (`defn`) are then removed from the syntax tree +(respectively replace by no-ops) as they are not used anymore. `let` definitions +are kept, as they are executed every time they are encountered. TODO: Garbage collection, slot recycling (free-slot-list), reference counting? +### Built-in functions and constructs + +Built-in functions or constructs such as `let` and `for` are represented by a +normal `yexpr_t` value of type `YEXPR_BUILTIN` with the `builtin` field in the +inner union being set. Refer to `expr.h` for the complete list of built-ins. + +Built-ins are resolved in the first preprocessor step, before symbols are +resolved. + +Note that `defn` is a built-in, but is not expected to be present in the +processed program tree. All function definitions should be stored immutably and +be referenced from the program as IDs. They are not defined during execution +phase. + ## Function calls +During preprocessing, function definitions are found, references in them are +resolved for the local or parent scope, and the resulting s-expr is stored as +function expression in the value table. The parent scope is given a reference to +the function value, which (as `yfunc_t`) includes a description of the +function's arguments. Subsequent calls are resolved as usual to a numeric ID. +Calls shouldn't be checked, as assignments can result in a different function +being stored at runtime when the actual call happens. The `defn` is removed from +the syntax tree. + A function is a stored `yexpr_t` tree value. Essentially the same as a normal value, but with a few descriptions attached, like the number of arguments it expects and the numeric references that it expects arguments in. Before calling, expressions are copied into those references. - TODO: Pass-by-value copies value/duplicates reference
--- a/src/expr.h Sat Aug 24 10:12:56 2019 +0200 +++ b/src/expr.h Sat Aug 24 19:38:11 2019 +0200 @@ -16,8 +16,8 @@ * @{ */ -/// @brief Numeric reference to a stored value or function (see value.h). Must have a -/// MSB that is 0xff. +/// @brief Numeric reference to a stored value or function (see value.h). Must +/// have a MSB that is 0xff. typedef uint64_t yvalue_id_t; /** @@ -79,7 +79,20 @@ void yref_destroy(yref_t* ref); /** - * Type of an yexpr_t value. + * @brief A yexpr_t can be a builtin (which looks like an ID), described by the + * `builtin` field. + */ +typedef enum { + YBUILTIN_UNDEF = 0, + YBUILTIN_FOR = 1, + YBUILTIN_LET = 2, + YBUILTIN_DEFN = 3, +} YBUILTIN_TYPE; + +/** + * @brief Type of an yexpr_t value. + * + * Each enum value corresponds to a union field being set. */ typedef enum { YEXPR_UNDEF = 0, @@ -88,6 +101,7 @@ YEXPR_ATOM = 3, YEXPR_LIST = 4, YEXPR_REF = 5, + YEXPR_BUILTIN = 6, } YEXPR_TYPE; /** @@ -96,19 +110,22 @@ */ struct yexpr_t { union { + /// A number. + long long n; /// A literal string. ystr_t str; + /// An atom. + yatom_t atom; /// A list of yexpr_t. yvec_t list; - /// A number. - long long n; - /// An atom. - yatom_t atom; /// A named reference (to a value or function described by yvalue_t). yref_t ref; + /// A builtin such as `for`, `let`, ... + YBUILTIN_TYPE builtin; } value; YEXPR_TYPE typ; }; + typedef struct yexpr_t yexpr_t; /**