Mercurial > lbo > hg > ylisp
view src/value.h @ 128:38714d118bbd
value: Implement stack-references for function calls
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Sun, 01 Sep 2019 19:22:12 +0200 |
parents | 63650268d006 |
children | df0e17d18c80 |
line wrap: on
line source
#ifndef value_h #define value_h #define _GNU_SOURCE #include <stdbool.h> #include <stdint.h> #include "expr.h" #include "func.h" #include "types.h" #include "base/str.h" #include "base/vec.h" /** * @file value.h * @brief Types and functions for describing values and references to values. * @addtogroup language * @{ */ // See expr.h for definitions of yref_t, yvalue_id_t, YREF_TYPE. /// An invalid value ID. const yvalue_id_t YVALUE_INVALID_ID; /// Use YVALUE_INSERT in `yvalue_set()` to insert a new value. const yref_t YVALUE_INSERT; /// Type of a `yvalue_t` value. enum YVALUE_TYPE { YVALUE_UNDEF = 0, YVALUE_FUNC = 1, YVALUE_EXPR = 2, }; /** * @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 reference pointing to the same value as `ref`. The caller * assumes ownership of the returned reference and needs to destroy it later. */ yref_t yref_clone(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 new reference to function argument. */ yref_t yref_new_cix(size_t ix); /** * Return the stack-relative index of ref. */ uint64_t yref_cix(yref_t* ref); /** * 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 Copies the contents of a reference to a new slot and returns a new * reference. (not for functions, which are immutable for now) */ yref_t yvalue_clone(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). * * Expressions or functions assigned to a yvalue_t are owned by it; do not * destroy them. Use `yvalue_destroy()` instead. */ typedef struct { union { /// A function to be called. Functions are immutable, they can not be // updated once set. yfunc_t func; /// An expression (often a scalar number/string/atom) yexpr_t expr; } value; /// Type of a value. enum YVALUE_TYPE typ; } yvalue_t; /** * @brief Create an unnamed value ID. */ yvalue_id_t yvalue_create(void); /** * @brief Free all memory used by a value. */ void yvalue_destroy(yvalue_t* val); /** * @brief Resolve a symbol to an ID. Caller retains ownership of `sym`. */ yvalue_id_t yvalue_resolve_symbol(ystr_t* sym); /** * @brief Resolve a symbol to an ID or create a new ID if one doesn't exist * already. Also allocates a place in the value table. Caller retains ownership * of `sym`. */ yvalue_id_t yvalue_resolve_or_create_symbol(ystr_t* sym); /** * @brief Translate a symbol in `ref` to an ID, or create a new ID. `ref` is * updated to be an ID ref. Caller retains ownership of `ref`. * * NOTE: If `ref` is symbolic, this function frees the symbol string. This * means that it is an error to supply a pointer to a reference that is copied * from another reference that is freed later (double-free). */ void yvalue_resolve_or_create_ref(yref_t* ref); /** * @brief Set a value referenced by `ref`. If a new anonymous reference should * be created, use the special ref value `YVALUE_INSERT`. The value pointed to * by val may not be destroyed afterwards (the variable itself can be * deallocated though). If the reference is a symbolic reference that does not * exist yet, it is resolved and created first. * * The reference at which the value was inserted at is returned (this is only * useful if YVALUE_INSERT is used). */ yref_t yvalue_set(yref_t ref, yvalue_t* val); /** * @brief Return a pointer to the value referenced by `ref`. The pointed-to * value may be modified to update the value. */ yvalue_t* yvalue_get(yref_t ref); /** * @brief Free all stored values. */ void yvalue_free_all(void); /** * @} */ #endif