1 个不稳定版本

0.1.0 2019年2月28日

#806编程语言

146 星 & 9 关注者

26KB
543

Atto

Atto 是一款疯狂简单的函数式编程语言。

它具有由波兰表示法驱动的完全语法,没有分隔符(它忽略了所有非分隔空白)。这种简单性带来了什么?嗯...一个拥有约 200 行自托宿解释器的疯狂简单语言。

尽管存在这些设计限制,实际上在 Atto 中编写相当令人愉悦的代码是可能的。结合异常可扩展的语法(您可以定义自己的运算符,或者覆盖在 core 库中定义的运算符),这使得它非常适合解决通常在更指令性语言中难以解决的问题。

设计

Atto 的设计极其简单。有两种类型的结构

函数: fn <name> [args] is <expr>

表达式: <literal> [expr]

就是这样。表达式、函数调用、字面量和操作都被视为同一件事。

我留给您一个快速阶乘计算示例,展示 Atto 的紧凑表达性。

fn f n is
  if = n 0
    1
  * n f - n 1

是的,就是这样。

用 Atto 编写的 Atto 解释器

examples/self-hosted.at,我编写了一个基于 REPL 的完全功能的 Atto 解释器。它支持函数声明、函数调用以及 Atto 所有的评估运算符,包括 I/O。它存在一些小问题,如对无效输入的反应不可预测。然而,它应该能够成功运行任何有效的 Atto 程序(假设您的堆足够大)。

这让我想起:我需要在Rust解释器中使用一个非递归解释算法。另外,尾调用优化会很好。

核心库

Atto附带一个core库。它提供了一系列非内建函数和实用工具,这些函数和工具也是用Atto编写的。此外,它提供了Atto使用中常见的所有运算符。Atto解释器隐式地在您运行的内容之上插入core库,其性质类似于C的#include

  • # x y:忽略第一个值,只评估第二个(用于注释)
  • @ x y:忽略第二个值,只评估第一个
  • ! x:取反布尔值
  • wrap x:将值包裹在列表中
  • empty:生成空列表
  • debug_enabled:可以重写以启用调试工具
  • debug i x:以信息标签x显示x的值
  • assert i x:断言x为真
  • assert_eq x y:断言xy等价
  • is_atom x:确定一个值是否为原子(即:null、布尔值或数字)
  • is_str x:确定一个值是否为字符串
  • is_list x:确定x是否为列表
  • is_bool x:确定x是否为布尔值
  • is_num x:确定x是否为数字
  • is_null x:确定x是否为null
  • len l:确定列表的长度
  • skip n l:跳过列表中的前n个值
  • nth n l:获取列表中的第n个元素
  • in x l:确定x是否在列表中
  • split i l:将列表分割为两个单独的列表,在索引i处分割

您可以在src/atto/core.at上查看有关core提供的完整文档。

教程

基本算术运算符

fn main is
	+ 5 7

生成:12

fn main is
	- * 3 3 5

生成:4

将值打印到控制台

fn main is
	print "Hello, world!"
fn main is
	print str 1337

从用户接收输入并将它们转换为值

fn main is
    print + "Product = " str
    	* litr input "second: "
          litr input "first: "

将值配对成二维列表

fn main is
	pair 3 17

生成:[3, 17]

合并列表

fn main is
	fuse pair 3 17 pair 5 8

生成:[3, 17, 5, 8]

条件表达式

fn main is
	if true
		10
		5

生成:10

fn main is
	if false
		10
		5

生成:5

选择列表中的第一个值

fn main is
	head pair 3 17

生成:3

选择列表头部之后的部分值

fn main is
	tail fuse 3 fuse 17 9

结果: [17, 9]

将字符串转换为值

fn main is
	- 7 litr "3"

生成:4

fn main is
	+ 7 litr "8.5"

结果: 15.5

fn main is
	= null litr "null"

结果: true

定义带参数的函数

fn add x y is
	+ x y

fn main is
	add 5 3

结果: 8

递归查找列表大小

fn size l is
	if = null head
		0
		+ 1 size tail l
fn main is
	size fuse 1 fuse 2 3

生成:3

优化

目前,Atto的Rust解释器几乎不进行优化。尽管如此,以下我将尝试讨论一些我觉得很有希望的想法。

Atto的设计不允许在函数内部重新分配值,也不允许修改。这,以及语法解析非常快速,使其成为许多优化极好的潜在目标。内联、常量传播、CSE检测和尾调用优化在Atto的设计之上自然容易实现。

重新分配的缺乏也意味着Atto的设计是仿射类型系统 按设计,无需编译器对移动语义分析或类似的支持。

一些真正令人印象深刻的优化障碍是它的动态类型系统。然而,在许多情况下,类型很可能在编译时推断出来,并为每个函数生成针对传递给它的类型的专用机器代码。

我还在为Atto的静态类型版本工作。然而,我还没有确定一个足够简单的设计,以补充当前的设计。

依赖关系

~4MB
~66K SLoC