今天你 Emo 了没?
向下滚动,认识 Emo
Emo
语法简洁·显式定义·符合直觉
一门国产系统级编程语言。从原生可执行文件到 WebAssembly, 从 BEAM 虚拟机到裸机内核 —— 一门语言,贯通整个系统栈。
当前版本:v0.26.1024-alpha 2026 (冬至) 「立冬,十月节。冬,终也,万物收藏也。」
// 这是一行注释
class User {
def init(age Int64) {
self.age = age
}
def adult?() Bool {
return self.age >= 18
}
}
const fuxi = User.new(age: 128)
emo Company {
def can_hire?(u User) Bool {
return u.adult?()
}
}
const can_hire = Company.can_hire?(fuxi)
var result = if can_hire { "能啊" } else { "肯定不行" }
println("这人能要吗?${result}")编译目标
一门语言,五个目标
同一份 Emo 代码,可以编译到系统栈的每一层 —— 写应用、写服务、写前端,一直写到操作系统内核。
核心特色
为清晰而生
Emo 汲取三十年开源编程语言的经验与教训,围绕三条原则设计:表达力强的语法、最少惊讶原则、多编译目标。
◆明确的语法
调用一定带括号,return 一定写出来,代码块只有一种形状。一切所见即所得,解析器与读者都不必猜测。
◆渐进式类型
运行时动态类型,编译期静态检查。函数签名必写类型,其余交给推断;类型信息还会反哺原生代码的性能。
◆默认不可变
const / var 分层明确,类实例是值类型;长期可变状态只住在 Box 里,且永远不跨越进程边界。
◆Actor 并发
do 起进程,<- 发消息,receive 收信箱。崩溃隔离与监管内建,无共享内存原语。
◆直接风格网络
没有 async/await,没有函数染色。任何函数都能做 IO,调度器在 io_uring / kqueue / IOCP 之上切换进程。
◆结构化模块
目录树即模块树:没有 import / export,路径即引用,internal/ 的可见性由编译器强制。
◆自带包管理
require 引入依赖,精确版本 + MVS 解析,构建即安装;中心注册表支持私有部署。
◆配置即代码
Emo 就是自己的配置语言:受限 Profile 保证终止、密封、无副作用,不再需要第二种 Schema 语言。
◆C 互操作
foreign def 一行声明即可链接 C 库;OCaml 5 实现,一流的 C FFI 直通原生后端。
并发
进程与消息传递,Actor 模型的嫡系
Emo 的并发围绕进程与消息传递构建,直接映射 BEAM 进程; 原生后端则以 OCaml 5 effects 实现调度器 —— 与 Eio 同源的地基。
- 消息传递是唯一核心原语,共享内存不在语义之内
- 尾调用有保证,递归就是收信循环的惯用形态
- 未处理的错误只杀死出错的进程,监管策略交给库
// 三个进程, 一条消息链
def doubler(next Pid) Int64 {
receive {
(i, n) -> {
next <- (i, n * 2)
return doubler(next)
}
"done" -> {
next <- "done"
return halt()
}
}
}
def labeler(count Int64, boss Pid) Int64 {
receive {
(i, n) -> {
println("订单 ${i}: ${n} 件")
return labeler(count + 1, boss)
}
"done" -> {
boss <- (self_pid(), count)
return halt()
}
}
}
def feed(line Pid, i Int64) Int64 {
if i > 3 {
line <- "done"
return 0
}
line <- (i, i)
return feed(line, i + 1)
}
const lab = do labeler(0, self_pid())
const line = do doubler(lab)
feed(line, 1)
receive {
(who, handled) -> { println("处理了 ${handled} 个订单") }
}// 接口属于调用方: 形状匹配即满足, 无需 implements
interface Greeter {
def greet() String
}
class Machine {
def greet() String {
return "[beep] 你好"
}
}
class Friend {
def greet() String {
return "很高兴见到你"
}
}
def welcome(g Greeter) String {
if g.is(Machine) {
return "一台机器说: ${g.greet()}"
}
return "一位朋友说: ${g.greet()}"
}
println(welcome(Machine.new()))
println(welcome(Friend.new()))抽象
结构化接口,零成本多态
interface 声明一组方法签名,任何形状匹配的类都自动满足 —— 不需要 implements。接口属于调用方,实现方甚至不必知道接口存在。
- 编译期校验形状,运行时鸭子分派,零开销
- 没有继承 —— 复用靠组合、鸭子类型与接口
g.is(Machine)为真后,g自动收窄类型
EmoUI 规划中
UI 就是普通的 Emo 代码
EmoUI 是用 Emo 写的组件式 UI 框架:没有模板语言, 组件树就是带代码块的嵌套调用。Emo 的语法正是为它塑形。
- 组件即函数,Props 由内置类型检查器把关
- UI 事件即进程消息 —— 天然长成 Elm 架构
- 响应式原语显式可预测,编译器把可静态确定的更新编译成定向刷新
// 没有模板语言 —— UI 就是普通的 Emo 代码
page(title: "首页") {
navbar() {
logo()
menu(routes)
}
list(users) -> (user User) {
card(user) {
text(user.name)
text(user.bio)
}
}
}// kernel_main.emo — RISC-V 目标: 无 OS, 无 libc
//
// emo build kernel_main.emo --target riscv64 -o kernel.img
// qemu-system-riscv64 -kernel kernel.img
def kernel_main() {
uart.write_line("hello from EmoOS")
// 显式内存原语: 危险的操作, 看起来就危险
const status = peek(uart_status_addr)
poke(uart_data_addr, status)
}EmoOS 规划中
一门能写内核的语言
Emo 的边界一直延伸到操作系统层:RISC-V 编译目标面向裸机, 无 OS、无 libc、无默认运行时,直接产出 QEMU 可引导镜像。
- 分层核心库:内核代码只用零依赖的
core - 内存原语显式命名 —— 危险的操作看起来就危险
- GC、分配器、调度器可替换;内核编译到 RISC-V,Shell 与应用留在原生目标 —— 一门语言贯通系统两侧