I am currently working on the implementation of a new programming language, for
ID: 639591 • Letter: I
Question
I am currently working on the implementation of a new programming language, for fun. I realize that most languages never become popular, but I still want the language to have a high-quality implementation. The language is loosely lisp-like. It supports closures, first-class continuations, a homoiconic syntax, first-class functions, etc. In addition, I want my language to be able to have access to already established library code (specifically the Java Standard library, etc).
Dynamically compiling to JVM byte-code is essentially out of the question, because of the difficulty of implementing the stated feature set (excluding first-class functions) using a virtual machine that is not designed to support it. On the other-hand, compiling to C/C++ or some other lower-level language will lead to an unwanted degree of platform-dependence and/or reduce/remove the ability to use the Java standard library via programs written in my language.
My (largely-completed) approach to the implementation is to implement a custom p-code interpreter in Java. The high-level language simply compiles its code on-the-fly to essentially an array of instructions for this custom virtual machine. Each instruction is an object that implements a common interface. When executed, the instructions manipulate a stack-machine. Unfortunately, executing each instruction requires a virtual method call; whereas, the normal implementation of such interpreters does not use object based instructions. However, current micro-benchmarks and guess-based-estimates indicate that the completed implementation should match the speed of Python, given equivalent programs.
So do you think this method of implementation is crazy or amateurish, given the language's design goals?
What would you do differently?
Explanation / Answer
What you propose seems like a generally sound approach. The object-per-instruction might be a bit heavyweight, but there's no reason you can't start with that, especially if it's an easy design to work with.
Although you suggest that compiling to bytecode is out of the question at the moment, that's something you can always decide to add later. You can have a runtime environment that interprets some code and compiles the rest of it (Lisp environments have been doing that forever, and JIT compilers continue to do that today).
Keep in mind that there can always be more than one language implementation. C++ was first implemented as Cfront, a preprocessor on top of C. Early JVMs always interpreted bytecode, but they almost all JIT now. Python has multiple implementations, some of which even compile down to native machine code where possible.
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.