#编程语言 #语言 #脚本语言 #动态 #脚本 #评估 #编程

bin+lib chap

Chap 是一种易于学习、解释性、用 Rust 编写的脚本语言

3 个稳定版本

2.2.2 2024年6月6日
2.2.1 2024年6月5日
2.0.1 2024年5月2日

93编程语言 中排名

Download history 145/week @ 2024-05-02 3/week @ 2024-05-16 3/week @ 2024-05-23 92/week @ 2024-05-30 213/week @ 2024-06-06 8/week @ 2024-06-13 6/week @ 2024-06-27 22/week @ 2024-07-04

136 每月下载量

GPL-3.0 许可证

140KB
3K SLoC

Chap

forthebadge made-with-rust
Rust GitHub license

Chap 是一种易于学习、动态、解释性、无关键词的语言,用 Rust 编写。

记住,Chap 不是一个工具!它是艺术。

语法介于 Lisp汇编PHP 之间。

ChapApp 是一个基于浏览器的离线 Chap 编辑器/编译器(由 WASM 支持)。ChapApp 也用 Rust(Dioxus)编写。在新标签页中打开 ChapApp

目录

  1. 为什么命名为 'Chap'?
  2. 功能
  3. 关键词
  4. 语法
  5. 运算符
  6. 控制流
  7. 示例
  8. 数据类型
  9. 内存管理
  10. 安装
  11. 如何使用
  12. 内置函数

名称

Rust 或 راست 在波斯语中意为“正确”,Chap 或 چپ 意为“左边”。

如果你在 Rust(正确)上编写代码过多,不久后你可能会逐渐成为资本主义者。所以你需要写一些 Chap(左边)来逃离矩阵。

Chap 解锁了 二维 全栈开发。前端⬆️、后端⬇️、Rust➡️、Chap⬅️。

功能

  1. 易于学习。
  2. 跨平台(它在 Linux、MacOS、Windows、Web(WASM)上运行)

关键词

是什么让编程语言难以学习?

"Keywords"
语言 关键词 难度级别
C# 102 5/5
Java 48 4/5
Python 35 3/5
Lua 22 2/5
Chap 0 0/5

Chap 中没有关键词。

语法

Chap 中的一行普通代码由 -> 运算符分隔的 3 块组成

chunk1 -> chunk2 -> chunk3
块 1 块 2 块 3
输入参数 函数名 输出变量
param1, param2 -> function_name -> $output_variable

例如

1, 2 -> add -> $sum

1 和 2 由 "," 分隔是输入参数。
这些输入参数正在移动到 "add" 函数。
最后 $sum 是一个变量,在其中存储 add 结果。

注意:“add” 不是一个关键词,它是一个内置函数。

好吧,但为什么呢?

英语是一种 “从左到右”(即 LTR)的语言,编程语言应该遵循同样的规则,对吧?

错误

// c base languages:
result = send(sqrt(1 + 2).toString());
   ↑       ↑    ↑     ↑       ↑
   5       4    2     1       3

但是章

// chap
1,2 -> add -> sqrt -> to_string -> send -> $result
        ↑       ↑         ↑          ↑        ↑
        1       2         3          4        5

实际上,它的顺序是自左向右,就像正常的英语。

注意:"链"语法是在2.0.0版本中添加的

语法规则

使用//注释,右侧所写的内容将被编译器忽略。

1, 2 -> add -> $sum // this is a comment

您可以通过分号";"分隔行来在一行中编写多行代码。

1 -> $a; $a, 2-> sum -> $b; $b -> print -> $_

输入参数由逗号","分隔。

输入参数可以是

  1. 变量
  2. 字符串,用"字符包围,如:"hello world"
  3. 整数,仅是一个数字:5
  4. 浮点数,是浮点数的正常形式 3.14
  5. 布尔值,是true或false
  6. 标签以@开头。 更多关于控制流
$a, "hello", 5, 3.14, false -> function_name -> $output_var

函数名不区分大小写。

函数名对其他任何内容也不敏感

