Before starting, I realize that I haven't yet really told you what's the main use of an Amool class.
So I'll make a short explanation here:
An Amool class can be executed. When you do that, its text-contents
will be parsed and converted into a character stream.
Most of it will just be copied directely. However, words beginning with
"@" make the parser "branch" to another class.
This chapter explains how you can "call" your child definitions from the code, ie in the same way as you use a macro in a preprocessor.
All calls begin with the At (@) symbol, which is then followed by either the name of the child or a path to that class (if it can't be reached directely).
&+Example &+name John Smith && Hello, my name is @name :-) &&
So, this class defines a child named @name which contains the string John Smith, and it's text refers to that child. So, when executing that class, you will get:
Hello, my name is | @name | :-) |
![]() | ||
John Smith |
Hello, my name is John Smith :-)
When the child is not reachable directely (ie, is not a child of the current class, but for
instance a child of a child), you have to write a path of symbols, separated by dots (.).
The compiler will search for the first symbol, and when found, it will search for the second one
from the found class, and so on until it reaches the last symbol of the path, which will
be the class that wil be executed.
For instance, the following call:
@myGui.myWindow.preferenceArea.string.defaultValue
will search for a class named defaultValue, child of a string, child of preferenceArea, itself child
of myWindow, child of myGui, child of the current class.
Currently (I have not yet really found anything that satisfies me), when referencing a symbol that has multiple definitions, a random one will be returned! You can access all of them using the built-in class @amool.internal.forAll (see built in classes for details)
When I tell you about inheritance, and child contribution, this will get important. For now, the context
is always changed to the class being executed.
This means that when you call a class from inside another one, the context will change to the latter,
and when it is over, it will be set back to the caller.
&+Hello &+One &+name John && Hi, I'm @name && &+Two &+name Bob && Hello World, My name is @name && @One.name says: @One @Two.name says: @Two &&
Executing the class Hello will return:
@One.name | says: | @One | @Two.name | says: | @Two | ||
![]() | ![]() | ![]() | ![]() | ||||
John | Hi,I'm | @name | Bob | Hello World, My name is | @name | ||
![]() | ![]() | ||||||
John | Bob |
John says: Hi, I'm John
Bob says: Hello World, My name is Bob
So the parser first executes the string
@One.name
To do that, it looks for a class named @One in the current context, and finds
the one defined just above it. So it changes the context to it. Then it looks
for a child named @name, in that context, and finds the one defined as John.
Now it sets the context to that class, and executes its contents, which is John,
precisely.
So then it goes back to the class Hello, and executes says:, which is directely
written to the output. Then it sees @One, so it looks for the child named
@One, finds it, and branches to it. Then it executes the contents of that child.
Hi, I'm @name is therefore executed, having the class @One as context.
And so on :-)