ldmud-3.4.1/doc/
ldmud-3.4.1/doc/efun.de/
ldmud-3.4.1/doc/efun/
ldmud-3.4.1/doc/man/
ldmud-3.4.1/doc/other/
ldmud-3.4.1/mud/
ldmud-3.4.1/mud/heaven7/
ldmud-3.4.1/mud/lp-245/
ldmud-3.4.1/mud/lp-245/banish/
ldmud-3.4.1/mud/lp-245/doc/
ldmud-3.4.1/mud/lp-245/doc/examples/
ldmud-3.4.1/mud/lp-245/doc/sefun/
ldmud-3.4.1/mud/lp-245/log/
ldmud-3.4.1/mud/lp-245/obj/Go/
ldmud-3.4.1/mud/lp-245/players/lars/
ldmud-3.4.1/mud/lp-245/room/death/
ldmud-3.4.1/mud/lp-245/room/maze1/
ldmud-3.4.1/mud/lp-245/room/sub/
ldmud-3.4.1/mud/lp-245/secure/
ldmud-3.4.1/mud/morgengrauen/
ldmud-3.4.1/mud/morgengrauen/lib/
ldmud-3.4.1/mud/sticklib/
ldmud-3.4.1/mud/sticklib/src/
ldmud-3.4.1/mudlib/uni-crasher/
ldmud-3.4.1/pkg/
ldmud-3.4.1/pkg/debugger/
ldmud-3.4.1/pkg/diff/
ldmud-3.4.1/pkg/misc/
ldmud-3.4.1/src/autoconf/
ldmud-3.4.1/src/hosts/
ldmud-3.4.1/src/hosts/GnuWin32/
ldmud-3.4.1/src/hosts/amiga/
ldmud-3.4.1/src/hosts/win32/
ldmud-3.4.1/src/ptmalloc/
ldmud-3.4.1/src/util/
ldmud-3.4.1/src/util/erq/
ldmud-3.4.1/src/util/indent/hosts/next/
ldmud-3.4.1/src/util/xerq/
ldmud-3.4.1/src/util/xerq/lpc/
ldmud-3.4.1/src/util/xerq/lpc/www/
ldmud-3.4.1/test/t-030925/
ldmud-3.4.1/test/t-040413/
ldmud-3.4.1/test/t-041124/
#ifndef CLOSURE_H__
#define CLOSURE_H__ 1

#include "driver.h"
#include "typedefs.h"

#include "bytecode.h"
#ifdef USE_NEW_INLINES
#include "svalue.h"
#endif /* USE_NEW_INLINES */

/* --- Types --- */

/* --- struct lambda_s:  ---
 *
 * If the closure uses constant values, they are stored in an svalue[]
 * right before the struct lambda and indexed from the end.
 * For lfun closures, the context variables are stored after the
 * lambda_s. If the lfun closure has no context variables, or for
 * other kinds of closures the context[] part is not allocated at all.
 */

struct lambda_s
{
    /* svalue_t values[]
     *
     * For lambda closures, the constant values used by the function
     * which are indexed from the end. That means that value #x can
     * be found at address ((svalue_t *)lambda_t)[-x-1].
     */

    p_int ref;          /* ref count */
    object_t *ob;
      /* Object the closure is bound to (for bound UNBOUND_LAMBDAs just
       * during the execution of the lambda).
       */

    object_t   *prog_ob;
    ptrdiff_t   prog_pc;
      /* Blueprint object and relative for the program creating this closure,
       * or NULL. Since this information is error reporting purposes only,
       * the lambda keeps a reference to the blueprint and not the program
       * itself to not get in the way of swapping or other things.
       */

    union               /* Closure information: */
    {
        unsigned short var_index;
          /* _IDENTIFIER: index in the variable table
           */
#       define VANISHED_VARCLOSURE_INDEX ((unsigned short)-1)
          /*              Special value for vanished variable closures.
           *              TODO: it's tested with >=0 at places :-(,
           */

        struct {
            /* CLOSURE_LFUN */
            object_t       *ob;          /* Originating object */
            unsigned short index;        /* Index in the object's function
                                          * table */
            unsigned short inhIndex;     /* 0, or (1 + inheritance index)
                                          * for closure referencing
                                          * inherited functions (even if
                                          * overloaded).
                                          */
            unsigned short context_size; /* Number of context vars */
        } lfun;

