# auto-lang **Repository Path**: auto-stack/auto-lang ## Basic Information - **Project Name**: auto-lang - **Description**: A language that automates many things. - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 7 - **Forks**: 0 - **Created**: 2024-10-15 - **Last Updated**: 2026-02-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ![icon](docs/icon.png) AutoLang is a programming language designed for automation and flexibility. - **Automation**: AutoLang is designed for automation of many development tasks. - **Flexible**:AutoLang supports multiple syntaxes, each tailored to a particular scenario. - AutoLang: AutoLang itself is a static/dynamic mixed language, and can be transpiled to C and Rust. - AutoScript: AutoLang can be used as a dynamic scripting language, and be embedded into Rust/C projects as a scripting engine. - AutoConfig: AutoLang is a superset of JSON, and can be used as a dynamic configuration language. - AutoDSL: AutoLang can be used as a DSL for UI applications. - AutoShell: AutoLang can be used as a cross-platform shell script. - Auto2C: AutoLang can be transpiled to C, and work with C in a mixed project managed by AutoMan. - **Simplicity**&**Efficiency**: - As a scripting language, AutoLang provides simplicity and ease of use on par with Python. - As a static language, AutoLang is transpiled to C and Rust, providing similar performance to C and Rust. - **Fullstack**:AutoLang is part of AutoStack, a fullstack platform for development. - Standard Library: A customizable standard library that supports BareMetal, RTOS and Linux/Windows/MacOS/Web. - Builder&Package Manager: AutoMan is a builder that supports Auto/C/Rust mixed projects. It's configured with AutoConfig. - UI Framework: AutoUI is a cross-platform UI framework based on Rust/GPUI, similar to Jetpack Compose. It now supports Windows/Linux/Mac, and will be extended to Web, Bevy and HarmonyOS. - Code Gen: AutoGen is a powerfull code generation tool that supports C/Rust/HTML and more. See [Tutorial](docs/tutorials/autogen-tutorial.md). - IDE: As AutoUI is based on Zed/GPUI, we'll build a plugin system with AutoLang, and provide a IDE. ## Execution Modes **AutoVM** is the default execution engine for AutoLang (Plan 081). AutoVM is a fast bytecode VM that provides consistent behavior across all platforms. ### Mode Selection AutoLang supports multiple execution and transpilation modes: - **AutoVM** (default) - Fast bytecode VM execution - **C Transpilation** - Transpile to C for embedded systems - **Rust Transpilation** - Transpile to Rust for native applications - **Evaluator** - Legacy TreeWalker interpreter (deprecated) You can specify the execution mode in your `pac.at` file: ```auto // pac.at name: "myapp" version: "1.0.0" mode: "autovm" // Options: "autovm", "c", "rust", "evaluator" app("myapp") { dependencies: [ "std:core", ("hal", mode: "c"), # HAL in C ("crypto", mode: "rust"), # Crypto in Rust ] } ``` ### Mixed-Mode Projects Different parts of your project can use different execution modes: ```auto mode: "autovm" # Main app uses AutoVM app("mixed_app") { dependencies: [ ("hal", mode: "c"), # Hardware layer in C ("crypto", mode: "rust"), # Crypto library in Rust "utils", # Utilities in AutoVM (default) ] } ``` AutoVM bytecode can call C and Rust functions via the FFI layer, enabling seamless integration between modes. ### Environment Variable Override You can override the execution mode at runtime: ```bash # Force Evaluator mode (for debugging) export AUTO_EXECUTION_ENGINE=evaluator auto run myapp.at # Force AutoVM mode export AUTO_EXECUTION_ENGINE=autovm auto run myapp.at ``` **Note**: The `use-bigvm` feature flag is deprecated. AutoVM is now the default and no feature flags are required. ### Learn More - [Mode Selection Guide](docs/guides/mode-selection-guide.md) - [FFI Usage Guide](docs/guides/ffi-usage-guide.md) - [Migration Guide](docs/guides/migration-guide.md) - [Plan 081: AutoVM as Default](docs/plans/081-autovm-default-mode.md) ## Language Tour #### Hello World ```rust // Script mode print("Hello, world!") // Static mode fn main { println("Hello, world!") } ``` #### Basic Types and Storage Values Auto supports basic types: int(i32), uint(u32), byte(u8), float(f64), bool, nil. ```rust // normal storage value, not mutable let a int = 1 a = 2 // Error! a is not mutable // variable storage value, with type inference var b = 2.2 b = 3.3 // const storage value, usually used as global constants const PI = 3.14 PI = 3.15 // Error! PI is not mutable // variant storage value, used in script mode (dynamic typing) var c = true // vars can mutate its value c = false // and its type! c = "hello" // nil is a special type, it's a zero-size type c = nil // operations that includes nil will always return nil let d = nil + 1 // d is nil ``` TODO: translate more syntax overview examples into Language Tour ## Scenarios and Usages ### 1. Auto2C A function in AutoLang: ```rust // math.a pub fn add(a int, b int) int { a + b } ``` ```rust // main.a use math::add fn main { println(add(1, 2)) } ``` Transpiles to three C files: math.h, math.c and main.c: ```c // math.h #pragma once #include int32_t add(int32_t a, int32_t b); ``` ```c // math.c #include #include "math.h" int32_t add(int32_t a, int32_t b) { return a + b; } ``` ```c #include #include #include "math.h" int main(void) { printf("%d\n", add(1, 2)); return 0; } ``` ### 2. AutoConfig AutoConfig is a superset of JSON, and can use scripting abilities of AutoLang. ```rust // use Standard library use std::str::upper; // Variable var dir = "/home/user/data" // {key : value} pairs root: dir // Function call root_upper: root.upper() // String interpolation views: f"${dir}/views" // Find key in config styles: f"${views}/styles" // Object attrs: { prefix: "auto" // Array excludes: [".git", ".auto"] } ``` This dynamic config is evaluated to a big JSON object. ### 3. AutoMan AutoConfig is used to configure AutoMan, the builder for Auto and C projects. ```rust project: "osal" version: "v0.0.1" // Dependencies, can specify parameters dep(FreeRTOS, "v0.0.3") { heap: "heap_5" config_inc: "demo/inc" } // Libraries in this project lib(osal) { pac(hsm) { skip: ["hsm_test.h", "hsm_test.c"] } pac(log) link: FreeRTOS } // Ports to different platforms with support for multiple toolchains/IDEs port(windows, cmake, x64, win32, "v1.0.0") port(stm32, iar, arm_cortex_m4, f103RE, "v1.0.0") // Executables exe(demo) { // Static link link: osal // Specify output file name outfile: "demo.bin" } ``` ### 4. AutoShell ```rust #!auto // Built-in common libraries in script mode print "Hello, world!" // The following command will be converted to function call: `mkdir("src/app", p=true)` mkdir -p src/app cd src/app touch main.rs // Define variables and functions as usual scripting language let ext = ".c" fn find_c_files(dir) { ls(dir).filter(|f| f.endswith(ext)).sort() } // Call commands in a loop touch "merged.txt" for f in find_c_files("src/app") { cat f >> "merged.txt" } // Call async commands in a loop let downloads = for f in readlines("remote_files.txt").map(trim) { async curl f"http://database.com/download?file=${f}" } // Wait for all downloads to complete await downloads.join() ``` AutoShell is implemented by adding a special rule to AutoLang: - When in shell scenaria, all `first level` statements will support a shell like call syntax. for example: ```bash grep -Hirn TODO . ``` will be converted to this normal Auto function call: ```rust grep(key:"TODO", dir:".", H, i, r, n) ``` And if `grep()` is defined in `std::shell`, it will be called directly. If not found, a compile error will be reported. These Auto shell functions are actually implemented by Rust code, e.g.: [coreutils](https://github.com/uutils/coreutils) ### 5. AutoTemplate ```html ${title}

