前言 想開發一些小工具,所以想系統性的學習一遍aardio,之前都是哪裡不會搜哪裡,順便寫些教程。我的主要語言是Python,所以會以Python作為對比來加深印象。 aardio的基礎語法和JavaScript基本類似,如果你學過JavaScript,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 發佈!