跳到主要内容

weekly 2024-05-27

· 阅读需 3 分钟

MoonBit 周报 Vol.42:核心库进行API整理工作、工具链持续完善

MoonBit更新

  • 【核心库 Breaking】核心库进行API整理工作
    • 所有immutable数据结构被放在immut路径下,如@immutable_hashmap.Map变为@immut/hashmap.Map
// Before
let a : @immutable_hashmap.Map[Int, Int] = @immutable_hashmap.make()
// After
let a : @immut/hashmap.Map[Int, Int] = @immut/hashmap.make()
  • 核心库中 Option[T] 类型性能优化
    • 在类型 T 是一个引用类型情况下,对于 Option[T] 类型的值,Some(v) 会被直接编译成 vNone 会在 wasm-gc 后端被编译成 ref.null ,在 JavaScript 后端被编译成 undefined,从而避免内存分配
  • 核心库中引入了 fn panic[T]() -> T 函数,这个函数可以用于在测试块中,其中测试的名字需要以 "panic" 开头:
test "panic test ok" {
panic() // 测试通过
}

test "panic test failed" {
() // 测试失败
}

IDE更新

  • 【VS Code插件】增加了testfor的代码片段 test片段 test.gif for片段 for.gif

构建系统更新

  • 【初始化】moon new 会自动对创建的项目进行版本控制初始化,目前支持 git
  • 【测试】现在可以指定对多个包进行测试
moon test -p a b c
moon test -p a -p b -p c

工具链更新

  • 【安装】现在可以指定版本号进行安装
# Mac与Linux用户
# 下载最新版
curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash
# 下载 bleeding 版本
curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash -s bleeding
# 下载特定版本
curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash -s 0.1.20240520+b1f30d5e1
# Windows用户
# 下载最新版
irm cli.moonbitlang.cn/install/powershell.ps1 | iex
# 下载特定版本
$env:MOONBIT_INSTALL_VERSION = "0.1.20240520+b1f30d5e1"; irm cli.moonbitlang.cn/install/powershell.ps1 | iex

weekly 2024-05-20

· 阅读需 3 分钟

MoonBit更新

  • 【Breaking Change】Array重命名为FixedArray@vec.Vec重命名为Array
// Before
fn init {
let array : @vec.Vec[Int] = [1, 2, 3]
}
// After
fn main {
let array : Array[Int] = [1, 2, 3]
}
  • 【语法】键值对(如Map HashMap等)增加模式匹配支持
    • 类型需实现op_get方法,其键为原生类型(Int Char String Bool等),值为Option[T]
    • 匹配时,键需为字面量
    • { "key": pat } 中,模式 pat 类型是 Option[T]None表示 "key"不存在,Some(p)表示 "key"存在,且 p 会被用于匹配这个键的值
    • 匹配键值对的模式都是开放的:未被匹配的键即使存在也会被忽略掉
    • 键值对模式会生成优化过的代码,每个键至多被查询一次
fn main {
let map = @map.Map::[ ("a", 1) ]
match map {
// 当 `map` 包含 "b" 时匹配,
// 并把 "b" 在 `map` 中的值绑定到 `y`
{ "b": Some(y) } => println(y)
// 当 `map` 不包含 "b" 而包含 "a" 时匹配,
// 并把 "a" 的值绑定到 `k`
{ "b": None, "a": Some(k) } => println(k)
// 编译器提示 { "b": None, "a": None } 的情况未被匹配到
}
// 输出:1
}
  • 【语法】允许在已知类型信息的情况下省略newtype构造器
type A Int

pub fn op_add(self : A, other : A) -> A {
self.0 + other.0 // 省略构造器
}

fn main {
A::A(0) + 1 |> ignore // 省略 1 的构造器
let _c : A = 0 + 1 + 2
}

