NodeC  0.1

These are the primitives to define effect handlers and yield operations. More...

Data Structures

struct  lh_optag_
 Operation values. More...
 
struct  lh_operation
 Opereation defintion. More...
 
struct  lh_handlerdef
 Handler definition. More...
 
struct  yieldargs
 Structure to pass multiple arguments from a yield. More...
 

Macros

#define lh_value_cstack_ptr(p)
 Convert a C stack pointer to an lh_value.
 
#define lh_cstack_ptr_value(r, v)
 Convert an lh_value back to an adjusted C stack pointer. More...
 
#define lh_value_yieldargs(y)
 Convert a yieldargs structure to a generic value.
 
#define lh_yieldargs_value(r, v)
 Convert an lh_value back to a yieldargs structure.
 
#define lh_effect_null
 Null effect.
 
#define lh_op_null
 The null operation tag is used for the final operation struct in a list of operations.
 

Typedefs

typedef struct _lh_resume * lh_resume
 A "resume" continuation. More...
 
typedef const char *const * lh_effect
 Effect values. More...
 
typedef const struct lh_optag_lh_optag
 Operation values. More...
 
typedef lh_value() lh_opfun(lh_resume r, lh_value local, lh_value arg)
 Operation functions are called when that operation is yielded to.
 

Enumerations

enum  lh_opkind {
  LH_OP_NULL, LH_OP_FORWARD, LH_OP_NORESUMEX, LH_OP_NORESUME,
  LH_OP_TAIL_NOOP, LH_OP_TAIL, LH_OP_SCOPED, LH_OP_GENERAL
}
 Operation kinds. More...
 

Functions

lh_value lh_handle (const lh_handlerdef *def, lh_value local, lh_actionfun *body, lh_value arg)
 Handle a particalur effect. More...
 
lh_value lh_yield (lh_optag optag, lh_value arg)
 Yield an operation to the nearest enclosing handler.
 
lh_value lh_yield_local (lh_optag optag)
 lh_yield_local yields to the first enclosing handler for operation optag and returns its local state. More...
 
lh_value lh_scoped_resume (lh_resume r, lh_value local, lh_value res)
 Resume a continuation. More...
 
lh_value lh_tail_resume (lh_resume r, lh_value local, lh_value res)
 Final resumption of a scoped continuation. More...
 
void lh_release (lh_resume r)
 Explicitly release a first-class continuation without resuming.
 
lh_value lh_call_resume (lh_resume r, lh_value local, lh_value res)
 Resume a first-class contiunation with a specified result.
 
lh_value lh_release_resume (lh_resume r, lh_value local, lh_value res)
 Resume a first-class contiunation with a specified result. More...
 
void * lh_cstack_ptr (lh_resume r, void *p)
 Adjust a C stack pointer. More...
 
lh_value lh_yieldN (lh_optag optag, int argcount,...)
 Yield with multiple arguments. More...
 
const char * lh_optag_name (lh_optag optag)
 Get the name of an operation tag.
 
const char * lh_effect_name (lh_effect effect)
 Get the name of an effect tag.
 

Detailed Description

These are the primitives to define effect handlers and yield operations.


Data Structure Documentation

◆ lh_optag_

struct lh_optag_

Operation values.

An operation is identified by an effect and index in that effect. There are defined automatically using LH_DEFINE_OPn macros and can be referred to using LH_OPTAG(effect,opname).

Data Fields
lh_effect effect
long opidx

◆ lh_operation

struct lh_operation

Opereation defintion.

An operation has a kind, an identifying tag, and an associated operation function.

Data Fields
lh_opfun * opfun The operation function; use NULL (with LH_OP_FORWARD) to have the operation forwarded to the next enclosing effect (i.e. a direct tail-resume with the same arguments).
lh_opkind opkind Kind of the operation.
lh_optag optag The identifying tag.

◆ lh_handlerdef

struct lh_handlerdef

Handler definition.

Data Fields
lh_effect effect The Effect being handled.
lh_acquirefun * local_acquire Called when the local state needs to be acquired. Can be NULL.
lh_releasefun * local_release Called when the local state is released. Can be NULL.
const lh_operation * operations Definitions of all handled operations ending with an operation with lh_opkind LH_OP_NULL.

Can be NULL to handle no operations; Note: all operations must be in the same order here as in the effect definition! (since each operation has a fixed index).

lh_resultfun * resultfun Invoked when the handled action is done; can be NULL in which case the action result is passed unchanged.

