本文仅供有编程基础的用户快速了解常用语法。如果『没有编程基础』 ,那么您可以通过学习任何一门编程语言去弥补你的编程基础,不同编程语言虽然语法不同 —— 编程基础与经验都是可以互通的。我经常看到一些新手说自己没有编程基础或经验,然后过了三年、五年,我看到他还是在说自己没有编程基础或经验。仅仅是掌握编程基础知识或者积累基本的编程经验 —— 通过任何你喜欢的编程语言都不难做到。编程真正困难的并不是怎么拿到入场券 —— 而是如何写出优秀的软件。

有的新手跟我说:“我没有编程基础,学了几个小时,都没有掌握编程基础 ……你的文档是怎么写的,你的教程是怎么写的 ……你们这些做编程语言的人到底是怎么想的 ……”。其实零基础前提下只想花几个小时就能学会一门新编程语言 —— 这只有百年不遇的天才能做到。aardio 很小也很简单。编写 aardio 程序也很简单,几句代码就可以写一个可运行的程序,没有任何复杂的操作。aardio 的文档和教程对很多基础知识都有讲解,也提供了大量可直接运行与使用的范例 —— 很适合新手。 不止一次有用户向我反馈,下载 aardio 只是简单地看了一下教程就把程序写出来了。也有不少用户向我反馈,尝试学习过很多编程语言都没有成功 —— 但是学习 aardio 只用了很短的时间就找到感觉了。

▶ 第一个控制台程序

//导入库
import console; 

//加载动画
console.showLoading("加载动画测试");
sleep(1000); //暂停 1 秒

//输出字符串
console.log('测试字符串');

//输出变量
console.dump({a=123;b=456});

//以 JSON 格式输出变量
console.dumpJson({a=123;b=456});

//暂停并等待按键
console.pause(true);

▶ 第一个窗口程序

import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio form")
winform.add(
button={cls="button";text="测试";left=435;top=395;right=680;bottom=450;color=14120960;font=LOGFONT(h=-14);note="点这里";z=2};
edit={cls="edit";left=18;top=16;right=741;bottom=361;edge=1;multiline=1;z=1}
)
/*}}*/

//按钮回调事件
winform.button.oncommand = function(){
    winform.edit.text = "测试"; //修改控件属性
}

//显示窗口
winform.show();

//启动界面消息循环,保持窗口显示,并响应用户操作
win.loopMessage();

▶ 调用静态 API

//加载 DLL
var dll = raw.loadDll("user32.dll");

//调用 API 函数
dll.MessageBox(0,"测试","标题",0);

aardio 已经默认加载了一些常用的系统 DLL 对象,例如 ::User32, ::Kernel32, ::Shell32,::Ntdll 等。

所以上面的代码可以简化为:

::User32.MessageBox(0,"测试","标题",0);

▶ 静态结构体

var info = {
    INT size = 8;
    INT time;
}
::User32.GetLastInputInfo( info )

因为 aardio 函数支持多返回值,且结构体默认为传址输出参数 —— 会添加到返回值中,所以上面的代码也可以这样写:

var ok,info = ::User32.GetLastInputInfo( {
    INT size = 8;
    INT time;
} );

▶ 注释语句

// 单行注释

/*  
多行注释,首尾星号数目必须相同。
*/

▶ 变量、赋值

var n = null;
var str = "字符串";

aardio 中的变量默认为当前名字空间变量,使用 var 语句可以定义局部变量。

▶ 语句、语句块

{
    var n = null;
    var str = "字符串";
}

语句尾部可以加分号也可以不加。

语句块首尾加 { } 标记,var 语句支持语句块作用域。

▶ 数值

var num = 123.01; //10 进制数值
var hex = 0xEFEF; //16 进制数值
var num2 = 123_456; //可用下划线作为分隔符
var num3 = 2#010; //可在 # 号前自定义进制

▶ 算术运算

var num = 3 + 2; //加,值为 5
var num = 3 - 2; //减,值为 1
var num = 3 * 2; //乘,值为 6
var num = 3 / 2; //除,值为 1.5
var num = 3 % 2; //取模,值为 1
var num = 3 ** 2; //乘方,值为 9

▶ 位运算

import console;

//按位取反
var n = ~2#101;
//显示2#11111111111111111111111111111010
console.printf("2#%b", n)

//按位与
var n = 2#101 & 2#100;
//显示2#100
console.printf("2#%b", n)

