Mercurial > lbo > hg > ylisp
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;