CS 3723
Programming Languages 
  Contrasts   


Contrasts:
  • Syntax versus Semantics.

    • Syntax: The word syntax when used in programming languages refers to the appearance of a program. During the semester we will be giving this vague definition a precise, formal, mathematical (and very useful) definition.

      Our syntax will be what is called context-free syntax, referring to a description of the correct appearance of a program element that is independent of the context, that is, independent of what comes before or after. Thus a = b + 17; is a syntactically correct assignment statement in most of our languages these days, but it is incorrect if a and b are arrays or files or classes.

    • Semantics: The word semantics in programming languages refers to the meaning of a program. There are formal mathematical ways to define semantics, but these are difficult and have not been as successful as the definitions of syntax, so we will use informal descriptions in this course.

  • Run-time versus Compile-time.

    In this course, when applied to a "normal" programming language, compile-time refers to the time and actions taken during compilations, linking, and loading of a program: everything before the actual execution. Run-time refers to the time and actions taking during the execution of a program.

    In studying, and particularly in writing compilers, it is very important to keep these two times straight. It turns out that these issues can be confusing, and we will see some of this in the course (on a small scale).

  • Translation versus Interpretation

    For a program, translation means the process of converting the program to another equivalent form. When we are translating a program in a high-level language into a lower-level language (one that is closer to the machine), one uses the term compilation. In the case of an "ordinary" compiled language, there are several distinct phases:

    • first the compile (= translation) phase, at compile-time,
    • then the process of getting ready for execution, which may include linking and loading (also at compile-time), and
    • finally the execution phase, at run-time.

    The term interpretation refers to an equivalent way to handle (execute) a program, where there is no separate compile phase, but simply a single execution or interpretation phase that does everything, during which the program is directly executed. To say this differently, an interpreter will take an input program, and directly carry out the intent of the program, line-by-line, without any compilation. A "pure" interpreter has no compile-time, but just run-time.

    For real programming languages, there are often intermediate forms, where partial compilation occurs, to translate the program into another form, and then this other form might be interpreted (executed directly). Whether a language is compiled or interpreted, or what degree of intermediate form is used, has significant implications:

    • Compiled: extra compile time, runs faster, often less flexible language.
    • Interpreted: no compile time, runs slower, often more flexible language.

  • Example of Translation versus Interpretation

    Consider a program that calls for an addition, say like: a = a + b;

    • Compiler: Here the compiler will output an actual machine language "add" instruction. No add occurs at compile-time. At run-time the add instruction will be executed and the add operation will be carried out. The compiler will decide at compile-time whether it is adding integers or doubles or what, and will output the proper add instruction. At run-time the correct type of add will be hard-wired in so that it can be executed very efficiently.

      If the compiler encounters something like (8 + 5), it can let this addition happen during run-time, or in some cases it can improve run-time performance by moving the addition back into compile time, that is, replacing the expression with 13.

    • Interpreter: Here the interpreter will read the statement, will fetch values for a and b, and then will add them, all at the same time. The machine language "add" instruction that is used will be buried in the code for the interpreter program. The interpreter will be prepared to carry out a variety of adds, including for integers and for doubles. During its processing it will decide based on the types of a and b and will select the correct add, all at run-time. Thus far more is going on at run-time here than with a compiler.


Further Examples:
  • Straight compiler: C++ or C. These are the gold standard for compiled languages that produce efficient programs to run.

  • Hybrid system: Java Compiler and Virtual Machine. Originally, the Java compiler translated Java code to byte code This byte code was then interpreted by the Java virtual machine. The result was fairly efficient, but not at all competitive with C or C++. Now the Java virtual machine usually does on-the-fly compilation of the byte code to machine language, and execution can be comparable to C or C++ (though still off by a factor of 2 to 10).

  • Straight (or "pure") interpreter: Ruby, Python, etc. These are examples of scripting languages. Examples also include the old standby Perl, and many others. These have become ever more important over the years. Originally they were always interpreted, but now they are often compiled. They allow quick implementation of complex tasks and are extremely powerful. With such languages, systems programming tasks (for example) which could be carried out in C, end up requiring far less time to write and a far smaller program.

( Revision date: 2014-05-21. Please use ISO 8601, the International Standard.)