stupidedi 1.1.0

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 (500) hide show
  1. data/README.md +215 -0
  2. data/Rakefile +108 -0
  3. data/bin/edi-ed +71 -0
  4. data/bin/edi-pp +81 -0
  5. data/doc/Defining.md +0 -0
  6. data/doc/Generating.md +321 -0
  7. data/doc/LICENSE.md +0 -0
  8. data/doc/Navigating.md +645 -0
  9. data/doc/Parsing.md +0 -0
  10. data/doc/Serializing.md +7 -0
  11. data/doc/Tokenizing.md +0 -0
  12. data/doc/Validating.md +0 -0
  13. data/doc/design/Parser.md +0 -0
  14. data/doc/design/Reader.md +0 -0
  15. data/lib/ruby/array.rb +164 -0
  16. data/lib/ruby/blank.rb +67 -0
  17. data/lib/ruby/enumerable.rb +35 -0
  18. data/lib/ruby/exception.rb +33 -0
  19. data/lib/ruby/hash.rb +4 -0
  20. data/lib/ruby/instance_exec.rb +26 -0
  21. data/lib/ruby/module.rb +79 -0
  22. data/lib/ruby/object.rb +63 -0
  23. data/lib/ruby/string.rb +73 -0
  24. data/lib/ruby/symbol.rb +24 -0
  25. data/lib/ruby/to_d.rb +81 -0
  26. data/lib/ruby/to_date.rb +33 -0
  27. data/lib/ruby/to_time.rb +24 -0
  28. data/lib/ruby/try.rb +43 -0
  29. data/lib/stupidedi/blank_slate.rb +11 -0
  30. data/lib/stupidedi/builder/builder_dsl.rb +281 -0
  31. data/lib/stupidedi/builder/constraint_table.rb +418 -0
  32. data/lib/stupidedi/builder/generation.rb +112 -0
  33. data/lib/stupidedi/builder/instruction.rb +102 -0
  34. data/lib/stupidedi/builder/instruction_table.rb +204 -0
  35. data/lib/stupidedi/builder/navigation.rb +655 -0
  36. data/lib/stupidedi/builder/state_machine.rb +55 -0
  37. data/lib/stupidedi/builder/states/abstract_state.rb +332 -0
  38. data/lib/stupidedi/builder/states/failure_state.rb +69 -0
  39. data/lib/stupidedi/builder/states/functional_group_state.rb +97 -0
  40. data/lib/stupidedi/builder/states/initial_state.rb +63 -0
  41. data/lib/stupidedi/builder/states/interchange_state.rb +94 -0
  42. data/lib/stupidedi/builder/states/loop_state.rb +79 -0
  43. data/lib/stupidedi/builder/states/table_state.rb +96 -0
  44. data/lib/stupidedi/builder/states/transaction_set_state.rb +112 -0
  45. data/lib/stupidedi/builder/states/transmission_state.rb +59 -0
  46. data/lib/stupidedi/builder/tokenization.rb +196 -0
  47. data/lib/stupidedi/builder.rb +23 -0
  48. data/lib/stupidedi/color.rb +93 -0
  49. data/lib/stupidedi/config/code_list_config.rb +42 -0
  50. data/lib/stupidedi/config/editor_config.rb +51 -0
  51. data/lib/stupidedi/config/functional_group_config.rb +62 -0
  52. data/lib/stupidedi/config/interchange_config.rb +79 -0
  53. data/lib/stupidedi/config/transaction_set_config.rb +91 -0
  54. data/lib/stupidedi/config.rb +101 -0
  55. data/lib/stupidedi/editor/00501.rb +341 -0
  56. data/lib/stupidedi/editor/005010/N2.rb +0 -0
  57. data/lib/stupidedi/editor/005010/N3.rb +0 -0
  58. data/lib/stupidedi/editor/005010/N4.rb +63 -0
  59. data/lib/stupidedi/editor/005010/NM1.rb +0 -0
  60. data/lib/stupidedi/editor/005010.rb +469 -0
  61. data/lib/stupidedi/editor/X222-HC837.rb +195 -0
  62. data/lib/stupidedi/editor/abstract_ed.rb +36 -0
  63. data/lib/stupidedi/editor/claim_ack.rb +9 -0
  64. data/lib/stupidedi/editor/implementation_ack.rb +213 -0
  65. data/lib/stupidedi/editor/interchange_ack.rb +9 -0
  66. data/lib/stupidedi/editor/result.rb +100 -0
  67. data/lib/stupidedi/editor/result_set.rb +69 -0
  68. data/lib/stupidedi/editor/transaction_set_ed.rb +275 -0
  69. data/lib/stupidedi/editor/transmission_ed.rb +90 -0
  70. data/lib/stupidedi/editor.rb +37 -0
  71. data/lib/stupidedi/either.rb +287 -0
  72. data/lib/stupidedi/exceptions/invalid_element_error.rb +8 -0
  73. data/lib/stupidedi/exceptions/invalid_schema_error.rb +8 -0
  74. data/lib/stupidedi/exceptions/output_error.rb +8 -0
  75. data/lib/stupidedi/exceptions/parse_error.rb +8 -0
  76. data/lib/stupidedi/exceptions/stupidedi_error.rb +8 -0
  77. data/lib/stupidedi/exceptions/tokenize_error.rb +8 -0
  78. data/lib/stupidedi/exceptions/zipper_error.rb +8 -0
  79. data/lib/stupidedi/exceptions.rb +11 -0
  80. data/lib/stupidedi/guides/005010/X214-HN277.rb +409 -0
  81. data/lib/stupidedi/guides/005010/X221-HP835.rb +613 -0
  82. data/lib/stupidedi/guides/005010/X221A1-HP835.rb +613 -0
  83. data/lib/stupidedi/guides/005010/X222-HC837P.rb +2291 -0
  84. data/lib/stupidedi/guides/005010/X222A1-HC837P.rb +2297 -0
  85. data/lib/stupidedi/guides/005010/X231-FA999.rb +123 -0
  86. data/lib/stupidedi/guides/005010/X231A1-FA999.rb +119 -0
  87. data/lib/stupidedi/guides/005010/element_reqs.rb +38 -0
  88. data/lib/stupidedi/guides/005010/guide_builder.rb +180 -0
  89. data/lib/stupidedi/guides/005010/segment_reqs.rb +32 -0
  90. data/lib/stupidedi/guides/005010.rb +64 -0
  91. data/lib/stupidedi/guides.rb +5 -0
  92. data/lib/stupidedi/inspect.rb +26 -0
  93. data/lib/stupidedi/reader/input/abstract_input.rb +133 -0
  94. data/lib/stupidedi/reader/input/delegated_input.rb +111 -0
  95. data/lib/stupidedi/reader/input/file_input.rb +155 -0
  96. data/lib/stupidedi/reader/input.rb +30 -0
  97. data/lib/stupidedi/reader/position.rb +69 -0
  98. data/lib/stupidedi/reader/result.rb +168 -0
  99. data/lib/stupidedi/reader/segment_dict.rb +175 -0
  100. data/lib/stupidedi/reader/separators.rb +85 -0
  101. data/lib/stupidedi/reader/stream_reader.rb +172 -0
  102. data/lib/stupidedi/reader/token_reader.rb +466 -0
  103. data/lib/stupidedi/reader/tokens/component_element_tok.rb +56 -0
  104. data/lib/stupidedi/reader/tokens/composite_element_tok.rb +64 -0
  105. data/lib/stupidedi/reader/tokens/repeated_element_tok.rb +64 -0
  106. data/lib/stupidedi/reader/tokens/segment_tok.rb +51 -0
  107. data/lib/stupidedi/reader/tokens/simple_element_tok.rb +63 -0
  108. data/lib/stupidedi/reader.rb +121 -0
  109. data/lib/stupidedi/schema/abstract_def.rb +74 -0
  110. data/lib/stupidedi/schema/abstract_use.rb +73 -0
  111. data/lib/stupidedi/schema/code_list.rb +94 -0
  112. data/lib/stupidedi/schema/element_def.rb +173 -0
  113. data/lib/stupidedi/schema/element_req.rb +56 -0
  114. data/lib/stupidedi/schema/element_use.rb +251 -0
  115. data/lib/stupidedi/schema/functional_group_def.rb +114 -0
  116. data/lib/stupidedi/schema/interchange_def.rb +93 -0
  117. data/lib/stupidedi/schema/loop_def.rb +152 -0
  118. data/lib/stupidedi/schema/repeat_count.rb +85 -0
  119. data/lib/stupidedi/schema/segment_def.rb +108 -0
  120. data/lib/stupidedi/schema/segment_req.rb +43 -0
  121. data/lib/stupidedi/schema/segment_use.rb +98 -0
  122. data/lib/stupidedi/schema/syntax_note.rb +63 -0
  123. data/lib/stupidedi/schema/table_def.rb +139 -0
  124. data/lib/stupidedi/schema/transaction_set_def.rb +88 -0
  125. data/lib/stupidedi/schema.rb +28 -0
  126. data/lib/stupidedi/sets/absolute_set.rb +297 -0
  127. data/lib/stupidedi/sets/abstract_set.rb +174 -0
  128. data/lib/stupidedi/sets/null_set.rb +125 -0
  129. data/lib/stupidedi/sets/relative_complement.rb +137 -0
  130. data/lib/stupidedi/sets/relative_set.rb +269 -0
  131. data/lib/stupidedi/sets/universal_set.rb +104 -0
  132. data/lib/stupidedi/sets.rb +57 -0
  133. data/lib/stupidedi/tail_call.rb +109 -0
  134. data/lib/stupidedi/thread_local.rb +174 -0
  135. data/lib/stupidedi/values/abstract_element_val.rb +19 -0
  136. data/lib/stupidedi/values/abstract_val.rb +130 -0
  137. data/lib/stupidedi/values/composite_element_val.rb +95 -0
  138. data/lib/stupidedi/values/functional_group_val.rb +102 -0
  139. data/lib/stupidedi/values/interchange_val.rb +86 -0
  140. data/lib/stupidedi/values/invalid_envelope_val.rb +61 -0
  141. data/lib/stupidedi/values/invalid_segment_val.rb +78 -0
  142. data/lib/stupidedi/values/loop_val.rb +70 -0
  143. data/lib/stupidedi/values/repeated_element_val.rb +105 -0
  144. data/lib/stupidedi/values/segment_val.rb +104 -0
  145. data/lib/stupidedi/values/segment_val_group.rb +20 -0
  146. data/lib/stupidedi/values/simple_element_val.rb +80 -0
  147. data/lib/stupidedi/values/table_val.rb +66 -0
  148. data/lib/stupidedi/values/transaction_set_val.rb +66 -0
  149. data/lib/stupidedi/values/transmission_val.rb +52 -0
  150. data/lib/stupidedi/values.rb +21 -0
  151. data/lib/stupidedi/version.rb +3 -0
  152. data/lib/stupidedi/versions/functional_groups/004010/element_defs.rb +54 -0
  153. data/lib/stupidedi/versions/functional_groups/004010/element_reqs.rb +18 -0
  154. data/lib/stupidedi/versions/functional_groups/004010/element_types/date_val.rb +527 -0
  155. data/lib/stupidedi/versions/functional_groups/004010/element_types/fixnum_val.rb +335 -0
  156. data/lib/stupidedi/versions/functional_groups/004010/element_types/float_val.rb +299 -0
  157. data/lib/stupidedi/versions/functional_groups/004010/element_types/identifier_val.rb +287 -0
  158. data/lib/stupidedi/versions/functional_groups/004010/element_types/string_val.rb +338 -0
  159. data/lib/stupidedi/versions/functional_groups/004010/element_types/time_val.rb +309 -0
  160. data/lib/stupidedi/versions/functional_groups/004010/element_types.rb +124 -0
  161. data/lib/stupidedi/versions/functional_groups/004010/functional_group_def.rb +30 -0
  162. data/lib/stupidedi/versions/functional_groups/004010/segment_defs/GE.rb +20 -0
  163. data/lib/stupidedi/versions/functional_groups/004010/segment_defs/GS.rb +27 -0
  164. data/lib/stupidedi/versions/functional_groups/004010/segment_defs/SE.rb +20 -0
  165. data/lib/stupidedi/versions/functional_groups/004010/segment_defs/ST.rb +20 -0
  166. data/lib/stupidedi/versions/functional_groups/004010/segment_defs.rb +23 -0
  167. data/lib/stupidedi/versions/functional_groups/004010/segment_reqs.rb +18 -0
  168. data/lib/stupidedi/versions/functional_groups/004010/syntax_notes.rb +174 -0
  169. data/lib/stupidedi/versions/functional_groups/004010.rb +38 -0
  170. data/lib/stupidedi/versions/functional_groups/005010/element_defs.rb +1405 -0
  171. data/lib/stupidedi/versions/functional_groups/005010/element_reqs.rb +18 -0
  172. data/lib/stupidedi/versions/functional_groups/005010/element_types/date_val.rb +577 -0
  173. data/lib/stupidedi/versions/functional_groups/005010/element_types/fixnum_val.rb +322 -0
  174. data/lib/stupidedi/versions/functional_groups/005010/element_types/float_val.rb +354 -0
  175. data/lib/stupidedi/versions/functional_groups/005010/element_types/identifier_val.rb +368 -0
  176. data/lib/stupidedi/versions/functional_groups/005010/element_types/operators.rb +117 -0
  177. data/lib/stupidedi/versions/functional_groups/005010/element_types/string_val.rb +398 -0
  178. data/lib/stupidedi/versions/functional_groups/005010/element_types/time_val.rb +327 -0
  179. data/lib/stupidedi/versions/functional_groups/005010/element_types.rb +132 -0
  180. data/lib/stupidedi/versions/functional_groups/005010/functional_group_def.rb +30 -0
  181. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/AK1.rb +21 -0
  182. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/AK2.rb +21 -0
  183. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/AK9.rb +28 -0
  184. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/AMT.rb +21 -0
  185. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/BHT.rb +24 -0
  186. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/BPR.rb +49 -0
  187. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CAS.rb +56 -0
  188. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CL1.rb +22 -0
  189. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CLM.rb +41 -0
  190. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CLP.rb +34 -0
  191. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CN1.rb +24 -0
  192. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CR1.rb +32 -0
  193. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CR2.rb +35 -0
  194. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CR3.rb +25 -0
  195. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CRC.rb +26 -0
  196. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CTP.rb +36 -0
  197. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CTX.rb +24 -0
  198. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/CUR.rb +57 -0
  199. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DMG.rb +34 -0
  200. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DN1.rb +22 -0
  201. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DN2.rb +24 -0
  202. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DTM.rb +24 -0
  203. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/DTP.rb +21 -0
  204. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/FRM.rb +25 -0
  205. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/GE.rb +20 -0
  206. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/GS.rb +27 -0
  207. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/HCP.rb +39 -0
  208. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/HI.rb +31 -0
  209. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/HL.rb +22 -0
  210. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/IK3.rb +22 -0
  211. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/IK4.rb +22 -0
  212. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/IK5.rb +24 -0
  213. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/K3.rb +21 -0
  214. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/LIN.rb +69 -0
  215. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/LQ.rb +22 -0
  216. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/LX.rb +19 -0
  217. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/MEA.rb +39 -0
  218. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/MIA.rb +45 -0
  219. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/MOA.rb +28 -0
  220. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/N1.rb +24 -0
  221. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/N2.rb +20 -0
  222. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/N3.rb +20 -0
  223. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/N4.rb +30 -0
  224. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/NM1.rb +35 -0
  225. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/NTE.rb +20 -0
  226. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/OI.rb +24 -0
  227. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PAT.rb +31 -0
  228. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PER.rb +32 -0
  229. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PLB.rb +40 -0
  230. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PRV.rb +26 -0
  231. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PS1.rb +21 -0
  232. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/PWK.rb +30 -0
  233. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/QTY.rb +25 -0
  234. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/RDM.rb +23 -0
  235. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/REF.rb +23 -0
  236. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SBR.rb +28 -0
  237. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SE.rb +20 -0
  238. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/ST.rb +21 -0
  239. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/STC.rb +30 -0
  240. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SV1.rb +44 -0
  241. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SV2.rb +29 -0
  242. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SV3.rb +30 -0
  243. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SV5.rb +29 -0
  244. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SVC.rb +26 -0
  245. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/SVD.rb +24 -0
  246. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/TOO.rb +21 -0
  247. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/TRN.rb +22 -0
  248. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/TS2.rb +40 -0
  249. data/lib/stupidedi/versions/functional_groups/005010/segment_defs/TS3.rb +45 -0
  250. data/lib/stupidedi/versions/functional_groups/005010/segment_defs.rb +227 -0
  251. data/lib/stupidedi/versions/functional_groups/005010/segment_reqs.rb +18 -0
  252. data/lib/stupidedi/versions/functional_groups/005010/syntax_notes.rb +165 -0
  253. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/FA999.rb +38 -0
  254. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HB271.rb +85 -0
  255. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HC837.rb +163 -0
  256. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HI278.rb +64 -0
  257. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HN277.rb +74 -0
  258. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HP835.rb +68 -0
  259. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HR276.rb +57 -0
  260. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/HS270.rb +53 -0
  261. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs/RA820.rb +240 -0
  262. data/lib/stupidedi/versions/functional_groups/005010/transaction_set_defs.rb +68 -0
  263. data/lib/stupidedi/versions/functional_groups/005010.rb +38 -0
  264. data/lib/stupidedi/versions/functional_groups.rb +8 -0
  265. data/lib/stupidedi/versions/interchanges/00401/element_defs.rb +224 -0
  266. data/lib/stupidedi/versions/interchanges/00401/interchange_def.rb +45 -0
  267. data/lib/stupidedi/versions/interchanges/00401/segment_defs/IEA.rb +20 -0
  268. data/lib/stupidedi/versions/interchanges/00401/segment_defs/ISA.rb +34 -0
  269. data/lib/stupidedi/versions/interchanges/00401/segment_defs/TA1.rb +23 -0
  270. data/lib/stupidedi/versions/interchanges/00401/segment_defs.rb +28 -0
  271. data/lib/stupidedi/versions/interchanges/00401.rb +23 -0
  272. data/lib/stupidedi/versions/interchanges/00501/element_defs.rb +269 -0
  273. data/lib/stupidedi/versions/interchanges/00501/interchange_def.rb +47 -0
  274. data/lib/stupidedi/versions/interchanges/00501/segment_defs/IEA.rb +20 -0
  275. data/lib/stupidedi/versions/interchanges/00501/segment_defs/ISA.rb +34 -0
  276. data/lib/stupidedi/versions/interchanges/00501/segment_defs/ISB.rb +18 -0
  277. data/lib/stupidedi/versions/interchanges/00501/segment_defs/ISE.rb +18 -0
  278. data/lib/stupidedi/versions/interchanges/00501/segment_defs/TA1.rb +23 -0
  279. data/lib/stupidedi/versions/interchanges/00501/segment_defs/TA3.rb +18 -0
  280. data/lib/stupidedi/versions/interchanges/00501/segment_defs.rb +37 -0
  281. data/lib/stupidedi/versions/interchanges/00501.rb +23 -0
  282. data/lib/stupidedi/versions/interchanges.rb +8 -0
  283. data/lib/stupidedi/versions.rb +6 -0
  284. data/lib/stupidedi/writer/claredi.rb +142 -0
  285. data/lib/stupidedi/writer/default.rb +124 -0
  286. data/lib/stupidedi/writer.rb +6 -0
  287. data/lib/stupidedi/zipper/abstract_cursor.rb +351 -0
  288. data/lib/stupidedi/zipper/dangling_cursor.rb +103 -0
  289. data/lib/stupidedi/zipper/edited_cursor.rb +157 -0
  290. data/lib/stupidedi/zipper/memoized_cursor.rb +131 -0
  291. data/lib/stupidedi/zipper/path.rb +124 -0
  292. data/lib/stupidedi/zipper/root_cursor.rb +120 -0
  293. data/lib/stupidedi/zipper.rb +25 -0
  294. data/lib/stupidedi.rb +66 -0
  295. data/spec/examples/integration/generating.example +551 -0
  296. data/spec/examples/integration/navigating.example +214 -0
  297. data/spec/examples/integration/parsing.example +445 -0
  298. data/spec/examples/ruby/array.example +476 -0
  299. data/spec/examples/ruby/blank.example +62 -0
  300. data/spec/examples/ruby/count.example +68 -0
  301. data/spec/examples/ruby/object.example +99 -0
  302. data/spec/examples/ruby/string.example +111 -0
  303. data/spec/examples/ruby/symbol.example +117 -0
  304. data/spec/examples/ruby/to_d.example +90 -0
  305. data/spec/examples/ruby/try.example +50 -0
  306. data/spec/examples/stupidedi/either.example +375 -0
  307. data/spec/examples/stupidedi/reader/failure.example +68 -0
  308. data/spec/examples/stupidedi/reader/input/delegated_input.example +292 -0
  309. data/spec/examples/stupidedi/reader/separators.example +73 -0
  310. data/spec/examples/stupidedi/reader/stream_reader.example +48 -0
  311. data/spec/examples/stupidedi/reader/success.example +34 -0
  312. data/spec/examples/stupidedi/reader/token_reader.example +775 -0
  313. data/spec/examples/stupidedi/reader.example +168 -0
  314. data/spec/examples/stupidedi/sets/absolute_set.example +1577 -0
  315. data/spec/examples/stupidedi/sets/null_set.example +2 -0
  316. data/spec/examples/stupidedi/sets/relative_set.example +2 -0
  317. data/spec/examples/stupidedi/sets/universal_set.example +1 -0
  318. data/spec/examples/stupidedi/versions/005010/element_types/an.example +201 -0
  319. data/spec/examples/stupidedi/versions/005010/element_types/dt.example +258 -0
  320. data/spec/examples/stupidedi/versions/005010/element_types/id.example +192 -0
  321. data/spec/examples/stupidedi/versions/005010/element_types/nn.example +177 -0
  322. data/spec/examples/stupidedi/versions/005010/element_types/r.example +178 -0
  323. data/spec/examples/stupidedi/versions/005010/element_types/tm.example +2 -0
  324. data/spec/examples/stupidedi/zipper/abstract_cursor.example +417 -0
  325. data/spec/examples/stupidedi/zipper.example +9 -0
  326. data/spec/fixtures/X186-AG824/1-bad.txt +21 -0
  327. data/spec/fixtures/X186-AG824/1-good.txt +17 -0
  328. data/spec/fixtures/X186-AG824/2-bad.txt +26 -0
  329. data/spec/fixtures/X186-AG824/2-good.txt +21 -0
  330. data/spec/fixtures/X186-AG824/3-bad.txt +87 -0
  331. data/spec/fixtures/X186-AG824/3-good.txt +61 -0
  332. data/spec/fixtures/X212-HN277/1-bad.txt +54 -0
  333. data/spec/fixtures/X212-HN277/1-good.txt +46 -0
  334. data/spec/fixtures/X212-HN277/2-bad.txt +37 -0
  335. data/spec/fixtures/X212-HN277/2-good.txt +29 -0
  336. data/spec/fixtures/X212-HN277/3-bad.txt +22 -0
  337. data/spec/fixtures/X212-HN277/3-good.txt +17 -0
  338. data/spec/fixtures/X212-HN277/4-bad.txt +30 -0
  339. data/spec/fixtures/X212-HN277/4-good.txt +24 -0
  340. data/spec/fixtures/X212-HR276/1-bad.txt +53 -0
  341. data/spec/fixtures/X212-HR276/1-good.txt +46 -0
  342. data/spec/fixtures/X212-HR276/2-bad.txt +45 -0
  343. data/spec/fixtures/X212-HR276/2-good.txt +38 -0
  344. data/spec/fixtures/X212-HR276/3-bad.txt +32 -0
  345. data/spec/fixtures/X212-HR276/3-good.txt +26 -0
  346. data/spec/fixtures/X212-HR276/4-bad.txt +32 -0
  347. data/spec/fixtures/X212-HR276/4-good.txt +26 -0
  348. data/spec/fixtures/X214-HN277/1-bad.txt +58 -0
  349. data/spec/fixtures/X214-HN277/1-good.txt +47 -0
  350. data/spec/fixtures/X214-HN277/2-bad.txt +34 -0
  351. data/spec/fixtures/X214-HN277/2-good.txt +22 -0
  352. data/spec/fixtures/X214-HN277/3-bad.txt +64 -0
  353. data/spec/fixtures/X214-HN277/3-good.txt +54 -0
  354. data/spec/fixtures/X214-HN277/4-bad.txt +77 -0
  355. data/spec/fixtures/X214-HN277/4-good.txt +63 -0
  356. data/spec/fixtures/X216-HI278/1-bad.txt +42 -0
  357. data/spec/fixtures/X216-HI278/1-good.txt +27 -0
  358. data/spec/fixtures/X216-HI278/2-bad.txt +43 -0
  359. data/spec/fixtures/X216-HI278/2-good.txt +29 -0
  360. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-1.txt +24 -0
  361. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-1_Clean.txt +20 -0
  362. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-2.txt +46 -0
  363. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-2_Clean.txt +30 -0
  364. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-3.txt +38 -0
  365. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-3_Clean.txt +24 -0
  366. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-4a.txt +39 -0
  367. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-4a_Clean.txt +24 -0
  368. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-4b.txt +43 -0
  369. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-4b_Clean.txt +25 -0
  370. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-5.txt +63 -0
  371. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-5_Clean.txt +41 -0
  372. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-6.txt +36 -0
  373. data/spec/fixtures/X217-HI278/Sample_278_Request_5010X217-6_Clean.txt +20 -0
  374. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-1r.txt +34 -0
  375. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-1r_Clean.txt +23 -0
  376. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-2r.txt +46 -0
  377. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-2r_Clean.txt +31 -0
  378. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-3r.txt +44 -0
  379. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-3r_Clean.txt +26 -0
  380. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-4ar_Clean.txt +28 -0
  381. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-4br_Clean.txt +35 -0
  382. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-5r.txt +60 -0
  383. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-5r_Clean.txt +42 -0
  384. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-6r.txt +40 -0
  385. data/spec/fixtures/X217-HI278/Sample_278_Response_5010X217-6r_Clean.txt +24 -0
  386. data/spec/fixtures/X218-RA820/1-bad.txt +31 -0
  387. data/spec/fixtures/X218-RA820/1-good.txt +25 -0
  388. data/spec/fixtures/X218-RA820/2-bad.txt +37 -0
  389. data/spec/fixtures/X218-RA820/2-good.txt +29 -0
  390. data/spec/fixtures/X218-RA820/3-bad.txt +29 -0
  391. data/spec/fixtures/X218-RA820/3-good.txt +23 -0
  392. data/spec/fixtures/X218-RA820/4-bad.txt +36 -0
  393. data/spec/fixtures/X218-RA820/4-good.txt +27 -0
  394. data/spec/fixtures/X220-BE834/1-bad.txt +35 -0
  395. data/spec/fixtures/X220-BE834/1-good.txt +29 -0
  396. data/spec/fixtures/X220-BE834/10-bad.txt +26 -0
  397. data/spec/fixtures/X220-BE834/10-good.txt +19 -0
  398. data/spec/fixtures/X220-BE834/2-bad.txt +31 -0
  399. data/spec/fixtures/X220-BE834/2-good.txt +23 -0
  400. data/spec/fixtures/X220-BE834/3-bad.txt +36 -0
  401. data/spec/fixtures/X220-BE834/3-good.txt +26 -0
  402. data/spec/fixtures/X220-BE834/4-bad.txt +27 -0
  403. data/spec/fixtures/X220-BE834/4-good.txt +21 -0
  404. data/spec/fixtures/X220-BE834/5-bad.txt +26 -0
  405. data/spec/fixtures/X220-BE834/5-good.txt +17 -0
  406. data/spec/fixtures/X220-BE834/6-bad.txt +25 -0
  407. data/spec/fixtures/X220-BE834/6-good.txt +20 -0
  408. data/spec/fixtures/X220-BE834/7-bad.txt +25 -0
  409. data/spec/fixtures/X220-BE834/7-good.txt +20 -0
  410. data/spec/fixtures/X220-BE834/8-bad.txt +25 -0
  411. data/spec/fixtures/X220-BE834/8-good.txt +20 -0
  412. data/spec/fixtures/X220-BE834/9-bad.txt +27 -0
  413. data/spec/fixtures/X220-BE834/9-good.txt +21 -0
  414. data/spec/fixtures/X221-HP835/1-bad.txt +58 -0
  415. data/spec/fixtures/X221-HP835/1-good.txt +40 -0
  416. data/spec/fixtures/X221-HP835/2-bad.txt +51 -0
  417. data/spec/fixtures/X221-HP835/2-good.txt +40 -0
  418. data/spec/fixtures/X221-HP835/3a-bad.txt +78 -0
  419. data/spec/fixtures/X221-HP835/3a-good.txt +49 -0
  420. data/spec/fixtures/X221-HP835/3b-bad.txt +60 -0
  421. data/spec/fixtures/X221-HP835/3b-good.txt +32 -0
  422. data/spec/fixtures/X221-HP835/3c-bad.txt +55 -0
  423. data/spec/fixtures/X221-HP835/3c-good.txt +34 -0
  424. data/spec/fixtures/X222-HC837/1-bad.txt +60 -0
  425. data/spec/fixtures/X222-HC837/1-good.txt +53 -0
  426. data/spec/fixtures/X222-HC837/10a-bad.txt +52 -0
  427. data/spec/fixtures/X222-HC837/10a-good.txt +40 -0
  428. data/spec/fixtures/X222-HC837/10b-bad.txt +99 -0
  429. data/spec/fixtures/X222-HC837/10b-good.txt +80 -0
  430. data/spec/fixtures/X222-HC837/10c-bad.txt +105 -0
  431. data/spec/fixtures/X222-HC837/10c-good.txt +80 -0
  432. data/spec/fixtures/X222-HC837/11-bad.txt +69 -0
  433. data/spec/fixtures/X222-HC837/11-good.txt +45 -0
  434. data/spec/fixtures/X222-HC837/12-bad.txt +73 -0
  435. data/spec/fixtures/X222-HC837/12-good.txt +51 -0
  436. data/spec/fixtures/X222-HC837/13-bad.txt +64 -0
  437. data/spec/fixtures/X222-HC837/13-good.txt +46 -0
  438. data/spec/fixtures/X222-HC837/3a-bad.txt +83 -0
  439. data/spec/fixtures/X222-HC837/3a-good.txt +59 -0
  440. data/spec/fixtures/X222-HC837/3b-bad.txt +97 -0
  441. data/spec/fixtures/X222-HC837/3b-good.txt +70 -0
  442. data/spec/fixtures/X222-HC837/3c-bad.txt +95 -0
  443. data/spec/fixtures/X222-HC837/3c-good.txt +74 -0
  444. data/spec/fixtures/X222-HC837/4-bad.txt +67 -0
  445. data/spec/fixtures/X222-HC837/4-good.txt +48 -0
  446. data/spec/fixtures/X222-HC837/5-bad.txt +73 -0
  447. data/spec/fixtures/X222-HC837/5-good.txt +60 -0
  448. data/spec/fixtures/X222-HC837/6-bad.txt +50 -0
  449. data/spec/fixtures/X222-HC837/6-good.txt +39 -0
  450. data/spec/fixtures/X222-HC837/7-bad.txt +93 -0
  451. data/spec/fixtures/X222-HC837/7-good.txt +78 -0
  452. data/spec/fixtures/X222-HC837/8-bad.txt +64 -0
  453. data/spec/fixtures/X222-HC837/8-good.txt +52 -0
  454. data/spec/fixtures/X222-HC837/9-bad.txt +56 -0
  455. data/spec/fixtures/X222-HC837/9-good.txt +38 -0
  456. data/spec/fixtures/X223-HC837/1-bad.txt +66 -0
  457. data/spec/fixtures/X223-HC837/1-good.txt +53 -0
  458. data/spec/fixtures/X223-HC837/2-bad.txt +69 -0
  459. data/spec/fixtures/X223-HC837/2-good.txt +60 -0
  460. data/spec/fixtures/X223-HC837/3-bad.txt +89 -0
  461. data/spec/fixtures/X223-HC837/3-good.txt +61 -0
  462. data/spec/fixtures/X223-HC837/4-bad.txt +60 -0
  463. data/spec/fixtures/X223-HC837/4-good.txt +40 -0
  464. data/spec/fixtures/X223-HC837/5-bad.txt +75 -0
  465. data/spec/fixtures/X223-HC837/5-good.txt +58 -0
  466. data/spec/fixtures/X224-HC837/1-bad.txt +54 -0
  467. data/spec/fixtures/X224-HC837/1-good.txt +44 -0
  468. data/spec/fixtures/X224-HC837/2a-bad.txt +52 -0
  469. data/spec/fixtures/X224-HC837/2a-good.txt +42 -0
  470. data/spec/fixtures/X224-HC837/2b-bad.txt +67 -0
  471. data/spec/fixtures/X224-HC837/2b-good.txt +52 -0
  472. data/spec/fixtures/X224-HC837/3-bad.txt +67 -0
  473. data/spec/fixtures/X224-HC837/3-good.txt +51 -0
  474. data/spec/fixtures/X224-HC837/4-bad.txt +49 -0
  475. data/spec/fixtures/X224-HC837/4-good.txt +40 -0
  476. data/spec/fixtures/X230-FA997/1-bad.txt +19 -0
  477. data/spec/fixtures/X230-FA997/1-good.txt +16 -0
  478. data/spec/fixtures/X231-FA999/1-bad.txt +20 -0
  479. data/spec/fixtures/X231-FA999/1-good.txt +20 -0
  480. data/spec/fixtures/X279-HB271/1-bad.txt +36 -0
  481. data/spec/fixtures/X279-HB271/1-good.txt +30 -0
  482. data/spec/fixtures/X279-HB271/2-bad.txt +22 -0
  483. data/spec/fixtures/X279-HB271/2-good.txt +16 -0
  484. data/spec/fixtures/X279-HB271/3-bad.txt +44 -0
  485. data/spec/fixtures/X279-HB271/3-good.txt +36 -0
  486. data/spec/fixtures/X279-HS270/1-bad.txt +29 -0
  487. data/spec/fixtures/X279-HS270/1-good.txt +23 -0
  488. data/spec/fixtures/X279-HS270/2-bad.txt +32 -0
  489. data/spec/fixtures/X279-HS270/2-good.txt +25 -0
  490. data/spec/spec_helper.rb +34 -0
  491. data/spec/support/fixtures.rb +26 -0
  492. data/spec/support/matchers/either_matchers.rb +26 -0
  493. data/spec/support/matchers/navigation_matchers.rb +247 -0
  494. data/spec/support/node.rb +41 -0
  495. data/spec/support/quickcheck/characters.rb +28 -0
  496. data/spec/support/quickcheck/property.rb +105 -0
  497. data/spec/support/quickcheck/serialized_edi.rb +399 -0
  498. data/spec/support/quickcheck.rb +302 -0
  499. data/spec/support/rcov.rb +34 -0
  500. metadata +577 -0
