🤖

ChatGPT4.0と一緒にプログラミング言語を開発する

2023/03/28に公開

1 年ぐらい前から、趣味で Syvora という名前のプログラミング言語を開発している。
「から」といっても、コミットログはこんな感じ。

楽しく開発していたのだけど、相談相手がいなくて詰まったら他の言語のコンパイラを見るぐらいしか選択肢がなく、いったん諦めていた。

だがしかし、ChatGPT4.0 が登場して状況が大きく変わった。
いつ質問しても良い専門知識を持った優秀な同僚が常にそばにいてくれるので、超楽しい。

この楽しさを共有したい。

ChatGPT が解決してくれた悩み

やり取りは全て DeepL で翻訳して英語でやっている。
本当はやり取りの一つ一つが長いけど、超要約して書いていく。

構文編

import 文

malt03:

TypeScript に近い構文にしようと思っているけど、書きたい順序と書く順序が逆なのが不満。

import { Foo } from "./bar.js"

上の例なら、 "./bar.js" を書いてから Foo を書きたい。絞り込んでオートコンプリートを効かせたいからだ。なんか解決策あるかな?

ChatGPT:

こんなのはどう?

import "./bar.js" with { Foo }

メソッドチェーン

malt03:

Syvora では JSX ライクな関数呼び出し構文を採用していて、読みやすさは気に入ってるんだけどメソッドチェーンができないのをどうにかしたい。
TypeScript なら以下のようにかける。

const result = array.filter((n) => n % 2 === 0).map((n) => n * 2)

Syvora だとこう書くしかない。

const tmp = <array.filter>
  fn(n) -> Bool { return n % 2 == 0 }
</array.filter>
const result = <tmp.map>
  fn(n) -> Int { return n * 2 }
</tmp.map>

解決できないかな?

ChatGPT:

こう書くのはどう?

const result = array.
  <filter>
    fn(n) -> Bool { return n % 2 == 0 }
  </filter>.
  <map>
    fn(n) -> Int { return n * 2 }
  </map>

新しいキーワード

malt03:

Syvora のブロックは、最後に評価した式を返す式として評価されるけど、その評価する式を明示的に示すキーワードを考えてほしい。
ブロックがその式を評価していることを明示して可読性を高めるため。

var a = {
  const x = 1
  const y = 2
  [keyword] 1 + 2
}

ChatGPT:

derive がいいと思う。
ブロック内の操作に基づいて、それに続く式の値を導出、取得することが明確になる。このキーワードは、ブロックの記述の結果として値を生成することが目的であることも示唆する。このキーワードは、ブロックのステートメントと結果の値の間に、論理的な進行と関連性を感じられる。

実装方針編

Generics について

malt03:

Generics をどのように実装するか悩んでいる。
いろんな選択肢があるけど、Syvora は API サーバーと Web フロントの開発がメインターゲット。パフォーマンスはスケールアウトで対応するから、それよりもコンパイル速度やバイナリサイズ、コールドスタートの速度が優先事項。

ChatGPT:

それなら、Java のような型を消去する実装がおすすめ。多少の実行時パフォーマンスを犠牲にコンパイルが早く、バイナリサイズも小さく、コールドスタート速度も早くできる。

実装編

再代入

malt03:

今、変数宣言の実装がこんな感じなんだけど、再代入の際に scope が示すメモリアドレスが変わっちゃうから、将来的にメモリを導入した時におかしくなりそう。どうしたらいい?

let expectedType: ExpectedType = try type.map { .specified(try scope.getType(name: $0.value)) } ?? .notVoid
let value = try rhs.build(module: module, builder: builder, scope: scope, expectedType: expectedType)!
try scope.addValue(name: token.value, value: value)

ChatGPT:

alloca っていうのを使うのが普通だよ。

let expectedType: ExpectedType = try valueDeclaration.values.type.map { .specified(try scope.getType(name: $0.value)) } ?? .notVoid
let (v, t) = try rhs.build(module: module, builder: builder, scope: scope, expectedType: expectedType)!
let alloca = builder.buildAlloca(type: try t.llvm())
builder.buildStore(v, to: alloca)
let value = (alloca, t)

print

malt03:

テスト用に print 関数をモジュールに定義して。Int64 を引数に取って何も返さない関数をお願い。

ChatGPT:

どうぞ

import LLVM

func addPrintFunction(module: Module) {
    let int64Type = IntType(width: 64)
    let voidType = VoidType()

    let functionType = FunctionType(argTypes: [int64Type], returnType: voidType)
    let printFunction = Function(name: "printInt64", type: functionType, in: module)

    let entryBlock = printFunction.appendBasicBlock(named: "entry")
    let builder = IRBuilder(block: entryBlock)

    // Declare the 'printf' function from the C library
    let printfType = FunctionType(argTypes: [PointerType(pointee: IntType.int8)], returnType: int64Type, isVarArg: true)
    let printfFunction = module.addFunction("printf", type: printfType)

    // Create a format string for 'printf' that prints an Int64 value followed by a newline
    let formatString = builder.buildGlobalStringPtr("%lld\n", name: "int64_format")

    // Call the 'printf' function with the format string and the Int64 argument
    let int64Arg = printFunction.parameters.first!
    _ = builder.buildCall(printfFunction, args: [formatString, int64Arg])

    builder.buildRetVoid()
}

これは色々と間違っていてそのままでは使えないので修正して使う予定。

その他

言語名

malt03:

プログラミング言語の名前を決めたい。
以下の条件を満たす造語を 10 個出力して。

  • 全く存在しない
  • 10 文字以内
  • 発音しやすい
  • 発音がわかりやすい
  • 見た目がかっこいい

ChatGPT:

  • ...
  • Syvora
  • ...

ChatGPT に相談するときのコツ

丁寧なコミュニケーションを心がける

ChatGPT が出してくれた出力に対して、きちんとお礼を言う。
否定する時も「ありがとう!めっちゃいいじゃん。だけどちょっとここを改良してほしいな」のように、やる気が出る言い回しを心がける。

ChatGPT は人が出力している文章を元に学習しているはずで、こちらがこういったコミュニケーションを心がけていると、やる気が出た人「らしい」返答をしてくれるし、正確性が増す気がする。

こっちが「Thank you!」とか言ってると「Certainly!」とか返してくれて、自分自身もやってて楽しくなってくる。

まずはザックリとした質問をして、その後詰めていく

割と雑めなオープンクエスチョンを投げても返答をしてくれるのがいいところ。
それで的を射た回答をしてくれることもあるので、最初から詰めすぎない。
また、返ってきた答えで、ChatGPT からすると何が不明瞭なのかも分かり易い。
そのやり取りの応酬で自分の頭もスッキリしてくる。
ちょっと長いけど、以下に dervie キーワードを決めた際のやり取りを載せておく。

スクリーンショット

コードを全部書いてもらうのは諦める

なんとなくイメージは湧いてるけどそもそもちょっと書き方わからないとか、書いたコードが動かないから間違いを指摘してほしいとかそういうのが得意。

大体書くべきことがわかっていて、あとやるだけっていうコードをガンガン書いてもらうのには向いてない。
文字数が多すぎて過去のことをどんどん忘れちゃうし、細かいミスも多くて自分でやった方が早い。

そういうのは、 GitHub Copilot X がきっと解決してくれる。

まとめ

ChatGPT4.0 最高!
現在 mish 社では全社員の ChatGPT Plus 代を会社で負担してます!(急な宣伝)

GitHubで編集を提案

Discussion