Statements

Control

There are the usual flow-of-control statements:

if name == "anyone"
print-line: "Anyone"
 
if x == 0
return 0
else
return x * (factorial: x - 1)
 
return # No value given, so this returns "nil".
 
loop
token = next-token
if token type == 'eof'
break
consume-token
 
if token type == 'comment'
continue
 
while which-item < num-items
print-line: (items at: which-item)
which-item += 1
 
for item in items
if item name is-empty
continue
print-line: item name
 
try
event-loop
else
# "exception" is automatically defined as the caught object.
print-line: exception message
 
throw MessageException new: "Couldn't connect."
 
switch justification
'left'
# ...
'right'
# ...
'center', 'centered'
# ...
'justified'
# ...
else
throw MessageException new: "Bad justification: " + justification string
Expression Statements

An expression on a line by itself also constitutes a statement:

print-line: "Hello world!"
Assignment

Assignment in Trylon is designed to be easy to read (and type), but the rules behind it can be a little complex.

proto MyObject
fields total
 
grand-total = 0 # A shared variable, with its initial value.
 
reset
total = 0 # Sets the object's "total" field.
 
frobnicate: value
massaged-value = value * 7 + 3 # Creates a new local variable.
total = total + massaged-value # Sets the object's "total" field.
grand-total = grand-total + massaged-value # Sets the shared variable.

The basic idea is that an assignment will assign to a variable in the current scope, and if no such variable exists, a new local variable will be created. The scope of the new local is the block in which it is assigned.

Assignment can also be a shorthand for a function call:

(array at: 7) = "hello" # is the same as:
array at: 7 put: "hello"

If the function being set is a unary function, rather than a keyword function, then the setter function's name is the unary function's name with a colon appended:

proto MyProto
fields real-name
 
name
return real-name
 
name: new-name
real-name = new-name + " Jr."
 
obj = MyProto new
obj name = "Joey Jo Jo Shabbadoo"
print-line: obj name # Prints "Joey Jo Jo Shabbadoo Jr."

(Indeed, the compiler treats *all* assignments this way, even those to local variables. So "foo = bar" can always be written as "foo: bar".)

Assignments are expressions, so you can do things like "x = y = 0".

The "for" Statement

A "for" statement can iterate over any collection that responds to the "iterate" message with an iterator object that responds to the "is-done", "current-item", and "go-forward" messages. So this:

for item in collection
print: item string

is roughly equivalent to this:

iterator = collection iterator
while !iterator is-done
item = iterator current-item
 
print: item string
 
iterator go-forward

(I say "roughly" because the "continue" statement would work correctly in a real "for" loop, and because the "iterator" variable isn't visible.)

Conditional Compilation ("iff" Statements)

The "iff" statement is used for conditional compilation:

iff debug
print-line: "Reached a certain point."

In this case, "debug" is not an expression, but the name of a symbol. If that symbol is defined in the build-settings, the block will be compiled. If not (or if it's set to "false"), the block will be completely ignored by the compiler.

You can't use an "else" block with an "iff" statement (not yet, anyway), but you can put a "!" before the symbol to reverse the sense of the test.

version = "1.0 "
iff development
version += "development"
iff !development
version += "release"

A few symbols are defined automatically in the build-settings. Most notably, the "sysname" (what you'd see if you typed "uname" at the shell) is defined.

display = nil
iff Linux
display = XlibDisplay new
iff Darwin
# Mac OSX calls itself Darwin, for the purposes of "uname".
display = CarbonDisplay new

Also defined are "trylon-2" (to distinguish from Trylon 1; Trylon 3 also defines it), and "targeting-c" to distinguish the C backend from the other backends (like the now-deleted Jolt backend, or any future backends).