2 个版本
0.1.1 | 2021 年 12 月 10 日 |
---|---|
0.1.0 | 2021 年 12 月 10 日 |
#753 在 编程语言 中
每月 70 次下载
47KB
881 行
quilt
一种编程语言
目录
安装
使用 cargo
cargo install quilt-lang
使用 docker
docker run --rm ghcr.io/quilt-lang/quilt
用法
quilt examples/hello_world.png
quilt --pixel-size 20 examples/hello_world_x20.png
开发
有用的命令
- 运行所有检查:
make check
- 使用 ImageMagick 缩放图像:
convert -scale 500% foo.png foo_x5.png
- 构建 docker 镜像:
docker build . -t quilt:<TAG>
文档
哲学
与其他编程语言不同,quilt 采用一种 极简主义 方法来构建程序。而不是“尽可能简单,不能再简单”,quilt 程序员被鼓励构建精美、多彩且华丽的程序。
在 Quilt 中编写程序
quilt 中的程序通过制作由像素组成的图像来构建。默认情况下,每个像素将被认为宽度为 1,高度为 1,但可以通过 --pixel-size
命令行参数进行调整。每条指令被定义为色调值的范围,以给程序员一些关于程序颜色的灵活性。色调是唯一考虑的参数;饱和度和亮度被忽略。
路径
执行从具有精确色调 300
的 START
像素开始;这是唯一不是色调范围的指令。执行继续沿着 道路 进行。道路可能是最常用的 quilt 指令,告诉程序“去哪里”。这意味着 quilt 程序除了有程序计数器外,还有一个方向。
优先级
当面临多个要执行/跟随的道路指令时,有一些规则关于执行将去哪里
- 道路始终比其他任何指令具有更高的优先级。
- 如果存在多条道路可以选择,则优先级将按照以下顺序应用:
- 首先考虑'前方'道路(与当前方向相同),如果存在的话。如果不存在,Quilt将接着考虑顺时针方向,然后是逆时针方向。如果在任何这三个方向上都没有道路,Quilt将采取'前方'指令。如果没有前方指令(这意味着程序计数器位于图像的边界上),执行将返回原路,无论该方向是否有道路。这意味着之前执行的指令将以相反的顺序重复。
这种优先级类似于右侧行车系统的驾驶。'右边'(逆时针方向)的指令总是先于其他指令考虑;唯一的例外是首先尝试前进方向;然后是右边,然后是左边,最后是后退。
参数
一些Quilt指令需要参数。参数始终是执行方向上的指令后的像素。参数的值将是该像素的色调。这意味着所有参数的最大值为360,因为这是色调的最大值。当像素作为参数被消耗时,它被视为数据。同样的像素,如果从不同的方向遇到,也可以被视为指令。
内存
Quilt提供堆栈、地址寄存器和磁带(一维数组)。要访问磁带,您必须使用MOVA
命令('A'代表'地址')将地址推送到地址寄存器中,然后是地址。要使用SAVE
命令将数据存储到磁带上,该命令写入tape[<地址 在地址寄存器>]
。您可以使用PUSH
将常数推送到堆栈上,后面跟一个带有要推送到堆栈上的色调值的像素数据。使用POP
从堆栈中弹出并丢弃结果。POPA
从堆栈中弹出并将其写入tape[<地址 在地址寄存器>]
。PUSHA
将tape[<地址 在地址寄存器>]
中的值复制到堆栈上。所有像ADD
、SUB
等算术指令都从堆栈中弹出两个参数并推入结果。
循环、条件判断和停止
有两个指令值得特别注意:pop-until
和output-until
。这两个命令都从堆栈中弹出,直到满足某个条件,并且output-until
还会输出它从堆栈中弹出的值。默认情况下,它们将堆栈中弹出的每个元素与0进行比较,只有当弹出的元素等于0时才停止。此逻辑可以通过条件进行更改。
条件类似于循环参数,它告诉指令要执行哪种比较。有六种:相等、不等、小于、小于等于、大于、大于等于。将条件放置在循环的角落将向循环指示要使用哪种比较。条件范围如下:
色调范围 | 比较 |
---|---|
默认 | 相等 |
0-8 | 不等 |
72-80 | 小于 |
144-152 | 小于等于 |
216-224 | 更大的 |
288-296 | 大于等于 |
一个角落被定义为向左回退一个像素,再顺时针移动一个像素:
在上面的例子中(来自 fib(n) -- 见下文),程序在这一点的方向是 东
。道路上橙色像素的色相为 18,因此是一个 pop-until
。其条件是逆时针方向前一个像素的红像素(如果你向东行进,这将是 pop-until
前的方格的右边)。它的色相为 0,因此告诉 pop-until
指令弹出循环中的元素,直到找到一个不等于 0 的元素(见上面的图表)。如果上述范围内没有提供条件,所有 pop-until
和 output-until
指令将继续执行,直到找到 0。
从堆栈中弹出是停止程序的唯一方法:优雅退出的方法是当没有剩余元素时从堆栈中弹出。
Quilt 指令
以下是从 commands.md
中提取的表格
命令名称 | 色调范围 |
---|---|
PUSHA |
0-8 |
POP UNTIL |
18-26 |
PUSH <数字> |
36-44 |
SAVE <数字> |
54-62 |
MOVA <地址> |
72-80 |
POPA |
90-98 |
ADD |
108-116 |
SUB |
126-134 |
MULT |
144-152 |
DIV |
162-170 |
ROAD |
180-188 |
LEFTSHIFT |
198-206 |
RIGHTSHIFT |
216-224 |
AND |
234-242 |
OR |
252-260 |
NOT |
270-278 |
XOR |
288-296 |
OUTPUT |
306-314 |
OUTPUT UNTIL |
324-332 |
MODULO |
342-350 |
START |
300 |
示例
你好,世界!

