2018年3月9日金曜日

オレオレ言語、Expressoについて・・・.NET Frameworkを標準ライブラリとして扱う編

こんにちは、はざまです。今回もExpressoに関する記事です。

今まではSystem.Mathなどの限られたクラスしか使えていませんでしたが、つい先日の更新でC#の型のnewとプロパティの読み出し、メソッド、コンストラクタのオーバーロード解決ができるようにしました。これで実質、.NET Framework全体をExpressoの標準ライブラリとみなすことができ、大きな財産となるはずです。また、.NET Frameworkの相互運用のためにnullリテラルを導入しました。nullリテラルは、.NET関連の文脈以外では禁止になる予定です。Expressoの文脈で値の有無を表現するには、別途用意するOption型を使用することにする予定です(Expresso独自の標準ライブラリをどう提供するかは未定です)。
module main;

import "System.IO.File" as File;
import "System.IO.FileStream" as FileStream;
import "System.Text.UTF8Encoding" as UTF8Encoding;


def main()
{
    var writer (- FileStream;
    try{
        writer = File.OpenWrite("./some_text.txt");
        let bytes = UTF8Encoding{encoderShouldEmitUTF8Identifier: true}.GetBytes("This is to test writing a file");
        writer.Write(bytes, 0, bytes.Length);
    }
    finally{
        if writer != null {
            writer.Dispose();
        }
    }
}

テストのコードをまるまんま写してきただけですが、このようにして.NETの型を活用できます。コンストラクタの呼び出しは、オブジェクト生成式にコンストラクタの引数の型の値を順番通り指定することで呼び出します。コンストラクタ・メソッドのオーバーロード解決は型のみを見て行っており、名前は今のところ見ていないのでなんでも構わないのですが、将来的には何かそこもバリデーションをかけたいところではあります(上記の例では、コンストラクタの引数名をオブジェクト生成式のフィールド名にしています)。なお、オブジェクト生成式でExpressoのclassを生成する場合には、フィールドが定義された順にフィールドの初期値を設定します。フィールド名をオブジェクト生成式で指定しても、その通りには現状解釈されないので注意してください。適当な初期値を与えたい場合は、ファクトリ関数を作成してください。ただし、クラス内に自身を返したり、自身を引数にするメソッドは書けないので注意です(なので、ファクトリ関数をmoduleの関数にするといいでしょう)。
C#のusingのような構文がないので、このようなtry, finallyの不恰好なコードになっていますが、これも新しい構文を追加するべきでしょうね、きっと。あと、予定としては、immutableな変数からは、自身をmutateするメソッドは呼べないようにも変更します(このコードだと、writer.writeが該当)(2018/4/8 追記: この日現在、実装されていますが、外部アセンブリ由来のコードに対してはチェックしていないので、エラーにはなりません。)。あと、現状Enumがないので、.NETのEnumを使用するコードも書けません。ExpressoのEnumは、Rustのような数学的データ型にする予定なので、導入したとしても、.NETのEnumは呼べない公算が大きいですが、ファイル生成の全パターンを網羅できなくなるので、なんとかします(多分)(2018/4/8 追記: .NETのenumを参照できるようになりました。これと別にExpressoのenumは数学的データ型として実装する予定です)。最後に、.NETのメソッドは、Expressoに合わせてキャメルケースに変換してあります。上のコードをFile.OpenWriteなどと書いて、あれ動かねえなんて茶番を演じないように気をつけましょう。(2018/4/8 追記: この仕様は複雑になるので、廃止しました)

0 件のコメント:

コメントを投稿

なにか意見や感想、質問などがあれば、ご自由にお書きください。