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);
    }