//按位或
var n = 2#101 | 2#110;
//显示2#111
console.printf("2#%b", n)

//按位异或
var n = 2#101 ^ 2#110;
//显示2#011
console.printf("2#%b", n);

//按位左移
var n = 2#101 << 1;
//显示2#1010
console.printf("2#%b", n);

//按位右移
var n = 2#101 >> 1;
//显示2#10
console.printf("2#%b", n);

//按位无符号右移
var n = -2 >>> 18;
//显示 16383
console.log(n);

console.pause();

▶ 字符串

var str = "普通字符串。
可直接包含换行符,不能包含回车符。
可以用 "" 表示一个双引号。";

var str2 = `反引号的作用与双引号一样。
可直接包含换行符,不能包含回车符。
可以用 `` 表示一个反引号。`;

var str3 = '转义字符串
忽略回车换行,反斜杆作为转义符使用
例如 rn 表示回车换行';

var str4 = /*
段注释可以赋值为字符串。
首尾星号数目必须配对。
忽略首尾紧邻星号的第一个空行(如果有的话),
其他换行总是会规范化为回车换行符,
也就是 'rn'。
*/

var str5 = //行注释也可赋值为字符串,不含回车换行
//在文件路径前加 $ 符号,可将该文件编译为字符串

var str6 = $"~/aardio.exe"

▶ 二进制字符串、文本编码

var bin = '字符串可以包含任意二进制数据,例如 '

var utf8 = "字符串可以包含文本,默认为 UTF-8 编码"

var utf16 = '转义字符串后加 u 字符表示 UTF-16 编码字符串'u

aardio 在很多地方都支持自动编码转换,例如调用 Unicode(UTF-16) 版本的 API 函数时,UTF-8 字符串可自动转换为UTF-16 编码字符串( 支持双向自动转换),例如以下两句代码的作用是相同的:

::User32.MessageBox(0,"内容","标题",0);

::User32.MessageBox(0,'内容'u,'标题'u,0);

在调用 ::User32.MessageBox 时,aardio 会自动检测并优先使用 Unicode 版本的 ::User32.MessageBoxW() 函数。当然,也可以主动在 API 函数名后加上大写的 W 尾标声明这是 Unicode 版本函数(即使该函数名尾部并没有 W,也可以添加 W 尾标)。

▶ 字符串连接

//使用 ++ 操作符连接字符串
var str = "字符串1" ++ "字符串2";

//如果 ++ 前后有引号,可省略一个 + 号。
var str = "字符串1" + "字符串2";

//用 string.concat() 函数连接支持多参数,支持 null 值
var str = string.concat("字符串1","字符串2")

▶ 读写文件

//写文件
string.save("/test.txt","要保存在文件的字符串");

//读文件
var str = string.load("/test.txt");

▶ 文件路径

/*
文件路径开始可用单个斜杠(或反斜杠)表示应用程序根目录。
应用程序根目录在开发时指工程目录,发布后指 exe 目录。
*/
var str = string.load("restest.txt");

//文件路径中正斜杠可自动转换为反斜杠
var str = string.load("/res/test.txt");

/*
文件路径开始用波浪线表示 exe 所在目录。
aardio 不需要生成 exe 就可以运行调试,此时波浪线表示 aardio.exe 所在目录。
*/
var str = string.load("~/res/test.txt");

/*
aardio 很多读文件的函数都兼容工程内嵌资源目录。
不需要修改代码,所以 "restest.txt" 可以是资源目录。
如果读取文件失败,string.load() 会返回 null 值(不报错)。
*/
var str = string.load("restest.txt");

/*
将文件转换为完整路径。
将路径传给第三方组件时,建议这样转换一下。
*/
var path = io.fullpath("restest.txt");

注意在 aardio 中双引号内不需要转义反斜杠。所以不用写为 “restest.txt”,单引号内才需要这样写。

在 aardio 中一般不必要使用 “./dir/test.txt” 这样的相对当前目录路径。因为当前目录可以任意更改,你不知道什么时候某个第三方组件是不是悄悄帮你改了当前目录。

▶ 嵌入文件到字符串

在文件路径前加上 $ 操作符可将该文件编译为字符串对象。

在编译该代码时文件必须存在,程序发布后就不再需要这个文件了。

示例:

var str = $"dirtest.txt";

不要用这个方法包含资源目录下的资源文件,

因为这等于将同一个文件重复包含了多次,会不必要地增加发布体积。

