跳到主要内容

错误处理

Alia 语言提供 try、catch 与 throw 关键字处理错误。

1. 基本语法​

try-catch 语句​

try <Stack tryStack> catch <Key e> <Stack catchStack>

try 块抛出的错误由 catch 捕获,错误值绑定到变量 e,其作用域限于 catch 块。Alia 不含 finally 子句。

throw 语句​

throw <Value error>

throw 为内置别名,抛出 ThrownError 信号,实参可为任意值;经 catch 捕获时原样绑定。无 try 包裹时抛出会终止程序。

2. 基本用法​

抛出错误​

throw new Error ['发生错误']
throw new Error ['发生错误', 'CustomError']

捕获错误​

try {
print '尝试执行'
throw new Error ['发生错误']
print '这行不会执行'
} catch e {
print '捕获到错误: ' .. e
}

3. 错误类型​

Error 是内置错误类,构造形式为 new Error ['message', 'name', 'cause'],实参按位置传入:

  • message:错误描述,默认 ''
  • name:错误名称,默认 'Error'
  • cause:原始原因,默认 Null
  • stack:堆栈信息,取自 cause,无 cause 时为 Null

实例方法:

  • toString / valueOf:字符串表示 / 消息内容
  • toDescription / toColoredDescription:描述文本 / 染色描述
  • toCode / toColoredCode:代码表示 / 染色代码表示
const error = new Error ['错误信息', 'CustomError']
print typeOf error ~ 输出 'Error'
print error.message ~ 输出 '错误信息'
print error.name ~ 输出 'CustomError'

typeOf 对 Error 实例返回 'Error';区分自定义错误应使用 error.name。

4. 示例代码​

4.1 基本错误处理​

~ 基本错误处理
try {
print '开始执行'
const result = 10 / 0
print '结果: ' .. result
} catch e {
print '捕获到错误: ' .. e
}
print '继续执行'

4.2 自定义错误​

~ 自定义错误:以 name 区分错误种类
try {
print '开始执行'
throw new Error ['自定义错误', 'CustomError']
} catch e {
print '错误信息: ' .. e.message
print '错误名称: ' .. e.name
}

4.3 嵌套错误处理​

~ 嵌套错误处理
try {
print '外层 try 开始'
try {
print '内层 try 开始'
throw new Error ['内层错误']
} catch innerError {
print '捕获内层错误: ' .. innerError
throw new Error ['外层错误']
}
} catch outerError {
print '捕获外层错误: ' .. outerError
}

4.4 错误处理与函数​

~ 错误处理与函数
alias divide <Number a> <Number b> -> Number {
if b == 0 {
throw new Error ['除数不能为零', 'DivisionByZero']
}
return a / b
}

try {
const result = call divide [10, 0]
print '结果: ' .. result
} catch e {
print '错误: ' .. e
}

try {
const result = call divide [10, 2]
print '结果: ' .. result
} catch e {
print '错误: ' .. e
}

5. 错误处理最佳实践​

5.1 使用 name 区分错误种类​

alias validateUser <Object user> -> Boolean {
if user.name == '' {
throw new Error ['用户名不能为空', 'ValidationError']
}
if user.email == '' {
throw new Error ['邮箱不能为空', 'ValidationError']
}
return true
}

try {
const user = *[ name: '', email: 'user@example.com' ]
validateUser user
} catch e {
if e.name == 'ValidationError' {
print '验证错误: ' .. e.message
} else {
print '未知错误: ' .. e
}
}

5.2 错误传播​

在函数中捕获错误并重新抛出,添加更多上下文信息:

alias readFile <String path> -> {
try {
~ 尝试读取文件
throw new Error ['文件不存在', 'FileError']
} catch e {
throw new Error ['读取文件失败: ' .. e.message .. ' (路径: ' .. path .. ')', 'ReadError']
}
}

try {
readFile 'nonexistent.txt'
} catch e {
print '错误: ' .. e.message
}

5.3 错误恢复​

在捕获错误后进行恢复,继续执行:

alias getUser <Number id> -> Object {
try {
~ 尝试从数据库获取用户
throw new Error ['用户不存在', 'NotFound']
} catch e {
~ 返回默认用户
return *[ id: id, name: '未知用户' ]
}
}

const user = getUser 999
print '用户: ' .. user.name

6. 与其他语言的比较​

与 JavaScript 比较​

// JavaScript
try {
throw new Error('错误信息');
} catch e {
console.log('捕获到错误:', e.message);
}
~ Alia
try {
throw new Error ['错误信息']
} catch e {
print '捕获到错误: ' .. e
}

与 Python 比较​

# Python
try:
raise Exception('错误信息')
except Exception as e:
print('捕获到错误:', str(e))
~ Alia
try {
throw new Error ['错误信息']
} catch e {
print '捕获到错误: ' .. e
}

7. 错误诊断系统​

Alia 实现了结构化的错误诊断系统,为解析、类型检查、运行与编译阶段提供统一的诊断输出。

7.1 诊断输出格式​

每条诊断以圆角矩形框输出(非 TTY 时为纯文本行),包含以下字段:

  1. 类型:Error / Warn,框体颜色分别为红色 / 黄色。
  2. 标题:顶部框线显示 Error: <错因> / Warn: <错因>。
  3. 直接位置:At <文件相对位置> line:column:(标签随语言环境显示)。
  4. 错误代码:带背景与行号的代码行,错误位置下方标记波浪线。
  5. 错误类型:Type: <大类>:<具体代码>,如 Type: TypeError:Mismatch。
  6. 错误原因:Reason: 对应原因描述。
  7. 修复方法:Fix: 修复建议描述。
  8. 修复后代码:与错误代码格式相同,用绿色标记添加位置。
  9. 引用链:From: 上一次调用位置(如有)。

7.2 错误类型代码​

错误类型代码由 <大类>:<具体代码> 组成,大类包括:

  • ParseError:解析错误
  • TypeError:类型错误
  • RuntimeError:运行时错误
  • CompilerError:编译错误
  • FFIError:FFI 错误

下一步​