Mercurial > lbo > hg > ylisp
changeset 60:2144052c96b4
expr, value: Move interdependent types into dedicated header file
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Sat, 24 Aug 2019 21:25:59 +0200 |
parents | f05f6a7896a3 |
children | 81b4668981e6 |
files | src/expr.c src/expr.h src/types.h src/value.c src/value.h |
diffstat | 5 files changed, 236 insertions(+), 171 deletions(-) [+] |
line wrap: on
line diff
--- a/src/expr.c Sat Aug 24 21:24:37 2019 +0200 +++ b/src/expr.c Sat Aug 24 21:25:59 2019 +0200 @@ -1,66 +1,14 @@ #include "expr.h" +#include <src/value.h> +#include <src/built-ins.h> + #include <src/base/str.h> #include <src/base/vec.h> #include <assert.h> #include <stdio.h> -static const yvalue_id_t YVALUE_ID_MARKER = 0xff00000000000000; - -bool yvalue_is_valid(yvalue_id_t id) { - return (id & YVALUE_ID_MARKER) == YVALUE_ID_MARKER; -} - -YREF_TYPE yref_type(yref_t* ref) { - if ((ref->ref.id & YVALUE_ID_MARKER) == YVALUE_ID_MARKER) { - return YREF_ID; - } - return YREF_SYM; -} - -yvalue_id_t yvalue_create(void); - -yref_t yref_new(void) { - yref_t ref = {.ref.id = yvalue_create() }; - return ref; -} - -yref_t yref_new_id(yvalue_id_t id) { - assert(yvalue_is_valid(id)); - yref_t ref = {.ref.id = id}; - return ref; -} - -yref_t yref_new_str(ystr_t* sym) { - yref_t ref = {.ref.sym = *sym}; - return ref; -} - -yref_t yref_new_c(const char* sym) { - yref_t ref = {.ref.sym = ystr_new(sym)}; - return ref; -} - -ystr_t yref_debug(yref_t* ref) { - YREF_TYPE typ = yref_type(ref); - if (typ == YREF_ID) { - ystr_t s = ystr_new(NULL); - ystr_build(&s, "id:<%llu>", ref->ref.id); - return s; - } else if (typ == YREF_SYM) { - ystr_t s = ystr_new(NULL); - ystr_build(&s, "id:<\"%s\">", ystr_str(&ref->ref.sym)); - return s; - } - return ystr_new("id:INVALID"); -} - -void yref_destroy(yref_t* ref) { - if (ref == NULL) return; - if (yref_type(ref) == YREF_SYM) ystr_destroy(&ref->ref.sym); -} - void yexpr_init(yexpr_t* v) { v->typ = YEXPR_UNDEF; memset(&v->value, 0, sizeof(v->value)); @@ -75,10 +23,13 @@ void yexpr_destroy(yexpr_t* v) { if (v == NULL) return; switch (v->typ) { + // Cases where the value is internal to the yexpr_t value: case YEXPR_UNDEF: case YEXPR_NUMBER: case YEXPR_ATOM: + case YEXPR_BUILTIN: break; + // External values: case YEXPR_STRING: ystr_destroy(&v->value.str); break; @@ -107,6 +58,12 @@ v->value.n = n; } +void yexpr_set_builtin(yexpr_t* v, YBUILTIN_TYPE b) { + yexpr_destroy(v); + v->typ = YEXPR_BUILTIN; + v->value.builtin = b; +} + void yexpr_set_str(yexpr_t* v, ystr_t str) { yexpr_destroy(v); v->typ = YEXPR_STRING; @@ -181,6 +138,9 @@ fprintf(stderr, "%s", ystr_str(&tmp)); ystr_destroy(&tmp); break; + case YEXPR_BUILTIN: + fprintf(stderr, "%s", ybuiltin_name(expr->value.builtin)); + break; case YEXPR_LIST: fprintf(stderr, "("); yexpr_t* var = YVEC_AT(&expr->value.list, 0, yexpr_t); @@ -191,5 +151,7 @@ } fprintf(stderr, ")"); break; + default: + assert(false /* Unhandled YEXPR_TYPE */); } }
--- a/src/expr.h Sat Aug 24 21:24:37 2019 +0200 +++ b/src/expr.h Sat Aug 24 21:25:59 2019 +0200 @@ -1,133 +1,18 @@ #ifndef src_expr_h #define src_expr_h -#include <src/atom.h> +#include <src/types.h> #include <stdbool.h> #include <stdio.h> #include <string.h> -#include <src/base/str.h> -#include <src/base/vec.h> - /** * @file expr.h * @addtogroup language * @{ */ -/// @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; - -/** - * @brief Checks if the id is a valid ID. - */ -bool yvalue_is_valid(yvalue_id_t id); - -typedef enum { - YREF_UNDEF = 0, - YREF_ID = 1, - YREF_SYM = 2, -} YREF_TYPE; - -/** - * @brief A reference to a stored function or value. To be used as value (not - * pointer). - */ -typedef struct { - union { - ystr_t sym; - yvalue_id_t id; - } ref; -} yref_t; - -/** - * @brief Return type of a reference. - */ -YREF_TYPE yref_type(yref_t* ref); - -/** - * Create a new unnamed reference. - */ -yref_t yref_new(void); - -/** - * Create a new reference with the given ID. - */ -yref_t yref_new_id(yvalue_id_t id); - -/** - * Create a new reference to the given symbol. Takes ownership of `sym`, it must - * not be freed afterwards. - */ -yref_t yref_new_str(ystr_t* sym); - -/** - * Create a new reference to the given symbol. - */ -yref_t yref_new_c(const char* sym); - -/** - * Create a debug description of ref. - */ -ystr_t yref_debug(yref_t* ref); - -/** - * @brief Deallocate memory used by the reference itself. - */ -void yref_destroy(yref_t* ref); - -/** - * @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, - YEXPR_NUMBER = 1, - YEXPR_STRING = 2, - YEXPR_ATOM = 3, - YEXPR_LIST = 4, - YEXPR_REF = 5, - YEXPR_BUILTIN = 6, -} YEXPR_TYPE; - -/** - * A value. Can be either a fundamental value (number, string, atom) or a list - * of values. - */ -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 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; - /** * Initialize a yexpr_t to the undefined value. */ @@ -156,6 +41,11 @@ void yexpr_set_str(yexpr_t* v, ystr_t str); /** + * Initialize a yexpr_t value with a builtin. + */ +void yexpr_set_builtin(yexpr_t* v, YBUILTIN_TYPE b); + +/** * Initialize a yexpr_t with an atom. */ void yexpr_set_atom(yexpr_t* v, yatom_t atom); @@ -193,6 +83,8 @@ * If `expr` is uninitialized or a list: append `arg` to it. If it is a value: * Append value to a new list, append `arg` to the list, and assign the list to * `expr`. + * + * Ownership of arg goes to `expr`; do not explicitly destroy `arg`. */ void yexpr_init_or_extend(yexpr_t* expr, yexpr_t arg);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/types.h Sat Aug 24 21:25:59 2019 +0200 @@ -0,0 +1,112 @@ +#ifndef src_types_h +#define src_types_h + +/** + * @file types.h + * @brief Collection of inter-dependent types used by the core implementation. + * @addtogroup language + * @{ + */ + +#include <src/atom.h> +#include <src/base/str.h> +#include <src/base/vec.h> + +/// @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; + +/** + * @brief Type of a reference: Symbolic or numeric. + * + * Symbolic references can be resolved to a numeric one, creating a "value slot" (see `value.h`). + */ +typedef enum { + YREF_UNDEF = 0, + YREF_ID = 1, + YREF_SYM = 2, +} YREF_TYPE; + +/** + * @brief A reference to a stored function or value. To be used as value (not + * pointer). + */ +typedef struct { + union { + ystr_t sym; + yvalue_id_t id; + } ref; +} yref_t; + +/** + * @brief A yexpr_t can be a builtin (which looks like an ID), described by the + * `builtin` field. + * + * NOTE: Don't forget updating YBUILTIN_ENUM_STR when adding types here. + */ +typedef enum { + YBUILTIN_UNDEF = 0, + YBUILTIN_FOR = 1, + YBUILTIN_LET = 2, + YBUILTIN_DEFN = 3, + + YBUILTIN_PLUS = 4, + YBUILTIN_MINUS = 5, + YBUILTIN_MULT = 6, + YBUILTIN_DIV = 7, + + YBUILTIN_IF = 8, + YBUILTIN_SEQ = 9, +} YBUILTIN_TYPE; + +/** + * @brief Type of an yexpr_t value. + * + * Each enum value corresponds to a union field being set. + */ +typedef enum { + YEXPR_UNDEF = 0, + YEXPR_NUMBER = 1, + YEXPR_STRING = 2, + YEXPR_ATOM = 3, + YEXPR_LIST = 4, + YEXPR_REF = 5, + YEXPR_BUILTIN = 6, +} YEXPR_TYPE; + +/** + * A value. Can be either a fundamental value (number, string, atom) or a list + * of values. + */ +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 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; + +/** + * @brief Type of a built-in function called during execution. + * + * The functions return a yexpr_t of which the caller assumes ownership. + */ +typedef yexpr_t (*ybuiltin_fn)(yvec_t* call_stack); + + +/** + * @} + */ +#endif
--- a/src/value.c Sat Aug 24 21:24:37 2019 +0200 +++ b/src/value.c Sat Aug 24 21:25:59 2019 +0200 @@ -36,6 +36,8 @@ // reference-counting in different table) static yvalue_id_t yvalue_counter = YVALUE_COUNTER_OFFSET; +static const yvalue_id_t YVALUE_ID_MARKER = 0xff00000000000000; + static inline void yvalue_init_tables(void) { if (yvalue_table_initialized) return; yvalue_table_initialized = true; @@ -43,6 +45,60 @@ YVEC_INIT(&yvalue_table, YVALUE_INITIAL_VALUES, yvalue_t); } +bool yvalue_is_valid(yvalue_id_t id) { + return (id & YVALUE_ID_MARKER) == YVALUE_ID_MARKER; +} + +YREF_TYPE yref_type(yref_t* ref) { + if ((ref->ref.id & YVALUE_ID_MARKER) == YVALUE_ID_MARKER) { + return YREF_ID; + } + return YREF_SYM; +} + +yvalue_id_t yvalue_create(void); + +yref_t yref_new(void) { + yref_t ref = {.ref.id = yvalue_create() }; + return ref; +} + +yref_t yref_new_id(yvalue_id_t id) { + assert(yvalue_is_valid(id)); + yref_t ref = {.ref.id = id}; + return ref; +} + +yref_t yref_new_str(ystr_t* sym) { + yref_t ref = {.ref.sym = *sym}; + return ref; +} + +yref_t yref_new_c(const char* sym) { + yref_t ref = {.ref.sym = ystr_new(sym)}; + return ref; +} + +ystr_t yref_debug(yref_t* ref) { + YREF_TYPE typ = yref_type(ref); + if (typ == YREF_ID) { + ystr_t s = ystr_new(NULL); + ystr_build(&s, "id:<%llu>", ref->ref.id); + return s; + } else if (typ == YREF_SYM) { + ystr_t s = ystr_new(NULL); + ystr_build(&s, "id:<\"%s\">", ystr_str(&ref->ref.sym)); + return s; + } + return ystr_new("id:INVALID"); +} + +void yref_destroy(yref_t* ref) { + if (ref == NULL) return; + if (yref_type(ref) == YREF_SYM) ystr_destroy(&ref->ref.sym); +} + + void yvalue_destroy(yvalue_t* val) { switch (val->typ) { case YVALUE_EXPR:
--- a/src/value.h Sat Aug 24 21:24:37 2019 +0200 +++ b/src/value.h Sat Aug 24 21:25:59 2019 +0200 @@ -8,6 +8,7 @@ #include <src/expr.h> #include <src/func.h> +#include <src/types.h> #include <src/base/str.h> #include <src/base/vec.h> @@ -34,6 +35,48 @@ }; /** + * @brief Checks if the id is a valid ID. + */ +bool yvalue_is_valid(yvalue_id_t id); + +/** + * @brief Return type of a reference. + */ +YREF_TYPE yref_type(yref_t* ref); + +/** + * Create a new unnamed reference. + */ +yref_t yref_new(void); + +/** + * Create a new reference with the given ID. + */ +yref_t yref_new_id(yvalue_id_t id); + +/** + * Create a new reference to the given symbol. Takes ownership of `sym`, it must + * not be freed afterwards. + */ +yref_t yref_new_str(ystr_t* sym); + +/** + * Create a new reference to the given symbol. + */ +yref_t yref_new_c(const char* sym); + +/** + * Create a debug description of ref. + */ +ystr_t yref_debug(yref_t* ref); + +/** + * @brief Deallocate memory used by the reference itself. + */ +void yref_destroy(yref_t* ref); + + +/** * @brief A value with a name, stored in the global value table to be referenced * by name or ID. To be used as pointer (not value). *