Compiler construction 编译语言可以是同音的吗?

Compiler construction 编译语言可以是同音的吗?,compiler-construction,lisp,scheme,interpreter,homoiconicity,Compiler Construction,Lisp,Scheme,Interpreter,Homoiconicity,根据定义,“同音”一词的意思是: 代码和数据的相同表示形式 在LISP中,这意味着您可以有一个带引号的列表并对其求值,因此(car list)将是函数,(cdr list)将是参数。这可以发生在编译时,也可以发生在运行时,但是它需要一个解释器 没有编译时解释器的编译语言也可能是同形的吗?还是同象似性的概念仅限于口译员?是的。lisp可以编译成本地二进制文件在我看来,这是一个奇怪的问题: 首先,该部分是向程序员提供的接口。语言的要点在于,它们抽象了一个较低级别的功能,该功能保留了与较高级别表示相同

根据定义,“同音”一词的意思是:

代码和数据的相同表示形式

在LISP中,这意味着您可以有一个带引号的列表并对其求值,因此
(car list)
将是函数,
(cdr list)
将是参数。这可以发生在编译时,也可以发生在运行时,但是它需要一个解释器


没有编译时解释器的编译语言也可能是同形的吗?还是同象似性的概念仅限于口译员?

是的。lisp可以编译成本地二进制文件

在我看来,这是一个奇怪的问题:

首先,该部分是向程序员提供的接口。语言的要点在于,它们抽象了一个较低级别的功能,该功能保留了与较高级别表示相同的语义(尽管方法不同)

dsm的机器代码点是一个很好的点,但提供:

  • 所呈现的语法和语义是相同的
  • 转换为较低级别的形式(机器代码、解释或其他)不会删除任何原始语义
  • 为什么较低级别的实施在这里很重要?

    此外:

    没有编译时解释器的编译语言

    如果没有一些程序对其进行解释,它将被要求是CPU的本机语言,因此CPU的本机语言将被要求是同源标志(或运行代码的VM)

    没有编译时解释的语言。。。将受到相当大的限制。。。因为它们根本不会被编译


    但我不是专家,可能没有抓住要点。

    构建在虚拟机(.net clr、jre等)之上的语言可以使用允许动态生成代码的高级技术。其中一个是IL编织。虽然它不像ECMAScript/Lisp/Scheme等的eval那样清晰,但它在某种程度上可以模拟这种行为


    例如,请查看Castle DynamicProxy,更多交互式示例请查看LinqPAD、F#interactive、Scala interactive。

    “Homoiconic”是一种模糊的结构“代码就是数据”更清晰一些

    无论如何,维基百科上关于同性恋的第一句话也没那么糟糕。它说,语言必须有一个使用其数据结构的源表示。如果我们忘记了将“字符串”作为源代码表示(这很简单,而且对于有一个有用的概念“HOMOIGINAL”没有多大帮助),那么Lisp有列表、符号、数字、字符串等,它们用于表示源代码。EVAL函数的接口决定了语言使用的源代码表示形式。在本例中,Lisp不是字符串。EVAL期望通常各种各样的数据结构和Lisp的求值规则确定字符串的求值结果是自身的(因此不会被解释为程序表达式,而只是字符串数据)。数字也会计算为自身。列表(sin 3.0)是一个符号和数字的列表。计算规则规定,此列表(带有表示函数的符号)作为第一个对象,将作为函数应用程序进行计算。对于数据、特殊运算符、宏应用程序和函数应用程序,有一些类似的求值规则。就这样

    为了说明这一点:在Lisp中,函数EVAL是在Lisp数据结构上定义的。它需要一个数据结构,根据其求值规则对其求值,并返回一个结果——同样使用其数据结构

    这与homoiconic的定义相匹配:源代码使用Lisp的数据类型具有本机表示

    现在,有趣的部分是:如何实现EVAL并不重要。重要的是它使用Lisp数据结构接受源代码,执行代码并返回结果

    因此,EVAL使用编译器是完全合法的

    (EVAL code)  =  (run (compile-expression code))
    
    有几个Lisp系统就是这样工作的,有些甚至没有解释器

    因此,“homoigic”表示源代码具有数据表示。它并没有说在运行时必须解释此源代码,或者执行基于此源代码

    如果代码已编译,则在运行时既不需要编译器也不需要解释器。只有当程序想在运行时评估或编译代码时才需要这些,而这通常是不需要的


    Lisp还提供了一个原语函数READ,该函数将数据的外部表示(S表达式)转换为数据的内部表示(Lisp数据)。因此,它还可以用于将源代码的外部表示转换为源代码的内部表示。Lisp没有对源代码使用特殊的解析器-因为代码是数据,所以只有读取。

    问题是许多处理器将指令和数据区域分开,并主动阻止程序修改自己的代码。这种代码过去被称为“退化代码”,被认为是一件非常糟糕的事情


    解释器(和VM)没有这个问题,因为它们可以将整个程序视为数据,只有“代码”是解释器。

    在最字面的形式中,C是同音符号。您可以使用
    &functionName
    访问函数的表示形式,并使用
    somePtrCastToFnPtr(SomeArgs)
    执行数据。但是,这是在机器代码级别,如果没有某种库支持,您将发现很难使用它。某种嵌入式编译器(我似乎记得LLVM可以做到这一点)会使它更实用;您只需将编译器的副本粘贴到语言运行库中即可。是众多优秀的编译器之一。Lisp通常是编译的。已经有使用JIT编译器而不是解释器的实现

    因此,这是没有必要的