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;
 
 /**