In this question I presented an idea I have for a simple programming language. The way programs written in this language will be run, is inside an interpreter written in Java, which will interpret the source code directly and execute it.

I would say that there is no doubt that this language would be considered a 'programming language'. It is capable of producing programs that can run, and there exists a platform for them to run on (the interpreter).

However, most answers on my question said that this interpreter won't be considered a VM.

I am used to thinking that all programming languges create programms that are most commonly either compiled to machine code and executed natively, or compiled to some kind of bytecode or IL and interpreted (executed) on a VM. (Or like in the rare case of the Dart language, interpreted and executed by a VM which interprets the source-code directly, no IL or bytecode).

But in my case - if it's true that my interpreter isn't considered a VM - programs written in my language do not run on a VM, and do not run natively, but rather run on an interpreter.

My question:

Are there programming languages in existence, that their programms are most commonly executed similarly? Not on a VM, and not natively, but rather run on an interpreter? (which is not considered a VM - although I must add I still don't understand why an interpreter that's used as a platform for other programs to run on isn't considered a VM).

closed as too broad by gnat, GlenH7, user40980, Bart van Ingen Schenau, World Engineer Mar 12 '14 at 14:28

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 5
    Whether a programming language is interpreted, compiled or runs in a virtual machine is not a property of the language itself. It is a property of the implementation. When you would publish a specification of your language, someone could write a machine code compiler or CLR bytecode compiler for it. – Philipp Mar 9 '14 at 12:19
  • If your interpreter is written in Java running on a Java JVM it is running on a VM. The interpreter is not a VM. – Rig Mar 9 '14 at 13:58

A VM is a piece of software that offers a machine-like abstraction. In the context of virtualization, a VM might abstract hardware resources. In programming language VMs, the VM offers a machine model, e.g. with a specific instruction set, a number of stacks, and a memory model.

It is true that we can interpret any language as an instruction set, but usually VM instructions are more fine-grained than high-level programming directives. For example, the high-level foo("bar", "baz") might have been changed to these instructions for a stack machine:

PUSH "baz"
PUSH "bar"
PUSH 2      ; number of arguments
LOAD "foo"  ; load the value of a variable onto the stack, here a function
CALL        ; the "CALL" op pops a function and number of arguments off the stack,
            ; then calls it

How these instructions are executed is irrelevant for this discussion, they may well be interpreted.

An interpreter that “directly” executes foo("bar", "baz") would generally not be considered to be a VM. Direct interpretation has fallen out of favor even for simple hobby languages, but early BASIC dialects used to be interpreted. Today, simple interpretation might be still used for simple shell languages.

The problem with naive, line-based interpreters is the difficulty of implementing structured and procedural programming. Let's assume we want to write if (x) { y } else { z }. This could be done with conditional GOTOs:

10 GOTO 40 IF x
20 z
30 GOTO 50
40 y

This is far to fragile for any serious use, but is very easy to implement. But Go To is Considered Harmful, and we rather much prefer an if/else construct. For example, bash uses if/then/else/fi:

if x
then y
else z

If the condition if false, the interpreter could jump to the matching else – but this is essentially a balanced parens problem, because conditionals may be nested. Another complication is that statements can also be separated via ; instead of newlines, so it's not simply a matter of looking at the first word in every line.

In short, any language with even remotely bearable syntax should be parsed into a data structure prior to execution. The output of a parser is called an Abstract Syntax Tree. E.g. foo("bar", 4 + variable) might produce this AST:

name: "foo"
 length: 2
 /      \
String  Addition
"bar"    /    \
       Int   Variable
        4    name: "variable"

An AST can be evaluated bottom-up. First, we replace the variable with its value (e.g. 38). Next, the subtree

 /   \
4    38

would get evaluated, which replaces this subtree with 42. Finally, the function get's executed which substitutes that part of the tree.

Describing the operational semantics of a programming language using these graphs is nice, but it's not a good model for actual execution: this destroys the original tree, so you have to make a copy for stuff like loop bodies or procedures. And if we have variables, our interpreter needs a concept of an environment which already brings us very close to being a VM.

We cross that boundary to being a VM if we note that the nodes in our AST are essentially Opcodes. If we order the tree operations (here: bottom-up, right to left: post-order traversal), and do not update the actual tree but place the intermediate values on the stack instead, the above example could also have been written as a more assembler-like

Variable "variable"
Int 4
String "bar"
List 2
FunctionCall "foo"

Most first implementations of programming languages are either transcompilers into another programming language or interpreters, because these are a lot easier to write than compilers or virtual machines.

When the language becomes popular and the first people start complaining about its lack of performance, people start to look for ways to make the implementations of the language execute faster. Making it a compiled language would change how it is used and deployed. So the usual choice is to turn the interpreter into a virtual machine which converts the source to bytecode before running it.

A good example is Javascript. When Netscape invented Javascript in 1995, it was purely interpreted. But when people started using JS for more and more complex applications, speed started to matter. There was also the browser war going on, where all the browser vendors tried to outperform each other. So browser vendors started looking at ways to make JS execute faster. SpiderMonkey, the Javascript engine by Mozilla, compiles Javascript to Bytecode and runs it in a VM. Google's V8 engine is even compiling Javascript code to native machine code before running it.

  • So basically, there is such a thing as a language that runs only on an interpreter, and not on a VM or natively. It exists, though it's generally slow in performance. Correct? – NPElover Mar 9 '14 at 15:03

I have pondered this question many times. My answer is that these terms are only marginally useful, that there may be something of a spectrum of languages and implementations between them, but ultimately:

A VM executes an intermediate code; an interpreter executes the source code.

For a VM, the source code is merely "syntactic sugar" over the intermediate code. The source code is not required after compilation. Multiple languages could target the same VM. (JVM, CLR)

For an interpreter, the source code is all there is, and it is parsed, analysed and executed immediately. It might be tokenised, but if so it can be guaranteed that a version of the original source code can be reconstructed from the tokenised form.

So, where is such a language? There are almost none of them in existence. Most languages get compiled sooner or later for the performance improvement. The ones that can't are those where runtime values are or could be directly interpolated into the statements, or where nobody could be bothered to write a compiler.

Most shell script languages are interpreted: sh, bash, csh, MSDOS/Windows BAT files, etc. Desk top calculators (dc). A graphic package like Gnuplot. Editor scripts (sed, ed, vi). The configuration file for a major piece of software like Apache. These are all interpreted, but some of them only marginally qualify as languages.

That's all I can think of.

  • Thanks for your answer. So you're saying that languages that are only interpreted and not run on a VM or natively, do exist, but very rarely. Correct? – NPElover Mar 9 '14 at 15:21
  • 1
    @NPElover: I think the more important point is that the distinction between interpreted vs VM vs native is subjective and thus not as useful as one might think at first. – hugomg Mar 10 '14 at 4:17
  • @NPElover: Full scale programming languages that are only interpreted are rare: I don't know any. Scripting or control languages that are only interpreted are common: the examples I gave would cover dozens or hundreds. – david.pfx Mar 10 '14 at 13:37

Not the answer you're looking for? Browse other questions tagged or ask your own question.