// to_string = ToString = TOSTRING = to string = t o s t r_i_n_g

变量应以$开头,这是PHP最爱的特性。

变量名规则

$12 // Ok
$sp a ce // OK
$#^3 // Ok
$a,b // comma not allowed
$really? // question mark at the end not allowed
$rea?lly // OK
$some->thing // "->" is not allowed 

简短语法功能

如果一个函数没有输出变量,您可以删除chunk3

"hello world" -> print
    ↑              ↑         ↑
   input         function   removed chunk3

如果一个函数没有输入参数,您可以删除chunk1

              input -> $user_input
 ↑              ↑         ↑
nothing      function    output

删除chunk2(函数名)意味着赋值给变量

1 -> $variable
// it's actually short for:
// 1 -> assign -> $variable

如果一个函数没有输入参数和输出变量,只需写函数名

exit

如果一个函数有输出变量,但您删除了chunk3,函数的结果将被打印

1, 2 -> add
// it's short for:
// 1, 2 -> add -> print

如果您只写一些参数,chap将打印它们

1, 2
// result: 1, 2

// or
$a
// prints whatever $a is

正如您所猜想的,我们拥有世界上最小的hello world

"Hello World"

我希望我还能删除双引号呢:)

链式语法(也称为管道)

有时您有一系列函数调用,如下所示

1, 2 -> add -> $tmp1
$tmp1 -> sqrt -> $tmp2
$tmp2 -> print

如您所见,一个函数调用的输出是下一个函数调用的输入。

在这种情况下,您可以使用管道语法将函数并排写出,并消除临时变量

1, 2 -> add -> sqrt -> print

括号

当其中一个函数有多个参数时,您不能使用管道。

1,2 -> add -> add -> print
               ↑
               This needs two input params

在这种情况下,您可以使用括号

(1,2 -> add), (3 -> sqrt) -> add -> print

这转换了两个

1,2 -> add -> $TMP1
3 -> sqrt -> $TMP2
$TMP1, $TMP2 -> add -> print

运算符

有一个操作符 ->,它将数据从左到右移动,也是语言的标志。

为什么操作符很糟糕?
因为它们在不同类型上的行为不同。看看这个Python示例

number = input("Enter a number:")
result = number * 5 # multiply number by 5
print(number, "* 5 =", result)

以下代码有错误,结果将是

Enter a number: 3
3 * 5 = 33333
# no runtime error

为什么?因为Python使用相同的操作符用于math.multiply和strings.repeat。

所以*操作符是一个"不是类型安全的"操作符,并且当您忘记向它传递正确的类型时,它会执行意外的操作,并且它会在不抛出运行时错误的情况下发生(这是不好的)。

在Chap中的相同代码

input -> $number
$number, 5 -> multiply -> $result 
$result
// error in line 2: multiply function works only with numbers int and float

运行时错误比逻辑错误要好,Chap中有repeat函数

"foo ", 3 -> repeat
// foo foo foo 

在许多语言中,"+"操作符也有相同的问题

# Python
def add(a, b):
    a + b # concat or add? both?

add("1", "2") # 12
add(1, 2) # 3
// Chap:
"1", "2" -> concat // 12
1, 2 -> concat // 12 // you can concat integers safely
1, 2 -> add // 3
"1", "2" -> add // runtime error

调试器

您可以在函数名末尾放置一个?来调试该行

1 -> $a
2 -> $b
$a, $b -> add? -> $c
// result 1, 2 -> add -> 3

Chap还有一个名为"dump"的函数,它打印您拥有的每个变量。

控制流

您可以创建一个这样的标签

@tag_name

然后您可以跳转到它

@tag_name -> jump
// or
@tag_name, true -> jump_if
// or
@tag_name, 1, 1 -> jump_if_equal
// or
@tag_name, 1, 0 -> jump_if_not_equal

循环

向后跳转会创建循环

@l
    "Hello until your battery dies"
@l -> jump

如果

@i, 1, 1 -> jump_if_equal
    "this will not print"
@i

注意:缩进不是必需的

数组

