Мне нужно генерировать несколько bools одновременно - PullRequest
0 голосов
/ 08 января 2019

у меня есть:

struct MyStruct {
     !Ipv4En : bool;
     !Ipv6En : bool;
     keep Ipv4En == TRUE or Ipv6En == TRUE;

     MyMethod() is {
         gen Ipv4En;
         gen Ipv6En;
     };
 };

Я всегда получаю Ipv4En TRUE, потому что эти 2 bools не генерируются вместе. Они не могут быть созданы, когда я генерирую MyStruct. Как я могу сгенерировать их вместе?

Тем временем я исправил это (не нравится решение): Я удалил! в определении.

temp : MyStruct;
gen temp;

Ipv4En = temp.Ipv4En;
Ipv6En = temp.Ipv6En;

1 Ответ

0 голосов
/ 09 января 2019

Поскольку для действия gen требуется только один gen-item, необходимо сгруппировать две переменные, которые вы хотите решить вместе. Вы можете сделать это, определив новый struct:

struct IpVersionInfo {
  Ipv4En: bool;
  Ipv6En: bool;

  keep Ipv4En == TRUE or Ipv6En == TRUE;
};

Вместо двух переменных для включений вы используете одну переменную этого нового struct типа:

struct MyStruct {
    !ipVersionInfo: IpVersionInfo;

    MyMethod() is {
        gen ipVersionInfo;
    };
};

Если вы выполните пару итераций, вы увидите, что можете достичь всех комбинаций:

extend sys {

    run() is also {
        for i from 1 to 20 {
            var s: MyStruct = new;
            s.MyMethod();
            outf(
                    "Ipv4En = %s, Ipv6En = %s\n",
                    s.ipVersionInfo.Ipv4En,
                    s.ipVersionInfo.Ipv6En);
        };
    };

};

Это требует изменения API, поэтому вам нужно обновить весь код, на который ссылаются Ipv4En и Ipv6En.

Помимо группировки двух полей в struct, есть и другие способы решения вашей проблемы. Другим примером может быть определение enum, которое содержит значения для ваших юридических случаев:

type ip_version_info_e: [ V4, V6, BOTH ];

Как и раньше, вы можете использовать переменную этого типа в вашем struct:

struct MyStruct {
    !ip_version_info: ip_version_info_e;

    MyMethod() is {
        gen ip_version_info;
    };
};

Если вы выполните пару итераций нового кода, вы увидите, что он также достигает всех возможных комбинаций:

extend sys {

    run() is also {
        for i from 1 to 20 {
            var s: MyStruct = new;
            s.MyMethod();
            outf(
                    "Ipv4En = %s, Ipv6En = %s\n",
                    s.ip_version_info in [ V4, BOTH ],
                    s.ip_version_info in [ V6, BOTH ]);
        };
    };

};

Независимо от того, как вы решили решить проблему, вы должны скрывать внутреннюю реализацию от любого клиентского кода, который использует MyStruct. Обратите внимание, что операторы out сверху выглядят по-разному в зависимости от того, как мы решили обрабатывать настройки IP-версии. Вместо того, чтобы клиентский код заглядывал слишком глубоко внутрь MyStruct, вы должны определить следующие два метода:

isIpv4Enabled(): bool;
isIpv6Enabled(): bool;

В случае, когда мы сгруппировали две логические переменные в struct, реализации этих двух методов:

struct MyStruct {
    // ...

    isIpv4Enabled(): bool is {
        result = ipVersionInfo.Ipv4En;
    };

    isIpv6Enabled(): bool is {
        result = ipVersionInfo.Ipv6En;
    };
};

В случае, когда мы определили enum, мы имеем:

struct MyStruct {
    // ...

    isIpv4Enabled(): bool is {
        result = ip_version_info in [ V4, BOTH ];
    };

    isIpv6Enabled(): bool is {
        result = ip_version_info in [ V6, BOTH ];
    };
};

В обоих случаях клиентский код для печати будет одинаковым:

extend sys {

    run() is also {
        for i from 1 to 20 {
            var s: MyStruct = new;
            s.MyMethod();
            outf(
                    "Ipv4En = %s, Ipv6En = %s\n",
                    s.isIpv4Enabled(),
                    s.isIpv4Enabled());
        };
    };

};

Это главное преимущество. Таким образом, вы можете в будущем изменить реализацию MyStruct и не трогать какой-либо другой код, который ее использует.

...