1 unstable release
0.1.0 | Oct 17, 2024 |
---|
#435 in Programming languages
195 downloads per month
65KB
1.5K
SLoC
Auto编程语言
Auto编程语言(Auto Lang)有如下特点:
- 设计目标:自动化
- 类型:类C
- 生态:C/C++/Rust
- 实现语言:Rust
Auto语言是Soutek公司推出的技术产品Soutek Auto Stack的一部分。
用途
1. 作为配置语言,替代JSON/YAML
// 标准库
use std::str::upper;
// 变量
var dir = "/home/user/data"
// {key : value}对
root: dir
// 函数调用
root_upper: root.upper()
// 字符串
views: f"${dir}/views"
// 可以在配置中查找key
styles: f"${views}/styles"
// 对象
attrs: {
prefix: "auto"
// 数组
excludes: [".git", ".auto"]
}
Auto语言的配置文件(Auto Config)后缀名为.ac
。
2. 作为构建器
配合Auto Builder,可以实现类似CMake的C/C++工程构建:
project: "osal"
version: "v0.0.1"
// 依赖项目,可以指定参数
dep(FreeRTOS, "v0.0.3") {
heap: "heap_5"
config_inc: "demo/inc"
}
// 本工程中的库
lib(osal) {
pac(hsm) {
skip: ["hsm_test.h", "hsm_test.c"]
}
pac(log)
link: FreeRTOS
}
// 可以输出到不同的平台,指定不同的编译工具链、架构和芯片
port(windows, cmake, x64, win32, "v1.0.0")
port(stm32, iar, arm_cortex_m4, f103RE, "v1.0.0")
// 可执行文件
exe(demo) {
// 静态链接
link: osal
// 指定输出文件名
outfile: "demo.bin"
}
3. 作为脚本
#!auto
// 脚本模式下内置了常用的库
print "Hello, world!"
// 下面的命令会自动转化为函数调用:`mkdir("src/app", p=true)`
mkdir -p src/app
cd src/app
touch main.rs
// 也可以定义变量和函数
var ext = ".c"
fn find_c_files(dir) {
ls(dir).filter(|f| f.endswith(ext)).sort()
}
// 可以顺序调用命令
touch "merged.txt"
for f in find_c_files("src/app") {
cat f >> "merged.txt"
}
// 可以异步调用多个命令
let downloads = for f in readlines("remote_files.txt").map(trim) {
async curl f"http://database.com/download?file=${f}"
}
// 可以选择等待所有的文件都下载完成
await downloads.join()
Auto语言的脚本(Auto Script)文件后缀名为.as
。
Auto语言提供了一个动态执行环境(Auto Shell),可以用于脚本执行、开发调试等。
4. 作为模板
<html>
<head>
<title>${title}</title>
</head>
<body>
<h1>${title}</h1>
<ul>
$ for n in 1..10 {
<li>Item $n</li>
}
</ul>
</body>
</html>
模板可以替代任意形式的文本。
Auto语言的模板(Auto Template)文件后缀名为.at
。
Auto模板是Auto Gen代码生成系统的基础。
5. 作为UI系统的DSL
在Auto UI系统中,Auto模板用来描述UI界面。 Auto UI模板的语法风格类似Kotlin,组织模式类似于Vue.js。
// 定义一个组件
widget counter(id) {
// 数据模型
model {
var count: i32 = 0
fn reset() {
count = 0
}
}
// 视图,用来描述UI的布局
view {
cols {
button("➕") {
on_click: || count += 1
}
text(f"Count: {count}")
button("➖") {
on_click: || count -= 1
}
icon("🔄") {
on_click: || reset()
}
style {gap-2 w-full}
}
// 样式,支持Tailwind CSS语法
style {w-24 h-24 border-1 border-color-gray-300}
}
}
语法概览
变量
// 变量定义
var a = 1
// 指定类型
var b bool = false
// 多变量
var c, d = 2, 3
// 常量定义
const PI = 3.14
函数
// 函数定义
fn add(a int, b int) int {
a + b
}
// 函数变量(Lambda)
var my_mul = |a int, b int| a * b
// 函数作为参数
fn calc(a int, b int, op fn(int, int) int) int {
op(a, b)
}
// 函数调用
calc(2, 3, add)
calc(2, 3, my_mul)
数组
// 数组
var arr = [1, 2, 3, 4, 5]
// 下标
println(arr[0])
println(arr[-1]) // 最后一个元素
// 切片
var slice = arr[1..3] // [2, 3]
var slice1 = arr[..4] // [1, 2, 3, 4]
var slice2 = arr[3..] // [4, 5]
var slice3 = arr[..] // [1, 2, 3, 4, 5]
// 范围(Range)
var r = 0..10 // 0 <= r < 10
var r1 = 0..=10 // 0 <= r <= 10
控制流
// 条件判断
if a > 0 {
println("a is positive")
} else if a == 0 {
println("a is zero")
} else {
println("a is negative")
}
// 循环访问数组
for i in [1, 2, 3] {
println(i)
}
// 循环一个范围
for n in 0..5 {
println(n)
}
// 带下标的循环
for i, n in arr() {
println(f"arr[{i}] = {n}")
}
// 无限循环
var i = 0
loop {
println("loop")
if i > 10 {
break
}
i += 1
}
// 模式匹配,类似switch/match
when a {
// is 用于精确匹配
is 41 => println("a is 41"),
// in 用于范围匹配
in 0..9 => println("a is a single digit"),
// if 用于条件匹配
if a > 10 => println("a is a big number"),
// as 用于类型判断
as str => println("a is a string"),
// 其他情况
else => println("a is a weired number")
}
对象
// 对象
var obj = {
name: "John",
age: 30,
is_student: false
}
// 访问对象成员
println(obj.name)
// 成员赋值
obj.name = "Tom"
// get or else
println(obj.get_or("name", "Unknown"))
// get or insert
println(obj.get_or_insert("name", 10))
// 所有成员
println(obj.keys())
println(obj.values())
println(obj.items())
// 遍历对象
for k, v in obj {
println(f"obj[{k}] = {v}")
}
// 删除
obj.remove("name")
枚举(TODO)
enum Axis {
Vertical // 0
Horizontal // 1
}
// 带成员的枚举
enum Scale {
name str
S("Small")
M("Medium")
L("Large")
}
// 枚举变量
var a = Scale.M
// 访问枚举成员
println(a.name)
// 枚举匹配
when a {
is Scale::S => println("a is small")
is Scale::M => println("a is medium")
is Scale::L => println("a is large")
else => println("a is not a Scale")
}
// 联合枚举
enum Shape union {
Point(x int, y int)
Rect(x int, y int, w int, h int)
Circle(x int, y int, r int)
}
// 联合枚举匹配
var s = get_shape(/*...*/)
when s as Shape {
is Point(x, y) => println(f"Point($x, $y)")
is Rect(x, y, w, h) => println(f"Rect($x, $y, $w, $h)")
is Circle(x, y, r) => println(f"Circle($x, $y, $r)")
else => println("not a shape")
}
// 获取联合枚举的数据
var p = s as Shape::Point
println(p.x, p.y)
类型(TODO)
// 类型别名
type MyInt = int
// 类型组合
type Num = int | float
// 类型判断
trait Printable {
fn print()
}
type MyInt {
data int
}
MyInt as Printable {
pub fn print() {
println(.data)
}
}
// 类型判断
var myint = MyInt{10}
print(myint)
trait Indexable {
fn get(index int) any
}
type MyArray {
data []any
as Indexable {
pub fn get(index int) any {
.data[index]
}
}
}
// 复杂类型判断,参数为type,且返回bool的函数,可以用来做任意逻辑的类型判断
fn IsArray(T type) bool {
when T {
is []E => true
as Iterable => true
else => false
}
}
// 这里参数arr的类型只要通过了IsArray(T)的判断,就能够调用,否则报错
fn add_all(arr if IsArray) {
var sum = 0
for n in arr {
sum += n
}
return sum
}
add_all([1, 2, 3, 4, 5])
var d = 15
add_all(d) // Error! d既不是[]int数组,也没有实现Iterable接口
type MySet {
data [int]int
cur int
pub static fn new(data int...) MySet {
MySet{data: data.pack(), cur: 0}
}
// ...
as Iterable {
pub fn next() int {
var n = .data[.cur]
.cur += 1
return n
}
}
}
// MySet实现了Iterable接口,所以可以用于for循环
add_all(MySet::new(1, 2, 3, 4, 5))
生成器(TODO)
// 生成器
fn fib() {
var a, b = 0, 1
loop {
yield b
a, b = b, a + b
}
}
// 使用生成器
for n in fib() {
println(n)
}
// 或者函数式
fib().take(10).foreach(|n| println(n))
异步(TODO)
// 任意函数
fn fetch(url str) str {
// ...
}
// do关键字表示异步调用
let r = do fetch("https://api.github.com")
// 返回的是一个Future,需要等待结果
println(wait r)
// 多个异步调用
let tasks = for i in 1..10 {
do fetch(f"https://api.github.com/$i")
}
// 等待所有任务都完成(或者超时)
let results = wait tasks
println(results)
节点
// 节点
node button(id) {
text str
scale Scale
onclick fn()
}
// 新建节点
button("btn1") {
text: "Click me"
scale: Scale.M
onclick: || println("button clicked")
}
// 多层节点
node div(id) {
kids: []any
}
node li(id) {
text str
kids: []div
}
node ul(id=nil) {
kids: []li
}
node label(content) {
}
ul {
li {
label("Item 1: ")
button("btn1") {
text: "Click me"
onclick: || println("button clicked")
}
div { label("div1")}
}
li { label("Item 2") }
li { label("Item 3") }
}
使用与安装
Auto语言编译器本身只依赖于Rust和Cargo。
> git clone git@gitee.com:auto-stack/auto-lang.git
> cd auto-lang
> cargo run
Dependencies
~5–12MB
~144K SLoC