返回

文章详情

迷你Kotlin

Hacker News2026年7月17日 12:50

Kotlin → WebAssembly · 用C语言编写的编译器 一个在浏览器标签中运行的Kotlin编译器。minikotlin是从头开始用C编写的,以手动方式发出WebAssembly GC字节码——没有JVM,没有LLVM,没有Binaryen,没有Gradle。编译器本身也是编译为WASM,因此.kt源文件输入后会输出一个运行的.wasm模块,完全在标签中。后端WASM-GC结构 · call_ref · EH服务器没有在客户端运行的端到端测试 366 前端:657 运行时依赖 0 没有安装 greeter — minikotlin Studio // Main.kt + Greeter.kt 作为一个单元编译 fun main () { val g = Greeter ( "WebAssembly" ) println (g.greet()) ( 1 .. 3 ). forEach { println ( "tick $ it " ) } } build 2 .kt → main.wasm · ok, 41ms Hello, WebAssembly tick 1 tick 2 tick 3 流水线 .kt → lex → parse → sema → HIR → MIR → WASM-GC → run 01 一次传递,所有步骤到字节码。没有中间VM,没有外部后端。前端 — 词法分析器,解析器,语义分析(称为mkf) — 在手动编写WASM-GC之前,交给两个自己的IR。输入Kotlin源文件 多个.kt文件,作为一个单元编译以便彼此可见。前端 · mkf lex · parse · sema 名称、类型和智能转换已解析。657前端测试。高IR HIR 一个去糖化的、带类型的树,仍然接近语言。中IR MIR 降级为操作、本地变量、结构布局和虚表。代码生成 WASM-GC 字节码直接发出。没有LLVM,没有Binaryen参与。输出 main.wasm 在同一浏览器标签中实例化和运行。编译器本身作为WASM交付,因此它在您的代码运行的地方运行 — 无需安装工具链。02 现在使用的Kotlin。不是一个令牌子集。这些都正确地降级到WASM-GC类型系统 — 每一个都在后面有端到端测试。类和对象对象模型 继承(open / override),带默认方法的接口,生成 equals / hashCode / copy 的数据类,枚举,以及命名、伴生和匿名对象表达式。密封和智能转换 控制流 密封层次结构与详尽的 when,is 检查编译为 ref.test,以及在分支之间保持的流感知智能转换。空安全类型 可空类型端到端 — ?. 安全调用,?: elvis 和 !! 断言 — 包括可空原始类型,通过 Any 进行装箱。泛型类型 函数和类上的类型参数 — fun <T> id(x: T): T — 降级到装箱的 Any 表示。运算符和扩展设计 运算符重载(加,获取等)派发到LHS类,自定义访问器及其背字段,扩展函数在自己的命名空间中。协程 非阻塞启动,延迟和 coroutineScope — 实际暂停编译为CPS闭包,没有Asyncify,没有JSPI和没有线程。标准库 手写的字符串/字符操作,高阶函数(映射/过滤/遍历等),kotlin.math,以及作用域函数 let / apply / run / also / with。03 Kotlin思想如何变为WASM指令。降级是任何编译器的有趣部分。四个真实的 — 每一个都将语言构造映射到具体的WASM-GC机制,由手动编写。L.01 类实例 → struct.new 每个类都变为GC结构类型;属性是真实的结构字段。分配是struct.new,而不是手动构造的字节堆。L.02 虚拟调用 → call_ref 打开和覆盖的方法通过每个类的虚表。虚拟调用是函数引用加载后跟call_ref — 真实的动态调度。L.03 类型检查 → ref.test 一个is检查和一个when (x) { is T -> } arm编译为ref.test,缩小的值通过ref.cast重用 — 免费的智能转换。L.04 协程 → CPS闭包 一个暂停点在缝隙处分割函数并捕获其余部分作为继续。一个简单的延迟将令牌交给主机并从setTimeout恢复 — 真正退出栈。04 一个实例,已编译并运行。以下所有内容均支持Kotlin。Studio用编译器自己的词法分析器突出显示它,然后就地运行结果WASM。Race.kt import kotlinx.coroutines.* 密封类 Lane ( val id: Int ) 类 Fast : Lane ( 1 ) 类 Slow : Lane ( 2 ) fun Lane . pace (): Long = when ( this ) { is Fast -> 120 is Slow -> 300 } fun main () = runBlocking { val lanes = listOf ( Fast (), Slow ()) coroutineScope { lanes. forEach { lane -> launch { delay (lane. pace ()) println ( "lane $ {lane.id} in" ) } } } println ( "race over" ) } 两个协程,实际上在竞赛中。每次启动都在其延迟处暂停并让出。速度较快的车道首先恢复;coroutineScope在最后一行运行之前等待两个子协程。没有阻塞和没有Asyncify — 暂停被编译为继续闭包。密封的 Lane,when (this) { is … } 调度和 Lane.pace() 扩展都被真正降级,而不是被解释。> lane 1 in > lane 2 in > race over

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

请我喝杯咖啡