aas-core-codegen 0.0.16__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (604) hide show
  1. aas_core_codegen/__init__.py +6 -0
  2. aas_core_codegen/__main__.py +8 -0
  3. aas_core_codegen/common.py +500 -0
  4. aas_core_codegen/cpp/__init__.py +1 -0
  5. aas_core_codegen/cpp/aas_common/__init__.py +6 -0
  6. aas_core_codegen/cpp/aas_common/_generate.py +713 -0
  7. aas_core_codegen/cpp/common.py +681 -0
  8. aas_core_codegen/cpp/constants/__init__.py +6 -0
  9. aas_core_codegen/cpp/constants/_generate.py +568 -0
  10. aas_core_codegen/cpp/description.py +654 -0
  11. aas_core_codegen/cpp/enhancing/__init__.py +4 -0
  12. aas_core_codegen/cpp/enhancing/_generate.py +993 -0
  13. aas_core_codegen/cpp/iteration/__init__.py +6 -0
  14. aas_core_codegen/cpp/iteration/_generate.py +2332 -0
  15. aas_core_codegen/cpp/jsonization/__init__.py +6 -0
  16. aas_core_codegen/cpp/jsonization/_generate.py +2619 -0
  17. aas_core_codegen/cpp/main.py +694 -0
  18. aas_core_codegen/cpp/naming.py +170 -0
  19. aas_core_codegen/cpp/optionaling.py +557 -0
  20. aas_core_codegen/cpp/pattern/__init__.py +6 -0
  21. aas_core_codegen/cpp/pattern/_generate.py +508 -0
  22. aas_core_codegen/cpp/revm/__init__.py +6 -0
  23. aas_core_codegen/cpp/revm/_generate.py +1149 -0
  24. aas_core_codegen/cpp/stringification/__init__.py +5 -0
  25. aas_core_codegen/cpp/stringification/_generate.py +955 -0
  26. aas_core_codegen/cpp/structure/__init__.py +7 -0
  27. aas_core_codegen/cpp/structure/_generate.py +1503 -0
  28. aas_core_codegen/cpp/transpilation.py +1383 -0
  29. aas_core_codegen/cpp/unrolling.py +159 -0
  30. aas_core_codegen/cpp/verification/__init__.py +6 -0
  31. aas_core_codegen/cpp/verification/_generate.py +3073 -0
  32. aas_core_codegen/cpp/visitation/__init__.py +6 -0
  33. aas_core_codegen/cpp/visitation/_generate.py +521 -0
  34. aas_core_codegen/cpp/wstringification/__init__.py +5 -0
  35. aas_core_codegen/cpp/wstringification/_generate.py +586 -0
  36. aas_core_codegen/cpp/xmlization/__init__.py +6 -0
  37. aas_core_codegen/cpp/xmlization/_generate.py +5373 -0
  38. aas_core_codegen/cpp/yielding.py +201 -0
  39. aas_core_codegen/csharp/__init__.py +1 -0
  40. aas_core_codegen/csharp/common.py +224 -0
  41. aas_core_codegen/csharp/constants/__init__.py +5 -0
  42. aas_core_codegen/csharp/constants/_generate.py +409 -0
  43. aas_core_codegen/csharp/copying/__init__.py +4 -0
  44. aas_core_codegen/csharp/copying/_generate.py +498 -0
  45. aas_core_codegen/csharp/description.py +1103 -0
  46. aas_core_codegen/csharp/enhancing/__init__.py +4 -0
  47. aas_core_codegen/csharp/enhancing/_generate.py +667 -0
  48. aas_core_codegen/csharp/jsonization/__init__.py +4 -0
  49. aas_core_codegen/csharp/jsonization/_generate.py +1630 -0
  50. aas_core_codegen/csharp/main.py +421 -0
  51. aas_core_codegen/csharp/naming.py +157 -0
  52. aas_core_codegen/csharp/reporting/__init__.py +4 -0
  53. aas_core_codegen/csharp/reporting/_generate.py +266 -0
  54. aas_core_codegen/csharp/stringification/__init__.py +4 -0
  55. aas_core_codegen/csharp/stringification/_generate.py +243 -0
  56. aas_core_codegen/csharp/structure/__init__.py +6 -0
  57. aas_core_codegen/csharp/structure/_generate.py +1341 -0
  58. aas_core_codegen/csharp/transpilation.py +990 -0
  59. aas_core_codegen/csharp/unrolling.py +211 -0
  60. aas_core_codegen/csharp/verification/__init__.py +6 -0
  61. aas_core_codegen/csharp/verification/_generate.py +1457 -0
  62. aas_core_codegen/csharp/visitation/__init__.py +5 -0
  63. aas_core_codegen/csharp/visitation/_generate.py +579 -0
  64. aas_core_codegen/csharp/xmlization/__init__.py +4 -0
  65. aas_core_codegen/csharp/xmlization/_generate.py +1980 -0
  66. aas_core_codegen/golang/__init__.py +1 -0
  67. aas_core_codegen/golang/aas_common/__init__.py +4 -0
  68. aas_core_codegen/golang/aas_common/_generate.py +152 -0
  69. aas_core_codegen/golang/common.py +303 -0
  70. aas_core_codegen/golang/constants/__init__.py +5 -0
  71. aas_core_codegen/golang/constants/_generate.py +339 -0
  72. aas_core_codegen/golang/description.py +501 -0
  73. aas_core_codegen/golang/enhancing/__init__.py +4 -0
  74. aas_core_codegen/golang/enhancing/_generate.py +527 -0
  75. aas_core_codegen/golang/jsonization/__init__.py +4 -0
  76. aas_core_codegen/golang/jsonization/_generate.py +1740 -0
  77. aas_core_codegen/golang/main.py +368 -0
  78. aas_core_codegen/golang/naming.py +412 -0
  79. aas_core_codegen/golang/pointering.py +631 -0
  80. aas_core_codegen/golang/reporting/__init__.py +4 -0
  81. aas_core_codegen/golang/reporting/_generate.py +218 -0
  82. aas_core_codegen/golang/stringification/__init__.py +4 -0
  83. aas_core_codegen/golang/stringification/_generate.py +394 -0
  84. aas_core_codegen/golang/structure/__init__.py +6 -0
  85. aas_core_codegen/golang/structure/_generate.py +1493 -0
  86. aas_core_codegen/golang/transpilation.py +1191 -0
  87. aas_core_codegen/golang/unrolling.py +159 -0
  88. aas_core_codegen/golang/verification/__init__.py +6 -0
  89. aas_core_codegen/golang/verification/_generate.py +1513 -0
  90. aas_core_codegen/golang/xmlization/__init__.py +4 -0
  91. aas_core_codegen/golang/xmlization/_generate.py +2507 -0
  92. aas_core_codegen/infer_for_schema/__init__.py +21 -0
  93. aas_core_codegen/infer_for_schema/_inline.py +693 -0
  94. aas_core_codegen/infer_for_schema/_len.py +527 -0
  95. aas_core_codegen/infer_for_schema/_pattern.py +311 -0
  96. aas_core_codegen/infer_for_schema/_set.py +394 -0
  97. aas_core_codegen/infer_for_schema/_stringify.py +201 -0
  98. aas_core_codegen/infer_for_schema/_types.py +135 -0
  99. aas_core_codegen/infer_for_schema/match.py +122 -0
  100. aas_core_codegen/intermediate/__init__.py +78 -0
  101. aas_core_codegen/intermediate/_hierarchy.py +397 -0
  102. aas_core_codegen/intermediate/_stringify.py +989 -0
  103. aas_core_codegen/intermediate/_translate.py +5128 -0
  104. aas_core_codegen/intermediate/_types.py +2901 -0
  105. aas_core_codegen/intermediate/construction.py +750 -0
  106. aas_core_codegen/intermediate/doc.py +344 -0
  107. aas_core_codegen/intermediate/pattern_verification.py +428 -0
  108. aas_core_codegen/intermediate/revm.py +985 -0
  109. aas_core_codegen/intermediate/type_inference.py +2266 -0
  110. aas_core_codegen/java/__init__.py +1 -0
  111. aas_core_codegen/java/common.py +197 -0
  112. aas_core_codegen/java/constants/__init__.py +5 -0
  113. aas_core_codegen/java/constants/_generate.py +334 -0
  114. aas_core_codegen/java/copying/__init__.py +4 -0
  115. aas_core_codegen/java/copying/_generate.py +502 -0
  116. aas_core_codegen/java/description.py +774 -0
  117. aas_core_codegen/java/enhancing/__init__.py +4 -0
  118. aas_core_codegen/java/enhancing/_generate.py +820 -0
  119. aas_core_codegen/java/generation/__init__.py +5 -0
  120. aas_core_codegen/java/generation/_generate.py +285 -0
  121. aas_core_codegen/java/jsonization/__init__.py +4 -0
  122. aas_core_codegen/java/jsonization/_generate.py +1472 -0
  123. aas_core_codegen/java/main.py +438 -0
  124. aas_core_codegen/java/naming.py +187 -0
  125. aas_core_codegen/java/optional.py +514 -0
  126. aas_core_codegen/java/reporting/__init__.py +4 -0
  127. aas_core_codegen/java/reporting/_generate.py +248 -0
  128. aas_core_codegen/java/stringification/__init__.py +4 -0
  129. aas_core_codegen/java/stringification/_generate.py +212 -0
  130. aas_core_codegen/java/structure/__init__.py +6 -0
  131. aas_core_codegen/java/structure/_generate.py +1767 -0
  132. aas_core_codegen/java/transpilation.py +1111 -0
  133. aas_core_codegen/java/verification/__init__.py +6 -0
  134. aas_core_codegen/java/verification/_generate.py +1536 -0
  135. aas_core_codegen/java/visitation/__init__.py +5 -0
  136. aas_core_codegen/java/visitation/_generate.py +689 -0
  137. aas_core_codegen/java/xmlization/__init__.py +4 -0
  138. aas_core_codegen/java/xmlization/_generate.py +2274 -0
  139. aas_core_codegen/jsonld/__init__.py +1 -0
  140. aas_core_codegen/jsonld/main.py +455 -0
  141. aas_core_codegen/jsonschema/__init__.py +1 -0
  142. aas_core_codegen/jsonschema/main.py +982 -0
  143. aas_core_codegen/main.py +245 -0
  144. aas_core_codegen/naming.py +133 -0
  145. aas_core_codegen/opcua/__init__.py +1 -0
  146. aas_core_codegen/opcua/main.py +1525 -0
  147. aas_core_codegen/opcua/naming.py +126 -0
  148. aas_core_codegen/parse/__init__.py +46 -0
  149. aas_core_codegen/parse/_rules.py +796 -0
  150. aas_core_codegen/parse/_stringify.py +532 -0
  151. aas_core_codegen/parse/_translate.py +3940 -0
  152. aas_core_codegen/parse/_types.py +973 -0
  153. aas_core_codegen/parse/retree/__init__.py +46 -0
  154. aas_core_codegen/parse/retree/_fix.py +434 -0
  155. aas_core_codegen/parse/retree/_parse.py +1143 -0
  156. aas_core_codegen/parse/retree/_render.py +298 -0
  157. aas_core_codegen/parse/retree/_stringify.py +199 -0
  158. aas_core_codegen/parse/retree/_types.py +362 -0
  159. aas_core_codegen/parse/retree/_visitor.py +70 -0
  160. aas_core_codegen/parse/tree.py +1303 -0
  161. aas_core_codegen/protobuf/__init__.py +1 -0
  162. aas_core_codegen/protobuf/common.py +225 -0
  163. aas_core_codegen/protobuf/description.py +1102 -0
  164. aas_core_codegen/protobuf/main.py +115 -0
  165. aas_core_codegen/protobuf/naming.py +143 -0
  166. aas_core_codegen/protobuf/structure/__init__.py +6 -0
  167. aas_core_codegen/protobuf/structure/_generate.py +502 -0
  168. aas_core_codegen/py.typed +1 -0
  169. aas_core_codegen/python/__init__.py +1 -0
  170. aas_core_codegen/python/aas_common/__init__.py +4 -0
  171. aas_core_codegen/python/aas_common/_generate.py +63 -0
  172. aas_core_codegen/python/common.py +406 -0
  173. aas_core_codegen/python/constants/__init__.py +5 -0
  174. aas_core_codegen/python/constants/_generate.py +377 -0
  175. aas_core_codegen/python/description.py +508 -0
  176. aas_core_codegen/python/jsonization/__init__.py +4 -0
  177. aas_core_codegen/python/jsonization/_generate.py +1391 -0
  178. aas_core_codegen/python/main.py +323 -0
  179. aas_core_codegen/python/naming.py +255 -0
  180. aas_core_codegen/python/stringification/__init__.py +4 -0
  181. aas_core_codegen/python/stringification/_generate.py +129 -0
  182. aas_core_codegen/python/structure/__init__.py +6 -0
  183. aas_core_codegen/python/structure/_generate.py +1801 -0
  184. aas_core_codegen/python/transpilation.py +958 -0
  185. aas_core_codegen/python/unrolling.py +156 -0
  186. aas_core_codegen/python/verification/__init__.py +6 -0
  187. aas_core_codegen/python/verification/_generate.py +1471 -0
  188. aas_core_codegen/python/xmlization/__init__.py +4 -0
  189. aas_core_codegen/python/xmlization/_generate.py +3003 -0
  190. aas_core_codegen/python_protobuf/__init__.py +1 -0
  191. aas_core_codegen/python_protobuf/main.py +1424 -0
  192. aas_core_codegen/python_protobuf/naming.py +85 -0
  193. aas_core_codegen/rdf_shacl/__init__.py +1 -0
  194. aas_core_codegen/rdf_shacl/_description.py +351 -0
  195. aas_core_codegen/rdf_shacl/common.py +206 -0
  196. aas_core_codegen/rdf_shacl/main.py +114 -0
  197. aas_core_codegen/rdf_shacl/naming.py +145 -0
  198. aas_core_codegen/rdf_shacl/rdf.py +435 -0
  199. aas_core_codegen/rdf_shacl/shacl.py +453 -0
  200. aas_core_codegen/run.py +124 -0
  201. aas_core_codegen/smoke/__init__.py +1 -0
  202. aas_core_codegen/smoke/main.py +219 -0
  203. aas_core_codegen/specific_implementations.py +72 -0
  204. aas_core_codegen/stringify.py +333 -0
  205. aas_core_codegen/typescript/__init__.py +1 -0
  206. aas_core_codegen/typescript/aas_common/__init__.py +4 -0
  207. aas_core_codegen/typescript/aas_common/_generate.py +472 -0
  208. aas_core_codegen/typescript/common.py +340 -0
  209. aas_core_codegen/typescript/constants/__init__.py +5 -0
  210. aas_core_codegen/typescript/constants/_generate.py +347 -0
  211. aas_core_codegen/typescript/description.py +530 -0
  212. aas_core_codegen/typescript/jsonization/__init__.py +4 -0
  213. aas_core_codegen/typescript/jsonization/_generate.py +1510 -0
  214. aas_core_codegen/typescript/main.py +258 -0
  215. aas_core_codegen/typescript/naming.py +189 -0
  216. aas_core_codegen/typescript/stringification/__init__.py +4 -0
  217. aas_core_codegen/typescript/stringification/_generate.py +367 -0
  218. aas_core_codegen/typescript/structure/__init__.py +6 -0
  219. aas_core_codegen/typescript/structure/_generate.py +2500 -0
  220. aas_core_codegen/typescript/transpilation.py +1051 -0
  221. aas_core_codegen/typescript/unrolling.py +159 -0
  222. aas_core_codegen/typescript/verification/__init__.py +6 -0
  223. aas_core_codegen/typescript/verification/_generate.py +1578 -0
  224. aas_core_codegen/xsd/__init__.py +1 -0
  225. aas_core_codegen/xsd/main.py +1187 -0
  226. aas_core_codegen/xsd/naming.py +83 -0
  227. aas_core_codegen/yielding/__init__.py +1 -0
  228. aas_core_codegen/yielding/flow.py +139 -0
  229. aas_core_codegen/yielding/linear.py +754 -0
  230. aas_core_codegen-0.0.16.dist-info/METADATA +211 -0
  231. aas_core_codegen-0.0.16.dist-info/RECORD +604 -0
  232. aas_core_codegen-0.0.16.dist-info/WHEEL +5 -0
  233. aas_core_codegen-0.0.16.dist-info/entry_points.txt +3 -0
  234. aas_core_codegen-0.0.16.dist-info/licenses/AUTHORS +9 -0
  235. aas_core_codegen-0.0.16.dist-info/licenses/LICENSE +23 -0
  236. aas_core_codegen-0.0.16.dist-info/top_level.txt +2 -0
  237. dev/continuous_integration/__init__.py +1 -0
  238. dev/continuous_integration/check_help_in_readme.py +208 -0
  239. dev/continuous_integration/check_init_and_pyproject_consistent.py +154 -0
  240. dev/continuous_integration/precommit.py +400 -0
  241. dev/dev_scripts/__init__.py +1 -0
  242. dev/dev_scripts/compare_rendered_regexes_against_source_py.py +42 -0
  243. dev/dev_scripts/copy_to_aas_core3_cpp.py +100 -0
  244. dev/dev_scripts/copy_to_aas_core3_java.py +90 -0
  245. dev/dev_scripts/download_latest_aas_core_meta_v3.py +114 -0
  246. dev/dev_scripts/draw_bipartite_graph_based_on_lines.py +37 -0
  247. dev/dev_scripts/run_tests_with_rerecord.py +69 -0
  248. dev/dev_scripts/update_to_aas_core_meta.py +174 -0
  249. dev/integration_tests/input/jsonschema/boilerplate/main.py +55 -0
  250. dev/integration_tests/input/meta_model.py +38 -0
  251. dev/integration_tests/input/python/boilerplate/main.py +153 -0
  252. dev/integration_tests/main.py +258 -0
  253. dev/test_data/csharp/test_structure/concrete_class_with_descendants/meta_model.py +15 -0
  254. dev/test_data/csharp/test_structure/constructor_without_arguments/all_properties_optional/meta_model.py +9 -0
  255. dev/test_data/csharp/test_structure/constructor_without_arguments/no_properties/meta_model.py +6 -0
  256. dev/test_data/csharp/test_verification/builtin_functions/len/on_list/meta_model.py +20 -0
  257. dev/test_data/csharp/test_verification/builtin_functions/len/on_str/meta_model.py +16 -0
  258. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/as_prefix/meta_model.py +8 -0
  259. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/as_suffix/meta_model.py +8 -0
  260. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_group_with_quantifier/meta_model.py +8 -0
  261. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_the_middle/meta_model.py +8 -0
  262. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_union/meta_model.py +8 -0
  263. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/single_utf32_literal/meta_model.py +8 -0
  264. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/with_quantifier_within_group/meta_model.py +8 -0
  265. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/with_quantifier_without_group/meta_model.py +8 -0
  266. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/at_the_beginning/meta_model.py +8 -0
  267. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/at_the_end/meta_model.py +8 -0
  268. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/in_the_middle/meta_model.py +8 -0
  269. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/multiple/meta_model.py +8 -0
  270. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/single/meta_model.py +8 -0
  271. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/single_with_quantifier/meta_model.py +8 -0
  272. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/mixed_with_non_utf32/meta_model.py +8 -0
  273. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/more_than_two_high_surrogates/meta_model.py +8 -0
  274. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/multiple_utf32_ranges/meta_model.py +8 -0
  275. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/multiple_utf32_ranges_mixed_with_non_utf32/meta_model.py +8 -0
  276. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/same_high_surrogate/meta_model.py +8 -0
  277. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/same_high_surrogate_with_quantifier/meta_model.py +8 -0
  278. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/two_high_surrogates/meta_model.py +8 -0
  279. dev/test_data/intermediate/expected/class/empty/meta_model.py +6 -0
  280. dev/test_data/intermediate/expected/class/implementation_specific_method/meta_model.py +8 -0
  281. dev/test_data/intermediate/expected/class/inheritance/meta_model.py +41 -0
  282. dev/test_data/intermediate/expected/class/methods_with_contracts/meta_model.py +15 -0
  283. dev/test_data/intermediate/expected/class/only_method_no_property/meta_model.py +7 -0
  284. dev/test_data/intermediate/expected/class/only_property_no_method/meta_model.py +9 -0
  285. dev/test_data/intermediate/expected/constant/constant_set/of_enum/meta_model.py +12 -0
  286. dev/test_data/intermediate/expected/constant/constant_set/of_str/meta_model.py +4 -0
  287. dev/test_data/intermediate/expected/constant/constant_set/with_description/meta_model.py +6 -0
  288. dev/test_data/intermediate/expected/constant/constant_set/with_superset_of/meta_model.py +14 -0
  289. dev/test_data/intermediate/expected/constant/constant_str/only_value/meta_model.py +7 -0
  290. dev/test_data/intermediate/expected/constant/constant_str/with_description/meta_model.py +5 -0
  291. dev/test_data/intermediate/expected/documentation/docstring_with_special_characters_in_literal/meta_model.py +20 -0
  292. dev/test_data/intermediate/expected/documentation/docstring_with_special_characters_outside_literal/meta_model.py +20 -0
  293. dev/test_data/intermediate/expected/empty/meta_model.py +2 -0
  294. dev/test_data/intermediate/expected/enumeration/meta_model.py +9 -0
  295. dev/test_data/intermediate/expected/interface/basic/meta_model.py +14 -0
  296. dev/test_data/intermediate/expected/interface/empty/meta_model.py +7 -0
  297. dev/test_data/intermediate/expected/interface/inheritance/meta_model.py +27 -0
  298. dev/test_data/intermediate/expected/interface/method_signature/meta_model.py +10 -0
  299. dev/test_data/intermediate/expected/interface/only_constructor/meta_model.py +11 -0
  300. dev/test_data/intermediate/expected/method/non_mutating/implementation_specific/meta_model.py +12 -0
  301. dev/test_data/intermediate/expected/method/non_mutating/understood/meta_model.py +11 -0
  302. dev/test_data/intermediate/expected/type_annotation/atomic/meta_model.py +9 -0
  303. dev/test_data/intermediate/expected/type_annotation/subscripted/class/meta_model.py +13 -0
  304. dev/test_data/intermediate/expected/type_annotation/subscripted/primitive/meta_model.py +9 -0
  305. dev/test_data/intermediate/unexpected/constant_set/of_enum/enumeration_literals_in_subset_outside_of_superset/meta_model.py +20 -0
  306. dev/test_data/intermediate/unexpected/constant_set/of_enum/invalid_literal/meta_model.py +11 -0
  307. dev/test_data/intermediate/unexpected/constant_set/of_enum/mismatch_between_enumeration_and_literal/meta_model.py +30 -0
  308. dev/test_data/intermediate/unexpected/constant_set/of_enum/mismatch_in_enumerations_between_subset_and_superset/meta_model.py +21 -0
  309. dev/test_data/intermediate/unexpected/constant_set/of_str/literals_in_subset_outside_of_superset/meta_model.py +18 -0
  310. dev/test_data/intermediate/unexpected/constant_set/of_str/mismatch_between_type_annotation_and_literals/meta_model.py +10 -0
  311. dev/test_data/intermediate/unexpected/constant_set/of_str/superset_and_subset_mismatch_in_type/meta_model.py +12 -0
  312. dev/test_data/intermediate/unexpected/constraints/dangling_constraintref/meta_model.py +18 -0
  313. dev/test_data/intermediate/unexpected/constraints/duplicate_constraints/meta_model.py +20 -0
  314. dev/test_data/intermediate/unexpected/documentation/unexpected_documentation_elements/meta_model.py +34 -0
  315. dev/test_data/intermediate/unexpected/invariant/class_invariant_uses_re/meta_model.py +10 -0
  316. dev/test_data/intermediate/unexpected/invariant/invariant_of_constrained_primitive_uses_re/meta_model.py +7 -0
  317. dev/test_data/intermediate/unexpected/invariant/unexpected_argument_count_to_len/meta_model.py +20 -0
  318. dev/test_data/intermediate/unexpected/invariant/unhandled_built_in_function/meta_model.py +16 -0
  319. dev/test_data/intermediate/unexpected/method_definitions/non_constant_default/meta_model.py +7 -0
  320. dev/test_data/intermediate/unexpected/optional_constructor_arguments_wo_default/default_non_none/meta_model.py +16 -0
  321. dev/test_data/intermediate/unexpected/optional_constructor_arguments_wo_default/no_default/meta_model.py +16 -0
  322. dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/after_inheritance/meta_model.py +58 -0
  323. dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/type_missmatch/meta_model.py +9 -0
  324. dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/within_class/meta_model.py +22 -0
  325. dev/test_data/jsonschema/test_main/regression_when_len_constraints_on_inherited_property/meta_model.py +28 -0
  326. dev/test_data/opcua/test_main/abstract_and_concrete_classes/meta_model.py +37 -0
  327. dev/test_data/opcua/test_main/classes_with_invariants/meta_model.py +21 -0
  328. dev/test_data/opcua/test_main/concrete_class_with_descendant/meta_model.py +27 -0
  329. dev/test_data/opcua/test_main/concrete_class_with_enum/meta_model.py +21 -0
  330. dev/test_data/opcua/test_main/concrete_class_with_list_of_instances/meta_model.py +21 -0
  331. dev/test_data/opcua/test_main/concrete_class_with_primitive_attributes/meta_model.py +41 -0
  332. dev/test_data/opcua/test_main/concrete_class_with_string/meta_model.py +13 -0
  333. dev/test_data/opcua/test_main/constrained_primitive/meta_model.py +20 -0
  334. dev/test_data/opcua/test_main/multiple_inheritance/meta_model.py +25 -0
  335. dev/test_data/parse/expected/constant/constant_set/of_enum/meta_model.py +12 -0
  336. dev/test_data/parse/expected/constant/constant_set/of_str/meta_model.py +4 -0
  337. dev/test_data/parse/expected/constant/constant_set/with_description/meta_model.py +6 -0
  338. dev/test_data/parse/expected/constant/constant_set/with_superset_of/meta_model.py +14 -0
  339. dev/test_data/parse/expected/constant/constant_str/only_value/meta_model.py +7 -0
  340. dev/test_data/parse/expected/constant/constant_str/with_description/meta_model.py +5 -0
  341. dev/test_data/parse/expected/enum/ok/meta_model.py +15 -0
  342. dev/test_data/parse/expected/implementation_specific_class/properties_and_methods_in_implementation_specific_class/meta_model.py +17 -0
  343. dev/test_data/parse/expected/inheritance/basic/meta_model.py +11 -0
  344. dev/test_data/parse/expected/inheritance/diamond/meta_model.py +26 -0
  345. dev/test_data/parse/expected/inheritance/inheritance_from_concrete_class/meta_model.py +10 -0
  346. dev/test_data/parse/expected/invariants/in_relation/meta_model.py +16 -0
  347. dev/test_data/parse/expected/method/arguments/meta_model.py +7 -0
  348. dev/test_data/parse/expected/method/basic/meta_model.py +7 -0
  349. dev/test_data/parse/expected/method/contracts/condition_as_keyword_argument/meta_model.py +8 -0
  350. dev/test_data/parse/expected/method/contracts/condition_as_positional_argument/meta_model.py +8 -0
  351. dev/test_data/parse/expected/method/contracts/description_as_keyword_argument/meta_model.py +8 -0
  352. dev/test_data/parse/expected/method/contracts/description_as_positional_argument/meta_model.py +8 -0
  353. dev/test_data/parse/expected/method/contracts/multiple_contracts_in_order/meta_model.py +17 -0
  354. dev/test_data/parse/expected/method/contracts/postcondition/basic/meta_model.py +10 -0
  355. dev/test_data/parse/expected/method/contracts/postcondition/snapshot/with_keyword_arguments/meta_model.py +9 -0
  356. dev/test_data/parse/expected/method/contracts/postcondition/snapshot/with_positional_arguments/meta_model.py +9 -0
  357. dev/test_data/parse/expected/method/default/meta_model.py +9 -0
  358. dev/test_data/parse/expected/method/description/meta_model.py +8 -0
  359. dev/test_data/parse/expected/method/is_implementation_specific/meta_model.py +8 -0
  360. dev/test_data/parse/expected/method/non_mutating/meta_model.py +11 -0
  361. dev/test_data/parse/expected/method/returns_none/meta_model.py +7 -0
  362. dev/test_data/parse/expected/method/returns_something/meta_model.py +7 -0
  363. dev/test_data/parse/expected/single_class/description/meta_model.py +12 -0
  364. dev/test_data/parse/expected/single_class/empty/meta_model.py +6 -0
  365. dev/test_data/parse/expected/single_class/property/description/meta_model.py +14 -0
  366. dev/test_data/parse/expected/single_class/property/mandatory/meta_model.py +6 -0
  367. dev/test_data/parse/expected/single_class/property/optional/meta_model.py +6 -0
  368. dev/test_data/parse/expected/single_class/property/recursion_to_entity/meta_model.py +6 -0
  369. dev/test_data/parse/unexpected/class_decorators/non_name_decorator/meta_model.py +7 -0
  370. dev/test_data/parse/unexpected/class_decorators/unknown_decorator/meta_model.py +7 -0
  371. dev/test_data/parse/unexpected/class_definitions/is_abstract_and_implementation_specific/meta_model.py +8 -0
  372. dev/test_data/parse/unexpected/class_definitions/unexpected_docstring_before_a_method/meta_model.py +11 -0
  373. dev/test_data/parse/unexpected/class_definitions/unexpected_docstring_for_a_pass/meta_model.py +9 -0
  374. dev/test_data/parse/unexpected/class_definitions/unexpected_double_description_for_a_property/meta_model.py +10 -0
  375. dev/test_data/parse/unexpected/class_inheritances/inheriting_from_implementation_specific_parent/meta_model.py +20 -0
  376. dev/test_data/parse/unexpected/class_inheritances/non_name_super_class/meta_model.py +6 -0
  377. dev/test_data/parse/unexpected/enum/expression_as_assignment_value/meta_model.py +6 -0
  378. dev/test_data/parse/unexpected/enum/non_assignment/meta_model.py +8 -0
  379. dev/test_data/parse/unexpected/enum/non_string_literal/meta_model.py +6 -0
  380. dev/test_data/parse/unexpected/enum/unexpected_inheritance/meta_model.py +6 -0
  381. dev/test_data/parse/unexpected/method_contracts/contract/non_lambda_condition/meta_model.py +8 -0
  382. dev/test_data/parse/unexpected/method_contracts/contract/non_string_literal_description/meta_model.py +8 -0
  383. dev/test_data/parse/unexpected/method_contracts/contract/without_any_arguments/meta_model.py +8 -0
  384. dev/test_data/parse/unexpected/method_contracts/contract/without_condition/meta_model.py +8 -0
  385. dev/test_data/parse/unexpected/method_contracts/postcondition/OLD_in_postcondition_without_snapshot/meta_model.py +8 -0
  386. dev/test_data/parse/unexpected/method_contracts/postcondition/argument_missing_in_function/meta_model.py +8 -0
  387. dev/test_data/parse/unexpected/method_contracts/precondition/argument_missing_in_function/meta_model.py +8 -0
  388. dev/test_data/parse/unexpected/method_contracts/snapshot/argument_missing_in_function/meta_model.py +8 -0
  389. dev/test_data/parse/unexpected/method_contracts/snapshot/capture_not_a_lambda/meta_model.py +8 -0
  390. dev/test_data/parse/unexpected/method_contracts/snapshot/invalid_name/meta_model.py +8 -0
  391. dev/test_data/parse/unexpected/method_contracts/snapshot/name_not_a_string_literal/meta_model.py +8 -0
  392. dev/test_data/parse/unexpected/method_contracts/snapshot/without_a_capture/meta_model.py +8 -0
  393. dev/test_data/parse/unexpected/method_contracts/snapshot/without_a_name/meta_model.py +8 -0
  394. dev/test_data/parse/unexpected/method_decorators/non_mutating/non_mutating_constructor/meta_model.py +8 -0
  395. dev/test_data/parse/unexpected/method_decorators/non_mutating/non_mutating_verification_function/meta_model.py +8 -0
  396. dev/test_data/parse/unexpected/method_decorators/non_name_decorator/meta_model.py +8 -0
  397. dev/test_data/parse/unexpected/method_decorators/unknown_call_decorator/meta_model.py +8 -0
  398. dev/test_data/parse/unexpected/method_decorators/unknown_name_decorator/meta_model.py +8 -0
  399. dev/test_data/parse/unexpected/method_definitions/argument_with_final/meta_model.py +7 -0
  400. dev/test_data/parse/unexpected/method_definitions/argument_without_a_type_annotation/meta_model.py +7 -0
  401. dev/test_data/parse/unexpected/method_definitions/default_for_self/meta_model.py +7 -0
  402. dev/test_data/parse/unexpected/method_definitions/dunder/meta_model.py +7 -0
  403. dev/test_data/parse/unexpected/method_definitions/init_with_return_type/meta_model.py +7 -0
  404. dev/test_data/parse/unexpected/method_definitions/with_keyword_only_arguments/meta_model.py +7 -0
  405. dev/test_data/parse/unexpected/method_definitions/with_positional_arguments/meta_model.py +7 -0
  406. dev/test_data/parse/unexpected/method_definitions/with_type_annotation_for_self/meta_model.py +7 -0
  407. dev/test_data/parse/unexpected/method_definitions/with_variable_arguments/meta_model.py +7 -0
  408. dev/test_data/parse/unexpected/method_definitions/with_variable_keyword_arguments/meta_model.py +7 -0
  409. dev/test_data/parse/unexpected/method_definitions/without_arguments/meta_model.py +7 -0
  410. dev/test_data/parse/unexpected/method_definitions/without_self/meta_model.py +7 -0
  411. dev/test_data/parse/unexpected/method_definitions/without_type_annotation_for_result/meta_model.py +7 -0
  412. dev/test_data/parse/unexpected/property_definitions/final_without_subscript/meta_model.py +6 -0
  413. dev/test_data/parse/unexpected/property_definitions/nested_final/meta_model.py +6 -0
  414. dev/test_data/parse/unexpected/property_definitions/non_simple/meta_model.py +6 -0
  415. dev/test_data/parse/unexpected/property_definitions/unexpected_assignment/meta_model.py +6 -0
  416. dev/test_data/parse/unexpected/property_definitions/unexpected_non_name_property/meta_model.py +6 -0
  417. dev/test_data/parse/unexpected/property_definitions/without_type_annotation/meta_model.py +6 -0
  418. dev/test_data/parse/unexpected/symbol_table/constant_set_with_a_non_set_subset/meta_model.py +6 -0
  419. dev/test_data/parse/unexpected/symbol_table/dangling_inheritance/meta_model.py +6 -0
  420. dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_a_property/meta_model.py +6 -0
  421. dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_an_argument/meta_model.py +7 -0
  422. dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_constant_set/meta_model.py +6 -0
  423. dev/test_data/parse/unexpected/symbol_table/dangling_subset_in_constant_set/meta_model.py +4 -0
  424. dev/test_data/parse/unexpected/symbol_table/inheritance_from_non_class/meta_model.py +10 -0
  425. dev/test_data/parse_retree/expected/character_set/common_escaping/source.py +1 -0
  426. dev/test_data/parse_retree/expected/character_set/complementing/double_caret/source.py +1 -0
  427. dev/test_data/parse_retree/expected/character_set/complementing/multiple_ranges/source.py +1 -0
  428. dev/test_data/parse_retree/expected/character_set/complementing/suffix_dash/source.py +1 -0
  429. dev/test_data/parse_retree/expected/character_set/escape_first_caret/source.py +1 -0
  430. dev/test_data/parse_retree/expected/character_set/literals_which_need_no_escaping_in_characters_set_but_need_escaping_outside/source.py +1 -0
  431. dev/test_data/parse_retree/expected/character_set/multiple_ranges/source.py +1 -0
  432. dev/test_data/parse_retree/expected/character_set/single_literal/source.py +1 -0
  433. dev/test_data/parse_retree/expected/character_set/single_range/source.py +1 -0
  434. dev/test_data/parse_retree/expected/character_set/unescaped_dash/only_dash/source.py +1 -0
  435. dev/test_data/parse_retree/expected/character_set/unescaped_dash/prefix_dash/source.py +1 -0
  436. dev/test_data/parse_retree/expected/character_set/unescaped_dash/suffix_dash/source.py +1 -0
  437. dev/test_data/parse_retree/expected/dot/source.py +1 -0
  438. dev/test_data/parse_retree/expected/empty/group/source.py +1 -0
  439. dev/test_data/parse_retree/expected/empty/group_in_a_group/source.py +1 -0
  440. dev/test_data/parse_retree/expected/empty/group_of_union_of_empty_concatenations/source.py +1 -0
  441. dev/test_data/parse_retree/expected/empty/regex/source.py +1 -0
  442. dev/test_data/parse_retree/expected/empty/union_of_empty_concatenations/source.py +1 -0
  443. dev/test_data/parse_retree/expected/escaped_literals/source.py +1 -0
  444. dev/test_data/parse_retree/expected/formatted_value/at_the_beginning/source.py +1 -0
  445. dev/test_data/parse_retree/expected/formatted_value/at_the_end/source.py +1 -0
  446. dev/test_data/parse_retree/expected/formatted_value/in_the_middle/source.py +1 -0
  447. dev/test_data/parse_retree/expected/formatted_value/single_formatted_value/source.py +1 -0
  448. dev/test_data/parse_retree/expected/literal/source.py +1 -0
  449. dev/test_data/parse_retree/expected/quantifier/greedy/at_least_3/source.py +1 -0
  450. dev/test_data/parse_retree/expected/quantifier/greedy/at_least_one/source.py +1 -0
  451. dev/test_data/parse_retree/expected/quantifier/greedy/at_most_3/source.py +1 -0
  452. dev/test_data/parse_retree/expected/quantifier/greedy/exactly_3/source.py +1 -0
  453. dev/test_data/parse_retree/expected/quantifier/greedy/maybe/source.py +1 -0
  454. dev/test_data/parse_retree/expected/quantifier/greedy/zero_or_more/source.py +1 -0
  455. dev/test_data/parse_retree/expected/quantifier/non_greedy/at_least_3/source.py +1 -0
  456. dev/test_data/parse_retree/expected/quantifier/non_greedy/at_least_one/source.py +1 -0
  457. dev/test_data/parse_retree/expected/quantifier/non_greedy/at_most_3/source.py +1 -0
  458. dev/test_data/parse_retree/expected/quantifier/non_greedy/exactly_3/source.py +1 -0
  459. dev/test_data/parse_retree/expected/quantifier/non_greedy/maybe/source.py +1 -0
  460. dev/test_data/parse_retree/expected/quantifier/non_greedy/zero_or_more/source.py +1 -0
  461. dev/test_data/parse_retree/expected/quantifier/on_a_character_set/source.py +1 -0
  462. dev/test_data/parse_retree/expected/quantifier/on_a_formatted_value/source.py +1 -0
  463. dev/test_data/parse_retree/expected/quantifier/on_a_group/source.py +1 -0
  464. dev/test_data/parse_retree/expected/quantifier/on_a_literal/source.py +1 -0
  465. dev/test_data/parse_retree/expected/start_and_stop_symbols/double_end_symbol/source.py +1 -0
  466. dev/test_data/parse_retree/expected/start_and_stop_symbols/double_start_symbol/source.py +1 -0
  467. dev/test_data/parse_retree/expected/start_and_stop_symbols/end_symbol_in_the_middle/source.py +1 -0
  468. dev/test_data/parse_retree/expected/start_and_stop_symbols/only_start_symbol/source.py +1 -0
  469. dev/test_data/parse_retree/expected/start_and_stop_symbols/only_stop_symbol/source.py +1 -0
  470. dev/test_data/parse_retree/expected/start_and_stop_symbols/start_symbol_at_the_beginning/source.py +1 -0
  471. dev/test_data/parse_retree/expected/start_and_stop_symbols/start_symbol_in_the_middle/source.py +1 -0
  472. dev/test_data/parse_retree/expected/start_and_stop_symbols/stop_symbol_at_the_end/source.py +1 -0
  473. dev/test_data/parse_retree/expected/union/of_character_sets/source.py +1 -0
  474. dev/test_data/parse_retree/expected/union/of_groups/source.py +1 -0
  475. dev/test_data/parse_retree/expected/union/of_string_literals/source.py +1 -0
  476. dev/test_data/parse_retree/expected/union/within_group/source.py +1 -0
  477. dev/test_data/parse_retree/expected/whitespace/source.py +1 -0
  478. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/Uxxxxxxxx_out_of_range/source.py +1 -0
  479. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/only_backslash/source.py +1 -0
  480. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_Uxxxxxxxx/source.py +1 -0
  481. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_uxxxx/source.py +1 -0
  482. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_x/source.py +1 -0
  483. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unexpected_escaping/source.py +1 -0
  484. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/digit/source.py +1 -0
  485. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_digit/source.py +1 -0
  486. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_whitespace/source.py +1 -0
  487. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_word/source.py +1 -0
  488. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/whitespace/source.py +1 -0
  489. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/word/source.py +1 -0
  490. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/Uxxxxxxxx_out_of_range/source.py +1 -0
  491. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/only_backslash/source.py +1 -0
  492. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_Uxxxxxxxx/source.py +1 -0
  493. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_uxxxx/source.py +1 -0
  494. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_x/source.py +1 -0
  495. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unexpected_escaping/source.py +1 -0
  496. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/digit/source.py +1 -0
  497. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_digit/source.py +1 -0
  498. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_whitespace/source.py +1 -0
  499. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_word/source.py +1 -0
  500. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/whitespace/source.py +1 -0
  501. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/word/source.py +1 -0
  502. dev/test_data/parse_retree/unexpected/invalid_character_range/source.py +1 -0
  503. dev/test_data/parse_retree/unexpected/invalid_quantifier/at_least_x/source.py +1 -0
  504. dev/test_data/parse_retree/unexpected/invalid_quantifier/between_3_and_x/source.py +1 -0
  505. dev/test_data/parse_retree/unexpected/invalid_quantifier/exactly_x/source.py +1 -0
  506. dev/test_data/parse_retree/unexpected/unhandled_group_directives/source.py +1 -0
  507. dev/test_data/parse_retree/unexpected/unterminated/character_set/source.py +1 -0
  508. dev/test_data/parse_retree/unexpected/unterminated/group/source.py +1 -0
  509. dev/test_data/parse_retree/unexpected/unterminated/group_of_union_of_empty_concatenations/source.py +1 -0
  510. dev/test_data/parse_retree/unexpected/unterminated/quantifier/source.py +1 -0
  511. dev/test_data/parse_retree/unexpected/unterminated/quantifier_with_comma/source.py +1 -0
  512. dev/test_data/parse_retree/unexpected/unterminated/quantifier_with_number_and_comma/source.py +1 -0
  513. dev/test_data/proto/test_main/expected/abstract_and_concrete_classes/meta_model.py +37 -0
  514. dev/test_data/proto/test_main/expected/concrete_class_with_descendants/meta_model.py +30 -0
  515. dev/test_data/proto/test_main/expected/concrete_class_with_enum/meta_model.py +21 -0
  516. dev/test_data/proto/test_main/expected/concrete_class_with_list_of_instances/meta_model.py +21 -0
  517. dev/test_data/proto/test_main/expected/concrete_class_with_primitive_attributes/meta_model.py +41 -0
  518. dev/test_data/python_protobuf/test_main/abstract_and_concrete_classes/expected_output/pbization.py +532 -0
  519. dev/test_data/python_protobuf/test_main/abstract_and_concrete_classes/meta_model.py +37 -0
  520. dev/test_data/python_protobuf/test_main/concrete_class_with_descendant/expected_output/pbization.py +527 -0
  521. dev/test_data/python_protobuf/test_main/concrete_class_with_descendant/meta_model.py +27 -0
  522. dev/test_data/python_protobuf/test_main/concrete_class_with_enum/expected_output/pbization.py +290 -0
  523. dev/test_data/python_protobuf/test_main/concrete_class_with_enum/meta_model.py +21 -0
  524. dev/test_data/python_protobuf/test_main/concrete_class_with_list_of_instances/expected_output/pbization.py +328 -0
  525. dev/test_data/python_protobuf/test_main/concrete_class_with_list_of_instances/meta_model.py +23 -0
  526. dev/test_data/python_protobuf/test_main/concrete_class_with_primitive_attributes/expected_output/pbization.py +274 -0
  527. dev/test_data/python_protobuf/test_main/concrete_class_with_primitive_attributes/meta_model.py +41 -0
  528. dev/test_data/rdf_shacl/test_main/expected/regression_when_lang_string_class_is_missing/meta_model.py +29 -0
  529. dev/test_data/rdf_shacl/test_main/expected/regression_when_len_constraints_on_inherited_property/meta_model.py +27 -0
  530. dev/test_data/rdf_shacl/test_main/unexpected/regression_len_constraint_on_class_property/meta_model.py +61 -0
  531. dev/test_data/real_meta_models/aas_core_meta.v3.py +5721 -0
  532. dev/test_data/smoke/test_main/unexpected/infer_for_schema_error/meta_model.py +12 -0
  533. dev/test_data/smoke/test_main/unexpected/intermediate_error/meta_model.py +18 -0
  534. dev/test_data/smoke/test_main/unexpected/parse_error/meta_model.py +5 -0
  535. dev/test_data/smoke/test_main/unexpected/pattern_verification_unparsable_regex/direct_match/meta_model.py +8 -0
  536. dev/test_data/smoke/test_main/unexpected/type_error/meta_model.py +18 -0
  537. dev/tests/__init__.py +1 -0
  538. dev/tests/common.py +197 -0
  539. dev/tests/cpp/__init__.py +0 -0
  540. dev/tests/cpp/test_common.py +32 -0
  541. dev/tests/cpp/test_main.py +144 -0
  542. dev/tests/cpp/test_pattern.py +188 -0
  543. dev/tests/cpp/test_verification.py +189 -0
  544. dev/tests/cpp/test_yielding.py +225 -0
  545. dev/tests/csharp/__init__.py +0 -0
  546. dev/tests/csharp/live_test_main.py +109 -0
  547. dev/tests/csharp/test_common.py +28 -0
  548. dev/tests/csharp/test_description.py +684 -0
  549. dev/tests/csharp/test_main.py +129 -0
  550. dev/tests/csharp/test_structure.py +93 -0
  551. dev/tests/csharp/test_verification.py +82 -0
  552. dev/tests/description.py +29 -0
  553. dev/tests/golang/__init__.py +0 -0
  554. dev/tests/golang/test_common.py +78 -0
  555. dev/tests/golang/test_main.py +128 -0
  556. dev/tests/infer_for_schema/__init__.py +0 -0
  557. dev/tests/infer_for_schema/common.py +47 -0
  558. dev/tests/infer_for_schema/test_len_on_properties.py +955 -0
  559. dev/tests/infer_for_schema/test_len_on_self.py +580 -0
  560. dev/tests/infer_for_schema/test_patterns_on_properties.py +686 -0
  561. dev/tests/infer_for_schema/test_patterns_on_self.py +258 -0
  562. dev/tests/infer_for_schema/test_property_in_set_of_enumeration_literals.py +600 -0
  563. dev/tests/infer_for_schema/test_property_in_set_of_primitives.py +549 -0
  564. dev/tests/intermediate/__init__.py +0 -0
  565. dev/tests/intermediate/test_constructor.py +719 -0
  566. dev/tests/intermediate/test_hierarchy.py +221 -0
  567. dev/tests/intermediate/test_revm.py +134 -0
  568. dev/tests/intermediate/test_translate.py +337 -0
  569. dev/tests/intermediate/test_type_inference.py +333 -0
  570. dev/tests/intermediate/test_types.py +169 -0
  571. dev/tests/java/__init__.py +0 -0
  572. dev/tests/java/test_common.py +20 -0
  573. dev/tests/java/test_description.py +128 -0
  574. dev/tests/java/test_main.py +234 -0
  575. dev/tests/jsonld_context/test_main.py +79 -0
  576. dev/tests/opcua/__init__.py +3 -0
  577. dev/tests/opcua/test_main.py +110 -0
  578. dev/tests/our_jsonschema/__init__.py +3 -0
  579. dev/tests/our_jsonschema/test_main.py +232 -0
  580. dev/tests/parse/__init__.py +0 -0
  581. dev/tests/parse/test_parse.py +503 -0
  582. dev/tests/parse/test_retree.py +272 -0
  583. dev/tests/proto/__init__.py +0 -0
  584. dev/tests/proto/test_main.py +112 -0
  585. dev/tests/python/__init__.py +0 -0
  586. dev/tests/python/test_common.py +124 -0
  587. dev/tests/python/test_main.py +126 -0
  588. dev/tests/python/test_xml_playground.py +254 -0
  589. dev/tests/python_protobuf/__init__.py +0 -0
  590. dev/tests/python_protobuf/test_main.py +111 -0
  591. dev/tests/rdf_shacl/__init__.py +0 -0
  592. dev/tests/rdf_shacl/test_common.py +32 -0
  593. dev/tests/rdf_shacl/test_description.py +223 -0
  594. dev/tests/rdf_shacl/test_main.py +194 -0
  595. dev/tests/smoke/__init__.py +0 -0
  596. dev/tests/smoke/test_main.py +83 -0
  597. dev/tests/test_common.py +94 -0
  598. dev/tests/typescript/__init__.py +0 -0
  599. dev/tests/typescript/test_common.py +108 -0
  600. dev/tests/typescript/test_main.py +125 -0
  601. dev/tests/xsd/__init__.py +0 -0
  602. dev/tests/xsd/test_main.py +227 -0
  603. dev/tests/yielding/__init__.py +0 -0
  604. dev/tests/yielding/test_linear.py +558 -0
