File: usrguide.sgml

package info (click to toggle)
tela 1.28-2
  • links: PTS
  • area: main
  • in suites: slink
  • size: 6,596 kB
  • ctags: 5,519
  • sloc: ansic: 14,013; cpp: 13,376; lex: 1,651; fortran: 1,048; yacc: 834; sh: 715; makefile: 464
file content (1155 lines) | stat: -rw-r--r-- 48,713 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
<!doctype linuxdoc system>

<!-- Tela User's Guide in SGML format -->
<!-- ================================ -->

<article>

<!-- Title information -->
<!-- ================= -->

<title>Tela User's Guide <author> Pekka Janhunen,
<tt/tela-suggestions@fmi.fi, tela-bugs@fmi.fi/
<date>v1.21, 13 February 1995

<!-- Table of contents -->
<!-- ================= -->
<toc>

<!--  ************ -->
<sect>Introduction
<!--  ************ -->

<p>
Tela is a numerical computing environment mainly targeted for
numerical simulation pre- and postprocessing work. The language
supports arbitrary rank arrays (hence the name, Tensor Language), and
has powerful programming capabilities including F90 style vector
notation.

The on-line help is intended to be the primary source of
documentation.  The command <bf/help/ (<ref id="cmdhelp" name="help">)
gives help of reserved words, intrinsic functions, standard functions,
and user functions. The function docview() can be used to view the
same documentation in plain ASCII form, in TeX DVI form, and in
Hypertext Markup Language (HTML) form. Right from the beginning you
should be familiar with the <bf/help/ command, and learn to browse the
HTML documentation. If you want a printed ``manual'', you can convert
the DVI files into PostScript using the standard TeX tool <bf/dvips/
and print them.

The file you are now reading is the User's Guide. Other relevant document files
include <url url="html:telahelp.html" name="telahelp">,
<url url="html:telafuncs.html" name="telafuncs"> and
<url url="html:telafuncsSectioned.html" name="telafuncsSectioned">.
The <bf/help/ (<ref id="cmdhelp" name="help">) can retrieve the equivalent information.

(For Xmosaic viewers only: If the previous links do not work, you can
try the universal links to the FMI/GEO WWW site:
<url url="http://www.geo.fmi.fi/prog/tela/telahelp.html" name="telahelp.html">,
<url url="http://www.geo.fmi.fi/prog/tela/telafuncs.html" name="telafuncs.html">
and <url url="http://www.geo.fmi.fi/prog/tela/telafuncsSectioned.html" name="telafuncsSectioned.html">).

<!-- Send Tela bug reports to <tt/tela-bugs@fmi.fi/. -->
<!-- Send suggestions to <tt/tela-suggestions@fmi.fi/. -->

<!--  ********************** -->
<sect>Simple interactive use
<!--  ********************** -->
<p>

When you start Tela from the Unix prompt without arguments (usually by
typing <bf/tela/), the system enters interactive mode after reading
some initialization files and is ready to parse and execute command
lines. The Tela prompt is ``&gt; ''. The GNU Readline library is the first
layer interacting with the user. This library makes it easy to modify
and reexecute previous commands. The most important key combinations
are (Ctrl means keeping Control down when pressing the key):

<tscreen><verb>
Ctrl-P         Get Previous line
Ctrl-N         Get Next line
Ctrl-F         Forward cursor one character position
Ctrl-B         Backward cursor one character position

Ctrl-A         Set cursor position at beginning of line
Ctrl-E         Set cursor position at End of line
Ctrl-K         Delete (Kill) text beyond cursor position

TAB            Try to complete reserved word, identifier or filename
Enter          Execute command line (cursor need not be at end position)

Ctrl-C         Interrupt command during command execution
Ctrl-D         Quit Tela (must be alone in line)
</verb></tscreen>

You have probably used other software which also uses the GNU Readline
library, e.g. the GNU debugger <bf/gdb/. If your terminal is properly
configured, you can use the arrow keys instead of Ctrl-P, Ctrl-N,
Ctrl-F and Ctrl-B to move in the history buffer. You should get
familiar with these commands as soon as possible, since it will
greatly speed up your working with Tela. The command completion is
able to complete Tela reserved words, function names (either
intrinsic, standard, or user-defined), variables names and
filenames. Filename completion is invoked if the TAB key is pressed
inside a string (``...''). This can be useful with the <bf/source/
command, for example.

Tela uses the X window system to display graphics. The graphics is
displayed by a separate program, named PlotMTV, but calling it is
transparent to the user. The DISPLAY environment variable must be
properly defined, otherwise the graphics will not work.

Try entering the following commands first (``&gt; `` means the Tela prompt
which you obviously do not type):

<tscreen><verb>
> x=0:0.1:4*pi
> plot(x,sin(x))
</verb></tscreen>

The first command creates a vector of real numbers ranging from 0 to 4
times Pi with step 0.1 and assigns the vector to variables x. The
second command then plots sin(x) versus x. A graph of sin(x) should
appear in a new PlotMTV window, if not, the system is not properly
installed.

In Matlab, an expression is printed if there is no semicolon at the
end of command line.  In Tela, however, an expression is printed if it
is not assigned to any variable, regardless of any semicolon. In fact,
Tela internally inserts a semicolon at the end of every command line
before actually parsing it. The insertion is not done when reading
commands from a file.

This leads us to the next topic: how to execute commands from a file.
Type

<tscreen><verb>
> source("demo")
</verb></tscreen>