@@ -0,0 +1,137 @@
1
+ # encoding: UTF-8
2
+
3
+ module Stupidedi
4
+ module Sets
5
+
6
+ #
7
+ # This data type is an infinite and non-enumerable set of values that
8
+ # encodes the complement of a {RelativeSet}
9
+ #
10
+ class RelativeComplement < AbstractSet
11
+
12
+ def initialize(complement)
13
+ @complement = complement
14
+ end
15
+
16
+ # (see AbstractSet#include?)
17
+ def include?(object)
18
+ not @complement.include?(object)
19
+ end
20
+
21
+ # (see AbstractSet#size)
22
+ # @return Infinity
23
+ def size
24
+ 1.0 / 0.0
25
+ end
26
+
27
+ # (see AbstractSet#finite?)
28
+ # @return false
29
+ def finite?
30
+ false
31
+ end
32
+
33
+ # (see AbstractSet#empty?)
34
+ # @return false
35
+ def empty?
36
+ false
37
+ end
38
+
39
+ # (see AbstractSet#replace)
40
+ def replace(other)
41
+ Sets.build(other)
42
+ end
43
+
44
+ # @group Set Operations
45
+ #########################################################################
46
+
47
+ # (see AbstractSet#complement)
48
+ def complement
49
+ # ¬(¬A) = A
50
+ @complement
51
+ end
52
+
53
+ # (see AbstractSet#intersection)
54
+ def intersection(other)
55
+ if other.is_a?(RelativeComplement)
56
+ # ¬A ∩ ¬B = ¬(A ∪ B)
57
+ complement.union(other.complement).complement
58
+ else
59
+ # ¬A ∩ B = B ∖ A
60
+ Sets.build(other).difference(complement)
61
+ end
62
+ end
63
+
64
+ # (see AbstractSet#union)
65
+ def union(other)
66
+ if other.is_a?(RelativeComplement)
67
+ # ¬A ∪ ¬B = ¬(A ∩ B)
68
+ complement.intersection(other.complement).complement
69
+ else
70
+ # ¬A ∪ B = ¬(A ∖ B)
71
+ complement.difference(Sets.build(other)).complement
72
+ end
73
+ end
74
+
75
+ # (see AbstractSet#symmetric_difference)
76
+ def symmetric_difference(other)
77
+ if other.is_a?(RelativeComplement)
78
+ # ¬A ⊖ ¬B = (¬A ∖ ¬B) ∪ (¬B ∖ ¬A)
79
+ # = (B ∖ A) ∪ (A ∖ B)
80
+ # = A ⊖ B
81
+ complement.symmetric_difference(other.complement)
82
+ else
83
+ # ¬A ⊖ B = (¬A ∖ B) ∪ (B ∖ ¬A)
84
+ # = (¬A ∩ ¬B) ∪ (B ∩ A)
85
+ # = (¬B ∖ A) ∪ (A ∖ ¬B)
86
+ # = A ⊖ ¬B
87
+ other = Sets.build(other)
88
+
89
+ intersection(other.complement).
90
+ union(other.intersection(complement))
91
+ end
92
+ end
93
+
94
+ # (see AbstractSet#difference)
95
+ def difference(other)
96
+ if other.is_a?(RelativeComplement)
97
+ # ¬A ∖ ¬B = ¬A ∩ B = B ∖ A
98
+ other.complement.difference(complement)
99
+ else
100
+ # ¬A ∖ B = ¬A ∩ ¬B = ¬(A ∪ B)
101
+ complement.union(Sets.build(other)).complement
102
+ end
103
+ end
104
+
105
+ # @group Set Ordering
106
+ #########################################################################
107
+
108
+ # (see AbstractSet#proper_subset?)
109
+ def proper_subset?(other)
110
+ other.is_a?(RelativeComplement) and intersection(other) == self
111
+ end
112
+
113
+ # (see AbstractSet#proper_superset?)
114
+ def proper_superset?(other)
115
+ other.is_a?(RelativeComplement) and intersection(other) == other
116
+ end
117
+
118
+ # (see AbstractSet#==)
119
+ def ==(other)
120
+ eql?(other) or
121
+ (other.is_a?(RelativeComplement) and complement == other.complement)
122
+ end
123
+
124
+ # @group Pretty Printing
125
+ #########################################################################
126
+
127
+ # @return [String]
128
+ def inspect
129
+ "RelativeComplement(#{@complement.inspect})"
130
+ end
131
+
132
+ # @endgroup
133
+ #########################################################################
134
+ end
135
+
136
+ end
137
+ end
@@ -0,0 +1,269 @@
1
+ # encoding: UTF-8
2
+
3
+ module Stupidedi
4
+ module Sets
5
+
6
+ #
7
+ # This data type encodes a set of unique values that belong to an _infinite_
8
+ # universe of possible values (aka domain). Set operations generally perform
9
+ # worse than {AbsoluteSet}, as they operate on {Hash} values and require
10
+ # iterating the underlying {Hash} of at least one of the two sets in `O(n)`
11
+ # time.
12
+ #
13
+ # This is suitable for sets that don't have an inherently restricted domain
14
+ # (eg sets of arbitrary {String} values), including those where the domain
15
+ # is significantly large compared to the typical size of sets built from
16
+ # those values. {RelativeSet} also requires only a single step to execute
17
+ # {#include?}, while {AbsoluteSet} requires two.
18
+ #
19
+ class RelativeSet < AbstractSet
20
+ include Enumerable
21
+
22
+ def initialize(hash)
23
+ @hash = hash
24
+ end
25
+
26
+ # Yields each element in the set to the implicit block argument.
27
+ #
28
+ # @return [void]
29
+ def each
30
+ @hash.keys.each{|o| yield o }
31
+ end
32
+
33
+ # Returns an {Array} containing each element in this set
34
+ #
35
+ # @return [Array]
36
+ def to_a
37
+ @hash.keys
38
+ end
39
+
40
+ # (see AbstractSet#include?)
41
+ def include?(object)
42
+ @hash.include?(object)
43
+ end
44
+
45
+ # (see AbstractSet#finite?)
46
+ #
47
+ # @return true
48
+ def finite?
49
+ true
50
+ end
51
+
52
+ # Returns a single element from the set, with no guarantees about which
53
+ # element. If the set is {#empty?}, the return value is undefined.
54
+ def first
55
+ @hash.keys.first
56
+ end
57
+
58
+ # (see AbstractSet#replace)
59
+ def replace(other)
60
+ Sets.build(other)
61
+ end
62
+
63
+ # (see AbstractSet#size)
64
+ def size
65
+ @hash.size
66
+ end
67
+
68
+ # (see AbstractSet#empty?)
69
+ def empty?
70
+ @hash.empty?
71
+ end
72
+
73
+ # @group Set Operations
74
+ #########################################################################
75
+
76
+ # @return [RelativeSet]
77
+ def map
78
+ RelativeSet.new(@hash.keys.inject({}) do |hash, key|
79
+ hash[yield(key)] = true
80
+ hash
81
+ end)
82
+ end
83
+
84
+ # @return [RelativeSet]
85
+ def select
86
+ RelativeSet.new(@hash.clone.delete_if{|o,_| not yield(o) })
87
+ end
88
+
89
+ # @return [RelativeSet]
90
+ def reject
91
+ RelativeSet.new(@hash.clone.delete_if{|o,_| yield(o) })
92
+ end
93
+
94
+ # (see AbstractSet#complement)
95
+ # @return [RelativeComplement]
96
+ def complement
97
+ RelativeComplement.new(self)
98
+ end
99
+
100
+ # (see AbstractSet#intersection)
101
+ def intersection(other)
102
+ if other.is_a?(RelativeComplement)
103
+ # A ∩ ¬B = ¬B ∩ A
104
+ other.intersection(self)
105
+ elsif other.is_a?(AbstractSet)
106
+ if other.is_a?(RelativeSet) and size > other.size
107
+ # For efficiency, iterate the smaller of the two sets: A ∩ B = B ∩ A
108
+ other.intersection(self)
109
+ elsif other.empty?
110
+ # A ∩ ∅ = ∅
111
+ NullSet.build
112
+ else
113
+ hash = @hash.clone.delete_if{|o,_| not other.include?(o) }
114
+
115
+ if hash.empty?
116
+ NullSet.build
117
+ else
118
+ RelativeSet.new(hash)
119
+ end
120
+ end
121
+ else
122
+ intersection(Sets.build(other))
123
+ end
124
+ end
125
+
126
+ # (see AbstractSet#intersection)
127
+ def union(other)
128
+ if other.is_a?(RelativeComplement)
129
+ # A ∪ ¬B = ¬B ∪ A
130
+ other.union(self)
131
+ elsif other.is_a?(AbstractSet)
132
+ unless other.is_a?(RelativeSet) and size < other.size
133
+ hash = other.inject(@hash.clone){|h,o| h[o] = true; h }
134
+
135
+ if hash.empty?
136
+ NullSet.build
137
+ else
138
+ RelativeSet.new(hash)
139
+ end
140
+ else
141
+ # For efficiency, iterate the smaller of the two sets: A ∪ B = B ∪ A
142
+ if other.empty?
143
+ self
144
+ else
145
+ other.union(self)
146
+ end
147
+ end
148
+ else
149
+ union(Sets.build(other))
150
+ end
151
+ end
152
+
153
+ # (see AbstractSet#difference)
154
+ def difference(other)
155
+ if other.is_a?(RelativeComplement)
156
+ # A ∖ ¬B = A ∩ B
157
+ intersection(other.complement)
158
+ elsif other.is_a?(AbstractSet)
159
+ if other.empty?
160
+ self
161
+ else
162
+ # A ∖ B = A ∩ ¬B
163
+ hash = @hash.clone.delete_if{|o,_| other.include?(o) }
164
+
165
+ if hash.empty?
166
+ NullSet.build
167
+ else
168
+ RelativeSet.new(hash)
169
+ end
170
+ end
171
+ else
172
+ difference(Sets.build(other))
173
+ end
174
+ end
175
+
176
+ # (see AbstractSet#symmetric_difference)
177
+ def symmetric_difference(other)
178
+ if other.is_a?(RelativeComplement)
179
+ # A ⊖ ~B = (A ∖ ¬B) | (¬B ∖ A)
180
+ # = (A ∩ B) | (¬B ∩ ¬A)
181
+ # = (B ∖ ¬A) | (¬A ∖ B)
182
+ # = ~A ⊖ B
183
+ intersection(other.complement).
184
+ union(other.intersection(complement))
185
+ else
186
+ # A ⊖ B = (A ∖ B) | (B ∖ A)
187
+ # = (A ∪ B) - (A ∩ B)
188
+ other = Sets.build(other)
189
+
190
+ if other.empty?
191
+ self
192
+ else
193
+ union(other).difference(intersection(other))
194
+ end
195
+ end
196
+ end
197
+
198
+ # @group Set Ordering
199
+ #########################################################################
200
+
201
+ # (see AbstractSet#==)
202
+ def ==(other)
203
+ eql?(other) or
204
+ (other.is_a?(Enumerable) and
205
+ @hash.keys == other.to_a)
206
+ end
207
+
208
+ # @group Pretty Printing
209
+ #########################################################################
210
+
211
+ # @return [void]
212
+ def pretty_print(q)
213
+ q.text("RelativeSet[#{size}]")
214
+ q.group(2, "(", ")") do
215
+ q.breakable ""
216
+
217
+ elements = to_a
218
+ elements.take(5).each do |e|
219
+ unless q.current_group.first?
220
+ q.text ","
221
+ q.breakable
222
+ end
223
+ q.pp e
224
+ end
225
+
226
+ if elements.length > 5
227
+ q.text ","
228
+ q.breakable
229
+ q.text "..."
230
+ end
231
+ end
232
+ end
233
+
234
+ # @return [String]
235
+ def inspect
236
+ "RelativeSet(#{to_a.map(&:inspect).join(', ')})"
237
+ end
238
+
239
+ # @endgroup
240
+ #########################################################################
241
+ end
242
+
243
+ class << RelativeSet
244
+ # @group Constructors
245
+ #########################################################################
246
+
247
+ # @return [RelativeSet]
248
+ def build(object)
249
+ if object.is_a?(RelativeSet)
250
+ object
251
+ elsif object.is_a?(Enumerable)
252
+ if object.empty?
253
+ NullSet.build
254
+ elsif object.is_a?(Hash)
255
+ new(object)
256
+ else
257
+ new(object.inject({}){|h,o| h[o] = true; h })
258
+ end
259
+ else
260
+ raise TypeError
261
+ end
262
+ end
263
+
264
+ # @endgroup
265
+ #########################################################################
266
+ end
267
+
268
+ end
269
+ end
@@ -0,0 +1,104 @@
1
+ module Stupidedi
2
+ module Sets
3
+
4
+ # @private
5
+ UniversalSet = Class.new(RelativeComplement) do
6
+
7
+ def initialize
8
+ end
9
+
10
+ # @return [UniversalSet]
11
+ def build
12
+ self
13
+ end
14
+
15
+ # @return true
16
+ def include?(object)
17
+ true
18
+ end
19
+
20
+ # @return false
21
+ def finite?
22
+ false
23
+ end
24
+
25
+ # @return Infinity
26
+ def size
27
+ 1.0 / 0.0
28
+ end
29
+
30
+ # @return false
31
+ def empty?
32
+ false
33
+ end
34
+
35
+ # @return [AbstractSet]
36
+ def replace(other)
37
+ Sets.build(other)
38
+ end
39
+
40
+ # @group Set Operations
41
+ #########################################################################
42
+
43
+ # @return NullSet
44
+ def complement
45
+ # ¬U = ∅
46
+ NullSet.build
47
+ end
48
+
49
+ # @return [AbstractSet]
50
+ def intersection(other)
51
+ # U & A = A
52
+ Sets.build(other)
53
+ end
54
+
55
+ # @return [AbstractSet]
56
+ def union(other)
57
+ # U ∪ A = U
58
+ self
59
+ end
60
+
61
+ # @return [AbstractSet]
62
+ def symmetric_difference(other)
63
+ # U ⊖ A = (U ∖ A) ∪ (A ∖ U) = (¬A) ∪ (∅) = ¬A
64
+ Sets.complement(other)
65
+ end
66
+
67
+ # @return [AbstractSet]
68
+ def difference(other)
69
+ # U ∖ A = ¬A
70
+ Sets.complement(other)
71
+ end
72
+
73
+ # @group Set Ordering
74
+ #########################################################################
75
+
76
+ # @return [Boolean]
77
+ def proper_subset?(other)
78
+ false
79
+ end
80
+
81
+ # @return [Boolean]
82
+ def proper_superset?(other)
83
+ not other.eql?(self)
84
+ end
85
+
86
+ # @return [Boolean]
87
+ def ==(other)
88
+ eql?(other)
89
+ end
90
+
91
+ # @group Pretty Printing
92
+ #########################################################################
93
+
94
+ # @return [String]
95
+ def inspect
96
+ "UniversalSet"
97
+ end
98
+
99
+ # @endgroup
100
+ #########################################################################
101
+ end.new
102
+
103
+ end
104
+ end
@@ -0,0 +1,57 @@
1
+ module Stupidedi
2
+
3
+ module Sets
4
+ autoload :AbstractSet, "stupidedi/sets/abstract_set"
5
+ autoload :AbsoluteSet, "stupidedi/sets/absolute_set"
6
+ autoload :NullSet, "stupidedi/sets/null_set"
7
+ autoload :RelativeComplement, "stupidedi/sets/relative_complement"
8
+ autoload :RelativeSet, "stupidedi/sets/relative_set"
9
+ autoload :UniversalSet, "stupidedi/sets/universal_set"
10
+ end
11
+
12
+ class << Sets
13
+ # @group Constructors
14
+ ###########################################################################
15
+
16
+ # @return [Sets::AbstractSet]
17
+ def build(object)
18
+ if object.is_a?(Sets::AbstractSet)
19
+ object
20
+ elsif object.is_a?(Enumerable)
21
+ Sets::RelativeSet.build(object)
22
+ else
23
+ raise TypeError,
24
+ "argument must be an AbstractSet or Enumerable"
25
+ end
26
+ end
27
+
28
+ # @return [Sets::AbstractSet]
29
+ def complement(other)
30
+ build(other).complement
31
+ end
32
+
33
+ # @return [Sets::UniversalSet]
34
+ def universal
35
+ Sets::UniversalSet.build
36
+ end
37
+
38
+ # @return [Sets::NullSet]
39
+ def empty
40
+ Sets::NullSet.build
41
+ end
42
+
43
+ # @return [Sets::AbsoluteSet]
44
+ def absolute(other, universe = other)
45
+ if universe.eql?(other)
46
+ Sets::AbsoluteSet.build(universe)
47
+ else
48
+ Sets::AbsoluteSet.build(universe).intersection(other)
49
+ end
50
+ end
51
+
52
+ # @endgroup
53
+ ###########################################################################
54
+ end
55
+
56
+
57
+ end
@@ -0,0 +1,109 @@
1
+ module Stupidedi
2
+
3
+ #
4
+ # This performs tail call optimization on methods declared by the programmer
5
+ # to be in tail call form. It can't actually verify if they are, so be sure
6
+ # to write tests for your methods.
7
+ #
8
+ # Because the optimizations are done in pure Ruby, the benefits are somewhat
9
+ # limited -- the stack doesn't grow but it only begins to outperform the
10
+ # unoptimized code only when the stack reaches a depth of about 5000 frames.
11
+ # Before that threshold, it actually performs significantly worse -- about 70%
12
+ # slower at 50 stack frames, and nearly 100% slower at 10 stack frames.
13
+ #
14
+ # @example
15
+ # class Unoptimized
16
+ # def fact(n, accumulator = 1)
17
+ # (n < 2) ? accumulator : fact(n-1, n * accumulator)
18
+ # end
19
+ # end
20
+ #
21
+ # class Optimized
22
+ # include TailCall
23
+ #
24
+ # def fact(n, accumulator = 1)
25
+ # (n < 2) ? accumulator : fact(n-1, n * accumulator)
26
+ # end
27
+ #
28
+ # optimize_tailcall :fact
29
+ # end
30
+ #
31
+ # Benchmarks
32
+ # ----------
33
+ # o = Optimized.new
34
+ # u = Unoptimized.new
35
+ #
36
+ # [10, 50, 100, 500, 1000, 5000, 10000, 50000].each do |n|
37
+ # Benchmark.bm do |x|
38
+ # x.report("#{n} optim = ") { puts(begin; o.fact(n).size; rescue; $! end) }
39
+ # x.report("#{n} plain = ") { puts(begin; u.fact(n).size; rescue; $! end) }
40
+ # end
41
+ # end
42
+ #
43
+ # With 10000 stack frames the optimized version runs about 40% faster. These
44
+ # benchmark results were produced by Ruby Enterprise Edition 1.8.7
45
+ #
46
+ # n tco plain ratio
47
+ # ------------------------------------
48
+ # 10 0.7918 0.0045 0.0056
49
+ # 50 0.2476 0.0674 0.2723
50
+ # 100 0.5207 0.2008 0.3856
51
+ # 500 2.5064 1.0426 0.4160
52
+ # 1000 5.8834 3.2413 0.5509
53
+ # 5000 42.5210 41.7398 0.9816
54
+ # 10000 14.5664 20.3000 1.3936
55
+ # 25000 9.3729 (stack err)
56
+ #
57
+ # It seems like this tradeoff makes sense only for methods we know are going to
58
+ # consistently generate thousands of stack frames. We're probably better off
59
+ # using Ruby YARV (1.9) in all cases though, since it performs faster in general
60
+ # and it supposedly implements tail call optimization in the interpreter.
61
+ #
62
+ #
63
+ # @see http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/145593
64
+ #
65
+ module TailCall
66
+ def self.included(base)
67
+ base.extend(ClassMethods)
68
+ end
69
+
70
+ # @private
71
+ module ClassMethods
72
+
73
+ # @return [void]
74
+ def optimize_tailcall(*names)
75
+ @__tc ||= Hash.new
76
+
77
+ for name in names
78
+ @__tc[name.to_sym] = instance_method(name)
79
+
80
+ module_eval <<-RUBY
81
+ def #{name}(*args, &block)
82
+ if Thread.current[:tc_#{name}]
83
+ throw(:recurse_#{name}, [args, block])
84
+ else
85
+ Thread.current[:tc_#{name}] =
86
+ self.class.instance_variable_get(:@__tc)[:#{name}].bind(self)
87
+
88
+ result = catch(:done_#{name}) do
89
+ while true
90
+ args, block =
91
+ catch(:recurse_#{name}) do
92
+ throw(:done_#{name},
93
+ Thread.current[:tc_#{name}].call(*args, &block))
94
+ end
95
+ end
96
+ end
97
+
98
+ Thread.current[:tc_#{name}] = nil
99
+
100
+ result
101
+ end
102
+ end
103
+ RUBY
104
+ end
105
+ end
106
+ end
107
+
108
+ end
109
+ end