私は Delphi 側を少し違った方法で実装しますが (以下を参照)、それを除けば、あなたのソリューションは正しいように見えます。
お気づきのように、奇妙な点は、DWScript が静的セットを配列として表すことです。ただし、これはコンパイラ フロントエンドの単なる制限であり、いつか解決されることを願っています。DWScript の問題 #10: 静的配列からセットへの暗黙的なキャストを改善する を参照してください。
次のスクリプトは、コンパイラがセットと配列の間で暗黙的なキャストを実行する場合を示しています。
type
TMyEnum = (meOne, meTwo);
type
TMySet = set of TMyEnum;
type
TMyArray = array of TMyEnum;
procedure TestSet(MySet: TMySet);
begin
ShowMessage(integer(MySet).toString);
end;
procedure TestArray(MyArray: TMyArray);
var
MySet: TMySet;
begin
MySet := [];
for var i := 0 to MyArray.Length-1 do
Include(MySet, MyArray[i]);
ShowMessage(integer(MySet).toString);
end;
begin
TestSet([]);
TestArray([]);
TestSet([meOne]);
TestArray([meOne]);
TestSet([meOne, meTwo]);
TestArray([meOne, meTwo]);
var VarSet: TMySet = [meOne, meTwo];
TestSet(VarSet);
// Syntax Error: Argument 0 expects type "array of TMyEnum" instead of "TMySet"
// TestArray(VarSet);
var VarArray: TMyArray = [meOne, meTwo];
TestArray(VarArray);
// Syntax Error: Argument 0 expects type "array of TMyEnum" instead of "TMySet"
// TestArray(VarSet);
// Syntax Error: Incompatible types: "TMySet" and "array [0..1] of TMyEnum" const ConstSet: TMySet = [meOne, meTwo];
// const ConstSet: TMySet = [meOne, meTwo];
// TestSet(ConstSet);
// TestArray(ConstSet);
// Syntax Error: Incompatible types: "array of TMyEnum" and "array [0..1] of TMyEnum"
// const ConstArray: TMyArray = [meOne, meTwo];
// TestSet(ConstArray);
// TestArray(ConstArray);
end;
上記は純粋にスクリプト側の実装です。Delphi 側の実装をミックスに追加すると、問題が発生する可能性があります。
MessageDlg関数の単純化された実装を検討してください。
Delphi 側の宣言 (TdwsUnit 経由):
type
TMsgDlgBtn = (mbYes, mbNo, mbOK, mbCancel, etc...);
TMsgDlgButtons = set of TMsgDlgBtn;
function MessageDlg(const Msg: string; Buttons: TMsgDlgButtons): integer;
Delphi 側の実装:
Info.ResultAsInteger := MessageDlg(Info.ParamAsString[0], mtInformation, TMsgDlgButtons(Word(Info.ParamAsInteger[1])), -1);
スクリプト側の使用法:
begin
// Implicit cast from array to set fails:
// Syntax Error: There is no overloaded version of "MessageDlg" that can be called with these arguments
// MessageDlg('Test', [mbOK]);
var Buttons: TMsgDlgButtons = [mbOK];
MessageDlg('Test', Buttons);
end;
代わりに、セットパラメーターを配列として宣言するソリューションで同じことを試してみましょう。
Delphi 側の宣言 (TdwsUnit 経由):
type
TMsgDlgBtn = (mbYes, mbNo, mbOK, mbCancel, etc...);
TMsgDlgButtons = array of TMsgDlgBtn;
function MessageDlg(const Msg: string; Buttons: TMsgDlgButtons): integer;
Delphi 側の実装:
var
Buttons: TMsgDlgButtons;
i: integer;
ButtonArray: IScriptDynArray;
begin
ButtonArray := Info.Params[1].ScriptDynArray;
Buttons := [];
for i := 0 to ButtonArray.ArrayLength-1 do
Include(Buttons, TMsgDlgBtn(ButtonArray.AsInteger[i]));
Info.ResultAsInteger := MessageDlgEx(Info.ParamAsString[0], mtInformation, Buttons, -1);
end;
スクリプト側の使用法:
begin
MessageDlg('Test', [mbOK]);
var Buttons: TMsgDlgButtons = [mbOK];
// Note that an implicit cast from set to array is performed
MessageDlg('Test', Buttons);
end;
DWScriptの私自身のブランチでは、列挙値の配列からセットへの暗黙的なキャストを実行するようにコンパイラを変更しました。これは見事に機能し、他の方法では失敗する上記のすべてのケースを解決します。