此 quilt 程序将 Hello world
打印到标准输出,后跟换行符。quilt 中的所有输出都是文本到标准输出。没有标准库,因此不支持其他输出格式。
执行从图像的左下角开始。此像素的色相为 300,因此它是起始像素。quilt 然后沿着蓝色的路螺旋式地向图像中心移动,那里有其他指令。跟随道路后发生的第一件事是到达初始橙色像素,其色相为 36。查阅上述表格,我们看到这是一个 push
指令。由于道路转向了南方,执行方向面向南方,并且它期望在这一点上得到参数。push 后面的红色像素的色相为 0,并且是参数。因此,现在堆栈中已推送了一个 0。然后我们推送一个 10:\n
。你可以看到我们进行了一系列的推送,有时在道路之间进行推送以转向执行并继续螺旋模式。我们将 Hello world
的其余部分的 ascii 表示法反向推送。然后 quilt 读取内循环右上角的黄色像素,此时堆栈如下所示:0 10 33 100 108 114 111 119 32 111 108 108 101 72(这是 Hello world\n0
的反向 ascii)。然后我们跟随道路,直到我们到达色相为 324 的粉色正方形。在上面查看,我们看到这是一个 output-until
指令,它从堆栈中弹出并输出,直到它看到一个 0。
图像中在蓝色道路之间的所有紫色实际上是一个 or
指令,但由于 quilt 的优先级规则,它从未被执行,因此技术上可以是任何颜色,除了道路。
Fib(n)
由于没有输入,为了计算fib(n),必须将n硬编码到程序中。改变(11, 29)像素的色调将改变n
。在这幅图中,它是6。此外,quilt没有提供打印长度超过一个数字的方法,因此对于输入>6(其中fib(n).to_string().len() > 1
)的输出将只能以fib(n)对应值的ascii字符形式可见。

此程序将1 1 2 3 5 8
打印到stdout。其工作原理留给读者练习。
依赖项
~16MB
~118K SLoC