◆ yieldargs

struct yieldargs

Structure to pass multiple arguments from a yield.

Data Fields
int argcount guaranteed to be >= 0
lh_value args[1] allocated to contain argcount arguments

Macro Definition Documentation

◆ lh_cstack_ptr_value

#define lh_cstack_ptr_value (   r,
 
)

Convert an lh_value back to an adjusted C stack pointer.

The pointer is adjusted to now pointing into the heap allocated resumption. This can be used inside operation handlers but use with care.

Typedef Documentation

◆ lh_effect

typedef const char* const* lh_effect

Effect values.

Operations are identified by a constant string pointer. They are compared by address though so they must be declared as static constants (using #LH_NEWOPTAG)

◆ lh_optag

typedef const struct lh_optag_ * lh_optag

Operation values.

An operation is identified by an effect and index in that effect. There are defined automatically using LH_DEFINE_OPn macros and can be referred to using LH_OPTAG(effect,opname).

◆ lh_resume

typedef struct _lh_resume* lh_resume

A "resume" continuation.

This is first-class, and can be stored in data structures etc, and can survive the scope of an operation function. It can be resumed through lh_resume() or lh_release_resume().

Enumeration Type Documentation

◆ lh_opkind

enum lh_opkind

Operation kinds.

When defining the operations that a handler can handle, these are specified to make the handling of operations more efficient. If you are not sure, LH_OP_GENERAL is always safe to use :-) At this point LH_OP_TAIL and LH_OP_NORESUME are most efficient since they do not need to set up a jump point.

Enumerator
LH_OP_NULL 

Invalid operation (used in static declarations to signal end of the operation array)

LH_OP_FORWARD 

forwarding operation, the opfun should be NULL in this case. Never calls this operations but always forwards to the next innermost handler (i.e. a tail-resumptive identity operation).

LH_OP_NORESUMEX 

promise to never resume – and in C++/SEH, instruct to unwind without even running destructors

LH_OP_NORESUME 

promise to never resume.

LH_OP_TAIL_NOOP 

promise to not call yield and resume at most once, and if resumed, it is the last action performed by the operation function.

LH_OP_TAIL 

promise to resume at most once, and if resumed, it is the last action performed by the operation function.

LH_OP_SCOPED 

promise to never resume, or to always resume within the scope of an operation function.

LH_OP_GENERAL 

may resume zero, once, or multiple times, and can be resumed outside the scope of the operation function.

Function Documentation

◆ lh_cstack_ptr()

void* lh_cstack_ptr ( lh_resume  r,
void *  p 
)

Adjust a C stack pointer.

Inside an operation handler, adjust a pointer that was pointing to the C stack at capture time to point inside the now captured stack. This can be used to pass values by stack reference to operation handlers. Use with care.

◆ lh_handle()

lh_value lh_handle ( const lh_handlerdef def,
lh_value  local,
lh_actionfun body,
lh_value  arg 
)

Handle a particalur effect.

Handles operations yielded in body(arg) with the given handler definition def.

◆ lh_release_resume()

lh_value lh_release_resume ( lh_resume  r,
lh_value  local,
lh_value  res 
)

Resume a first-class contiunation with a specified result.

Also releases the continuation and it cannot be resumed again!

◆ lh_scoped_resume()

lh_value lh_scoped_resume ( lh_resume  r,
lh_value  local,
lh_value  res 
)

Resume a continuation.

Use this when not resuming in a tail position.

◆ lh_tail_resume()

lh_value lh_tail_resume ( lh_resume  r,
lh_value  local,
lh_value  res 
)

Final resumption of a scoped continuation.

Only call lh_tail_resume as the last action of an operation function, i.e. it must occur in tail position of an operation function.

◆ lh_yield_local()

lh_value lh_yield_local ( lh_optag  optag)

lh_yield_local yields to the first enclosing handler for operation optag and returns its local state.

This should be used with care as it violates the encapsulation principle but works well for implicit parameters and to reduce the number of explicit operations for many effects. Note, still forwards through effect handlers that use an lh_opfun of NULL, and, more precisely, returns the state for the innermost enclosing handler that does not have a NULL operation.

◆ lh_yieldN()

lh_value lh_yieldN ( lh_optag  optag,
int  argcount,
  ... 
)

Yield with multiple arguments.

The operation function gets a yieldargs* as its argument containing argcount arguments. The yieldarg* pointer is valid during the scope of the operation function and freed automatically afterwards.