changeset 175:07ff95760f4a

func/preprocess: Prepare some facilities for proper closures
author Lewin Bormann <lbo@spheniscida.de>
date Wed, 11 Sep 2019 21:37:43 +0200
parents 0c4e9e76a2f2
children 4a70971df28b
files src/func.h src/preprocess.c src/types.h
diffstat 3 files changed, 26 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/func.h	Mon Sep 09 19:57:39 2019 +0200
+++ b/src/func.h	Wed Sep 11 21:37:43 2019 +0200
@@ -39,6 +39,12 @@
     /// Vector of yarg_desc_t values, each describing an argument, in order of
     /// appearance.
     yvec_t args;
+    /// Vector of yarg_desc_t values, each describing a value to be captured in
+    /// a closure. When defining the function, the interpreter should copy the
+    /// values of these references into the closure yexpr_t value (via the
+    /// to-be-implemented _mkclsr built-in). / When calling a function, the
+    /// captured values are pushed onto the stack before the function arguments.
+    yvec_t captured;
 } yfunc_t;
 
 /**
--- a/src/preprocess.c	Mon Sep 09 19:57:39 2019 +0200
+++ b/src/preprocess.c	Wed Sep 11 21:37:43 2019 +0200
@@ -141,6 +141,7 @@
         ypreprocess_scope_t* scope =
             *YVEC_AT(scope_stack, index, ypreprocess_scope_t*);
 
+        // If found: Add reference to closure captured list
         for (size_t ref = 0; ref < scope->refs.len; ref++) {
             ypreprocess_existing_t* candidate =
                 YVEC_AT(&scope->refs, ref, ypreprocess_existing_t);
@@ -214,7 +215,7 @@
                                          ypreprocess_scope_t*))
                                    ->refs,
                               &funcref);
-
+                    // TODO: Build in references to captured args here (for closures) and give to subsequent functions
                     yvec_t* func_body = &func->value.func.body;
                     for (size_t i = 0; i < func_body->len; i++) {
                         ypreprocess_refs_recursive(
@@ -225,6 +226,8 @@
                 }
             }
 
+            // Not a function definition.
+
             // Resolve list elements recursively.
             for (size_t i = 0; i < expr->value.list.len; i++) {
                 yexpr_t* elem = YVEC_AT(&expr->value.list, i, yexpr_t);
--- a/src/types.h	Mon Sep 09 19:57:39 2019 +0200
+++ b/src/types.h	Wed Sep 11 21:37:43 2019 +0200
@@ -48,6 +48,14 @@
     } ref;
 } yref_t;
 
+typedef struct {
+    /// Reference to function code.
+    yref_t id;
+    /// List of yexpr_t in the order of the `captured` field of the function
+    /// pointed to by id.
+    yvec_t captured;
+} yclosure_t;
+
 /**
  * @brief A yexpr_t can be a builtin (which looks like an ID), described by the
  * `builtin` field.
@@ -81,6 +89,8 @@
 
     YBUILTIN_RAISE = 15,
     YBUILTIN_RECOVER = 16,
+
+    YBUILTIN_INTERNAL_MKCLSR = 100,
 } YBUILTIN_TYPE;
 
 /**
@@ -99,8 +109,11 @@
     YEXPR_ATOM = 3,
     /// A list of expressions.
     YEXPR_LIST = 4,
-    /// A reference to a value or function.
+    /// A reference to a value.
     YEXPR_REF = 5,
+    /// A closure, i.e. reference to a function (in value table) and attached
+    /// closure data.
+    YEXPR_FUNC = 6,
     /// A reference to a built-in function.
     YEXPR_BUILTIN = 6,
     /// An exception described by the `str` field - when returned from a
@@ -127,6 +140,8 @@
         yref_t ref;
         /// A builtin such as `for`, `let`, ...
         YBUILTIN_TYPE builtin;
+        /// A closure, i.e. function reference with associated data.
+        yclosure_t closure;
     } value;
     /// Type of this expression.
     YEXPR_TYPE typ;