Issues with the Generated Java


The software developed in this project will translate the Kenya code written by the programmer into Java so that it can be compiled and run. (In fact, in order to allow generics as detailed in the previous section, the code produced will actually be GJ, not Java, but as GJ is a superset of Java, I shall use the term Java to describe the code produced unless specifically talking about generics.)

Qualities of the Code

The main objective for the Java was that it should be as near as possible to the code that a Java programmer would write from scratch to solving a problem. Often generated code is very obviously generated. It is often more verbose and less elegant than code written by a human. I wanted to make sure that the code generated from Kenya is clear and simple, so that it is as easy as possible for the novice programmer to understand what the Java does, whilst providing a good example of how to write good Java code.

I also wanted to show exactly what code was necessary. A different approach would have been to provide a lot of library code which could be called, allowing the generated code to be kept small. However, I wanted to avoid providing "black box" functionality hiding the implementation from the user. The idea is to allow the programmer to see how things work so that they can do them for themselves.

Going against this is the fact that there is a Java paradigm of code re-use. Once you have written code to do something once, you don't write it again, but import it from the previous project. This points towards the use of library code. A compromise needed to be reached.

Library Routines

I have decided to provide the routines for getting input into a program ( reading numbers and strings from the keyboard ) in a library. Doing input in Java is not simple. The simplest code to read an integer that I can come up with is still quite complex (see the language design section). The code could be wrapped in a function:

static int read()
{
  try {
       java.io.BufferedReader stdin = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));
       String line = stdin.readLine();
       return Integer.parseInt(line);
  }
  
  catch (java.io.IOException e) { System.out.println(e); }
  catch (NumberFormatException e) { System.out.println(e); }
       
  return 0;
}

A different function is required for each type of data to be read. A Java programmer would probably write a wrapper class called something like IntReader with a static method read() or they would write a Reader class which contained several methods: readInt(), readReal() etc. They would then use this class in any program that they wrote in future, using an import statement to include the class, or just by putting a copy of it in the same package.

I have decided to write separate classes IntReader, DoubleReader and StrReader which are in a package called kenya.io . The use of the readInt(), readReal() or readStr() functions in a Kenya program causes the relevant class (or the whole package) to be imported into the generated Java program.