... .. ... 005 53 ( 008 55 / 011 45 y^x 014 75 - 017 54 ) 020 42 STO
003 76 2nd Lbl 006 43 RCL 009 01 1 012 53 ( 015 43 RCL 018 54 ) 021 25 25
004 75 - 007 25 25 010 00 0 013 08 8 016 26 26 019 59 2nd Int ... .. ...
T COMPILER
The T Compiler has been developped using lex and yacc tools (actually flex and bison).
For new comers, lex generates a lexical analyzer that performs pattern-matching on text. On its side, yacc reads a grammar specification and generates a parser for it. This parser consists of a set of routines which are invoked when a specific pattern is found by the lexical analyzer.
Despite it is not mandatory to go deep inside the T Compiler processing, it helps to understand why a program written in T Language generates more or less programming steps. Thus, it may help to optimize a program that first doesn't fit in memory.
VARIABLES FROM INSIDE
As a general rule, the T Compiler maps each variable to a TI59 register.
Let's consider the following declarations:
double value;
double *pointer;
double values[5];
double *pointers[10];
According to the above rule, such declarations will trigger the following register assignments:
// Variable Scope Register Content
// value main 00 Value
// pointer main 01 Address
// values[0] main 02 Value
// values[1] main 03 Value
// values[2] main 04 Value
// values[3] main 05 Value
// values[4] main 06 Value
// pointers[0] main 07 Address
// pointers[1] main 08 Address
// pointers[2] main 09 Address
// pointers[3] main 10 Address
// pointers[4] main 11 Address
// pointers[5] main 12 Address
// pointers[6] main 13 Address
// pointers[7] main 14 Address
// pointers[8] main 15 Address
// pointers[9] main 16 Address
Keep in mind a declaration doesn't generate any programming step: it is just a simple mapping between a variable identifier and a register in the calculator.
On the opposite, using a variable is step consuming. For instance, value = value + 1 will generate RCL 00 + 1 = STO 00.
As a variable may contain the address of another variable, statements like pointer = &value or pointers[5] = &values[1] are also valid. They will generate the following register assignments and steps:
// Variable Scope Register Content
// values[(0)] main 17 Address
// pointers[(5)] main 18 Address
0 STO 01 // pointer = &value
7 STO 18 5 SUM 18 // Computes pointers[5] address (7 + 5 = 12) and stores it in register 18
2 STO 17 1 SUM 17 // Computes values[1] address (2 + 1 = 3) and stores it in register 17
RCL 17 STO 2nd Ind 18 // Recalls register 17 (3) and stores it in register contained in register 18 (12)
As you can see, access to an array requires a dynamic index computation. It is made from the array base address plus the index value (that may be far more complex than a simple integer value). As a drawback, this computation generates additional steps and increases memory consumption (registers 17 and 18 are now used). Therefore array usage must be as limited as possible.
SUBROUTINES FROM INSIDE
The T Language defines two types of reusable code:
-
Functions which accept arguments passed by value and return a value.
-
Procedures which accept arguments passed by value or by reference but don't return any value.
As a general rule, the declaration of an argument triggers a new register assignment whatever the passing mode.
Anyway, there is an important difference at the call:
-
An argument passed by value sees its value copied to this register.
-
An argument passed by reference sees its address copied to this register.
Let's come back to the following program:
double myFunction(double var)
{
var=var+1;
return var;
}
void myProcedure(double *var)
{
*var=*var+1;
}
void main()
{
double a;
double b;
a=1;
b=myFunction(a);
display(a); // Will display 1
display(b); // Will display 2
myProcedure(&a);
display(a); // Will display 2
}
First, here is the mapping between variables and registers:
// Variable Scope Register Content
// var myFunction 00 Value
// var myProcedure 01 Address
// a main 02 Value
// b main 03 Value
And then, the steps generated by the T Compiler:
2nd Lbl -
RCL 00 + 1 = STO 00
RCL 00
INV SBR
2nd Lbl (
RCL 2nd Ind 01 + 1 = STO 2nd Ind 01
INV SBR
2nd Lbl R/S
1 STO 02
RCL 02 STO 00 SBR - STO 03
RCL 02 R/S
RCL 03 R/S
2 STO 01 SBR (
RCL 02 R/S
INV SBR
CONTROL STRUCTURES FROM INSIDE
With the TI59, if implementation is made a little bit upside down: the test itself doesn't deal with the if but with the else clause (due to the jump that comes right after the comparison). This makes the test reading a little bit difficult.
a==b, a!=b, a<=b, a>b tests are implemented with the following pattern:
a x><t
b test C
instructions...
GTO D
2nd Lbl C
instructions...
2nd Lbl D
a>=b and a<b tests are implemented with another pattern:
b x><t
a test C
instructions...
GTO D
2nd Lbl C
instructions...
2nd Lbl D
The while implementation is based on a if statement. It uses the following pattern:
2nd Lbl C
a x><t
b test D
instructions...
GTO C
2nd Lbl D
T COMPILER OUTPUT
Assuming you submit a file named program.c, the T Compiler will generate two output files:
-
A file named program.ti59 that contains all AOS instructions and a register/step/label report.
-
A file named program.step that contains all AOS instructions, unindented and numbered.
For the quadratic equation example, the .ti59 file looks like this:
SBR R/S
R/S
RST
2nd Lbl R/S
2nd Lbl A
R/S STO 00 R/S
2nd Lbl B
R/S STO 01 R/S
2nd Lbl C
R/S STO 02
// Compute delta
RCL 01 * RCL 01 - 4 * RCL 00 * RCL 02 = STO 03
0 x><t
RCL 03 INV 2nd x>=t -
// Real solutions
(RCL 01 +/- - RCL 03 sqrt) / (2 * RCL 00) = R/S
(RCL 01 +/- + RCL 03 sqrt) / (2 * RCL 00) = R/S
GTO (
2nd Lbl -
// No solutions
99999999 R/S
2nd Lbl (
INV SBR
// Resources status
// ----------------
// T Compiler V1.0.2
// Required partioning is 10 registers (1 2nd Op 17) and 880 steps
// 4 registers used out of 10 (6 left)
// 98 steps used out of 880 (782 left)
// 2 common labels used out of 77 (75 left)
// Variable Scope Register Content
// a main 00 Value
// b main 01 Value
// c main 02 Value
// delta main 03 Value
// Module: main Label: 2nd Lbl R/S
// Argument Scope Register Content
On its side, the .step file looks like that:
000 71 SBR
001 91 R/S
002 91 R/S
003 81 RST
004 76 2nd Lbl
005 91 R/S
006 76 2nd Lbl
007 11 A
008 91 R/S
009 42 STO
010 00 00
011 91 R/S
012 76 2nd Lbl
013 12 B
014 91 R/S
015 42 STO
016 01 01
017 91 R/S
018 76 2nd Lbl
019 13 C
020 91 R/S
021 42 STO
022 02 02
023 43 RCL
024 01 01
025 65 *
026 43 RCL
027 01 01
028 75 -
029 04 4
030 65 *
031 43 RCL
032 00 00
033 65 *
034 43 RCL
035 02 02
036 95 =
037 42 STO
038 03 03
039 00 0
040 32 x><t
041 43 RCL
042 03 03
043 22 INV
044 77 2nd x>=t
045 75 -
046 53 (
047 43 RCL
048 01 01
049 94 +/-
050 75 -
051 43 RCL
052 03 03
053 34 sqrt
054 54 )
055 55 /
056 53 (
057 02 2
058 65 *
059 43 RCL
060 00 00
061 54 )
062 95 =
063 91 R/S
064 53 (
065 43 RCL
066 01 01
067 94 +/-
068 85 +
069 43 RCL
070 03 03
071 34 sqrt
072 54 )
073 55 /
074 53 (
075 02 2
076 65 *
077 43 RCL
078 00 00
079 54 )
080 95 =
081 91 R/S
082 61 GTO
083 53 (
084 76 2nd Lbl
085 75 -
086 09 9
087 09 9
088 09 9
089 09 9
090 09 9
091 09 9
092 09 9
093 09 9
094 91 R/S
095 76 2nd Lbl
096 53 (
097 92 INV SBR
SCOPE & CONTENT
The scope of a variable is the place where this variable is known. It may be either local to a function/procedure or global to a program.
On top, a variable has a specific content. It is either a value - any number - or an address (a register number where to find a value)
myFunction(double var)
Variable var is mapped to register 00 which contains the argument's value. Direct use of register 00 is possible.
CALL TO myFunction
Variable a value (RCL 02) is copied to var (register 00) in myFunction.
CALL TO myProcedure
Variable a address (02) is copied to
var (register 01) in myProcedure.
myProcedure(double *var)
Variable var is mapped to register 01 which contains the argument's address. Indirect use of register 01 is required.
COMPARISONS (1)
The value to compare (a)
is swapped with t. b is compared to t using the following AOS instructions:
-
a==b: INV 2nd x=t
-
a!=b: 2nd x=t
-
a<=b: INV 2nd x>=t
-
a>b : 2nd x>=t
AOS INSTRUCTIONS
In the .ti59 file, AOS instructions are formated according to the program logic and comments are still present.
This view helps to understand the T Compiler translation.
RESOURCES STATUS
This report gives useful information about:
-
The split required between registers and steps.
-
The number of available registers in the packet of 10.
-
The number of available steps.
-
The number of available common labels.
Obviously, none of these values should be negative. Otherwise, it would mean the program cannot fit in memory.
AOS INSTRUCTIONS
In the .step file, AOS instructions are numbered and displayed with their code.
This view helps to type in the program and to check errors.
COMPARISONS (2)
The value to be compared (b)
is swapped with t. a is compared to t using the following AOS instructions:
-
a>=b: INV 2nd x>=t
-
a<b: 2nd x>=t