Evaluation


In this section the results of tests performed on the language and the development environment will be presented.

Testing the Language

The Kenya language was designed to be used by novice programmers to solve the sorts of problems set in introductory programming courses. Solutions to a selection of the exercises set for the first year computing laboratories at Imperial College have been coded in Kenya. The code for these solutions is given in Appendix C along with their translations to Java.

The fact that solutions to these exercises can be coded in Kenya shows that it would be possible to use it for teaching a first year programming course with similar exercises.

Exercises

Star Triangle

The object of this exercise is to draw a triangle of stars (asterisks) on the screen with one star at the top and ten at the bottom. This demonstrates the use of textual output, integer variables and for loops.

Fibonacci

The object of this exercise is to calculate the nth term of a Fibonacci sequence where n and the two starting terms (positions 0 and 1) are given by the user. This demonstrates the definition and use of a recursive function, conditional statements and getting input from the user.

Put Base

The object of this exercise is to produce a program which outputs a given number in a given base. This demonstrates the use of a void function and the mathematical modulus operator.

A comparison of the amount of code which needs to be written (in terms of the number of characters) between Kenya, Turing and Java is given below. Comments were removed from all the programs before measuring their size so that only executed code was taken into account :

Exercise Kenya TuringJava
Star Triangle89 chars 242 chars259 chars
Fibonacci 519520734
Put Base 400507641

The size of programs to solve different exercises in different languages

In all cases it can be seen that Kenya is at least as concise as either of the other languages. This is good as it points to Kenya being a simple language with no unnecessary syntax, which was one of the key design goals.

The newly designed Kenya does posess many of the qualities of a good teaching language, and fulfils the above aims to a high degree. It is of course not possible to say that Kenya is a good teaching language without it being used to teach a novice programmer or an introductory programming class. Unfortunately, at this stage in the year there are hardly any novice programmers in the department, due to the college's highly effective teaching (and the threat of exams!) and so it was difficult to test it "in the field". Also the environment has not been developed to be sufficiently robust to give to a class for laboratory work. It is intended only to demonstrate the possibilities of working with the language.

The Language Implementation

The implementation of the Kenya language produced in this project is not quite in line with the original specification. A couple of extra restrictions were added in order to fix some of the shift/reduce errors encountered while developing the grammar for the language. The grammar had to be changed at several points during the development of the translator and the type checker in order that the necessary parts of the data structure were available from particular nodes in the tree (mostly this was achieved by "flattening" productions).

With the pressure of time mounting towards the end of the project, two compromises were necessary. When a function call is made, the keyword call must be placed in front of the name of the function. Also, when a logical not operator is applied, the expression to which it applies must be in brackets, even if it only consists of one term. If further development is done on an implementation of Kenya, work should be undertaken to correct the grammar so that the language can be used exactly as it was designed without these restrictions.

Apart from these points, the implementation allows full use of the language as it was designed. In all the tests carried out, the translator produced correct Java code from correct Kenya programs.

The Kenya language is designed to be as simple as possible whilst still being useful. This means that some "shortcuts" used by more experienced programmers ( for example the use of the increment operator ) are not provided. As the translator produces Java code directly related to the Kenya code written, the increment operator is not used in the Java code ( except in the one case of modifying the index variable in a for loop ). This may not be the code that a Java programmer would write, but it is clear what the code does in relation to the Kenya code.

An interesting point to consider is whether the translator should perform any optimisations. For instance in the above case the translator might come across:

  a = a + 1;

in the Kenya code. The current system would write out exactly the same statement in the Java code, but Java has an increment operator, so if the translator is to follow the rule of generating the code that a human Java programmer would write then it should possibly generate the shorter:

  a += 1;

or even

  a++;

Taking account of these cases would add complexity to the design of the translator, as the identifier used in the right hand side of the expression needs to be matched with that on the left. This is something to be considered as a future improvement to the system.

Another optimisation which might be made is that of constant folding, i.e. if the result of an expression can be computed at compile time rather than having to be left to be computed at runtime this will save on the required computation when the program is run. This technique might be applied if the following code is encountered:

  const int secondsInDay =  60 * 60 * 24;
  const real pi = 22.0 / 7.0;

