Files
camellya/README.md
2026-01-19 22:07:25 +08:00

224 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Camellya Script Language
一个类似 Lua 的脚本语言,使用 C++23 实现,具有以下特性:
## 特性
- **0-based 索引**:数组和列表从 0 开始索引
- **明确的类型系统**:区分 list 和 map
- **类支持**:支持 class 定义,包含字段和方法
- **类型推断**:使用 `var` 关键字自动推断变量类型,也支持显式类型注解
- **类 Lua 的 API**:提供简单的嵌入式 API
## 语法示例
### 基本类型
```javascript
// 类型自动推断
var x = 10;
var name = "Alice";
var flag = true;
// 显式类型声明
var y : number = 3.14;
var title : string = "Developer";
var active : bool = false;
```
### List0-indexed
```javascript
var numbers = [10, 20, 30]; // 自动推断为 list
print(numbers[0]); // 输出: 10
numbers[1] = 99;
```
### Map
```javascript
var person = {"name": "Bob", "age": "25"}; // 自动推断为 map
print(person["name"]); // 输出: Bob
person["city"] = "New York";
```
### 函数
```javascript
func add(number a, number b) -> number {
return a + b;
}
var result = add(10, 20); // 自动推断返回值类型
```
### 类
```javascript
class Person {
var age : number; // 类成员必须显式声明类型
var name : string;
func sayHi() -> string {
print(name, "says: I'm", age, "years old");
return "Done";
}
}
var p : Person; // 实例化类
p.age = 10;
p.name = "Peter";
p.sayHi();
```
### 控制流
```javascript
// if-else
if (x > 10) {
print("x is greater than 10");
} else {
print("x is less than or equal to 10");
}
// while loop
var i = 0;
while (i < 5) {
print("Count:", i);
i = i + 1;
}
// for loop
for (var j = 0; j < 3; j = j + 1) {
print("For loop:", j);
}
```
## 编译和使用
### 编译
```bash
mkdir build
cd build
cmake ..
make
```
### 运行示例
```bash
./camellya_test
```
### 嵌入到 C++ 项目
```cpp
#include "library.h"
#include <iostream>
int main() {
camellya::State state;
// 执行脚本字符串
const char* script = R"(
class Person {
var age : number;
var name : string;
func sayHi() -> string {
print(name, "says: I'm", age, "years old");
return "Done";
}
}
var p : Person;
p.age = 10;
p.name = "Peter";
p.sayHi();
)";
if (!state.do_string(script)) {
std::cerr << "Error: " << state.get_error() << std::endl;
}
// 或者从文件执行
state.do_file("script.chun");
// 注册 C++ 函数
state.register_function("my_func",
[](const std::vector<camellya::ValuePtr>& args) -> camellya::ValuePtr {
// 你的实现
return std::make_shared<camellya::NilValue>();
});
return 0;
}
```
## API 参考
### State 类
主要 API 类,类似于 `lua_State`
- `bool do_string(const std::string& script)` - 执行脚本字符串
- `bool do_file(const std::string& filename)` - 执行脚本文件
- `void register_function(const std::string& name, NativeFunction func)` - 注册 C++ 函数
- `ValuePtr get_global(const std::string& name)` - 获取全局变量
- `void set_global(const std::string& name, ValuePtr value)` - 设置全局变量
- `const std::string& get_error()` - 获取最后的错误信息
### 栈操作(类似 Lua
- `void push_number(double value)`
- `void push_string(const std::string& value)`
- `void push_bool(bool value)`
- `void push_nil()`
- `double to_number(int index)`
- `std::string to_string(int index)`
- `bool to_bool(int index)`
- `int get_top()`
- `void pop(int n = 1)`
## 内置函数
- `print(...)` - 打印多个参数到标准输出
- `len(container)` - 返回 list、map 或 string 的长度
## 项目结构
```
camellya/
├── library.h # 主头文件
├── library.cpp # 主实现
├── lexer.h/cpp # 词法分析器
├── parser.h/cpp # 语法分析器
├── ast.h # 抽象语法树定义
├── value.h/cpp # 值类型系统
├── interpreter.h/cpp # 解释器
├── state.h/cpp # 主 API 接口
├── main.cpp # 示例程序
├── example.cml # 示例脚本
└── CMakeLists.txt # 构建配置
```
## 特性对比
| 特性 | Lua | Camellya |
|------|-----|----------|
| 索引起始 | 1 | 0 |
| Table | 统一的 table | 区分 list 和 map |
| 类型 | 动态 | 类型推断 + 可选类型注解 |
| 类 | 通过 metatable | 原生支持 |
| 语法 | `function` | `func` |
| 变量声明 | 无需声明 | `var` 关键字 |
## 许可证
MIT License
## 版本
当前版本0.1.0