A menu of choices appears, but let us first explain what the
<bf/source/ command does. It looks for file named ``demo.t'' in the
current TELAPATH (if the file name contains a period, the ``.t'' is
not appended). The TELAPATH is a list of directories where input files
are searched, similar in function to the Unix PATH. The file
``demo.t'' is found in some standard directory and commands in it are
executed. The current TELAPATH can be seen by giving the command
<bf/telapath()/.

When reading commands from a t-file, there should be a semicolon at the
end of each statement (or actually separating the consecutive
statements, but the difference is unessential here).

OK, now play with the demos. Press a number and ENTER to the menus, to
get back to command level select Quit.

The typical and recommended way to use Tela when developing something
bigger than one line is the following: Open an editor window and a
shell (Xterm) executing Tela on your workstation. Create a t-file, for
example ``mine.t'' with the editor and write some Tela commands in
it. Remember to use semicolons as statement separators. Try it out by
typing <bf/source(``mine.t'')/ in the Tela window. You must have
started Tela from the same directory where ``mine.t'' lies, or you can
use the Tela <bf/cd/ command to change to that directory. (See
<bf/help cd/.) Doing this repeatedly you only need save the file from
the editor and press Ctrl-P ENTER in Tela window to execute the file
with changes you just made. This is only slightly clumsier than
program development with Turbo Pascal in the old times: instead of a
single keypress you now have to press three keys and switch the window with
the mouse once to execute the program!

<!--  ********************** -->
<sect>Basics of the language
<!--  ********************** -->
<p>

The first thing to be mentioned about the Tela language is that it is
in many respects similar to C, or C++. So much so that I usually use
the GNU Emacs C++ mode to edit Tela code, since there is not a
specific Tela mode (maybe you could contribute one?).  There
is an <bf/if/ statement (<ref id="cmdif" name="if">), a <bf/while/
statement (<ref id="cmdwhile" name="while">) and a <bf/for/ statement
(<ref id="cmdfor" name="for">). There are of course many syntactic
differences also, but two of them are the most fundamental:

1. In C, a semicolon ends a statement whilst in Tela a semicolon is a
separator between successive statements. Tela's use of semicolons is
equivalent to Pascal rather than C in this respect. This means for
example that the right brace is usually followed by a semicolon in
Tela, or at least that a semicolon does no harm there.

2. In C the assignment is an operator, i.e. <em/a=b/ is syntatically
an expression not a statement. In Tela the assignment is a statement.
This is also similar to Pascal. This implies that the use of
assignment is more restricted in Tela than it is in C or C++.

<sect1>Flow of control statements
<!--   ************************** -->
<p>

The following subsubsections describe the Tela control structures.

<sect2><heading><label id="cmdif">The if statement</>
<!--   =========================================== -->
<p>

The <bf>if</bf> statement has the following syntax (<em/stmt/ = statement):

<tscreen><verb>
if (expr)
   stmt
</verb></tscreen>

or

<tscreen><verb>
if (expr)
    stmt
else
    stmt
</verb></tscreen>

The conditional expression <em/expr/ must be enclosed in parentheses.
There must be no semicolon between <em/stmt/ and <bf/else/.

The expression must evaluate to integer scalar or array. The condition is
considered true if the scalar is nonzero or if all the array elements are
nonzero. Examples:

<tscreen><verb>
if (x!=0)
    format("x is nonzero, x=``\n",x)    // notice no semicolon
else {
    x = 1;
    format("x was zero and is now 1\n");// this semicolon is optional
};  // this semicolon separates this if stmt from the next stmt, if any
</verb></tscreen>

Nested <bf/if/ statements are written in the following style:

<tscreen><verb>
if (a == 1) {
    /* action for a==1 */
} else if (a == 2) {
    /* action for a==2 */
} else if (a == 3) {
    /* action for a==3 */
} else {
   /* action for none of the above */
};
</verb></tscreen>

<sect2><heading><label id="cmdwhile">The while statement</>
<!--   ================================================= -->
<p>
The <bf/while/ loop statement has the following syntax:

<tscreen><verb>
while (expr)
    stmt ;
</verb></tscreen>

For example:

<tscreen><verb>
    while (!found) {
        LookForIt();
        counter++
    };
</verb></tscreen>

The statement is executed until <em/expr/ evaluates to true.
The "trueness" of <em/expr/ is similar to the <bf/if/ statement (<ref
id="cmdif" name="if">): a scalar and all elements of an integer array
must be nonzero for <em/expr/ to be true.

<sect2><heading><label id="cmdrepeat">The repeat statement</>
<!--   =================================================== -->
<p>
The <bf/repeat/ loop statement has the form

<tscreen><verb>
repeat
    stmt1;
    stmt2;
    ...
until expr;
</verb></tscreen>

The statements <em/stmt1/, <em/stmt2/, ... are iterated until <em/expr/
evaluates to true (nonzero). The statements are always executed at least
once. It is analogous to the <bf/repeat/ statement in Pascal.

<sect2><heading><label id="cmdfor">The for statement</>
<!--   ============================================= -->
<p>
The <bf/for/ loop statment has the form

<tscreen><verb>
for (initstmt; expr; updatestmt) stmt;
</verb></tscreen>

It is equivalent to the <bf/while/ statement
<tscreen><verb>
initstmt;
while (expr) {
    stmt;
    updatestmt;
};
</verb></tscreen>