${title}

    $ for n in 1..10 {
  • Item $n
  • }
``` An Auto Template is actually a normal code embedded with Auto snippets. We do a translation form the above HTML code into normal Auto code: ```rust `` `` ` ${title}` `` `` `

${title}

` `
    ` for n in 1..10 { `
  • Item $n
  • ` } `
` `` `` ``` These are lines of strings (potentially with `$` interpolation), some of which are wrapped by `for` blocks; In Template scenario, these lines are treated as string expression statements, and will be congregated into a big string. As a comparison, statements in normal Auto code are executed one by one, but only the last statement is returned. AutoTemplate can work with any type of text. AutoTemplate is the basis of `AutoGen`, which can generate many types of code. ### 6. AutoUI [`AutoUI`](https://github.com/auto-stack/auto-ui) is a UI framework based on `Zed/GPUI`, supporting Windows/Linux/MacOS/Web. AutoLang works as a DSL to describe UI components. The syntax is similar to Kotlin, and the code organization is similar to Vue.js. ```rust // Define a component widget counter { // Model that stores reactive data model { var count: i32 = 0 fn reset() { count = 0 } } // View that describes UI layout view { cols { button("➕") { // callback function that works with data in the model on_click: => count += 1 } text(f"Count: {count}") button("➖") { on_click: => count -= 1 } icon("🔄") { on_click: => reset() } style {gap-2 w-full} } } style { // Style currently supports Tailwind CSS syntax "w-24 h-24 border-1 border-color-gray-300" } } ``` A widget described above will be parsed into a `DynamicWidget` object, which can be directly drawn in `AutoUI`. In this dynamic mode, widgets support live reloading. Later, we'll provide a static mode that transpiles the Auto code into Rust code, and the output UI executable could be as performant as native GPUI applications (like the Zed Editor). ## Syntax Overview TODO: translate into English ### 存量 在auto语言里,有三种不同类型的"存量",用来存放与访问数据: - 定量(`let`):定量是声明之后就不能再改变的量,但是可以取地址和访问。相当于Rust中的`let`。 - 变量(`var`):这种存量的值可以任意改变,但是类型一旦确定就不能再改变。这其实就是C/C++中的普通变量。在Rust中,这样的变量用`let mut`声明。 - 常量(`const`):常量是声明之后就不能再改变的量,但是可以取地址和访问。相当于Rust中的`const`。 ```rust // 定量 let b = 1 // Error! 定量不能修改 b = 2 // 可以用来计算新的存量 let f = e + 4 // 定量可以重新声明,但类型不能改变 let b = b * 2 // 变量定义,编译器可以自动推导类型 var a = 1 // 变量的定义可以指定类型 var b bool = false // 声明多个变量 var c, d = 2, 3 // 变量可以修改,也叫"赋值" a = 10 // 甚至可以交换两个变量的值 c, d = d, c // 常量定义:常量只能是全局量 const PI = 3.14 ``` ### 数组 ```rust // 数组 let arr = [1, 2, 3, 4, 5] // 下标 println(arr[0]) println(arr[-1]) // 最后一个元素 // 切片 let slice = arr[1..3] // [2, 3] let slice1 = arr[..4] // [1, 2, 3, 4] let slice2 = arr[3..] // [4, 5] let slice3 = arr[..] // [1, 2, 3, 4, 5] // 范围(Range) let r = 0..10 // 0 <= r < 10 let r1 = 0..=10 // 0 <= r <= 10 ``` ### 对象 ```rust // 对象 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") ``` ### Grid Grid是Auto语言的二维数组,可以用于表格数据。 Grid可以扩展为类似DataFrame/Tensor的多维结构,用来和Python交互,进行AI相关的开发。 ```rust // 定义一个Grid let grid = grid(a:"first", b:"second", c:"third") { [1, 2, 3] [4, 5, 6] [7, 8, 9] } // 转化为JSON var json = grid.to_json() // 相当于 var grid = { "cols": [ {id: "a", name: "first"}, {id: "b", name: "second"}, {id: "c", name: "third"}, ], "data": [ {"a": 1, "b": 2, "c": 3}, {"a": 4, "b": 5, "c": 6}, {"a": 7, "b": 8, "c": 9}, ] } ``` ### 函数 ```rust // 函数定义 fn add(a int, b int) int { a + b } // 函数变量(Lambda) let mul = |a int, b int| a * b // 函数作为参数 fn calc(op |int, int| int, a int, b int) int { op(a, b) } // 函数调用 calc(add, 2, 3) calc(mul, 2, 3) ``` ### 数值的传递 在Auto语言中,值的传递可以有如下几种形式: - 拷贝(copy):拷贝传递,直接拷贝一份数据。 - 引用(ref):引用传递,不需要拷贝数据,但是不可以修改原始数据。 - 转移(move):转移传递,把值的所有权转移到目标存量,转移后原始存量就不能再用了 - 指针(ptr):新建一个指向同一个地址的指针。可以进行底层的操作。指针只在底层的系统编程中使用,因此要放在`sys`代码块中。 引用比拷贝节省了内存空间和复制时间,但引用实际上也是通过地址进行间接访问的,所以访问时间会比拷贝略慢。 对于较小的数据,如int、float、bool,或者类似于`Point{x, y}`这种简单的数据类型,传递时进行拷贝的代价很小,往往比引用更合适。 我们把这种类型叫做“数值类型”。 对于较大的数据,如`Vec`、`HashMap`、`String`等,传递时进行拷贝的代价较大,往往用引用更合适。 我们把这种类型叫做“引用类型”。 因此,Auto语言针对不同的数据,采取了不同的传递方式: 1. 对于较小的“数值类型”的存量,默认用拷贝传递。 2. 对于较大的“引用类型”的存量,默认用引用传递。 下面举两个例子: ```rust // 数值类型:默认拷贝传递 let a = 1 let b = a // 这里b是a的一份拷贝 var c = a // 这里c是a的一份拷贝,而且c可以修改 c = 2 println(c) // 2 println(a) // 1 // a没有变化 ``` ```rust // 引用类型:默认引用传递 let a = [1, 2, 3, 4, 5] // 数组默认是引用类型 let b = a // 这里b是a的一个引用,在使用b的时候,就和使用a一样。内存中只存在一个数组。 var c = a // 错误!由于a是不可修改的,所以可修改的c不能引用它。 var d = copy a // 如果想进行修改,可以显式地复制它。 d[0] = 9 // d = [9, 2, 3, 4, 5] println(a) // a = [1, 2, 3, 4, 5], a数组没变 ``` 上面的例子中,使用`copy`关键字,显式地进行了拷贝。 但这样效率显然不高,因此我们还有一个“两全其美”的办法,那就是转移: ```rust // 转移传递 let a = [1, 2, 3, 4, 5] let b = move a // 转移后,a不能再使用 println(a) // Error! a已经不能再使用 var c = move b // b转移给了c,由于是转移,c可以选择修改 c[0] = 9 // c = [9, 2, 3, 4, 5] println(b) // Error! b已经不能再使用 ``` 我们可以看到,`a`的值在转移到`b`之后,它的声明周期就结束了。 从此存量`a`不复存在,但它的“灵魂”会继续在`b`中存活。 同样,`b`转移给`c`时,由于转移操作实际上一种"转世重生"、"借尸还魂", 因此`c`可以拥有和`b`不一样的属性,比如`var`。 转移相当于把拷贝和引用的好处结合在一起了,但代价是什么呢? 代价是需要编译器能够逐行分析每个存量的生命周期。 也需要程序员能够分辨出来,某个存量,什么时候就已经挂掉了。 Rust程序员很多时候在跟编译器斗争,就是因为没搞清楚每个存量的生命周期。 由于转移和指针都是比较高阶的功能,Auto语言的早期版本暂时不会实现他们, 只是作为设计放在这里。 ### 引用和指针 上面讲的拷贝和转移,都是直接操作数据,而引用和指着,则是间接地操作数据。 引用和指针的主要区别有两个: 1. 引用的作用主要是为了避免复制(例如函数传参时),方便访问。因此它用起来和原值的体验应该是一样的,所以指针虽然实际上是间接访问,但编译器做了体验优化,看起来跟直接使用一样。 2. 指针则有更多底层的功能:它可以获取地址,甚至进行地址运算。这些操作是系统级的底层代码才需要的,因此需要在`sys`代码块中执行(类似于Rust的`unsafe`块)。 ```rust // 引用 let a = [0..99999] // 我们用一个很大的数组 let b = a // 如果直接新建一个b的值,那么会把a的值拷贝一份 let c = ref a // 此时c只是a的一个“参考视图”,它本身并不存数据,也没有拷贝操作。 b = 2 // Error: 引用不能修改原始量的值 // 这里的`buf`参数,实际上是个引用 fn read_buffer(buf Buffer) { for n in buf.data { println(n) } } // var ref可以用来修改变量: var x = 1 fn inc(a var ref int) { a += 1 } inc(x) println(x) // 2 ``` ```rust // 指针 // 指针和引用不同的地方在于,因为它和原始量指向同一个地址,因此可以修改原始量的值。 var x = 1 sys { var p = ptr x p.target += 1 // 间接修改x的值,注意这里和C不一样,用的是`.target` } println(x) // 2 // 在函数调用时,指针类型的参数,可以修改原始量 var m = 10 fn inc(a ptr int) { a += 10 } inc(m) println(m) // 20 // 指针还可以直接进行地址运算 sys { // 注意:地址运算要放在sys块中 var arr = [1, 2, 3, 4, 5] var p = ptr arr // p的类型是 Ptr<[5]int> println(p) // [1, 2, 3, 4, 5] p[0] = 101 // 直接修改arr[0]的值 println(arr) // [101, 2, 3, 4, 5] var o = p // 记住p的地址 p.inc(2) // 地址自增2,此时p指向的是arr[2] println(p) // [3, 4, 5] println(o[0]) // 101 p.jump(o) // 跳回到o println(p) // [101, 2, 3, 4, 5] } ``` ### 控制流 ```rust // 条件判断 if a > 0 { println("a is positive") } else if a == 0 { println("a is zero") } else { println("a is negative") } // 循环访问数组 for n in [1, 2, 3] { println(n) } // 循环修改数组的值 var arr = [1, 2, 3, 4, 5] for ref n in arr { n = n * n } println(arr) // [1, 4, 9, 16, 25] // 循环一个范围 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 is a { // 精确匹配 41 -> println("a is 41"), // as 用于类型判断 as str -> println("a is a string"), // in 用于范围匹配 in 0..9 -> println("a is a single digit"), // if 用于条件匹配 if a > 10 -> println("a is a big number"), // 其他情况 else x-> println("a is a weired number") } ``` ### 枚举(TODO) ```rust enum Axis { Vertical // 0 Horizontal // 1 } // 带成员的枚举 enum Scale { name str S("Small") M("Medium") L("Large") } // 枚举变量 var a = Scale.M // 访问枚举成员 println(a.name) // 枚举匹配 is a { Scale::S -> println("a is small") Scale::M -> println("a is medium") 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(/*...*/) is s as Shape { Point(x, y) -> println(f"Point($x, $y)") Rect(x, y, w, h) -> println(f"Rect($x, $y, $w, $h)") 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) ``` ### Object-Oriented Programming Auto provides complete object-oriented programming support, including type definitions, inheritance, composition, and the spec system. #### Type Definitions ```rust // Define a type type Point { x int y int // Instance method fn distance(other Point) float { sqrt((.x - other.x) ** 2 + (.y - other.y) ** 2) } fn info() str { f"Point(.x, .y)" } } // Create instance var p = Point() p.x = 1 p.y = 2 println(p.info()) // "Point(1, 2)" println(p.distance(p)) // 0.0 ``` #### Single Inheritance Use the `is` keyword for single inheritance. Child types automatically inherit all fields and methods from the parent: ```rust // Parent class type Animal { name str fn speak() { print("Animal sound") } fn info() str { f"{.name}" } } // Child class inherits from parent type Dog is Animal { breed str // Can override parent methods fn speak() { print("Woof!") } // Can add new methods fn fetch() { print("Fetching...") } } fn main() { let dog = Dog() dog.name = "Buddy" dog.breed = "Labrador" // Access inherited fields print(dog.name) // Call inherited method (overridden) dog.speak() // "Woof!" // Call own method dog.fetch() } ``` **Inheritance Features**: - ✅ Field inheritance: Child types automatically include all parent fields - ✅ Method inheritance: Child types automatically get all parent methods - ✅ Method overriding: Child types can override parent methods - ✅ Type checking: Inheritance relationships are verified at compile time #### Composition Use the `has` keyword for composition to integrate functionality from other types: ```rust type Engine { power int fn start() { print("Engine started") } } type Car { has engine Engine fn drive() { .engine.start() print("Driving...") } } ``` #### Spec System Specs define interface contracts. Types can implement multiple specs: ```rust // Define spec spec Reader { fn read() str fn is_eof() bool } spec Writer { fn write(s str) fn flush() } // Implement spec (using 'as' keyword) type File as Reader, Writer { path str fn read() str { // Read file } fn is_eof() bool { // Check if end of file } fn write(s str) { // Write to file } fn flush() { // Flush buffer } } // Polymorphic function fn copy(src Reader, dst Writer) { while !src.is_eof() { let line = src.read() dst.write(line) } dst.flush() } ``` #### Transpiler Support Auto's OOP features are supported by both C and Rust transpilers: **C Transpilation** (flat struct + method prefix): ```c struct Dog { char* name; // inherited field char* breed; // own field }; void Dog_Speak(struct Dog *self) { printf("%s\n", "Woof!"); } ``` **Rust Transpilation** (flat struct + impl block): ```rust struct Dog { name: String, // inherited field breed: String, // own field } impl Dog { fn speak(&self) { println!("Woof!"); } } ``` > 📖 **More OOP Features**? See [Single Inheritance Implementation](docs/plans/021-single-inheritance.md) and [Spec Polymorphism Documentation](docs/plans/020-stdlib-io-expansion.md) ### 生成器(TODO) ```rust // 生成器 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) ```rust // 任意函数 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) ``` ### 节点 ```rust // 节点 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。 ```bash > git clone git@gitee.com:auto-stack/auto-lang.git > cd auto-lang > cargo build --release > cargo run --release ``` ## 架构说明 AutoLang 有一个主要实现(Rust 编译器),支持五种执行模式: 1. **解释执行**: 直接运行 AutoLang 代码(REPL、脚本执行) 2. **转译到 C (a2c)**: 将 AutoLang 转译为 C 代码,用于嵌入式系统 3. **转译到 Rust (a2r)**: 将 AutoLang 转译为 Rust 代码,用于原生应用 4. **转译到 Python (a2p)**: 将 AutoLang 转译为 Python 代码,用于快速原型和 Python 生态集成 5. **转译到 JavaScript (a2j)**: 将 AutoLang 转译为 JavaScript (ES6+) 代码,用于 Web 开发和 Node.js 测试文件说明: - `crates/auto-lang/test/a2c/` - Auto 到 C 转译器测试 - `crates/auto-lang/test/a2r/` - Auto 到 Rust 转译器测试 - `crates/auto-lang/test/a2p/` - Auto 到 Python 转译器测试 - `crates/auto-lang/test/a2j/` - Auto 到 JavaScript 转译器测试 ## Python Transpiler (a2p) AutoLang 支持转译到 Python 3.10+,实现以下特性: ### 核心特性 - ✅ **完美 F-string 映射**: AutoLang 和 Python 的 f-string 语法几乎相同 - ✅ **模式匹配**: 完整支持 `match/case` 语句(需要 Python 3.10+) - ✅ **智能类生成**: 自动检测 `@dataclass` 和普通类 - ✅ **类型支持**: 结构体、枚举、方法和继承 - ✅ **零依赖**: 生成的 Python 代码只需要标准库 ### 使用方法 ```bash # 转译 AutoLang 到 Python auto.exe python hello.at # 运行生成的 Python python hello.py ``` ### 代码示例 **AutoLang 代码:** ```auto type Point { x int y int fn modulus() int { .x * .x + .y * .y } } fn main() { let p = Point{x: 0, y: 0} print(f"Modulus: ${p.modulus()}") } ``` **生成的 Python 代码:** ```python class Point: def __init__(self, x: int, y: int): self.x = x self.y = y def modulus(self): return self.x * self.x + self.y * self.y def main(): p = Point(x=0, y=0) print(f"Modulus: {p.modulus()}") if __name__ == "__main__": main() ``` ### 语言映射 | AutoLang | Python | 说明 | |----------|--------|------| | `type Point { x int }` | `@dataclass\nclass Point:` | 无方法时使用 @dataclass | | `type Point { fn m() {} }` | `class Point:\n def __init__...` | 有方法时使用普通类 | | `enum Color { Red }` | `class Color(Enum)` | 使用 enum.Enum | | `is x { 0 => print() }` | `match x:\n case 0:` | Python 3.10+ | | `for i in 0..10` | `for i in range(0, 10)` | 范围转换为 range() | | `f"hello $name"` | `f"hello {name}"` | 自动转换变量语法 | ### 测试覆盖 当前支持 10 个测试用例,全部通过 ✅: 1. `000_hello` - 基础打印 2. `002_array` - 数组和索引 3. `003_func` - 函数 4. `006_struct` - 结构体定义 (@dataclass) 5. `007_enum` - 枚举定义 (class Enum) 6. `008_method` - 类方法 7. `010_if` - if/else 语句 8. `011_for` - for 循环 9. `012_is` - 模式匹配 (match/case) 10. `015_str` - F-strings ### 文档 完整的 Python 转译器文档请参考:[Python Transpiler Documentation](docs/python-transpiler.md) ### 限制 以下特性尚未实现: - Lambda 函数 - 块表达式 - If 表达式(三元运算符) - 枚举变体访问(如 `Color.Red`) - 结构体构造语法(如 `Point{x: 1, y: 2}`) - for 循环中的 enumerate ### Python 版本要求 - **最低版本**: Python 3.10+ - **原因**: `match/case` 语句需要 Python 3.10 或更高版本 ## JavaScript Transpiler (a2j) AutoLang 支持转译到 JavaScript ES6+,实现以下特性: ### 核心特性 - ✅ **完美 Template Literal 映射**: AutoLang 的 f-string 语法与 JavaScript 模板字符串几乎相同 - ✅ **ES6+ 类**: 使用现代 ES6 class 语法生成结构体 - ✅ **模式匹配**: 完整支持 `switch/case` 语句 - ✅ **方法支持**: 自动将 `.x` 转换为 `this.x` - ✅ **动态类型**: JavaScript 的动态类型与 AutoLang 完美匹配 - ✅ **零依赖**: 生成的 JavaScript 代码无需任何 polyfills ### 使用方法 ```bash # 转译 AutoLang 到 JavaScript auto.exe java-script hello.at # 运行生成的 JavaScript(需要 Node.js) node hello.js ``` ### 代码示例 **AutoLang 代码:** ```auto type Point { x int y int fn modulus() int { .x * .x + .y * .y } } fn main() { let p = Point{x: 3, y: 4} let m = p.modulus() print(f"Modulus: $m") } ``` **生成的 JavaScript 代码:** ```javascript class Point { constructor(x, y) { this.x = x; this.y = y; } modulus() { return this.x * this.x + this.y * this.y; } } function main() { const p = new Point(3, 4); const m = p.modulus(); console.log(`Modulus: ${m}`); } main(); ``` ### 语言映射 | AutoLang | JavaScript | 说明 | |----------|-----------|------| | `let x = 1` | `const x = 1` | 不可变变量使用 const | | `var x = 1` | `let x = 1` | 可变变量使用 let | | `type Point { x int }` | `class Point { constructor... }` | ES6 类语法 | | `enum Color { Red }` | `const Color = Object.freeze({...})` | 冻结对象防止修改 | | `is x { 0 => print() }` | `switch (x) { case 0: ... }` | switch/case 语句 | | `for i in 0..10` | `for (let i = 0; i < 10; i++)` | 传统 for 循环 | | `f"hello $name"` | `` `hello ${name}` `` | 模板字符串(反引号) | | `.x` (方法内) | `this.x` | 自动转换 self 为 this | | `print(...)` | `console.log(...)` | 自动转换函数名 | ### 测试覆盖 当前支持 9 个测试用例,全部通过 ✅: 1. `000_hello` - 基础打印 2. `002_array` - 数组和索引 3. `003_func` - 函数声明和调用 4. `006_struct` - 结构体定义 (ES6 class) 5. `007_enum` - 枚举定义 (Object.freeze) 6. `008_method` - 类方法 (this 转换) 7. `010_if` - if/else 语句 8. `011_for` - for 循环 9. `012_is` - 模式匹配 (switch/case) ### 文档 完整的 JavaScript 转译器文档请参考:[JavaScript Transpiler Documentation](docs/javascript-transpiler.md) ### 限制 以下特性尚未实现: - Lambda 函数(箭头函数) - If 表达式(三元运算符 `? :`) - ES6 模块(import/export) - 异步支持(async/await) - 生成器函数 ### 环境要求 - **Node.js**: v12.0.0 或更高版本(支持 ES6+) - **浏览器**: 任意现代浏览器(Chrome 51+, Firefox 54+, Safari 10+, Edge 15+) - **原因**: 需要支持 ES6+ 特性(class、模板字符串、箭头函数等)