Nov.04.2015 -- CAlive to introduce flow { } blocks

44 views
Skip to first unread message

Rick C. Hodgin

unread,
Nov 4, 2015, 11:12:37 AM11/4/15
to caliveprogra...@googlegroups.com
CAlive will introduce a flow control block which brings structure to unstructured code, while allowing quick-and-easy organization of code that, because of its nature, may not be so easy to organize otherwise.

The flow { } block was created to provide several features:

    (1)  Give unstructured code requirements more structure.
    (2)  To un-indent heavily indented or nested code.
    (3)  Self-document source code by using human readable token
         names as placeholders for computer code and algorithms.
    (4)  Encapsulation of related coding requirements.
    (5)  The ability to mix extracted code blocks with legitimate
         function calls.
    (6)  To provide an isolated and encapsulated framework for
         exception handling (which are called "inquirys" in CAlive).
    (7)  To move the code related to the needs of the key algorithm
         to a point AFTER their reference.
    (8)  To provide documentation for initialization and cleanup code
         related to the algorithm or block.

-----
Its syntax in general form is this:

    flow {
        // Local variable declarations are allowed

        // Main/key algorithm goes here

        // When control reaches here, it naturally flows out
    }

-----
Within the flow { } block you can append flowofs directly to it which are known to the code in the flow block, and as with the external flowofs, these can be referenced as needed:

    flow {
        // Use directly
        sample;

        // Or prefix with flowof for documentation:
        flowof sample;

    } flowof sample {
        // Code to execute at the "sample;" location in source code goes here
    }


-----
The flow { } blocks can have their flowofs used more than once, and they can be used in traditional logic locations:

    flow {
        sample;

        if (x == 4)
            sample;

    } flowof sample {
        printf("Sample\n");
    }

-----
The flow { } block can have built-in and encapsulated functions which are called which may or may not receive parameters, and may or may not return results:

    flow {
        int count;   // Local variable declarations are allowed

        no_params_init();
        printf("%d\n", return_params());
        input_params(3);
        printf("%d, %d\n", count, all_params(5, 6));

    } void no_params_init(void) {
        count = 0;

    } int return_params(void) {
        return(42);

    } void input_params(int qty) {
        count += qty;

    } int all_params(int a, int b) {
        return(a + b);
    }

-----
The flow { } block has flow control keywords, though typically flow will be top-down and it will auto-exit:

    flow {
        flowin;   // Restarts the flow again from the top
        flowout;  // Leaves the flow

    } int some_function(...) {
        // To return to the caller before reaching the end, use:
        return(...);

        // To exit the flow here rather than returning, use flowout:
        flowout;

    } flowof sample {
        // Operations here have their context in the main flow { }
        // block, so everything that works there works here.
        flowin;
        flowout;
    }

