Robbert,

> i wonder if it is possible to implement a single stepper or debugger in avail 
> itself.

Heh. Mark and I have wondered the same thing. We will probably build a debugger 
into the VM, however, just for performance and deeper support. Even though L2 
is not part of the unwritten “specification” of Avail, the debugger should 
probably have L2 support to assist VM developers. Since L2 isn’t exposed to an 
Avail programmer, L2 debugging is unattainable in an Avail program, making 
Avail itself an unsuitable substrate for this purpose.

> via reified immutable continuations may be?

This should probably be sufficient for L1 debugging, but we haven’t given the 
specifics too much thought yet. I feel that Avail seriously wants for a 
debugger, so we should probably turn attention to that within the next few 
milestones.

> are there any examples of how continuations work?

Fortunately, continuations are used quite extensively in the Avail library, so 
examples abound. For basic looping control structures and low-level 
continuation support, check out:

        /avail/Avail/Foundation/Early Control Structures
        /avail/Avail/Foundation/Control Structures

For computation backtracking, check out:

        /avail/Avail/Foundation/Backtracking
        /avail/Avail/Foundation Tests/Backtracking Tests

For coroutines / generators, check out:

        /avail/Avail/Data Abstractions/Iterators/Generators

For fabricating a base continuation by hand, check out:

        /avail/Avail/Foundation/Exceptions (line 1532)

Fabricating a continuation by hand is extremely unusual. The typical case is to 
obtain a continuation by “freezing” the current continuation with a label 
statement. Exactly zero or one label statement may appear per block, i.e., 
function definition, and must be the first statement. A label statement is a 
dollar sign $ (U+0024), then an alphanumeric identifier, then optionally a 
colon : (U+003A) followed by a return type expression; if the return type 
expression is omitted, then top is inferred. A label statement is both a 
definition and an executable assignment. It declares a local constant, whose 
name is given by the identifier, and defines it as the result of the 
corresponding L1 “pushLabel” instruction, which freezes the current 
continuation. The program counter (PC) for the frozen continuation corresponds 
to the “pushLabel” instruction; as it so happens, the PC will always be 1. The 
stack of the frozen continuation is always empty.

There is a primitive for rendezvousing with another fiber to obtain its current 
continuation, but I don’t remember if this primitive is exposed yet. The 
mechanism works, as far as I know, so if I’d not exposed yet, then I’ll expose 
it this weekend.

Other than store it somewhere or query its attributes, there are essentially 
three things that you can do with a continuation:

Restart it with the same arguments (“Restart_”).
Restart it with different arguments (“Restart_with_”).
Exit it by returning into its caller (“Exit_with_” for non-top-valued 
continuations, or “Exit_” for top-valued continuations); if it doesn’t have a 
caller, then the current fiber exits.

Note that each of these operations are bottom-valued statements. A 
bottom-valued statement must be the last statement of its enclosing function, 
and must not be followed by a semicolon ; (U+003B). (This is a little unusual, 
but it ensures, by construction, that you cannot even write unreachable code 
after a bottom-valued statement.) Each of these operations causes the current 
fiber to forget its current continuation and proceed accordingly with the 
specified continuation.

> i ask this because i want to implement a traceability/incremental computation 
> framework.

Sounds fascinating! Let us know if you need any help with the design or 
implementation.

--
Todd L Smith
CEO | The Avail Foundation, LLC
http://www.availlang.org

Reply via email to