The syntax is rather similar to C, but there is a difference:
the <em/initstmt/, <em/updatestmt/ and <em/stmt/ are statements,
not expressions. On the other hand there is no comma operator in Tela.
Thus you cannot write <bf/for(i=0,j=0; i<10; i++)/ but instead you
must write

<tscreen><verb>
for ({i=1; j=1}; i<=10; i++) { /* ... */ };
</verb></tscreen>

We intentionally changed the loop running from 1, not 0, to remind 
that in Tela the first array index is 1, not 0 as in C.

<sect1>Expressions and assignments
<!--   *************************** -->
<p>

The following subsubsections describe Tela expressions and assignment statements.

<sect2><heading><label id="cmdexpr">Operators</>
<!--   ====================================== -->
<p>
Expressions are composed of atomic expressions and operators.  Atomic
expressions can be variable names, literal constants (integers, reals,
imaginary constants, characters, array constructors, and strings),
function calls, or array references. Operators usually obey the precedence
rules in other programming languages where possible. The operators are,
from lowest to highest precedence:

<tscreen><verb>
Operators       Associativity       Meaning
---------       -------------       -------
:               non-associative     Vector creation
||              left                Logical OR
&&              left                Logical AND
== !=           left                Equality and nonequality
> >= < <=       left                Greater than etc.
+ -             left                Addition and subtraction
* ** / mod      left                Pointwise multiplication,
                                      matrix multiplication,
                                      pointwise division,
                                      modulus operation
- +             non-associative     Unary minus and plus
^               right               Exponentiation
!               non-associative     Logical NOT
.' '            non-associative     Transpose, Hermitian transpose
</verb></tscreen>

In Fortran, the operator <bf/**/ would be exponentiation, in Tela it
is matrix multiplication. In C <bf/&circ;/ would be logical XOR, in
Tela it is exponentiation. In Matlab <bf/*/ denotes matrix
multiplication and <bf/.*/ pointwise multiplication, in Tela <bf/*/ is
pointwise multiplication and <bf/**/ is the matrix product. There are
no matrix power and division operators in Tela as there are in
Matlab. The equivalent of matrix division in Tela is the function
<bf/linsolve/. The vector creation operator uses the notation
<bf/a:step:b/, which follows the Matlab convention. In Fortran-90 the
step is the last member, <bf/a:b:step/. The set of operators is the
same as in C, with the addition of vector creation, matrix
multiplication, modulus, exponentiation, transpose and Hermitian
transpose operators. These additional operators follow Matlab
conventions except for the difference in pointwise and matrix nature
of multiplication.

<sect2><heading><label id="cmdexpr">Atomic expressions</>
<!--   =============================================== -->
<p>
Atomic expressions can be:

<tscreen><verb>
variable names         a, b_89, $x, $_x9$
integer constants      0, 23
real constants         1.23, 4.5E3, 0.03
imaginary constants    1.23i, 4.5E3i, 0.03i
characters             'a'
array constructors     #(1,2,3), #(a,b; c,d)
strings                "with possible escape sequences\n"
function calls         f(), f(1), f(a+b,g(c))
array references       a[i,j], a[1], a[1:imax,2:jmax-1]
mapped references      a<[i,j]>, a<[1]>
</verb></tscreen>

Variable names, or any identifier names for that matter, start with a
letter. The rest of the characters can also be digits or underscores.
The dollar sign is also accepted as a ``letter'' in identifiers.

Imaginary constants are obtained from real constants by appending
<bf/i/ with no intervening white space. There is no explicit notation
for complex constants, you must use the addition or subtraction
operators as in <bf/2+3i/ or <bf/0.5-0.75i/. The way to denote the
imaginary unit ``i'' is to write <bf/1i/. Notice that ``i'' here is
part of the syntax. There is no predefined variable or constant named
``i'', and 2+3*i will generally not work as expected (unless you have assigned
<bf/i = 1i/, but this is not recommended).

Character constants are equivalent to their ASCII codes (integers) if
used in arithmetic expressions. This practice is similar to C.

Array constructors are a bit more complicated. Syntactically
an array constructor has the form <bf/&num;(/<em/component-list/<bf/)/,
where <em/component-list/ consists of expressions separated by commas
and/or semicolons. Commas denote appending the components to form
a vector. For example, <bf/&num;(1:5,10)/ will produce the integer vector
<bf/&num;(1,2,3,4,5,10)/, and <bf/&num;(1,2.3,4:-1:1,34)/ produces
<bf/&num;(1, 2.3, 4, 3, 2, 1, 34)/. The last example gives a real vector
because one of the components was fractional number.

A semicolon in the array constructor denotes composing a higher-rank
array of the components, which must be lower-rank arrays (or scalars).
For example, a matrix can be constructed from its row vectors <bf/v1/
and <bf/v2/ by <bf/&num;(v1;v2)/. The precedence of a semicolon inside
array constructor is lower than the precedence of a comma, thus
<bf/&num;(a,b; c,d)/ will construct of 2x2 matrix.

The array constructors work for higher rank arrays as well.  The
result of array constructor using commas has rank equal to the highest
rank of the components, and the ranks of the components may not differ
by more than one. The important exception is the case where all the
components are scalars; in this case the result is a vector. The semicolon
array constructor always produces a result which has rank one greater than
the rank of the components, which must be same for all components in
the semicolon case. Using array constructors for higher-rank components
has been rare in practice.

Notice that the commas and semicolons have completely different meaning
inside array constructors than outside them.

Strings may contain escape sequences similar to C language strings.

