3 个稳定版本
2.2.2 | 2024年6月6日 |
---|---|
2.2.1 | 2024年6月5日 |
2.0.1 | 2024年5月2日 |
93 在 编程语言 中排名
136 每月下载量
140KB
3K SLoC
Chap
Chap 是一种易于学习、动态、解释性、无关键词的语言,用 Rust 编写。
记住,Chap 不是一个工具!它是艺术。
ChapApp 是一个基于浏览器的离线 Chap 编辑器/编译器(由 WASM 支持)。ChapApp 也用 Rust(Dioxus)编写。在新标签页中打开 ChapApp。
目录
名称
Rust 或 راست 在波斯语中意为“正确”,Chap 或 چپ 意为“左边”。
如果你在 Rust(正确)上编写代码过多,不久后你可能会逐渐成为资本主义者。所以你需要写一些 Chap(左边)来逃离矩阵。
Chap 解锁了 二维 全栈开发。前端⬆️、后端⬇️、Rust➡️、Chap⬅️。
功能
- 易于学习。
- 跨平台(它在 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 -> $_
输入参数由逗号","分隔。
输入参数可以是
- 变量
- 字符串,用"字符包围,如:"hello world"
- 整数,仅是一个数字:5
- 浮点数,是浮点数的正常形式 3.14
- 布尔值,是true或false
- 标签以@开头。 更多关于控制流
$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(运行执行打印循环)
❯ chap
-> "hello world"
hello world
->
文件执行器
❯ chap number_guess_game.chp
1
wrong
2
wrong
3
you win answer was: 3
作为库使用
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
星号
内置函数
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