【Juno開発】変数・定数を作った時の感想と苦労した点
はじめに
みなさんどうも。rii_125です。
最近、Junoを開発しているのですがついに変数、定数の基礎の基礎を完成させました。今までは、見せかけの変数という感じでしたが型チェックのある程度効いて、少し使えるようになったので紹介したいと思います。
また、Junoの開発を絶賛大募集中ですのでdiscordサーバーから参加を申し込むか、issueからでも参加を受け付けています。
public static main() {
print("Welcome to Juno world!");
}
変数宣言
こちらを見てもらったほうが早いかもしれません。
変数宣言はvar 変数名 : 型;の宣言が基本です。変数の代入には変数名 = 値;となります。まあ、基本中の基本です。この文法に従ってコーディングをしていきます。
問題1【変数宣言&代入の実装】
まず、変数宣言の原型が完成する前までは
public static main() {
var a : int = 125;
var b : string = "rii_125";
}
でのみ変数が使えた。けれど、
public static main() {
var errorVar : string; // ←ここでエラー(変数宣言のみだと値と=が検出されないから)
errorVar = "rii_125"; // ←ここが読まれない
}
ということが発生しました。
解決策
解決策として、=がない場合は宣言だけとしてとらえるような設計になりました。
if文でチェックして=がない時だけ宣言のみの変数だと認識させました。
問題2 【定数が宣言できない】
本来定数は、finalを使用して宣言します。
public static main() {
final PI : float = 3.14; // 定数として定義されるはず
}
しかし、未知の文字として表示されRuntimeException[1]が発生しています。
そりゃそうですよ。だって定義すらしてませんもの。
解決策
-
TokenType.javaにFINALを定義 -
TypedVarDeclacrationNode.javaにfinalの型の定義の仕方をデフォルトコンストラクタに再設定 -
Lexer.javaにfinalの字句解析のための列挙をswitchに定義 -
Parser.javaにfinalの文法表現やエラーの設定などを行う
この手順を行うことで、無事に解決することができました。
ちなみにここは、copilotに2時間くらいかけて完成させました。思った以上に時間がかかりすぎていて定数の実装に時間がかかるとは思ってもいませんでしたね。特に継承するときに暗黙のsuper();やうまく継承できていなかったりして自分のコードの汚さにビックリ!思った以上にコードの解析に時間がかかってしまったので次回からの反省ですね。😥
上のコードのsuper();の実装に30分くらいかかってます...
問題3 【floatが機能しない】
浮動型小数であるfloatが全く機能していないことに気づいて定数のコーディングの後試しにfloatで実験すると、未知の文字として.が定義されていませんでした。(この時の僕は、floatの実装を終えていたと勘違いしていました。😅)
public static main() {
final PI : float = 3.14; // RuntimeException : 未知の文字'.'
}
解決策
Lexer.javaに数値(int型とfloat型)にのみ.があると小数だと認識するようにするかつ型チェックをTypeChecker.javaに行ってもらうことで解決できました。
良い点
- 型チェックを前より厳格に行うことができた
- 宣言のみの変数・定数の宣言を実装することができた
反省点
- もう少しきれいにコードを書きたい
- 継承関係をもう一度きれいに整理したい
- コードレビューをする人がいない(Claudeにでもやってもらうかな...)
まとめ
今回は、基礎の基礎が完成したJunoの変数について開発した感想と問題点・解決策を記事にしてみました。自分の課題点が早めに見つかってよかったなと思いつつ、今後は改めて設計の仕方を見直したいと思います。
またこの記事からZennCLIを導入しました。かな~り快適に作業をすることができたので皆さんもやってみてはいかがでしょうか。
Junoのリポジトリは下から↓
-
想定していない例外や本来使用されない文法をJunoでは
RuntimeExceptionを採用して意図的に例外を生み出しています。 ↩︎
Discussion