🖤

NeovimでCommon Lisp(加えてProlog, ELIZA)を外部依存ゼロで動かせるプラグインを作った

2025/01/15に公開

https://github.com/sirasagi62/nvim-lcl-lisp-runner

NeovimからCommon Lispとその上で実行されるProlog,ELIZAを外部依存無しで実行できる(=SBCL/Claspのような処理系すらインストールせずに実行できるようにする)という謎プラグインを作成しました。

スクリーンショット

Common Lisp

Prolog

ELIZA

概要

諸事情でCommon Lispを手軽にNeovimから呼び出して、デバッグできる環境が欲しくなったので作成しました。ついでにPrologとELIZAについても実行できるようにしたかったので、デモ用に同梱してあります。主な機能として

  • :RunLCLLCL(後述する今回用いたCL処理系)のREPLを起動する。
  • :RunPrologでCLで書かれたProlog対話処理系を起動する
  • :RunElizaでCLで書かれたELIZAを起動する

があります。PrologとELIZAはPeter Norvigの"Paradigms of Artificial Intelligence Programming"の実装を移植したものになります。

特徴

メリット

  • 外部依存が一切なく、不完全なstdlib含めて1MB(プラグインとしては大きめ)
  • CLの機能をLuaで拡張できる(後述するLCLによるものです)
  • REPLをNeovimから手軽に呼び出せる

デメリット

  • Lua上で実行するという特性上、実行速度が遅い(Gen11のintel Core i7で動かしているのに1992年のコンピュータと比較して1.5倍程度の速度しか出ない)
  • Common Lispの標準ライブラリ、言語機能で一部使えないものがある
  • LuaJITがバンドルされたNeovimでないと何故か動かない

正直、Common Lispの入門処理系としては全く不向きなプラグインです。あくまでPrologとELIZAを動かすための最小限のCL処理系が同梱されている、という程度の認識のほうが正しいかもしれません。
逆に

  • CLで書かれたPrologとELIZAに触れてみたいけど、本格的な処理系を入れるのは躊躇している
  • エディタで自己完結する謎プラグインが好き

という方には適しているかもしれません。
またプラグイン自体はCommon Lispの実行系とUI部分が別れているため、本プラグインを改造してSBCL/Claspに依存する代わりに高速・安定・完全なCL処理系で実行できるようにするのもいいかもしれません。読者の皆様への演習課題としておきます。

仕組み

言うまでもなく、Neovim以外の依存を持たないということは、Neovimが持つ言語処理系であるVimscript/Luaのどちらかの上でCommon Lispを実行しなければならないということを意味します。今回の実装ではLCLと呼ばれるLuaで実装されたCommon Lisp処理系を用いることで、Common Lispを強引にLua上で実行しています。

しかし、ユーザーが今使っているNeovimプロセス上で直接LCLを実行すると次のような不都合が生じます。

  • LCLの処理によりエディタ側の処理がブロックされてしまう
  • Neovimが受け持っていると標準入出力と起動しているCommon Lispの標準入出力を適切に接続する必要が生じる
    特に2番目はREPLに立脚しているCommon Lispでは致命的な問題です。

この問題を回避するために本プラグインでは「Common Lispを実行するためのLuaをスクリプトを実行するためのNeovimプロセス」を別途Neovimの組み込みターミナル上で起動しています。具体的にはheadlessモードでNeovimを起動し、その上でluafileコマンドを用いてLCLを実行しています。headlessモードで起動することでNeovim内のコマンドの実行結果が直接標準入出力に接続されるようになり、前述した標準入出力の問題を回避しているわけです。さらにこの「Lisp用のNeovimプロセス」が「ユーザーが起動したNeovimのターミナル」と接続されることでユーザーからはCommon LispがNeovim中で動いているようにみえるというわけです。長々と説明しましたが、結局は「Luaの黒魔術でCommon Lispインタプリタに擬態させた別プロセスのNeovim」をNeovimのターミナルで実行しているだけです。

なおPrologとElizaについては、単に以上のCL処理系で動かしているだけです。例えばデモとして実装されているPrologは実際には「Neovimから起動した別のNeovim上で動かされているLuaスクリプト上で動くCommon Lisp上にマクロで実装されたProlog」となっているわけです。インセプションみたいですね。

まとめ

NeovimでCommon Lispを(強引に)実行する謎プラグイン、nvim-lcl-clisp-runnerの紹介でした。NeovimでPrologやELIZAに触れてみたい方はぜひ試してみてください。

Discussion