2 个版本

0.1.1 2021 年 12 月 10 日
0.1.0 2021 年 12 月 10 日

#753编程语言

Download history • Rust 包仓库 1/week @ 2024-03-26 • Rust 包仓库 10/week @ 2024-04-02 • Rust 包仓库

每月 70 次下载

MIT 许可证

47KB
881

quilt

Crates.io MIT License Downloads Lines of code Rust CI

一种编程语言

目录

  1. 安装
  2. 用法
  3. 开发
  4. 文档
    1. 哲学
    2. 在 Quilt 中编写程序
    3. Quilt 指令
  5. 示例

安装

使用 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 命令行参数进行调整。每条指令被定义为色调值的范围,以给程序员一些关于程序颜色的灵活性。色调是唯一考虑的参数;饱和度和亮度被忽略。

路径

执行从具有精确色调 300START 像素开始;这是唯一不是色调范围的指令。执行继续沿着 道路 进行。道路可能是最常用的 quilt 指令,告诉程序“去哪里”。这意味着 quilt 程序除了有程序计数器外,还有一个方向。

优先级

当面临多个要执行/跟随的道路指令时,有一些规则关于执行将去哪里

  1. 道路始终比其他任何指令具有更高的优先级。
  2. 如果存在多条道路可以选择,则优先级将按照以下顺序应用:
    • 首先考虑'前方'道路(与当前方向相同),如果存在的话。如果不存在,Quilt将接着考虑顺时针方向,然后是逆时针方向。如果在任何这三个方向上都没有道路,Quilt将采取'前方'指令。如果没有前方指令(这意味着程序计数器位于图像的边界上),执行将返回原路,无论该方向是否有道路。这意味着之前执行的指令将以相反的顺序重复。

这种优先级类似于右侧行车系统的驾驶。'右边'(逆时针方向)的指令总是先于其他指令考虑;唯一的例外是首先尝试前进方向;然后是右边,然后是左边,最后是后退。

参数

一些Quilt指令需要参数。参数始终是执行方向上的指令后的像素。参数的值将是该像素的色调。这意味着所有参数的最大值为360,因为这是色调的最大值。当像素作为参数被消耗时,它被视为数据。同样的像素,如果从不同的方向遇到,也可以被视为指令。

内存

Quilt提供堆栈、地址寄存器和磁带(一维数组)。要访问磁带,您必须使用MOVA命令('A'代表'地址')将地址推送到地址寄存器中,然后是地址。要使用SAVE命令将数据存储到磁带上,该命令写入tape[<地址 地址寄存器>]。您可以使用PUSH将常数推送到堆栈上,后面跟一个带有要推送到堆栈上的色调值的像素数据。使用POP从堆栈中弹出并丢弃结果。POPA从堆栈中弹出并将其写入tape[<地址 地址寄存器>]PUSHAtape[<地址 地址寄存器>]中的值复制到堆栈上。所有像ADDSUB等算术指令都从堆栈中弹出两个参数并推入结果。

循环、条件判断和停止

有两个指令值得特别注意:pop-untiloutput-until。这两个命令都从堆栈中弹出,直到满足某个条件,并且output-until还会输出它从堆栈中弹出的值。默认情况下,它们将堆栈中弹出的每个元素与0进行比较,只有当弹出的元素等于0时才停止。此逻辑可以通过条件进行更改。

条件类似于循环参数,它告诉指令要执行哪种比较。有六种:相等、不等、小于、小于等于、大于、大于等于。将条件放置在循环的角落将向循环指示要使用哪种比较。条件范围如下:

色调范围 比较
默认 相等
0-8 不等
72-80 小于
144-152 小于等于
216-224 更大的
288-296 大于等于

一个角落被定义为向左回退一个像素,再顺时针移动一个像素:屏幕截图 2021-12-09 上午10:55:06

在上面的例子中(来自 fib(n) -- 见下文),程序在这一点的方向是 。道路上橙色像素的色相为 18,因此是一个 pop-until。其条件是逆时针方向前一个像素的红像素(如果你向东行进,这将是 pop-until 前的方格的右边)。它的色相为 0,因此告诉 pop-until 指令弹出循环中的元素,直到找到一个不等于 0 的元素(见上面的图表)。如果上述范围内没有提供条件,所有 pop-untiloutput-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

示例

你好,世界!

Screen Shot 2021-12-09 at 1 07 49 PM

此 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字符形式可见。

Screen Shot 2021-12-09 at 11 04 25 PM

此程序将1 1 2 3 5 8 打印到stdout。其工作原理留给读者练习。

依赖项

~16MB
~118K SLoC