@@ -0,0 +1,3073 @@
1
+ """Generate the C++ verification functions."""
2
+ import io
3
+ from typing import (
4
+ Optional,
5
+ List,
6
+ Tuple,
7
+ Union,
8
+ Sequence,
9
+ Mapping,
10
+ Final,
11
+ )
12
+
13
+ from icontract import ensure, require
14
+
15
+ from aas_core_codegen import intermediate
16
+ from aas_core_codegen import specific_implementations
17
+ from aas_core_codegen.common import (
18
+ Error,
19
+ Identifier,
20
+ assert_never,
21
+ Stripped,
22
+ indent_but_first_line,
23
+ wrap_text_into_lines,
24
+ )
25
+ from aas_core_codegen.cpp import (
26
+ common as cpp_common,
27
+ naming as cpp_naming,
28
+ description as cpp_description,
29
+ transpilation as cpp_transpilation,
30
+ optionaling as cpp_optionaling,
31
+ yielding as cpp_yielding,
32
+ )
33
+ from aas_core_codegen.cpp.common import (
34
+ INDENT as I,
35
+ INDENT2 as II,
36
+ INDENT3 as III,
37
+ INDENT4 as IIII,
38
+ )
39
+ from aas_core_codegen.intermediate import type_inference as intermediate_type_inference
40
+ from aas_core_codegen.parse import tree as parse_tree
41
+ from aas_core_codegen.yielding import flow as yielding_flow
42
+
43
+
44
+ # region Generation
45
+
46
+
47
+ @ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
48
+ def _generate_verification_function_definition(
49
+ verification: Union[
50
+ intermediate.ImplementationSpecificVerification,
51
+ intermediate.TranspilableVerification,
52
+ intermediate.PatternVerification,
53
+ ],
54
+ spec_impls: specific_implementations.SpecificImplementations,
55
+ ) -> Tuple[Optional[Stripped], Optional[Error]]:
56
+ """Generate the definition of a verification functions."""
57
+ if isinstance(verification, intermediate.ImplementationSpecificVerification):
58
+ implementation_key = specific_implementations.ImplementationKey(
59
+ f"verification/{verification.name}.hpp"
60
+ )
61
+
62
+ code = spec_impls.get(implementation_key, None)
63
+
64
+ if code is None:
65
+ return None, Error(
66
+ verification.parsed.node,
67
+ f"The header snippet is missing for "
68
+ f"the implementation-specific verification "
69
+ f"function: {implementation_key}",
70
+ )
71
+
72
+ return code, None
73
+
74
+ arg_types_names = [
75
+ (
76
+ cpp_common.generate_type_with_const_ref_if_applicable(
77
+ type_annotation=arg.type_annotation,
78
+ types_namespace=cpp_common.TYPES_NAMESPACE,
79
+ ),
80
+ cpp_naming.argument_name(arg.name),
81
+ )
82
+ for arg in verification.arguments
83
+ ]
84
+
85
+ function_name = cpp_naming.function_name(verification.name)
86
+ arg_definitions_joined = ",\n".join(
87
+ f"{arg_type} {arg_name}" for arg_type, arg_name in arg_types_names
88
+ )
89
+
90
+ blocks = [] # type: List[Stripped]
91
+ if verification.description is not None:
92
+ comment, errors = cpp_description.generate_comment_for_summary_remarks(
93
+ description=verification.description,
94
+ context=cpp_description.Context(
95
+ namespace=cpp_common.VERIFICATION_NAMESPACE, cls_or_enum=None
96
+ ),
97
+ )
98
+ if errors is not None:
99
+ return None, Error(
100
+ verification.parsed.node,
101
+ f"Failed to generate the description for "
102
+ f"verification function {verification.name!r}",
103
+ errors,
104
+ )
105
+ assert comment is not None
106
+ blocks.append(comment)
107
+
108
+ blocks.append(
109
+ Stripped(
110
+ f"""\
111
+ bool {function_name}(
112
+ {I}{indent_but_first_line(arg_definitions_joined, I)}
113
+ );"""
114
+ )
115
+ )
116
+
117
+ return Stripped("\n".join(blocks)), None
118
+
119
+
120
+ def _constrained_primitive_verificator_value_is_pointer(
121
+ primitive_type: intermediate.PrimitiveType,
122
+ ) -> bool:
123
+ """
124
+ Check whether we keep the value of a constrained primitive as a pointer.
125
+
126
+ Values which are cheap to copy such as booleans and integers are copied by value
127
+ in the verificator constructor. On the other hand, primitive types represented as
128
+ STL containers are copied as pointers to avoid unnecessary cost.
129
+
130
+ In many places in code we have to decide how to dereference the value.
131
+ """
132
+ if primitive_type is intermediate.PrimitiveType.BOOL:
133
+ return False
134
+
135
+ elif primitive_type is intermediate.PrimitiveType.INT:
136
+ return False
137
+
138
+ elif primitive_type is intermediate.PrimitiveType.FLOAT:
139
+ return False
140
+
141
+ elif primitive_type is intermediate.PrimitiveType.STR:
142
+ return True
143
+
144
+ elif primitive_type is intermediate.PrimitiveType.BYTEARRAY:
145
+ return True
146
+
147
+ else:
148
+ assert_never(primitive_type)
149
+
150
+
151
+ def _generate_definition_of_verify_constrained_primitive(
152
+ constrained_primitive: intermediate.ConstrainedPrimitive,
153
+ ) -> Stripped:
154
+ """Generate the def. of a verification function for the constrained primitive."""
155
+ verify_name = cpp_naming.function_name(
156
+ Identifier(f"verify_{constrained_primitive.name}")
157
+ )
158
+
159
+ arg_type = cpp_common.generate_primitive_type_with_const_ref_if_applicable(
160
+ constrained_primitive.constrainee
161
+ )
162
+
163
+ arg_name = cpp_naming.argument_name(Identifier("that"))
164
+
165
+ if _constrained_primitive_verificator_value_is_pointer(
166
+ primitive_type=constrained_primitive.constrainee
167
+ ):
168
+ documentation_comment = Stripped(
169
+ """\
170
+ /**
171
+ * \\brief Verify that the invariants hold for \\p that value.
172
+ *
173
+ * The \\p that value should outlive the verification.
174
+ *
175
+ * \\param that value to be verified
176
+ * \\return Iterable over constraint violations
177
+ */"""
178
+ )
179
+ else:
180
+ documentation_comment = Stripped(
181
+ """\
182
+ /**
183
+ * \\brief Verify that the invariants hold for \\p that value.
184
+ *
185
+ * \\param that value to be verified
186
+ * \\return Iterable over constraint violations
187
+ */"""
188
+ )
189
+
190
+ return Stripped(
191
+ f"""\
192
+ {documentation_comment}
193
+ std::unique_ptr<IVerification> {verify_name}(
194
+ {I}{arg_type} {arg_name}
195
+ );"""
196
+ )
197
+
198
+
199
+ # fmt: off
200
+ @ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
201
+ @ensure(
202
+ lambda result:
203
+ not (result[0] is not None) or result[0].endswith('\n'),
204
+ "Trailing newline mandatory for valid end-of-files"
205
+ )
206
+ # fmt: on
207
+ def generate_header(
208
+ symbol_table: intermediate.SymbolTable,
209
+ spec_impls: specific_implementations.SpecificImplementations,
210
+ library_namespace: Stripped,
211
+ ) -> Tuple[Optional[str], Optional[List[Error]]]:
212
+ """Generate the C++ header for the verification code."""
213
+ namespace = Stripped(f"{library_namespace}::verification")
214
+
215
+ include_guard_var = cpp_common.include_guard_var(namespace)
216
+
217
+ include_prefix_path = cpp_common.generate_include_prefix_path(library_namespace)
218
+
219
+ blocks = [
220
+ Stripped(
221
+ f"""\
222
+ #ifndef {include_guard_var}
223
+ #define {include_guard_var}"""
224
+ ),
225
+ cpp_common.WARNING,
226
+ Stripped(
227
+ f"""\
228
+ #include "{include_prefix_path}/common.hpp"
229
+ #include "{include_prefix_path}/iteration.hpp"
230
+ #include "{include_prefix_path}/pattern.hpp"
231
+ #include "{include_prefix_path}/types.hpp"
232
+
233
+ #pragma warning(push, 0)
234
+ #include <set>
235
+ #pragma warning(pop)"""
236
+ ),
237
+ cpp_common.generate_namespace_opening(library_namespace),
238
+ Stripped(
239
+ """\
240
+ /**
241
+ * \\defgroup verification Verify that instances conform to the meta-model constraints.
242
+ * @{
243
+ */
244
+ namespace verification {"""
245
+ ),
246
+ Stripped(
247
+ """\
248
+ // region Forward declarations
249
+ class Iterator;
250
+ class IVerification;
251
+
252
+ namespace impl {
253
+ class IVerificator;
254
+ } // namespace impl
255
+ // endregion Forward declarations"""
256
+ ),
257
+ Stripped(
258
+ f"""\
259
+ /**
260
+ * Represent a verification error in an instance.
261
+ */
262
+ struct Error {{
263
+ {I}/**
264
+ {I} * Human-readable description of the error
265
+ {I} */
266
+ {I}std::wstring cause;
267
+
268
+ {I}/**
269
+ {I} * Path to the erroneous value
270
+ {I} */
271
+ {I}iteration::Path path;
272
+
273
+ {I}explicit Error(std::wstring a_cause);
274
+ {I}Error(std::wstring a_cause, iteration::Path a_path);
275
+ }}; // struct Error"""
276
+ ),
277
+ Stripped(
278
+ f"""\
279
+ /**
280
+ * \\brief Iterate over the verification errors.
281
+ *
282
+ * The user is expected to take ownership of the errors if they need to be further
283
+ * processed.
284
+ *
285
+ * Unlike STL, this is <em>not</em> a light-weight iterator. We implement
286
+ * a "yielding" iterator by leveraging code generation so that we always keep
287
+ * the model stack as well as the properties verified thus far.
288
+ *
289
+ * This means that copy-construction and equality comparisons are much more heavy-weight
290
+ * than you'd usually expect from an STL iterator. For example, if you want to sort
291
+ * the errors by some criterion, you are most probably faster if you populate a vector,
292
+ * and then sort the vector.
293
+ *
294
+ * Also, given that this iterator is not light-weight, you should in almost all cases
295
+ * avoid the postfix increment (it++) and prefer the prefix one (++it) as the postfix
296
+ * increment would create an iterator copy every time.
297
+ *
298
+ * We follow the C++ standard, and assume that comparison between the two iterators
299
+ * over two different collections results in undefined behavior. See
300
+ * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2948.html and
301
+ * https://stackoverflow.com/questions/4657513/comparing-iterators-from-different-containers.
302
+ */
303
+ class Iterator {{
304
+ {I}using iterator_category = std::forward_iterator_tag;
305
+ {I}/// The difference is meaningless, but has to be defined.
306
+ {I}using difference_type = std::ptrdiff_t;
307
+ {I}using value_type = Error;
308
+ {I}using pointer = const Error*;
309
+ {I}using reference = const Error&;
310
+
311
+ public:
312
+ {I}explicit Iterator(
313
+ {II}std::unique_ptr<impl::IVerificator> verificator
314
+ {I}) :
315
+ {I}verificator_(std::move(verificator)) {{
316
+ {II} // Intentionally empty.
317
+ {I}}}
318
+
319
+ {I}Iterator(const Iterator& other);
320
+ {I}Iterator(Iterator&& other);
321
+
322
+ {I}Iterator& operator=(const Iterator& other);
323
+ {I}Iterator& operator=(Iterator&& other);
324
+
325
+ {I}reference operator*() const;
326
+ {I}pointer operator->() const;
327
+
328
+ {I}// Prefix increment
329
+ {I}Iterator& operator++();
330
+
331
+ {I}// Postfix increment
332
+ {I}Iterator operator++(int);
333
+
334
+ {I}friend bool operator==(const Iterator& a, const Iterator& b);
335
+ {I}friend bool operator!=(const Iterator& a, const Iterator& b);
336
+
337
+ private:
338
+ {I}std::unique_ptr<impl::IVerificator> verificator_;
339
+ }};"""
340
+ ),
341
+ Stripped("bool operator==(const Iterator& a, const Iterator& b);"),
342
+ Stripped("bool operator!=(const Iterator& a, const Iterator& b);"),
343
+ Stripped(
344
+ f"""\
345
+ /// \\cond HIDDEN
346
+ namespace impl {{
347
+ class IVerificator {{
348
+ public:
349
+ {I}virtual void Start() = 0;
350
+ {I}virtual void Next() = 0;
351
+ {I}virtual bool Done() const = 0;
352
+
353
+ {I}virtual const Error& Get() const = 0;
354
+ {I}virtual Error& GetMutable() = 0;
355
+ {I}virtual long Index() const = 0;
356
+
357
+ {I}virtual std::unique_ptr<IVerificator> Clone() const = 0;
358
+
359
+ {I}virtual ~IVerificator() = default;
360
+ }}; // class IVerificator
361
+ }} // namespace impl
362
+ /// \\endcond"""
363
+ ),
364
+ Stripped(
365
+ f"""\
366
+ class IVerification {{
367
+ public:
368
+ {I}virtual Iterator begin() const = 0;
369
+ {I}virtual const Iterator& end() const = 0;
370
+ {I}virtual ~IVerification() = default;
371
+ }}; // class IVerification"""
372
+ ),
373
+ Stripped(
374
+ f"""\
375
+ /**
376
+ * \\brief Verify that the instance conforms to the meta-model constraints.
377
+ *
378
+ * Do not proceed to verify the instances referenced from
379
+ * the given instance.
380
+ *
381
+ * Range-based loops should fit the vast majority of the use cases:
382
+ * \\code
383
+ * std::shared_ptr<types::Environment> env = ...;
384
+ * for (const Error& error : NonRecursiveVerification(env)) {{
385
+ * {I}report_somehow(error);
386
+ * }}
387
+ * \\endcode
388
+ *
389
+ * We use const references to shared pointers here for efficiency. Since
390
+ * we do not make a copy of \\p that shared pointer, it is very important that
391
+ * the given shared pointer outlives the verification, lest cause undefined behavior.
392
+ * See these StackOverflow questions:
393
+ * * https://stackoverflow.com/questions/12002480/passing-stdshared-ptr-to-constructors/12002668#12002668
394
+ * * https://stackoverflow.com/questions/3310737/should-we-pass-a-shared-ptr-by-reference-or-by-value
395
+ * * https://stackoverflow.com/questions/37610494/passing-const-shared-ptrt-versus-just-shared-ptrt-as-parameter
396
+ */
397
+ class NonRecursiveVerification : public IVerification {{
398
+ public:
399
+ {I}NonRecursiveVerification(
400
+ {II}const std::shared_ptr<types::IClass>& instance
401
+ {I});
402
+
403
+ {I}Iterator begin() const override;
404
+ {I}const Iterator& end() const override;
405
+
406
+ {I}~NonRecursiveVerification() override = default;
407
+ private:
408
+ {I}const std::shared_ptr<types::IClass>& instance_;
409
+ }}; // class NonRecursiveVerification"""
410
+ ),
411
+ Stripped(
412
+ f"""\
413
+ /**
414
+ * \\brief Verify that the instance conforms to the meta-model constraints.
415
+ *
416
+ * Also verify recursively all the instances referenced from
417
+ * the given instance.
418
+ *
419
+ * Range-based loops should fit the vast majority of the use cases:
420
+ * \\code
421
+ * std::shared_ptr<types::Environment> env = ...;
422
+ * for (const Error& error : RecursiveVerification(env)) {{
423
+ * {I}report_somehow(error);
424
+ * }}
425
+ * \\endcode
426
+ *
427
+ * We use const references to shared pointers here for efficiency. Since
428
+ * we do not make a copy of \\p that shared pointer, it is very important that
429
+ * the given shared pointer outlives the verification, lest cause undefined behavior.
430
+ * See these StackOverflow questions:
431
+ * * https://stackoverflow.com/questions/12002480/passing-stdshared-ptr-to-constructors/12002668#12002668
432
+ * * https://stackoverflow.com/questions/3310737/should-we-pass-a-shared-ptr-by-reference-or-by-value
433
+ * * https://stackoverflow.com/questions/37610494/passing-const-shared-ptrt-versus-just-shared-ptrt-as-parameter
434
+ */
435
+ class RecursiveVerification : public IVerification {{
436
+ public:
437
+ {I}RecursiveVerification(
438
+ {II}const std::shared_ptr<types::IClass>& instance
439
+ {I});
440
+
441
+ {I}Iterator begin() const override;
442
+ {I}const Iterator& end() const override;
443
+
444
+ {I}~RecursiveVerification() override = default;
445
+ private:
446
+ {I}const std::shared_ptr<types::IClass>& instance_;
447
+ }}; // class RecursiveVerification"""
448
+ ),
449
+ ] # type: List[Stripped]
450
+
451
+ errors = [] # type: List[Error]
452
+
453
+ if len(symbol_table.verification_functions) > 0:
454
+ blocks.append(Stripped("// region Verification functions"))
455
+
456
+ for verification in symbol_table.verification_functions:
457
+ block, error = _generate_verification_function_definition(
458
+ verification=verification, spec_impls=spec_impls
459
+ )
460
+ if error is not None:
461
+ errors.append(error)
462
+ continue
463
+ else:
464
+ assert block is not None
465
+ blocks.append(block)
466
+
467
+ blocks.append(Stripped("// endregion Verification functions"))
468
+
469
+ if len(symbol_table.constrained_primitives) > 0:
470
+ blocks.append(Stripped("// region Verification of constrained primitives"))
471
+
472
+ for constrained_primitive in symbol_table.constrained_primitives:
473
+ blocks.append(
474
+ _generate_definition_of_verify_constrained_primitive(
475
+ constrained_primitive=constrained_primitive
476
+ )
477
+ )
478
+
479
+ blocks.append(Stripped("// endregion Verification of constrained primitives"))
480
+
481
+ if len(errors) > 0:
482
+ return None, errors
483
+
484
+ blocks.extend(
485
+ [
486
+ Stripped(
487
+ """\
488
+ } // namespace verification
489
+ /**@}*/"""
490
+ ),
491
+ cpp_common.generate_namespace_closing(library_namespace),
492
+ cpp_common.WARNING,
493
+ Stripped(f"#endif // {include_guard_var}"),
494
+ ]
495
+ )
496
+
497
+ out = io.StringIO()
498
+ for i, block in enumerate(blocks):
499
+ if i > 0:
500
+ out.write("\n\n")
501
+
502
+ out.write(block)
503
+
504
+ out.write("\n")
505
+
506
+ return out.getvalue(), None
507
+
508
+
509
+ def _generate_error_implementation() -> List[Stripped]:
510
+ """Generate the implementation of the ``Error`` struct."""
511
+ return [
512
+ Stripped("// region struct Error"),
513
+ Stripped(
514
+ f"""\
515
+ Error::Error(
516
+ {I}std::wstring a_cause
517
+ ) :
518
+ {I}cause(std::move(a_cause)) {{
519
+ {I}// Intentionally empty.
520
+ }}"""
521
+ ),
522
+ Stripped(
523
+ f"""\
524
+ Error::Error(
525
+ {I}std::wstring a_cause,
526
+ {I}iteration::Path a_path
527
+ ) :
528
+ {I}cause(std::move(a_cause)),
529
+ {I}path(std::move(a_path)) {{
530
+ {I}// Intentionally empty.
531
+ }}"""
532
+ ),
533
+ Stripped("// endregion struct Error"),
534
+ ]
535
+
536
+
537
+ def _generate_new_non_recursive_verificator_definition() -> Stripped:
538
+ """Generate the def. of the factory function for non-recursive verificators."""
539
+ new_non_recursive_verificator = cpp_naming.function_name(
540
+ Identifier("new_non_recursive_verificator")
541
+ )
542
+
543
+ return Stripped(
544
+ f"""\
545
+ /**
546
+ * Produce a non-recursive verificator of the instance given its runtime model type.
547
+ */
548
+ std::unique_ptr<impl::IVerificator> {new_non_recursive_verificator}(
549
+ {I}const std::shared_ptr<types::IClass>& instance
550
+ );"""
551
+ )
552
+
553
+
554
+ def _generate_iterator_implementation() -> List[Stripped]:
555
+ """Generate the implementation of the class ``Iterator``."""
556
+ return [
557
+ Stripped("// region struct Iterator"),
558
+ Stripped(
559
+ f"""\
560
+ Iterator::Iterator(
561
+ {I}const Iterator& other
562
+ ) :
563
+ {I}verificator_(other.verificator_->Clone()) {{
564
+ {I}// Intentionally empty.
565
+ }}"""
566
+ ),
567
+ Stripped(
568
+ f"""\
569
+ Iterator::Iterator(
570
+ {I}Iterator&& other
571
+ ) :
572
+ {I}verificator_(std::move(other.verificator_)) {{
573
+ {I}// Intentionally empty.
574
+ }}"""
575
+ ),
576
+ Stripped(
577
+ f"""\
578
+ Iterator& Iterator::operator=(const Iterator& other) {{
579
+ {I}return *this = Iterator(other);
580
+ }}"""
581
+ ),
582
+ Stripped(
583
+ f"""\
584
+ Iterator& Iterator::operator=(Iterator&& other) {{
585
+ {I}if (this != &other) {{
586
+ {II}verificator_ = std::move(other.verificator_);
587
+ {I}}}
588
+
589
+ {I}return *this;
590
+ }}"""
591
+ ),
592
+ Stripped(
593
+ f"""\
594
+ const Error& Iterator::operator*() const {{
595
+ {I}if (verificator_->Done()) {{
596
+ {II}throw std::logic_error(
597
+ {III}"You want to de-reference from a completed iterator "
598
+ {III}"over verification errors."
599
+ {II});
600
+ {I}}}
601
+
602
+ {I}return verificator_->Get();
603
+ }}"""
604
+ ),
605
+ Stripped(
606
+ f"""\
607
+ const Error* Iterator::operator->() const {{
608
+ {I}if (verificator_->Done()) {{
609
+ {II}throw std::logic_error(
610
+ {III}"You want to de-reference from a completed iterator "
611
+ {III}"over verification errors."
612
+ {II});
613
+ {I}}}
614
+
615
+ {I}return &(verificator_->Get());
616
+ }}"""
617
+ ),
618
+ Stripped(
619
+ f"""\
620
+ // Prefix increment
621
+ Iterator& Iterator::operator++() {{
622
+ {I}if (verificator_->Done()) {{
623
+ {II}throw std::logic_error(
624
+ {III}"You want to move a completed iterator "
625
+ {III}"over verification errors."
626
+ {II});
627
+ {I}}}
628
+
629
+ {I}verificator_->Next();
630
+ {I}return *this;
631
+ }}"""
632
+ ),
633
+ Stripped(
634
+ f"""\
635
+ // Postfix increment
636
+ Iterator Iterator::operator++(int) {{
637
+ {I}Iterator result(*this);
638
+ {I}++(*this);
639
+ {I}return result;
640
+ }}"""
641
+ ),
642
+ Stripped(
643
+ f"""\
644
+ bool operator==(const Iterator& a, const Iterator& b) {{
645
+ {I}return a.verificator_->Index() == b.verificator_->Index();
646
+ }}"""
647
+ ),
648
+ Stripped(
649
+ f"""\
650
+ bool operator!=(const Iterator& a, const Iterator& b) {{
651
+ {I}return a.verificator_->Index() != b.verificator_->Index();
652
+ }}"""
653
+ ),
654
+ Stripped("// endregion struct Iterator"),
655
+ ]
656
+
657
+
658
+ def _generate_non_recursive_verification() -> List[Stripped]:
659
+ """Generate the ``NonRecursiveVerification`` class."""
660
+ return [
661
+ Stripped("// region NonRecursiveVerification"),
662
+ Stripped(
663
+ f"""\
664
+ NonRecursiveVerification::NonRecursiveVerification(
665
+ {I}const std::shared_ptr<types::IClass>& instance
666
+ ) : instance_(instance) {{
667
+ {I}// Intentionally empty.
668
+ }}"""
669
+ ),
670
+ Stripped(
671
+ f"""\
672
+ Iterator NonRecursiveVerification::begin() const {{
673
+ {I}std::unique_ptr<impl::IVerificator> verificator(
674
+ {II}NewNonRecursiveVerificator(instance_)
675
+ {I});
676
+
677
+ {I}verificator->Start();
678
+
679
+ {I}// NOTE(mristin):
680
+ {I}// We short-circuit here for efficiency, as we can immediately dispose
681
+ {I}// of the verificator.
682
+ {I}if (verificator->Done()) {{
683
+ {II}return Iterator(common::make_unique<AlwaysDoneVerificator>());
684
+ {I}}}
685
+
686
+ {I}return Iterator(std::move(verificator));
687
+ }}"""
688
+ ),
689
+ Stripped(
690
+ f"""\
691
+ const Iterator& NonRecursiveVerification::end() const {{
692
+ {I}static Iterator iterator(common::make_unique<AlwaysDoneVerificator>());
693
+ {I}return iterator;
694
+ }}"""
695
+ ),
696
+ Stripped("// endregion NonRecursiveVerification"),
697
+ ]
698
+
699
+
700
+ def _generate_recursive_verification() -> List[Stripped]:
701
+ """Generate the ``RecursiveVerification`` class."""
702
+ return [
703
+ Stripped("// region RecursiveVerification"),
704
+ Stripped(
705
+ f"""\
706
+ RecursiveVerification::RecursiveVerification(
707
+ {I}const std::shared_ptr<types::IClass>& instance
708
+ ) : instance_(instance) {{
709
+ {I}// Intentionally empty.
710
+ }}"""
711
+ ),
712
+ Stripped(
713
+ f"""\
714
+ Iterator RecursiveVerification::begin() const {{
715
+ {I}std::unique_ptr<impl::IVerificator> verificator(
716
+ {II}common::make_unique<RecursiveVerificator>(instance_)
717
+ {I});
718
+
719
+ {I}verificator->Start();
720
+
721
+ {I}// NOTE(mristin):
722
+ {I}// We short-circuit here for efficiency, as we can immediately dispose
723
+ {I}// of the verificator.
724
+ {I}if (verificator->Done()) {{
725
+ {II}return Iterator(common::make_unique<AlwaysDoneVerificator>());
726
+ {I}}}
727
+
728
+ {I}return Iterator(std::move(verificator));
729
+ }}"""
730
+ ),
731
+ Stripped(
732
+ f"""\
733
+ const Iterator& RecursiveVerification::end() const {{
734
+ {I}static Iterator iterator(common::make_unique<AlwaysDoneVerificator>());
735
+ {I}return iterator;
736
+ }}"""
737
+ ),
738
+ Stripped("// endregion RecursiveVerification"),
739
+ ]
740
+
741
+
742
+ def _generate_always_done_verificator() -> List[Stripped]:
743
+ """Generate the verificator which always has ``Done`` set."""
744
+ return [
745
+ Stripped("// region class AlwaysDoneVerificator"),
746
+ Stripped(
747
+ f"""\
748
+ class AlwaysDoneVerificator : public impl::IVerificator {{
749
+ public:
750
+ {I}void Start() override;
751
+ {I}void Next() override;
752
+ {I}bool Done() const override;
753
+ {I}const Error& Get() const override;
754
+ {I}Error& GetMutable() override;
755
+ {I}long Index() const override;
756
+ {I}std::unique_ptr<impl::IVerificator> Clone() const override;
757
+
758
+ {I}virtual ~AlwaysDoneVerificator() = default;
759
+ }}; // class AlwaysDoneVerificator"""
760
+ ),
761
+ Stripped(
762
+ f"""\
763
+ void AlwaysDoneVerificator::Start() {{
764
+ {I}// Intentionally empty.
765
+ }}"""
766
+ ),
767
+ Stripped(
768
+ f"""\
769
+ void AlwaysDoneVerificator::Next() {{
770
+ {I}throw std::logic_error(
771
+ {II}"You want to move an AlwaysDoneVerificator, "
772
+ {II}"but the verificator is always done, as its name suggests."
773
+ {I});
774
+ }}"""
775
+ ),
776
+ Stripped(
777
+ f"""\
778
+ bool AlwaysDoneVerificator::Done() const {{
779
+ {I}return true;
780
+ }}"""
781
+ ),
782
+ Stripped(
783
+ f"""\
784
+ const Error& AlwaysDoneVerificator::Get() const {{
785
+ {II}throw std::logic_error(
786
+ {III}"You want to get from an AlwaysDoneVerificator, "
787
+ {III}"but the verificator is always done, as its name suggests."
788
+ {II});
789
+ }}"""
790
+ ),
791
+ Stripped(
792
+ f"""\
793
+ Error& AlwaysDoneVerificator::GetMutable() {{
794
+ {II}throw std::logic_error(
795
+ {III}"You want to get mutable from an AlwaysDoneVerificator, "
796
+ {III}"but the verificator is always done, as its name suggests."
797
+ {II});
798
+ }}"""
799
+ ),
800
+ Stripped(
801
+ f"""\
802
+ long AlwaysDoneVerificator::Index() const {{
803
+ {I}return -1;
804
+ }}"""
805
+ ),
806
+ Stripped(
807
+ f"""\
808
+ std::unique_ptr<impl::IVerificator> AlwaysDoneVerificator::Clone() const {{
809
+ {I}return common::make_unique<AlwaysDoneVerificator>(*this);
810
+ }}"""
811
+ ),
812
+ Stripped("// endregion class AlwaysDoneVerificator"),
813
+ ]
814
+
815
+
816
+ @ensure(lambda cls, result: all(id(prop) in cls.property_id_set for prop in result))
817
+ def _collect_constrained_primitive_properties(
818
+ cls: intermediate.ConcreteClass,
819
+ ) -> List[intermediate.Property]:
820
+ """Select the properties which are annotated as constrained primitives."""
821
+ result = [] # type: List[intermediate.Property]
822
+ for prop in cls.properties:
823
+ type_anno = intermediate.beneath_optional(prop.type_annotation)
824
+
825
+ if isinstance(type_anno, intermediate.PrimitiveTypeAnnotation):
826
+ pass
827
+
828
+ elif isinstance(type_anno, intermediate.OurTypeAnnotation):
829
+ if isinstance(type_anno.our_type, intermediate.Enumeration):
830
+ pass
831
+
832
+ elif isinstance(type_anno.our_type, intermediate.ConstrainedPrimitive):
833
+ result.append(prop)
834
+
835
+ elif isinstance(
836
+ type_anno.our_type,
837
+ (intermediate.AbstractClass, intermediate.ConcreteClass),
838
+ ):
839
+ pass
840
+
841
+ else:
842
+ assert_never(type_anno.our_type)
843
+
844
+ elif isinstance(type_anno, intermediate.ListTypeAnnotation):
845
+ assert isinstance(
846
+ type_anno.items, intermediate.OurTypeAnnotation
847
+ ) and isinstance(
848
+ type_anno.items.our_type,
849
+ (intermediate.AbstractClass, intermediate.ConcreteClass),
850
+ ), (
851
+ f"NOTE (mristin, 2023-03-29): We expect only lists of classes "
852
+ f"at the moment, but you specified {type_anno}. "
853
+ f"Please contact the developers if you need this feature."
854
+ )
855
+
856
+ pass
857
+ else:
858
+ assert_never(type_anno)
859
+
860
+ return result
861
+
862
+
863
+ class VerificatorQualities:
864
+ """Model the relevant qualities of a verificator."""
865
+
866
+ #: Class that we want to verify
867
+ cls: Final[intermediate.ConcreteClass]
868
+
869
+ #: If set, the verificator performs no verification steps.
870
+ is_noop: Final[bool]
871
+
872
+ #: List properties which are annotated with an (possibly optional) constrained
873
+ #: primitive
874
+ constrained_primitive_properties: Final[Sequence[intermediate.Property]]
875
+
876
+ # fmt: off
877
+ @ensure(
878
+ lambda self:
879
+ not (
880
+ len(self.cls.invariants) == 0
881
+ and len(self.constrained_primitive_properties) == 0
882
+ ) or self.is_noop,
883
+ "The verificator is a no-op if there are no invariants and no constrained "
884
+ "primitive properties in the class"
885
+ )
886
+ @ensure(
887
+ lambda self:
888
+ not (
889
+ len(self.cls.invariants) > 0
890
+ or len(self.constrained_primitive_properties) > 0
891
+ ) or not self.is_noop,
892
+ "The verificator is *not* a no-op if there is at least one invariant or "
893
+ "a property annotated with a constrained primitive"
894
+ )
895
+ # fmt: on
896
+ def __init__(self, cls: intermediate.ConcreteClass) -> None:
897
+ self.cls = cls
898
+
899
+ self.constrained_primitive_properties = (
900
+ _collect_constrained_primitive_properties(cls=cls)
901
+ )
902
+
903
+ self.is_noop = (
904
+ len(cls.invariants) == 0 and len(self.constrained_primitive_properties) == 0
905
+ )
906
+
907
+
908
+ @require(lambda verificator_qualities: verificator_qualities.is_noop)
909
+ def _generate_empty_non_recursive_verificator(
910
+ verificator_qualities: VerificatorQualities,
911
+ ) -> List[Stripped]:
912
+ """
913
+ Generate an implementation of a non-recursive verificator which is always done.
914
+
915
+ Though the implementation is a duplicate in logic of ``AlwaysDoneVerificator``,
916
+ the assertion error messages are different, so we generate a separate class.
917
+ """
918
+ # Shortcut
919
+ cls = verificator_qualities.cls
920
+
921
+ of_cls = cpp_naming.class_name(Identifier(f"Of_{cls.name}"))
922
+ interface_name = cpp_naming.interface_name(cls.name)
923
+
924
+ return [
925
+ Stripped(
926
+ f"""\
927
+ class {of_cls} : public impl::IVerificator {{
928
+ public:
929
+ {I}{of_cls}(
930
+ {II}const std::shared_ptr<types::IClass>& instance
931
+ {I});
932
+
933
+ {I}void Start() override;
934
+ {I}void Next() override;
935
+ {I}bool Done() const override;
936
+ {I}const Error& Get() const override;
937
+ {I}Error& GetMutable() override;
938
+ {I}long Index() const override;
939
+
940
+ {I}std::unique_ptr<impl::IVerificator> Clone() const override;
941
+
942
+ {I}~{of_cls}() override = default;
943
+ }}; // class {of_cls}"""
944
+ ),
945
+ Stripped(
946
+ f"""\
947
+ {of_cls}::{of_cls}(
948
+ {I}const std::shared_ptr<types::IClass>&
949
+ ) {{
950
+ {I}// Intentionally empty.
951
+ }}"""
952
+ ),
953
+ Stripped(
954
+ f"""\
955
+ void {of_cls}::Start() {{
956
+ {I}// Intentionally empty.
957
+ }}"""
958
+ ),
959
+ Stripped(
960
+ f"""\
961
+ void {of_cls}::Next() {{
962
+ {I}throw std::logic_error(
963
+ {II}"You want to move "
964
+ {II}"a verificator {of_cls}, "
965
+ {II}"but the verificator is always done as "
966
+ {II}"{interface_name} "
967
+ {II}"has no invariants defined."
968
+ {I});
969
+ }}"""
970
+ ),
971
+ Stripped(
972
+ f"""\
973
+ bool {of_cls}::Done() const {{
974
+ {I}return true;
975
+ }}"""
976
+ ),
977
+ Stripped(
978
+ f"""\
979
+ const Error& {of_cls}::Get() const {{
980
+ {I}throw std::logic_error(
981
+ {II}"You want to get from "
982
+ {II}"a verificator {of_cls}, "
983
+ {II}"but the verificator is always done as "
984
+ {II}"{interface_name} "
985
+ {II}"has no invariants defined."
986
+ {I});
987
+ }}"""
988
+ ),
989
+ Stripped(
990
+ f"""\
991
+ Error& {of_cls}::GetMutable() {{
992
+ {I}throw std::logic_error(
993
+ {II}"You want to get mutable from "
994
+ {II}"a verificator {of_cls}, "
995
+ {II}"but the verificator is always done as "
996
+ {II}"{interface_name} "
997
+ {II}"has no invariants defined."
998
+ {I});
999
+ }}"""
1000
+ ),
1001
+ Stripped(
1002
+ f"""\
1003
+ long {of_cls}::Index() const {{
1004
+ {I}return -1;
1005
+ }}"""
1006
+ ),
1007
+ Stripped(
1008
+ f"""\
1009
+ std::unique_ptr<impl::IVerificator> {of_cls}::Clone() const {{
1010
+ {I}return common::make_unique<
1011
+ {II}{of_cls}
1012
+ {I}>(*this);
1013
+ }}"""
1014
+ ),
1015
+ ]
1016
+
1017
+
1018
+ class _ClassInvariantTranspiler(cpp_transpilation.Transpiler):
1019
+ """Transpile invariants of the classes."""
1020
+
1021
+ def __init__(
1022
+ self,
1023
+ type_map: Mapping[
1024
+ parse_tree.Node, intermediate_type_inference.TypeAnnotationUnion
1025
+ ],
1026
+ is_optional_map: Mapping[parse_tree.Node, bool],
1027
+ environment: intermediate_type_inference.Environment,
1028
+ symbol_table: intermediate.SymbolTable,
1029
+ ) -> None:
1030
+ """Initialize with the given values."""
1031
+ cpp_transpilation.Transpiler.__init__(
1032
+ self,
1033
+ type_map=type_map,
1034
+ is_optional_map=is_optional_map,
1035
+ environment=environment,
1036
+ types_namespace=cpp_common.TYPES_NAMESPACE,
1037
+ )
1038
+
1039
+ self._symbol_table = symbol_table
1040
+
1041
+ def transform_name(
1042
+ self, node: parse_tree.Name
1043
+ ) -> Tuple[Optional[Stripped], Optional[Error]]:
1044
+ if node.identifier in self._variable_name_set:
1045
+ return Stripped(cpp_naming.variable_name(node.identifier)), None
1046
+
1047
+ if node.identifier == "self":
1048
+ # The ``instance_`` refers to the instance under verification.
1049
+ return Stripped("instance_"), None
1050
+
1051
+ if node.identifier in self._symbol_table.constants_by_name:
1052
+ constant = cpp_naming.constant_name(node.identifier)
1053
+ return Stripped(f"{cpp_common.CONSTANTS_NAMESPACE}::{constant}"), None
1054
+
1055
+ if node.identifier in self._symbol_table.verification_functions_by_name:
1056
+ return Stripped(cpp_naming.function_name(node.identifier)), None
1057
+
1058
+ our_type = self._symbol_table.find_our_type(name=node.identifier)
1059
+ if isinstance(our_type, intermediate.Enumeration):
1060
+ return (
1061
+ Stripped(
1062
+ f"{cpp_common.TYPES_NAMESPACE}::{cpp_naming.enum_name(node.identifier)}"
1063
+ ),
1064
+ None,
1065
+ )
1066
+
1067
+ return None, Error(
1068
+ node.original_node,
1069
+ f"We can not determine how to transpile the name {node.identifier!r} "
1070
+ f"to C++. We could not find it neither in the local variables, "
1071
+ f"nor in the global constants, nor in verification functions, "
1072
+ f"nor as an enumeration. If you expect this name to be transpilable, "
1073
+ f"please contact the developers.",
1074
+ )
1075
+
1076
+
1077
+ @ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
1078
+ def _transpile_class_invariant(
1079
+ invariant: intermediate.Invariant,
1080
+ symbol_table: intermediate.SymbolTable,
1081
+ environment: intermediate_type_inference.Environment,
1082
+ ) -> Tuple[Optional[Stripped], Optional[Error]]:
1083
+ """Translate the invariant from the meta-model into a C++ condition."""
1084
+ # fmt: off
1085
+ type_map, inference_error = (
1086
+ intermediate_type_inference.infer_for_invariant(
1087
+ invariant=invariant,
1088
+ environment=environment
1089
+ )
1090
+ )
1091
+ # fmt: on
1092
+
1093
+ if inference_error is not None:
1094
+ return None, inference_error
1095
+
1096
+ assert type_map is not None
1097
+
1098
+ optional_inferrer = cpp_optionaling.Inferrer(
1099
+ environment=environment, type_map=type_map
1100
+ )
1101
+
1102
+ _ = optional_inferrer.transform(invariant.body)
1103
+
1104
+ if len(optional_inferrer.errors) > 0:
1105
+ return None, Error(
1106
+ invariant.parsed.node,
1107
+ "Failed to infer whether one or more nodes are ``common::optional`` "
1108
+ "in the invariant",
1109
+ optional_inferrer.errors,
1110
+ )
1111
+
1112
+ transpiler = _ClassInvariantTranspiler(
1113
+ type_map=type_map,
1114
+ is_optional_map=optional_inferrer.is_optional_map,
1115
+ environment=environment,
1116
+ symbol_table=symbol_table,
1117
+ )
1118
+
1119
+ expr, error = transpiler.transform(invariant.body)
1120
+
1121
+ if error is not None:
1122
+ return None, error
1123
+
1124
+ assert expr is not None
1125
+ return expr, None
1126
+
1127
+
1128
+ @require(lambda verificator_qualities: not verificator_qualities.is_noop)
1129
+ @ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
1130
+ def _generate_non_recursive_verificator_execute(
1131
+ verificator_qualities: VerificatorQualities,
1132
+ symbol_table: intermediate.SymbolTable,
1133
+ environment: intermediate_type_inference.Environment,
1134
+ ) -> Tuple[Optional[Stripped], Optional[List[Error]]]:
1135
+ """Generate the impl. of the ``Execute()`` for a verificator of class ``cls``."""
1136
+ flow = [
1137
+ yielding_flow.command_from_text(
1138
+ """\
1139
+ done_ = false;
1140
+ error_ = nullptr;
1141
+ index_ = -1;"""
1142
+ )
1143
+ ] # type: List[yielding_flow.Node]
1144
+
1145
+ errors = [] # type: List[Error]
1146
+ for invariant in verificator_qualities.cls.invariants:
1147
+ condition_expr, error = _transpile_class_invariant(
1148
+ invariant=invariant, symbol_table=symbol_table, environment=environment
1149
+ )
1150
+ if error is not None:
1151
+ errors.append(error)
1152
+ continue
1153
+
1154
+ assert condition_expr is not None
1155
+
1156
+ # NOTE (mristin, 2023-10-17):
1157
+ # We need to wrap the description in multiple literals as a single long
1158
+ # string literal is often too much for the readability.
1159
+ invariant_description_lines = wrap_text_into_lines(invariant.description)
1160
+
1161
+ invariant_description_literals_joined = "\n".join(
1162
+ cpp_common.wstring_literal(line) for line in invariant_description_lines
1163
+ )
1164
+
1165
+ flow.append(
1166
+ yielding_flow.IfFalse(
1167
+ condition_expr,
1168
+ [
1169
+ yielding_flow.command_from_text(
1170
+ f"""\
1171
+ error_ = common::make_unique<Error>(
1172
+ {I}{indent_but_first_line(invariant_description_literals_joined, I)}
1173
+ );
1174
+ // No path is prepended as the error refers to the instance itself.
1175
+ ++index_;"""
1176
+ ),
1177
+ yielding_flow.Yield(),
1178
+ ],
1179
+ )
1180
+ )
1181
+
1182
+ for prop in verificator_qualities.constrained_primitive_properties:
1183
+ type_anno = intermediate.beneath_optional(prop.type_annotation)
1184
+ assert isinstance(type_anno, intermediate.OurTypeAnnotation) and isinstance(
1185
+ type_anno.our_type, intermediate.ConstrainedPrimitive
1186
+ )
1187
+
1188
+ of_constrained_primitive = cpp_naming.class_name(
1189
+ Identifier(f"Of_{type_anno.our_type.name}")
1190
+ )
1191
+
1192
+ getter_name = cpp_naming.getter_name(prop.name)
1193
+
1194
+ property_enum = cpp_naming.enum_name(Identifier("Property"))
1195
+ property_literal = cpp_naming.enum_literal_name(prop.name)
1196
+
1197
+ if isinstance(prop.type_annotation, intermediate.OptionalTypeAnnotation):
1198
+ # NOTE (mristin, 2023-11-01):
1199
+ # Be careful! You have to keep the following snippet in semantical sync with
1200
+ # the code in the else-clause!
1201
+
1202
+ flow.append(
1203
+ yielding_flow.IfTrue(
1204
+ f"instance_->{getter_name}().has_value()",
1205
+ [
1206
+ yielding_flow.command_from_text(
1207
+ f"""\
1208
+ constrained_primitive_verificator_ = (
1209
+ {I}common::make_unique<
1210
+ {II}constrained_primitive_verificator::{of_constrained_primitive}
1211
+ {I}>(
1212
+ {II}*(instance_->{getter_name}())
1213
+ {I})
1214
+ );
1215
+ constrained_primitive_verificator_->Start();"""
1216
+ ),
1217
+ yielding_flow.For(
1218
+ "!constrained_primitive_verificator_->Done()",
1219
+ "constrained_primitive_verificator_->Next();",
1220
+ [
1221
+ yielding_flow.command_from_text(
1222
+ f"""\
1223
+ // We intentionally take over the ownership of the errors' data members,
1224
+ // as we know the implementation in all the detail, and want to avoid a costly
1225
+ // copy.
1226
+ error_ = common::make_unique<Error>(
1227
+ {I}std::move(
1228
+ {II}constrained_primitive_verificator_->GetMutable()
1229
+ {I})
1230
+ );
1231
+
1232
+ error_->path.segments.emplace_back(
1233
+ {I}common::make_unique<iteration::PropertySegment>(
1234
+ {II}iteration::{property_enum}::{property_literal}
1235
+ {I})
1236
+ );
1237
+
1238
+ ++index_;"""
1239
+ ),
1240
+ yielding_flow.Yield(),
1241
+ ],
1242
+ ),
1243
+ yielding_flow.command_from_text(
1244
+ "constrained_primitive_verificator_ = nullptr;"
1245
+ ),
1246
+ ],
1247
+ )
1248
+ )
1249
+ else:
1250
+ # NOTE (mristin, 2023-11-01):
1251
+ # Be careful! You have to keep the following snippet in semantic sync with
1252
+ # the code in the if-clause!
1253
+
1254
+ flow.append(
1255
+ yielding_flow.command_from_text(
1256
+ f"""\
1257
+ constrained_primitive_verificator_ = (
1258
+ {I}common::make_unique<
1259
+ {II}constrained_primitive_verificator::{of_constrained_primitive}
1260
+ {I}>(
1261
+ {II}instance_->{getter_name}()
1262
+ {I})
1263
+ );
1264
+ constrained_primitive_verificator_->Start();"""
1265
+ )
1266
+ )
1267
+ flow.append(
1268
+ yielding_flow.For(
1269
+ "!constrained_primitive_verificator_->Done()",
1270
+ "constrained_primitive_verificator_->Next();",
1271
+ [
1272
+ yielding_flow.command_from_text(
1273
+ f"""\
1274
+ // We intentionally take over the ownership of the errors' data members,
1275
+ // as we know the implementation in all the detail, and want to avoid a costly
1276
+ // copy.
1277
+ error_ = common::make_unique<Error>(
1278
+ {I}std::move(
1279
+ {II}constrained_primitive_verificator_->GetMutable()
1280
+ {I})
1281
+ );
1282
+
1283
+ error_->path.segments.emplace_back(
1284
+ {I}common::make_unique<iteration::PropertySegment>(
1285
+ {II}iteration::{property_enum}::{property_literal}
1286
+ {I})
1287
+ );
1288
+
1289
+ ++index_;"""
1290
+ ),
1291
+ yielding_flow.Yield(),
1292
+ ],
1293
+ )
1294
+ )
1295
+ flow.append(
1296
+ yielding_flow.command_from_text(
1297
+ "constrained_primitive_verificator_ = nullptr;"
1298
+ )
1299
+ )
1300
+
1301
+ flow.append(
1302
+ yielding_flow.command_from_text(
1303
+ """\
1304
+ done_ = true;
1305
+ error_ = nullptr;
1306
+ index_ = -1;"""
1307
+ )
1308
+ )
1309
+
1310
+ if len(errors) > 0:
1311
+ return None, errors
1312
+
1313
+ code = cpp_yielding.generate_execute_body(
1314
+ flow=flow, state_member=Identifier("state_")
1315
+ )
1316
+
1317
+ of_cls = cpp_naming.class_name(Identifier(f"of_{verificator_qualities.cls.name}"))
1318
+
1319
+ return (
1320
+ Stripped(
1321
+ f"""\
1322
+ void {of_cls}::Execute() {{
1323
+ {I}{indent_but_first_line(code, I)}
1324
+ }}"""
1325
+ ),
1326
+ None,
1327
+ )
1328
+
1329
+
1330
+ @require(lambda verificator_qualities: not verificator_qualities.is_noop)
1331
+ @ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
1332
+ def _generate_non_recursive_verificator_implementation(
1333
+ verificator_qualities: VerificatorQualities,
1334
+ symbol_table: intermediate.SymbolTable,
1335
+ environment: intermediate_type_inference.Environment,
1336
+ ) -> Tuple[Optional[List[Stripped]], Optional[Error]]:
1337
+ """Generate the impl. of a non-recursive verificator for ``cls``."""
1338
+ cls = verificator_qualities.cls
1339
+
1340
+ of_cls = cpp_naming.class_name(Identifier(f"Of_{cls.name}"))
1341
+
1342
+ interface_name = cpp_naming.interface_name(cls.name)
1343
+
1344
+ copy_data_members_snippet = Stripped(
1345
+ """\
1346
+ instance_ = other.instance_;
1347
+ done_ = other.done_;
1348
+ index_ = other.index_;
1349
+ error_ = common::make_unique<Error>(*other.error_);
1350
+ state_ = other.state_;"""
1351
+ )
1352
+
1353
+ move_data_members_snippet = Stripped(
1354
+ """\
1355
+ instance_ = std::move(other.instance_);
1356
+ done_ = other.done_;
1357
+ index_ = other.index_;
1358
+ error_ = std::move(other.error_);
1359
+ state_ = other.state_;"""
1360
+ )
1361
+
1362
+ if len(verificator_qualities.constrained_primitive_properties) > 0:
1363
+ copy_data_members_snippet = Stripped(
1364
+ f"""\
1365
+ {copy_data_members_snippet}
1366
+ constrained_primitive_verificator_ = (
1367
+ {I}other.constrained_primitive_verificator_->Clone()
1368
+ );"""
1369
+ )
1370
+
1371
+ move_data_members_snippet = Stripped(
1372
+ f"""\
1373
+ {move_data_members_snippet}
1374
+ constrained_primitive_verificator_ = std::move(
1375
+ {I}other.constrained_primitive_verificator_
1376
+ );"""
1377
+ )
1378
+
1379
+ blocks = [
1380
+ Stripped(
1381
+ f"""\
1382
+ {of_cls}::{of_cls}(
1383
+ {I}const std::shared_ptr<types::IClass>& instance
1384
+ ) :
1385
+ {I}// NOTE (mristin)
1386
+ {I}// We cast here despite the cost of increasing the use count of the shared pointer.
1387
+ {I}// Otherwise, if we didn't cast, we would not be able to have a uniform interface
1388
+ {I}// for the verification functions based on the shared pointer.
1389
+ {I}instance_(
1390
+ {II}std::dynamic_pointer_cast<
1391
+ {III}types::{interface_name}
1392
+ {II}>(
1393
+ {III}instance
1394
+ {II})
1395
+ {I}) {{
1396
+ {I}// Intentionally empty.
1397
+ }}"""
1398
+ ),
1399
+ Stripped(
1400
+ f"""\
1401
+ {of_cls}::{of_cls}(
1402
+ {I}const {of_cls}& other
1403
+ ) {{
1404
+ {I}{indent_but_first_line(copy_data_members_snippet, I)}
1405
+ }}"""
1406
+ ),
1407
+ Stripped(
1408
+ f"""\
1409
+ {of_cls}::{of_cls}(
1410
+ {I}{of_cls}&& other
1411
+ ) {{
1412
+ {I}{indent_but_first_line(move_data_members_snippet, I)}
1413
+ }}"""
1414
+ ),
1415
+ Stripped(
1416
+ f"""\
1417
+ {of_cls}& {of_cls}::operator=(
1418
+ {I}const {of_cls}& other
1419
+ ) {{
1420
+ {I}return *this = {of_cls}(other);
1421
+ }}"""
1422
+ ),
1423
+ Stripped(
1424
+ f"""\
1425
+ {of_cls}& {of_cls}::operator=(
1426
+ {I}{of_cls}&& other
1427
+ ) {{
1428
+ {I}if (this != &other) {{
1429
+ {II}{indent_but_first_line(move_data_members_snippet, II)}
1430
+ {I}}}
1431
+ {I}return *this;
1432
+ }}"""
1433
+ ),
1434
+ Stripped(
1435
+ f"""\
1436
+ void {of_cls}::Start() {{
1437
+ {I}state_ = 0;
1438
+ {I}Execute();
1439
+ }}"""
1440
+ ),
1441
+ Stripped(
1442
+ f"""\
1443
+ void {of_cls}::Next() {{
1444
+ {I}#ifdef DEBUG
1445
+ {I}if (Done()) {{
1446
+ {II}throw std::logic_error(
1447
+ {III}"You want to move a verificator {of_cls}, "
1448
+ {III}"but the verificator was done."
1449
+ {II});
1450
+ {I}}}
1451
+ {I}#endif
1452
+
1453
+ {I}Execute();
1454
+ }}"""
1455
+ ),
1456
+ Stripped(
1457
+ f"""\
1458
+ bool {of_cls}::Done() const {{
1459
+ {I}return done_;
1460
+ }}"""
1461
+ ),
1462
+ Stripped(
1463
+ f"""\
1464
+ const Error& {of_cls}::Get() const {{
1465
+ {I}#ifdef DEBUG
1466
+ {I}if (Done()) {{
1467
+ {II}throw std::logic_error(
1468
+ {III}"You want to get from a verificator {of_cls}, "
1469
+ {III}"but the verificator was done."
1470
+ {II});
1471
+ {I}}}
1472
+ {I}#endif
1473
+
1474
+ {I}return *error_;
1475
+ }}"""
1476
+ ),
1477
+ Stripped(
1478
+ f"""\
1479
+ Error& {of_cls}::GetMutable() {{
1480
+ {I}#ifdef DEBUG
1481
+ {I}if (Done()) {{
1482
+ {II}throw std::logic_error(
1483
+ {III}"You want to get mutable from a verificator {of_cls}, "
1484
+ {III}"but the verificator was done."
1485
+ {II});
1486
+ {I}}}
1487
+ {I}#endif
1488
+
1489
+ {I}return *error_;
1490
+ }}"""
1491
+ ),
1492
+ Stripped(
1493
+ f"""\
1494
+ long {of_cls}::Index() const {{
1495
+ {I}#ifdef DEBUG
1496
+ {I}if (Done() && index_ != -1) {{
1497
+ {II}throw std::logic_error(
1498
+ {III}common::Concat(
1499
+ {IIII}"Expected index to be -1 "
1500
+ {IIII}"from a done verificator {of_cls}, "
1501
+ {IIII}"but got: ",
1502
+ {IIII}std::to_string(index_)
1503
+ {III})
1504
+ {II});
1505
+ {I}}}
1506
+ {I}#endif
1507
+
1508
+ {I}return index_;
1509
+ }}"""
1510
+ ),
1511
+ Stripped(
1512
+ f"""\
1513
+ std::unique_ptr<impl::IVerificator> {of_cls}::Clone() const {{
1514
+ {I}return common::make_unique<
1515
+ {II}{of_cls}
1516
+ {I}>(*this);
1517
+ }}"""
1518
+ ),
1519
+ ] # type: List[Stripped]
1520
+
1521
+ execute_block, execute_errors = _generate_non_recursive_verificator_execute(
1522
+ verificator_qualities=verificator_qualities,
1523
+ symbol_table=symbol_table,
1524
+ environment=environment,
1525
+ )
1526
+ if execute_errors is not None:
1527
+ return None, Error(
1528
+ cls.parsed.node,
1529
+ f"Failed to generate Execute() method as {of_cls!r}",
1530
+ execute_errors,
1531
+ )
1532
+
1533
+ assert execute_block is not None
1534
+ blocks.append(execute_block)
1535
+
1536
+ return blocks, None
1537
+
1538
+
1539
+ @ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
1540
+ def _generate_non_recursive_verificator(
1541
+ cls: intermediate.ConcreteClass,
1542
+ symbol_table: intermediate.SymbolTable,
1543
+ base_environment: intermediate_type_inference.Environment,
1544
+ ) -> Tuple[Optional[List[Stripped]], Optional[Error]]:
1545
+ """Generate the non-recursive verificator for the ``cls``."""
1546
+ environment = intermediate_type_inference.MutableEnvironment(
1547
+ parent=base_environment
1548
+ )
1549
+
1550
+ assert environment.find(Identifier("self")) is None
1551
+ environment.set(
1552
+ identifier=Identifier("self"),
1553
+ type_annotation=intermediate_type_inference.OurTypeAnnotation(our_type=cls),
1554
+ )
1555
+
1556
+ verificator_qualities = VerificatorQualities(cls=cls)
1557
+
1558
+ if verificator_qualities.is_noop:
1559
+ return (
1560
+ _generate_empty_non_recursive_verificator(
1561
+ verificator_qualities=verificator_qualities
1562
+ ),
1563
+ None,
1564
+ )
1565
+
1566
+ of_cls = cpp_naming.class_name(Identifier(f"Of_{cls.name}"))
1567
+
1568
+ interface_name = cpp_naming.interface_name(cls.name)
1569
+
1570
+ private_data_members = [
1571
+ Stripped(
1572
+ f"""\
1573
+ std::shared_ptr<types::{interface_name}> instance_;
1574
+ bool done_;
1575
+ long index_;
1576
+ std::unique_ptr<Error> error_;
1577
+ std::uint32_t state_;"""
1578
+ )
1579
+ ] # type: List[Stripped]
1580
+
1581
+ if len(verificator_qualities.constrained_primitive_properties) > 0:
1582
+ private_data_members.append(
1583
+ Stripped(
1584
+ "std::unique_ptr<impl::IVerificator> "
1585
+ "constrained_primitive_verificator_;"
1586
+ )
1587
+ )
1588
+
1589
+ private_data_members_joined = "\n".join(private_data_members)
1590
+
1591
+ blocks = [
1592
+ Stripped(
1593
+ f"""\
1594
+ class {of_cls} : public impl::IVerificator {{
1595
+ public:
1596
+ {I}{of_cls}(
1597
+ {II}const std::shared_ptr<types::IClass>& instance
1598
+ {I});
1599
+
1600
+ {I}{of_cls}(
1601
+ {II}const {of_cls}& other
1602
+ {I});
1603
+ {I}{of_cls}(
1604
+ {II}{of_cls}&& other
1605
+ {I});
1606
+ {I}{of_cls}& operator=(
1607
+ {II}const {of_cls}& other
1608
+ {I});
1609
+ {I}{of_cls}& operator=(
1610
+ {II}{of_cls}&& other
1611
+ {I});
1612
+
1613
+ {I}void Start() override;
1614
+ {I}void Next() override;
1615
+ {I}bool Done() const override;
1616
+ {I}const Error& Get() const override;
1617
+ {I}Error& GetMutable() override;
1618
+ {I}long Index() const override;
1619
+
1620
+ {I}std::unique_ptr<impl::IVerificator> Clone() const override;
1621
+
1622
+ {I}~{of_cls}() override = default;
1623
+
1624
+ private:
1625
+ {I}{indent_but_first_line(private_data_members_joined, I)}
1626
+
1627
+ {I}void Execute();
1628
+ }}; // class {of_cls}"""
1629
+ )
1630
+ ] # type: List[Stripped]
1631
+
1632
+ impl_blocks, error = _generate_non_recursive_verificator_implementation(
1633
+ verificator_qualities=verificator_qualities,
1634
+ symbol_table=symbol_table,
1635
+ environment=environment,
1636
+ )
1637
+ if error is not None:
1638
+ return None, error
1639
+
1640
+ assert impl_blocks is not None
1641
+ blocks.extend(impl_blocks)
1642
+
1643
+ return blocks, None
1644
+
1645
+
1646
+ def _generate_new_non_recursive_verificator_implementation(
1647
+ symbol_table: intermediate.SymbolTable,
1648
+ ) -> Stripped:
1649
+ """Generate the factory of non-recursive verificators based on the model type."""
1650
+ case_blocks = [] # type: List[Stripped]
1651
+ for cls in symbol_table.concrete_classes:
1652
+ enum_name = cpp_naming.enum_name(Identifier("Model_type"))
1653
+ literal_name = cpp_naming.enum_literal_name(cls.name)
1654
+ verificator_of_cls = cpp_naming.class_name(Identifier(f"Of_{cls.name}"))
1655
+
1656
+ case_blocks.append(
1657
+ Stripped(
1658
+ f"""\
1659
+ case types::{enum_name}::{literal_name}:
1660
+ {I}return common::make_unique<
1661
+ {II}non_recursive_verificator::{verificator_of_cls}
1662
+ {I}>(
1663
+ {II}instance
1664
+ {I});"""
1665
+ )
1666
+ )
1667
+
1668
+ case_blocks.append(
1669
+ Stripped(
1670
+ f"""\
1671
+ default:
1672
+ {I}throw std::logic_error(
1673
+ {II}common::Concat(
1674
+ {III}"Unexpected model type: ",
1675
+ {III}std::to_string(
1676
+ {IIII}static_cast<std::uint32_t>(instance->model_type())
1677
+ {III})
1678
+ {II})
1679
+ {I});"""
1680
+ )
1681
+ )
1682
+
1683
+ case_blocks_joined = "\n".join(case_blocks)
1684
+
1685
+ switch_stmt = Stripped(
1686
+ f"""\
1687
+ switch (instance->model_type()) {{
1688
+ {I}{indent_but_first_line(case_blocks_joined, I)}
1689
+ }}"""
1690
+ )
1691
+
1692
+ new_non_recursive_verificator = cpp_naming.function_name(
1693
+ Identifier("new_non_recursive_verificator")
1694
+ )
1695
+
1696
+ return Stripped(
1697
+ f"""\
1698
+ std::unique_ptr<impl::IVerificator> {new_non_recursive_verificator}(
1699
+ {I}const std::shared_ptr<types::IClass>& instance
1700
+ ) {{
1701
+ {I}{indent_but_first_line(switch_stmt, I)}
1702
+ }}"""
1703
+ )
1704
+
1705
+
1706
+ def _generate_recursive_verificator_execute() -> Stripped:
1707
+ """Generate the impl. of the ``Execute()`` method for recursive verificator."""
1708
+ flow = [
1709
+ yielding_flow.command_from_text(
1710
+ """\
1711
+ error_ = nullptr;
1712
+ index_ = -1;
1713
+ done_ = false;
1714
+
1715
+ verificator_ = NewNonRecursiveVerificator(*instance_);
1716
+ verificator_->Start();"""
1717
+ ),
1718
+ yielding_flow.For(
1719
+ "!verificator_->Done()",
1720
+ "verificator_->Next();",
1721
+ [
1722
+ yielding_flow.command_from_text(
1723
+ f"""\
1724
+ // We intentionally take over the ownership of the errors' data members,
1725
+ // as we know the implementation in all the detail, and want to avoid a costly
1726
+ // copy.
1727
+ error_ = common::make_unique<Error>(
1728
+ {I}std::move(
1729
+ {II}verificator_->GetMutable()
1730
+ {I})
1731
+ );
1732
+ // No path is prepended as the error refers to the instance itself.
1733
+ ++index_;"""
1734
+ ),
1735
+ yielding_flow.Yield(),
1736
+ ],
1737
+ ),
1738
+ yielding_flow.command_from_text(
1739
+ f"""\
1740
+ verificator_ = nullptr;
1741
+
1742
+ {{
1743
+ {I}// NOTE (mristin):
1744
+ {I}// We will not need descent, so we introduce it in the scope.
1745
+ {I}iteration::Descent descent(
1746
+ {II}*instance_
1747
+ {I});
1748
+ {I}iterator_ = std::move(descent.begin());
1749
+
1750
+ {I}// NOTE (mristin):
1751
+ {I}// descent.end() is a constant reference, so we make an explicit
1752
+ {I}// copy here.
1753
+ {I}iterator_end_ = descent.end();
1754
+ }}"""
1755
+ ),
1756
+ yielding_flow.For(
1757
+ "*iterator_ != *iterator_end_",
1758
+ "++(*iterator_);",
1759
+ [
1760
+ yielding_flow.command_from_text(
1761
+ f"""\
1762
+ verificator_ = NewNonRecursiveVerificator(
1763
+ {I}*(*iterator_)
1764
+ );
1765
+ verificator_->Start();"""
1766
+ ),
1767
+ yielding_flow.For(
1768
+ "!verificator_->Done()",
1769
+ "verificator_->Next();",
1770
+ [
1771
+ yielding_flow.command_from_text(
1772
+ f"""\
1773
+ // We intentionally take over the ownership of the errors' data members,
1774
+ // as we know the implementation in all the detail, and want to avoid a costly
1775
+ // copy.
1776
+ error_ = common::make_unique<Error>(
1777
+ {I}std::move(
1778
+ {II}verificator_->GetMutable()
1779
+ {I})
1780
+ );
1781
+
1782
+ error_->path = std::move(
1783
+ {I}iteration::MaterializePath(
1784
+ {II}*iterator_
1785
+ {I})
1786
+ );
1787
+
1788
+ ++index_;"""
1789
+ ),
1790
+ yielding_flow.Yield(),
1791
+ ],
1792
+ ),
1793
+ yielding_flow.command_from_text("verificator_ = nullptr;"),
1794
+ ],
1795
+ ),
1796
+ yielding_flow.command_from_text(
1797
+ """\
1798
+ iterator_.reset();
1799
+ iterator_end_.reset();
1800
+ done_ = true;
1801
+ index_ = -1;"""
1802
+ ),
1803
+ ] # type: Sequence[yielding_flow.Node]
1804
+
1805
+ code = cpp_yielding.generate_execute_body(
1806
+ flow=flow, state_member=Identifier("state_")
1807
+ )
1808
+
1809
+ return Stripped(
1810
+ f"""\
1811
+ void RecursiveVerificator::Execute() {{
1812
+ {I}{indent_but_first_line(code, I)}
1813
+ }}"""
1814
+ )
1815
+
1816
+
1817
+ def _generate_recursive_verificator() -> List[Stripped]:
1818
+ """Generate the impl. and definition of the recursive verificator."""
1819
+ blocks = [
1820
+ Stripped(
1821
+ f"""\
1822
+ class RecursiveVerificator : public impl::IVerificator {{
1823
+ public:
1824
+ {I}RecursiveVerificator(
1825
+ {II}const std::shared_ptr<types::IClass>& instance
1826
+ {I});
1827
+
1828
+ {I}RecursiveVerificator(const RecursiveVerificator& other);
1829
+ {I}RecursiveVerificator(RecursiveVerificator&& other);
1830
+ {I}RecursiveVerificator& operator=(const RecursiveVerificator& other);
1831
+ {I}RecursiveVerificator& operator=(RecursiveVerificator&& other);
1832
+
1833
+ {I}void Start() override;
1834
+ {I}void Next() override;
1835
+ {I}bool Done() const override;
1836
+ {I}const Error& Get() const override;
1837
+ {I}Error& GetMutable() override;
1838
+ {I}long Index() const override;
1839
+
1840
+ {I}std::unique_ptr<impl::IVerificator> Clone() const override;
1841
+
1842
+ {I}~RecursiveVerificator() override = default;
1843
+
1844
+ private:
1845
+ {I}// NOTE(mristin):
1846
+ {I}// We use a pointer to a shared pointer here so that we can implement
1847
+ {I}// copy-assignment and move-assignment. Otherwise, if we used a constant
1848
+ {I}// reference here, the assignments could not be implemented as C++ does not
1849
+ {I}// allow re-binding of constant references.
1850
+ {I}const std::shared_ptr<types::IClass>* instance_;
1851
+
1852
+ {I}std::uint32_t state_;
1853
+ {I}std::unique_ptr<impl::IVerificator> verificator_;
1854
+ {I}bool done_;
1855
+ {I}long index_;
1856
+ {I}std::unique_ptr<Error> error_;
1857
+ {I}common::optional<iteration::Iterator> iterator_;
1858
+ {I}common::optional<iteration::Iterator> iterator_end_;
1859
+
1860
+ {I}void Execute();
1861
+ }}; // class RecursiveVerificator"""
1862
+ ),
1863
+ Stripped(
1864
+ f"""\
1865
+ RecursiveVerificator::RecursiveVerificator(
1866
+ {I}const std::shared_ptr<types::IClass>& instance
1867
+ ) : instance_(&instance) {{
1868
+ {I}// Intentionally empty.
1869
+ }}"""
1870
+ ),
1871
+ Stripped(
1872
+ f"""\
1873
+ RecursiveVerificator::RecursiveVerificator(const RecursiveVerificator& other) {{
1874
+ {I}instance_ = other.instance_;
1875
+ {I}state_ = other.state_;
1876
+ {I}verificator_ = other.verificator_->Clone();
1877
+ {I}done_ = other.done_;
1878
+ {I}index_ = other.index_;
1879
+ {I}error_ = common::make_unique<Error>(*(other.error_));
1880
+ {I}iterator_ = other.iterator_;
1881
+ {I}iterator_end_ = other.iterator_end_;
1882
+ }}"""
1883
+ ),
1884
+ Stripped(
1885
+ f"""\
1886
+ RecursiveVerificator::RecursiveVerificator(RecursiveVerificator&& other) {{
1887
+ {I}instance_ = other.instance_;
1888
+ {I}state_ = other.state_;
1889
+ {I}verificator_ = std::move(other.verificator_);
1890
+ {I}done_ = other.done_;
1891
+ {I}index_ = other.index_;
1892
+ {I}error_ = std::move(other.error_);
1893
+ {I}iterator_ = std::move(other.iterator_);
1894
+ {I}iterator_end_ = std::move(other.iterator_end_);
1895
+ }}"""
1896
+ ),
1897
+ Stripped(
1898
+ f"""\
1899
+ RecursiveVerificator& RecursiveVerificator::operator=(
1900
+ {I}const RecursiveVerificator& other
1901
+ ) {{
1902
+ {I}return *this = RecursiveVerificator(other);
1903
+ }}"""
1904
+ ),
1905
+ Stripped(
1906
+ f"""\
1907
+ RecursiveVerificator& RecursiveVerificator::operator=(RecursiveVerificator&& other) {{
1908
+ {I}if (this != &other) {{
1909
+ {II}instance_ = other.instance_;
1910
+ {II}state_ = other.state_;
1911
+ {II}verificator_ = std::move(other.verificator_);
1912
+ {II}done_ = other.done_;
1913
+ {II}index_ = other.index_;
1914
+ {II}error_ = std::move(other.error_);
1915
+ {II}iterator_ = std::move(other.iterator_);
1916
+ {II}iterator_end_ = std::move(other.iterator_end_);
1917
+ {I}}}
1918
+
1919
+ {I}return *this;
1920
+ }}"""
1921
+ ),
1922
+ Stripped(
1923
+ f"""\
1924
+ void RecursiveVerificator::Start() {{
1925
+ {I}state_ = 0;
1926
+ {I}Execute();
1927
+ }}"""
1928
+ ),
1929
+ Stripped(
1930
+ f"""\
1931
+ void RecursiveVerificator::Next() {{
1932
+ {I}#ifdef DEBUG
1933
+ {I}if (Done()) {{
1934
+ {II}throw std::logic_error(
1935
+ {III}"You want to get from a RecursiveVerificator, "
1936
+ {III}"but the verificator was done."
1937
+ {II});
1938
+ {I}}}
1939
+ {I}#endif
1940
+
1941
+ {I}Execute();
1942
+ }}"""
1943
+ ),
1944
+ Stripped(
1945
+ f"""\
1946
+ bool RecursiveVerificator::Done() const {{
1947
+ {I}return done_;
1948
+ }}"""
1949
+ ),
1950
+ Stripped(
1951
+ f"""\
1952
+ const Error& RecursiveVerificator::Get() const {{
1953
+ {I}#ifdef DEBUG
1954
+ {I}if (Done()) {{
1955
+ {II}throw std::logic_error(
1956
+ {III}"You want to get from a RecursiveVerificator, "
1957
+ {III}"but the verificator is done."
1958
+ {II});
1959
+ {I}}}
1960
+ {I}#endif
1961
+
1962
+ {I}return *error_;
1963
+ }}"""
1964
+ ),
1965
+ Stripped(
1966
+ f"""\
1967
+ Error& RecursiveVerificator::GetMutable() {{
1968
+ {I}#ifdef DEBUG
1969
+ {I}if (Done()) {{
1970
+ {II}throw std::logic_error(
1971
+ {III}"You want to get mutable from a RecursiveVerificator, "
1972
+ {III}"but the verificator is done."
1973
+ {II});
1974
+ {I}}}
1975
+ {I}#endif
1976
+
1977
+ {I}return *error_;
1978
+ }}"""
1979
+ ),
1980
+ Stripped(
1981
+ f"""\
1982
+ long RecursiveVerificator::Index() const {{
1983
+ {I}#ifdef DEBUG
1984
+ {I}if (Done() && index_ != -1) {{
1985
+ {II}throw std::logic_error(
1986
+ {III}common::Concat(
1987
+ {IIII}"Expected index to be -1 "
1988
+ {IIII}"from a done RecursiveVerificator, "
1989
+ {IIII}"but got: ",
1990
+ {IIII}std::to_string(index_)
1991
+ {III})
1992
+ {II});
1993
+ {I}}}
1994
+ {I}#endif
1995
+
1996
+ {I}return index_;
1997
+ }}"""
1998
+ ),
1999
+ Stripped(
2000
+ f"""\
2001
+ std::unique_ptr<impl::IVerificator> RecursiveVerificator::Clone() const {{
2002
+ {I}return common::make_unique<RecursiveVerificator>(*this);
2003
+ }}"""
2004
+ ),
2005
+ ] # type: List[Stripped]
2006
+
2007
+ execute_block = _generate_recursive_verificator_execute()
2008
+ blocks.append(execute_block)
2009
+
2010
+ return blocks
2011
+
2012
+
2013
+ def _generate_pattern_verification_implementation(
2014
+ verification: intermediate.PatternVerification,
2015
+ ) -> Stripped:
2016
+ """Generate the implementation of the given pattern verification function."""
2017
+ assert len(verification.arguments) == 1
2018
+ arg = verification.arguments[0]
2019
+
2020
+ arg_type = cpp_common.generate_type_with_const_ref_if_applicable(
2021
+ type_annotation=arg.type_annotation, types_namespace=cpp_common.TYPES_NAMESPACE
2022
+ )
2023
+ arg_name = cpp_naming.argument_name(arg.name)
2024
+
2025
+ verification_name = cpp_naming.function_name(verification.name)
2026
+
2027
+ program_name = cpp_naming.constant_name(Identifier(f"{verification.name}_program"))
2028
+
2029
+ return Stripped(
2030
+ f"""\
2031
+ bool {verification_name}(
2032
+ {I}{indent_but_first_line(arg_type, I)} {arg_name}
2033
+ ) {{
2034
+ {I}return revm::Match(
2035
+ {II}pattern::{program_name},
2036
+ {II}{arg_name}
2037
+ {I});
2038
+ }}"""
2039
+ )
2040
+
2041
+
2042
+ class _TranspilableVerificationTranspiler(cpp_transpilation.Transpiler):
2043
+ """Transpile the body of a :class:`TranspilableVerification`."""
2044
+
2045
+ # fmt: off
2046
+ @require(
2047
+ lambda environment, verification:
2048
+ all(
2049
+ environment.find(arg.name) is not None
2050
+ for arg in verification.arguments
2051
+ ),
2052
+ "All arguments defined in the environment"
2053
+ )
2054
+ # fmt: on
2055
+ def __init__(
2056
+ self,
2057
+ type_map: Mapping[
2058
+ parse_tree.Node, intermediate_type_inference.TypeAnnotationUnion
2059
+ ],
2060
+ is_optional_map: Mapping[parse_tree.Node, bool],
2061
+ environment: intermediate_type_inference.Environment,
2062
+ symbol_table: intermediate.SymbolTable,
2063
+ verification: intermediate.TranspilableVerification,
2064
+ ) -> None:
2065
+ """Initialize with the given values."""
2066
+ cpp_transpilation.Transpiler.__init__(
2067
+ self,
2068
+ type_map=type_map,
2069
+ is_optional_map=is_optional_map,
2070
+ environment=environment,
2071
+ types_namespace=cpp_common.TYPES_NAMESPACE,
2072
+ )
2073
+
2074
+ self._symbol_table = symbol_table
2075
+
2076
+ self._argument_name_set = frozenset(arg.name for arg in verification.arguments)
2077
+
2078
+ def transform_name(
2079
+ self, node: parse_tree.Name
2080
+ ) -> Tuple[Optional[Stripped], Optional[Error]]:
2081
+ if node.identifier in self._variable_name_set:
2082
+ return Stripped(cpp_naming.variable_name(node.identifier)), None
2083
+
2084
+ if node.identifier in self._argument_name_set:
2085
+ return Stripped(cpp_naming.argument_name(node.identifier)), None
2086
+
2087
+ if node.identifier in self._symbol_table.constants_by_name:
2088
+ constant = cpp_naming.constant_name(node.identifier)
2089
+ return Stripped(f"{cpp_common.CONSTANTS_NAMESPACE}::{constant}"), None
2090
+
2091
+ if node.identifier in self._symbol_table.verification_functions_by_name:
2092
+ return Stripped(cpp_naming.function_name(node.identifier)), None
2093
+
2094
+ our_type = self._symbol_table.find_our_type(name=node.identifier)
2095
+ if isinstance(our_type, intermediate.Enumeration):
2096
+ return (
2097
+ Stripped(
2098
+ f"{cpp_common.TYPES_NAMESPACE}::{cpp_naming.enum_name(node.identifier)}"
2099
+ ),
2100
+ None,
2101
+ )
2102
+
2103
+ return None, Error(
2104
+ node.original_node,
2105
+ f"We can not determine how to transpile the name {node.identifier!r} "
2106
+ f"to C++. We could not find it neither in the constants, nor in "
2107
+ f"verification functions, nor as an enumeration. "
2108
+ f"If you expect this name to be transpilable, please contact "
2109
+ f"the developers.",
2110
+ )
2111
+
2112
+
2113
+ @ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
2114
+ def _generate_implementation_of_transpilable_verification(
2115
+ verification: intermediate.TranspilableVerification,
2116
+ symbol_table: intermediate.SymbolTable,
2117
+ base_environment: intermediate_type_inference.Environment,
2118
+ ) -> Tuple[Optional[Stripped], Optional[Error]]:
2119
+ """Transpile the verification to a function implementation."""
2120
+ # fmt: off
2121
+ type_inference, inference_error = (
2122
+ intermediate_type_inference.infer_for_verification(
2123
+ verification=verification,
2124
+ base_environment=base_environment
2125
+ )
2126
+ )
2127
+ # fmt: on
2128
+
2129
+ if inference_error is not None:
2130
+ return None, inference_error
2131
+
2132
+ assert type_inference is not None
2133
+
2134
+ optional_inferrer = cpp_optionaling.Inferrer(
2135
+ environment=type_inference.environment_with_args,
2136
+ type_map=type_inference.type_map,
2137
+ )
2138
+ for node in verification.parsed.body:
2139
+ _ = optional_inferrer.transform(node)
2140
+
2141
+ if len(optional_inferrer.errors) > 0:
2142
+ return None, Error(
2143
+ verification.parsed.node,
2144
+ f"Failed to infer whether one or more nodes are ``common::optional`` "
2145
+ f"in the verification function {verification.name!r}",
2146
+ optional_inferrer.errors,
2147
+ )
2148
+
2149
+ transpiler = _TranspilableVerificationTranspiler(
2150
+ type_map=type_inference.type_map,
2151
+ is_optional_map=optional_inferrer.is_optional_map,
2152
+ environment=type_inference.environment_with_args,
2153
+ symbol_table=symbol_table,
2154
+ verification=verification,
2155
+ )
2156
+
2157
+ body = [] # type: List[Stripped]
2158
+ for node in verification.parsed.body:
2159
+ stmt, error = transpiler.transform(node)
2160
+ if error is not None:
2161
+ return None, Error(
2162
+ verification.parsed.node,
2163
+ f"Failed to transpile the verification function {verification.name!r}",
2164
+ [error],
2165
+ )
2166
+
2167
+ assert stmt is not None
2168
+ body.append(stmt)
2169
+
2170
+ arg_types_names = [
2171
+ (
2172
+ cpp_common.generate_type_with_const_ref_if_applicable(
2173
+ type_annotation=arg.type_annotation,
2174
+ types_namespace=cpp_common.TYPES_NAMESPACE,
2175
+ ),
2176
+ cpp_naming.argument_name(arg.name),
2177
+ )
2178
+ for arg in verification.arguments
2179
+ ]
2180
+
2181
+ function_name = cpp_naming.function_name(verification.name)
2182
+ arg_definitions_joined = ",\n".join(
2183
+ f"{arg_type} {arg_name}" for arg_type, arg_name in arg_types_names
2184
+ )
2185
+
2186
+ body_joined = "\n".join(body)
2187
+
2188
+ return (
2189
+ Stripped(
2190
+ f"""\
2191
+ bool {function_name}(
2192
+ {I}{indent_but_first_line(arg_definitions_joined, I)}
2193
+ ) {{
2194
+ {I}{indent_but_first_line(body_joined, I)}
2195
+ }}"""
2196
+ ),
2197
+ None,
2198
+ )
2199
+
2200
+
2201
+ @require(lambda constrained_primitive: len(constrained_primitive.invariants) == 0)
2202
+ def _generate_empty_constrained_primitive_verificator(
2203
+ constrained_primitive: intermediate.ConstrainedPrimitive,
2204
+ ) -> List[Stripped]:
2205
+ """
2206
+ Generate a constrained primitive verificator which is always done.
2207
+
2208
+ Though the implementation is a duplicate in logic of ``AlwaysDoneVerificator``,
2209
+ the assertion error messages are different, so we generate a separate class.
2210
+ """
2211
+ of_constrained_primitive = cpp_naming.class_name(
2212
+ Identifier(f"Of_{constrained_primitive.name}")
2213
+ )
2214
+
2215
+ value_type = cpp_common.generate_primitive_type_with_const_ref_if_applicable(
2216
+ primitive_type=constrained_primitive.constrainee
2217
+ )
2218
+
2219
+ return [
2220
+ Stripped(
2221
+ f"""\
2222
+ class {of_constrained_primitive} : public impl::IVerificator {{
2223
+ public:
2224
+ {I}{of_constrained_primitive}(
2225
+ {II}{value_type} value
2226
+ {I});
2227
+
2228
+ {I}void Start() override;
2229
+ {I}void Next() override;
2230
+ {I}bool Done() const override;
2231
+ {I}const Error& Get() const override;
2232
+ {I}Error& GetMutable() override;
2233
+ {I}long Index() const override;
2234
+
2235
+ {I}std::unique_ptr<impl::IVerificator> Clone() const override;
2236
+
2237
+ {I}virtual ~{of_constrained_primitive}() = default;
2238
+ }}; // class {of_constrained_primitive}"""
2239
+ ),
2240
+ Stripped(
2241
+ f"""\
2242
+ {of_constrained_primitive}::{of_constrained_primitive}(
2243
+ {I}{value_type}
2244
+ ) {{
2245
+ {I}// Intentionally empty.
2246
+ }}"""
2247
+ ),
2248
+ Stripped(
2249
+ f"""\
2250
+ void {of_constrained_primitive}::Start() {{
2251
+ {I}// Intentionally empty.
2252
+ }}"""
2253
+ ),
2254
+ Stripped(
2255
+ f"""\
2256
+ void {of_constrained_primitive}::Next() {{
2257
+ {I}throw std::logic_error(
2258
+ {II}"You want to move "
2259
+ {II}"a verificator {of_constrained_primitive}, "
2260
+ {II}"but the verificator is always done as "
2261
+ {II}"there are no invariants defined for this constrained primitive."
2262
+ {I});
2263
+ }}"""
2264
+ ),
2265
+ Stripped(
2266
+ f"""\
2267
+ bool {of_constrained_primitive}::Done() const {{
2268
+ {I}return true;
2269
+ }}"""
2270
+ ),
2271
+ Stripped(
2272
+ f"""\
2273
+ const Error& {of_constrained_primitive}::Get() const {{
2274
+ {I}throw std::logic_error(
2275
+ {II}"You want to get from "
2276
+ {II}"a verificator {of_constrained_primitive}, "
2277
+ {II}"but the verificator is always done as "
2278
+ {II}"there are no invariants defined for this constrained primitive."
2279
+ {I});
2280
+ }}"""
2281
+ ),
2282
+ Stripped(
2283
+ f"""\
2284
+ Error& {of_constrained_primitive}::GetMutable() {{
2285
+ {I}throw std::logic_error(
2286
+ {II}"You want to get mutable from "
2287
+ {II}"a verificator {of_constrained_primitive}, "
2288
+ {II}"but the verificator is always done as "
2289
+ {II}"there are no invariants defined for this constrained primitive."
2290
+ {I});
2291
+ }}"""
2292
+ ),
2293
+ Stripped(
2294
+ f"""\
2295
+ long {of_constrained_primitive}::Index() const {{
2296
+ {I}return -1;
2297
+ }}"""
2298
+ ),
2299
+ Stripped(
2300
+ f"""\
2301
+ std::unique_ptr<impl::IVerificator> {of_constrained_primitive}::Clone() const {{
2302
+ {I}return common::make_unique<
2303
+ {II}{of_constrained_primitive}
2304
+ {I}>(*this);
2305
+ }}"""
2306
+ ),
2307
+ ]
2308
+
2309
+
2310
+ class _ConstrainedPrimitiveInvariantTranspiler(cpp_transpilation.Transpiler):
2311
+ """Transpile invariants of the constrained primitives."""
2312
+
2313
+ def __init__(
2314
+ self,
2315
+ type_map: Mapping[
2316
+ parse_tree.Node, intermediate_type_inference.TypeAnnotationUnion
2317
+ ],
2318
+ is_optional_map: Mapping[parse_tree.Node, bool],
2319
+ environment: intermediate_type_inference.Environment,
2320
+ symbol_table: intermediate.SymbolTable,
2321
+ constrained_primitive: intermediate.ConstrainedPrimitive,
2322
+ ) -> None:
2323
+ """Initialize with the given values."""
2324
+ cpp_transpilation.Transpiler.__init__(
2325
+ self,
2326
+ type_map=type_map,
2327
+ is_optional_map=is_optional_map,
2328
+ environment=environment,
2329
+ types_namespace=cpp_common.TYPES_NAMESPACE,
2330
+ )
2331
+
2332
+ self._symbol_table = symbol_table
2333
+ self._constrained_primitive = constrained_primitive
2334
+
2335
+ def transform_name(
2336
+ self, node: parse_tree.Name
2337
+ ) -> Tuple[Optional[Stripped], Optional[Error]]:
2338
+ if node.identifier in self._variable_name_set:
2339
+ return Stripped(cpp_naming.variable_name(node.identifier)), None
2340
+
2341
+ if node.identifier == "self":
2342
+ # The ``value_`` refers to the value under verification.
2343
+ if _constrained_primitive_verificator_value_is_pointer(
2344
+ primitive_type=self._constrained_primitive.constrainee
2345
+ ):
2346
+ return Stripped("(*value_)"), None
2347
+ else:
2348
+ return Stripped("value_"), None
2349
+
2350
+ if node.identifier in self._symbol_table.constants_by_name:
2351
+ constant = cpp_naming.constant_name(node.identifier)
2352
+ return Stripped(f"{cpp_common.CONSTANTS_NAMESPACE}::{constant}"), None
2353
+
2354
+ if node.identifier in self._symbol_table.verification_functions_by_name:
2355
+ return Stripped(cpp_naming.function_name(node.identifier)), None
2356
+
2357
+ our_type = self._symbol_table.find_our_type(name=node.identifier)
2358
+ if isinstance(our_type, intermediate.Enumeration):
2359
+ return (
2360
+ Stripped(
2361
+ f"{cpp_common.TYPES_NAMESPACE}::{cpp_naming.enum_name(node.identifier)}"
2362
+ ),
2363
+ None,
2364
+ )
2365
+
2366
+ return None, Error(
2367
+ node.original_node,
2368
+ f"We can not determine how to transpile the name {node.identifier!r} "
2369
+ f"to C++. We could not find it neither in the local variables, "
2370
+ f"nor in the global constants, nor in verification functions, "
2371
+ f"nor as an enumeration. If you expect this name to be transpilable, "
2372
+ f"please contact the developers.",
2373
+ )
2374
+
2375
+
2376
+ # fmt: off
2377
+ @require(
2378
+ lambda invariant, constrained_primitive:
2379
+ id(invariant) in constrained_primitive.invariant_id_set
2380
+ )
2381
+ @ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
2382
+ # fmt: on
2383
+ def _transpile_constrained_primitive_invariant(
2384
+ invariant: intermediate.Invariant,
2385
+ symbol_table: intermediate.SymbolTable,
2386
+ environment: intermediate_type_inference.Environment,
2387
+ constrained_primitive: intermediate.ConstrainedPrimitive,
2388
+ ) -> Tuple[Optional[Stripped], Optional[Error]]:
2389
+ """Translate the invariant from the meta-model into a C++ condition."""
2390
+ # fmt: off
2391
+ type_map, inference_error = (
2392
+ intermediate_type_inference.infer_for_invariant(
2393
+ invariant=invariant,
2394
+ environment=environment
2395
+ )
2396
+ )
2397
+ # fmt: on
2398
+
2399
+ if inference_error is not None:
2400
+ return None, inference_error
2401
+
2402
+ assert type_map is not None
2403
+
2404
+ optional_inferrer = cpp_optionaling.Inferrer(
2405
+ environment=environment, type_map=type_map
2406
+ )
2407
+
2408
+ _ = optional_inferrer.transform(invariant.body)
2409
+
2410
+ if len(optional_inferrer.errors) > 0:
2411
+ return None, Error(
2412
+ invariant.parsed.node,
2413
+ "Failed to infer whether one or more nodes are ``common::optional`` "
2414
+ "in the invariant",
2415
+ optional_inferrer.errors,
2416
+ )
2417
+
2418
+ transpiler = _ConstrainedPrimitiveInvariantTranspiler(
2419
+ type_map=type_map,
2420
+ is_optional_map=optional_inferrer.is_optional_map,
2421
+ environment=environment,
2422
+ symbol_table=symbol_table,
2423
+ constrained_primitive=constrained_primitive,
2424
+ )
2425
+
2426
+ expr, error = transpiler.transform(invariant.body)
2427
+
2428
+ if error is not None:
2429
+ return None, error
2430
+
2431
+ assert expr is not None
2432
+ return expr, None
2433
+
2434
+
2435
+ @require(lambda constrained_primitive: len(constrained_primitive.invariants) > 0)
2436
+ def _generate_constrained_primitive_verificator_execute(
2437
+ constrained_primitive: intermediate.ConstrainedPrimitive,
2438
+ symbol_table: intermediate.SymbolTable,
2439
+ environment: intermediate_type_inference.Environment,
2440
+ ) -> Tuple[Optional[Stripped], Optional[List[Error]]]:
2441
+ """Generate the ``Execute()`` in the constrained primitive verificator."""
2442
+ flow = [
2443
+ yielding_flow.command_from_text(
2444
+ """\
2445
+ done_ = false;
2446
+ error_ = nullptr;
2447
+ index_ = -1;"""
2448
+ )
2449
+ ] # type: List[yielding_flow.Node]
2450
+
2451
+ errors = [] # type: List[Error]
2452
+ for invariant in constrained_primitive.invariants:
2453
+ condition_expr, error = _transpile_constrained_primitive_invariant(
2454
+ invariant=invariant,
2455
+ symbol_table=symbol_table,
2456
+ environment=environment,
2457
+ constrained_primitive=constrained_primitive,
2458
+ )
2459
+ if error is not None:
2460
+ errors.append(error)
2461
+ continue
2462
+
2463
+ assert condition_expr is not None
2464
+
2465
+ # NOTE (mristin, 2023-11-01):
2466
+ # We need to wrap the description in multiple literals as a single long
2467
+ # string literal is often too much for the readability.
2468
+ invariant_description_lines = wrap_text_into_lines(invariant.description)
2469
+
2470
+ invariant_description_literals_joined = "\n".join(
2471
+ cpp_common.wstring_literal(line) for line in invariant_description_lines
2472
+ )
2473
+
2474
+ flow.append(
2475
+ yielding_flow.IfFalse(
2476
+ condition_expr,
2477
+ [
2478
+ yielding_flow.command_from_text(
2479
+ f"""\
2480
+ error_ = common::make_unique<Error>(
2481
+ {I}{indent_but_first_line(invariant_description_literals_joined, I)}
2482
+ );
2483
+ // No path is prepended as the error refers to the value itself.
2484
+ ++index_;"""
2485
+ ),
2486
+ yielding_flow.Yield(),
2487
+ ],
2488
+ )
2489
+ )
2490
+
2491
+ flow.append(
2492
+ yielding_flow.command_from_text(
2493
+ """\
2494
+ done_ = true;
2495
+ error_ = nullptr;
2496
+ index_ = -1;"""
2497
+ )
2498
+ )
2499
+
2500
+ if len(errors) > 0:
2501
+ return None, errors
2502
+
2503
+ code = cpp_yielding.generate_execute_body(
2504
+ flow=flow, state_member=Identifier("state_")
2505
+ )
2506
+
2507
+ of_constrained_primitive = cpp_naming.class_name(
2508
+ Identifier(f"of_{constrained_primitive.name}")
2509
+ )
2510
+
2511
+ return (
2512
+ Stripped(
2513
+ f"""\
2514
+ void {of_constrained_primitive}::Execute() {{
2515
+ {I}{indent_but_first_line(code, I)}
2516
+ }}"""
2517
+ ),
2518
+ None,
2519
+ )
2520
+
2521
+
2522
+ @ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
2523
+ def _generate_constrained_primitive_verificator(
2524
+ constrained_primitive: intermediate.ConstrainedPrimitive,
2525
+ symbol_table: intermediate.SymbolTable,
2526
+ environment: intermediate_type_inference.Environment,
2527
+ ) -> Tuple[Optional[List[Stripped]], Optional[Error]]:
2528
+ """Generate the def. and impl. of a verificator for a constrained primitive."""
2529
+ if len(constrained_primitive.invariants) == 0:
2530
+ return (
2531
+ _generate_empty_constrained_primitive_verificator(
2532
+ constrained_primitive=constrained_primitive
2533
+ ),
2534
+ None,
2535
+ )
2536
+
2537
+ of_constrained_primitive = cpp_naming.class_name(
2538
+ Identifier(f"Of_{constrained_primitive.name}")
2539
+ )
2540
+
2541
+ input_value_type = cpp_common.generate_primitive_type_with_const_ref_if_applicable(
2542
+ primitive_type=constrained_primitive.constrainee
2543
+ )
2544
+
2545
+ value_type = cpp_common.generate_primitive_type(constrained_primitive.constrainee)
2546
+ if _constrained_primitive_verificator_value_is_pointer(
2547
+ constrained_primitive.constrainee
2548
+ ):
2549
+ data_value_type = f"const {value_type}*"
2550
+
2551
+ constructor_init = "value_(&value)"
2552
+
2553
+ else:
2554
+ data_value_type = value_type
2555
+
2556
+ constructor_init = "value_(value)"
2557
+
2558
+ move_snippet = Stripped(
2559
+ """\
2560
+ value_ = other.value_;
2561
+ index_ = other.index_;
2562
+ error_ = std::move(other.error_);
2563
+ done_ = other.done_;
2564
+ state_ = other.state_;"""
2565
+ )
2566
+
2567
+ blocks = [
2568
+ Stripped(
2569
+ f"""\
2570
+ class {of_constrained_primitive} : public impl::IVerificator {{
2571
+ public:
2572
+ {I}{of_constrained_primitive}(
2573
+ {II}{input_value_type} value
2574
+ {I});
2575
+
2576
+ {I}{of_constrained_primitive}(
2577
+ {II}const {of_constrained_primitive}& other
2578
+ {I});
2579
+ {I}{of_constrained_primitive}(
2580
+ {II}{of_constrained_primitive}&& other
2581
+ {I});
2582
+ {I}{of_constrained_primitive}& operator=(
2583
+ {II}const {of_constrained_primitive}& other
2584
+ {I});
2585
+ {I}{of_constrained_primitive}& operator=(
2586
+ {II}{of_constrained_primitive}&& other
2587
+ {I});
2588
+
2589
+ {I}void Start() override;
2590
+ {I}void Next() override;
2591
+ {I}bool Done() const override;
2592
+ {I}const Error& Get() const override;
2593
+ {I}Error& GetMutable() override;
2594
+ {I}long Index() const override;
2595
+
2596
+ {I}std::unique_ptr<impl::IVerificator> Clone() const override;
2597
+
2598
+ {I}~{of_constrained_primitive}() override = default;
2599
+
2600
+ private:
2601
+ {I}{data_value_type} value_;
2602
+ {I}long index_;
2603
+ {I}std::unique_ptr<Error> error_;
2604
+ {I}bool done_;
2605
+ {I}std::uint32_t state_;
2606
+
2607
+ {I}void Execute();
2608
+ }}; // class {of_constrained_primitive}"""
2609
+ ),
2610
+ Stripped(
2611
+ f"""\
2612
+ {of_constrained_primitive}::{of_constrained_primitive}(
2613
+ {I}{input_value_type} value
2614
+ ) : {constructor_init} {{
2615
+ {I}// Intentionally empty.
2616
+ }}"""
2617
+ ),
2618
+ Stripped(
2619
+ f"""\
2620
+ {of_constrained_primitive}::{of_constrained_primitive}(
2621
+ {I}const {of_constrained_primitive}& other
2622
+ ) {{
2623
+ {I}value_ = other.value_;
2624
+ {I}index_ = other.index_;
2625
+ {I}error_ = common::make_unique<Error>(*other.error_);
2626
+ {I}done_ = other.done_;
2627
+ {I}state_ = other.state_;
2628
+ }}"""
2629
+ ),
2630
+ Stripped(
2631
+ f"""\
2632
+ {of_constrained_primitive}::{of_constrained_primitive}(
2633
+ {I}{of_constrained_primitive}&& other
2634
+ ) {{
2635
+ {I}{indent_but_first_line(move_snippet, I)}
2636
+ }}"""
2637
+ ),
2638
+ Stripped(
2639
+ f"""\
2640
+ {of_constrained_primitive}& {of_constrained_primitive}::operator=(
2641
+ {I}const {of_constrained_primitive}& other
2642
+ ) {{
2643
+ {I}return *this = {of_constrained_primitive}(other);
2644
+ }}"""
2645
+ ),
2646
+ Stripped(
2647
+ f"""\
2648
+ {of_constrained_primitive}& {of_constrained_primitive}::operator=(
2649
+ {I}{of_constrained_primitive}&& other
2650
+ ) {{
2651
+ {I}if (this != &other) {{
2652
+ {II}{indent_but_first_line(move_snippet, II)}
2653
+ {I}}}
2654
+
2655
+ {I}return *this;
2656
+ }}"""
2657
+ ),
2658
+ Stripped(
2659
+ f"""\
2660
+ void {of_constrained_primitive}::Start() {{
2661
+ {I}state_ = 0;
2662
+ {I}Execute();
2663
+ }}"""
2664
+ ),
2665
+ Stripped(
2666
+ f"""\
2667
+ void {of_constrained_primitive}::Next() {{
2668
+ {I}#ifdef DEBUG
2669
+ {I}if (Done()) {{
2670
+ {II}throw std::logic_error(
2671
+ {III}"You want to move a verificator {of_constrained_primitive}, "
2672
+ {III}"but the verificator was done."
2673
+ {II});
2674
+ {I}}}
2675
+ {I}#endif
2676
+
2677
+ {I}Execute();
2678
+ }}"""
2679
+ ),
2680
+ Stripped(
2681
+ f"""\
2682
+ bool {of_constrained_primitive}::Done() const {{
2683
+ {I}return done_;
2684
+ }}"""
2685
+ ),
2686
+ Stripped(
2687
+ f"""\
2688
+ const Error& {of_constrained_primitive}::Get() const {{
2689
+ {I}#ifdef DEBUG
2690
+ {I}if (Done()) {{
2691
+ {II}throw std::logic_error(
2692
+ {III}"You want to get from a verificator {of_constrained_primitive}, "
2693
+ {III}"but the verificator was done."
2694
+ {II});
2695
+ {I}}}
2696
+ {I}#endif
2697
+
2698
+ {I}return *error_;
2699
+ }}"""
2700
+ ),
2701
+ Stripped(
2702
+ f"""\
2703
+ Error& {of_constrained_primitive}::GetMutable() {{
2704
+ {I}#ifdef DEBUG
2705
+ {I}if (Done()) {{
2706
+ {II}throw std::logic_error(
2707
+ {III}"You want to get mutable from a verificator {of_constrained_primitive}, "
2708
+ {III}"but the verificator was done."
2709
+ {II});
2710
+ {I}}}
2711
+ {I}#endif
2712
+
2713
+ {I}return *error_;
2714
+ }}"""
2715
+ ),
2716
+ Stripped(
2717
+ f"""\
2718
+ long {of_constrained_primitive}::Index() const {{
2719
+ {I}#ifdef DEBUG
2720
+ {I}if (Done() && index_ != -1) {{
2721
+ {II}throw std::logic_error(
2722
+ {III}common::Concat(
2723
+ {IIII}"Expected index to be -1 "
2724
+ {IIII}"from a done verificator {of_constrained_primitive}, "
2725
+ {IIII}"but got: ",
2726
+ {IIII}std::to_string(index_)
2727
+ {III})
2728
+ {II});
2729
+ {I}}}
2730
+ {I}#endif
2731
+
2732
+ {I}return index_;
2733
+ }}"""
2734
+ ),
2735
+ Stripped(
2736
+ f"""\
2737
+ std::unique_ptr<impl::IVerificator> {of_constrained_primitive}::Clone() const {{
2738
+ {I}return common::make_unique<
2739
+ {II}{of_constrained_primitive}
2740
+ {I}>(*this);
2741
+ }}"""
2742
+ ),
2743
+ ] # type: List[Stripped]
2744
+
2745
+ execute_block, execute_errors = _generate_constrained_primitive_verificator_execute(
2746
+ constrained_primitive=constrained_primitive,
2747
+ symbol_table=symbol_table,
2748
+ environment=environment,
2749
+ )
2750
+ if execute_errors is not None:
2751
+ return None, Error(
2752
+ constrained_primitive.parsed.node,
2753
+ f"Failed to generate Execute() method for {of_constrained_primitive!r}",
2754
+ execute_errors,
2755
+ )
2756
+
2757
+ assert execute_block is not None
2758
+ blocks.append(execute_block)
2759
+
2760
+ return blocks, None
2761
+
2762
+
2763
+ def _generate_implementation_of_verify_constrained_primitive(
2764
+ constrained_primitive: intermediate.ConstrainedPrimitive,
2765
+ ) -> Stripped:
2766
+ """Generate the implementation of the function ``Verify{Constrained Primitive}``."""
2767
+ verify_name = cpp_naming.function_name(
2768
+ Identifier(f"verify_{constrained_primitive.name}")
2769
+ )
2770
+
2771
+ of_constrained_primitive = cpp_naming.class_name(
2772
+ Identifier(f"Of_{constrained_primitive.name}")
2773
+ )
2774
+
2775
+ value_type = cpp_common.generate_primitive_type_with_const_ref_if_applicable(
2776
+ primitive_type=constrained_primitive.constrainee
2777
+ )
2778
+
2779
+ return Stripped(
2780
+ f"""\
2781
+ std::unique_ptr<IVerification> {verify_name}(
2782
+ {I}{value_type} that
2783
+ ) {{
2784
+ {I}return common::make_unique<
2785
+ {II}constrained_primitive_verification::{of_constrained_primitive}
2786
+ {I}>(that);
2787
+ }}"""
2788
+ )
2789
+
2790
+
2791
+ def _generate_constrained_primitive_verification(
2792
+ constrained_primitive: intermediate.ConstrainedPrimitive,
2793
+ ) -> List[Stripped]:
2794
+ """Generate the verification class for the constrained primitive."""
2795
+ of_constrained_primitive = cpp_naming.class_name(
2796
+ Identifier(f"Of_{constrained_primitive.name}")
2797
+ )
2798
+
2799
+ value_type = cpp_common.generate_primitive_type_with_const_ref_if_applicable(
2800
+ primitive_type=constrained_primitive.constrainee
2801
+ )
2802
+
2803
+ return [
2804
+ Stripped(f"// region {of_constrained_primitive}"),
2805
+ Stripped(
2806
+ f"""\
2807
+ class {of_constrained_primitive} : public IVerification {{
2808
+ public:
2809
+ {I}{of_constrained_primitive}(
2810
+ {II}{value_type} value
2811
+ {I});
2812
+
2813
+ {I}Iterator begin() const override;
2814
+ {I}const Iterator& end() const override;
2815
+
2816
+ {I}~{of_constrained_primitive}() override = default;
2817
+ private:
2818
+ {I}{value_type} value_;
2819
+ }}; // class ConstrainedPrimitiveVerification"""
2820
+ ),
2821
+ Stripped(
2822
+ f"""\
2823
+ {of_constrained_primitive}::{of_constrained_primitive}(
2824
+ {I}{value_type} value
2825
+ ) : value_(value) {{
2826
+ {I}// Intentionally empty.
2827
+ }}"""
2828
+ ),
2829
+ Stripped(
2830
+ f"""\
2831
+ Iterator {of_constrained_primitive}::begin() const {{
2832
+ {I}std::unique_ptr<impl::IVerificator> verificator(
2833
+ {II}common::make_unique<
2834
+ {III}constrained_primitive_verificator::{of_constrained_primitive}
2835
+ {II}>(value_)
2836
+ {I});
2837
+
2838
+ {I}verificator->Start();
2839
+
2840
+ {I}// NOTE(mristin):
2841
+ {I}// We short-circuit here for efficiency, as we can immediately dispose
2842
+ {I}// of the verificator.
2843
+ {I}if (verificator->Done()) {{
2844
+ {II}return Iterator(common::make_unique<AlwaysDoneVerificator>());
2845
+ {I}}}
2846
+
2847
+ {I}return Iterator(std::move(verificator));
2848
+ }}"""
2849
+ ),
2850
+ Stripped(
2851
+ f"""\
2852
+ const Iterator& {of_constrained_primitive}::end() const {{
2853
+ {I}static Iterator iterator(common::make_unique<AlwaysDoneVerificator>());
2854
+ {I}return iterator;
2855
+ }}"""
2856
+ ),
2857
+ Stripped(f"// endregion {of_constrained_primitive}"),
2858
+ ]
2859
+
2860
+
2861
+ # fmt: off
2862
+ @ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
2863
+ @ensure(
2864
+ lambda result:
2865
+ not (result[0] is not None) or result[0].endswith('\n'),
2866
+ "Trailing newline mandatory for valid end-of-files"
2867
+ )
2868
+ # fmt: on
2869
+ def generate_implementation(
2870
+ symbol_table: intermediate.SymbolTable,
2871
+ spec_impls: specific_implementations.SpecificImplementations,
2872
+ library_namespace: Stripped,
2873
+ ) -> Tuple[Optional[str], Optional[List[Error]]]:
2874
+ """Generate the C++ implementation of the verification code.."""
2875
+ namespace = Stripped(f"{library_namespace}::{cpp_common.VERIFICATION_NAMESPACE}")
2876
+
2877
+ include_prefix_path = cpp_common.generate_include_prefix_path(library_namespace)
2878
+
2879
+ errors = [] # type: List[Error]
2880
+
2881
+ base_environment = intermediate_type_inference.populate_base_environment(
2882
+ symbol_table=symbol_table
2883
+ )
2884
+
2885
+ blocks = [
2886
+ cpp_common.WARNING,
2887
+ Stripped(
2888
+ f"""\
2889
+ #include "{include_prefix_path}/common.hpp"
2890
+ #include "{include_prefix_path}/constants.hpp"
2891
+ #include "{include_prefix_path}/pattern.hpp"
2892
+ #include "{include_prefix_path}/revm.hpp"
2893
+ #include "{include_prefix_path}/verification.hpp"
2894
+
2895
+ #pragma warning(push, 0)
2896
+ #include <map>
2897
+ #include <set>
2898
+ #pragma warning(pop)"""
2899
+ ),
2900
+ cpp_common.generate_namespace_opening(namespace),
2901
+ *_generate_error_implementation(),
2902
+ *_generate_always_done_verificator(),
2903
+ ] # type: List[Stripped]
2904
+
2905
+ if len(symbol_table.verification_functions) > 0:
2906
+ blocks.append(Stripped("// region Verification functions"))
2907
+
2908
+ for verification in symbol_table.verification_functions:
2909
+ if isinstance(verification, intermediate.PatternVerification):
2910
+ blocks.append(
2911
+ _generate_pattern_verification_implementation(
2912
+ verification=verification
2913
+ )
2914
+ )
2915
+
2916
+ elif isinstance(verification, intermediate.TranspilableVerification):
2917
+ block, error = _generate_implementation_of_transpilable_verification(
2918
+ verification=verification,
2919
+ symbol_table=symbol_table,
2920
+ base_environment=base_environment,
2921
+ )
2922
+
2923
+ if error is not None:
2924
+ errors.append(error)
2925
+ else:
2926
+ assert block is not None
2927
+ blocks.append(block)
2928
+
2929
+ elif isinstance(
2930
+ verification, intermediate.ImplementationSpecificVerification
2931
+ ):
2932
+ implementation_key = specific_implementations.ImplementationKey(
2933
+ f"verification/{verification.name}.cpp"
2934
+ )
2935
+
2936
+ block = spec_impls.get(implementation_key, None)
2937
+
2938
+ if block is None:
2939
+ errors.append(
2940
+ Error(
2941
+ verification.parsed.node,
2942
+ f"The implementation is missing for "
2943
+ f"the implementation-specific verification "
2944
+ f"function: {implementation_key}",
2945
+ )
2946
+ )
2947
+ else:
2948
+ # NOTE (mristin, 2024-01-09):
2949
+ # Some verification functions only live in the header and have
2950
+ # no code in the implementation file. For example, the verification
2951
+ # functions which are templated.
2952
+ if len(block.strip()) > 0:
2953
+ blocks.append(block)
2954
+ else:
2955
+ assert_never(verification)
2956
+
2957
+ blocks.append(Stripped("// endregion Verification functions"))
2958
+
2959
+ if len(symbol_table.constrained_primitives) > 0:
2960
+ blocks.append(Stripped("// region Verification of constrained primitives"))
2961
+
2962
+ blocks.append(Stripped("namespace constrained_primitive_verificator {"))
2963
+
2964
+ for constrained_primitive in symbol_table.constrained_primitives:
2965
+ invariant_environment = intermediate_type_inference.MutableEnvironment(
2966
+ parent=base_environment
2967
+ )
2968
+
2969
+ assert invariant_environment.find(Identifier("self")) is None
2970
+ invariant_environment.set(
2971
+ identifier=Identifier("self"),
2972
+ type_annotation=intermediate_type_inference.OurTypeAnnotation(
2973
+ our_type=constrained_primitive
2974
+ ),
2975
+ )
2976
+
2977
+ verificator_blocks, error = _generate_constrained_primitive_verificator(
2978
+ constrained_primitive=constrained_primitive,
2979
+ symbol_table=symbol_table,
2980
+ environment=invariant_environment,
2981
+ )
2982
+
2983
+ if error is not None:
2984
+ errors.append(error)
2985
+ else:
2986
+ assert verificator_blocks is not None
2987
+ blocks.extend(verificator_blocks)
2988
+
2989
+ blocks.append(Stripped("} // namespace constrained_primitive_verificator"))
2990
+
2991
+ blocks.append(Stripped("namespace constrained_primitive_verification {"))
2992
+
2993
+ for constrained_primitive in symbol_table.constrained_primitives:
2994
+ blocks.extend(
2995
+ _generate_constrained_primitive_verification(
2996
+ constrained_primitive=constrained_primitive
2997
+ )
2998
+ )
2999
+
3000
+ blocks.append(Stripped("} // namespace constrained_primitive_verification"))
3001
+
3002
+ for constrained_primitive in symbol_table.constrained_primitives:
3003
+ blocks.append(
3004
+ _generate_implementation_of_verify_constrained_primitive(
3005
+ constrained_primitive=constrained_primitive
3006
+ )
3007
+ )
3008
+
3009
+ blocks.append(Stripped("// endregion Verification of constrained primitives"))
3010
+
3011
+ blocks.extend(
3012
+ [
3013
+ _generate_new_non_recursive_verificator_definition(),
3014
+ Stripped("// region Non-recursive verificators"),
3015
+ Stripped("namespace non_recursive_verificator {"),
3016
+ ]
3017
+ )
3018
+
3019
+ for cls in symbol_table.concrete_classes:
3020
+ nrv_blocks, nrv_error = _generate_non_recursive_verificator(
3021
+ cls=cls, symbol_table=symbol_table, base_environment=base_environment
3022
+ )
3023
+ if nrv_error is not None:
3024
+ errors.append(nrv_error)
3025
+ else:
3026
+ assert nrv_blocks is not None
3027
+ blocks.extend(nrv_blocks)
3028
+
3029
+ blocks.append(Stripped("} // namespace non_recursive_verificator"))
3030
+
3031
+ blocks.extend(
3032
+ [
3033
+ _generate_new_non_recursive_verificator_implementation(
3034
+ symbol_table=symbol_table
3035
+ ),
3036
+ Stripped("// endregion Non-recursive verificators"),
3037
+ Stripped("// region Recursive verificators"),
3038
+ ]
3039
+ )
3040
+
3041
+ blocks.extend(
3042
+ [
3043
+ *_generate_recursive_verificator(),
3044
+ Stripped("// endregion Recursive verificators"),
3045
+ *_generate_non_recursive_verification(),
3046
+ *_generate_recursive_verification(),
3047
+ *_generate_iterator_implementation(),
3048
+ ]
3049
+ )
3050
+
3051
+ if len(errors) > 0:
3052
+ return None, errors
3053
+
3054
+ blocks.extend(
3055
+ [
3056
+ cpp_common.generate_namespace_closing(namespace),
3057
+ cpp_common.WARNING,
3058
+ ]
3059
+ )
3060
+
3061
+ writer = io.StringIO()
3062
+ for i, block in enumerate(blocks):
3063
+ if i > 0:
3064
+ writer.write("\n\n")
3065
+
3066
+ writer.write(block)
3067
+
3068
+ writer.write("\n")
3069
+
3070
+ return writer.getvalue(), None
3071
+
3072
+
3073
+ # endregion