Compilation 解释器如何运行代码?
阅读所有编译过的与解释过的文章——看起来像是编译过的——意味着机器将直接运行编译过的代码,而解释过的,解释器将运行代码。但是如果代码在机器上,解释器如何运行代码呢?它是否仍然需要将它所解释的内容转换为机器代码,并让机器运行它?在一天结束的时候,为了让机器正常运行,一切都必须以机器代码结束?它似乎只是意味着它一次只通过一行语言运行,而编译意味着一次通过所有语言。在那之后,基本上是一样的,对吗?相关: 不,它不需要将其转换为机器代码。这些指令仅仅向解释器本身提供指令,然后解释器自己执行这些指令 考虑一种真正愚蠢的“语言”,它包含以下指令: 添加[编号]Compilation 解释器如何运行代码?,compilation,programming-languages,interpreted-language,Compilation,Programming Languages,Interpreted Language,阅读所有编译过的与解释过的文章——看起来像是编译过的——意味着机器将直接运行编译过的代码,而解释过的,解释器将运行代码。但是如果代码在机器上,解释器如何运行代码呢?它是否仍然需要将它所解释的内容转换为机器代码,并让机器运行它?在一天结束的时候,为了让机器正常运行,一切都必须以机器代码结束?它似乎只是意味着它一次只通过一行语言运行,而编译意味着一次通过所有语言。在那之后,基本上是一样的,对吗?相关: 不,它不需要将其转换为机器代码。这些指令仅仅向解释器本身提供指令,然后解释器自己执行这些指令 考虑
减去[数字]
除以[数字]
乘[数] 我们可以实现这样的“解释器”(用C语言编写):
publicstaticvoid执行语句(列表指令)
{
int结果=0;
foreach(指令中的字符串指令)
{
string[]action=instruction.Split(“”);
int number=int.Parse(操作[1]);
开关(操作[0]。修剪().ToLower())
{
案例“添加”:
结果+=数字;
打破
案例“减法”:
结果-=数量;
打破
“划分”一案:
结果/=数字;
打破
“乘法”情况:
结果*=数字;
打破
}
}
Console.WriteLine(“结果:+Result”);
}
ExecuteStatements
方法将被编译为机器代码。另外,我们有这样一个文本文件:
加1
减去1
加10
乘以50
除5
结果将是100。字符串实际上从未编译成任何东西——它们只是告诉解释器要采取什么操作
显然,这种“语言”甚至不是模糊的图灵完备,但问题是,在任何时候,我们都不会以某种方式将其“翻译”成机器代码,“解释器”只会执行指定的任何操作
实际上,我曾经编写过一个解释器,作为测试自动化框架的一部分。当有人对API进行调用时,我们会截取调用,对其使用反射来确定调用内容和参数,并将反射元数据序列化为JSON。随后,我们反序列化了JSON,并使用反射调用之前使用相同参数运行的任何方法。引擎实际上并不需要机器代码——它只是使用反射来确定调用要做什么
这里是关键的洞察:解释的代码本身实际上什么都不做——它所做的只是向解释器提供它需要采取的动作。解释器已经“知道”如何使用解释器语言执行所有可以执行的操作,因此不需要额外的机器代码
打个比方,把你正在解释的代码想象成菜谱,把解释器想象成厨师。食谱规定了像“加1杯面粉并搅拌”这样的动作。厨师知道如何按照食谱中的任何指示来做,他自己也会做。严格地说,食谱实际上并没有做任何事情——它只是坐在那里让厨师阅读,这样厨师就可以知道该采取什么行动。没有必要为了完成食谱而让食谱成为真正的厨师——它只需要有人知道如何遵循它的指示
TL;DR您不需要将其“翻译”为机器代码-您只需要有足够的信息让口译员知道要采取什么行动。一个好的解释器已经“知道”如何采取语言可以实现的任何操作,因此不需要创建任何额外的机器代码。谢谢@EJoshuaS!我想我认为机器代码是一切都必须经过的东西,以使东西工作,但你是说,解释器完全绕过机器代码,可以以某种方式与硬件本身通信来执行代码?@stackjlei解释器通常是机器代码。它对硬件没有任何特殊的“挂钩”(解释器只是一个普通的程序),只是程序“知道”如何采取解释语言实现的任何动作。@stackjlei把你解释的代码想象成一个菜谱,而解释器则是一个厨师。食谱本身并没有任何作用,它只是坐在那里给厨师指路,而厨师“知道”如何遵循食谱可能提供的任何指示。
public static void ExecuteStatements(List<string> instructions)
{
int result = 0;
foreach (string instruction in instructions)
{
string[] action = instruction.Split(' ');
int number = int.Parse(action[1]);
switch (action[0].Trim().ToLower())
{
case "add":
result += number;
break;
case "subtract":
result -= number;
break;
case "divide":
result /= number;
break;
case "multiply":
result *= number;
break;
}
}
Console.WriteLine("Result: " + result);
}