PL design

So far, you have explored three different paradigms of PL: imperative, functional, and object oriented. There are certain classes of problems which are suitable for each of paradigms. That's the programmers eyeview. As a programmer you know the choices you have in choosing a language. What about the designer? What choices do they have? What are the implications once the decisions are frozen? This assignment gives you an idea of desiger's choices. An important requirement of a designer is the ability to "foresee" user's requirements. Can you?

What does the user want?

In this assignment we'll consider a specific problem physicists, for example, face in programming. Consider the calculation of voltage given current and resistance. Everybody knows that voltage = current*resistance. Only a physicist remembers that each of these quantities carries a unit with it. If the current is in milliamperes and the resistance is in gigaohms, then the voltage is in megavolts. If physicists program in any language, they have to keep track of the units themselves. As you can see, this can become tedious if you are working with hundreds of such variables, each with its own unit. The user wants some help from the language in keeping track of the units.

Designer's problem

This is the user's perception of the problem. Many times, users have only a vague idea of what they want. A successful designer should have a much better idea of the problem than the user. In the case of PL design, you have to worry about the following: what does "keeping track of units" mean? It can mean some of the following.
  1. unit inference: When you multiply ohms and amps, you get volts.
  2. error detection: You just cannot add millivolts and microamps. Any statement which does that has an error.
  3. automatic unit conversion: What about adding millivolts and microvolts? The compiler can either flag an error or it can automatically convert units to a common one. What happens depends on the goals of design.
Once you have decided on the extent of language support, you have to decide on actual language syntax and semantics. The following are some of the issues involved.
  1. Language Paradigm

    One way of treating dimensioned quantities is to consider them as variables with units.

      float v (millivolt), i (microampere);
    
    Here v is associated with the unit millvolt and i is associated with microampere. This is the imperative paradigm.

    Another way is to treat them as classes. You can have a class Voltage defined as below.

       class Voltage {
          private float v;
          private String unit = "Volt";
        /*  rest of the class */
       }
    
  2. Language Syntax: The following examples are in the imperative notation only for illustration. You should use your own notation in your report.

    What does the programmer see? Which of the following is a more covenient way to declare and use 5 pounds?

        float w = 5 lb;  // imperative syntax
        float w = 5 (lb);  // another imperative syntax
        Weight v = new Weight(5, "lb"); // Java syntax
        Weight v(5, "lb"); // C++ syntax
    

    What about expressions? In the following expressions, the constant 3 with some unit (lb, oz, or Volt) is added to w.

          w1 = w + 3 (lb);
          w1 = w + 3 (oz);
          w1 = w + 3 (Volt);
    
    (One of the expressions has a unit mismatch.)

    What about temporary variables? Temporary variables are useful for making large expressions readable. For example, instead of writing

        a = ((b+c)*d)/e;
    
    the programmer can write
        t = (b+c)*d;
        a = t/e;
    
    which is hopefully more readable. Should temporary be declared with actual units or can they be declared to have "temporary" units? If a variable has temporary units, the compiler/runtime calculates its actual units.
    float tmp = 5 (V) / 5 (mA); // no need to "declare" the units of "tmp"
                                // the units of "tmp" are inferred
    float resistance (ohm) = tmp + 10 (ohm); // start checking units
    

    Data structures: What types of arrays are permitted? Only weight arrays or weight and voltage arrays? Can weight arrays mix pounds and kilograms?

    Functions: Can functions specify the units of their arguments and returned value?

    I/O: How are the values read and written to files? Is unit checking/conversion done at input?

  3. Language semantics

    Now we come to the most difficult part of language design: the meaning of language constructs and the division of labor. Suppose we have the following code fragment.

       w1 = 10 (oz);
       w2 = 10 (kg);
       w3 (lb) = w1 + w2;
    
    Should the above fragment be considered syntactically meaningful? If yes, who does the conversion of units? The compiler or the runtime? Each has its advantages.

    Another important issue is the specification of conversion formulas. How does the programmer add to this background information? Suppose the programmer wants to introduce a new monetary unit shekel and provide a conversion to dollar, how can it be done?

  4. Efficiency

    Since the language is meant for numerical calculations, you should carefully consider the compilation and runtime costs of each of the features you introduce.

The assigment

The above list is illustrative of the examples and issues you should consider in designing a new language which supports units. You can add more examples and issues. Infact, the best way to start is to list down lot of different examples and study the requirements. You can try the command man units and look at the file /usr/share/lib/unittab to get an idea of units involved in real problems.

This is what you do:

  1. Explore the possibility of using a library of functions handling units. What are the advantages and disadvantages of such an approach?
  2. In light of the examples and issues, evaluate the suitability of each paradigm for the new language.
  3. Choose one of the paradigms and justify your choice.
  4. Give the syntax for: declarations (constants, variables, arrays, structs, etc), expressions, functions and procedures, and I/O
  5. Specify whether unit conversions are automatic and whether they are performed at compile time or runtime.
  6. Specify how the user introduces the units used in the program, the unit conversions, and the use of prefixes like "micro", "giga", etc.
  7. Give some example problems and programs. Trace the compilation and execution
  8. Discuss the suitability of compilation and interpretation for running the programs.
  9. Comment on the compilation and runtime costs of each feature.
  10. Pitfalls in your proposed notation
You should submit a report of at least 20 pages discussing the above and other issues in detail.

Submission

You should submit the report and self-evaluation form to Renata Teixeira on Mar 10 between 6:00 - 7:00 PM at APM 3349D.