世界を動かす技術を、日本語で。

1024バイトでPythonインタプリタを作る

概要

  • Austin Z. Henley による、 1024バイトのC言語でPythonインタプリタを自作 した挑戦記
  • FizzBuzz が動作するほどPython風な構文を実装
  • 構文・機能の大幅な制限コードゴルフ による最小化
  • 制限内で実現した機能工夫 の詳細解説
  • 最終的な ゴルフ済みCソースコード と実装可能な機能一覧

1024バイトで作るPythonインタプリタ挑戦記

  • 週末の趣味 として、 C言語のみ1024バイト以内 のPythonインタプリタ自作に挑戦
  • マクロや外部ライブラリ の使用は禁止、純粋なCコードのみ利用
  • FizzBuzz のような、Pythonらしい構文(def、コロン、インデント、if文の括弧省略など)を目標
  • Pythonの全機能実装は不可能 だが、「Pythonっぽさ」を重視したサブセットを目指す
  • 構文制限追加制約 も導入し、実装可能な範囲を明確化

初期実装と課題

  • 512バイト では機能不足と判明、 1024バイト に目標変更
  • 最小限の電卓機能 からスタートし、徐々に構文・処理を拡張
  • 再帰下降パーサ の経験を活かしつつも、 Python特有のインデントや構文 に苦戦
  • 変数名は1文字小文字限定 で、シンボルテーブルへの直接アクセスを実現
  • エラー処理は一切なし、コードの正確さを前提とする設計

パーサ・実行の仕組み

  • グローバル変数 で状態管理(ソース配列・変数テーブル・現在位置など)
  • 再帰下降パース で式を解析しながら即時実行
  • インデント減少でブロック終了、Cのコールスタックを利用した再帰的実行
  • ループ・関数 は、ソース内の位置記録とジャンプで実現
  • if・for・while 等の制御構文も、最小限のバイト数で工夫して表現

コードゴルフの工夫

  • 変数・関数名を1文字化
  • libcへのリンク前提 で標準ライブラリ利用
  • グローバル変数最大活用、C89の暗黙のint型宣言利用
  • ASCII値や三項演算子、ビット演算 でさらなる短縮
  • Stack OverflowやTips for golfing in C 等を参考に、伝統的なゴルフ技法を応用
  • 可読版から機能削減 し、最終的なゴルフ版は 1024バイト に収束

実装できた機能一覧

  • 整数型の1文字変数 とリテラル
  • 変数代入
  • + - * % の算術演算(優先順位あり、単項は式先頭のみ対応)
  • < > <= >= == の比較(一式につき1つのみ対応)
  • 整数の真偽値判定
  • if/else制御構文
  • whileループ(else対応)
  • for x in range(y)ループ(else対応)
  • 引数なし関数定義と呼び出し(再帰対応)
  • インデントによるブロック構造(スコープなし)
  • print(整数式または1つの文字列リテラル)
  • コメント対応

感想・まとめ

  • 機能拡張とバイト削減の両立 が非常に困難で、 コードゴルフの大変さ を痛感
  • 比較演算子の削減 など、FizzBuzz専用ならさらにバイト削減可能
  • GitHub に可読版・ゴルフ版両方を公開
  • 今後しばらくコードゴルフは遠慮したい という心境
  • あなたも1024バイトPythonに挑戦してみては?

コードゴルフ版Cソース(抜粋)

  • 実際の 1024バイトCコード は記事内に掲載
  • 極限まで短縮された関数名・変数名 と、 ASCII値・演算子活用 の工夫
  • 可読性は犠牲 だが、 動作するPythonサブセットインタプリタ を実現

参考・リンク

  • Austin Z. Henley のGitHubリポジトリ(可読版・ゴルフ版両方公開)
  • Stack Overflow: Tips for golfing in C
  • Teeny Tiny Compiler など、他の小型言語実装プロジェクト

Hackerたちの意見

実際にこういうのが必要な人には、Snekっていうのがあるよ: https://sneklang.org/ 「Snekは、数kBのフラッシュとRAMを持つプロセッサをターゲットにした小さな埋め込み言語です。」

そうなんだけど、Snekをソースからコンパイルしたり修正したりするのはすごく難しい。Posixみたいに、1つのCファイルで例を作ってくれたらよかったのに。いろんなプラットフォーム用のたくさんのファイルと、Pythonで書かれたカスタムパーサー(Lola)があるのは面倒だな。

それかForth。

自由意志をうまく使ってて、文章もよく書けてるね。すごくいいウォークスルーだ、オースティン!

こんな小さな作り話の言語を「解釈」してるのにはすごくがっかりした。これはPythonでもないし、Pythonの桁数にも達してないよ。

確かに、タイトルは「Python風」って書くべきだったね。

そうだね、ここで動くPythonコードの量は、この特定のFizzBuzzの例よりも多くはないと思う。たくさんのショートカットが使われてるけど、それは理解できるかな。

これはジャスティン・タニーのSectorLISPと同じような精神を感じるね。めっちゃクール! https://justine.lol/sectorlisp/

それか、sectorC https://github.com/xorvoid/sectorc 編集: sectorCがpython1024をコンパイルできるか気になるな。

SectorLISPは実装において重要な問いを投げかけてる:Lispをどれだけ削ぎ落としたらLispじゃなくなるのか。提出されたインタプリタでは同じことはされてないけど。だから、SectorLISPの目標はLispを本質にまで削減した実装である一方、Python-1024の目標は可能な限り最小のコードでPythonを模倣することみたいだね。

これめっちゃクールだね!何ができるか、何がオプションかを見るのが楽しい。以前、他のミニランゲージで「1文字変数」の制限を見たことはあるけど、ソース自体を関数呼び出しやループのターゲットにするのは初めてだ。すごく理にかなってるけど、思いつかなかったな。

でも、ソース自体を関数呼び出しやループのターゲットとして使うのは初めてだな。これは8ビットマイクロコンピュータのインタプリタでは標準的なやり方だった。64Kのアドレス空間しかないから、最初にASTを作るのはすごく無駄に思えるから、ソースから直接解釈するんだ。シェルスクリプトを実行するとき、シェルもまだこれをやってると思う。DOSのCOMMAND.COMは確実にそうだし。

Hacker Newsで議論の続きを見る