1 个不稳定版本
0.1.0 | 2019 年 11 月 13 日 |
---|
#1196 在 开发工具
91KB
3K SLoC
卡里
简介
"std" import
"The answer to live is: " print
1 [ 2 3 7 ] [ * ] fold println
卡里是一种编程语言,它是
- 可嵌入的:设计用于嵌入到宿主应用程序中。
- 解释的:语言由解释器解析和执行。
- 动态的:类型在运行时进行检查。
- 强类型:类型转换始终是显式的。
- 基于堆栈的:没有变量。所有数据都生活在隐式堆栈上。
- 后缀:操作由其参数 precedes
卡里是一种通用语言,但本身具有与外界交互的非常有限的能力。它被设计为嵌入到宿主应用程序中,该应用程序可以扩展它以提供所需的任何特定领域功能。
卡里是用 Rust 编写的,并设计为嵌入到 Rust 应用程序中。
示例用例包括
- 在 CAD 应用程序中计算几何定义。
- 作为游戏引擎的脚本语言。
- 一个用于复杂应用程序的图灵完备配置语言。
以及你可以想到的任何其他东西。
当前状态
卡里可以使用,但仍然非常原始和不成熟。它缺少许多基本功能,并且目前可以扩展的方式有限。除非你对在解释器上工作感到完全舒适,否则不要将卡里用于任何严肃的事情。
话虽如此,如果你喜欢这里提出的概念并且愿意尝试,卡里可能是一个不错的起点。
用法
你可以这样运行 Kari 程序(需要 just
)
git clone https://github.com/kari-lang/kari.git
just run hello # or run any other example from `kr/examples`
just test # run all tests from `kr/tests`
要运行自己的程序,你应该能够 cargo install
Kari 解释器,并使用它来运行程序,无论它们位于何处。这目前尚未记录。
要在您的应用程序中嵌入 Kari 程序,请依赖于 kari
crate
# Cargo.toml
[dependencies]
kari = "0.1"
Kari API的主要入口点是Evaluator
。您可以使用它的API来运行Kari程序。目前这部分尚未文档化。
教程
Kari是一种基于堆栈的连续语言,这意味着没有变量,所有数据都存在于隐式堆栈上。考虑以下Kari程序。
1
该程序由一个单词组成,1
,它将值1
推送到堆栈。整数实际上是作为特殊语法实现的,但从概念上看,您可以将1
视为一个不接受输入并将值1
推送到堆栈上的函数。
Kari中的单词由空白字符分隔。包含多个单词的程序将按顺序执行这些单词所引用的函数。
1 2
该程序由两个单词组成,将值1
和2
推送到堆栈。Kari不关心您使用哪种空白字符来分隔单词,因此以下程序完全等效。
1
2
到目前为止,我们只看了那些将单词推送到堆栈的函数。但当然,函数也可以从堆栈中弹出值。
1 2 +
该程序将值1
和2
推送到堆栈。然后+
函数将弹出这两个数字并推回它们的和3
。所以程序结束时堆栈上只剩下值3
。
我们可以通过添加注释来使这个程序更具说明性。
1 2 + # sums up `1` and `2`, leaving `3` on the stack
注释从#
开始,直到下一行结束。
Kari中除了数字之外还有其他值。
true # a boolean
1 # an integer
2.0 # a float
"a string"
:a_symbol # symbols are much like strings, except they don't allow whitespace
[ 1 2 3 ] # a list of numbers
[ "a" "list" "of" "strings" ]
我们可以调用更多函数。其中一些是内置函数,定义在全局命名空间中,其他的是定义在Kari的标准库中,需要导入。以下程序将加载标准库并将其函数导入本地命名空间。
"std" import
完成此操作后,我们可以使用在std
中定义的函数以及内置函数。
"std" import
"Hello, world!" println # prints "Hello, world!" and a line break
1 2 = # compares `1` and `2`; leaves `false` on the stack, as they're not equal
true assert # will do nothing, but `false assert` would have failed the program
由于所有函数都共享隐式堆栈,我们可以一起更改不同的函数以创建更复杂的操作。
1 2 + # add `1` and `2`, leaving `3` on the stack
3 = # push another `3`, compare those `3`s using the equals operator
# `3` and `3` are equal, so the previous operation left `true` on the stack
assert # assert that the top value on the stack is `true`; consumes the value
或者更短
1 2 + 3 = assert # test the `+` function
关于Kari提供的函数还有很多东西要学习,但让我们以一个重要的概念结束这个教程:如何定义自己的函数。
我们已经看到了理解函数定义所需的所有概念
- 我们已经看到了列表,匿名函数只是单词列表。
- 我们已经看到了符号,它可以用来定义函数名。
我们最后缺少的是内置函数define
,它接受匿名函数和符号来定义新的命名函数。
[ 2 + ] :add_two define
1 add_two 3 = assert
参考
目前没有参考文档解释所有语言功能、内置函数和标准库。请参考以下资料
- 存储库中的Kari代码。请注意,许多示例已经过时且无法工作,但测试是最新更新的。
- 定义所有内置函数的builtins.rs文件。
- Kari标准库。
许可
在此特此授予使用、复制、修改和/或以任何目的(无论是否付费)分发此软件的许可权。
本软件按“原样”提供,作者放弃与此软件有关的所有保证,包括所有关于适销性和适用性的暗示保证。在任何情况下,作者均不对任何特殊、直接、间接或后果性损害或任何因使用、数据或利润损失而导致的损害负责,无论这些损害是因合同、疏忽或其他侵权行为造成的,无论这些损害是否与使用或性能有关。
依赖项
~0.8–8.5MB
~52K SLoC