什么是 VM,为什么动态语言需要 VM?
因此,例如,Python和Java有VM,C和Haskell没有( 如果我错了,请纠正我)
想想两边有什么语言,我找不到原因。Java在很多方面都是静态的,而Haskell提供了很多动态功能。
因此,例如,Python和Java有VM,C和Haskell没有( 如果我错了,请纠正我)
想想两边有什么语言,我找不到原因。Java在很多方面都是静态的,而Haskell提供了很多动态功能。
这与静态与动态无关。
相反,它是关于独立于底层硬件平台(“构建一次,随处运行” - 理论上......
实际上,这也与语言无关。可以编写一个 C 编译器来为 JVM 生成字节码。可以编写一个生成 x86 机器代码的 Java 编译器。
让我们暂时忘记 VM(我保证,我们将回到下面的内容),并从这个重要事实开始:
对于提供垃圾回收的语言,必须有某种“运行时”/运行时环境/事物来执行它。
这就是为什么Python,Java和Haskell需要“运行时”,而C,没有,可以直接编译成原生代码。
请注意,psyco是一个Python优化器,它将Python代码编译为机器代码,但是,许多机器代码包括对C-Python运行时函数的调用,例如,等。PyImport_AddModule
PyImport_GetModuleDict
Haskell/GHC与psyco编译的Python处于类似的状态。s被添加为简单的机器指令,但更复杂的东西分配对象等,调用运行时。Int
还有什么?
如果我们要向 C 中添加异常,我们生成的机器代码将需要为每个函数和每个函数调用做一些事情。
如果我们同时添加“闭包”,就会添加更多内容。
现在,与其在每个函数中重复这个样板机器代码,不如让它调用一个子程序来做必要的事情,比如PyErr_Occurred
。
所以现在,基本上每个原始的源代码行都映射到对某些函数的某些调用和较小的唯一部分。
这里有一个想法(顺便说一句,让我们把这个想法称为“虚拟机”)。
让我们来表示你的Python代码,例如:
def has_no_letters(text):
return text.upper() == text.lower()
作为内存中的数据结构,例如:
{ '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'),
]
}
现在,让我们编写一个执行此内存中数据结构的解释器。
让我们讨论一下与直接来自文本的解释器相比,这样做的好处,以及编译为机器代码的好处。
wt(f, d(o, e), s) <= th(i, s) + cr(a, p * d + o)