一起来实现一个基于元编程的 Io-JSON 库吧!

首先,元编程是什么

Metaprogramming is the process of writing computer programs that treat programs as data, enabling them to analyze or transform existing programs or generate new ones.

按照中文社区比较流行的说法就是……「代码即数据」!

即是通过代码来处理或生成代码,可以实现一些类似「生成重复繁琐的代码」、「自定义语法」的功能。这里我们就考虑利用 Io 的元编程功能自定义语法,让 Io “以为” JSON 是一段合法的 Io 代码。

先来看看 Io 眼中的 JSON

这是一段 JSON 代码:

{
  "Bob Smith": "111-111-111",
  "Sally Johnson":
  {
    "phone": "222-222-222",
    "email": "abc@efg.com"
  },
  "number": 10,
  "list": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}

因为 Io 允许我们自定义 {}[] 的行为,并且会把它们翻译成 curlyBracketssquareBrackets ,这段代码就会被解释成这样:

curlyBrackets(
  "Bob Smith": "111-111-111",
  "Sally Johnson": curlyBrackets(
    "phone": "222-222-222", "email": "abc@efg.com"
  ),
  "number": 10,
  "list": squareBrackets(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
)

再通过 OperatorTable addAssignOperator(":", "assign"): 设置为一个 assign operator,这段 JSON 就会被识别为:

curlyBrackets(
  assign("\"Bob Smith\"", "111-111-111"),
  assign("\"Sally Johnson\"", curlyBrackets(
    assign("\"phone\"", "222-222-222"), assign("\"email\"", "abc@efg.com")
  )),
  assign("\"number\"", 10),
  assign("\"list\"", squareBrackets(1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
)

注意,由于 Io 会把 assign operator 左侧作为变量名并转为字符串作为 assign 的参数,所以我们后续处理时还要把 JSON 原有的双引号去掉。

做到这里事情就比较简单了,我们只要实现 curlyBracketssquareBracketsassign 就可以了。

具体实现

为了便于实现我们可以把 JSON 作为 Map 的一个子类。

JSON = Map clone

curlyBrackets

根据 JSON 的结构,每个 culyBrackets 的参数都是若干个 assign 语句。那么通过 Io 原生的消息操作[1] 把每一条 assign 提取出来,并在当前的 JSON 环境下执行即可。

JSON curlyBrackets := method(
  call message arguments foreach(arg,
    doMessage(arg)
  )
)

squareBrackets

对于一个 squareBrackets(x1, x2, ...) 语句,只要对 xi 计算后,重新组成一个 List

JSON squareBrackets := method(
  call message arguments map(x, doMessage(x))
)

assign

由于 JSON 直接继承于 Map,所以 assign 只要把第一个参数的双引号去掉后用 atPut 插入一个 key-value 对。

因为 assignkey 参数是 immutable 的状态,还需要先做一个 asMutable 操作。

JSON assign := method(key, value,
  atPut(
    key asMutable removePrefix("\"") removeSuffix("\""),
    value
  )
)

完整实现

整个库的关键部分就是上文这些,完整的代码放在我的 GitHub 仓库里。

  1. 如果有机会的话会考虑再写一篇关于 Io 消息操作的博文

一起来实现一个基于元编程的 Io-JSON 库吧!
https://littlejianch.github.io/let-s-implment-a-json-lib-in-io-by-metaprogramming/
Author
LittleJian
Posted on
July 12, 2022
Licensed under