Do you know how Robin Hood saved the princess from gail ? Well, first he shot an arrow in the gails door, connected with a thin wire. The princess pulled on the wire to get a thicker one and a thicker one until it was that thick they could kick out the window bound to the thick kable and pulled by horses.
Ok,... but why I'm telling you this ? Because GAPP works the same way. Think the princess as your project that uses GAPP for development. The horses are represented by your machine and the wires that get thicker and thicker are the interpreting programming languages. Most importand is SWITCH (the thin wire on the arrow), from there on you quickly contact Slang or Python.
When a file is loaded the output is normally the same text. Unless there is a so called switch in it. What is a switch ? A switch starts swith a
[ followed by a single switch character and finisched by a ]Don't worry about array or map subscribtions, that has been taken care of.
example (using slang)
Here is my text in the file
[$_var version=111]
[+
evalfile("funcs_[$version].sl");
]
And here it ends
The + is used to switch from text to execution of slang code. The slang code is interpreted instantly and fast. In this case by loading slang functions from funcs_111.sl. Switch commands can be nested and generally are expanded from inside to outside. The example is not very practical but it shows importand aspects of GAPP. The first is a expression declaration with _var as designator. The only thing you should understand is that it defines variable 'version' inside the slang interpreter before entering the second switch. The second switch also contains a netsted switch inside a textstring. Because GAPP is syntax independed it simply exands the found expression before the outer switch is evaluated. Another interesting aspect is the way switches are detected and determinated in the source. In fact while parsing the source, the parser ONLY senses a '[' character. That means that parsing text (aspecially if not ment to be preprocessed with GAPP and has no switches) is as fast as possible. The SWITCH parser is optimized to minimize the per character operations because all operations for each character that passes heavily effects the performance. It is very likely than GAPP is several orders faster then other preprocessors. Let's continue with another example before diving in the details of SWITCH.
example (switch macro)
-- SQL query examply
-- Defining a switch macro
[# query(table,fields,filter)
select (#fields)
from (#table)
where (#filter)
]
-- Calling a switch macro
[@query(books, title, date<"2000/01/01")]
; -- execute
GAPP can use SWITCH to define and call macro's much more elegantly then CCCP or m4 can do. The basic requirement was to let the macro produce what is meant. Particularly the macro should be expanded in precisely the same form as it is defined.
Future versions of GAPP will even place the macro expansion at a predeterminated column so that if the macro call is indented, the expansion of it will do the same identation. In some languages this is required (like in python), but mostly if not, a wrong identation can be very disturbing when inspecting the preprocessed code.
Behind the scenes, macro's are translated to slang functions. This will allow excahnge of macro's and slang functions as long the slang functions use strings as arguments. There are some amazing details about macro's which will be discussed later.
All GAPP actions happen within square brackets, on the outside there is only text. So unless squary brackets appear, GAPP does nothing more than passing the text. Next we will describe all the SWITCH commands briefly.
A switch command is a single unsymetric punctuator character right after the opening square bracket. There are only a few (10) for the most usefull commands of a preprocessor (like macros) but most more functionality is handled by slang and others. Here is a overview of the switch language.
char Command description/action
/ Ignore The enclosed contents is ignored entirely.
Contents (normally the most inner commands are
expanded first. Any nested switch commands
are not executed. This is mostly used
for comments but genarally excludes text
from the output text. It is easy to disable
switches of source sections. To disable
a switch simply put a / in place. Like
[+ ....] to [/+ ....]. This is a very
usefull asset while developping.
$ Value Variable or expression is substituted
Expression by its value. If the first wordt after $
encountered begins with a underscore ( _ )
it is a designator. Designator _var is defined
to declare a variable.
+ Interprete The section is interpreted as slang code.
Slang Functions can be defined and called. Or
emediate code is executed. You should take
a look to the startup files in <ROOT>/lib/gapp
and see what you can use directly.
~ Text Used to allow coditional text sections
Out controlled by slang. It ensures that the
enclosed text is put that way in the output
text by slang.
* Quote Ensures output is quoted accoring actual quote
Text characters. This is used to make long text
translated to strings for slang functions
without appearing as strings.
# Define Define a macro, similair to CCCP in its
Macro definition but does real multiline macros.
Expansion of multiple lines and not on a
single line. The definition needs no line
breaks.
@ Call Call macro defined with # or certain slang
Macro functions. Because macro calls are always in
[@ ...] they are clearly distinguishable from
C++ function calls. Multiple macro calls can
be enclosed in one switch wrapper. Arguments
are included in
: Include Include an other gapp files automaitcally only
Files once. The expressions in it are expanded too.
There are some raw versions defined in slang if
you need less smart ways to include. For pure CCCP
include files use gapp command [!headers ....].
= Server Connect to server program and send a command.
Request The syntax depends on the server. Currently
there is a python server which can load
complex definitions before proprocessing
starts. This can save time and allow very
complex processing or even code generation.
! Gapp Transfers command control to a gapp command.
Command A gapp command is a single word with any kind
of text data till a closing squire brace `]'.
There are system gapp commands (natively
implememented) and user gapp commands (implementable
in slang). If the command is not recognized as a
system gapp command it is assumed to be a user
gapp command. System gapp commands are overloadable
by configuration of gapp.
& Pass In the first place simply passing text does not
Text seem to be usefull but it is because of evaluation
options. In GAPP/OPEN evaluation options however
are not implemented, so the function of passing
text is very limited. It is still usefull in
combination with / (ignore contents) to enable or
disable parts of source code being compiled or not
during development in order to find errors for
example.
space No evaluation Generally everything that can not be interpreted
will be placed unchanged in the output. But only a
space character will be guarateed to work always
that way. Also in future versions of GAPP. Other
characters may become added for a special meaning.
So it is wise (not required) to add a space behind
every [ if no GAPP evealuation is intended.
Get used to these few commands, store them in your brain. If you are working with GAPP then these are your daily tools. There are only a few to learn here and that is by design. The next level of commands are gapp commands. Remembering them is simpler since these are full words. There is no limitation in number of possible gapp commands. The rest will be standard macro's, slang functions and server requests, issues I'll tell about later. But if you know about these commands and somewhat of the slang language you will benefit most from gapp. And,... very quickly!