许多编写游戏程序和其他应用程序的人在应用程序中嵌入了一种语言,以允许用户编写小程序。
据我所知,最流行的embedded languages 大概是最流行的第一顺序(尽管“更流行”并不一定意味着“更好”)似乎是:
- 专为这一特定应用程序定制的领域特定语言,其他任何地方都没有使用
- 卢阿a
- Tcl
- Python a b,通常是简化的子集,例如 PyMite c
- 第四次
- JavaScript a
- Lisp
- AngelScript a
- XPL0 a b
- 松鼠a
- Haskell a b
- NPCI(纳米伪 C 解释)a
- RoboTalk
- 解释一些硬件机器语言(为什么这是最不受欢迎的选择?有充分的理由,如下所述)。
您可能想查看 Gamedev StackExchange,特别是像 "How do you add a scripting language to a game?" 这样的问题。
您可能想在 StackOverflow 上查看标记为 "embedded language" 的一些问题;
如
"Selecting An Embedded Language",
"What is a good embeddable language I can use for scripting inside my software?"
"Alternatives to Lua as an embedded language?"
"Which game scripting language is better to use: Lua or Python?",
等等
这些语言的许多实现都使用某种
bytecode 内部。
通常,同一高级编程语言(如 JavaScript)的两种不同实现在内部使用两种完全不同的字节码语言(a)。
通常几种高级编程语言编译成相同的底层字节码语言——例如,Python 的 Jython 实现、JavaScript 的 Rhino 实现、Tcl 的 Jacl 实现、JScheme 和 Scheme 的其他几种实现,以及 Pascal 的几种实现;都编译成相同的 JVM 字节码。
详情
为什么要使用脚本语言而不是解释某些硬件机器语言?
为什么是"Alternate Hard And Soft Layers"?
为了获得简单性和更快的开发。
更快的开发
人们通常使用脚本语言而不是编译语言来更快地工作。
让初始原型工作通常要快得多——解释器会处理一堆机器语言强制你显式写出的幕后东西:将变量的初始值设置为零、子程序序言和子程序-epilog 代码、malloc 和 realloc 以及 free 和相关的内存管理东西,当容器满时增加容器的大小,等等。
一旦有了初始原型,添加新功能就会更快:脚本语言具有快速的编辑-执行-调试周期,因为它们避免了编译语言的编辑-编译-执行-调试周期的“编译”阶段。
简单
我们希望嵌入式语言在两个方面“简单”:
如果用户想编写一个小代码来完成一些概念上微不足道的任务,我们不想用复杂的语言吓跑这个人,需要 20 磅的书和几个月的学习才能编写没有缓冲区溢出的“Hello, $USER”。
由于我们正在实现该语言,我们想要一些易于实现的东西。也许一些简单的底层指令我们可以在一个周末敲出一个简单的解释器,也许我们可以通过最少的调整来重用某种预先存在的编译器。
当人们构建 CPU 时,硬件限制总是会限制指令集。
许多概念上“简单”的操作——人们一直在使用的东西——
最终需要大量机器语言指令来实现。
嵌入式语言没有这些硬件限制,允许我们实现
更复杂的“指令”执行(对人类而言)在概念上看起来很简单的事情。
这通常会使系统在上述两种方面变得更简单:
直接使用该语言编写代码的人(或为该语言编写编译器的人)最终编写的代码要少得多,单步调试代码所花费的时间也更少,等等。
对于每个这样的高级操作,我们将复杂性从编译器转移到解释器内的指令实现。与其(您编写代码)编译器将一些更高级别的操作分解为中间语言中的一个短循环(并在运行时在解释器中反复单步执行该循环),不如编译器以中间语言发出一条指令(并且您在解释器对该中间“指令”的实现中编写相同的一系列操作)。使用编译语言(“内部”复杂指令)实现所有 CPU 密集型的东西,极其简单的解释器通常足够快。 (即,您避免花费大量时间构建 JIT 或尝试以其他方式加快速度)。
由于这些原因和其他原因,许多游戏程序员使用“脚本”语言作为他们的“嵌入式语言”。
(我现在看到 Javier 已经建议“使用嵌入式脚本语言”,
所以这变成了对为什么这是解释硬件机器语言的一个很好的替代方案,并在一种特定的脚本语言似乎不适合时指出替代方案的长篇大论。