初始化

[1 2 3 4] -> $myArray

插入

$myArray, 5 -> insert

弹出

$myArray-> pop -> $last_item

通过索引获取项目

$myArray, 1 -> get -> $first_item
// arrays index start from 1

示例

注意:您可以在ChapApp中测试和调整示例。

hello_world.chp

"Hello world"
Hello world

counter.chp

0 -> $counter
@l
    $counter -> increase
@l, $counter, 100 -> jump_if_not_equal
$counter
100

number_guess_game.chp

1,10 -> random_number -> $answer
@loop
    input -> $guess
    $guess -> to_int -> $guess
    @win, $answer, $guess -> jump_if_equal
    "wrong"
@loop -> jump

@win
"you win"
1
wrong
2
wrong
3
you win

christmas_tree.chp

 // Editable
0 -> $counter
@loop
    $counter -> increase

    $counter, 2 -> multiply -> $stars_size
    10, $counter -> minus -> $space_size

    "*", $stars_size -> repeat -> $stars
    " ", $space_size -> repeat -> $spaces

    $spaces, $stars -> cat
@loop, $counter, 10 -> jump if not equal
         **
        ****
       ******
      ********
     **********
    ************
   **************
  ****************
 ******************
********************

christmas_tree_with_trunk.chp


 // Editable
0 -> $counter
@loop
    $counter -> increase

    $counter, 1 -> multiply -> $stars_size
    19, $counter -> minus -> $space_size

    " * ", $stars_size -> repeat -> $stars
    " ", $space_size -> repeat -> $spaces

    $spaces, $stars -> cat

    "`*-", $stars_size -> repeat -> $stars
    " ", $space_size -> repeat -> $spaces

    $spaces, $stars -> cat
@loop, $counter, 10 -> jump if not equal

3 -> $c
@loop
    $c-> increase

    $c, 2 -> multiply -> $stars_size
    22, $c-> minus -> $space_size


    "*", $stars_size -> repeat -> $stars
    " ", $space_size -> repeat -> $spaces

    $spaces, $stars -> cat

