Playground:
Code:
enum

动机

enumenumenumenum
enumenum
package task

type TaskStatus int

const (
  Todo TaskStatus = iota
  Pending
  Done
)

现在,我们引入前端,因为数据库里存的是 0、1这样的数据,那前端拿到的 API 返回值往往也是这样子的,如

{
  todos: [
    {name: "Learning", status: 0}
  ]
}
statusenum
enum TaskStatus {
  Todo,
  Pending,
  Done
}
enum

基于这样重复劳动的问题,所以就有了本文要所讲的这个小工具

转换

进行语言的转换,必须理解源语言所表达的含义,这里也就用到了传统的编译相关的一些技术

分词

分词就是将一句话分成一个个单词
how are you?howareyou?
TaskStatus
[]token.Token{
    {
        Value: "package",
        Type:  "Package",
        Start: {0, 0},
        End:   {0, 6},
    },
    {
        Value: "task",
        Type:  "Identifier",
        Start: {0, 8},
        End:   {0, 11},
    },
    {
        Value: "type",
        Type:  "Type",
        Start: {2, 0},
        End:   {2, 3},
    },
    {
        Value: "TaskStatus",
        Type:  "Identifier",
        Start: {2, 5},
        End:   {2, 14},
    },
    {
        Value: "int",
        Type:  "IntType",
        Start: {2, 16},
        End:   {2, 18},
    },
    {
        Value: "const",
        Type:  "Const",
        Start: {4, 0},
        End:   {4, 5},
    },
    {
        Value: "(",
        Type:  "LeftParentheses",
        Start: {4, 6},
        End:   {4, 6},
    },
    {
        Value: "Todo",
        Type:  "Identifier",
        Start: {5, 1},
        End:   {5, 4},
    },
    {
        Value: "TaskStatus",
        Type:  "Identifier",
        Start: {5, 6},
        End:   {5, 15},
    },
    {
        Value: "=",
        Type:  "Assignment",
        Start: {5, 17},
        End:   {5, 17},
    },
    {
        Value: "iota",
        Type:  "IOTA",
        Start: {5, 19},
        End:   {5, 22},
    },
    {
        Value: "Pending",
        Type:  "Identifier",
        Start: {6, 1},
        End:   {6, 7},
    },
    {
        Value: "Done",
        Type:  "Identifier",
        Start: {7, 1},
        End:   {7, 4},
    },
    {
        Value: ")",
        Type:  "RightParentheses",
        Start: {8, 0},
        End:   {8, 0},
    },
}

分词的 workflow 如下

生成 AST

根据上一步分析出来的 token,生成对应的抽象语法树

ast.File{
    Name: "task",
    Body: {
        ast.TypeDeclaration{
            Id:   "TaskStatus",
            Kind: "int",
        },
        ast.ConstDeclaration{
            BaseDeclaration: ast.BaseDeclaration{},
            Declarators:     {
                {
                    Kind:  "TaskStatus",
                    Id:    "Todo",
                    Value: "iota",
                },
                {
                    Kind:  "",
                    Id:    "Pending",
                    Value: "",
                },
                {
                    Kind:  "",
                    Id:    "Done",
                    Value: "",
                },
            },
        },
    },
}
typeStatusinttokenTypeDeclaration
func (a *AstGenerator) readTypeDeclaration() TypeDeclaration {
    d := TypeDeclaration{}

    next, _ := a.nextToken(true)
    d.Id = next.Value

    next, _ = a.nextToken(true)

    if next.Type == token.IntType {
	d.Kind = Int
    } else {
	d.Kind = String
    }

    return d
}

执行 AST

enum

遍历上一步生成的 AST,生成相关的计算值

{
  TaskStatus: {
    Todo: 0,
    Pending: 1,
    Done: 2
  }
}
enum
enumenum
namespace task {
  export enum TaskStatus {
    Done = 2,
    Pending = 1,
    Todo = 0,
  }
}

Playground

因为转换的源代码是用 Golang 写的,所以这里是将 Golang 变异成 wasm 运行在浏览器的