Here's a reply I posted to someone in this thread:
https://groups.google.com/d/msg/comp.lang.c/LeL4CPfktfg/H0IUuADCBQAJI've left it un-edited as is, though some of the syntax is slightly off:
Casks are fully expanded forms in source code. They can have return
values, function names, and parameters when in the form of a
(|reference|) cask, or a ~|utility|~ cask:
(||return|function_name|param1, param2, param3, ...||)
~||return|function_name|param1, param2, param3, ...||~
(|reference|) casks are used to call other things (functions, adhocs,
member functions), whereas ~|utility|~ casks can do that, but they
are designed more for injecting whatever code where you want it to
be:
~|x = 5; printf("%d\n", my_function(x));|~
And then to simplify them in the GUI editor, there are additional
parts which can be added:
(||return|function_name|param1, param2, param3, ...||).name(update_total)
~|x = 5; printf("%d\n", my_function(x));|~.name(debug_print)
So that in the GUI editor they will appear in their short forms:
(o|update_total|o)
~|debug_print|~
Since casks are enclosed expressions, they can be inserted anywhere in
code. If they are inserted before a parameter is used, they will be
called before that parameter is put on the stack. If they're inserted
after, then they'll be called after it's on the stack. If they're
inserted before a logic test, then they'll be called before the test
is made. If they're inserted after a logic test, then they'll be called
after the logic test is made (if the logic then reached that far, for
example).
And so on...
-----
There are two more types of casks:
[|definition|]
<|logic|>
[|definition|] casks alter the way things are defined. You can put
in overrides, or augments to their definition. An example people
might be aware of would be:
char p [|const|];
// same as "const char p;"
Why would someone do this? Casks show up graphically in the editor,
and it may be more eye catching to see something which looks like this
in the GUI editor:
[char p];
Where the coloring of the "char p" portion is highlighted so that it
conveys the const nature without the keyword const. That's just an
example, by the way, but one I will probably include, along with other
similar ones.
-----
<|logic|> casks respond to true or false conditions set by flow control
operators, or they can inject their own as the left-most place in the
cask, then acting like a ((cond) ? iftrue : iffalse) expression:
<||cond|iftrue|iffalse||>
There are specific types, however, which are called META and MEFA, for
true and false, respectively:
<|meta|iftrue||>
<|mefa|iffalse||>
In these cases, these casks can be added to expressions and then will
signal the code based on the logic condition result:
if (x == 5 <|meta|iftrue||> <|meta|iffalse||>)
{
// Normal code here
}
In this example, the equivalent code would be:
llTest = (x == 5);
if (!llTest)
{
iffalse();
} else {
iftrue();
// Normal code here
}
And they can be inserted anywhere there are logic tests.
There are two other types of logic cask which follows the meta/mefa form
that I haven't introduced yet. They relate to new features of CAlive:
<|meia|> // Inquiry signal handler casks
<|mema|> // Message handler casks
If you think a line might throw an exception, which is called an inquiry
in CAlive, then you can attach a <|meia|> logic cask to it, and when
the inquiry happens, it will trigger that code:
some_function() <|meia|inquiry_handler||>;
Now, if something in some_function() or lower triggers an inquiry, it
will come back to this point and call the inquiry_handler() function.
And if there are specific types, then it can be moved to the left-most
slot for the testing:
some_function() <||_OUT_OF_MEMORY|meia|inquiry_handler_memory||>
<||_FLOATING_POINT|meia|inquiry_handler_fp||>
<|meia|inquiry_handler_default||>;
In this case, those two types of inquirys are handled explicitly, with
all others falling through to the default handler. If the default
handler wasn't specified, then other inquirys would not be handld here.
And <|meia|> casks can be inserted anywhere. I also introduce a special
flow control block which is similar to try..catch which handles inquiries.
-----
<|mema|> are message hander casks. It is a new CAlive feature to allow
not only a return value to be returned, but also a message. Messages
are available specifically to trigger <|mema|> casks, and are ignored
otherwise. Messages can return any combination of an integer, pointer
to text, or a pointer to any other thing, as int num, char* msg, and
void* p members.
void handler_message(char* p, int i)
{
printf("%s on %d\n", p, i);
}
some_function() <|mema|handler_message(mema.msg, mema.num)||>;
void some_function(void)
{
if (date_is_monday_thru_friday)
return message "Hi, mom!", day_of_week_number;
}
In this case, the message would be returned if the logic test passed,
and it would trigger the handler_message() function only in that case.
By embedding a ~|utility|~ cask within the <|mema|> cask, it then also
becomes possible to handle direct branching based on the returned
message, though this is typically handled through the flow { } blocks,
which I have not yet introduced, though I did introduce them many
months ago.