有没有可能通过某种配置,是的println能自动追加 \x00 结尾

一、描述问题:

  1. 因为我无法重写全局的 println 函数,所以我无法自己追加 \x00 结尾
  2. 因为 println 是一次函数调用,而一次 println 会调用多次 print_char
  3. 如果调用多次 print_char,我无法知道到底调用了几次 println(“example_str_with_\x10”)。

二、我的需求:

我希望在浏览器中,使用console.log 来替代 println,但是因为我只能重写 print_char 而不是 println,这就导致我无法知道 println 到底调用了几次。如果我只是简单地使用 \n 来分割也不合理,因为 println打印的内容本身就可能包含多个回车符

三、可能的实现方案:

方案A:提供更加丰富的对构建阶段的hook能力,从而可以编译期间对 println 函数做替换

方案B:提供 config_println(end~ : String) → Unit 函数,可以自定义 println 的默认追加的结尾符号(默认是 \x10)

方案B是最简单的,针对性解决问题,带来的影响也小。
方案A可以提供最大的灵活性和性能,我可以直接返回字符串内存的 地址、长度,然后直接在runtime 侧直接实现打印。

这个需求实现一个FFI就可以解决。以js后端为例:

extern "js" fn my_println(x : String) = "(s) => console.log(s)"

对于wasm后端,需要根据你选择的运行时的文档来配置。nodejs 可以参考这个模版:moonbit-wasm-nodejs-ts-template/src/ts/app.ts at master · moonbit-community/moonbit-wasm-nodejs-ts-template · GitHub

参考

https://docs.moonbitlang.com/zh-cn/latest/language/ffi.html

当然,自己的库使用怎么都行。

关键是第三方库怎么办?

我们可能会用 virtual package 的方式替代掉原生的 println,并替换为 write / print / ewrite / eprint。
另一种方式便是彻底删除 println,不在 core 里提供任何平台相关的能力。

  1. 用 virtual package是个不错的办法,加油尽快稳定
  2. 彻底删除 println 是可以,但日志打印是刚需,还是希望 moonbit官方提供标准库,参考 GitHub - WebAssembly/wasi-logging: WASI logging API

不过关于virtual package,目前文档说的:“需要完整地实现 virtual package 中的 .mbti 文件中规定的接口”,如果能只实现部分接口就好了,这样我还可以跟其它impl包进行搭配

区分输出与日志打印是个不错的思路,或许我们也会往这个方向去做