Array references follow the Pascal syntax, separating the dimensions
with a comma. The indices may be vectors, which follows the Fortran-90
and Matlab array syntax ideas (``gather'' operations).

In addition to normal array references, Tela also supports <em/mapped/
array references. In mapped referencing the index objects must all agree
in type (they are usually arrays). The number of indices must be equal
to the rank of the indexed array and the result will have size equal to
an index object. For example,

<tscreen><verb>
A<[1:5,1:5]>
</verb></tscreen>

will produce the first five diagonal elements of matrix A as a vector.
Mapped indexing can be used to extract N-dimensional component subsets
from M-dimensional arrays, both N and M being arbitrary. The function
<bf/intpol/ (linear interpolation) can be thought as a generalization of
mapped indexing, where the ``index'' expressions need not be integers.

<sect2><heading><label id="cmdexpr">Assignments</>
<!--   ======================================== -->
<p>
Assignments can take the following three forms:

<tscreen><verb>
variable = expr ;

variable[index1,...] = expr ;

[var1,var2,...] = fname(expr1,expr2,...) ;
</verb></tscreen>

The first form is a simple assignment, where the value of the
expressions is assigned to a variable. The second form is the
``scatter'' operation, or indexed assignment. The indices follow the
same rules as if the array reference appears on the right-hand-side of
an assignment (see previous subsubsection).

The third form is actually not an assignment but a function call with
several output arguments a la Matlab.  The output variables must be
separated by commas (In Matlab the commas may be left out.) The output
variables must be simple identifiers, not expressions. For example,
you cannot say

<tscreen><verb>
[b[1],b[2]] = f();         // WRONG!!!
</verb></tscreen>

You must use auxiliary variables, as in

<tscreen><verb>
[b1,b2] = f();
b[1] = b1; b[2] = b2;
</verb></tscreen>

There are some chances that this limitation might be removed in some
future version.

<sect1>Defining functions
<!--   ****************** -->
<p>

Examples of function definition statements:
<tscreen><verb>
function f() { /* body */ };     // the simplest form

function f(x) { /* body */ };

function y=f(x) local(a) { /* ... */; y = sin(x) };

function [x,y] = f(a,b) { /* ... */ };

function [x,y;z,w] = f(a,b;n) global { /* ... */ };
</verb></tscreen>

The definition always begins with the reserved word <bf/function/.
After <bf/function/ comes the output argument specification (possibly
empty), followed by the function name and input argument list,
possible <bf/local/ or <bf/global/ declarations and finally the
function body enclosed in curly braces.

Input arguments are passed by reference. They may not be modified in
the function body. (If you try, you get a warning message.) Thus the
calling program may <em/think/ that the input arguments are passed by
value even though they actually aren't. In C++ the type of the input
arguments would be <bf/const Ttype&amp;/, and in Fortran-90 they would
correspond to the ``intent input'' arguments. Input arguments are
listed following the function name both when defining and calling a
function.

Output arguments are listed in brackets before the ``<bf/=/'' sign 
and the function name both in definition and calling phases. If there is
only one output argument, the brackets may be dropped (see the third example
above). Output arguments are also passed by reference, but obviously
they may and should be modified by the function body.

By default, input arguments are obligatory and outputs arguments are
optional. That is, the calling program must supply all input arguments,
but it may leave out some or all of the output arguments. For example,
if <bf/f/ is defined as

<tscreen><verb>
function [a,b,c] = f(x,y) { /* ... */ };
</verb></tscreen>

all the following are legal call forms for <bf/f/:

<tscreen><verb>
[X,Y,Z] = f(2+3i,sin(X+y));     // use all output arguments

[X,Y] = f(1,2);     // ignore the third output argument

X = f(1,2);         // ignore second and third

[] = f(1,2);        // ignore all
</verb></tscreen>

The default behavior of obligatory and optional arguments can be
changed by using the semicolon inside argument list. At most one
semicolon may appear inside an argument list. The rule is simple:
all arguments <em/before/ the semicolon are obligatory, that is,
required, and all arguments <em/after/ the semicolon are optional.
This rule applies to both input and output argument lists.
Examples:
<tscreen><verb>
function f1(x,y;z,w) { /* ... */ };

function [a;b] = f2(x,y) { /* ... */ };

function [a;] = f3() { /* ... */ };

function [a;b] = f4(x;y) { /* ... */ };
</verb></tscreen>

