Are there any languages that are interpreted in something interpreted, like Python? If so, what are the advantages?
Many interpreters are written in interpreted languages; this is really a property of the implementation rather than the language. The advantage generally is to be able to use that host language for implementing the other, for convenience, existing knowledge, or particular features of the language that make it suitable for implementing other languages. These are just the same reasons you might use those languages for any other program too.
Implementing an interpreter under an interpreter isn’t generally either easier or harder than implementing it under a compiler. The host language could be implemented either way (and sometimes there are implementations both ways — like Python!), and typical interpreters could run on any implementation of the language they’re written in. The short answer is then that yes, they can be and are built that way, but no, there’s no strong reason in general to do it one way or the other.
While there’s generally no inherent difference to an interpreter in an interpreted language, there are a few situations where it can be relevant:
- Metacircular interpreters are a style of interpreter implemented within the language they’re interpreting, leveraging the host language’s functionality to execute code. These aren’t necessarily built on top of interpreters, but interpreters do often expose more reflective facilities to do this, and sometimes you can stack nesting dolls of interpreters this way.
- Domain-specific languages used for things like configuration and special-purpose business logic within a program are generally interpreted, and implemented in the host language of that program. Some implementation strategies are more viable in interpreters, and that can make creating the DSL in the first place more likely.
- Prototyping or exploratory language design within an interpreter can be more convenient if only for avoiding compile cycles, but dynamic
evalin particular is very rare in compilers and can be useful.
- Languages targeting platforms built around interpreted languages, like the web, need to conform to that restriction.
I have written many interpreters in both (typically-) compiled and interpreted languages. The reasons for one or another have all been external, determined by other systems I was working with or my whims and preferences at the time, and could have been overcome if something had been a little different. That is also the case in general: other factors dominate the decision rather than the implementation strategy of the host language.
Languages aren't interpreted. Nor are they compiled. Languages just are.
The term "interpreted language" is non-sensical. It is a category error. Shriram Krishnamurthi once said in an interview something like "if English were a typed language, 'interpreted language' would be a type error".
A particular implementation of a language may use interpretation or compilation (or, in most modern mainstream high-performance implementations, likely both), but that is purely a trait of the implementation, not the language.
Therefore, the question doesn't make sense.
Every language can be implemented by an interpreter. Every language can be implemented by a compiler. You can automatically derive a compiler from an interpreter. You can easily derive an interpreter from a compiler.
The vast majority of modern mainstream languages have both interpreted and compiled implementations.
One possible interpretation of the question is: "has there ever been an instance where there were two levels of interpretation", and the answer is that this happens all the time. In fact, a CPU is nothing but an interpreter for its instruction set, so every time you run a natively compiled interpreter, you are using two levels of interpretation. E.g., when you run a Python program in CPython, CPython first compiles the Python program into CPython byte code, then it interprets this CPython byte code, whilst itself being interpreted by the CPU.
Or, a much simpler argument: many interpreters are written in C. There are interpreters for C. Ergo, you can run an interpreter written in C on an interpreter for C.
One issue not mentioned in the other answers so far is garbage collection.
As already mentioned, being "interpreted" is a property of a language implementation, not a property of the language itself, as the same language could have both a compiler and an interpreter. However, we can talk about dynamic languages, i.e. those with features like dynamic types, runtime type checks or duck typing, construction of new types at runtime, and especially mechanisms like
exec which evaluate code from strings at runtime. Dynamic languages tend to be implemented as interpreters, though there are several notable exceptions.