verification-helper icon indicating copy to clipboard operation
verification-helper copied to clipboard

C# 対応

Open kmyk opened this issue 5 years ago • 15 comments

親 issue: #116

考えてなかったけどやってくれそうな人がいるので 同時に F# 対応も入るとうれしい

kmyk avatar Jan 29 '20 02:01 kmyk

@riantkb @key-moon @cannorin

kmyk avatar Jan 29 '20 02:01 kmyk

C#/F# には #include に相当するものがないですが,csprojfsproj から単一ファイルの生成をするという感じですか

cannorin avatar Jan 29 '20 02:01 cannorin

仕様についてなのですが、C#の特性上関数やコード片を外に出すことができません。 ライブラリ的にはやはり関数なども置けたほうが嬉しいため、対応をするのであればC# scripting形式のファイルとしてライブラリを扱うのが良いのかな、とおもったりしています。 そうすると#load "[filepath]"で別のライブラリをincludeのように参照できます。()

key-moon avatar Jan 29 '20 02:01 key-moon

F# script (fsx) にも #load プリミティヴがありそのように使うことができます (cf. https://docs.microsoft.com/ja-jp/dotnet/fsharp/tutorials/fsharp-interactive/)

cannorin avatar Jan 29 '20 02:01 cannorin

Roslyn って言ってたのを昨日見たのでとりあえず名前だけ挙げておきます (私は何なのかよく分かってません) https://twitter.com/kymn_/status/1222084445970132992

kmyk avatar Jan 29 '20 02:01 kmyk

Roslynは.NET Coreで使われているコンパイラで、Compiler as a Serviceを掲げて構文解析等のAPIを提供しているものです。 C#のプロジェクトをライブラリにする場合はこれが方法となると思いますので、検討したいです。 パッと思いつくメリット・デメリットとしては、

メリット

  • C#プロジェクトでライブラリが書ける
  • 依存関係等をあまり意識しなくてよくなる(プロジェクトについてコンパイラがよしなにしてくれるので)
  • 名前空間をつけられる(追記)
  • テストについて、NUnit等のテスト用フレームワークを用いたテストの記述ができる(?)(かなりめんどくさそうではある)
  • 別用途への適用ができるかも(提出ファイル自動生成等)

デメリット

  • 関数をライブラリ化する際に、Classで包まなければいけない(ボイラープレートが増える)
  • 同じClass名のライブラリを作るのが煩雑になりそう(同一名前空間に同名Classが存在できないため)
  • 実装が多分つらい

くらいでしょうか

key-moon avatar Jan 29 '20 03:01 key-moon

https://github.com/riantkb/csharp/blob/83deb5ebbb7ecf65ab9a5987aab2feb461453ae8/test/BITTest.csx こんなふうに書いて dotnet script test/BITTest.csx とすると動いたので,テストコードを c# script 形式で書くのはありかもしれないです.

ただ,c# script だと名前空間が定義できないので,ライブラリがちゃんと名前空間で分けられていたりすると動かないので少し微妙…

riantkb avatar Jan 29 '20 05:01 riantkb

名前空間をつけている人がVerifyできなくなるのはあまり宜しくないので、生C#への対応は必須そうですね。それとは別にscriptでの手軽さは残したいので、簡単にできそうなscriptへの対応をまずは生やそうと思います。

key-moon avatar Jan 29 '20 06:01 key-moon

list_attributesが表すものについて、C#ではどのようにして対応するかを検討したいです。 list_attributesはVerifyファイルの指定などに使われています。詳しくは以下の引用と、C++での実装を参考にしてください。(C++では#defineマクロの値をkey-value辞書として返すようにしています)

list_attributes (設定情報の辞書を返す) だけは設計が自明でないんですが、うまくやってください。 実用的には「コンパイラが clang++ でかつ ulimit に失敗している場合のみ実行をスキップしたい」などの単純な条件分岐を含む設定が可能な仕様にする必要があります。