▶ 名字空间

//导入其他库文件,同时也导入该库创建的名字空间
import console;

//打开名字空间
namespace test.a.b{
   
    //定义当前名字空间变量
    console = 123;
   
    //..console 等价于 global.console
    ..console.log(console);
}

console.pause(true);

默认名字空间为全局名字空间,也就是 global 名字空间。在其他名字空间访问 global 名字空间必须在变量前加上两点( .. ) 。例如 global.console 等价于 ..console 。

在 aardio 中使用 import 导入其他库文件,同时也导入该库创建的名字空间。导入名字空间只是引入模块,访问该名字空间仍然要写完整的名字空间路径。

▶ 表 (table)

table(表)是aardio中唯一的复合数据类型,除了非复合的基础数据类型以外,aardio 中几乎所有的复合对象都是表,即使是变量的命名空间也是表。表的本质是一个集合,可以用于容纳其他的数据成员,并且表也可以嵌套的包含其他的表(table),在aardio里表几乎可以容纳一切其他对象。

表可以包含键值对:

tab = {
     a = 123;
     str = "字符串";
     [123] = "不符合变量命名规则的键应放在下标内。";
     ["键 名"] = "不符合变量命名规则的键应放在下标内。";
     键名 = {
         test = "表也可以包含表";
     }
 }

表也可以包含数组:

//在表中创建数组
var array = {
     [1] = 123;
     [2] = "数组的值可以是任何其他对象";
     [3] = { "也可以嵌套包含其他表或数组"}
 }
 
//数组的键可以省略,下面这样写也可以(并且建议省略)
var array = {
     123;
     "数组的值可以是任何其他对象";
     { "也可以嵌套包含其他表或数组"}
}

在表中允许使用类 JavaScript 语法,用冒号代替等号分隔键值,用逗号代替分号分隔元素,并可用引号包含键名。

示例:

 var tag ={"name1":123,"name2":456}

注意如果键名以下划线开始,则为常量字段(值为 非 null 值时不可修改) —— 可通过元属性 _readonly 禁用此规则(参考语法手册)。

▶ 成员操作符

var tab = {a = 123; b = 456};

/*
用点号访问表成员,点号后面必须跟合法的标识符
*/
var item = tab.a;

/*
用下标操符符 [] 访问表成员,[] 里可以放任何表达式。
*/
var item = tab["a"];

/*
用直接下标操符符 [[]] 访问表成员,[[]] 里可以放任何表达式。
直接下标不会触发元方法,用于 null 值也会返回 null 而不是报错。
*/
var item = tab[["a"]];

▶ null 值

未定义的变量值默认为 null 。

获取表对象不存在的成员值时也会返回 null 而不会报错。如果对象本身是 null 值,使用点号、普通下标获取成员值会报错,改用直接下标 [[]] 则不会报错,而是会返回 null 值。

用 # 操作符获取 null 值长度返回 0 而不是报错。

将表对象的成员赋值为 null 就可以删除该成员。

在逻辑运算中,null 值为 false。

▶ 取数组或字符串长度

import console;