In both of these cases the value to be assigned to the constant can be calculated at compile time. It is difficult to say whether it should be done at translation time. In the first case, the fact that the multiplication is written out helps to assure the programmer that the value is correct. In the second case, it is more debatable. Most compilers will do constant folding when generating executable code, and so there should not be a speed increase associated with calculation of the value at translation time. However, if the code was:

  real diameter = 23.7;
  real radius = diameter / 2;

then not all of the operands of the division are real numbers, and a type conversion needs to be applied to the 2 before the calculation can be done. The compiler will either add in such a function so that the expression becomes something like

  radius = diameter / int_to_real( 2 )   

or it will rewrite the value 2 as 2.0 . Perhaps this should be done at translation time, as the division of a real by an integer is a type mismatch, and maybe the programmer should know if the compiler is going to have to do something to fix their code so that it works ( especially if it has a computational cost, as with a function call ). This is not done in the current Kenya system, and it just allows through arithmetic with mixed integer and real terms and assumes the compiler will deal with it.

Testing the Development Environment

The software developed in this project provides a development environment for writing Kenya programs, checking their correctness and translating them into Java. This tool was written in Java, and the code comprises just over 30,000 lines of source code. Approximately 20,000 lines of this code was generated by SableCC to create the lexical analyser, the parser and the classes which represent the different nodes in the abstract syntax tree.

Responsiveness

As the code for this tool is quite large, I decided not to create all of the objects when the application starts up, but to put off creating objects and loading classes until they were needed (load on first use). This is possible as Java supports dynamic class loading. Doing this decreases the amount of time that the user has to wait when starting the application. It does mean, however, that the user will experience a short delay the first time that they activate a certain feature, for instance the first time they parse a piece of code or access the help. This delay does not occur on repreated use of these features as the classes have already been loaded and initialised. In no case is the delay more than a second or two, and this is deemed acceptable for general use.

Running the Kenya system on a machine with a 300MHz Pentium II processor, Redhat Linux v6.2 and the IBM Java Virtual Machine, the time taken to parse, type check and translate one of the programs from the exercises given above averages approximately 0.5 seconds. This time is much smaller than the time taken to compile the Java code, which averages around 5 seconds. The delay added to producing running code by having to translate it from Kenya to Java is therefore negligible.

Usability

Several students of the department of computing at Imperial College were given the system to test. (These students were actually quite experienced programmers, rather than novices, but their experience was considered valuable in assessing the usability of the system). They were given the user manual and the set of example programs which are included in the appendices of this report. None of the students experienced any difficulty in writing a simple program in Kenya, translating it to Java, compiling and running it.

The error messages produced by the type checker (discussed further below) seemed sufficient for the users to identify and correct simple errors in their programs. It was mentioned that it would be nice to have the location of the error highlighted in the editing window.

The view was expressed that it would be nice to have automatic indentation in the editing windows, and that indenting the Java code in a different way might make its function clearer. These are slightly more important than just cosmetic changes, but indentation is quite personal to individual programmers.

Some concerns were raised over consistency between representations of the program in the system. If the Kenya code is edited does it invalidate then Java version? If the execute button is pressed, which version of the code is run? These issues would need to be addressed before deploying the system in a laboratory environment.

Error Reporting

Some examples of errors detected by the type checker are shown below. In the first case a variable called "Name" has been declared as a string, but has had an integer assigned to it. This is an example of a type check.

Type Check

In the next example, two variables are declared with the same name. This is not allowed as the machine will not know which of the two variables the programmer is referring to. This is an example of a uniqueness check.

Type Check

The information that the system provides about errors in programs is probably not sufficiently detailed at the moment to enable novice programmers to debug their programs easily and fully. The lexical analyser and parser used in this project are generated automatically from the grammar. Although this does not mean that it is not possible to change the way that they report errors, if changes are made they are overwritten the next time that the parser generator is run (this needs to be done every time that a change is made to the grammar). Once the grammar has been completely finalised and there is no need to regenerate the analysis code, changes could be made to provide more friendly error messages.

One of the major failings in terms of debugging messages is that it has not been possible to report the line numbers of semantic errors. When the parser creates the abstract syntax tree representing the program it does not record in each node the line number on which the production which generated it was found. The data stored in a Node could be altered, and the parser changed to record line numbers as the code is analysed, but this would require fairly large changes to the parser. Again this would only be possible after the parser had been generated for the last time, and would be difficult as the parser was designed by someone else, and so some significant reverse engineering would be required.