mirror of
https://gitee.com/zlgopen/awtk.git
synced 2024-11-30 02:58:26 +08:00
improve fscript docs and testcase
This commit is contained in:
parent
151d1b8c15
commit
ddfbed2fc7
224
docs/fscript.md
224
docs/fscript.md
@ -6,9 +6,9 @@ fscript 是一个极简的脚本引擎,借鉴了函数语言中一些思路,
|
||||
|
||||
* 特色:
|
||||
* 小内存。最低开销小于 400 字节。
|
||||
* 小巧。核心代码 1000 行,扩展函数 700 行。
|
||||
* 小巧。核心代码 1000 行,扩展函数 800 行。
|
||||
* 灵活。支持多条语句、函数嵌套调用和变量定义。
|
||||
* 简单。只有函数调用和表达式,熟悉任何一种编程语言的人,5分钟内即可学会。
|
||||
* 简单。熟悉任何一种编程语言的人,5 分钟内即可学会。
|
||||
* 强大。超过 60 个内置函数,支持条件语句和循环语句,支持复杂的表达式,支持用 C 语言扩展函数。
|
||||
|
||||
> 如果不需要数学函数,可以定义 AWTK_LITE 宏。
|
||||
@ -29,12 +29,22 @@ fscript 是一个极简的脚本引擎,借鉴了函数语言中一些思路,
|
||||
print("hello fscript")
|
||||
```
|
||||
|
||||
在 PC 上测试运行:
|
||||
* 在 PC 上测试运行:
|
||||
|
||||
如:
|
||||
```
|
||||
./bin/runFScript 'print("hello fscript")'
|
||||
```
|
||||
|
||||
* 在 PC 上测试运行指定文件:
|
||||
|
||||
> 第一个命令行参数以 @ 开头表示它是一个脚本文件,读取其内容执行。
|
||||
|
||||
如:
|
||||
```
|
||||
./bin/runFScript @tests/testdata/demo_while1.fs
|
||||
```
|
||||
|
||||
## 3. 语法
|
||||
|
||||
### 数据类型
|
||||
@ -58,10 +68,60 @@ print("hello", 123)
|
||||
|
||||
### 定义变量
|
||||
|
||||
* 通过 set 函数设置
|
||||
|
||||
如:
|
||||
|
||||
```
|
||||
set(a, 123)
|
||||
```
|
||||
|
||||
* 通过=赋值
|
||||
|
||||
如:
|
||||
|
||||
```
|
||||
a = 123
|
||||
b = "abc"
|
||||
c = true
|
||||
```
|
||||
|
||||
#### 变量名命名规则:
|
||||
|
||||
* 以字母开头,后面可用数字、英文下划线和英文点。
|
||||
|
||||
如:
|
||||
|
||||
```
|
||||
age=123
|
||||
name="fscript"
|
||||
file_name="test.txt"
|
||||
```
|
||||
|
||||
* 英文点"."可以用来访问对象的成员,如果对应的对象不存在则当作普通变量。
|
||||
|
||||
如:
|
||||
|
||||
```
|
||||
msg.payload = "hello"
|
||||
```
|
||||
|
||||
>在这里,如果对象 msg 存在,msg.payload 为 msg 对象的 payload 成员,否则 msg.payload 则是一个普通变量。
|
||||
|
||||
* a、b、c 和 d 为快速访问变量,具有更快的访问速度,建议在循环中优先使用。
|
||||
|
||||
如:
|
||||
|
||||
```
|
||||
a=0
|
||||
b=0
|
||||
while(a < 100) {
|
||||
a=a+1
|
||||
b=b+a
|
||||
print(a, b)
|
||||
}
|
||||
```
|
||||
|
||||
### 获取变量
|
||||
|
||||
```
|
||||
@ -70,47 +130,102 @@ a
|
||||
|
||||
> 获取变量时,如果变量不存在,自动当成字符串处理。不希望当成字符串,可以加上$前缀。
|
||||
|
||||
如:
|
||||
|
||||
```
|
||||
./bin/runFScript 'print($abc)'
|
||||
|
||||
get var abc failed
|
||||
(null)
|
||||
result:true
|
||||
cost: 112 us
|
||||
```
|
||||
|
||||
```
|
||||
./bin/runFScript 'print(abc)'
|
||||
|
||||
get var abc failed
|
||||
abc
|
||||
result:true
|
||||
cost: 112 us
|
||||
```
|
||||
|
||||
### 函数嵌套调用
|
||||
|
||||
```
|
||||
print(join(",", 1, 2, 3))
|
||||
print(join(",", +(1, 2), -(5, 2), *(2, 3), /(9, 3)))
|
||||
print(join(",",1,2,3,4), join(";",5,6,7,8))
|
||||
```
|
||||
|
||||
### 条件执行
|
||||
|
||||
* 语句方式
|
||||
|
||||
```
|
||||
if(false, print("a"), print("b"))
|
||||
a=random(1, 100)
|
||||
b=random(1, 100)
|
||||
|
||||
print("a is ", a);
|
||||
print("b is ", b);
|
||||
|
||||
if(a < b) {
|
||||
print(a, "<", b)
|
||||
} else {
|
||||
print(a, ">=", b)
|
||||
}
|
||||
```
|
||||
|
||||
> 代码块需要用 {} 扩起来,else 语句可以省略。
|
||||
|
||||
* 函数方式
|
||||
|
||||
```
|
||||
if(true, print("a"), print("b"))
|
||||
```
|
||||
|
||||
### 循环执行
|
||||
|
||||
* 语句方式
|
||||
|
||||
```
|
||||
set(a, 0)
|
||||
while(a < 10, print(a), set(a, a+1))
|
||||
a=0
|
||||
b=0
|
||||
|
||||
while(a < 100) {
|
||||
a=a+1
|
||||
b=b+a
|
||||
print(a, b)
|
||||
}
|
||||
```
|
||||
|
||||
> 代码块需要用 {} 扩起来
|
||||
|
||||
* 函数方式
|
||||
|
||||
```
|
||||
a=0
|
||||
while(a < 10, print(a), a=a+1)
|
||||
```
|
||||
|
||||
### 表达式
|
||||
|
||||
为了确保优先级正确,尽量用括号明确优先级。
|
||||
|
||||
#### 支持的操作符
|
||||
|
||||
* 四则运算:+ - * / %
|
||||
* 逻辑运算: || && !
|
||||
* 逻辑运算:|| && !
|
||||
* 位运算:| & ~
|
||||
* 比较运算:< <= > >= ==
|
||||
* 条件运算: (p) ? a : b
|
||||
* 条件运算:(p) ? a : b
|
||||
|
||||
> 对于加法运算(+),参数中有字符串时,进行字符串连接。
|
||||
> 对于加法运算 (+),参数中有字符串时,进行字符串连接。
|
||||
|
||||
#### 示例
|
||||
|
||||
```
|
||||
set(a, 10);
|
||||
set(b, 20);
|
||||
a = 10
|
||||
b = 20
|
||||
```
|
||||
|
||||
```
|
||||
@ -131,7 +246,6 @@ a<=b
|
||||
a>b
|
||||
a>=b
|
||||
(1+2)*(2+3)
|
||||
(1+2)*(2+3)
|
||||
sin(a) + sin(b)
|
||||
a<b ? print(a) : print(b)
|
||||
set(a, a+1)
|
||||
@ -185,88 +299,6 @@ print(a+b)
|
||||
print(join(",", a, b))
|
||||
```
|
||||
|
||||
#### noop
|
||||
|
||||
> 空函数。什么也不做,主要给 if 函数用。
|
||||
----------------------------
|
||||
|
||||
##### 原型
|
||||
|
||||
```
|
||||
noop()
|
||||
```
|
||||
|
||||
#### seq
|
||||
|
||||
> 把组合多条语句组合成一条语句。方便在if语句中执行多条语句。
|
||||
----------------------------
|
||||
|
||||
##### 原型
|
||||
|
||||
```
|
||||
seq(s1, s2, s3, ...)
|
||||
```
|
||||
|
||||
示例
|
||||
|
||||
```js
|
||||
if(
|
||||
msg.topic == "eof",
|
||||
seq(
|
||||
print(msg.topic),
|
||||
set(aborted, true),
|
||||
#("文件读取完毕,关闭定时器"),
|
||||
set(flow.timer.enable, false)
|
||||
),
|
||||
seq(
|
||||
print(str(msg.payload, true)),
|
||||
set(msg.payload, toupper(str(msg.payload, true)))
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
#### if
|
||||
|
||||
> 条件执行。如果第一个参数为 true,执行第二个参数,否则执行第三个参数。
|
||||
----------------------------
|
||||
|
||||
##### 原型
|
||||
|
||||
```
|
||||
if(p, s1, s2)
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```
|
||||
set(a, 1)
|
||||
if(<(a, 0), print(" a < 0"), print("a >= 0"))
|
||||
```
|
||||
|
||||
#### while
|
||||
|
||||
> 循环执行。如果第一个参数为 true,循环执行后面参数的各个语句,直到第一个参数返回 false 为止。
|
||||
----------------------------
|
||||
|
||||
##### 原型
|
||||
|
||||
```
|
||||
while(p, s1, ...)
|
||||
```
|
||||
|
||||
#### 示例
|
||||
|
||||
```
|
||||
set(a, 0)
|
||||
while(a < 10, print(a), set(a, a+1))
|
||||
```
|
||||
|
||||
```
|
||||
set(a, 0)
|
||||
set(b, 0)
|
||||
while(a < 10, print(a, ",", b), set(b, b+a), set(a, a+1))
|
||||
```
|
||||
|
||||
#### set
|
||||
|
||||
> 设置变量的值。
|
||||
@ -474,7 +506,7 @@ float("123")
|
||||
str(var [,force_pointer_as_str])
|
||||
```
|
||||
|
||||
> force\_pointer\_as\_str 如果输入参数是POINTER类型,是否将强制转换成字符串。
|
||||
> force\_pointer\_as\_str 如果输入参数是 POINTER 类型,是否将强制转换成字符串。
|
||||
|
||||
#### 示例
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "tkc/fs.h"
|
||||
#include "tkc/mem.h"
|
||||
#include "tkc/utils.h"
|
||||
#include "tkc/platform.h"
|
||||
@ -5,6 +6,42 @@
|
||||
#include "tkc/fscript.h"
|
||||
#include "tkc/object_default.h"
|
||||
|
||||
static ret_t run_fscript(const char* code, uint32_t times) {
|
||||
value_t v;
|
||||
char buff[64];
|
||||
uint64_t start = time_now_us();
|
||||
object_t* obj = object_default_create();
|
||||
tk_mem_dump();
|
||||
if (times > 1) {
|
||||
/*stress test*/
|
||||
uint32_t i = 0;
|
||||
fscript_t* fscript = fscript_create(obj, code);
|
||||
for (i = 0; i < times; i++) {
|
||||
fscript_exec(fscript, &v);
|
||||
value_reset(&v);
|
||||
}
|
||||
fscript_destroy(fscript);
|
||||
} else {
|
||||
fscript_eval(obj, code, &v);
|
||||
log_debug("result:%s\n", value_str_ex(&v, buff, sizeof(buff) - 1));
|
||||
value_reset(&v);
|
||||
}
|
||||
OBJECT_UNREF(obj);
|
||||
log_debug("cost: %d us\n", (int)(time_now_us() - start));
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
static ret_t run_fscript_file(const char* filename, uint32_t times) {
|
||||
uint32_t size = 0;
|
||||
char* code = (char*)file_read(filename, &size);
|
||||
return_value_if_fail(code != NULL, RET_BAD_PARAMS);
|
||||
run_fscript(code, times);
|
||||
TKMEM_FREE(code);
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
platform_prepare();
|
||||
|
||||
@ -13,29 +50,13 @@ int main(int argc, char* argv[]) {
|
||||
printf("Usage: %s script\n", argv[0]);
|
||||
return 0;
|
||||
} else {
|
||||
value_t v;
|
||||
char buff[64];
|
||||
uint64_t start = time_now_us();
|
||||
const char* code = argv[1];
|
||||
object_t* obj = object_default_create();
|
||||
tk_mem_dump();
|
||||
if (argc == 3) {
|
||||
/*stress test*/
|
||||
uint32_t i = 0;
|
||||
uint32_t times = tk_atoi(argv[2]);
|
||||
fscript_t* fscript = fscript_create(obj, code);
|
||||
for (i = 0; i < times; i++) {
|
||||
fscript_exec(fscript, &v);
|
||||
value_reset(&v);
|
||||
}
|
||||
fscript_destroy(fscript);
|
||||
uint32_t times = argc > 2 ? tk_atoi(argv[2]) : 1;
|
||||
if (*code == '@') {
|
||||
run_fscript_file(code + 1, times);
|
||||
} else {
|
||||
fscript_eval(obj, code, &v);
|
||||
log_debug("result:%s\n", value_str_ex(&v, buff, sizeof(buff) - 1));
|
||||
value_reset(&v);
|
||||
run_fscript(code, times);
|
||||
}
|
||||
OBJECT_UNREF(obj);
|
||||
log_debug("cost: %d us\n", (int)(time_now_us() - start));
|
||||
}
|
||||
tk_mem_dump();
|
||||
|
||||
|
24
tests/testdata/demo_expr.fs
vendored
Normal file
24
tests/testdata/demo_expr.fs
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
a = 10
|
||||
b = 20
|
||||
|
||||
print(a<b)
|
||||
print(1+2)
|
||||
print(1-2)
|
||||
print(1*2)
|
||||
print(1/2)
|
||||
print(3%2)
|
||||
print(a||b)
|
||||
print(a&&b)
|
||||
print(a|b)
|
||||
print(a&b)
|
||||
print(!a)
|
||||
print(~a)
|
||||
print(a<b)
|
||||
print(a<=b)
|
||||
print(a>b)
|
||||
print(a>=b)
|
||||
print((1+2)*(2+3))
|
||||
print(sin(a) + sin(b))
|
||||
print(set(a, a+1))
|
||||
print(set(a, a+b))
|
||||
print("abc" + "123")
|
11
tests/testdata/demo_if1.fs
vendored
Normal file
11
tests/testdata/demo_if1.fs
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
a=random(1, 100)
|
||||
b=random(1, 100)
|
||||
|
||||
print("a is ", a);
|
||||
print("b is ", b);
|
||||
|
||||
if(a < b) {
|
||||
print(a, "<", b)
|
||||
} else {
|
||||
print(a, ">=", b)
|
||||
}
|
8
tests/testdata/demo_while1.fs
vendored
Normal file
8
tests/testdata/demo_while1.fs
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
a=0
|
||||
b=0
|
||||
|
||||
while(a < 100) {
|
||||
a=a+1
|
||||
b=b+a
|
||||
print(a, b)
|
||||
}
|
3
tests/testdata/demo_while2.fs
vendored
Normal file
3
tests/testdata/demo_while2.fs
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
a=0
|
||||
while(a < 10, print(a), a=a+1)
|
||||
|
Loading…
Reference in New Issue
Block a user