因此,例如,Python和Java有VM,C和Haskell没有。(如我错了请纠正我)
考虑到线路两侧有哪些语言,我找不到原因。Java在很多方面都是静态的,而Haskell提供了许多动态功能。
解决方案
让我们忘记虚拟机一秒钟(我们会回到下面的那些,我保证),并从这个重要的事实开始:
C没有垃圾收集。
对于提供垃圾收集的语言,必须有某种“运行时”/运行时环境/事物来执行它。
这就是为什么Python,Java和Haskell需要“运行时”,而C则不需要,可以直接编译为本机代码。
需要注意的是Psyco的是,编译Python代码的机器码Python的优化,然而,很多的机器代码由调用C-Python的运行时的功能,如PyImport_AddModule,PyImport_GetModuleDict等。
Haskell/GHC is in a similar boat to psyco-compiled Python. Ints are added as simple machine instructions, but more complicated stuff which allocate objects etc, invoke the runtime.
What else?
C doesn't have "exceptions"
If we were to add exceptions to C, our generated machine code would need to do some stuff for every function and for every function call.
If we then add "closures" as well, there would be more stuff added.
Now, instead of having this boilerplate machine code repeated in every function, we could make it instead call a subprocedure to do the necessary stuff, something like PyErr_Occurred.
So now, basically every original source line maps to some calls to some functions and a smaller unique part.
But as long as we're doing so much stuff per original source code line, why even bother with machine code?
Here's an idea (btw let's call this idea a "Virtual Machine").
Let's represent your Python code, which is for example:
defhas_no_letters(text):returntext.upper()==text.lower()
As an in-memory data-structure, for example:
{'func_name':'has_no_letters','num_args':1,'kwargs':[],'codez':[('get_attr','tmp_a','arg_0','upper'),# tmp_a = arg_0.upper('func_call','tmp_b','tmp_a',[]),# tmp_b = tmp_a() # tmp_b = arg_0.upper()('get_attr','tmp_c','arg_0','lower'),('func_call','tmp_d','tmp_c',[]),('get_global','tmp_e','=='),('func_call','tmp_f','tmp_e',['tmp_b','tmp_d']),('return','tmp_f'),]}
Now, let's write an interpreter that executes this in-memory data structure.
Let's discuss the benefits of this over direct-from-text-interpreters, and then the benefits over compiling to machine code.
The benefits of VMs over direct-from-text-interpreters
The VM system gives you all the syntax errors before executing the code.
When evaluating a loop, a VM system doesn't parse the source code each time it runs.
Making the VM faster than the direct-from-text-interpreter.
So the direct interpreter runs slower with long variable name, and faster with short variable names. This encourages people to write crappy mathematician-style code such as wt(f, d(o, e), s) <= th(i, s) + cr(a, p * d + o)
The benefits of VMs over compiling to machine code
The in-memory data structure describing the program, or the "VM code", will probably be much more compact than boilerplate-full machine code which does the same stuff again and again for every original line of code. This will make the VM system run faster because less "instructions" will need to be fetched from memory.
Creating a VM is much simpler than creating a compiler to machine code. You can probably do this now without even knowing any assembly/machine-code.