How to alter the code at runtime in an interpreter

ccompilerinterpreters

While reading the difference between Compiler and interpreter , I found the following differences fromt he internet.

Advantages of using compiler:

  • Since compiler converts the program to native code of the target machine (object code), faster performance can be expected.
  • There is a scope for code optimisation.

Advantages of using interpreter:

  • Process of execution can be done in a single stage. There is no need of a compilation stage.
  • Alteration of codes possible during runtime.
  • Really useful for debugging the codes (because source code execution can be analyzed in an IDE)
  • Facilitates interactive code development.

In case of interpreter, stated as interpreter "there is a possibility of alter the code" and

In case of compiler "code optimization will be there"

Can anyone explain these 2 points ?

Best Answer

Side note: use compiler/interpreter distinction carefully, as it has its caveats.

  • Some folks use this distinction to assert that their language is faster because it is compiled/interpreted. The real answer is that a language cannot be faster/slower than another one: is German faster than Japanese?

  • Many other assertions related to this distinction don't make sense neither.

  • Many languages use more complicated approaches. For example, C# is compiled to IL, which is then “translated into native code or executed by a virtual machine”.

  • Some languages are “interpreted, but not really”.

Now to answer your question:

Altering the code:

Since the code is interpreted, it's easier to change it on the fly when executing it. One of such examples is eval(), used in some languages to dynamically inject source code available only as a string.

This being said, this point is both incomplete and confusing. C# is a compiled language (aside DLR), and still, there are ways to inject custom code during the execution of the app.

Code optimization:

Often, compilers are not limited to simply converting code written in source language to target language. They also do optimizations. Imagine you write:

const int ratio = 14;

function getFactor()
{
    int factor = 2 * ratio;
    string debug = "The factor is " + factor;
    return factor;
}

function computeSomething(int expenses)
{
    int factor;
    float result = (float)(expenses + factor) / 2;
    return result;
}

A compiler can use a few basic tricks to optimize this code:

  1. Inline

    The constant can be inlined, as well as the first function. This gives:

    function computeSomething(int expenses)
    {
        int factor = 2 * 14;
        string debug = "The factor is " + factor;
        float result = (float)(expenses + factor) / 2;
        return result;
    }
    
  2. Remove unused code

    Here, this will result in an important improvement, since string concatenation is often an expensive operation.

    function computeSomething(int expenses)
    {
        int factor = 2 * 14;
        float result = (float)(expenses + factor) / 2;
        return result;
    }
    
  3. Optimize mathematical operations

    Float multiplication is often cheaper than division.

    function computeSomething(int expenses)
    {
        int factor = 2 * 14;
        float result = (float)(expenses + factor) * 0.5;
        return result;
    }
    
  4. Remove intermediary variables

    function computeSomething(int expenses)
    {
        return (float)(expenses + (2 * 14)) * 0.5;
    }
    

Note that many today's interpreters also do those optimizations, which means that when you use an interpreted language, you should write your code for humans, not for computers, letting the interpreter do work.