Function <bf/f1/ has two obligatory input arguments and two optional ones.
It has no output arguments. (It is, however, permissible to assign the
``value'' of <bf/f1/ to a variable as in <bf/x=f1(0,0)/. The variable <bf/x/
has the void value after the assignment. The void value may be created
explicitly by using an expression consisting of just the colon ``<bf/:/'',
and it doesn't output anything when printed.)

Function <bf/f2/ has to obligatory input arguments, since there is no semicolon
in the input argument list. One of the two possible output arguments is obligatory
and the other one is optional. Function <bf/f3/ has no input arguments but one
obligatory output argument. Notice that the semicolon may be also the first or
last thing in the argument list. Finally, function <bf/f4/ has both input and
output optional and obligatory arguments.

Whether or not an optional input argument is present can be tested
e.g. by the standard function <bf/isdefined/, which returns 1 if the
argument is defined and 0 if it is undefined. The test will fail also
if the caller supplied the argument but it was bound to an undefined
variable; this behavior is usually what is wanted since passing an
undefined variable as argument is practically the same as not passing
any argument at all.

The role of obligatory and optional input arguments, and also the
meaning of optional output arguments, is clear. But what about
obligatory output arguments, why should anyone want to use such
things?  The answer is simple: they correspond to arguments that are
<em/both/ input <em/and/ output. By making an output argument
obligatory you force the caller to bind it to some variable, which
probably has some initial value that the function body may use.

Maybe we should pause for a while and recall the important concepts
introduced in this subsection. By default, input arguments are
obligatory and output arguments are optional. How it could be
otherwise? Input arguments are read in the function body, so they may
not be undefined. By making the output arguments optional by default
we allow the caller the freedom to ignore some output arguments.  The
semicolon modifies the default behavior. Everything to the left of the
semicolon becomes obligatory and everything to the right of the
semicolon becomes optional. Input/output arguments should be declared
as obligatory output arguments.

There is still one thing about function declaration, namely the
<bf/global//<bf/local/ declaration that may be placed in between the input
argument list and the function body. The declaration may take one of
four possible forms:

<tscreen><verb>
local           // Everything is automatically local. The default.
global          // Everything is automatically global.
local(a,b,...)  // The listed symbols are local, others are global.
global(a,b,...) // The listed symbols are global, others are local.
</verb></tscreen>

All ``free'' symbols that appear in the function body are either local
to the function or global. ``Free'' symbol means a symbol which is not
one of the input or output arguments, has not been declared autoglobal
using the standard function <bf/autoglobal/, and is not used as a
function name in the function body. By default, all free symbols are
local.  This corresponds to the Matlab convention. By inserting the
word <bf/global/ with no variable list, however, you can make all
free symbols refer to the globally visible symbols. By inserting
<bf/local(a,b,...)/ you declare the listed symbols as local; other
symbols remain global. This corresponds to the practice normally used
in compiled languages such as C, C++ and Pascal.  And finally, by
using the <bf/global(a,b,...)/ declaration you can use the
complementary approach where every symbol <em/except/ those listed are
local.  The last case again mimics Matlab with global declaration.

Thus you can choose among different strategies here. In some functions
it is more natural to list the local variables rather than the global ones,
if not for other reason but because sometimes the local variables are less
in number than global ones, and vice versa. The most improtant thing to
remember is to remember: Think about global/local every time you define
a new function. The experience is that many, maybe even most, error situations
in Tela arise from forgetting to properly declare a variable global or local.

The system has some autoglobal variables, which are always global even
if they are not explicitly declared. Among these are constants such as
<bf/pi/, <bf/Inf/, <bf/eps/, <bf/on/, <bf/off/, and some color and
line style names. Thus it is unnecessary to say <bf/global(pi)/ if
<bf/pi/ is used in a function. It is possible to override the
autoglobal character by explicitly listing the symbol in <bf/local/
declaration; for me it is bad programming style however.

On trick that can be useful when developing code is to at first make
most variables global. In this way they are available in the workspace
for inspection after the function has completed execution or stopped
in runtime error.  When the function is working you can then make as
many symbols local as possible.

<sect1>The package mechanism
<!--   ********************* -->
<p>

Typically in Tela you write a t-file with many, maybe a few tens of
functions. Sometimes the functions need to communicate among
themselves not only via arguments but also via global variables, as in
Pascal or C. For example if you are developing a fluid simulation code
the values of physical parameters such as grid spacing, viscosity etc.
are most naturally declared global and not explicitly passed to every
function that uses them. We have been taught that using globals is bad
programming style, however, in this case it actually increases the
modularity of the program because if you introduce more physical
parameters you need not change the call form and definition of every
function.

Problems may arise if you use such a t-file in conjunction with other
t-files. The global variables then share the same name space. Also the
internal auxiliary function names may be the same in two t-files. One
solution would be to use untypical symbol names, but this is not elegant.

The keyword <bf/package/ is there to hide internal symbol names from
external access. The use is very simple. Just enclose the whole t-file
in curly braces and put <bf/package global(var1,var2,...)/ in front.
In the list you should put all symbol names that you want to be externally
visible. Usually these are function names, but they may also be (global)
variable names. All other symbols are then put in a private name space
and they correspond to the <bf/static/ variables in C and C++.

It is also possible to use <bf/package local/ declaration as a complementary
approach, in analogy with global/local in function definition, but this form
is rarely used in practice. You may also put a character string between
<bf/package/ and <bf/global/ or <bf/local/ to name your package. This would
be required if you want to put stuff from more than one t-file in one and
a same package. Actually, if the string is left out, the fully qualified
t-file name is used as a unique package name.

Despite the syntactic similarity of global/local in package declaration and
function definition, the meaning is quite different. Symbols which are local
to a package are usually global to functions inside the package. (If they are
also local in the functions, declaring them local in the package context does
not make any difference.) Local variables in a function are currently implemented
as slots in a runtime stack, whereas global symbols (in the function sense)
are bound to workspace variables, which have name, value and attributes.
The only thing the <bf/package/ mechanism does is that it prepends to all local
(in the package sense) symbol names an invisible string which is unique to every
package. This way the variables are physically in the same global hash table but
with unique names.

<!--  *************** -->
<sect>Writing t-files
<!--  *************** -->

<p>

Tela source files (t-files, filenames ending with ``.t'') consist of
Tela statements separated by semicolons. A function definition is just
one type of statement in Tela, thus you can define as many functions
in one t-file as you wish. This feature sets Tela apart from Matlab,
where each M-file always defines only one function. Functions become
defined in the code generation phase. For this reason the order in
which the functions appear in the t-file is unessential, and a
function call may textually precede its definition. Whether this is
good programming style is up to you. Usually there is no point in
putting function definitions inside other functions; if you do it, the
result is the same as if it were a toplevel definition.

Examples of t-files can be found in /usr/local/lib/tela/t, or
whereever you have installed Tela. It is a bit difficult to give a
simple meaningful example which defines multiple functions. A
comprehensive example is provided by the file ``madala.t'', for
example. It also uses the <bf/package/ mechanism to make it a clean
entity that does not unnecessarily conflict with other packages' name
spaces.

<!--  **************************** -->
<sect>Program code representations
<!--  **************************** -->

<p>
Thus far we have used and studied only one form of existence of our
programs, namely the native Tela source code (t-files and command
line). Both internally and externally, programs exist in other forms
too. Here is a complete list of all code representations in Tela:

<verb>
- t-code (the native Tela code)
- "TreeCode" (internal representation for t-code)
- "FlatCode" (another internal representation for t-code)
- C-tela code (code similar to C++)
- Compiled object code (machine language)
</verb>

When a program is <bf/source/'d (<ref id="fnsource" name="source">) in or when a
command line is typed, a lexical analyzer first breaks it in tokens,
that is, keywords, separators, numbers, identifiers etc. The output of
the lexical analyzer is a stream of tokens without hierarchical
structure. A parser continues to produce a treelike representation,
the TreeCode. The TreeCode is no longer a stream but has structure in
it. TreeCode is immediately translated into FlatCode, which is a
sequence of virtual machine instructions that the Tela kernel can
understand, and it is reminiscent to assembly language. You can see
both TreeCode and FlatCode representations of your input by setting
the VerboseMode on:

<tscreen><verb>
>VerboseMode(on)
0
>1 + 2.3*pi
BLOCK[SET[PLUS[1,TIMES[2.3,pi]]],NOP]
Source file: "stdin"
no input args, no output args, no locals, stack frame size 1.
Maximum number of operands is 3.
0       MUL     $0,2.3,pi
4       INC     $0
6       PRI     $0
8.22566
</verb></tscreen>

Alternatively, you can invoke Tela with the --verbose or -v flag. The
FlatCode of any <em/source/'d (<ref id="fnsource" name="source">) function can be
seen by using <em/disasm/ (<ref id="fndisasm" name="disasm">):

<verb>
>disasm(mean)
Disassembly of 'mean', Source file: "std.t"
1 input arg, 1 output arg, no locals, stack frame size 4.
Maximum number of operands is 4.
0       CALL    sum,1,$3,$1
5       CALL    length,1,$0,$1
10      DIV     $2,$3,$0
</verb>

The definition of <em/mean/ is

<verb>
function y = mean(x)
// mean(x) computes the arithmetic mean of a numeric array x.
{
    y=sum(x)/length(x)
};
</verb>

and you can easily guess what each of the FlatCode instructions do.

C-tela code is another way to write new functions for Tela. Many Tela
builtin functions are written in C-tela; those which are not are
either in native t-code or are so-called intrinsic functions (meaning
that they generate virtual machine instructions directly like macros).
C-tela code can be compiled into object files using the program
<bf/telakka/ (<ref id="telakka" name="telakka">). The object files can
be either statically or dynamically linked with the rest of the Tela
kernel.

There exists a standard function <em/t2ct/ (<ref id="fnt2ct"
name="t2ct">) to translate t-code into C-tela code. The conversion is
made possible by the fact each FlatCode instruction can be made to
correspond simple C-tela codings. As of this writing, however, the
Tela compiling scheme is still somewhat incomplete and under
development. When it is fully functional, you can go all the way from
t-code down to object code automatically.

<!--  ******************** -->
<sect>Writing C-tela files
<!--  ******************** -->

<p>
C-tela files are C++ code equipped with Tela's function header
syntax.  There is a preprocessor, ctpp, that translates C-tela in
ordinary C++.  Calling ctpp is the responsibility of the tool program
<bf/telakka/ (<ref id="telakka" name="telakka">).

Let us begin with an example of a C-tela source file (let it be
mine.ct):

<tscreen><code>
// Our first C-tela example

[] = myfn(x)
/* myfn(x) checks that x is a positive scalar and outputs it.
   Error codes:
   1: x is not a positive scalar */
{
    if (!x.IsScalar()) return 1;
    switch (x.kind()) {
        case Kint:
            if (x.IntValue() <= 0) return 1;
            break;
        case Kreal:
            if (x.RealValue() <= 0) return 1;
            break;
        case Kcomplex:
            return 1;
        default:
            return 1;
    }
    cout << "myfn: x = " << x << '\n';
    return 0;
}

</code></tscreen>

You can compile it using <bf/telakka/ (<ref id="telakka" name="telakka">):

<tscreen><verb>
unix> telakka -c mine.ct
</verb></tscreen>

Then from Tela you can link the object file and test myfn as follows.

<tscreen><verb>
>link("mine.o")
>help myfn
myfn(x) checks that x is a positive scalar and outputs it.
>myfn(2)
myfn: x = 2
>myfn(-2)
Warning from C-function 'myfn':
  x is not a positive scalar.
>myfn(2+3.4i)
Warning from C-function 'myfn':
  x is not a positive scalar.
>myfn(#(1.2,3,4))
Warning from C-function 'myfn':
  x is not a positive scalar.
</verb></tscreen>

There are several points to be noticed with this simple example:

<verb>
- The function is declare using the [...] = f(...) type syntax.
- The /* ... */ comment immediately following the header is "hot".
  The Tela help command finds and displays the comment, up to line
  "Error codes:".
- The function should return zero on success, positive integer on
  nonfatal error and negative integer on fatal error. The error codes
  should be listed in the comment, following, one per line, the
  "Error codes:" line.
- All C++ constructs are available, in addition several classes and
  their associated members from Tela headers. The function arguments
  ("x" in our case) are of type Tobject and they can be e.g. outputted
  using cout << x.
</verb>

Rules for argument syntax are very similar to those found in Tela.
Output arguments are enclosed in square brackets and input arguments
in parentheses. Optional arguments are separated from obligatory
arguments with a semicolon, parameters to the right of the semicolon
are optional and parameters on the left hand side of the semicolon are
obligatory. If there is no semicolon in the output argument list, then
all output arguments are optional. If there is no semicolon in the
input argument list, then all input arguments are obligatory. In
addition, it is possible to use the ellipsis (...) notation to denote
an arbitrary number of optional arguments. The ellipsis is only
allowed as the last thing in a parameter (either input or output)
list. The following function has two obligatory output arguments, one
optional output argument, two obligatory input arguments, and any
number of optional input arguments, the first of which is named c:

<tscreen><verb>
[x,y; z] = f(a,b; c...)
</verb></tscreen>

The function body can refer to the arguments simply by name, and they
are of class Tobject. Actually the argument lists are implemented
using four C++ function parameters: the input argument list (argin),
the length of the input argument list (Nargin), the output argument
list (argout), and the length of the output argument list (Nargout).
Nargin and Nargout are of type int. argin and argout are arrays of
pointers to Tobject. The named arguments are just C preprocessor
macros. For example, if x is the first input argument, its definition
is

<tscreen><verb>
#define x (*(argin[0]))
</verb></tscreen>

The pointers contained in the argument arrays are protected against
modification by the C++ keyword const. In addition the input array
individual objects are also const. The C++ compiler will therefore
give an error message if you try to assign or otherwise modify an
input argument. Also Nargin and Nargout carry the const attribute,
because changing them is unnecessary.

Ellipsis arguments have no names and therefore must be referenced
using the argin and argout arrays explicitly. This is easy, for
example to process all input arguments starting from the second one
(which is *argin[1], remember that in C arrays start with subscript
0), you could use a code like this:

<tscreen><verb>
static void Process(const Tobject& obj) { /* ... */ }

[] = myfunc(x...)
/* Help message ... */
{
    /* ... */
    for (int i=1; i<Nargin; i++)
        Process(*argin[i]);
    /* ... */
}
</verb></tscreen>

As mentioned earlier, C-tela code is C++ code equipped with the
Tela-like function header syntax. In addition to this, there are also
some small restrictions on C-tela source files:

<tscreen><verb>
1. The function header must be on one line, and the first character
(the left square bracket) must be on first column.

2. The right brace which ends the C-tela function body must be in the
first column. No other right brace inside the function body may be in
first column.

3. You cannot temporarily remove C-tela functions from your source
file using preprocessor directies, e.g. by enclosing the lines in
#if 0 ... #endif. If you want to do this, you must also enclose the
function headers in a comment.
</verb></tscreen>

These rules should not limit your programming capabilities in any
serious way, and most of the time you do not have to even think about
them.

Then what can you do with the Tela objects, that are of type Tobject
in C++? Firstly, every Tobject has a tag containing that object's
kind. The possible kinds are (from header file object.H):

<tscreen><verb>

enum Tkind {                // Object kinds (types)
    Kint,                   // Integer scalar
    Kreal,                  // Real scalar
    Kcomplex,               // Complex scalar
    KIntArray,              // Integer array (n-dimensional)
    KRealArray,             // Real array
    KComplexArray,          // Complex array
    KObjectArray,           // Object (pointer) array, currently not used
    Kfunction,              // User-defined function, written in Tela
    KCfunction,             // Compiled and linked C-Tela function
    KIntrinsicFunction,     // Special "functions" generating inline code: abs, min, max ..
    Kvoid,                  // Empty value, when printed prints nothing
    Kundef                  // Undefined value, the default for new symbols
};

</verb></tscreen>

Let us then list the most useful Tobject public members:

<tscreen><verb>

class Tobject {
  /* ... */
    // --- constructors
    Tobject();                          // default constructor: it will have Undefined value
    Tobject(Tint a);                    // construct integer scalar object
    Tobject(Tchar ch);                  // construct character object
    Tobject(Treal a);                   // construct real scalar object
    Tobject(Tcomplex a);                // construct complex scalar object
    Tobject(Treal x, Treal y);          // construct complex scalar object
    Tobject(const Tint itab[], int N, int stringflag=0);    // construct integer vector or string
    Tobject(const Treal xtab[], int N); // construct real vector
    Tobject(const Tcomplex ztab[], int N);  // construct complex vector
    Tobject(const Tint itab[], const TDimPack& dp); // construct integer array
    Tobject(const Treal xtab[], const TDimPack& dp);    // construct real array
    Tobject(const Tcomplex ztab[], const TDimPack& dp); // construct complex array
    Tobject(const Tchar *str);          // construct string
    Tobject(const Tobject& obj);        // copy constructor: use other object's value

    // --- assignments
    Tobject& operator=(Tint a);         // assign integer scalar
    Tobject& operator=(Treal a);        // assign real scalar
    Tobject& operator=(const Tcomplex& a);  // assign complex scalar
    Tobject& operator=(Tchar ch);       // assign character
    Tobject& operator=(const Tchar *str);   // assign string
    Tobject& operator=(const Tobject& obj); // copy assignment: assign other object's value
    void izeros(const TDimPack& dp);    // set to zeroed int array of given dims
    void rzeros(const TDimPack& dp);    // set to zeroed real array of given dims
    void czeros(const TDimPack& dp);    // set to zeroed complex array of given dims
    void ireserv(const TDimPack& dp);   // set to uninitialized int array of given dims
    void rreserv(const TDimPack& dp);   // set to uninitialized real array of given dims
    void creserv(const TDimPack& dp);   // set to uninitialized complex array of given dims
    void SetToVoid();                   // set to void (empty) value
    void SetToUndefined();              // set to undefined value
    void SetStringFlag();               // set string flag (assuming it is IntArray already)
    void SetCharFlag();                 // (assume it is Kint already)
    void ClearStringFlag();             // unset string flag (assuming it is IntArray already)
    void ClearCharFlag();               // (assume it is Kint already)

    // --- comparison
    int operator==(const Tobject& obj) const;
    int operator!=(const Tobject& obj) const;

    // --- inquiry functions
    Tkind kind() const;                 // inquire object kind
    int length() const;                 // number of elements of array object
    Tint rank() const;                  // rank of array object
    Tint IntValue() const;              // value of integer scalar object
    Treal RealValue() const;            // value of real scalar object
    const Tcomplex& ComplexValue() const;   // value of complex scalar object
    Tint& IntRef();                     // modifiable lvalue of integer scalar object
    Treal& RealRef();                   // modifiable lvalue of real scalar object
    Tcomplex& ComplexRef();             // modifiable lvalue of complex scalar object
    Tint *IntPtr() const;               // start address of elements of integer array
    Treal *RealPtr() const;             // start address of elements of real array
    Tcomplex *ComplexPtr() const;       // start address of elements of complex array
    int IsNumerical() const;            // nonzero if object is numerical (scalar or array)
    int IsArray() const;                // nonzero if object is array
    int IsNumericalArray() const;       // nonzero if it is numerical array
    int IsScalar() const;               // nonzero if object is (numerical) scalar
    int IsFunction() const;             // nonzero if object is Tela-function
    int IsCfunction() const;            // nonzero if object is C-tela function
    int IsString() const;               // nonzero if object is string
    int IsChar() const;                 // nonzero if object is character
    int IsNonzero() const;              // tests whether object is not zero
    const TDimPack& dims() const;       // return array object's dimensions

    // --- other operations
    friend ostream& operator<<(ostream& o, const Tobject& obj);     // outputter

    // --- destructor
    ~Tobject();
};

</verb></tscreen>

Using all these members seems to be overwhelming task at first. But
there is certain logic behind this design. Basically, you can 

<!--  ****************** -->
<sect>Interfacing issues
<!--  ****************** -->

Here we explain the main mechanisms to communicate with other programs
and data files from Tela. How to extend Tela by your own C/C++
functions has been explained in the previous section.

<sect1>Matlab interfacing
<!--   ****************** -->
<p>

There are three principal mechanisms to use Tela together with Matlab.

You can import and export Matlab binary files to and from Tela using
the <bf/import/, <bf/import1/, <bf/export_matlab/ commands.  Also
Matlab-readable plain ASCII files can be read by <bf/import1/.  Even
all your workspace variables can be exported or imported easily in
binary form. That is, Tela has the same functionality as two separate
Matlab processes would have.

It is possible to translate your Matlab scripts and M-files to Tela
language.  A translator program <bf/m2t/ exists for this purpose.
See <bf/man m2t/ for details.

If you have the <bf/matlabeng.ct/ module linked within Tela, you can
call Matlab functions and evaluate strings as Matlab commands at run
time. To enable this, there is function <bf/matlab_start/, which starts
Matlab in the background and sets up necessary communication links.
This is a good aid in development phase if e.g. some important function
is missing in Tela. You can borrow it from Matlab.

<sect1>HDF interfacing
<!--   *************** -->
<p>

Tela's native binary format is the HDF (Hierarchical Data Format from
Univ. Illinois/NCSA) format. HDF files created with the <bf/save/ command
can be read by various programs supporting HDF, for example Spyglass
tool programs and IDL. The <bf/import/ command can also read many other
types of HDF files meaningfully. The function <bf/export_RIS8/ exports
8-bit raster image sets in HDF format.

<sect1>ASCII files
<!--   *********** -->
<p>

Generic ASCII files can be read by the <bf/import1/ command.
Multidimensional datasets can also be read by inserting the size
information on the first line in a simple format (see <bf/help
import1/). ASCII files can be written using the <bf/fformat/ and
<bf/fprintf/ functions.

<sect1>Graphics formats
<!--   **************** -->
<p>

The <bf/PlotMTV/ program is responsible for the graphics.  It will
save the image in PostScript file if you click the appropriate
button. In <bf/PlotMTV1.4.1t/ and later you can also save the image as
a GIF (Graphics Interchange Format) file by pressing another
button. When the main PlotMTV window has been divided in several data
windows, pressing the GIF button will include all data windows in the
file. Pressing Shift-G under these circumstances will include only the
current data window. The GIF saving will work properly only if the
whole window is visible on your workstation screen (or in the
virtual screen, i.e. it must be in video-RAM).

</article>