online-judge-tools / verification-helper

a testing framework for snippet libraries used in competitive programming
MIT License
227 stars 54 forks source link

C# 対応 #115

Open kmyk opened 4 years ago

kmyk commented 4 years ago

親 issue: #116

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

kmyk commented 4 years ago

@riantkb @key-moon @cannorin

cannorin commented 4 years ago

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

key-moon commented 4 years ago

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

cannorin commented 4 years ago

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

kmyk commented 4 years ago

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

key-moon commented 4 years ago

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

メリット

デメリット

くらいでしょうか

riantkb commented 4 years ago

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

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

key-moon commented 4 years ago

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

key-moon commented 4 years ago

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ディレクティブを使うのが最適かな、と思っているのですが、他に良い方法があれば教えて下さい。

kmyk commented 4 years ago

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

例:

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

cc: @camypaper

camypaper commented 4 years ago

現状の判定条件が行頭に #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 の解析を真面目にするのはしんどい割に労力に見合わなさそうという気もしています。

kmyk commented 4 years ago

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

camypaper commented 4 years ago

現状 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:ファイル名や依存関係に対するユーザ側の管理コストがかかる
key-moon commented 4 years ago

現状の判定条件が行頭に #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ファイルしか受け付けられない仕様になっているので、同一の解析器に突っ込むことはできなさそうです。なので、共存させる実装はかなり煩雑になりそうだなあという予測があります。

kzrnm commented 2 years ago

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

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