        bytecode_t code[1];
          /* LAMBDA and UNBOUND_LAMBDA closures: the function code, starting
           * with uint8 'num_values' and continuing with FUNCTION_NUM_ARGS
           * (which is where the fun_hdr_p will point to).
           * 'num_values' is the size of the svalue[] preceeding the lambda;
           * if it is 0xff, the actual size is stored in
           * svalue[-0xff].u.number.
           */
#       define LAMBDA_NUM_VALUES(p)  EXTRACT_UCHAR((char *)p)
#       define LAMBDA_NUM_ARGS(p)    EXTRACT_SCHAR((char *)p + sizeof(char))
#       define LAMBDA_NUM_VARS(p)    (*((unsigned char *)((char *)p + 2*sizeof(char))))
#       define LAMBDA_CODE(p)        ((bytecode_p)((unsigned char *)p + 3*sizeof(char)))

        lambda_t *lambda;
          /* BOUND_LAMBDA: pointer to the UNBOUND_LAMBDA structure.
           */
    } function;

#ifdef USE_NEW_INLINES
    svalue_t context[ /* .lfun.context_size */ 1];
      /* lfun-closure context variables, if any.
       * Putting this array into the function.lfun somehow causes memory
       * corruption because some lambda structures won't be allocated large
       * enough.
       */
#endif
};

#define LAMBDA_VALUE_OFFSET \
  (sizeof(svalue_t) + offsetof(lambda_t, function.code[1]))
  /* Offset from the fun_hdr_p of a lambda closure to the first
   * constant value (the one with index number 0).
   */

#ifndef USE_NEW_INLINES
#define SIZEOF_LAMBDA(num) sizeof(struct lambda_s)
#else /* USE_NEW_INLINES */
#define SIZEOF_LAMBDA(num) (sizeof(struct lambda_s) + (((int)num)-1) * sizeof(svalue_t))
#endif /* USE_NEW_INLINES */
  /* size_t SIZEOF_LAMBDA(int num)
   *   Size of a lambda closure with <num> context variables.
   */

/* --- Prototypes --- */

extern long      find_function(const string_t *name, const program_t *prog);
extern Bool      closure_eq (svalue_t * left, svalue_t * right);
extern int       closure_cmp (svalue_t * left, svalue_t * right);
extern void      set_closure_user(svalue_t *svp, object_t *owner);
extern void      replace_program_lambda_adjust(replace_ob_t *r_ob);
extern void      closure_init_lambda (lambda_t * l, object_t * obj);
#ifndef USE_NEW_INLINES
extern void      closure_literal(svalue_t *dest, int ix, unsigned short inhIndex);
extern void      closure_lfun (svalue_t *dest, object_t *obj, int ix, unsigned short inhIndex, Bool raise_error);
extern lambda_t *closure_new_lambda (object_t * obj, Bool raise_error);
#else /* USE_NEW_INLINES */
extern lambda_t *closure_new_lambda (object_t * obj, unsigned short context_size, Bool raise_error);
extern void      closure_lfun (svalue_t *dest, object_t *obj, int ix, unsigned short inhIndex, unsigned short num, Bool raise_error);
extern void      closure_literal(svalue_t *dest, int ix, unsigned short inhIndex, unsigned short num);
#endif /* USE_NEW_INLINES */
extern void      closure_identifier (svalue_t *dest, object_t * obj, int ix, Bool raise_error);
extern void      free_closure(svalue_t *svp);
extern Bool      is_undef_closure (svalue_t *sp);
extern void      closure_lookup_lfun_prog ( lambda_t * l , program_t ** pProg , string_t ** pName , Bool * pIsInherited);
extern const char * closure_operator_to_string (int type);
extern const char * closure_efun_to_string (int type);
extern string_t * closure_location (lambda_t *l);
extern string_t *closure_to_string (svalue_t * sp, Bool compact);
extern svalue_t *v_bind_lambda(svalue_t *sp, int num_arg);
extern svalue_t *f_lambda(svalue_t *sp);
extern svalue_t *f_symbol_function(svalue_t *sp);
extern svalue_t *f_symbol_variable(svalue_t *sp);
extern svalue_t *f_unbound_lambda(svalue_t *sp);
extern void      align_switch(bytecode_p pc);

#endif /* CLOSURE_H__ */