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
:断言x
和y
等价is_atom x
:确定一个值是否为原子(即:null、布尔值或数字)is_str x
:确定一个值是否为字符串is_list x
:确定x
是否为列表is_bool x
:确定x
是否为布尔值is_num x
:确定x
是否为数字is_null x
:确定x
是否为nulllen 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