Skip to the main content of this page.
The sable mammal, Martes zibellina
SABLE Programming Language

Statements

Most SABLE language constructs describe expressions, which may be used as statements. Only a few statements are not expressions.

Pragmas and Attributes

Syntactically these are statements, usually helping to define the unit in which they appear as we've seen. Pragmas are sometimes used where executable code appears, to assert something about the program state, for example:

someMethod.
    |list| {LIST[INT32]}.
    "...Set :list; it should not be empty..."
    {~ assert: [list notEmpty]}
    "..."

Variable Declaration

We've already seen these repeatedly, a list of words in vertical bars, optional TypeRef, optional pragmas and attributes, optionally initialized. This construct is used to declare temporary variables and class data members.

When initialized, the type is usually omitted unless the variable type needs to differ from what's inferred, practically eliminating type redundancy. SUBSTITUTION_TESTER had such a case. A method local can even be declared typeless and uninitialized; its type will be determined from the next assignment to it. We'll see this later in POKER_CONSOLE>~>#playOneHand.

Result Statements

A method or block body may end with one of three different result statements, all of which were present in the substitution framework example. Any method which specifies a return type in its heading must end with one of these; it cannot simply drop off the end.

Return Statement

Within a method body, a single caret symbol introduces the return value, which must be assignable to the method's return type.

Methods with no return can exit early by returning Void. A contrived example is:

databaseConnect: connectionString {STRING?}.
    "Connect to the database referenced by :connectionString.
     Do nothing if it's Nil."
      connectionString isNil then: [^Void].
     "...Complex connection behavior goes here..."

Throw Statement

A throw statement begins with three carets together; the expression which follows is the {EXCEPTION} to throw. From our last example:

throw: message {STRING}  ^{NO_RETURN}.
    {~ cilName: 'Throw'}
    "Throw a SUBSTITUTION_EXCEPTION with the given message and
     the character position of the current Substitution Pattern."
     ^^^{SUBSTITUTION_EXCEPTION} newMessage: message charPosition: substPosition

No-Return Statement

The >#throw: method above uses type {NO_RETURN}. This is a special SABLE-defined type used as the "return" type of methods which do not return normally. This one always throws an exception. Another example from the core library is System.ENVIRONMENT>~>#exit: which terminates the program. Nothing is legally assignable to the {NO_RETURN} type, not even the "result" of another non-returning method. The method therefore cannot return at all; it must end with a Throw Statement or another No-Return.

terminateProgram  ^{NO_RETURN}.
    ^^System.ENVIRONMENT exit: 15

Normally, such methods include a comment, "This method does not return." Then when the method is invoked, the program must again document, "Does not return." The SABLE philosophy is to let such important facts be codified as part of the program, not written in comments. Let the compiler help us ensure program integrity, for example, that no useless statements follow a non-returning method invocation. Non-returning methods therefore must be invoked in a No-Return Statement, introduced by two carets together. Our last example used No-Returns in SUBSTITUTER>~>#substitute:into: and DOLLAR_SUBSTITUTER>~>#substitutionResult.