POP-2000,一种通用POP-2方言
摘要
POP-2000是POP-2编程语言的一个新方言,旨在作为小型编译器和底层系统的通用语言,强调最小化语法和易于实现。
<p><a href="https://lobste.rs/s/w0d3um/pop_2000_lingua_franca_pop_2_dialect">评论</a></p>
查看缓存全文
缓存时间: 2026/08/25 03:38
# POP-2000,一种通用的 POP-2 方言
来源:https://hitogata.neocities.org/POP-2000
> 撰写于 2026-08-24
Devine(https://wiki.xxiivv.com/site/devine_lu_linvega.html)(因 Uxn(https://100r.co/site/uxn.html)而闻名)和我一直在深入讨论 POP-2(https://en.wikipedia.org/wiki/POP-2),这是一种源自 1970 年代的语言,最初与最早的 Lisp 方言在同一批开发者圈子里使用。
Devine 一直在研究用高级语言为 Uxn 编写新的汇编器,以协助引导 Uxn 系统的启动;而我个人则一直对那些能够成为优秀“微型编译器”的语言很感兴趣。我们由此发现了 POP-2(https://en.wikipedia.org/wiki/POP-2),认为它非常适合成为连接所有这些微型系统的通用语。
## 微型编译器(或者说,我为何不那么喜欢连接式编程)
我知道这个标题有点疯狂。别误会,我喜欢连接式编程范式——它通过并置和组合来形成新函数/构造的方式确实非常优雅。但我在为 ok(https://hitogata.neocities.org/ok.html)撰写的论文中试图阐明的一点是,我并非特别被连接式语言的这些特性所吸引——相反,我喜欢连接式语言是因为编写其解释器/编译器简直*容易得离谱*,同时(通常,但并非总是)还能提供一些底层控制——至少,与我平时喜欢玩的其他语言(如 C 或 Odin)相比是如此。
作为一个在接触计算机编程之前就创造了大量人造语言的人,我更关心的是语言开发的层面,而不是实际制作软件。具体来说,当我在构思一种编程语言时,我通常有以下目标:
- 尽可能容易地为给定系统实现解释器/编译器,理想情况下基本不使用任何外部工具/库进行解析或代码生成
- 相当“可用”(这个描述相当模糊和主观,但实质上它“不应该看起来像一个极简语言”,遵循“我看到就知道”的描述原则)
- 最小化的语法
- 最少的功能集,基本上只包含引导编译器/解释器所需的最低限度(这应该是在语言能运行后立即定为目标)
- 具有一些底层控制/支持“系统编程”,至少足以用该语言编写一个操作系统是可行的
- 应该能在小型系统上运行(通常我会设定我的最低期望是 ok(https://hitogata.neocities.org/ok.html)的水平,即大约 16MiB 内存且还有余量,但 Uxn(https://100r.co/site/uxn.html)或像 6502(https://en.wikipedia.org/wiki/MOS_Technology_6502)这样的处理器甚至更好)
连接式语言,以及通常面向小型/底层栈式虚拟机的语言,恰好非常契合这些约束条件。我并非因为认为连接式范式本身更优越而喜欢连接式语言,而是喜欢它们是因为连接式使得创建编程语言的实现问题变得*美妙地*小巧。其好处自然延伸到支持这类系统的经典论点(例如 permacomputing(https://viznut.fi/texts-en/permacomputing.html)等等)。
## 关于 POP-2 的一点介绍
如果你看看我之前概述的语言设计目标,并将它们与原始 POP-2 论文(http://bitsavers.informatik.uni-stuttgart.de/pdf/univOfEdinburgh/POP-2_Papers_1968.pdf)中概述的目标进行比较,你会发现它们基本上是相同的:
POP-2 的设计目标
Devine 的 POP-2 文章(https://wiki.xxiivv.com/site/pop2.html)很好地概述了为 Uxn 目标编写的 POP-2 方言,但简而言之,一个最小化的 POP-2 实现支持用 `vars x y z;` 一次性声明多个变量,用 `function myfunc a b;` 声明函数(后跟函数体和 `end`),基本的 `if`/`elseif`/`else` 控制流,使用 `=>` 进行 I/O,以及通过标签和 goto 进行循环。POP-2 *巧妙*之处在于,值会操作底层栈——根据 Devine 自己的文章:
```
function sum x y;
x + y;
end
sum(5, 6) * 2;
```
也可以用*这种方式*轻松编写,因为 `sum` 的参数只是被压入栈,`sum` 返回的值也只是被压入栈——而且,遇到像 `+` 这样的运算符时,它只是查看表达式中的下一个元素,将*该*元素压入栈,然后弹出该元素和栈中的下一个元素将它们相加:
```
function sum x y;
x; + y;
end
5; 6; sum(); * 2;
```
凭借这种与生俱来的基于栈的特性,只需添加一些基本的内存管理、针对不同系统的不同宽度值的支持,以及一个更通用的 I/O 系统,就足以形成一种便捷、对初学者友好的语言,它可以运行在众多微型系统上——不是替代这些系统*现有*语言,而更多是一种社会性实践,让新手从一种既容易学习又能在我们众多小型系统上运行的语言开始,同时这种语言对于我们这些小型系统的创造者来说,实现起来也足够容易。
## POP-2000,一个温和的提议
POP-2000(或 POP2K,我们尚未完全确定名称)是 POP-2 的一种标准化方言,目标是添加我们希望在我们的小型系统上使用的系统级支持,同时定义非常明确(如果你仔细研读 POP-2 论文的参考部分,其语法是有定义的,但*极其*晦涩难懂)。
过去几天我一直在不间断地开发它,同时在连接式 Discord 服务器上与 Devine(更像是“不停地骚扰 Devine”)讨论语法、语法结构等方面应该支持或添加哪些特性。
我希望能很快在网上发布更多细节——再次说明,就在不到一周前,这整个事情还只是一个“如果怎样”。我几乎已经完成了用 EBNF(https://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_form)记法编写的该语言的语法。我会很快创建一个包含“标准”的 Git 仓库(正在考虑不用 GitHub,考虑到其糟糕的忽视以及与 ICE(https://www.vox.com/recode/2019/10/9/20906605/github-ice-contract-immigration-ice-dan-friedman)的关系),一旦创建,我会将其添加到本文中。不过与此同时,我想先写写正在进行的工作。
我还希望用 C 语言为该语言编写一种参考实现的编译器,最初以 ok(https://hitogata.neocities.org/ok.html)为目标,这意味着很快我们的小型虚拟机将拥有一种高级语言!
### POP-2000 EBNF 语法(进行中)
目前,我用 EBNF 记法编写的*完整语法*如下(未来可能会有变动):
```
program = { element } ;
element = function
| vars
| imperative ;
function = "function" , identifier , [ params ] , ";" ,
[ function_body ] ,
"end" ;
const = "const"
vars = "vars" , var , { var } , ";" ;
var = identifier , [ ":" , ( integer | string ) ] ;
imperative = if
| ( statement_sequence , ";" ) ;
if = "if" , expression , "then" , [ body ] ,
{ "elseif" , expression , "then" , [ body ] } ,
[ "else" , [ body ] ] ,
"close" ;
body = { imperative | vars } , [ statement_sequence ] ;
statement_sequence = statement , { ";" , statement } ;
statement = goto
| labeled_statement
| expression_list ;
(* "return" 只允许出现在函数体内,
解析器应强制执行此规则 *)
goto = "goto" , identifier
| "return" ;
labeled_statement = label , { imperative } ;
label = identifier , ":" ;
expression_list = expression , { "," , expression } ;
expression = io ;
io = "=>" , primary
| assign ;
assign = "->" , primary
| apply ;
apply = "<>" , primary
| shift ;
shift = ( "<<" | ">>" ) , primary
| comparison ;
comparison = ( "<" | ">" | "=" | "!" ) , primary
| term ;
term = ( "+" | "-" ) , primary
| factor ;
factor = [ "*" | "/" | "%" ] , primary ;
primary = call
| reference
| quotation
| grouping
| index
| identifier
| literal ;
call = identifier , "(" , [ expression_list ] , ")" ;
reference = "#" , identifier ;
quotation = "@" , identifier ;
grouping = "(" , expression , ")" ;
index = "{" , expression , "}" ;
identifier = ( letter | "_" ) , { letter | digit | "_" } ;
literal = integer
| hexadecimal
| string ;
integer = digit , { digit } ;
hexadecimal = "0x" , hex_digit , { hex_digit } ;
string = "\"" , { string_char } , "\"" ;
string_char = ? any printable character except for double-quotes and backslash ?
| "\\\"" (* C风格转义双引号,使用 \" *)
| "\\" ; (* C风格转义反斜杠 *)
letter = "A" ... "Z"
| "a" ... "z" ;
digit = "0" ... "9" ;
hex_digit = digit
| "A" ... "F"
| "a" ... "f" ;
```
相似文章
几只野猫穿着ALGOL风衣。
POP-2是一种具有类似ALGOL语法和连接式求值的编程语言,提供基于栈的操作,并为Uxn等系统提供高效编译。它包括变量、函数、循环和I/O的简单结构,使其适合复古计算环境。
Opus 是一个基于 f 表达式(内核语言)语义的最小化、静态作用域的 Lisp 方言
Opus 是一个在 Haskell 中实现的、最小化、静态作用域的 Lisp 方言,它使用 Continuation-Passing Style 并编译为 WebAssembly,具有操作性原语以提供表达力
T3X/0:一门极简的过程式语言
T3X/0 是一门极简的过程式编程语言,提供免费编译器,旨在用于教学,并能在 Unix、DOS 和 CP/M 等系统间实现跨系统兼容性。
FreeOberon – 开源、跨平台,类似 Free Pascal/Turbo Pascal 的语言
FreeOberon 是一个用于 Oberon 编程语言的开源、跨平台 IDE 和编译器,其设计采用了 Pascal 环境经典的伪图形风格。
AP8L - apl
AP8L 是一种受 APL 启发的编程语言,嵌入在 PICO-8 中,支持类似 APL 的函数和基本图形。