GP programs will be written, viewed, edited, and debugged as visual blocks in the GP programming environment most of the time. However, a textual representation of GP programs is useful for several things:
GP programs can be converted from blocks into text and vice versa. The textual representation is human readable but, since GP programs will be written and viewed graphically except during system bootstrapping, it's not essential that it be optimized for manual editing.
The rest of this article describes the current syntax of GP. It will be updated as the syntax is extended (e.g. to add support for floating point numbers).
GP currently supports only positive and negative integers such as:
123
-17
Internally, integers are 31 bits, so their range is -1073741824 to 1073741823.
String are enclosed in single quotes:
'Welcome to GP!'
and can contain newline characters:
'Welcome to GP:
a blocks-based programming language
for casual programmers'
To include a single quote character in a string, double it:
'It''s fun!'
There are no other escape sequences. Strings are Unicode, encoded as UTF8. (The 7-bit ASCII character set is a subset of UTF8.)
A symbol is like a string without the quotes:
print
A symbol cannot contain embedded white space, cannot start with a digit or minus sign, and cannot contain parentheses or curly braces, but it can contain symbolic characters:
+ - <= ||
As you can guess from these examples, symbols are used for function names and operators. Internally, symbols are represented as strings; GP does not have a separate Symbol class as Smalltalk-80 does.
Booleans and nil are represented as themselves:
true
false
nil
These represent true, false, and nil objects in GP. Thus, if you want a string containing one of these words you must quote it:
'true'
A command is an operation name (symbol) followed by zero or more parameters:
print 'GP rocks!'
A parameter can be either a literal value (a number, string, boolean, or nil), an expression, or a command list.
An expression is a command enclosed in parentheses:
(mouseX)
(abs -10)
(at myArray 1)
(+ 3 4)
Note that expressions, like commands, are an operation name followed by any parameters. However, binary operators such as '+' can also be written in the more familiar infix order:
(3 + 4)
Note that each expression, including binary expressions, must be enclosed in parentheses; unlike many other languages the GP parser does not do automatic grouping based on operator precedence:
(3 + (2 + 2)) correct
(+ 3 2 2) correct
(3 + 2 + 2) syntax error!
A command list is a sequence of commands, one command per line, enclosed in curly braces:
{
print 'How do elephants hide in cherry trees?'
sleep 5000
print 'They paint their toenails red'
}
Commands lists are used in control structures:
repeat 10 {
print 'Hooray!'
}
Since the opening curly brace is on the same line as the repeat command, the entire command list is the second argument of the repeat command.
Generally, each command in a command list is on its own line, similar to the layout of visual blocks. However, as a convenience, a command list with only one command can be written on a single line:
repeat 10 { print 'Hooray!' }
You can also combine multiple statements on a single line by separating them with semicolons:
print 'Hello'; print 'World'
However, be aware that when a textual GP program is converted to blocks and and then back to text, it may be reformatted to have only one statement per line, depending on the rules built into the pretty printer.
An unquoted string parameter to a command or expression is interpreted as a variable reference. Thus, one can write:
print x 'squared is' (x * x)
Internally, GP represents references to the variable "x" as:
(v 'x')
Thus, a variable reference is just an ordinary expression and the print statement above is simply a more readable equivalent of:
print (v x) 'squared is' ((v x) * (v x))
GP has two operators to set and change variables:
score = 0 set score to zero
score += 1 increment score by one
A comment starts with a pair of slash characters and runs to the end of the line:
score = 0 // reset the score
Comments are ignored by the GP parser.
Some GP commands and operators are variadic; that is, they accept a variable number of parameters. We've already seen that the print command can take an arbitrary number of arguments:
print '11 divided by 3 is' (11 / 3) 'with a remainder of' (11 % 3)
The + operator is also variadic. While it's infix form always takes exactly two parameters:
(1 + 2)
it's prefix form can be used to sum up any number of parameters:
(+ 1 2)
(+ 1 2 3 4 5 6)
(+ 42)
(+) // the sum of an empty list, which is 0
Other useful variadic operators include "*", and the logical operations "and" and "or". The system library includes additional variadic functions such as "min" and "max".
The "if" command is also variadic; it takes one or more pairs of (condition, statement list) pairs, similar to the "if ... else if ... else ..." statement found in many other languages. Here's an example:
if (n > 0) {
print 'n is positive'
} (n < 0) {
print 'n is negative'
} true {
print 'n is zero'
}
or, more concisely:
if (n > 0) { print 'n is positive'
} (n < 0) { print 'n is negative'
} true { print 'n is zero' }
Note that the close bracket for each statement list in this form must be placed on the following line to tell the GP parser that the statement continues to the next line.
While this may look a bit strange due to the lack of extra "else if" keywords, it's actually quite easy to read, and the missing "else if" keywords will be displayed when this code is converted to blocks.
The 'help' command with no arguments will print a list of all GP commands. Help with an argument will give you help -- and often a short example -- for a particular command:
help +