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