2 个版本

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

#753编程语言

Download history 1/week @ 2024-03-26 10/week @ 2024-04-02

每月 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