构建系统更新

  • 配置文件选项统一为kebab-case(近期仍对snake_case保持兼容)
{
"is-main": true,
"test-import": []
}
  • 【Wasm,Wasm-GC】后端支持在moon.pkg.json中指定导出内存名称(默认为moonbit.memory)与编译选项(如-no-block-params以兼容binaryen工具链)
{ 
"link": {
"wasm": {
"export-memory-name": "custom_memory_name",
"flags": ["-no-block-params"]
},
}
  • moon check 增加 --deny-warn 选项,在有 warning 时视为失败,返回非0值
  • moon fmt 增加 --check选项,用于检查当前代码是否已被格式化

标准库更新

  • 增加实验性库moonbitlang/x,用于开发与测试API不稳定的包。moonbitlang/x中的包稳定后,我们会根据社区的意见,选取重要的包合入moonbitlang/core
    • num time uuid json5 均已移动至moonbitlang/x
  • Bytes API 变更,从Int迁移到了Byte类型:
fn Bytes::op_get(self : Bytes, index : Int) -> Byte
fn Bytes::op_set(self : Bytes, index : Int, value : Byte) -> Unit
fn Bytes::length(self : Bytes) -> Int
fn Bytes::make(len : Int, ~init : Byte = b'\x00') -> Bytes

weekly 2024-05-13

· 阅读需 4 分钟

MoonBit更新

  • 支持了构造器的 payload 中出现 mutable field,使用方式如下:
enum E {
C(mut ~x : Int, mut ~y : Int)
} derive(Debug)


fn swap_xy(x : E) -> Unit {
match x {
// `~y` 会绑定模式匹配前 `C` 中的 `y` 字段的值
// 当看到 `C(..) as c` 这种模式时,编译器知道 `c` 一定是构造器 `C`,
// 所以可以在分支内部用 `c.x`、`c.y` 直接访问 `C` 的字段
C(~y, ..) as c => {
// `c.x` 和 `c.y` 可以用于修改/读取 `C` 中最新的值
c.y = c.x
c.x = y
}
}
}

fn init {
let e : E = C(x=1, y=2)
debug(e) // C(x=1, y=2)
swap_xy(e)
debug(e) // C(x=2, y=1)
}

这个例子中的 swap_xy 函数对构造器 Cxy 两个 field 的值进行了交换,并且这个交换是 in-place 的,没有引入额外的内存分配

  • **数组字面量默认构建 vector。**对 Array literal 语法进行了重载,现在 Array literal 可以用来构造 Vector 或者 Array,具体的类型通过上下文决定,当上下文中类型信息不明确时,默认使用 Vector,比如
fn init {
let v = [1, 2, 3] // v has type @vec.Vec[Int]
let a : Array[_] = [1, 2, 3] // a has type Array[Int]
}
  • 报错信息中添加了错误代码,例如
./vec/sort.mbt:68:16-68:23 [E4021] The value identifier minimum is unbound.
./vec/sort_by.mbt:90:16-90:23 [E4021] The value identifier minimum is unbound.
./vec/vec.mbt:962:37-962:50 [E4020] Package "iter" not found in the loaded packages.
./vec/vec.mbt:963:3-963:13 [E4024] The type/trait @iter.Iter is not found.

IDE更新

  • 对构造器中的 labeled field 的 label 支持了 gotodef/gotoref/rename 等功能,例如 label.PNG

构建系统更新

  • 支持在 package 级别配置 warn list 与alert list
    • moon.pkg.json 中如下配置,可在编译时关闭对应的 warn 与 alter【其中 2alter_1alert_2 分别为编译器预设的 warn id (对于 Unused variable) 与用户自定义的 alert id】
{
"warn_list": "-2",
"alert_list": "-alert_1-alert_2"
}
  • -代表关闭对应 id 的 warn 与 alter,可用 moonc build-package -warn-help 查看预设的 warn

  • moon check|build|run|test 的默认后端由wasm切换为wasm-gc

  • moon test 默认执行模式由 release 修改为 debug

  • moon check|build|run|test支持自动安装依赖,而无需手动执行 moon install

  • moon doc --serve 支持指定地址与端口

-b, --bind <BIND> [default: 127.0.0.1]
-p, --port <PORT> [default: 3000]
  • 优化 moon 体积
平台优化前优化后
macOS arm647.3 MiB3.6 MiB
macOS x86_648.2 MiB4.1 MiB
Ubuntu x86_6414.0 MiB9.6 MiB
Windows x86_649.4 MiB4.9 MiB

工具链更新

  • moonrun 支持打印 backtrace, 使用样例: 使用 moon new hello 创建一个新项目,将 main/main.mbt 的内容替换为:
  fn bar() -> Unit {
abort("")
}

fn foo() -> Unit {
bar()
}

fn main {
foo()
}

执行 moon run main --debug,可观察到输出类似:

error: RuntimeError: unreachable
at $username/hello/main.bar.fn/1 (wasm://wasm/6fe99e5e:wasm-function[3]:0xe6)
at $username/hello/main.foo.fn/2 (wasm://wasm/6fe99e5e:wasm-function[4]:0xea)
at *init*/3 (wasm://wasm/6fe99e5e:wasm-function[5]:0xef)
at <anonymous>:9:22

weekly 2024-04-30

· 阅读需 6 分钟

MoonBit 更新

  • 新增JavaScript后端

目前MoonBit已新增对JavaScript的支持并带来前所未有的性能提升,在JS后端实现了超出Json5近8倍性能的优势。更详细的介绍可以看一下这篇文章:IDEA研究院编程语言MoonBit发布JavaScript后端,速度提升25倍

如果你想自己体验一下,可以点击:https://github.com/moonbit-community/benchmark-202404/tree/master/bench_json5

  • 现在MoonBit允许传递回调函数至FFI。但回调函数的参数和返回值类型目前只能是简单类型,如Int等。例子:

    // 使用示例:传递回调函数至外部
    fn set_callback(f : () -> Int) = "ffi" "set_callback"

    // 使用示例
    fn use_callback() -> Int = "ffi" "use_callback"

    test {
    let i = { val : 0 }
    set_callback(fn () {
    i.val += 1
    i.val
    })
    inspect(use_callback(), content="1")?
    inspect(use_callback(), content="2")?
    inspect(use_callback(), content="3")?
    inspect(use_callback(), content="4")?
    }

    let f

    export default {
    // 必要外部接口:将闭包转换为JS函数。其他运行时根据语言不同实现方式不同
    'moonbit:ffi': {
    make_closure: (funcref, context) => funcref.bind(null, context)
    },
    // 使用示例
    ffi: {
    set_callback: (func) => {
    f = func
    }, // 设置回调函数
    use_callback: () => f() // 使用回调函数
    }
    }
  • 修改显式实现 trait(extension method)的语法,允许显式写出要给哪个类型实现 trait

    // 为 `Trait` 的方法 `method` 提供默认实现
    impl Trait with method(...) { ... }

    // 给类型 `Type` 实现 `Trait` 的方法 `method`
    impl Trait for Type with method(...) { ... }

    // 带类型参数的情况
    impl[X] Trait for Array[X] with method(...) { ... }

    和之前的 fn Trait::method(...) 语法相比,新的语法允许显式写出实现 trait 的类型,签名信息更丰富、更清晰。由于写出了类型,编译器可以自动推断出方法的参数和返回值类型,不需要手动标注:

    trait MyTrait {
    f(Self) -> Option[Int]
    }

    // 无需标注 `self` 和返回值的类型
    impl MyTrait for Int with f(self) {
    // 编译器能自动推断出返回值的类型是 `Option[Int]`
    Some(self)
    }

  • 支持Bytes字面量

    Bytes字面量b"..." 会将双引号内的ASCII字符串转换为Bytes类型,字符串内支持十六进制和八进制转义。

     let b1 : Bytes = b"ASCII"
    let b2 : Bytes = b"\xFF\o000"

  • { x } 的二义性问题修复

现在{ x }会解析成只有一个x字段的struct,相当于{ x: x }。对于这种容易造成混淆的写法,编译器会发出警告。

IDE更新

  • 插件新增moonbit.autoUpdate的选项控制是否开启自动更新的提示
  • 插件支持多后端开发
    • 用户可以在vscode里选择不同的后端
    • 非当前后端的代码对比度会变低

plugins.gif

构建系统更新

  • 支持后端特定文件,这些文件的拓展名以 .wasm|wasm-gc|js.mbt结尾,例如:foo.wasm.mbtfoo.wasm-gc.mbtfoo.js.mbt。例如在 moon build --target js 中,只有普通的 .mbt 文件与 .js.mbt 才会参与构建。相应地,moon check|build|test、以及moonbitlang/core的链接修改为与后端相关。

  • moon.pkg.json 中的 ["link"]["js"]中新增 format 字段,用于指定输出的JavaScript模块格式,可能的值为 esm|cjs|iife,默认为 esm

    • esm模式下,使用export { x as y }语句导出
    • cjs模式下,使用exports.y = x导出
    • iife模式下,使用globalThis.y = x导出

    moon.pkg.json样例:

    {
"link": {
"js": {
"exports": [
"hello"
],
"format": "cjs"
}
}
}

  • moon test -u支持自动更新测试块中的多个inspect函数,以及添加 -limit 选项用于限制自动更新的最大迭代次数。

工具链更新

  • moonrun由wasmtime切换到v8,现在支持wasm-gc后端
    moon new hello
cd hello
moon run main --target wasm-gc
  • moon info 的更新
    • 支持对方法进行分组,方便对比不同数据结构的实现
    • 支持带标签的参数、默认参数和自动填充参数
type Map
impl Map {
debug_write[K : Debug, V : Debug](Self[K, V], Buffer) -> Unit
elems[K, V](Self[K, V]) -> List[V]
fold[K, V, T](Self[K, V], (T, V) -> T, ~init : T) -> T
from_array[K : Compare + Eq, V](Array[Tuple[K, V]]) -> Self[K, V]
// ...
}

weekly 2024-04-22

· 阅读需 5 分钟

MoonBit更新

  • 标准库里添加了 Iter 类型,该类型可以高效地对容器中的元素的进行访问,并且将访问过程优化成循环,使用方式比如:
test "iter" {
let sum = Iter::[1, 2, 3, 4, 5, 6]
.filter(fn { x => x % 2 == 1 })
.take(2)
.map(fn { x => x * x})
.reduce(fn (x, y) { x + y }, 0)
inspect(sum, content="10")?
}
  • 标准库里添加了VecView类型,可以使用如下方式对 Vec[T] 类型的值取它的 VecView[T]
test "view" {
let v = Vec::[1, 2, 3, 4, 5]
let vv1 = v[..]
let vv2 = v[1..]
let vv3 = v[..4]
let vv4 = v[1..4]
inspect(vv1, content="VecView::[1, 2, 3, 4, 5]")?
inspect(vv2, content="VecView::[2, 3, 4, 5]")?
inspect(vv3, content="VecView::[1, 2, 3, 4]")?
inspect(vv4, content="VecView::[2, 3, 4]")?
}
  • array pattern支持 [a, .. as rest, b]形式,其中 rest 会绑定到一个VecView,例如:
test "view_pattern" {
fn is_palindrome(s: VecView[Int]) -> Bool {
match s {
[] => true
[_] => true
[x, .. as rest, y] => x == y && is_palindrome(rest)
}
}
let v1 = Vec::[1, 2, 3, 4, 5]
@assertion.assert_false(is_palindrome(v1[..]))?
let v2 = Vec::[1, 2, 3, 2, 1]
@assertion.assert_true(is_palindrome(v2[..]))?
}
  • 标签参数调用时允许省略标签里的波浪线 ~,例如:
inspect(1, content="1")
  • 构造器支持带标签的参数:
pub enum Tree[X] {
Nil
Branch(X, ~left : Tree[X], ~right : Tree[X])
}

pub fn leftmost[X](self : Tree[X]) -> Option[X] {
loop self {
Nil => None
// 使用 `label=pattern` 来匹配构造器的带标签参数
Branch(top, left=Nil, right=Nil) => Some(top)
// `label=label` 可以简写成 `~label`
Branch(_, left=Nil, ~right) => continue right
// 可以用 `..` 来忽略所有剩余的带标签参数
Branch(_, ~left, ..) => continue left
}
}

fn init {
// 创建带标签的构造器的语法和调用带标签的函数一样
let t: Tree[Int] = Branch(0, right=Nil, left=Branch(1, left=Nil, right=Nil))
println(t.leftmost()) // `Some(1)`
}
  • 可选参数的默认值可以依赖前面的参数,例如:
fn f(~x: Int = 1, ~y: Int = x) -> Int {
x + y
}
  • Byte字面量支持八进制转义。

Byte.PNG

IDE更新

  • IDE 支持本地环境的 test codelens;支持expect test的自动更新。

test-codelens.GIF

  • 修复在线 IDE 在 Windows 上找不到 core 的问题。

  • 支持识别 test_import*_test.mbt 文件。

工具链更新

  • moonfmt

    • 修复了StringChar字面量中的转义序列没有被正确格式化的问题;
    • 调整针对{ ..record }的格式化。
  • moon infomoon coverage 现已支持 Windows。

  • moon info 支持在不引起歧义时缩短类型名称,使得生成结果更加干净:

    • 在没有同名类型定义的时候隐藏 builtin 的包名前缀;
    • 在没有歧义时使用包名的最后一部分代替完整的包名。 更新前:
package moonbitlang/core/map

// -- snip --

type Map
fn Map::debug_write[K : @moonbitlang/core/builtin.Debug, V : @moonbitlang/core/builtin.Debug](Map[K, V], @moonbitlang/core/builtin.Buffer) -> Unit
fn Map::keys_set[K : @moonbitlang/core/builtin.Compare + @moonbitlang/core/builtin.Eq, V](Map[K, V]) -> @moonbitlang/core/immutable_set.ImmutableSet[K]
fn Map::lookup[K : @moonbitlang/core/builtin.Compare + @moonbitlang/core/builtin.Eq, V](Map[K, V], K) -> Option[V]
fn Map::to_vec[K, V](Map[K, V]) -> @moonbitlang/core/vec.Vec[Tuple[K, V]]

更新后:

package moonbitlang/core/map

alias @moonbitlang/core/immutable_set as @immutable_set
alias @moonbitlang/core/vec as @vec

// -- snip --

type Map
fn Map::debug_write[K : Debug, V : Debug](Map[K, V], Buffer) -> Unit
fn Map::keys_set[K : Compare + Eq, V](Map[K, V]) -> @immutable_set.ImmutableSet[K]
fn Map::lookup[K : Compare + Eq, V](Map[K, V], K) -> Option[V]
fn Map::to_vec[K, V](Map[K, V]) -> @vec.Vec[Tuple[K, V]]

构建系统更新

  • moon test 添加测试过滤相关选项:
-p, --package <PACKAGE_NAME>  Run test in the specified package
-f, --file <FILE> Run test in the specified file, only valid when --package is specified
-i, --index <INDEX> Run the index-nth test in the specified file, only valid when --file is specified

命令示例:moon test -p username/hello/A -f hello.mbt -i 0 (运行 username/hello/A 包中 hello.mbt 文件中的第 0 个 test block);-f-i 分别在指定 -p-f 时才有效;如果不指定 -f 则运行 -p 指定包中所有测试,不指定 -i 则运行 -f 指定文件中所有测试。

  • moon check|build|test 添加 --sort-input 选项,用于生成稳定的构建顺序。

  • expect test 生成的 ~content= 省略 ~,变更为 content=

weekly 2024-04-15

· 阅读需 2 分钟

MoonBit is a Rust-like language (with GC support) and toolchain optimized for WebAssembly experience. This is our recent update:

Core Update

We have received 221 Repositories to MoonBit core since its open source in March, with 26 excellent contributors contributing about 10,000 lines of code of high quality. Thanks a lot for your passion and support for MoonBit!

0.PNG

Language Update

  • Expanded array patterns in pattern matching.

    • Support the vec type in the standard library.
    • Support for generic types [a, .., b].
    fn main {
    let xs = @vec.from_array([1, 2, 3])
    match xs {
    [1, .., 3] => { println("ok")}
    _ => println("not ok")
    }
    // Output: ok
    }

IDE Update

  • Changed the printing output of the online IDE from the Output channel to the terminal. Fixed the issue where the printing output was occasionally truncated in Firefox browsers. ANSI escape sequences can be used in browser code, for example:

1.PNG

  • Support autocompletion in the form of x |> @pkg.

1.5.PNG

  • Disabled inlay hint for matrix functions.

Before

2.PNG

After

3.PNG

Toolchain Update

  • Added (experimental) test coverage tools. (*Windows is not supported at the moment)

    • Added -enable-coverage option to moon test for enabling coverage during runtime.
    • Added moon coverage command for reading and processing coverage data.
      • After testing, moon coverage report -f <format> can be used to output coverage data. Supported output formats include:
        • bisect (default output format of OCaml Bisect tool)
        • html (output result webpage)
        • coveralls (JSON format suitable for CodeCov and Coveralls tool upload)
        • summary (output summary in the terminal) More functionalities can be viewed through moon coverage report -h.
      • moon coverage clean command can be used to clean up previous coverage data output.
  • The build system has added the moon info command for generating public interface files of software packages. (*Windows is not supported at the moment) Example:

    $ moon new hello
    $ cd hello
    $ moon info
    $ cat lib/lib.mbti
    package username/hello/lib

    // Values
    fn hello() -> String

    // Types and methods

    // Traits

    // Extension Methods
    ```

  • Fixed the issue where the annotation was misaligned caused by trailing commas in moonfmt.

  • Fixed the issue where file paths cannot contain spaces in moon.

weekly 2024-04-08

· 阅读需 2 分钟

MoonBit更新

  • 支持 array.iter intrinsic 并且已经对标准库中的函数进行标注,从而可以在特定情况下将循环进行内联,以提升运行效率

    /// @intrinsic %array.iter
    pub fn iter[T](self : Array[T], f : (T) -> Unit) -> Unit {
    for i = 0; i < self.length(); i = i + 1 {
    f(self[i])
    }
    }

工具链更新

  • 支持实验性的测试覆盖率统计工具
    • 工具已经实验性支持 MoonBit Core CI
    • 我们正在优化面向用户的接口

image

image

  • 默认关闭Alerts pragmas 中 unsafe/throw/raise 类别的警告,启用了 deprecated alert。
  • moonfmt
    • 修复带负号的字面量打印后注释错位的问题
    • 修复带负号字面量打印后括号消失的问题
  • 修复变量高亮
  • moonrun 支持 UTF-16 字符串的打印

构建系统更新

  • expect test 支持处理 Unicode 字符

image

weekly 2024-04-01

· 阅读需 5 分钟

MoonBit 更新

1. expect 测试添加 inspect 函数

expect 测试添加针对 Show 接口的 inspect 函数,签名如下:

pub fn inspect(
obj: Show,
~content: String = "",
~loc: SourceLoc = _,
~args_loc: ArgsLoc = _
) -> Result[Unit, String]

⚠️ 此API暂不稳定,在未来可能会更改为 expect 函数

使用 inspect 可以更方便编写测试,例如对于如下代码:

fn add(x: Int, y: Int) -> Int {
x + y
}

test {
inspect(add(1, 2))?
}

test {
(add(3, 4) |> inspect)?
}

执行 moon test -u 之后,文件被自动更新为:

fn add(x: Int, y: Int) -> Int {
x + y
}

test {
inspect(add(1, 2), ~content="3")?
}

test {
(add(3, 4) |> inspect(~content="7"))?
}

2.编译器内置函数迁移到标准库

把原本的在编译器内部的一些基础的 MoonBit 定义迁移到了标准库中。在线IDE上也可以使用标准库了

3. 支持 alert pragam

MoonBit 现在支持在顶层的文档注释中书写多个 pragam。所有的 pragam 以@开头,并且独占一行。

Untitled

目前支持函数和方法的 alert pragma,当被标记了 alert 的函数和方法被使用时会产生警告。这个机制可以用来标记已经弃用或者不安全的函数。alert pragma 的格式为@alert id "explain string",其中id可以是任意的标识符。

Untitled

4. 支持在 pragma 中标注 intrinsic

比如标准库中的如下代码在被标注 intrinsic 之后,在 JavaScript 后端会使用 String(..) 函数来将浮点数转化为字符串,后续会加入更多函数的 intrinsic 支持。

/// @intrinsic %f64.to_string
pub fn to_string(self : Double) -> String {
double_to_string(self)
}

5. 生成代码性能和体积的改进

  • 引入了消除局部 alias 的优化,从而避免生成无用的局部变量
  • 引入了常量传播的优化
  • 优化了生成的 wasm 代码中类型声明的部分,减少了冗余的类型声明

https://picx.zhimg.com/80/v2-18712f8e289e2548fdafcd3775aa060e_1440w.jpg?source=d16d100b

6. moonfmt 改进

  • 调整 function for loop 的打印格式,特殊情况不再打印分号
  • 针对 if/match 这种可读性差的嵌套的情况,格式化后加上额外的括号。格式化前和格式化后的效果:

格式化前:

Untitled

格式化后:

Untitled

7. 改进模式匹配完备性检查

8. 调整字符串的编码为UTF-16

构建系统更新

moon.pkg.json 中支持自定义函数导出名称

moon.pkg.json 中支持使用 ["link"][BACKEND]["exports] 字段自定义函数导出名称,并且默认不再导出所有的 pub 函数,必须要在 exports 中显式指定。此外,现在支持通过设置 link 字段链接非 main 包。

例如使用 moon new hello 创建一个新项目,其目录结构为:

.
├── README.md
├── lib
│ ├── hello.mbt
│ ├── hello_test.mbt
│ └── moon.pkg.json
├── main
│ ├── main.mbt
│ └── moon.pkg.json
└── moon.mod.json

在过去,执行 moon build,只有 main 包会生成 wasm 文件。

现在,在 moon.pkg.json 中支持 link 字段,可以对非 main 包生成 wasm 文件。link 字段的内容可以是一个布尔值:

{
"link": true // 表示当前包需要被链接
}

或者是一个对象,可以给不同的后端如 wasm 或者 wasm-gc ,设定链接选项。目前只支持 exports 选项,exports 是一个字符串数组,包含需要导出的函数及其需要导出的名称:

{
"link": {
"wasm": {
"exports": [
"hello" // 这里将函数 hello 导出为 hello,
]
},
"wasm-gc": {
"exports": [
"hello:hello_wasm_gc" // 这里将函数 hello 导出为 hello_wasm_gc
]
}
}
}

如果将 lib/moon.pkg.json 中的内容修改为:

{
"link": {
"wasm": {
"exports": [
"hello"
]
}
}
}

然后执行 moon build --output-wat,可以观察到输出的 target/wasm/release/build/lib/lib.wat 中包含如下内容:

(func $$username/hello/lib.hello.fn/1 (export "hello") (result i32)
(i32.const 10000))

其中的 (export "hello") 表示配置生效了。

IDE 更新

vscode 插件支持安装或更新 MoonBit工具链。

Untitled

weekly 2024-03-25

· 阅读需 3 分钟

构建系统更新

1. 支持 expect testing

a. 使用 moon new 新建一个 MoonBit 项目。

b. 在 lib/hello.mbt中写入:

pub fn hello() -> String {
"Hello, world!"
}

test {
let buf = Buffer::make(10)
buf.write_string(hello())
buf.expect()?
}

c. 然后运行 moon test --update或者 moon test -u:

$ moon test --update
expect test failed at lib/hello.mbt:8:3-8:15
Diff:
----
Hello, world!
----

Total tests: 1, passed: 0, failed: 1.

Auto updating expect tests and retesting ...

Total tests: 1, passed: 1, failed: 0.

d. 再次打开 lib/hello.mbt 文件,可以看到已经将测试结果 promote 到源码中。

pub fn hello() -> String {
"Hello, world!"
}

test {
let buf = Buffer::make(10)
buf.write_string(hello())
buf.expect(~content="Hello, world!")?
// ^~~~~~~~~~~~~~~~~~~~~~~~ 测试结果更新
}

2. moon run 不再支持 --output-wat选项。

MoonBit 更新

1. 支持多参数构造器的后端代码生成

支持多参数构造器(multi-argument constructor)的后端代码生成。现在构造一个泛型类型的值的时候,如果泛型参数为元组的话必须要写括号,即:

enum A[X] {
A(X)
}

fn init {
// Error, expecting 1 arg, getting 2
A::A(1, 2) |> ignore

// Ok
A::A((1, 2)) |> ignore
}

多参数构造器 unbox 了参数,能够提高生成的代码的性能,也允许程序员对数据的内存布局有了更多的掌控。

2. 调整了Int64的lsl, lsr, asr方法

现在移位参数不再是Int64,而是Int。同时调整了clz, ctz, popcnt方法,现在返回类型不再是Int64,而是Int。此项改变有助于我们在不支持原生Int64的平台上生成更高效的代码。

IDE 更新

1. 支持带标签参数的重命名。

2. VSCode 插件支持自动安装或者更新 MoonBit

a. 更新插件后,如果没有安装 moon 或者 moon 不是最新的时候,VSCode 右下角弹出自动安装/升级的提示。

Untitled

b. 点击 "yes", 来执行自动安装任务。任务完成后就可以用了。

Untitled

weekly 2024-03-18

· 阅读需 3 分钟

语言更新

1. 实验性地添加对 trait 实现默认方法的功能

trait MyShow {
repr(Self) -> String
str (Self) -> String // it has a default implementation
}

impl MyShow::str(self : Self) -> String {
// default implementation of str
self.repr()
}

type MyInt Int
fn repr(self:MyInt) -> String {
self.0.to_string()
}
// Now MyInt implements MyShow now

2. 允许类型定义的类型参数为 _

_可以用来定义 phantom type,来限制一些程序逻辑上非法的操作。例如我们希望不同单位的长度不能够相加:

type Length[_] Int

type Kilometer
type Mile

fn add[T](x: Length[T], y:Length[T]) -> Length[T] {
Length::Length(x.0 + y.0)
}

let d_km: Length[Kilometer] = Length(10)
let d_mile: Length[Mile] = Length(16)

此时,两个单位不同的长度并不能够直接相加:

fn init {
add(d_km, d_mile) |> ignore
// ^~~~~~ Error: Expr Type Mismatch
}

而两个单位相同的长度可以相加:

fn init {
add(d_km, d_km) |> ignore
// OK
}

3. 现在 Toplevel 函数没有标记返回值的行为改成报错

Toplevel 函数没有标记返回值的行为从之前的默认设置为 Unit 改成报错。

fn print_hello() {
// ^~~~~~~~~~~ Error:
// Missing type annotation for the return value.
println("Hello!")
}

4. 添加了按位取反的操作符

fn main {
println((1).lnot())
}

输出:

-2

5. 改进 List::to_string/debug_write 的输出

fn main {
let l = List::Cons(1, Cons(2, Cons(3, Nil)))
println(l)
}

输出:

List::[1, 2, 3]

6. 添加了 Byte 类型

byte 字面量由 b 作为前缀,使用方式如下:

fn init {
let b1 = b'a'
println(b1.to_int())
let b2 = b'\xff'
println(b2.to_int())
}

更多关于 Byte 的功能还在完善中

IDE更新

1.支持对 moonbitlang/core 的补全

2. 格式化的更新和修复:

  • 调整空的 struct、enum、trait,避免出现空行。

之前:

struct A {

}

之后:

struct A {}
  • 修复 continue 的错误缩进。
  • 修复多行语句格式化后出现分号的问题。

构建系统更新

1. moon.mod.json 添加了 test_import 字段

test_import这个字段中用到的依赖只会在测试的时候被用到。

2. 优化 moon test 输出

默认只输出失败的测试用例信息,如果需要完整输出可使用moon test -v命令。