1 个不稳定版本

0.1.0 2019 年 11 月 13 日

#1196开发工具

0BSD 许可证

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

该程序由两个单词组成,将值12推送到堆栈。Kari不关心您使用哪种空白字符来分隔单词,因此以下程序完全等效。

1
2

到目前为止,我们只看了那些将单词推送到堆栈的函数。但当然,函数也可以从堆栈中弹出值。

1 2 +

该程序将值12推送到堆栈。然后+函数将弹出这两个数字并推回它们的和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

参考

目前没有参考文档解释所有语言功能、内置函数和标准库。请参考以下资料

许可

在此特此授予使用、复制、修改和/或以任何目的(无论是否付费)分发此软件的许可权。

本软件按“原样”提供,作者放弃与此软件有关的所有保证,包括所有关于适销性和适用性的暗示保证。在任何情况下,作者均不对任何特殊、直接、间接或后果性损害或任何因使用、数据或利润损失而导致的损害负责,无论这些损害是因合同、疏忽或其他侵权行为造成的,无论这些损害是否与使用或性能有关。

依赖项

~0.8–8.5MB
~52K SLoC