Originally posted by @kmyk in https://github.com/kmyk/online-judge-verify-helper/issues/116#issuecomment-579569384

C#の#defineはシンボルの定義のみしか行えないので、他の方法を考える必要があります。 私は#pragmaディレクティブを使うのが最適かな、と思っているのですが、他に良い方法があれば教えて下さい。

key-moon avatar Jan 30 '20 08:01 key-moon

.csx の依存関係解析について、現在は #load しか認識してくれないけど using 句も認識してくれるとうれしそう。

例:

https://github.com/camypaper/complib/blob/3805a404c327922398484caa8c2c1f79a059e7e9/Tests/Graph/HLtree.test.csx#L5

cc: @camypaper

kmyk avatar May 06 '20 17:05 kmyk

現状の判定条件が行頭に #load がある程度のゆるさなので https://github.com/online-judge-tools/verification-helper/blob/daaa4d04f1625de766f6223c0f8a610077464841/onlinejudge_verify/languages/csharpscript.py#L61

https://github.com/camypaper/complib/blob/b1ba376a64964d1b6522b53b3ce26f763a4b4239/Tests/Graph/HLtree.test.csx#L2-L4

みたいにコメントで補足、というのでもなんとかなりそうです。 namespace の解析を真面目にするのはしんどい割に労力に見合わなさそうという気もしています。

camypaper avatar May 06 '20 18:05 camypaper

なるほど、#r "./../../bin/complib.dll" の時点ですでに全部が import されていて、using は名前空間を省略できるようにするだけなのか。つらそう 申し訳ないがひとまずはコメントで補足する方式でお願いします :bow:

kmyk avatar May 06 '20 18:05 kmyk

現状 3 つぐらい手は考えていて、今後やるにしても 2 程度が無難な落とし所な気が個人的にはしています

  1. roslyn などで頑張って解析
    • pros: ちゃんとできるのがうれしい、ユーザ側が気にせず使える
    • cons: 実装も保守も多分めちゃくちゃしんどい。
  2. [using static ディレクティブ] https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/using-static で使うライブラリのクラス名を明示させる(そういう用途のものではないが…)
    • pros: コード中に使うライブラリのクラスを明示できる(し、コード書く時の静的解析にもかかる)
    • cons: クラス名からファイル名は追跡できないのでそこのお世話をしないといけない。あとコードスニペットには対処不能(それは csx でやればいいけど)
  3. #load filepath をごまかして使う
    • pros: ほぼ何もしないのでコストが低い
    • cons:ファイル名や依存関係に対するユーザ側の管理コストがかかる

camypaper avatar May 07 '20 00:05 camypaper

現状の判定条件が行頭に #load がある程度のゆるさなので

これ、実はdotnet scriptでの実装をほぼそのまま取ってきてます(loadディレクティブとかはifディレクティブの影響を受けないので、実はこれでもロードされる)

//hoge.csx
#if HOGE
/*
#load "fuga.csx"
*/
#endif
//fuga.csx
System.Console.WriteLine("fuga");

C# scriptの理想的な使い方/依存関係の解決法は(たぶん)#load filepathでのロードなので、usingでの解決やroslynに突っ込むといったことは(scriptでない)C#プロジェクトに対応する方で行うべきなので、いい加減やります。(テストもテストプロジェクトを作ってテストを書くことでいい感じになって欲しいと思っていますが、少し煩雑なのでたしかに共存可能だと嬉しいかもしれない)

それとは別に、RoslynでのC# scriptのパースは1ファイルしか受け付けられない仕様になっているので、同一の解析器に突っ込むことはできなさそうです。なので、共存させる実装はかなり煩雑になりそうだなあという予測があります。

key-moon avatar May 08 '20 16:05 key-moon

拙作のライブラリ https://github.com/kzrnm/SourceExpander で Roslyn による依存関係の解決を実現しているので、これを使用して実装できるかと思います。

私の方で実装してみようと思うので、完成したら Pull request を送ってみます。

kzrnm avatar Mar 13 '22 16:03 kzrnm