-----
The flow { } block can handle exceptions, called inquirys:

    float my_function(float y, float z)
    {
        float x;

        flow {
            // Main/key code goes here
            // If something triggers an inquiry, it will hit the
            // inquiry block.

            // A <|meia|> cask can be used to override that behavior
            // on a line-by-line basis:
            x = y / z <|meia|set_zero_on_inquiry(&x)
|>;

        } void set_zero_on_inquiry(float* f) {
            *f = 0;

        } inquiry {
            // Automatically populates thisCode->inq, a class with
            // standard inquiry handler data and members:
            //
            // Some members:  thisCode->inq.iCode       -- Number
            //                thisCode->inq.iCat        -- Category
            //                thisCode->inq.iSeverity   -- Severity
            //                thisCode->inq.callstack() -- Callstack
            //
            // An optional name can be given, which has scope only
            // in this block.  Rather than using thisCode->inq,
            // you could include a name and use name->iCode, as in:
            //
            //     } inquiry name {
        }

-----
The flow { } block can handle encapsulated init and cleanup code:

    flow {
        // Main/key code goes here

    } always before {
        // Code is executed one time before the flow { } is entered

    } always after {
        // Code is executed when the flow is exited
    }

-----
The flow { } block can handle code that is not properly mated as by its { and } count.  In that case use {{ and }}:

    flow {
        if_cond;
        else_cond;

    } flowof if_cond {{
        if (x == 5)
        {
            // Process if it's 5

    }} flowof else_cond {{
        } else {
            // Process otherwise
        }
    }}

-----
Adhocs can be defined within flow { } blocks, or any of their flowofs:

    flow {
        adhoc int my_adhoc(int a, int b) {
            return(a + b + 9);
        }

        sample;

    } flowof sample {
        // Here we see the original adhoc from above is still in scope
        printf("%d, %d\n", my_adhoc(1, 2), my_other_adhoc(3, 4));

        // Here we see the definition which comes after its usage above
        adhoc int my_other_adhoc(int a, int b) {
            return(a + b + 99);
        }
    }

-----
And flow { } blocks can be nested as needed:

    flow name1 {

        flow name2 {
            // Include this sample:
            sample;
            name2.sample;

            // Include the sample from the name1 block:
            name1.sample;

        } flowof sample {
            // Code for this inner sample goes here
        }

    } flowof sample {
        // Code for sample goes here
    }

-----
The flow { } block is a very powerful creation.

It has the ability to give make writing code more self-documenting by choosing names which make sense, and by isolating algorithm portions as needed. And because it CAlive works closely with the GUI editor, the ability exists to pull all of the flowof blocks back inline as needed to see their normal inline appearance, and to edit them that way, to then have them go back into their flowof blocks for storage.

Best regards,
Rick C. Hodgin

Rick C. Hodgin

unread,
Jan 19, 2016, 9:14:20 AM1/19/16
to caliveprogra...@googlegroups.com
Jan.19.2016 -- CAlive will introduce new abilities to the flow { } block.  These include the ability to explicitly define variables in the header area, the ability to explicitly transfer program flow to named failure handlers which identify the code block as part of a failure condition, end { } blocks are now introduced which allow code to execute post-flow { } block, post-function, or post-app.  And finally, defer block are added which allow conditional execution of code at the end of either the flow { } block, or function, which are determined by program flow.

    flow read_file
    |
// Declarations / attributes related to this flow { } block can go here
    | const FILE* handle
    | char* header
    {
        open_file;
        read_header;

        ...
        // If some condition manually changes and the defer is no longer required:
        fclose(handle);
        nodefer close;

        ...

    } flow open_file {
        if (!(handle = fopen(...)))
            defer close;

    } flow read_header {
        read_header(&header);
        defer free_header;
        if (file header is wrong)
            failure(_SOME_OTHER_ERROR_CODE);

    } failure(int error) {
        // These can be overloaded with different parameters
        return(error);

        // Or, optionally issue a retry statement to avoid exiting the flow { } block:
        if (!retried)
        {
            change_directory();
            retried = true;
            retry open_file;
        }
        // Flow would now fall out of the block on the failure

    } defer close {
        // These can be overloaded with different names
        // Only those activated in source code will be executed
        fclose(handle);


    } defer function free_header {
        // These can be overloaded with different names
        // Only those activated in source code will be executed
        free(header);

    } end  {
        // Code to
engage as the block is exited naturally,
        // or if the end; keyword is used


    } end function {
        // Code to
engage at the end of the function

    } end app {
        // Code to
engage at the end of the app
    }

Rick C. Hodgin

unread,
Sep 12, 2016, 10:24:20 AM9/12/16
to caliveprogra...@googlegroups.com
Sep.12.2016 -- CAlive will introduce the start, start function, start app, and static keywords to the flow { } block.  These include the ability to explicitly breakout and run code at the start of the function each time it's called (start and start function are identical), or at the start of the app with start app and static, which are also identical.

    flow read_file
    | const FILE* handle
    | char* header
    {
        // Code here

    } start  {
        // Code to engage as the block is entered naturally,

    } start function {
        // Code to
engage at the start of the function

    } start app {
        // Code to
engage at the start of the app

    } static {
        // Code to
engage at the start of the app

        // Note:  Any variables defined in this block, or any of those declared
        //        in a static { } block in the main function body, are in scope.
    }

Rick C. Hodgin

unread,
Sep 12, 2016, 10:39:05 AM9/12/16
to CAlive Programming Language
CAlive will introduce the ability to specify isolated named and unnamed flow { } blocks.

    function example
    {
        // Code here
    };

    // An isolated and separated flow {} block.  Its syntax indicates
it belongs to the function "example"
    flowof example
    {
        name {

        } name2 {

        }
    };

A feature would allow the use of a common #include file to convey common operations without having to identify what it is they belong to:

    function example
    {
        // Code here
    };
    #include "common_flow_blocks.h"


    // common_flow_blocks.h
    // Anonymous flow block, which then is in context/scope to where it's used

    flow
    {
        name {

        } name2 {

        }
    };

Rick C. Hodgin

unread,
Sep 8, 2017, 9:44:00 AM9/8/17
to caliveprogra...@googlegroups.com
CAlive will introduce the ability to combine always before {..} and always after {..} blocks into a single always before after {..} block.

    // Iterate until we're finished
    while (QueryStatus(handle, &status))
    {
        // Are we done?
        if (status.nCurrentState == FINISHED)
            break;

        // Pause briefly
        pause;

    } always before after pause {
        // Pause half a second
        Sleep(500);
    }

In this example, the named always before after block is able to run before the while {..} loop, after the while {..} loop, and each time its name pause; is used in source code.  CAlive will expand the code above into this sequence:

    // Pause half a second before we begin
    Sleep(500);

    // Iterate until we're finished
    while (QueryStatus(handle, &status))
    {
        // Are we done?
        if (status.nCurrentState == FINISHED)
            break;

        // Pause briefly
        Sleep(500);
    }

    // Pause half a second after it completes
    Sleep(500);

Were this code used without the always before after pause block, it would be unclear that the two instances of Sleep(500); are related to the while block until you read the comments, and you would see the actual command used three times.

This ability allows code to correlated to its intended use directly, to be condensed, simplified, and more easily understood and documented.

Thank you,
Rick C. Hodgin

Reply all
Reply to author
Forward
0 new messages