@loop, $c, 7 -> jump if not equal


                   * 
                  `*-
                  *  * 
                 `*-`*-
                 *  *  * 
                `*-`*-`*-
                *  *  *  * 
               `*-`*-`*-`*-
               *  *  *  *  * 
              `*-`*-`*-`*-`*-
              *  *  *  *  *  * 
             `*-`*-`*-`*-`*-`*-
             *  *  *  *  *  *  * 
            `*-`*-`*-`*-`*-`*-`*-
            *  *  *  *  *  *  *  * 
           `*-`*-`*-`*-`*-`*-`*-`*-
           *  *  *  *  *  *  *  *  * 
          `*-`*-`*-`*-`*-`*-`*-`*-`*-
          *  *  *  *  *  *  *  *  *  * 
         `*-`*-`*-`*-`*-`*-`*-`*-`*-`*-
                  ********
                 **********
                ************
               **************

数据类型

1 -> type_of
int

3.14 -> type of
float

"ali" -> TypeOf
string

true -> type      
boolean

-> [1 2 3] -> type      
list

内存管理

您的操作系统将在进程完成后释放内存!

安装

下载版本

链接

从源代码构建

git clone https://github.com/ali77gh/Chap
cargo build --release
sudo cp ./target/release/chap /usr/bin

如何使用

REPL(运行执行打印循环)

./repl/mod.rs

 chap
-> "hello world"
hello world
-> 

文件执行器

./file_executor/mod.rs

 chap number_guess_game.chp 
1
wrong
2
wrong
3
you win answer was: 3

作为库使用

./lib.rs

cargo add chap # this include eval function

cargo build --release --lib

版本说明 2.0.0

  • 数组
  • 修复:'random'模块在WASM上无法工作
  • eval函数
  • ChapApp
  • 管道语法(1, 2 -> 添加 -> toString -> 打印)
  • 括号(1, 2 -> 添加),(2, 3 -> 添加)-> 连接 -> $var // 35
  • 新的调试语法 1,2 -> 添加? -> $sum

星号

Stargazers over time

内置函数

runtime/builtin_function
Chap 有 49 个内置函数(版本 2.0.0)(少于 Java 的关键字)

名称 输入参数 输出 描述
赋值 任何 任何 将值或变量放入其他变量 1 -> $a
std_out, print, show 任何,任何,任何,... 任何 将参数打印到控制台
std_in, input 字符串 从控制台读取用户输入
exit, quit, kill, end 结束执行
跳转 @tag 将执行器光标移动到具有指定名称的最近标签
jump_if @tag, bool 如果第一个参数为真,则跳转到标签
jump_if_not @tag, bool 如果第一个参数为假,则跳转到标签
jump_if_equal, jeq @tag, any, any 如果第二个和第三个参数相等,则跳转到标签
jump_if_not_equal, jneq @tag, any, any 如果第二个和第三个参数不相等,则跳转到标签
new_tag @tag 创建标签(您只需写下标签名称即可调用此操作)
add num, num num 添加两个数字 1 + 2 = 3 或 1.5 + 1 = 2.5
add_many, add_all num, num, num,... num 添加多个数字 1 + 2 + 3 = 6
minus num, num num 减去两个数字 3 - 2 = 1
multiply num, num num 减去两个数字 3 * 2 = 6
divide num, num num 除以两个数字 3 / 2 = 1.5
modulus, mod num, num num 除以余数 3 / 2 = 1
power, pow num, num num 幂 3 ** 2 = 9
square_root, sqrt num num 平方根 9 -> sqrt -> 3
increase, inc $num 将一个数字加到变量的简写形式:$a,1 -> 添加 -> $a
decrease, dec $num 从变量中减去一个数字的简写形式:$a,1 -> 减去 -> $a
equal, eq any, any bool 如果第一个和第二个相等则为真,否则为假
not_equal, neq any, any bool 如果第一个和第二个不相等则为真,否则为假
and bool, bool bool 逻辑与门
bool, bool bool or logical gate
not bool bool not logical gate
greater_than, gt num, num bool 如果第一个参数大于第二个参数则为真 3,2 -> true
less_than, lt num, num bool 如果第一个参数小于第二个参数则为真 3,2 -> false
concat, cat any, any 字符串 将输入转换为字符串并连接它们 "al","i" -> "ali"
repeat any, int 字符串 将输入转换为字符串并重复 "a",3 -> "aaa"
length, len 任何 int 将输入转换为字符串并返回长度 456 -> 3
contains, has 任何 bool 将输入转换为字符串并返回第一个是否包含第二个 11,1->true
slice, sub_string any, int, int 字符串 "hello", 1, 3 -> "el"
insert array, any 将项目插入到列表中
get array, int 任何 获取列表的第 n 项 second param 是项目的索引
pop array 任何 从列表中删除最后一个项目并返回它
last array 任何 返回列表的最后一个项目(不删除它)
has array, any bool 检查项目是否存在于列表中
remove array, any 从列表中删除给定的项目
remove_at array, int 删除第二个参数索引处的项目
index_of array, any int 在列表中搜索项目并返回索引
to_string 任何 字符串 将输入转换为字符串 1 -> "1"
to_float 字符串 float 将输入转换为浮点数 "1.5" -> 1.5 ; "a"->error
to_int 字符串 int 将输入转换为整数 "1" -> 1 ; "a"->error
dump, dump_memory 打印所有带值的变量
type_of, 类型 任何 字符串 打印参数 1 的类型 -> int; "s" -> 字符串
now_sec, now, unixtime float Unix 时间标准(以秒为单位)
wait_mil, wait_millis int 延迟代码执行 1 毫秒
wait_sec, wait_sec int 延迟代码执行 1 秒
wait_min, wait_minute int 延迟代码执行 1 分钟
wait_hour, wait_hour int 延迟代码执行 1 小时
wait_hour, wait_hour int 延迟代码执行 1 小时

依赖关系

~0–0.8MB
~12K SLoC