x-engine-c v0.2.13
The C engine for x-lang
Loading...
Searching...
No Matches
x-toplevel.h File Reference

The top-level bracket: what a form evaluated at top level sees, whatever environment is current when it is asked for. More...

#include "x-obj.h"

Go to the source code of this file.

Data Structures

struct  x_toplevel_t
 

Typedefs

typedef struct x_toplevel_t x_toplevel_t
 

Functions

void x_toplevel_enter (x_obj_t *p_base, x_toplevel_t *p_t)
 
void x_toplevel_leave (x_obj_t *p_base, x_toplevel_t *p_t)
 

Detailed Description

The top-level bracket: what a form evaluated at top level sees, whatever environment is current when it is asked for.

One implementation, two doors – x_eval_load around a file's forms, eval! around one form. The save-stack is hidden and the root is made current; the displaced state is parked on the root chain for the bracket's length, because a C local is not a root.

Author
Jon Ruttan (jonru.nosp@m.ttan.nosp@m.@gmai.nosp@m.l.co.nosp@m.m)

Typedef Documentation

◆ x_toplevel_t

typedef struct x_toplevel_t x_toplevel_t

The caller's bracket state: what was displaced, and the node it is parked on.

Function Documentation

◆ x_toplevel_enter()

void x_toplevel_enter ( x_obj_t p_base,
x_toplevel_t p_t 
)

Enter the bracket, filling p_t.

Enter the top-level bracket: what a form evaluated at top level sees, whatever environment is current when it is asked for.

A top-level form's defs must bind in the root, and the closures it makes must capture the root – not the environment of whatever was being evaluated when the form was asked for. Two doors ask: x_eval_load, for every form of a file (include runs under whatever called it, and its x-level wrapper is a closure), and eval!, for the one form the REPL loop reads (lib/he.x reaches (repl) through (unless batch? (do (banner) (repl))), so every form typed at the prompt sits under those frames). The bracket is two moves: the save-stack is hidden (nil), so a form sees an empty stack exactly as at the true top level and each x_eval balances its own pushes; and the root is made current.

The displaced state is HEAP: the caller's environment and its save-stack, and for the length of the bracket nothing on the base tree reaches them. A C local is not a root (x-heap.h), so a form that collects (a library collecting between definitions is ordinary) would sweep them, and the caller would walk freed memory on its next lookup. So both are parked on the root chain in the caller's own struct, one registered node holding the two pointers; the pop is in x_toplevel_leave. The error path needs nothing more: a guard restores the root chain and the save-stack from its own snapshot, so a longjmp out of a bracketed form drops the node with the C frame that owns it.

Parameters
p_basex_obj_t* – Base (execution context)
p_tx_toplevel_t* – the caller's bracket state, filled here
See also
x_toplevel_leave, x_eval_load, x_prim_eval_immediate

◆ x_toplevel_leave()

void x_toplevel_leave ( x_obj_t p_base,
x_toplevel_t p_t 
)

Leave the bracket: unroot the parked state and put it back.

Leave the top-level bracket: unroot the parked state and put it back.

Parameters
p_basex_obj_t* – Base (execution context)
p_tx_toplevel_t* – the state x_toplevel_enter filled
See also
x_toplevel_enter