nextzlog / todo

ToDo lists for ATS-4, CW4ISR, QxSL, ZyLO.
https://nextzlog.dev
1 stars 0 forks source link

CW4ISRに組み込む言語処理系の調査 #178

Closed JG1VPP closed 1 year ago

JG1VPP commented 1 year ago

概要

CW4ISRにマクロ拡張機能を提供するための言語処理系の候補を調査する。

JG1VPP commented 1 year ago

候補

go mod tidyで取得でき、言語仕様が安定して、メンテナンスされている処理系は、以下の通り。

JG1VPP commented 1 year ago

簡単な例

本体

package main

import (
    "fmt"
    "github.com/yuin/gopher-lua"
)

func Hello(L *lua.LState) int {
    fmt.Println(fmt.Sprintf("Good morning, %s!", L.ToString(1)))
    L.Pop(1)
    return 1
}

func main() {
    L := lua.NewState()
    defer L.Close()
    L.SetGlobal("hello", L.NewFunction(Hello))
    L.SetGlobal("world", lua.LString("world"))
    if err := L.DoFile("script.lua"); err != nil {
        panic(err)
    }
}

処理

hello("Bob")
print(world)

結果

$ go run test.go
Good morning, Bob!
world
JG1VPP commented 1 year ago

活用事例

JG1VPP commented 1 year ago

RPC

言語処理系を埋め込む代わりに、RPCで他のプロセスと連携させることも考えられる。

JG1VPP commented 1 year ago

JSON-RPC

標準ライブラリのnet/rpc/jsonrpcなら、Protobufに頼らずPython等の言語とも連携可能。単に趣味の問題。

JG1VPP commented 1 year ago

折衷案

内部処理系

機能を絞ったLuaを想定

外部処理系

RPC経由でPythonとの連携を想定

JG1VPP commented 1 year ago

その他の言語

traefik/yaegiはGoの仕様を完全にサポートしたスクリプト言語。有力な選択肢かも。

JG1VPP commented 1 year ago

JavaScript

dop251/gojaはECMAScript5.1の実装。Luaや独自言語よりも親しめそう。

package main

import (
    "fmt"
    "github.com/dop251/goja"
    "github.com/dop251/goja_nodejs/console"
    "github.com/dop251/goja_nodejs/require"
)

type Message struct {
    Data []float64
    Code string
    Freq int
    Time int
    Miss int
    Tone float64
    Mute float64
}

var msg = Message{
    Data: []float64{1, 2, 3},
    Code: "ABC",
    Freq: 100,
    Time: 10,
    Miss: 1,
    Tone: 100,
    Mute: 0,
}

func main() {
    vm := goja.New()
    req := new(require.Registry)
    req.Enable(vm)
    console.Enable(vm)
    vm.Set("message", msg)
    res, err := vm.RunString(`
        console.log(message.Code);
        message.Code = "DEF";
        message;`)
    if err != nil {
        fmt.Println(err.Error())
    } else {
        fmt.Println(res.Export())
        msg = res.Export().(Message)
    }
    fmt.Println(msg.Code)
}

実行結果:

$ go run script.go
2023/07/27 14:44:43 ABC
{[1 2 3] DEF 100 10 1 100 0}
DEF
JG1VPP commented 1 year ago

最終的に、JavaScript (ES5)を採用しました。以下のようにcw4i.jsを配置すると、受信中のメッセージを編集・処理できます。

function handle(messages) {
    return messages;
}

handle;

組み込みの処理系のため、外部のライブラリには対応できませんが、そのような用途には、プラグインやRPCで対応する予定です。