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