5个版本
| 0.1.4 | 2023年12月18日 |
|---|---|
| 0.1.3 | 2023年12月18日 |
| 0.1.2 | 2023年12月18日 |
| 0.1.1 | 2023年12月17日 |
| 0.1.0 | 2023年12月17日 |
#133 in 编程语言
每月21次下载
290KB
7K SLoC
nope脚本
nope是一种脚本编程语言,针对小型和有趣的程序进行了优化
nope是
- 有趣的
- 基于表达式的
- 垃圾回收
- 命令式,带有一些函数式元素
- 专注于解决实际问题
- 将数据与逻辑分离
- 可以原生表示JSON和XML
- 单个二进制文件
- 用Rust构建
- 将包含一个完整的stdlib
- 将具有事件循环并发模型

运行和安装
安装rust / cargo然后
cargo install nope-lang
您可以使用以下命令启动交互式repl
nope
或运行脚本
nope myscript.nope
如果您使用vim,可以使用以下命令安装语法支持
nope --install-vim-plugin
路线图
该项目目前处于一个非常非常早期的阶段
- 评估表达式
- 全局、局部变量和作用域
- 常量与运算符
- 数学stdlib
- 循环
- 函数
- 字典和数组
- 垃圾回收
- 错误,try catch
- 字符串stdlib
- 解析和序列化
- utils stdlib
- 资源类型
- os stdlib
- 单元测试
- v1.0
- 异步
- 异步stdlib
- v2.0
- 网络服务器
- v3.0
- 模块与包
- v4.0
- 性能
类型
以下表格应该能给您一个基本类型和允许的数据模型的概念。请注意,目前尚未实现数组和对象。
[
null: null,
void: [void _ ()]
bool: [true false]
num: [0 1 99 3.14 -1_000_000 0xdead 0b10101 NaN Inf PI]
string: ['foo' "bar" ~hello]
arrays: [1 2 true null []]
dicts: {key:32 val:99}
mixed: ['foo' key:'value']
]
nope中的所有数据都是上述类型和结构的组合。
注意,数字是64位浮点数,字符串是Unicode。
代码结构
让我们看看基本的nope程序。
let x = d6() + d6()
var winning = false
if x >= 10 (
set winning = true
print 'haha, yes! :)'
) else (
print 'oh no :('
)
在第一行,我们定义了一个名为x的变量,其初始值由一个调用两个函数'd6'并添加结果的运算符定义。变量'x'在当前作用域中的后续表达式中可用。由于它是用let定义的,因此不能用set来更改它。
在第二行中,我们声明了另一个变量,但这次它可以被修改。
我们接下来评估一个经典的if-else条件语句。请注意,与其他语言不同,代码块不是由花括号{/}定义的,而是由括号(/)定义的。原因是nope是一种基于表达式的语言,因此每个nope构造都是一个产生值的表达式。
以下示例将这些原则付诸实践。
let res = if flip_coin(), "heads" else "tails"
if返回一个值,该值将取决于flip_coin()的结果,可能是字符串“heads”或“tails”。
您可以用括号包围表达式,也可以用括号包围多个表达式。在后一种情况下,所有表达式都将按顺序评估,但只有最后一个表达式会产生值。
这就是我们使用set winning = true表达式来改变变量winning,并打印消息的原因。
请注意,print表达式print "hey"省略了其参数周围的括号。这并不是print函数的特殊情况。在nope中,所有函数参数的括号和逗号都是可选的。
let clamped_0_100 = max 0 min value 100
这也适用于没有参数的函数。
let score = d6 + d6 + d6
请注意,函数应用具有最高的优先级,因此print 1 + 1打印的是1,因为加法是在之后执行的。这并不总是您想要的。一种方法是用括号print(1 + 1),注意函数名和第一个括号之间的空格是有意义的。没有空格时,期望有完整的参数列表,而有空格时,只是单个参数的括号;max(1,2) / max (1) (2)
另一种方法是使用左箭头<-运算符。此运算符简单地评估右侧的完整表达式。因此,您可以像这样打印print <- 1 + 1。
按照惯例,nope中的所有函数都将它们操作的数据作为最后一个参数。
let txt = read_text 'file.txt'
let txt2 = upper txt
write_txt 'file2.txt' txt2
借助左箭头<-运算符,您可以编写以下代码:
write_txt 'file2.txt' <- upper <- read_text 'file.txt'
右箭头->运算符(尚未实现)执行相同的操作,但方向相反。
read_text 'file.txt' -> upper -> write_txt 'file2.txt'
运算符
相等==,!=
检查操作数是否为同一类型,如果是这样,则比较它们的值或引用
比较 <、>、<=、>=
首先将数字转换为它们的数值等价物(字符串和数组为NaN),然后进行比较
运算符 +-= 和 !+-= 比较数字的相等性,精度达到 EPSILON
算术运算符 +、-、*、/、%、**,
通常的数学运算。操作数转换为它们的数值等价物(字符串为NaN)
字符串的加法 + 将执行字符串连接,并将另一个操作数转换为字符串
整数 & 位运算
所有以 ~ 开头的算术运算符首先将操作数转换为 int32,然后执行整数运算。
例如 10 ~/ 4 是 2
位运算符 ~!、~|、~&、~^、~<<、~>>、~>>> 将操作数转换为 int32,然后执行位运算
布尔值 !、||、&&
操作数的布尔等价值是
false如果是null、void或0true否则
运算符
!取消布尔等价值的符号&&如果第一个操作数为假,则返回第一个操作数,否则返回第二个||如果第一个操作数为真,则返回第一个操作数,否则返回第二个
默认 ??
如果第一个操作数是 null 或 void,则返回第二个操作数,否则返回第一个
重复 *:
重复运算符将计算并求和第二个操作数 N 次,其中 N 是第一个操作数。
例如,这将掷骰子 3 次
print(3 *: d6)
请注意,首先将第一个操作数转换为数字。如果数字为零或负数,则返回 void。
循环
不支持两种循环机制,loop 无限重复后面的表达式,和 while,它评估一个条件,只要条件保持为真,就重复下一个表达式。
var i = 0, while i < 10 (
set i = print i + 1
)
continue 将直接跳转到下一次迭代,而 break 将停止迭代
var i = 0, loop (
if i < 10 (
set i = i + 1
continue
)
break
)
循环也是表达式,并返回它们的表达式的最后一个值。 break 返回空值,break_as 将中断并返回下一个表达式
var i = 0, let res = loop (
if i < 10 (
set i = i + 1
) else (
break_as 'done!'
)
)
打印到终端
print 和 echo 是类似的功能,它们接受一个参数,将值打印到终端,并返回它。区别在于 print 打印原始字符串转换后的值,而 echo 打印值的彩色内部表示。
在交互式解释器中,每次提交执行后都会回显。
请注意,由于 print 和 echo 都返回它们的参数,因此可以在表达式中使用它们来显示临时值。
var i = 0, while i < 10 (
set x = print x + 1
)
类型检查与转换
以下函数将转换为其类型: to_num、to_bool、to_str
以下函数测试类型: is_void、is_null、is_bool、is_num、is_int、is_nan、is_odd、is_even、is_str
算术函数和常量
Nope 支持以下算术函数
floor、ceil、abs、acos、acosh、sin、sinh、asin、asinh、cos、cosh、tan、tanh、atan、atanh、invlog2、log10、ln、ln1p、exp、expm1、sqrt、cbrt、round、fround、trunc、sign、max、min、pow、atan2
以下算术常量
NaN、Inf、PI、E、SQRT_2、SQRT_2PI、LN_2、LN_10、LOG2_10、LOG2_E、LOG10_2、LOG10_E、PHI、TAU、EPISLON、MAX|MIN_INTMAX|MIN_F64、MAX|MIN_I32|16|8、MAX_U32|16|8
字符串
len返回字符串的长度(扫描整个字符串)upper和lower用于转换字符串的大小写trim移除字符串开头和结尾的空白字符char_at(idx, text)获取字符串中指定索引的字符substr(from_idx, to_idx, text),根据字符索引返回子字符串。其中to_idx不包含在内。负索引从字符串末尾开始。replace(from, to, text)将text中的from替换为tofind(substr, str),返回substr在str中的位置或-1contains(substr, str)如果substr是str的子字符串,则返回truebitstr将数字转换为它的位表示形式的字符串
随机性
Nope 支持以下随机数生成器函数
random,flip_coin,rand100,d4,d6,d8,d10,d12,d20,d100
如果您想返回三次骰子投掷的总和,最好使用重复操作符 3*:d6
单位
Nope 允许您使用单位后缀注释数字字面量。
let distance = cos 45deg * (10Km + 3miles + 5yd + 3in + 5cm)
单位将数字转换为它们的国际单位制等效值。例如,所有距离都转换为米。
运行时不会保留数字的单位信息。单位不过是方便的语法技巧。
以下单位受到支持
pi,tau,phi,GT,MT,kT,T,kg,g,mg,ug,ng,Ti,Gi,Mi,ki,d,h,min,s,ms,us,ns,moon,deg,rad,in,km,m,dm,cm,mm,um,nm,lb,oz,mile,miles,ft,yd,F,C,K,m3,l,dm3,dl,cl,ml,cm3,barrel,cuft,ft3,gal,pint,cuin,in3,cuyd,yd3,m2,dm2,cm2,mm2,a,ha,km2,mile2,yd2,sqyd,ft2,sqft,in2,sqin,belgium,footballfield,TiB,TB,GiB,GB,MiB,MB,KiB,KB,million,billion,trillion,quadrillon,milli,thousandth,micro,nano,pico,
也可以使用from_unit和to_unit函数在运行时将一个单位转换为另一个单位。
let area_sqin = to_unit 'sqin' <- from_unit 'ha' <- 50
依赖项
~6-17MB
~182K SLoC