var array = {123;456};
console.log("数组长度",#array);

var str  = "abcd";
console.log("字符串长度",#str);

var n  = null;
console.log("null 值长度为 0",#n);

console.pause();

使用 # 操作取数组或字符串的值,也可以取 null 值的长度( 返回 0 )。

▶ if 语句

import console;
var enabled = true;

if (enabled) {
  console.log('enabled 的值为 true');
}
console.pause(true);

注意在逻辑运算中,非 0、非 null、非 false 为 true,反之为 false。

如果要准确判断一个变量的值是否为 true 或 false ,则应使用恒等操作符,如下:

import console;
var enabled = false;

if (enabled === false ) {
  console.log('enabled 的值为 false,不是 0,也不是 null');
}
elseif( enabled ){
  console.log('enabled 的值为真');
}
else{
  console.log('enabled 值为:',enabled);
}
console.pause(true);

上面的 elseif 也可以改为 else if。

▶ 逻辑操作符

逻辑非 既可以用 not 也可以用 ! 。

逻辑与 既可以用 and 也可以用 && 或者 ? 。

逻辑与 既可以用 or 也可以用 || 或者 : 。

aardio 语句在设计时试图兼容其他语言的一些基本语法,所以很多语法有类似上面的替代写法,例如可以用 begin end 替代 { } 包含语句块。

▶ 三元运算符

var n = 1;

// ret 值为 true
var ret = n ? true : 0;

要特别注意 ? 实际上是逻辑与操作符,: 实际上是逻辑或操作符。如果 a ? b : c 这个表达式里 b 为 false,则该表达式总是返回 c。这与其他类 C 语言的三元操作符不同,请注意区分。

▶ 定义函数

//定义函数:
add = function(a, b) {
  return a + b,"支持多个返回值";
}

//调用函数
var num,str = add(1, 2);

/*
要特别注意,函数可以返回多个值。
可以用 () 将多个返回值转换为单个调用参数。
*/
var str = tostring( ( add(1, 2) )  );

▶ for 循环语句

import console;

for(i=1;10;1){
    console.log(i);
}

console.pause();

▶ for in 循环语句

import console;

var tab = {
    a = 123;
    b = 456;
}

for(k,v in tab){
    console.log(k,v)
}

console.pause();

▶ while 循环语句

import console;

var i = 0;
while (i < 100) {  
    i++;
         
    console.log(i);
   
    if(i==10){
        break; //中止循环
    }
}
 
console.pause();

▶ while var 语句

import console;

//用法1,while条件中使用一个var语句
while(
    var i =  console.getNumber( "请输入数值,输入0退出:" )
    ) {
    console.log( i )
}

//用法2,while条件中使用var语句、循环前执行语句、条件判断语句
while(
    var i;
    i =  console.getNumber( "请输入数值,输入100退出:" );
    i != 100  ) {
    console.log( i )
}

//用法3,省略var语句,仅使用循环前执行语句、条件判断语句
var i = 0;
while( ;i++; i<10 ) {
    console.log(i)
}

//用法4,省略var语句,循环前执行语句,仅使用条件判断语句
while(i>0){
    i--;
    console.log(i);
}

console.pause(true);

▶ while var 模拟 for 循环

import console;

while( var i = 0; i++ ; i < 5  ) {
    console.log( i )
}

console.pause(true);

▶ break label, continue label, break N, continue N 语句

break 语句中断并退出当前循环语句。

continue 语句跳过当前循环体剩下的部分,继续执行下一次循环。

break label,continue label 通过为循环指定一个标号以中断指定的循环。

break N,continue N 通过指定循环语句的嵌套层次以中断指定的循环。

import console;

var i, j;
for (i = 0; 2; 1 ) { loop1:

   for (j = 0; 2; 1) { loop2:
   
      if (i == 1 && j == 1) {
         continue loop1;
      }
      else {
         console.log("i = " + i + ", j = " + j);
      }
   }
}
console.pause(true);

注意循环标号写在循环体内部开始处。

▶ 类

//定义类
class cls{
   
    //构造函数
    ctor(name,...){
        this.name = name;
        this.args = {...}
    };
   
    //属性
    value = staticNum;
   
    //成员函数
    add = function(v){
        this.value = this.value + v;
        return this.value;
    }
}


//打开类的名字空间
namespace cls{
    staticVar = "类的静态变量值";
    staticNum = 2;
}
 
//调用类创建对象
var obj = cls();

//调用对象函数
var v = obj.add(5);

类内部可以用 this 访问当前创建的实例对象。

类总是先调用构造函数 ctor 才会初始化其他成员。

每个类都有自己的名字空间。

类创建的所有实例共享同一名字空间。

类名字空间的成员也就是类的静态成员。

▶ self,this,owner

self 表示当前名字空间。

this 在类内部表示当前创建的实例对象。

每个函数都有自己的 owner 参数( 无法使用外部函数的 owner 参数 )。如果用点号作为成员操作符获取并调用对象的成员函数,则点号前面的对象是被调用成员函数的 owner 参数,否则被调用函数的 owner 参数为 null。例如 obj.func() 调用 obj 的成员函数 func,则 obj 是 obj.func 的 owner 参数。

注意一个独立的 aardio 代码文件编译后也相当于一个匿名的函数。独立运行的 aardio 代码文件 owner 参数默认为 null ,使用 import 语句加载的库文件,owner 参数为加载路径、或资源文件数据。

owner 在元方法中表示左操作数。

在迭代器函数中,owner 表示迭代目标对象。

aardio 允许用 call, callex, invoke 等函数调用其他函数并改变 owner 参数的值。

内容来源于网络如有侵权请私信删除

文章来源: 博客园

原文链接: https://www.cnblogs.com/aardio/p/16657471.html

你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!