895.7
is a literal expression whose value is the real number 895.7.
InventoryRecord(5, 'M')
is a constructor expression that creates a new instance of the class
InventoryRecord
. (The values in parentheses are initialization arguments necessary to instantiateInventoryRecord
.) The expression's value is the new InventoryRecord object.
temperature = 72
is an assignment expression that assigns the integer 72 to the local variable
temperature
. Its value is 72, but this is a case where the resultant value isn't typically important--the assignment is the important part of the expression. (We assume in this example thattemperature
is a variable that can accept a value of 72. It may be an integer variable, for example.)
temperature
is an access expression whose value is the object assigned to the local variable
temperature
. If the variable was assigned the integer 72 as it was in the previous expression, this expression's value would be 72--the object specified by the variable.
365 + 12
is an operator expression that has the operator
+
to compute the sum of the two integers 365 and 12. It has the value 377, the result of the operation.
tireStore.order()
is a request expression that calls the operation
order
on an object namedtireStore
. Its value is whatever object is returned by the operation.
temperature@Integer
is an assertion expression that says to the compiler that the object specified by the variable
temperature
is a member of the classInteger
.
Notice in the preceding examples that one or more expressions may be used within a larger expression. The operator expression 365 + 12
, for example, uses the two literal expressions 365
and 12
as components along with the operator +
.
When you consider expressions, it's important to note that although they usually have a value (a specified object or the result of a computation), expressions occasionally have no value at all. For example, not all operations return results, so a request expression might not return a value. The value of such an expression would be nil.
Creating statements is a fundamental part of Telescript programming; we'll spend a large part of this book learning about actions that can be described within a statement. We'll also learn the Telescript keywords (listed in Appendix B) that control many of those actions. For now, we'll take a simple look at the form of a statement, and observe this basic rule of statement syntax:
Each statement must end in a semicolon.
The semicolon separates one statement from another and will do so, in fact, without a line feed between statements. If you have the evil inclination to do so, you can write a whole series of statements all in a single line of text--as long as the statements are separated by semicolons. As it turns out, putting line feeds in the text of Telescript code has no effect--other than legibility--unless it falls within a string or it's used to end a comment line (as described later in this chapter).
There is one exception to the semicolon rule: you don't need a semicolon after the final statement of a script or the final statement in a block (a sequence of statements contained within a pair of curly brackets). It does no harm to put a semicolon in either of these locations, however, and it's a good habit to put a semicolon at the end of each statement no matter where it falls.
Take a look at three typical statements in a snippet of Telescript code:
pause = timeKeeper.halt(25+waitTime); ledger.billTime(workTime); if pause >= 50 {dispatcher.notify();};The first statement calls the operation
halt
on an object named timeKeeper
. It supplies as an argument the expression 25+waitTime
, which adds 25 to whatever value is stored in the variable waitTime
. It then assigns the value returned by the operation to the variable pause
.
The second statement simply calls the operation billTime
on an object named ledger
. It supplies the value stored in the variable workTime
as an argument for the operation. If the operation returns a result, it's ignored here.
The third statement is a bit more complex. It tests the operator expression pause >= 50
to see if it's true. If so, it executes the statement in brackets that calls the operation notify
on an object named dispatcher
. If not, execution skips the statement in brackets. Notice that there are two semicolons at the end of this statement--one at the end of the nested statement (the statement in the brackets), the other at the end of the statement outside the brackets.
As you can see, each of these statements defines an action or a group of actions. Each statement ends in a semicolon. And the statements together define a set of actions and the order in which those actions are executed.
The third statement illustrates another important rule of statement syntax:
One or more statements may be nested within another statement.
If so, the nested statement (or statements) are enclosed in parentheses or brackets, as you'll read later.
ledger.billTime(workTime);This statement is simply an operation call on an object, which--as you may recall--is a request expression.
It's important to note that whenever an expression is used as a statement, any value it returns is usually discarded. In the previous example, if the billTime
operation returns a value, that value is ignored and is discarded as execution passes on to the next statement.
Expressions used as statements are typically operation calls. In an operation-call statement, the action described is the method that executes when the operation is called.
Another common expression often used alone as a statement is an assignment expression. The action described is the action of assignment.
Take a look at some examples of declarations:
tally: Integer; roscoe: Agent; temperature: Real = 98.6;In the first declaration, a variable named
tally
is created to refer to an instance of the class Integer
. In the second declaration, a variable named roscoe
is created to refer to a member of the abstract class Agent
. And in the third declaration, a variable named temperature
is created to refer to an instance of the class Real
(which defines real numbers); the variable is then assigned a value of 98.6.Notice that the semicolon rule of statements also applies to declarations: You must end each declaration with a semicolon unless it falls at the end of a script or a block. Notice also that each declaration starts with a string of characters--an identifier, used in later statements to refer to the variable. The identifier is followed by a colon and then a class name. The class name specifies the type of variable to be created. The third example shows an option of declaration: an assignment can be added to a declaration.
The three examples show a lexical convention of Telescript programming: Class names all start with an upper-case letter; all other names (including variables in this case) start with a lower-case letter. Note that this is strictly a programming convention--it's not enforced by the Telescript language.
You'll read about declaration syntax in detail in Chapter 6.
When a block is executed, each of its statements is executed in logical order, starting from the first statement in the block. Statements are executed consecutively unless a program-flow statement (such as the if
statement you saw earlier) branches the execution. The block's execution ends when the last statement in the block is executed, or when execution branches to a statement outside the block as the result of a program-flow statement.
The Telescript language doesn't require (as do other languages) that all declarations must appear at the beginning of a block of statements. Declarations may be interspersed throughout statements.
{ pause = timeKeeper.halt(25+waitTime); ledger.billTime(workTime); if pause >= 50 { dispatcher.notify(); timeKeeper.overTime = true; } else { timeKeeper.overTime = false; }; }The block contains two nested blocks within it. The first nested block is contained in the first half of an if/else statement (following the keyword
if
). That block isn't executed unless the expression pause >= 50
evaluates to true. The second nested block is contained in the second half of the if/else statement (following the keyword else
). That block isn't executed unless the expression pause >= 50
evaluates to false. (Don't worry about the syntax of the program-flow if/else statement for now. It will be covered in detail in Chapter 7.)roscoe
. One roscoe
will have no affect on the other. You'll find more details about the scope of variables in Chapter 7.Within a class definition you'll find a block of code for each of the class's methods. A method block starts execution when the method's operation is called. When the block finishes execution, the operation is completed.
You'll also find blocks used in program-flow statements (as you saw in the last code snippet) to define a distinct set of statements that may or may not be executed. In this role, a block provides a starting and ending point for optional execution.
You should also note that an entire script, whether it's enclosed in brackets or not, is considered a block by Telescript. Execution of the script starts at the first statement in the block and ends at the last statement. Any variables declared within the script are local only to the script.
/*
and */
, the other delimited by //
and a Line Feed (<LF>
). This code example uses both varieties:
{ pause = timeKeeper.halt(25+waitTime); ledger.billTime(workTime); if pause >= 50 { //Record the fact that the halt time was too long. dispatcher.notify(); timeKeeper.overTime = true; } else { /* Record the fact that the halt wasn't too long. This allows the timeKeeper to tally without debit.*/ timeKeeper.overTime = false; }; }Whenever the Telescript compiler encounters the opening delimiter of a comment (a
/*
or a //
), it ignores all the text following until after the closing delimiter of the comment (a */
or <LF>
respectively). Between comment delimiters you're free to ignore all the rules of Telescript syntax to make your code legible to other programmers--and to yourself when you later confront the code you wrote in a late-night deadline blur.
Note that it's easier to use comments bounded by /*
and */
if you're writing multiple lines of comments--you can put as many line feeds as you want in your comment text without adding new delimiters for each line of text. You can't, however, nest /* */
comments because the Telescript compiler thinks the first */
it encounters is the end of the outer comment. Use the //
comments for nesting--for example, if you turn statements of Telescript code into comments for debugging.
<SPACE>
), a horizontal tab (<HT>
), a line feed (<LF>
), or any number of these characters in any combination. Breaks in source code separate program tokens. A program token is one or more characters in source code that are interpreted by the compiler as a single programming element. An operator such as +
is a token, an identifier like mangos
is a token, a class name such as Agent
is a token, and so on.
You can put breaks anywhere before the first token, after the last token, or between tokens to make your code more legible. The examples of code you've seen thus far have had plenty of breaks--spaces, horizontal tabs, and line feeds--to format the text of the code. Breaks are optional between most tokens. For example, the compiler reads the expression 2 + 2
to mean the same thing as the expression 2+2
.
You must put a break between any two tokens that consist only of the characters in the ranges '0'
through '9'
, 'A'
through 'Z'
, and 'a'
through 'z'
. The break tells the compiler where one token ends and the next token begins. For example, consider the line
if pause >= 50from the last example code. Every break in this line is optional except for the break between
"if"
and "pause"
.#include
and #define
to include text in your code and to define abbreviations. If you're not familiar with C preprocessor directives, you'll find them described in any standard ANSI C text.
Generated with Harlequin WebMaker