aardio教程一) 基础语法-上
前言
想开发一些小工具,所以想系统性的学习一遍aardio,之前都是哪里不会搜哪里,顺便写些教程。我的主要语言是Python,所以会以Python作为对比来加深印象。
aardio的基础语法和JavaScript基本类似,如果你学过JavaScript,aardio很容易上手。下面的文档来自官方文档 [1]
问题搜索途径
基础语法看:https://bbs.aardio.com/doc/reference/
一些库的使用,获取文档有以下途径:
- aardio官方论坛(https://bbs.aardio.com),我一般用谷歌搜索 site:bbs.aardio.com 搜索内容
- aardio官方公众号
- 打开编辑器开始页的话有开发指南和文档资源,右侧有官方资讯,刚入门都可以看一下。里面的库函数文档我经常用
- 写一个函数的时候右键转到定义,库代码下面一般都有注释怎么用
- 用vscode打开整个aardio软件目录,搜索你不知道怎么用的库,看看官方是怎么使用的,这个我用的最多
- aardio相关的第三方论坛:https://aardio.online/thread-20.htm
语法
标识符
变量标识符的定义和Python基本一样,语法如下:
- 字母(区分大小写)、数字和下划线,也可以用中文
- 数字不能作为变量首个字符
与Python不同的点:
- 除了单个下划线
_
,其他下划线开头的为常量,定义后无法被修改 - 可以以$符开头
- 包含中文时,前面不能有字符和数字
关键字
- | - |
---|---|
var 用于定义局部变量 |
def 用于定义关键字 |
and not or 逻辑运算符 |
begin end 用于包含语句块 |
if else elseif 用于条件判断语句 |
for in 用于循环语句 |
select case 用于条件判断语句 |
try catch 用于捕获异常 |
break continue 循环中断语句 |
function 用于创建函数 |
namespace 用于创建或打开名字空间 |
import 用于引用库 |
this 用于在类内部表示当前实例对象 |
global 用于表示全局名字空间 |
owner 用于表示调用函数的主体对象 |
while do 用于循环语句 |
null 用于表示空值 |
false true 用于表示布尔值 |
class ctor 用于创建类 |
return 用于函数中返回值 |
with 用于打开名字空间 |
self 用于表示当前名字空间 |
你如果闲的无聊的话,也可以使用def
自定义关键词,比如:
def 如果 = if
def 否则 = else
def 否则是 = elseif
def 名字空间= namespace
def 循环 = while
io.open();
如果 1== 1 {
io.print(" 1等于1 ")
}
否则{
io.print(" 1不等于1 ")
}
改个名字和图标,一款新的中文编程语言就写好了
分隔符和注释符
分隔每条语句可以用换行或者分号, 一下三种方法都可以:
var a = 1; var b = 2;
var a, b = 1, 2;
# 后面的分号可写可不写,我一般都写上
var a = 1
var b = 2
注释则是使用//
和/*
加*/
,也可以使用多个/***
和***/
,只需要前面和后面的数量对应上
操作符
算术运算符 | + 加 |
- 减 |
* 乘 |
/ 除 |
** 幂 |
% 模 |
按位运算符 | ~ 取反 |
& 与 |
` | ` 或 | ^ 异或 |
<< 左移 |
等式运算符 | == |
!= |
||||
逻辑运算符 | ! not |
` | or :` |
&& and ? |
||
关系运算符 | > |
< |
>= |
<= |
||
连接运算符 | ++ |
|||||
取长运算符 | # |
|||||
全局变量定义 | :: |
|||||
成员操作符 | . |
[] |
[[]] |
|||
包含操作符 | $ |
|||||
- 字符串之间使用关系运算符时,是从第一个字符开始比较,这个和Python也是一样的
++
并不是c语言里面的自增,而是用于字符串和字符串拼接,或者字符串和数值拼接。例如:1 ++ "2" == "12"
,也可以省略成1+"2"
- 取长运算符用于获取字符串和数组长度,如果是对象则调用
_len
元方法 - 在变量名前面加
::
表示为全局常量,比如::Kernel32 := raw.loadDll("Kernel32.dll");
,可以避免重复加载dll - 成员操作符.和[]基本可以混用,除非成员名称不符合aardio命令规定则使用[]
- [[]]一般是在元方法中使用,它不会调用元方法,可以避免无限递归
- 路径字符串前加
$
符表示内嵌该文件到编译后的exe中
逻辑运算符
||
、or
和:
再使用上基本没有区别,大部分情况下可以互相替换。
- 逻辑与和逻辑或运算符就能组成类似三元运算符的效果
true ? 1 : 0
a := 1
等同于a = a : 1
,可以用于避免重复赋值a ?= f(a)
等同于a = a ? f(a)
,可以只当a不为null执行f(a)- 也有像Python一样的用逻辑运算符做条件取值的操作,比如
a = 1 or 2
、b = 0 or 3
。语法和意思也和Python是一样的
按位无符号右移
a >>> n
将数值a按位向右移动n位(如果n大于等于32,则为n对32取模结果的位数) ,不保留符号位(负数不保持最高位为1,因此右移后会变成正数)
实际用途:
可以通过右移 0 位将有符号数强制转换为无符号数。例如 -1 >>> 0 的值为 0xFFFFFFFF , 其作用等价于 raw.convert( {int value = -1},{INT value}).value。
不声明调用静态 API 默认会返回 32位有符号整数,如果原 API 返回的是 32位无符号整数,那么只要简单的将返回值 >>> 0 就可以得到原来的无符号数值了
这里有一点很重要: 内存里的数据都是0和1,它是什么值只取决于你以什么类型读取它。
等式运算符
基础数据类型会判断值是否相等,而非基本类型则是判断对象是否相等或者调用_eq
元方法判断
元方法类似Python的魔法方法,可以重载对象的符号运算,比如_eq
重载==
。
0, null
与 false
相等,其他类型都与true
想等
跟数值类型比较时:
- 字符串会自动转为数值类型再做比较,空字符串""转为0,空白字符
\r\n\t
也是转为0 - 如果是对象,则是调用
_tonumber
元方法转数值
表达式 | 结果 |
---|---|
"123"==123 |
true |
"abc"==123 |
false |
""==0 |
true |
'\r\n\t '==0 |
true |
null==0 | false |
还有一个恒等判断的符号===
和!==
,它不会调用_eq
元方法,直接判断类型和数值都相等
运算符优先级
这个东西没必要记,有疑问时加括号即可。遇到别人的代码有疑问,可以运行测试下
基础数据类型
类型 | 举例值 | 说明 |
---|---|---|
type.null |
null | |
type.boolean |
布尔值 | |
type.number |
数值 | 默认为64位浮点数 |
type.string |
字符串 | 字符串和Python也基本一样,utf-8编码 |
type.buffer |
raw.buffer | 可用于接收c语言char* 数据 |
type.pointer |
指针 | 接收dll返回的指针数据,或者使用topointer(obj) |
type.table |
表 | aardio中的数组、字典等复杂类型 |
type.function |
函数 | function创建的函数 |
type.cdata |
内核对象 | 一般不用关心 |
type.fiber |
纤程 | 没用过 |
type.class |
类 | class关键词创建的类 |
null
任何没有定义或赋值的变量默认都是null。如果函数不传参数,默认传过去的也是null。
import console;
console.dump(a);
console.pause(true);
import console;
function f(a){
console.dump(a);
}
f()
console.pause(true);
数值类型
2#11
表示二进制数,8#11
表示八进制数,16#A
表示十六进制数,也可以表示为0xA
。2e+20
(2x10**20)表示科学计数法,+
仅表示指数的正负,可加可不加- 可以用
_
来分隔数值,111_222
等同于111222
字符串
aardio中定义的字符串都是utf-8编码
string.fromUnicode(s)
、string.toUnicode(s)
可以做utf-8 <=> utf-16
的转换,Windows上使用的Unicode编码一般就是指的utf-16,两个函数都可以指定第二个参数,代表目标编码的代码页,用于转换其他编码。
常用的代码页: 936(gb2312)、1200(utf-16 le)、1201(utf-16 be)、65001(utf-8)。所有代码页可以参考: 标准代码页(codepage)列表 [2]
Windows可以在cmd下使用chcp
命令查看当前使用的代码页,一般情况下都是936。
定义字符串的话有四种方式: 双引号("")、单引号('')、反引号(``)和注释符(/**/)。其中双引号和反引号用法是一样的
都可以定义多行字符串:
a = "1
2";
b = '1
2';
c = /*1
2*/
不同点:
- 只有单引号可以使用转义字符,例如
'\n'
表示换行。 - 单引号的换行会被忽略,所以单引号表示换行时和c语言一样使用转义字符
\n
- 双引号的换行会被替换成
\n
- 注释符的换行会被替换成
\r\n
- 在双引号中可以使用两个双引号表示双引号本身,例如
"1222""11111"
,则等同于'1222"11111'
- 在单引号中
\'
表示单引号本身, 例如'1222\'11111'
,则等同于"1222'11111"
'A'#
表示这个字符的ASCII值,也就是65'UTF16字符串'u
表示UTF-16 LE编码的字符串- 文件路径引号前加$符表示编译后将文件嵌入到exe中,加载dll时经常会用到
全局函数
Python中有str
、int
、print
这些可以使用的全局函数,aardio中也内置了一些可以全局使用的函数。我觉得用不到的就不在下面列出来了
tostring
- 将某个值转换为字符串,如果是对象则调用
_tostring
元方法。 - 第二个参数可以指定进制,比如
tostring(10, 16)
返回0xA
- 如果第一个参数是时间,则第二个参数可以指定格式化时间的字符串,比如
tostring(time(), "%Y-%m-%d %H:%M:%S")
topointer
将参数转换为指针,这个函数我还没用过。到时候用的时候再看什么作用
tonumber
- 将某个值转换为数值,如果是对象则调用
_tonumber
元方法。 - 如果是指针则返回内存地址
- 如果是字符串, 第二个参数可以指定进制,例如
tonumber("0xA", 16)
注意: 这个函数会返回两个值,第一个是转换后的数值。第二个是转换使用的字符数。例如tonumber("12a")
, 返回12和2.
一般会使用两个值接收var a, b = tonumber("12a")
invoke
invoke(被调用函数, owner, 参数1, 参数2)
调用指定函数,owner这个后面再提
call
call(被调用函数, owner, 参数)
调用指定函数,跟invoke基本类似
callex
callex(异常处理函数,被调用函数, owner, 参数)
当被调用函数代码出现异常时则调用异常处理函数
loadcode
加载编译代码,参数可以是代码字符串或者代码路径
loadcodex
加载编译和运行代码,参数可以是代码字符串或者代码路径
dumpcode
编译代码为二进制字节
sleep
同步阻塞休眠,和Python的time.sleep一样,单线程情况下会卡住界面。界面中应使用win.delay
type
用于获取对象的数据类型,一般使用type(obj) == type.string
来判断对象是不是字符串,所有类型请看基础语法中的基本数据类型
eval
运行aardio代码,并返回表达式的值
error
主动抛出异常
参考
- [1] aardio官方文档:
https://bbs.aardio.com/doc/reference/
- [2] 标准代码页(codepage)列表:
https://blog.csdn.net/jianggujin/article/details/80325461
- Python所有全局函数:
https://mp.weixin.qq.com/s/PA0lsojc-zkZ4eltj8P6Kg
本文由博客一文多发平台 OpenWrite 发布!