- name
- cangjie-lang
- description
- Cangjie programming language code generation and analysis expert. Use this when users need to write or analyze Cangjie code.
# 仓颉语言代码生成与分析工作手册
---
## 目录
- [第1章:语言基础定义](#第1章语言基础定义)
- [第2章:核心语法规则](#第2章核心语法规则)
- [2.1 变量声明](#21-变量声明)
- [2.2 基础类型](#22-基础类型)
- [2.3 表达式与控制流](#23-表达式与控制流)
- [2.4 函数](#24-函数)
- [2.5 枚举类型](#25-枚举类型)
- [2.6 模式匹配](#26-模式匹配)
- [2.7 Option类型](#27-option类型)
- [2.8 class类型](#28-class类型)
- [2.9 单元测试](#29-单元测试)
- [2.10 错误处理](#210-错误处理)
- [2.11 速查手册](#211-速查手册)
- [第3章:任务处理流程](#第3章任务处理流程)
- [3.1 代码生成流程](#31-代码生成流程)
- [3.2 代码分析流程](#32-代码分析流程)
- [第4章:19个⚠️易错点检查清单](#第4章19个易错点检查清单)
- [第5章:示例与模板参考](#第5章示例与模板参考)
- [第6章:质量控制标准](#第6章质量控制标准)
- [第7章:MCP文档集成](#第7章mcp文档集成)
---
## 第1章:语言基础定义
### 1.1 文件与后缀
- **文件后缀**:`.cj`
- **语言简称**:`cj`(Cangjie)
- **入口函数**:`main()`
### 1.2 注释
```cj
// 单行注释
/*
* 多行注释
*/
/**
* 文档注释
*/
```
### 1.3 代码块结构
```cj
main() {
// 代码主体
let a: Int64 = 20
var b: Int64 = 12
println("${a}${b}")
}
```
---
## 第2章:核心语法规则
### 2.1 变量声明
#### 语法格式
```cj
修饰符 变量名: 变量类型 = 初始值
```
#### 可变性修饰符
- `let` - **不可变变量**(只能赋值一次,初始化后不可修改)
- `var` - **可变变量**(可以被多次赋值)
⚠️ **易错点1**:`let` 不支持变量遮蔽(shadowing),不能在同一作用域内重新定义同名变量。
#### 可见性修饰符
| 修饰符 | 范围 | 默认值 |
|--------|------|--------|
| `private` | class定义内可见 | ❌ |
| `public` | 模块内外均可见 | ❌ |
| `protected` | 当前模块及当前类的子类可见 | ❌ |
| `internal` | 仅当前包及子包内可见 | ✅ **默认** |
#### 静态性修饰符
- `static` - 影响成员变量的存储和引用方式
#### 示例代码
```cj
main() {
let a: Int64 = 20 // 不可变变量
var b: Int64 = 12 // 可变变量
b = 23 // 可以修改var变量
println("${a}${b}")
}
```
**示例参考**:`examples/01_variable_declaration.cj`
---
### 2.2 基础类型
#### 数值类型
**有符号整数**:`Int8`、`Int16`、`Int32`、`Int64`、`IntNative`
**无符号整数**:`UInt8`、`UInt16`、`UInt32`、`UInt64`、`UIntNative`
**浮点类型**:`Float16`、`Float32`、`Float64`
**布尔类型**:`true`、`false`
#### 字符类型(Rune)
- 使用 `Rune` 表示,可以表示 Unicode 字符集中的所有字符
- **Rune → UInt32**:`UInt32(e)` - 获取 Unicode scalar value
- **整数 → Rune**:`Rune(num)` - 值必须在有效 Unicode 范围内
- 有效范围:`[0x0000, 0xD7FF]` 或 `[0xE000, 0x10FFFF]`
⚠️ **易错点2**:Rune 转整数时需确保在有效 Unicode 范围内,否则会编译错误或运行时抛异常。
#### 转义字符
```cj
let slash: Rune = r'\\'
let newLine: Rune = r'\n'
let tab: Rune = r'\t'
```
#### Unicode 字面量
```cj
let he: Rune = r'\u{4f60}' // 你
let llo: Rune = r'\u{597d}' // 好
```
#### 字符串类型(String)
仓颉支持**三种字符串字面量**:
**1. 单行字符串字面量**
内容定义在一对单引号或双引号内,只能写在同一行:
```cj
let s1: String = ""
let s2 = 'Hello Cangjie Lang'
let s3 = "\"Hello Cangjie Lang\""
let s4 = 'Hello Cangjie Lang\n' // \n 是转义字符,表示换行
```
**2. 多行字符串字面量**
开头结尾需各存在三个双引号(`"""`)或三个单引号(`'''`),内容从开头的三个引号**换行后**的第一行开始:
```cj
// 三个双引号
let s1: String = """
""" // 空字符串(换行后才开始)
// 三个单引号
let s2: String = '''
Hello,
Cangjie Lang'''
```
**3. 多行原始字符串字面量**
以一个或多个井号(`#`)和一个单引号或双引号开头,**转义规则不适用**,**不支持插值**:
```cj
let s1: String = #""# // 空字符串
let s2 = ##'#'\n'## // \n 不是换行符,是 \ 和 n 两个字符
let s3 = ###"
Hello,
Cangjie
Lang"### // 保留换行和缩进
```
⚠️ **易错点4**:在多行原始字符串字面量中,转义字符(如 `\n`、`\t`)**不会被转义**,字面量中的内容会维持原样。
⚠️ **易错点5**:多行原始字符串字面量**不支持插值**,不要使用 `${}` 语法。
#### 插值字符串
⚠️ **易错点3**:插值字符串中使用 `${}` 表达式
```cj
let fruit = "apples"
let count = 10
let s = "There are ${count * count} ${fruit}"
```
**适用范围**:插值字符串仅适用于**单行字符串字面量**和**多行字符串字面量**,**不适用于多行原始字符串字面量**。
#### 元组(Tuple)
- **类型表示**:`(T1, T2, ..., TN)`
- **至少二元**:`(Int64, Float64)`、`(Int64, Float64, String)`
- **索引访问**:`tuple[0]`、`tuple[1]`
```cj
var tuple = (true, false)
println(tuple[0])
```
#### 数组类型
```cj
Array<T> // T 是元素类型,可以是任意类型
```
#### 区间类型(Range)
- **类型表示**:`Range<T>`(泛型)
- **包含三个值**:`start`、`end`、`step`
- **约束**:
- `start` 和 `end` 类型相同(T)
- `step` 类型是 `Int64`
- `step` 值不能等于 0
#### Unit 类型
- **唯一值**:`()`
- **支持操作**:仅赋值、判等、判不等
- ⚠️ **不支持**:其他所有操作
**示例参考**:`examples/02_basic_types.cj`
---
### 2.3 表达式与控制流
#### 条件表达式
⚠️ **易错点5**:条件表达式的括号不能省略,这是与很多语言的差异。
```cj
if (条件) { // ✅ 必须有括号
分支 1
} else {
分支 2
}
```
#### if 表达式
**基本形式**:
```cj
if (条件) {
分支 1
} else {
分支 2
}
```
**if 作为表达式**(返回值):
```cj
let a = 10
let result = if (a > 5) {
"greater than 5"
} else {
"5 or less"
}
// result = "greater than 5"
```
**模式匹配(let pattern)**:
```cj
let a = Some(3)
let d = Some(1)
if (let Some(e) <- a && let Some(f) <- d) { // 两个模式都匹配
println("${e} ${f}") // 输出: 3 1
}
```
#### while 表达式
```cj
while (条件) {
循环体
}
// do-while 形式
do {
循环体
} while (条件)
```
#### for-in 表达式
```cj
for (迭代变量 in 序列) {
循环体
}
```
**元组遍历**:
```cj
let array = [(1, 2), (3, 4), (5, 6)]
for ((x, y) in array) {
println("${x}, ${y}")
}
```
**区间遍历**:
```cj
main() {
var sum = 0
for (i in 1..=100) { // 1 到 100(包含)
sum += i
}
println(sum)
}
```
#### 跳转控制
- 支持 `break`、`continue`
- ⚠️ **易错点6**:不支持标签跳转
- ⚠️ **易错点7**:完全不支持 `goto`
**示例参考**:`examples/03_control_flow.cj`
---
### 2.4 函数
#### 函数是一等公民
- 可以作为函数的参数或返回值
- 可以赋值给变量
- 函数本身也有类型
#### 函数类型
**语法**:`(参数类型) -> 返回类型`
- 参数类型用 `()` 括起,多个参数用 `,` 分隔
- 参数类型和返回类型用 `->` 连接
```cj
func add(a: Int64, b: Int64): Int64 {
return a + b
}
type FnType = (Int64) -> Unit
func display(a: Int64): Unit {
println(a)
}
// 命名参数
func name(name!:String)
// 命名参数还可以设置默认值
func name(name!:String = "小王")
```
#### 函数参数
⚠️ **易错点8**:函数参数默认是 `let` 定义的不可变变量
```cj
// a 和 b 默认是 let 不可变的(不能显式写 let 或 var)
func add(a: Int64, b: Int64): Int64 {
return a + b
}
```
⚠️ **重要**:
- **函数参数不能显式使用 `let` 或 `var` 修饰符**(包括顶层函数、class成员方法、struct成员方法等所有函数)
- 参数默认就是 `let` 不可变的
如果需要修改参数值,应该使用局部变量:
```cj
func modify(a: Int64): Int64 {
var result = a
result = result + 1 // 修改局部变量
return result
}
```
#### 返回值简写
```cj
func add(a: Int64, b: Int64): Int64 {
a + b // 最后一个表达式自动作为返回值
}
func returnAdd(): (Int64, Int64) -> Int64 {
add // 可以直接返回函数
}
```
#### Lambda 表达式
**语法**:
```cj
{ p1: T1, ..., pn: Tn => expressions | declarations }
```
**示例**:
```cj
// 完整类型声明
let f1 = { a: Int64, b: Int64 => a + b }
// 无参 Lambda
var display = { =>
println("Hello")
println("World")
}
// 类型推断
var sum1: (Int64, Int64) -> Int64 = { a, b => a + b }
var sum2: (Int64, Int64) -> Int64 = { a: Int64, b => a + b }
// Lambda 作为参数
func f(a1: (Int64) -> Int64): Int64 {
a1(1)
}
main(): Int64 {
f({ a2 => a2 + 10 }) // 参数类型推断
}
```
**Lambda 立即调用**:
⚠️ **易错点9**:Lambda 表达式可以立即调用
```cj
let r2 = { => 123 }() // r2 = 123,立即执行
var g = { x: Int64 => println("x = ${x}") }
g(2) // 调用 Lambda
```
**示例参考**:`examples/04_functions.cj`
---
### 2.5 枚举类型
#### 定义语法
View on GitHub