mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Compare commits
1486 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1c09046c13 | |||
| 716e7b815f | |||
| e3ae0e4f29 | |||
| 26475d0a78 | |||
| 762f682b80 | |||
| e6b72b2121 | |||
| 7ed9bb3bd3 | |||
| e2e6554b56 | |||
| 91bf55bbe5 | |||
| 0711c861ca | |||
| b158f26f0c | |||
| c9a66d4c41 | |||
| 68c5384830 | |||
| ec19c34a20 | |||
| f1eeaad84a | |||
| 86d102350b | |||
| afd46eccd1 | |||
| 65a2c2082d | |||
| 53e2df3e93 | |||
| c308a149f0 | |||
| 423f872c84 | |||
| 87ffab5713 | |||
| 9516731329 | |||
| c022e4643f | |||
| 610bcc88c2 | |||
| 698f5f707c | |||
| 5bbcea9b3b | |||
| b5d43a16a3 | |||
| ff08856fe3 | |||
| afca99a40b | |||
| 426c1f9e0b | |||
| 0a0cc5a217 | |||
| 31a961acf1 | |||
| cab6b0f39b | |||
| 25d390d6cc | |||
| 180b73fec4 | |||
| 0a022f7b8d | |||
| 418ad65db4 | |||
| 7e3e8d8ed5 | |||
| faf51f82c7 | |||
| 56db3cf3eb | |||
| f39f428ed4 | |||
| 61f49690e4 | |||
| 1bea1e2050 | |||
| 485955eccc | |||
| 4550f4e381 | |||
| c3188cac43 | |||
| 7d7f9feee7 | |||
| d25ebec988 | |||
| d47003aea4 | |||
| d9e2532552 | |||
| 9c5e28646b | |||
| 788e4388f8 | |||
| 57a435aa1d | |||
| 659c680a5b | |||
| 0419f07915 | |||
| f2084f300b | |||
| 8e59695625 | |||
| 65b04066a2 | |||
| 7ad53273a2 | |||
| d68da042b3 | |||
| 830321fed5 | |||
| 73727aeb50 | |||
| 31eb5f4e1b | |||
| cca5e0977c | |||
| 08bd095446 | |||
| 6a6586ca84 | |||
| 486c9d902d | |||
| 7d51a7bbf5 | |||
| 557805da07 | |||
| 68714ab648 | |||
| e022080390 | |||
| 3248de83b6 | |||
| eebb56713e | |||
| ae5463c9e4 | |||
| 63fade1396 | |||
| a7e42a2024 | |||
| c7327c84dc | |||
| b37b312081 | |||
| c240aeada9 | |||
| 1b185f08e7 | |||
| ac512e9d9f | |||
| 52d55e6069 | |||
| fa33a4d75a | |||
| 3dc3643e34 | |||
| 34872e90d4 | |||
| dffa203d07 | |||
| 7ff84789c3 | |||
| b3a181aaa1 | |||
| 80b5a56f51 | |||
| e89676a6ec | |||
| 91444c4747 | |||
| fdd5ce8fac | |||
| d2313aebd6 | |||
| e5f160dc7e | |||
| ab0f4db688 | |||
| 249fef7dc4 | |||
| 82e00ce60f | |||
| a690aef8d3 | |||
| f38e6c63e9 | |||
| 8392578216 | |||
| e6841abad6 | |||
| 54ec08c7f1 | |||
| d78acc7afe | |||
| 8ffd4e47fb | |||
| e8dcfe1745 | |||
| 01c2f59e14 | |||
| 9e3cbaaacd | |||
| 87ce740168 | |||
| fb49a94314 | |||
| 78195eb2ae | |||
| 09a99154c0 | |||
| 67897195de | |||
| 152e8c5bb2 | |||
| 4d5e3e1e63 | |||
| 7b04fcd092 | |||
| 8fc56f062e | |||
| 9bd2a3b5d9 | |||
| 346f154ece | |||
| 58f7f2361a | |||
| 68523b4ec4 | |||
| c0ae8a96a1 | |||
| 58ba38fe1e | |||
| f23f2bbdad | |||
| dd346be99a | |||
| 5ec5a41fd2 | |||
| 159575f630 | |||
| 505e601730 | |||
| d192a52edb | |||
| 3a9caad8eb | |||
| 19d3bb2d90 | |||
| fa5f5954da | |||
| b7e5c86612 | |||
| 3820ef791f | |||
| 8b43754644 | |||
| e9b1d9dc2f | |||
| 0ff1540e8b | |||
| 82053dd945 | |||
| ed4dbce052 | |||
| 05595c1284 | |||
| 2661ac7049 | |||
| 2760cea451 | |||
| f93734f622 | |||
| 292ea06d4d | |||
| 5e6cd86f6e | |||
| 366848996a | |||
| 1997fcf98f | |||
| 1595e8368a | |||
| 9b0ef58a48 | |||
| fd57af3ea4 | |||
| 2a24b40d30 | |||
| 9da9e5eb4e | |||
| 625976d793 | |||
| 3447162a4c | |||
| 04f8b0431c | |||
| fdaec90780 | |||
| 72522f8e0e | |||
| 0b44e802a9 | |||
| 4cd4c64266 | |||
| a170c1dd70 | |||
| 44fdd53f2e | |||
| b01b0d242b | |||
| ade7185a2b | |||
| 2a9525caab | |||
| 9b5910bd0f | |||
| 7592dfcf7d | |||
| c2634e18b6 | |||
| 28c50b3e90 | |||
| 901dccb2df | |||
| e6357f3baa | |||
| 02adae167f | |||
| cbf2738861 | |||
| a657117e4e | |||
| 20c0c6330f | |||
| b80e0ef742 | |||
| 593c12a5cd | |||
| 05f377dee4 | |||
| 0c6353aa2c | |||
| 2be42aef0f | |||
| 1bc1fed534 | |||
| 50b840c9de | |||
| f6564dd83e | |||
| e471d37ca5 | |||
| 75a01af710 | |||
| 5addd5db4a | |||
| 500bd38dfe | |||
| 2c93e4a0a8 | |||
| f76cc483d5 | |||
| e91b6a0378 | |||
| 441ff45a51 | |||
| 98c759e86a | |||
| 2a88a546b2 | |||
| 6aa091e5aa | |||
| bc88fc6ed1 | |||
| 814b7b5ef8 | |||
| 93bab387a7 | |||
| 471288f37d | |||
| d79dbd92f9 | |||
| 49d1b16822 | |||
| 306732e02d | |||
| a3fb80904d | |||
| 3554fc54de | |||
| b06dad43fa | |||
| e5eb7ef046 | |||
| 162243d95c | |||
| b7e56e9d20 | |||
| eeb6d5658d | |||
| a16885efe5 | |||
| 31827189ab | |||
| fbfe519be7 | |||
| b3a1d37926 | |||
| 2b2ff844a1 | |||
| b083c1351f | |||
| 821135e2df | |||
| 49d9fb8f41 | |||
| 9409a2ff6d | |||
| 5e469d2b92 | |||
| c88fd32713 | |||
| 4c974b9523 | |||
| f3564a405e | |||
| 322eb2328a | |||
| 6681e22c71 | |||
| 91c08d7631 | |||
| 8a18d1539b | |||
| fd086833ff | |||
| bfd11aab35 | |||
| fe77272c25 | |||
| c095736002 | |||
| 14206a75a3 | |||
| 1e52d47bc3 | |||
| fee9ec61bb | |||
| 11d5782687 | |||
| b03f1f78e3 | |||
| fbe876b871 | |||
| 672110dbe8 | |||
| e3b181586c | |||
| 35be8b2524 | |||
| 54246db00a | |||
| 62e8e910b2 | |||
| 0dca6206c1 | |||
| 8f386f7663 | |||
| 14c7a9c548 | |||
| afbbc0a2cb | |||
| 005ccd9c7e | |||
| 708d6a4964 | |||
| ca01c8792d | |||
| 4713cd9eb7 | |||
| b9817b00a4 | |||
| e89cc9b9fa | |||
| d886676690 | |||
| 64748691de | |||
| beb6e5c299 | |||
| 889f0f5f36 | |||
| 8558627b9b | |||
| 180f39bf4c | |||
| 4ce9058f64 | |||
| e27565152f | |||
| 43173e1299 | |||
| 53e2723fae | |||
| 8c9e712784 | |||
| 891839b976 | |||
| b09d2eb900 | |||
| cb42c98757 | |||
| 0bc8d1979c | |||
| e3bc680d98 | |||
| a921b936d6 | |||
| 5fef38e4c7 | |||
| dabb20ddbb | |||
| ea435f99da | |||
| b1f1fe2f81 | |||
| 17c9e65603 | |||
| 06428059f6 | |||
| 5bb3f60e49 | |||
| 7917b7f8bf | |||
| adb1eae912 | |||
| e60829405c | |||
| 3116d06003 | |||
| 695f29cd60 | |||
| 7e79840587 | |||
| 351614bbdd | |||
| 864a998c24 | |||
| eaf463ada3 | |||
| 48ba7c7bb0 | |||
| 3671404391 | |||
| 410a5031fc | |||
| 61e8f831dd | |||
| 36e1796e41 | |||
| 640fca3276 | |||
| 485efd9253 | |||
| 7c246cb9db | |||
| acd04ad519 | |||
| c90dbd12ef | |||
| 6f35b07fab | |||
| fd9617cad0 | |||
| 1829b76929 | |||
| 7bb2fc70f2 | |||
| 8f808cc9b1 | |||
| 33f72bb038 | |||
| c3ac33d9cd | |||
| cfed6e3a4b | |||
| 1a9195285c | |||
| b8fec13cab | |||
| 1d7c69a7cb | |||
| a212428fed | |||
| 633599a2cb | |||
| dfddc6a09f | |||
| e050cfb349 | |||
| 26d143bda8 | |||
| f29bc4607a | |||
| 54cd2623b3 | |||
| 58d819f317 | |||
| e38d1d278b | |||
| 5e7ced0785 | |||
| 47413d0507 | |||
| 33c8c8f8a6 | |||
| fb9358206e | |||
| a9abf65f03 | |||
| 70600c3ba8 | |||
| 5340d39ed4 | |||
| af8020e7fd | |||
| 2eeac91098 | |||
| 5013d2b20f | |||
| 3618556a95 | |||
| 97933665b6 | |||
| ba090a46af | |||
| a7f77fefa9 | |||
| 896de5532b | |||
| f715f2ddea | |||
| 23a4e7149d | |||
| a9b740b36b | |||
| faa4eaf680 | |||
| 55edae0226 | |||
| cfd0c93d7d | |||
| 55dcdd26cc | |||
| 778500563a | |||
| ff0a4f7867 | |||
| 1dbeda5c9c | |||
| c2b2bec9e2 | |||
| e7a4699135 | |||
| aa5c5de4fd | |||
| edaa7a1ba1 | |||
| 395260747a | |||
| f408143c28 | |||
| 7ed164ba89 | |||
| 4a2b055cdd | |||
| b64ce17852 | |||
| 1dddc2f712 | |||
| 14c21793a0 | |||
| c8fb7453fc | |||
| a7c8575fe3 | |||
| 0759647f06 | |||
| bda88bdbea | |||
| e76492c776 | |||
| d973a8ebc4 | |||
| fc247449e2 | |||
| 0c01afc3c9 | |||
| 72581696d3 | |||
| 2d4c092de7 | |||
| 1d16646506 | |||
| 028e34d345 | |||
| 2a38eb9325 | |||
| a8122a9d56 | |||
| 59c8fdd651 | |||
| 0fee6e1ee9 | |||
| 50a9c5d7c7 | |||
| 4b29abc565 | |||
| 84b499d02b | |||
| b956c0f43c | |||
| 023070a639 | |||
| b8869498b7 | |||
| 1b261382a0 | |||
| 4194fe9d65 | |||
| 1c66d42e47 | |||
| e66c990234 | |||
| 8bfad558f8 | |||
| 1ca06f407b | |||
| f0e54df4fe | |||
| 25c40c2f12 | |||
| 2213deeeaa | |||
| 8b92ab5c7b | |||
| c79e81ebc3 | |||
| 54905e98cf | |||
| 391e24210f | |||
| c9275bbbed | |||
| 05db341ef5 | |||
| 135b4773e3 | |||
| 0866fa38b0 | |||
| f7cf5812b1 | |||
| 87ef6aeb02 | |||
| 4880f6dc89 | |||
| 0e76faed8c | |||
| 5c15aa2f3b | |||
| c078783a5a | |||
| 66b1695ba9 | |||
| d88191e7e7 | |||
| b51b21fc63 | |||
| fabc460880 | |||
| 3b273243e6 | |||
| fc85016a32 | |||
| c6736357a7 | |||
| e3e87ee26a | |||
| 4df0380f1e | |||
| 4b09c7364e | |||
| 1905091634 | |||
| e340b17252 | |||
| 0bc6c17490 | |||
| e9ddb593f3 | |||
| 26e436e247 | |||
| f23c3cddc8 | |||
| e57d9e6047 | |||
| c1b9ec0c30 | |||
| 951ebbafdc | |||
| e683c95e90 | |||
| a072015c4e | |||
| 211d417b02 | |||
| 3a22d113ee | |||
| b1c8fad94a | |||
| 5a7ce01f12 | |||
| 203b071ca2 | |||
| baff7c63ee | |||
| 0da7b4454f | |||
| 306cb99b10 | |||
| 4b5c21cf3b | |||
| 77a3863a3d | |||
| 8e8bc9e40b | |||
| 4940ddb9fc | |||
| fb78f10893 | |||
| c8538be471 | |||
| a85bc19f35 | |||
| 1218ff5d47 | |||
| 36d016afd6 | |||
| 1a8483f17e | |||
| 1abff3f2ab | |||
| ceeb8c05df | |||
| ec390e8f1b | |||
| 6c84e6e4a5 | |||
| 0664c452ee | |||
| 59dabb38ab | |||
| 843053c97c | |||
| e8cea2accf | |||
| e924501693 | |||
| 0f5cf385b8 | |||
| 94aebe3137 | |||
| a5ac49de30 | |||
| 2ce6d23db6 | |||
| 10f28fc82d | |||
| a95b6d34aa | |||
| 92641248fa | |||
| 097bfdcac5 | |||
| 5d43a93046 | |||
| 75c1fccd08 | |||
| ef1a0e6358 | |||
| 7483753094 | |||
| c5ec37a8ab | |||
| 00845ea908 | |||
| 1d55260423 | |||
| b9523d0e06 | |||
| 2c84d94854 | |||
| 4790f28d62 | |||
| 3dc8634d86 | |||
| 7a116f27e4 | |||
| 79cfa377e1 | |||
| 4f31bcbc84 | |||
| 4c1494d58f | |||
| b43c146455 | |||
| 4c18e37f71 | |||
| 6ae4fb707a | |||
| e02cbb4426 | |||
| c9fa7b1919 | |||
| cafe6ce4f4 | |||
| 3c18ec27e9 | |||
| 6f1e1777cb | |||
| 0e0dad7697 | |||
| f7ff2d0ee3 | |||
| 1ad2dd6187 | |||
| e422ba0bff | |||
| 55431b4cef | |||
| 43594843d7 | |||
| f4f006ba40 | |||
| 3498a787ba | |||
| a1b71b64b3 | |||
| 6a2c0c6e2a | |||
| 83f2654bac | |||
| ec1a5af719 | |||
| d895861a30 | |||
| 0e93f1ff12 | |||
| dfb56074d6 | |||
| 3ff56a8e55 | |||
| f8ab3c1eeb | |||
| d398cd47d7 | |||
| a1f36316d2 | |||
| e5fb21b6d2 | |||
| 3ae621fcb3 | |||
| ec63b1a0e0 | |||
| ca837b1a24 | |||
| 03e88b9ae0 | |||
| 58fb6f421a | |||
| dc9c40f72d | |||
| 540efd3730 | |||
| e5e9d03482 | |||
| 623436276e | |||
| f55df0da7b | |||
| bce811a53a | |||
| 6b09692684 | |||
| 3d7141b7fe | |||
| ad17ba0e11 | |||
| e4a9b4a3ad | |||
| 421819dc2c | |||
| df68a3345d | |||
| a9d0d90f74 | |||
| 2a5545cc25 | |||
| 6999e45742 | |||
| ca0f32a208 | |||
| aa8786f79c | |||
| 7e520838b3 | |||
| 44b4f69fce | |||
| 8d7e95282c | |||
| 7fbbd7ab9f | |||
| 7990bb7fa7 | |||
| 06f90a3b45 | |||
| 100f0e6759 | |||
| 73b05f0130 | |||
| 165e7b181b | |||
| d0f60182af | |||
| d9049c10fa | |||
| bba6c9a1ce | |||
| e5056d058a | |||
| 83d02bcd5a | |||
| 5e22e8e350 | |||
| c0914dbb65 | |||
| b4dcb8f286 | |||
| 615f296fcf | |||
| ae786b18d5 | |||
| a510564d6d | |||
| b83ff8ccd8 | |||
| 35185e69bf | |||
| ddb1aae41d | |||
| 03614ed918 | |||
| 05129ab9b3 | |||
| 7ecb96a00a | |||
| 41039524a9 | |||
| 5b304c156c | |||
| 7ac39333b5 | |||
| ebf49932c7 | |||
| e7e5db51de | |||
| f0379c8c45 | |||
| 16e473caad | |||
| 69ad12de06 | |||
| d2163d13a8 | |||
| 949bf6ca43 | |||
| 2300c9f737 | |||
| dc5de38414 | |||
| 1a150a6e48 | |||
| 0ab9ac6b22 | |||
| 584e4e413a | |||
| 9fac1a3f8b | |||
| 398da99d05 | |||
| 55fced30cd | |||
| a3925f3dec | |||
| aec65f2605 | |||
| 4353623b72 | |||
| 6123d653b7 | |||
| fa33bd86a8 | |||
| 7d940e3682 | |||
| 16c2ac2588 | |||
| e14387440e | |||
| 11b6696ce2 | |||
| e647b16d1d | |||
| ad06781107 | |||
| c66978521d | |||
| 5a5adafabf | |||
| b07269584c | |||
| e0e23b1765 | |||
| 7c8c9f9532 | |||
| 7ff907f680 | |||
| f1ea7a31c0 | |||
| df2c3771f8 | |||
| f6f8bb2416 | |||
| 06ec17de60 | |||
| d549603a8a | |||
| b8ca0b7cd8 | |||
| c863e0dac8 | |||
| c6ea948030 | |||
| 346ebfb0ea | |||
| 25bee356b1 | |||
| 17cd7a65e7 | |||
| bceb6640fa | |||
| 977f79478f | |||
| bbb0882343 | |||
| d4ff92bcf6 | |||
| 3d98fa2e46 | |||
| a5b8603aa2 | |||
| a9e434e69a | |||
| e71a6a7b2c | |||
| 5ef8f18e9b | |||
| 99328695e3 | |||
| 9c0426c990 | |||
| 2db06c471e | |||
| 08a508cbee | |||
| 5bf60b4837 | |||
| d96b2c9a76 | |||
| 85fc9b88d0 | |||
| f73ac4112f | |||
| 0e452a75ac | |||
| b763759972 | |||
| c76631d445 | |||
| 6d42195fb2 | |||
| 274884abe5 | |||
| 761218e70b | |||
| b103fa229d | |||
| bda273f35d | |||
| 6bc38f4637 | |||
| 0ded91c806 | |||
| 81dc383291 | |||
| 550c878216 | |||
| e17092debd | |||
| c47a1984b4 | |||
| 7f3bda5653 | |||
| 5de7dc2948 | |||
| 83065df67a | |||
| f9d1d72217 | |||
| 36a0b864ba | |||
| f1207573bd | |||
| 6ebcb7417a | |||
| 9df7bceb15 | |||
| b724e06cf2 | |||
| bc9e3e6fd0 | |||
| 764a568aa4 | |||
| ff1194c134 | |||
| a5412d48fd | |||
| 842e6945f2 | |||
| 73ef548c63 | |||
| d75266dd1b | |||
| 10ed730e4b | |||
| cdf173d32c | |||
| 0e46b14b9e | |||
| 6975258efd | |||
| ae44e80668 | |||
| b00d45b095 | |||
| 4a99f4949e | |||
| cbb6f29875 | |||
| 940133b627 | |||
| 1fea63429e | |||
| 0b5d97ec42 | |||
| 6f4d4bbcc7 | |||
| 5d04e3316b | |||
| ff8b608c52 | |||
| cd9f53d42e | |||
| c35a402676 | |||
| 86ef9a2806 | |||
| 2b9f762ba1 | |||
| d3e273ba4e | |||
| f3279b41e6 | |||
| 5f7cdecdc9 | |||
| b746a0f0d2 | |||
| 9c78a9bfa2 | |||
| b7c3a876f1 | |||
| 3e67a116d1 | |||
| afa53809e2 | |||
| f35f975d26 | |||
| d4fc980527 | |||
| 6bb5ad786c | |||
| 597149ae23 | |||
| b4f9b031de | |||
| 284a1d12ee | |||
| 0ab21a9a5e | |||
| fbafa78098 | |||
| 4665b07f7b | |||
| fe3ac50845 | |||
| cb4b042777 | |||
| 393133e741 | |||
| 8b7a8978e2 | |||
| 8f2c62407c | |||
| 6c06e77446 | |||
| 6a9efd6849 | |||
| 9b2454c94d | |||
| 7405821f5a | |||
| 86f9254df0 | |||
| 825e93eba4 | |||
| 31ce73ddc3 | |||
| a2d0ee59c6 | |||
| 269f9f2125 | |||
| e65fa4d7a2 | |||
| d01003ce3a | |||
| ddd32d74e1 | |||
| 74714c8fee | |||
| c8da602752 | |||
| 03a3bd9178 | |||
| c210a8adf9 | |||
| 181f980b6c | |||
| 41c8c419cf | |||
| f723832ebc | |||
| 7ae20e0785 | |||
| 37f6e42293 | |||
| d6cb4f9cf2 | |||
| a751f7f196 | |||
| fef4b394a7 | |||
| de2363a9f0 | |||
| 388d26d770 | |||
| ab27abe083 | |||
| 625f9f6fa3 | |||
| e7fe6ee263 | |||
| 12e38597c8 | |||
| d489b41c31 | |||
| e4662d77e7 | |||
| 13a318b0c7 | |||
| f6896751b4 | |||
| ddfb24908c | |||
| 022570ab8d | |||
| b6598e052f | |||
| 77edafb04c | |||
| 59dc7d0763 | |||
| 1b45e034ba | |||
| 6316e0c75d | |||
| 92e24f809b | |||
| c7c9543bed | |||
| 57dad6e3fd | |||
| 23d18bbd62 | |||
| 93f5f22577 | |||
| 3f9d00ded3 | |||
| 4614b9d632 | |||
| 5405b47f41 | |||
| 14877469d1 | |||
| 07cf7b16f3 | |||
| 6c966a1f86 | |||
| 0cf5a0ee37 | |||
| fda64be996 | |||
| 71eeb86a99 | |||
| d08205b40d | |||
| 7f4cc0de51 | |||
| 7a13e89509 | |||
| 8a9b6c4352 | |||
| 0c3ee0ba66 | |||
| f2394859e3 | |||
| 3c8e1f94c4 | |||
| fc930700b7 | |||
| ce916b99b8 | |||
| b5dfbce767 | |||
| 44f07045d1 | |||
| 913b83d579 | |||
| 3c20c96f84 | |||
| b890528a18 | |||
| 344a7ce20c | |||
| 4122c320bb | |||
| db8265f428 | |||
| 4e365156d1 | |||
| 061d804a59 | |||
| 332d8d2a1c | |||
| 1519616ecb | |||
| c96def7c96 | |||
| e59ad60327 | |||
| fb85855fa1 | |||
| be2c1592ed | |||
| 1988bec23e | |||
| c3710dbb96 | |||
| 6b0c22e395 | |||
| b70d69de09 | |||
| 9afd376fa4 | |||
| b0cdb93a3a | |||
| 9c1f21aaa1 | |||
| 44e2c97152 | |||
| 5d781312ca | |||
| fa974a1f6a | |||
| af3d5d6c8a | |||
| 0d92431061 | |||
| 81ea81e05c | |||
| 3eebe81b35 | |||
| dcd5d0ffec | |||
| acdc2d1f24 | |||
| 679dfd75a8 | |||
| be86d8b45f | |||
| 80e03f3ffb | |||
| 82983330a3 | |||
| 1c2a2827b3 | |||
| f8121953e7 | |||
| 43795cb1f1 | |||
| 4c255c7739 | |||
| c3c882f681 | |||
| 8c408379aa | |||
| 7edbe428ca | |||
| 473b7d0efd | |||
| 7b01b969f5 | |||
| 29a9e698e3 | |||
| 999ce87129 | |||
| 77d6a953ff | |||
| ebd45b1072 | |||
| 0bff4b6a09 | |||
| 885916c84b | |||
| e88fc10679 | |||
| ec7f478eda | |||
| 67ab8406b8 | |||
| 23cc698134 | |||
| 5ede90cdf4 | |||
| 53f934a7ee | |||
| ef8df492e9 | |||
| 027b8d8377 | |||
| 46ccabacf0 | |||
| 6cde950017 | |||
| 0e2976bf93 | |||
| b7e71e4cef | |||
| 490de9dbe1 | |||
| 220c628210 | |||
| f0c1074b07 | |||
| 4a0c9c9e31 | |||
| 332a04af73 | |||
| 971a4f9122 | |||
| 0e0c96096d | |||
| 7d98055862 | |||
| 8cef3f946c | |||
| 3e1d60ae0b | |||
| c7b663f2cf | |||
| b406e9f795 | |||
| 1dcf8ba488 | |||
| 7a2391b120 | |||
| 4d6b8dbcb9 | |||
| f4a17dd7b5 | |||
| 5ed76e381c | |||
| 9c5db48d1f | |||
| d8b37d0381 | |||
| 4146b5c2b5 | |||
| 7507d46992 | |||
| be81504770 | |||
| 0848407ee5 | |||
| d713f8d761 | |||
| 2640896911 | |||
| 8d816fa142 | |||
| d3819620ce | |||
| a94525d4ea | |||
| 1e2c962fa5 | |||
| 897eabb1bb | |||
| e10b329fa3 | |||
| 861077f779 | |||
| 553dbad2c6 | |||
| 49e96a2e19 | |||
| 536b95eb48 | |||
| 9d89f8c00b | |||
| 377d6a47ac | |||
| f632baddb1 | |||
| 49db1db81f | |||
| 2e239a296e | |||
| f1a02dff58 | |||
| 381850280c | |||
| e98823f189 | |||
| e01d35ef79 | |||
| 298177fd6a | |||
| e00b48be4a | |||
| 7450a774a5 | |||
| 0ceaa0960a | |||
| 5760226e71 | |||
| ab54185005 | |||
| a809d42f5a | |||
| d6e41c3e51 | |||
| 3d8c1a7e97 | |||
| 2a1e616e4d | |||
| cbfa2b3588 | |||
| f68f5f6b97 | |||
| 7f4b57bb20 | |||
| 15f4bdb529 | |||
| 5b6e4eda2a | |||
| 3acaa44a70 | |||
| 8a5d783f2e | |||
| 5d7e4957e0 | |||
| da97715e11 | |||
| e03042ec19 | |||
| 9f677b72db | |||
| 476af3c647 | |||
| ab99e2c293 | |||
| 57610091ce | |||
| f0f4a1088a | |||
| 35deaae776 | |||
| 71357ff1d8 | |||
| bf32265743 | |||
| fe3227cd5c | |||
| 483a038d39 | |||
| 2c85213298 | |||
| 79b4f61b02 | |||
| 4b0b8f7e1a | |||
| 8976f47e0a | |||
| c082249838 | |||
| 786cbf06c3 | |||
| 1260d3b68a | |||
| f1fa5bf1c6 | |||
| 15d48efa4b | |||
| fd927d786e | |||
| c956e17c02 | |||
| 6c9013e22b | |||
| f3fb43c729 | |||
| ccd555421a | |||
| 01b9b71902 | |||
| 85a400e43d | |||
| cec53ff77e | |||
| 1b545a6b63 | |||
| 60104ce41d | |||
| 43ec918be1 | |||
| 0e10a23d7a | |||
| 0c52112dd4 | |||
| 04dbbff3c1 | |||
| f2cc1239a5 | |||
| f7f1aca8b5 | |||
| 5f2c7e47bb | |||
| 17c249780f | |||
| 5d9b84ef40 | |||
| 78b13b3955 | |||
| ef6a762d41 | |||
| bac37a9f1a | |||
| b2a16d6bf7 | |||
| c8341dbf7c | |||
| 5d099e40e6 | |||
| 63f10a1ee5 | |||
| 3366894a40 | |||
| 499498a6a7 | |||
| 84d8ecc1d7 | |||
| 4aca9ef98e | |||
| 1221f7676e | |||
| c040c8d92b | |||
| c6596cf26a | |||
| 64e5208404 | |||
| 4c9a604877 | |||
| a65f4dbb32 | |||
| db437b04a4 | |||
| 0d865a77d5 | |||
| ab3b6dbd2a | |||
| 3f90af6b42 | |||
| a7d611fb23 | |||
| 5d0fc7e57a | |||
| 8cea1f8907 | |||
| a117ec771b | |||
| 834523945e | |||
| db098d3e0e | |||
| 2294ebdd44 | |||
| 9146d5c34f | |||
| 8b3298b2d6 | |||
| 29ad0a7964 | |||
| a8bd06904d | |||
| a06adb176f | |||
| 8b5be554c7 | |||
| 8fbc4bef55 | |||
| f1767fd079 | |||
| 722d123b87 | |||
| 198c898817 | |||
| 4c25738ac7 | |||
| 2adb0c201e | |||
| 11c3ad999e | |||
| f229ed917e | |||
| 75ec86ed00 | |||
| 6b0860ce61 | |||
| 5dc688fb12 | |||
| 0789ec71e0 | |||
| d5ac785b31 | |||
| 198df61039 | |||
| f2d4640998 | |||
| 3f591d71c6 | |||
| 8bf492f127 | |||
| baa5d2e3f7 | |||
| 0828a962c0 | |||
| 42f9af41fb | |||
| 731dd78aa0 | |||
| 58f5115b22 | |||
| d077a5f0a6 | |||
| 56d4e41d76 | |||
| 96d4c2d385 | |||
| 1d781da8a6 | |||
| db72cdae28 | |||
| ab39ed4f82 | |||
| 9feb069124 | |||
| 0ff28c9e60 | |||
| ef0b239704 | |||
| 67e2dddb82 | |||
| 8f6b2121d9 | |||
| 4e2f4f4280 | |||
| ae04005092 | |||
| 3e075a7b6c | |||
| 68470bef86 | |||
| 2249551c63 | |||
| ac42ccc1fc | |||
| a8658b0f2c | |||
| a7462a7f42 | |||
| 3d288ef0d8 | |||
| 78be0172f7 | |||
| 9826ca54f2 | |||
| 9e0c48ddc6 | |||
| 2fadddcd20 | |||
| 24c345fe5c | |||
| 6c61a60609 | |||
| 4d46f366ac | |||
| f9c3ebd29d | |||
| 0a61df1c34 | |||
| 8f62957888 | |||
| 66e2928bd4 | |||
| 8494557006 | |||
| e910cf6169 | |||
| 1358725738 | |||
| ec7475d88b | |||
| 0e5c3c4ebd | |||
| 1b9c4855a3 | |||
| 006661394d | |||
| 36dbfd9bda | |||
| e86c252a99 | |||
| 8095754e28 | |||
| 7bdc709da0 | |||
| 7b88c1a8e5 | |||
| da24af34b9 | |||
| 2170fad406 | |||
| 648e9ea51b | |||
| 3f6a098626 | |||
| 9e10afe1d0 | |||
| 16aafdd866 | |||
| facf5f99d4 | |||
| a4ff31eaf6 | |||
| 3359b86ec7 | |||
| c8fdab8725 | |||
| e821c25d38 | |||
| b290e98f3b | |||
| cf23a85333 | |||
| dda73da640 | |||
| a3bfd735a0 | |||
| 451574f142 | |||
| f937af5745 | |||
| c7018ea962 | |||
| b499ad6749 | |||
| 8a6ce74b4d | |||
| 4696093673 | |||
| 1e41026b28 | |||
| f26d00d9e8 | |||
| 5d44f8582e | |||
| 7d5cf8749a | |||
| 46ab8fdf07 | |||
| 9fa3d77114 | |||
| 7b8d784040 | |||
| 7f9e333647 | |||
| 308341b990 | |||
| 1fc9a3019d | |||
| 1c360965e7 | |||
| 5fee3f5869 | |||
| e2c9a30571 | |||
| 04c21d9d6b | |||
| 25a0a6b038 | |||
| 5a9eedf541 | |||
| aa3cb0466e | |||
| ca2cfc6fe9 | |||
| 645b0fb58c | |||
| 14a72b0800 | |||
| a8bffdae50 | |||
| 468cc34c93 | |||
| dd52b88101 | |||
| 329938ef15 | |||
| 52aafcd001 | |||
| 59eaad9d78 | |||
| 2730231e50 | |||
| 8fe2a6ce0f | |||
| 515a093213 | |||
| d7fef24a95 | |||
| 460d628490 | |||
| 1c02b8558f | |||
| de3edcc170 | |||
| bad807e7f0 | |||
| 70e99d6b57 | |||
| 7fa9321c18 | |||
| e5fbe350b3 | |||
| 9501b18362 | |||
| a18904a4c2 | |||
| e9b57124a0 | |||
| adf453a584 | |||
| 059d707e3a | |||
| e1de86134d | |||
| 495a2e605d | |||
| fc666bfe20 | |||
| 46dee5716f | |||
| 01fce3dc35 | |||
| bf48473cf6 | |||
| c76dc33116 | |||
| e581f2ed97 | |||
| ce6c05600a | |||
| 718a9ceb6e | |||
| 542f0f7b16 | |||
| 91868286be | |||
| cc04f03393 | |||
| 2ef5d22b60 | |||
| b68e7a605c | |||
| b643a1a8bc | |||
| bd66c5d716 | |||
| cc01dedc65 | |||
| c377d504f6 | |||
| c6bd8ceab7 | |||
| e9cdc88008 | |||
| 31bc2b0009 | |||
| 9b8956cdd0 | |||
| 7d99830211 | |||
| 466a18b0d3 | |||
| aee1476ebd | |||
| 15945e14b9 | |||
| f0abd4241f | |||
| 3554a41a54 | |||
| 877e16501c | |||
| 1a3b32343e | |||
| b30eba6a13 | |||
| d0717efda6 | |||
| 7944d9a6d4 | |||
| 9a59cd7af8 | |||
| b200c7475a | |||
| c41e262667 | |||
| af0bef6dd8 | |||
| e8a4e4262a | |||
| 464d3fc0a3 | |||
| 057be5ffb5 | |||
| d0a7e01d9c | |||
| bf1cb87b34 | |||
| 39779b339e | |||
| 0fa94f9ead | |||
| 615e7e44e3 | |||
| 455f3954dc | |||
| abca63c73b | |||
| 04774e5bf2 | |||
| 7c62d89348 | |||
| 3642fe4013 | |||
| 81a0dcdb7a | |||
| fe99819bc9 | |||
| c279f00109 | |||
| 0b41066e83 | |||
| 051d7bc8db | |||
| 1ebe1c8b1f | |||
| 27f422880f | |||
| 3a73a58493 | |||
| 383a9c79e1 | |||
| dab87cf960 | |||
| a3a4f4d061 | |||
| 0c0b34136e | |||
| 87771ecf92 | |||
| 0bbd60b523 | |||
| 86edc9ab85 | |||
| 844b2c368f | |||
| c43795c664 | |||
| 6836f424c5 | |||
| 728d313b2c | |||
| 311f4a230f | |||
| 7e014efe45 | |||
| 38db5e550f | |||
| 9c2db2e134 | |||
| 86b69d7c5d | |||
| d83e15e866 | |||
| 0dbd1d5992 | |||
| f691a73c26 | |||
| a80a745b69 | |||
| f8a3af8086 | |||
| 3ae5fea2b8 | |||
| 74fe87c289 | |||
| 86d58a2d37 | |||
| 88a7fedea4 | |||
| 3dad125a1c | |||
| caab1c203c | |||
| 69623078a8 | |||
| 1fac605e3f | |||
| 458b517c6f | |||
| b31b8022db | |||
| d1c48192cb | |||
| 7e89736291 | |||
| 698378f076 | |||
| f2d4880098 | |||
| 906b516cfa | |||
| 0eafb089c9 | |||
| 905203ef5e | |||
| b5e2dc9097 | |||
| f6a82772e6 | |||
| 2229a2aa0f | |||
| 51cf6b6048 | |||
| ff845be72c | |||
| 7c9d941003 | |||
| d8189c2b19 | |||
| 024b09de0c | |||
| b341ee7c12 | |||
| 9ccf03e5ae | |||
| d2c1f4d10b | |||
| b462ef4506 | |||
| 4cac5e9c70 | |||
| cc66bf94d1 | |||
| 13650747e7 | |||
| 26c1dedcab | |||
| b9f7daf5b6 | |||
| 93d481d4b4 | |||
| e90ecff671 | |||
| 2af2a4fff8 | |||
| b2a0c9c6bf | |||
| 4f6703203b | |||
| 2a80cccf30 | |||
| 11961b42ac | |||
| 777cf70cc5 | |||
| 18f7b45ad1 | |||
| be2ec608e2 | |||
| 1c4428880b | |||
| 7d6f2beaaa | |||
| c165e50193 | |||
| a25ec0a749 | |||
| bdc118304c | |||
| c8a2c636e0 | |||
| 99e10b8dc4 | |||
| 4acfd1c7d2 | |||
| dd754220ce | |||
| 68de1e4fc5 | |||
| 0f5b8b66b0 | |||
| 6c67120ed4 | |||
| b19c315148 | |||
| 7337bfa497 | |||
| 07ceb138fa | |||
| 07f1ebd26d | |||
| 11ffb93852 | |||
| ca495944b6 | |||
| a55accd736 | |||
| c9a4091b83 | |||
| 1f4bd9fd9f | |||
| 2cc674e58e | |||
| 14cdff075d | |||
| 44473fecdd | |||
| 828551f86c | |||
| db7d829679 | |||
| 21963f8fa1 | |||
| cac0035348 | |||
| 78fe65aec4 | |||
| 71197d2737 | |||
| 238704592a | |||
| e724c5af98 | |||
| 1f217ea82e | |||
| 9bbfc38bb4 | |||
| 1d6b7f9bba | |||
| f5560e8f17 | |||
| c26f998ed5 | |||
| 625995424c | |||
| f3016752bd | |||
| ecd7ef5924 | |||
| 02daa2509d | |||
| 5fa3c39145 | |||
| 6c4d39412f | |||
| 042e4a4313 | |||
| 2467332c93 | |||
| efaf74672e | |||
| 5323498033 | |||
| e8efd10bd9 | |||
| 4603047eb1 | |||
| 359d2ae6fd | |||
| d34db58797 | |||
| c43a08314e | |||
| ec4982b2d3 | |||
| 8527c78fb5 | |||
| 2929c629d4 | |||
| de60400c64 | |||
| f80a4fd0e8 | |||
| 2d1134e9ea | |||
| fe7784efb0 | |||
| bfb9cf7922 | |||
| 4ab922044d | |||
| 7ee9ab89f9 | |||
| a426f0e2b5 | |||
| 752f7c1526 | |||
| 7d8cbf1a9c | |||
| 1b5c68567e | |||
| 8da787be72 | |||
| b913e7eefd | |||
| 2ba4933158 | |||
| 15de80a7cd | |||
| dacb8b626b | |||
| ae4fc77675 | |||
| 6d6be18d4e | |||
| 7f8324a2ed | |||
| 36343cf098 | |||
| c0738a74c6 | |||
| cfbc8a8995 | |||
| e92fd76248 | |||
| 1629e86063 | |||
| e4006cb53a | |||
| 0d05a22602 | |||
| 7b17158f88 | |||
| a09858af61 | |||
| a960a6f931 | |||
| 3a22166c67 | |||
| 3a97a453c4 | |||
| c455544ee2 | |||
| 1d1f273ca9 | |||
| 42752bffce | |||
| e7dbe6e87a | |||
| e82c1d3f38 | |||
| 50721e9bf8 | |||
| 9b13a59a55 | |||
| ee347f3417 | |||
| be9e203563 | |||
| 723db886e1 | |||
| 121475638d | |||
| 2103bc99ba | |||
| 669fe705cc | |||
| e61c469724 | |||
| 9439b981d8 | |||
| d1fee5892a | |||
| e7cd024498 | |||
| 24007b80b4 | |||
| a2f45bf8d1 | |||
| a44ada616e | |||
| 379c5a6d88 | |||
| b50093ad28 | |||
| 190264b3c8 | |||
| 0761b17245 | |||
| 9a2cbc4122 | |||
| e60951a305 | |||
| 1768ee02e5 | |||
| 8c34a8d561 | |||
| 689541d0fb | |||
| 093f4e2cff | |||
| fa39825b1b | |||
| 66a92240de | |||
| 78f5f98710 | |||
| 7e689e8680 | |||
| 59b7c4eaf0 | |||
| 91c285fcfe | |||
| 04097348e8 | |||
| baa40ef2b1 | |||
| 9c3c267bef | |||
| f3c71cf5da | |||
| ddfc4eb5ef | |||
| 376af5bac3 | |||
| 5b65ca3ebb | |||
| 7b2611ea28 | |||
| 8f4b7ac15c | |||
| 514450e891 | |||
| 7dc2b4f59f | |||
| f4f968241b | |||
| a0c4ca2406 | |||
| 1997420a7f | |||
| d894de86f4 | |||
| cb84ce30e7 | |||
| 9ee9c271d1 | |||
| dc61ef1c65 | |||
| 077f39bd38 | |||
| 9a1b25bdd8 | |||
| 5aeb99ad49 | |||
| 9c00de59ce | |||
| c46cb1b5eb | |||
| e5f30f83ce | |||
| 99c67749ff | |||
| 7d7a549a4f | |||
| 36045ea96f | |||
| 1c4f46f324 | |||
| a11780f4f1 | |||
| a3e1e535dc | |||
| 9f5ff9ddec | |||
| ba9cb1f757 | |||
| 10be4cbb2c | |||
| 87ce12dfe3 | |||
| 810e37b1c3 | |||
| d5cf1de1ae | |||
| 1d987d2fcd | |||
| 9850e6a9d0 | |||
| cd168c6f32 | |||
| 28e00d82fb | |||
| a6ab2c54f3 | |||
| 706ef1337a | |||
| 572b404935 | |||
| 2bf49c9232 | |||
| 083cd9ca8c | |||
| 355723ebca | |||
| 80e01e3659 | |||
| 1094bbfff8 | |||
| eda9d1a8fc | |||
| ab9dcc766e | |||
| 719452b8d2 | |||
| 14031bdf44 | |||
| 279587c138 | |||
| a8558512ec | |||
| e345d4c68f | |||
| 11b47459e7 | |||
| 39bd240116 | |||
| 7ff049457f | |||
| d9f3fd868a | |||
| f7c054bd39 | |||
| e8706d4ee7 | |||
| b9dff44582 | |||
| 56a8c592dd | |||
| a90d8b8a73 | |||
| d28f042118 | |||
| 7fd585bae1 | |||
| daa65c15de | |||
| 40c52f58d0 | |||
| ee2859de6e | |||
| b3c6075dc5 | |||
| b74458a486 | |||
| 526608c8a2 | |||
| f10b73efa7 | |||
| a2af349959 | |||
| b744097511 | |||
| a613bce3f2 | |||
| 8cee36b1b5 | |||
| 23afaf02dc | |||
| a26ce35c64 | |||
| d12f436bdb | |||
| 5a59fd3a5c | |||
| e641e9a380 | |||
| 2245818f91 | |||
| 78d2d909cf | |||
| 87d878292d | |||
| e44da8a6cc | |||
| 1e8097a4b8 | |||
| e96cdeb2af | |||
| db14b8e7d4 | |||
| d8e5e7df3f | |||
| 78ebe1b427 | |||
| 823df14ff4 | |||
| ec443d45db | |||
| 93edd26b3e | |||
| 005f01f2fc | |||
| bf4c226232 | |||
| c608c26ab4 | |||
| 49494a7367 | |||
| 8b48e2b4a4 | |||
| 97899a6922 | |||
| adb3bd6698 | |||
| d75d23294d | |||
| b4f0a68fba | |||
| 140da1c6ca | |||
| e27fb544df | |||
| e2b0606752 | |||
| c4e3c46e86 | |||
| 47a610e688 | |||
| 713aa48cf9 | |||
| 9dc875f246 | |||
| 40adffc676 | |||
| 0345215465 | |||
| a9593e1f57 | |||
| 5e8021bedb | |||
| c49541058c | |||
| 76e1017f48 | |||
| a341b8e0ff | |||
| cf827ab0e7 | |||
| 4f3a749da1 | |||
| 216e32751e | |||
| 5625e44371 | |||
| 1272df7cb6 | |||
| 35defaf1c9 | |||
| f4aa3e7ae7 | |||
| 1411d5b974 | |||
| 12144b9ad2 | |||
| 0f2d7e8a99 | |||
| b8912c3508 | |||
| 4bebd4d70f | |||
| cfe18142cb | |||
| 89147066f8 | |||
| bc5feb39a1 | |||
| e459ecc934 | |||
| 49e53bca5d | |||
| 06f1c82f64 | |||
| 0a21d9ec92 | |||
| e277079616 | |||
| 55b6ef43c5 | |||
| 14e1992ed0 | |||
| d39a05e68e | |||
| 49cc9c7cfa | |||
| c25d386c41 | |||
| acc8995060 | |||
| df529a83d6 | |||
| 7a94d02e8d | |||
| 38f4086a52 | |||
| dce09fb7fd | |||
| c869bdedc0 | |||
| 8c5cb5e782 | |||
| f89ee88a6c | |||
| 7618ca6bb3 | |||
| 8bfbca234f | |||
| 62e1823187 | |||
| 814f3305ca | |||
| d5982b43c5 | |||
| da557fbc82 | |||
| cc40f93ac8 | |||
| 911003987b | |||
| 5a425f598b | |||
| b8a23e6be8 | |||
| e8ca5e5169 | |||
| 858d67c154 | |||
| fc43022c95 | |||
| abe9ccfe4b | |||
| 88fa5851f4 | |||
| a0c62dd4b8 | |||
| 53ff8bab17 | |||
| aadcbb1690 | |||
| 0786e37ed6 | |||
| a0161d69a8 | |||
| f70a45ad3a | |||
| 558f6fc090 | |||
| e734ab3f95 | |||
| 209ad3171d | |||
| fb79282a5b | |||
| e205905d02 |
@@ -15,7 +15,9 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
.ccmalloc
|
.ccmalloc
|
||||||
.svn
|
.svn
|
||||||
|
.vscode
|
||||||
/.git
|
/.git
|
||||||
|
cscope.files
|
||||||
cscope.out
|
cscope.out
|
||||||
tags
|
tags
|
||||||
/src/y.tab.c
|
/src/y.tab.c
|
||||||
|
|||||||
+4
-3
@@ -5,7 +5,7 @@ sudo: false
|
|||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: linux
|
- os: linux
|
||||||
sudo: 9000
|
sudo: false
|
||||||
- os: osx
|
- os: osx
|
||||||
osx_image: xcode7.1
|
osx_image: xcode7.1
|
||||||
|
|
||||||
@@ -14,5 +14,6 @@ addons:
|
|||||||
packages:
|
packages:
|
||||||
- gperf
|
- gperf
|
||||||
|
|
||||||
env: MRUBY_CONFIG=travis_config.rb
|
env:
|
||||||
script: "./minirake all test"
|
- MRUBY_CONFIG=travis_config.rb
|
||||||
|
script: "./minirake -j4 all test"
|
||||||
|
|||||||
@@ -35,3 +35,6 @@ Original Authors "mruby developers" are:
|
|||||||
Terence Lee
|
Terence Lee
|
||||||
Zachary Scott
|
Zachary Scott
|
||||||
Tomasz Dąbrowski
|
Tomasz Dąbrowski
|
||||||
|
Christopher Aue
|
||||||
|
Masahiro Wakame
|
||||||
|
YAMAMOTO Masaya
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2017 mruby developers
|
Copyright (c) 2018 mruby developers
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ of the Ministry of Economy, Trade and Industry of Japan.
|
|||||||
|
|
||||||
## How to get mruby
|
## How to get mruby
|
||||||
|
|
||||||
The stable version 1.3.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/1.3.0.zip](https://github.com/mruby/mruby/archive/1.3.0.zip)
|
The stable version 2.0.0 of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/archive/2.0.0.zip](https://github.com/mruby/mruby/archive/2.0.0.zip)
|
||||||
|
|
||||||
The latest development version of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/zipball/master](https://github.com/mruby/mruby/zipball/master)
|
The latest development version of mruby can be downloaded via the following URL: [https://github.com/mruby/mruby/zipball/master](https://github.com/mruby/mruby/zipball/master)
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,12 @@ MRUBY_ROOT = File.dirname(File.expand_path(__FILE__))
|
|||||||
MRUBY_BUILD_HOST_IS_CYGWIN = RUBY_PLATFORM.include?('cygwin')
|
MRUBY_BUILD_HOST_IS_CYGWIN = RUBY_PLATFORM.include?('cygwin')
|
||||||
MRUBY_BUILD_HOST_IS_OPENBSD = RUBY_PLATFORM.include?('openbsd')
|
MRUBY_BUILD_HOST_IS_OPENBSD = RUBY_PLATFORM.include?('openbsd')
|
||||||
|
|
||||||
|
$LOAD_PATH << File.join(MRUBY_ROOT, "lib")
|
||||||
|
|
||||||
# load build systems
|
# load build systems
|
||||||
load "#{MRUBY_ROOT}/tasks/ruby_ext.rake"
|
require "mruby-core-ext"
|
||||||
load "#{MRUBY_ROOT}/tasks/mruby_build.rake"
|
require "mruby/build"
|
||||||
load "#{MRUBY_ROOT}/tasks/mrbgem_spec.rake"
|
require "mruby/gem"
|
||||||
|
|
||||||
# load configuration file
|
# load configuration file
|
||||||
MRUBY_CONFIG = (ENV['MRUBY_CONFIG'] && ENV['MRUBY_CONFIG'] != '') ? ENV['MRUBY_CONFIG'] : "#{MRUBY_ROOT}/build_config.rb"
|
MRUBY_CONFIG = (ENV['MRUBY_CONFIG'] && ENV['MRUBY_CONFIG'] != '') ? ENV['MRUBY_CONFIG'] : "#{MRUBY_ROOT}/build_config.rb"
|
||||||
@@ -63,7 +65,7 @@ MRuby.each_target do |target|
|
|||||||
exec = exefile("#{build_dir}/bin/#{bin}")
|
exec = exefile("#{build_dir}/bin/#{bin}")
|
||||||
objs = Dir.glob("#{current_dir}/tools/#{bin}/*.{c,cpp,cxx,cc}").map { |f| objfile(f.pathmap("#{current_build_dir}/tools/#{bin}/%n")) }
|
objs = Dir.glob("#{current_dir}/tools/#{bin}/*.{c,cpp,cxx,cc}").map { |f| objfile(f.pathmap("#{current_build_dir}/tools/#{bin}/%n")) }
|
||||||
|
|
||||||
file exec => objs + [libfile("#{build_dir}/lib/libmruby")] do |t|
|
file exec => objs + target.libraries do |t|
|
||||||
gem_flags = gems.map { |g| g.linker.flags }
|
gem_flags = gems.map { |g| g.linker.flags }
|
||||||
gem_flags_before_libraries = gems.map { |g| g.linker.flags_before_libraries }
|
gem_flags_before_libraries = gems.map { |g| g.linker.flags_before_libraries }
|
||||||
gem_flags_after_libraries = gems.map { |g| g.linker.flags_after_libraries }
|
gem_flags_after_libraries = gems.map { |g| g.linker.flags_after_libraries }
|
||||||
@@ -98,7 +100,7 @@ MRuby.each_target do |target|
|
|||||||
end
|
end
|
||||||
|
|
||||||
depfiles += MRuby.targets.map { |n, t|
|
depfiles += MRuby.targets.map { |n, t|
|
||||||
[t.libfile("#{t.build_dir}/lib/libmruby")]
|
t.libraries
|
||||||
}.flatten
|
}.flatten
|
||||||
|
|
||||||
depfiles += MRuby.targets.reject { |n, t| n == 'host' }.map { |n, t|
|
depfiles += MRuby.targets.reject { |n, t| n == 'host' }.map { |n, t|
|
||||||
@@ -116,10 +118,21 @@ task :all => depfiles do
|
|||||||
end
|
end
|
||||||
|
|
||||||
desc "run all mruby tests"
|
desc "run all mruby tests"
|
||||||
task :test => ["all"] do
|
MRuby.each_target do
|
||||||
MRuby.each_target do
|
next unless test_enabled?
|
||||||
run_test if test_enabled?
|
|
||||||
|
t = :"test_#{self.name}"
|
||||||
|
task t => ["all"] do
|
||||||
|
run_test
|
||||||
end
|
end
|
||||||
|
task :test => t
|
||||||
|
|
||||||
|
next unless bintest_enabled?
|
||||||
|
t = :"bintest_#{self.name}"
|
||||||
|
task t => ["all"] do
|
||||||
|
run_bintest
|
||||||
|
end
|
||||||
|
task :test => t
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "clean all built and in-repo installed artifacts"
|
desc "clean all built and in-repo installed artifacts"
|
||||||
|
|||||||
+14
-3
@@ -5,6 +5,10 @@ os: Visual Studio 2015
|
|||||||
clone_depth: 50
|
clone_depth: 50
|
||||||
|
|
||||||
|
|
||||||
|
cache:
|
||||||
|
- win_flex_bison-2.5.10.zip
|
||||||
|
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
# Visual Studio 2015 64bit
|
# Visual Studio 2015 64bit
|
||||||
@@ -18,10 +22,17 @@ environment:
|
|||||||
|
|
||||||
init:
|
init:
|
||||||
- call "%visualcpp%" %machine%
|
- call "%visualcpp%" %machine%
|
||||||
# For using bison.exe
|
# For using Rubyinstaller's Ruby 2.4 64bit
|
||||||
- set PATH=%PATH%;C:\cygwin\bin;
|
- set PATH=C:\Ruby24-x64\bin;%PATH%
|
||||||
|
- ruby --version
|
||||||
|
|
||||||
|
|
||||||
|
install:
|
||||||
|
- if not exist win_flex_bison-2.5.10.zip appveyor DownloadFile "https://github.com/lexxmark/winflexbison/releases/download/v.2.5.10/win_flex_bison-2.5.10.zip"
|
||||||
|
- 7z x -y -owin_flex_bison win_flex_bison-2.5.10.zip > nul
|
||||||
|
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
|
- set YACC=.\win_flex_bison\win_bison.exe
|
||||||
- set MRUBY_CONFIG=appveyor_config.rb
|
- set MRUBY_CONFIG=appveyor_config.rb
|
||||||
- ruby .\minirake test
|
- ruby .\minirake test all
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ MRuby::Build.new('debug') do |conf|
|
|||||||
# include all core GEMs
|
# include all core GEMs
|
||||||
conf.gembox 'full-core'
|
conf.gembox 'full-core'
|
||||||
conf.compilers.each do |c|
|
conf.compilers.each do |c|
|
||||||
c.defines += %w(MRB_GC_STRESS MRB_GC_FIXED_ARENA)
|
c.defines += %w(MRB_GC_STRESS MRB_GC_FIXED_ARENA MRB_METHOD_CACHE)
|
||||||
end
|
end
|
||||||
|
|
||||||
build_mrbc_exec
|
build_mrbc_exec
|
||||||
|
|||||||
+15
-15
@@ -68,7 +68,7 @@ class Vec
|
|||||||
def vnormalize
|
def vnormalize
|
||||||
len = vlength
|
len = vlength
|
||||||
v = Vec.new(@x, @y, @z)
|
v = Vec.new(@x, @y, @z)
|
||||||
if len > 1.0e-17 then
|
if len > 1.0e-17
|
||||||
v.x = v.x / len
|
v.x = v.x / len
|
||||||
v.y = v.y / len
|
v.y = v.y / len
|
||||||
v.z = v.z / len
|
v.z = v.z / len
|
||||||
@@ -92,10 +92,10 @@ class Sphere
|
|||||||
b = rs.vdot(ray.dir)
|
b = rs.vdot(ray.dir)
|
||||||
c = rs.vdot(rs) - (@radius * @radius)
|
c = rs.vdot(rs) - (@radius * @radius)
|
||||||
d = b * b - c
|
d = b * b - c
|
||||||
if d > 0.0 then
|
if d > 0.0
|
||||||
t = - b - Math.sqrt(d)
|
t = - b - Math.sqrt(d)
|
||||||
|
|
||||||
if t > 0.0 and t < isect.t then
|
if t > 0.0 and t < isect.t
|
||||||
isect.t = t
|
isect.t = t
|
||||||
isect.hit = true
|
isect.hit = true
|
||||||
isect.pl = Vec.new(ray.org.x + ray.dir.x * t,
|
isect.pl = Vec.new(ray.org.x + ray.dir.x * t,
|
||||||
@@ -118,16 +118,16 @@ class Plane
|
|||||||
d = -@p.vdot(@n)
|
d = -@p.vdot(@n)
|
||||||
v = ray.dir.vdot(@n)
|
v = ray.dir.vdot(@n)
|
||||||
v0 = v
|
v0 = v
|
||||||
if v < 0.0 then
|
if v < 0.0
|
||||||
v0 = -v
|
v0 = -v
|
||||||
end
|
end
|
||||||
if v0 < 1.0e-17 then
|
if v0 < 1.0e-17
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
t = -(ray.org.vdot(@n) + d) / v
|
t = -(ray.org.vdot(@n) + d) / v
|
||||||
|
|
||||||
if t > 0.0 and t < isect.t then
|
if t > 0.0 and t < isect.t
|
||||||
isect.hit = true
|
isect.hit = true
|
||||||
isect.t = t
|
isect.t = t
|
||||||
isect.n = @n
|
isect.n = @n
|
||||||
@@ -170,10 +170,10 @@ end
|
|||||||
|
|
||||||
def clamp(f)
|
def clamp(f)
|
||||||
i = f * 255.5
|
i = f * 255.5
|
||||||
if i > 255.0 then
|
if i > 255.0
|
||||||
i = 255.0
|
i = 255.0
|
||||||
end
|
end
|
||||||
if i < 0.0 then
|
if i < 0.0
|
||||||
i = 0.0
|
i = 0.0
|
||||||
end
|
end
|
||||||
i.to_i
|
i.to_i
|
||||||
@@ -183,11 +183,11 @@ def otherBasis(basis, n)
|
|||||||
basis[2] = Vec.new(n.x, n.y, n.z)
|
basis[2] = Vec.new(n.x, n.y, n.z)
|
||||||
basis[1] = Vec.new(0.0, 0.0, 0.0)
|
basis[1] = Vec.new(0.0, 0.0, 0.0)
|
||||||
|
|
||||||
if n.x < 0.6 and n.x > -0.6 then
|
if n.x < 0.6 and n.x > -0.6
|
||||||
basis[1].x = 1.0
|
basis[1].x = 1.0
|
||||||
elsif n.y < 0.6 and n.y > -0.6 then
|
elsif n.y < 0.6 and n.y > -0.6
|
||||||
basis[1].y = 1.0
|
basis[1].y = 1.0
|
||||||
elsif n.z < 0.6 and n.z > -0.6 then
|
elsif n.z < 0.6 and n.z > -0.6
|
||||||
basis[1].z = 1.0
|
basis[1].z = 1.0
|
||||||
else
|
else
|
||||||
basis[1].x = 1.0
|
basis[1].x = 1.0
|
||||||
@@ -221,8 +221,8 @@ class Scene
|
|||||||
p0 = Vec.new(isect.pl.x + eps * isect.n.x,
|
p0 = Vec.new(isect.pl.x + eps * isect.n.x,
|
||||||
isect.pl.y + eps * isect.n.y,
|
isect.pl.y + eps * isect.n.y,
|
||||||
isect.pl.z + eps * isect.n.z)
|
isect.pl.z + eps * isect.n.z)
|
||||||
nphi.times do |j|
|
nphi.times do
|
||||||
ntheta.times do |i|
|
ntheta.times do
|
||||||
r = Rand::rand
|
r = Rand::rand
|
||||||
phi = 2.0 * 3.14159265 * Rand::rand
|
phi = 2.0 * 3.14159265 * Rand::rand
|
||||||
x = Math.cos(phi) * Math.sqrt(1.0 - r)
|
x = Math.cos(phi) * Math.sqrt(1.0 - r)
|
||||||
@@ -241,7 +241,7 @@ class Scene
|
|||||||
@spheres[1].intersect(ray, occisect)
|
@spheres[1].intersect(ray, occisect)
|
||||||
@spheres[2].intersect(ray, occisect)
|
@spheres[2].intersect(ray, occisect)
|
||||||
@plane.intersect(ray, occisect)
|
@plane.intersect(ray, occisect)
|
||||||
if occisect.hit then
|
if occisect.hit
|
||||||
occlusion = occlusion + 1.0
|
occlusion = occlusion + 1.0
|
||||||
else
|
else
|
||||||
0.0
|
0.0
|
||||||
@@ -283,7 +283,7 @@ class Scene
|
|||||||
@spheres[1].intersect(ray, isect)
|
@spheres[1].intersect(ray, isect)
|
||||||
@spheres[2].intersect(ray, isect)
|
@spheres[2].intersect(ray, isect)
|
||||||
@plane.intersect(ray, isect)
|
@plane.intersect(ray, isect)
|
||||||
if isect.hit then
|
if isect.hit
|
||||||
col = ambient_occlusion(isect)
|
col = ambient_occlusion(isect)
|
||||||
rad.x = rad.x + col.x
|
rad.x = rad.x + col.x
|
||||||
rad.y = rad.y + col.y
|
rad.y = rad.y + col.y
|
||||||
|
|||||||
@@ -17,19 +17,19 @@ def test_lists()
|
|||||||
# li2 must now be empty
|
# li2 must now be empty
|
||||||
# remove each individual item from right side of li3 and
|
# remove each individual item from right side of li3 and
|
||||||
# append to right side of li2 (reversing list)
|
# append to right side of li2 (reversing list)
|
||||||
while (not li3.empty?)
|
until li3.empty?
|
||||||
li2.push(li3.pop)
|
li2.push(li3.pop)
|
||||||
end
|
end
|
||||||
# li3 must now be empty
|
# li3 must now be empty
|
||||||
# reverse li1 in place
|
# reverse li1 in place
|
||||||
li1.reverse!
|
li1.reverse!
|
||||||
# check that first item is now SIZE
|
# check that first item is now SIZE
|
||||||
if li1[0] != SIZE then
|
if li1[0] != SIZE
|
||||||
p "not SIZE"
|
p "not SIZE"
|
||||||
0
|
0
|
||||||
else
|
else
|
||||||
# compare li1 and li2 for equality
|
# compare li1 and li2 for equality
|
||||||
if li1 != li2 then
|
if li1 != li2
|
||||||
return(0)
|
return(0)
|
||||||
else
|
else
|
||||||
# return the length of the list
|
# return the length of the list
|
||||||
|
|||||||
+13
-13
@@ -8,7 +8,8 @@ MRuby::Build.new do |conf|
|
|||||||
toolchain :gcc
|
toolchain :gcc
|
||||||
end
|
end
|
||||||
|
|
||||||
enable_debug
|
# Turn on `enable_debug` for better debugging
|
||||||
|
# enable_debug
|
||||||
|
|
||||||
# Use mrbgems
|
# Use mrbgems
|
||||||
# conf.gem 'examples/mrbgems/ruby_extension_example'
|
# conf.gem 'examples/mrbgems/ruby_extension_example'
|
||||||
@@ -124,17 +125,17 @@ MRuby::Build.new('test') do |conf|
|
|||||||
conf.gembox 'default'
|
conf.gembox 'default'
|
||||||
end
|
end
|
||||||
|
|
||||||
MRuby::Build.new('bench') do |conf|
|
#MRuby::Build.new('bench') do |conf|
|
||||||
# Gets set by the VS command prompts.
|
# # Gets set by the VS command prompts.
|
||||||
if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
|
# if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']
|
||||||
toolchain :visualcpp
|
# toolchain :visualcpp
|
||||||
else
|
# else
|
||||||
toolchain :gcc
|
# toolchain :gcc
|
||||||
conf.cc.flags << '-O3'
|
# conf.cc.flags << '-O3'
|
||||||
end
|
# end
|
||||||
|
#
|
||||||
conf.gembox 'default'
|
# conf.gembox 'default'
|
||||||
end
|
#end
|
||||||
|
|
||||||
# Define cross build settings
|
# Define cross build settings
|
||||||
# MRuby::CrossBuild.new('32bit') do |conf|
|
# MRuby::CrossBuild.new('32bit') do |conf|
|
||||||
@@ -148,5 +149,4 @@ end
|
|||||||
# conf.gem 'examples/mrbgems/c_and_ruby_extension_example'
|
# conf.gem 'examples/mrbgems/c_and_ruby_extension_example'
|
||||||
#
|
#
|
||||||
# conf.test_runner.command = 'env'
|
# conf.test_runner.command = 'env'
|
||||||
#
|
|
||||||
# end
|
# end
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ To confirm mrdb was installed properly, run mrdb with the `--version` option:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ mrdb --version
|
$ mrdb --version
|
||||||
mruby 1.3.0 (2017-7-4)
|
mruby 2.0.0 (2018-12-11)
|
||||||
```
|
```
|
||||||
|
|
||||||
## 2.2 Basic Operation
|
## 2.2 Basic Operation
|
||||||
|
|||||||
@@ -114,14 +114,14 @@ inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list)
|
|||||||
|
|
||||||
mrb_ary_push(mrb, list, ary);
|
mrb_ary_push(mrb, list, ary);
|
||||||
|
|
||||||
arystr = mrb_str_buf_new(mrb, 64);
|
arystr = mrb_str_new_capa(mrb, 64);
|
||||||
mrb_str_buf_cat(mrb, arystr, head, sizeof(head));
|
mrb_str_cat(mrb, arystr, head, sizeof(head));
|
||||||
|
|
||||||
for(i=0; i<RARRAY_LEN(ary); i++) {
|
for(i=0; i<RARRAY_LEN(ary); i++) {
|
||||||
int ai = mrb_gc_arena_save(mrb);
|
int ai = mrb_gc_arena_save(mrb);
|
||||||
|
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
mrb_str_buf_cat(mrb, arystr, sep, sizeof(sep));
|
mrb_str_cat(mrb, arystr, sep, sizeof(sep));
|
||||||
}
|
}
|
||||||
if (mrb_array_p(RARRAY_PTR(ary)[i])) {
|
if (mrb_array_p(RARRAY_PTR(ary)[i])) {
|
||||||
s = inspect_ary(mrb, RARRAY_PTR(ary)[i], list);
|
s = inspect_ary(mrb, RARRAY_PTR(ary)[i], list);
|
||||||
@@ -129,11 +129,11 @@ inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list)
|
|||||||
else {
|
else {
|
||||||
s = mrb_inspect(mrb, RARRAY_PTR(ary)[i]);
|
s = mrb_inspect(mrb, RARRAY_PTR(ary)[i]);
|
||||||
}
|
}
|
||||||
mrb_str_buf_cat(mrb, arystr, RSTRING_PTR(s), RSTRING_LEN(s));
|
mrb_str_cat(mrb, arystr, RSTRING_PTR(s), RSTRING_LEN(s));
|
||||||
mrb_gc_arena_restore(mrb, ai);
|
mrb_gc_arena_restore(mrb, ai);
|
||||||
}
|
}
|
||||||
|
|
||||||
mrb_str_buf_cat(mrb, arystr, tail, sizeof(tail));
|
mrb_str_cat(mrb, arystr, tail, sizeof(tail));
|
||||||
mrb_ary_pop(mrb, list);
|
mrb_ary_pop(mrb, list);
|
||||||
|
|
||||||
return arystr;
|
return arystr;
|
||||||
|
|||||||
+1
-12
@@ -122,20 +122,9 @@ largest value of required alignment.
|
|||||||
* If defined `Float` will be a mruby object with `RBasic`.
|
* If defined `Float` will be a mruby object with `RBasic`.
|
||||||
|
|
||||||
## Instance variable configuration.
|
## Instance variable configuration.
|
||||||
`MRB_USE_IV_SEGLIST`
|
`MRB_IV_SEGMENT_SIZE`
|
||||||
* If defined enable segmented list in instance variable table instead of khash.
|
|
||||||
* Segmented list is a linked list of key and value segments.
|
|
||||||
* It will linear search instead of hash search.
|
|
||||||
|
|
||||||
`MRB_SEGMENT_SIZE`
|
|
||||||
* Default value is `4`.
|
* Default value is `4`.
|
||||||
* Specifies size of each segment in segment list.
|
* Specifies size of each segment in segment list.
|
||||||
* Ignored when `MRB_USE_IV_SEGLIST` isn't defined.
|
|
||||||
|
|
||||||
`MRB_IVHASH_INIT_SIZE`
|
|
||||||
* Default value is `8`.
|
|
||||||
* Specifies initial size for instance variable table.
|
|
||||||
* Ignored when `MRB_USE_IV_SEGLIST` is defined.
|
|
||||||
|
|
||||||
## Other configuration.
|
## Other configuration.
|
||||||
`MRB_UTF8_STRING`
|
`MRB_UTF8_STRING`
|
||||||
|
|||||||
@@ -26,6 +26,11 @@ conf.gem :github => 'masuidrive/mrbgems-example', :branch => 'master'
|
|||||||
conf.gem :bitbucket => 'mruby/mrbgems-example', :branch => 'master'
|
conf.gem :bitbucket => 'mruby/mrbgems-example', :branch => 'master'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can specify the sub directory of the repository with `:path` option:
|
||||||
|
```ruby
|
||||||
|
conf.gem github: 'mruby/mruby', path: 'mrbgems/mruby-socket'
|
||||||
|
```
|
||||||
|
|
||||||
To use mrbgem from [mgem-list](https://github.com/mruby/mgem-list) use `:mgem` option:
|
To use mrbgem from [mgem-list](https://github.com/mruby/mgem-list) use `:mgem` option:
|
||||||
```ruby
|
```ruby
|
||||||
conf.gem :mgem => 'mruby-yaml'
|
conf.gem :mgem => 'mruby-yaml'
|
||||||
@@ -174,11 +179,11 @@ Version requirement supports following operators:
|
|||||||
|
|
||||||
When more than one version requirements is passed, the dependency must satisfy all of it.
|
When more than one version requirements is passed, the dependency must satisfy all of it.
|
||||||
|
|
||||||
You can have default gem to use as depedency when it's not defined in *build_config.rb*.
|
You can have default gem to use as dependency when it's not defined in *build_config.rb*.
|
||||||
When the last argument of `add_dependency` call is `Hash`, it will be treated as default gem information.
|
When the last argument of `add_dependency` call is `Hash`, it will be treated as default gem information.
|
||||||
Its format is same as argument of method `MRuby::Build#gem`, expect that it can't be treated as path gem location.
|
Its format is same as argument of method `MRuby::Build#gem`, expect that it can't be treated as path gem location.
|
||||||
|
|
||||||
When a special version of depedency is required,
|
When a special version of dependency is required,
|
||||||
use `MRuby::Build#gem` in *build_config.rb* to override default gem.
|
use `MRuby::Build#gem` in *build_config.rb* to override default gem.
|
||||||
|
|
||||||
If you have conflicting GEMs use the following method:
|
If you have conflicting GEMs use the following method:
|
||||||
|
|||||||
+67
-26
@@ -38,7 +38,7 @@ puts [1,2,3]
|
|||||||
3
|
3
|
||||||
```
|
```
|
||||||
|
|
||||||
#### mruby [1.3.0 (2017-7-4)]
|
#### mruby [2.0.0 (2018-12-11)]
|
||||||
|
|
||||||
```
|
```
|
||||||
[1, 2, 3]
|
[1, 2, 3]
|
||||||
@@ -61,26 +61,10 @@ end
|
|||||||
|
|
||||||
```ZeroDivisionError``` is raised.
|
```ZeroDivisionError``` is raised.
|
||||||
|
|
||||||
#### mruby [1.3.0 (2017-7-4)]
|
#### mruby [2.0.0 (2018-12-11)]
|
||||||
|
|
||||||
No exception is raised.
|
No exception is raised.
|
||||||
|
|
||||||
## Check of infinite recursion
|
|
||||||
|
|
||||||
mruby does not check infinite recursion across C extensions.
|
|
||||||
|
|
||||||
```ruby
|
|
||||||
def test; eval 'test'; end; test
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Ruby [ruby 2.0.0p645 (2015-04-13 revision 50299)]
|
|
||||||
|
|
||||||
```SystemStackError``` is raised.
|
|
||||||
|
|
||||||
#### mruby [1.3.0 (2017-7-4)]
|
|
||||||
|
|
||||||
Segmentation fault.
|
|
||||||
|
|
||||||
## Fiber execution can't cross C function boundary
|
## Fiber execution can't cross C function boundary
|
||||||
|
|
||||||
mruby's ```Fiber``` is implemented in a similar way to Lua's co-routine. This
|
mruby's ```Fiber``` is implemented in a similar way to Lua's co-routine. This
|
||||||
@@ -105,7 +89,7 @@ p Liste.new "foobar"
|
|||||||
|
|
||||||
``` [] ```
|
``` [] ```
|
||||||
|
|
||||||
#### mruby [1.3.0 (2017-7-4)]
|
#### mruby [1.4.1 (2018-4-27)]
|
||||||
|
|
||||||
```ArgumentError``` is raised.
|
```ArgumentError``` is raised.
|
||||||
|
|
||||||
@@ -135,7 +119,7 @@ false
|
|||||||
true
|
true
|
||||||
```
|
```
|
||||||
|
|
||||||
#### mruby [1.3.0 (2017-7-4)]
|
#### mruby [2.0.0 (2018-12-11)]
|
||||||
|
|
||||||
```
|
```
|
||||||
true
|
true
|
||||||
@@ -158,7 +142,7 @@ defined?(Foo)
|
|||||||
nil
|
nil
|
||||||
```
|
```
|
||||||
|
|
||||||
#### mruby [1.3.0 (2017-7-4)]
|
#### mruby [2.0.0 (2018-12-11)]
|
||||||
|
|
||||||
```NameError``` is raised.
|
```NameError``` is raised.
|
||||||
|
|
||||||
@@ -175,7 +159,7 @@ alias $a $__a__
|
|||||||
|
|
||||||
``` nil ```
|
``` nil ```
|
||||||
|
|
||||||
#### mruby [1.3.0 (2017-7-4)]
|
#### mruby [2.0.0 (2018-12-11)]
|
||||||
|
|
||||||
Syntax error
|
Syntax error
|
||||||
|
|
||||||
@@ -197,12 +181,69 @@ end
|
|||||||
```ArgumentError``` is raised.
|
```ArgumentError``` is raised.
|
||||||
The re-defined ```+``` operator does not accept any arguments.
|
The re-defined ```+``` operator does not accept any arguments.
|
||||||
|
|
||||||
#### mruby [1.3.0 (2017-7-4)]
|
#### mruby [2.0.0 (2018-12-11)]
|
||||||
|
|
||||||
``` 'ab' ```
|
``` 'ab' ```
|
||||||
Behavior of the operator wasn't changed.
|
Behavior of the operator wasn't changed.
|
||||||
|
|
||||||
## ```Kernel.binding``` missing
|
## Kernel#binding is not supported
|
||||||
|
|
||||||
```Kernel.binding``` is not implemented as it is not in the
|
`Kernel#binding` method is not supported.
|
||||||
ISO standard.
|
|
||||||
|
#### Ruby [ruby 2.5.1p57 (2018-03-29 revision 63029)]
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ruby -e 'puts Proc.new {}.binding'
|
||||||
|
#<Binding:0x00000e9deabb9950>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### mruby [2.0.0 (2018-12-11)]
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./bin/mruby -e 'puts Proc.new {}.binding'
|
||||||
|
trace (most recent call last):
|
||||||
|
[0] -e:1
|
||||||
|
-e:1: undefined method 'binding' (NoMethodError)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Keyword arguments
|
||||||
|
|
||||||
|
mruby keyword arguments behave slightly different from CRuby 2.5
|
||||||
|
to make the behavior simpler and less confusing. Maybe in the
|
||||||
|
future, the simpler behavior will be adopted to CRuby as well.
|
||||||
|
|
||||||
|
#### Ruby [ruby 2.5.1p57 (2018-03-29 revision 63029)]
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)'
|
||||||
|
[[{"a"=>1}], {:b=>2}]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### mruby [mruby 2.0.0]
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./bin/mruby -e 'def m(*r,**k) p [r,k] end; m("a"=>1,:b=>2)'
|
||||||
|
trace (most recent call last):
|
||||||
|
[0] -e:1
|
||||||
|
-e:1: keyword argument hash with non symbol keys (ArgumentError)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Destructuring
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def m(a,(b,c),d); p [a,b,c,d]; end
|
||||||
|
m(1,[2,3],4) # => [1,2,3,4]
|
||||||
|
```
|
||||||
|
Destructured arguments (`b` and `c` in above example) cannot be accessed
|
||||||
|
from the default expression of optional arguments and keyword arguments,
|
||||||
|
since actual assignment is done after the evaluation of those default
|
||||||
|
expressions. Thus:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
def f(a,(b,c),d=b)
|
||||||
|
p [a,b,c,d]
|
||||||
|
end
|
||||||
|
f(1,[2,3])
|
||||||
|
```
|
||||||
|
|
||||||
|
CRuby gives `[1,2,3,nil]`. mruby raises `NoMethodError` for `b`.
|
||||||
|
|||||||
+127
@@ -0,0 +1,127 @@
|
|||||||
|
# The new bytecode
|
||||||
|
|
||||||
|
We will reimplement VM to use 8bit instruction code. By
|
||||||
|
bytecode, we mean real byte code. The whole purpose is
|
||||||
|
reducing the memory consumption of mruby VM.
|
||||||
|
|
||||||
|
# Instructions
|
||||||
|
|
||||||
|
Instructions are bytes. There can be 256 instructions. Currently we
|
||||||
|
have 94 instructions. Instructions can take 0 to 3 operands.
|
||||||
|
|
||||||
|
## operands
|
||||||
|
|
||||||
|
The size of operands can be either 8bits, 16bits or 24bits.
|
||||||
|
In the table.1 below, the second field describes the size (and
|
||||||
|
sign) of operands.
|
||||||
|
|
||||||
|
* B: 8bit
|
||||||
|
* sB: signed 8bit
|
||||||
|
* S: 16bit
|
||||||
|
* sS: signed 16bit
|
||||||
|
* W: 24bit
|
||||||
|
|
||||||
|
First two byte operands may be extended to 16bit. When those byte
|
||||||
|
operands are bigger than 256, the instruction will be prefixed by
|
||||||
|
`OP_EXT1` (means 1st operand is 16bit) or `OP_EXT2` (means 2nd operand
|
||||||
|
is 16bit) or `OP_EXT3` (means 1st and 2nd operands are 16bit).
|
||||||
|
|
||||||
|
For instructions marked by `'`, `OP_EXT1` can be prefixed. For those
|
||||||
|
with `"`, either `OP_EXT1` or `OP_EXT2` or `OP_EXT2` can be prefixed.
|
||||||
|
|
||||||
|
## table.1 Instruction Table
|
||||||
|
|
||||||
|
|Instruction Name |Operand type |Semantics
|
||||||
|
|-----------------|-------------|-----------------
|
||||||
|
|OP_NOP | - |
|
||||||
|
|OP_MOVE" |BB |R(a) = R(b)
|
||||||
|
|OP_LOADL" |BB |R(a) = Pool(b)
|
||||||
|
|OP_LOADI" |BsB |R(a) = mrb_int(b)
|
||||||
|
|OP_LOADI_0' |B |R(a) = 0
|
||||||
|
|OP_LOADI_1' |B |R(a) = 1
|
||||||
|
|OP_LOADI_2' |B |R(a) = 2
|
||||||
|
|OP_LOADI_3' |B |R(a) = 3
|
||||||
|
|OP_LOADSYM" |BB |R(a) = Syms(b)
|
||||||
|
|OP_LOADNIL' |B |R(a) = nil
|
||||||
|
|OP_LOADSELF' |B |R(a) = self
|
||||||
|
|OP_LOADT' |B |R(a) = true
|
||||||
|
|OP_LOADF' |B |R(a) = false
|
||||||
|
|OP_GETGV" |BB |R(a) = getglobal(Syms(b))
|
||||||
|
|OP_SETGV" |BB |setglobal(Syms(b), R(a))
|
||||||
|
|OP_GETSV" |BB |R(a) = Special[b]
|
||||||
|
|OP_SETSV" |BB |Special[b] = R(a)
|
||||||
|
|OP_GETIV" |BB |R(a) = ivget(Syms(b))
|
||||||
|
|OP_SETIV" |BB |ivset(Syms(b),R(a))
|
||||||
|
|OP_GETCV" |BB |R(a) = cvget(Syms(b))
|
||||||
|
|OP_SETCV" |BB |cvset(Syms(b),R(a))
|
||||||
|
|OP_GETCONST" |BB |R(a) = constget(Syms(b))
|
||||||
|
|OP_SETCONST" |BB |constset(Syms(b),R(a))
|
||||||
|
|OP_GETMCNST" |BB |R(a) = R(a)::Syms(b)
|
||||||
|
|OP_SETMCNST" |BB |R(a+1)::Syms(b) = R(a)
|
||||||
|
|OP_GETUPVAR' |BBB |R(a) = uvget(b,c)
|
||||||
|
|OP_SETUPVAR' |BBB |uvset(b,c,R(a))
|
||||||
|
|OP_JMP |S |pc+=a
|
||||||
|
|OP_JMPIF' |SB |if R(b) pc+=a
|
||||||
|
|OP_JMPNOT' |SB |if !R(b) pc+=a
|
||||||
|
|OP_ONERR |sS |rescue_push(pc+a)
|
||||||
|
|OP_EXCEPT' |B |R(a) = exc
|
||||||
|
|OP_RESCUE" |BB |R(b) = R(a).isa?(R(b))
|
||||||
|
|OP_POPERR |B |a.times{rescue_pop()}
|
||||||
|
|OP_RAISE' |B |raise(R(a))
|
||||||
|
|OP_EPUSH' |B |ensure_push(SEQ[a])
|
||||||
|
|OP_EPOP |B |A.times{ensure_pop().call}
|
||||||
|
|OP_SENDV" |BB |R(a) = call(R(a),Syms(b),*R(a+1))
|
||||||
|
|OP_SENDVB" |BB |R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2))
|
||||||
|
|OP_SEND" |BBB |R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c))
|
||||||
|
|OP_SENDB" |BBB |R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1))
|
||||||
|
|OP_CALL' |B |R(a) = self.call(frame.argc, frame.argv)
|
||||||
|
|OP_SUPER' |BB |R(a) = super(R(a+1),... ,R(a+b+1))
|
||||||
|
|OP_ARGARY' |BS |R(a) = argument array (16=5:1:5:1:4)
|
||||||
|
|OP_ENTER |W |arg setup according to flags (23=5:5:1:5:5:1:1)
|
||||||
|
|OP_KARG" |BB |R(a) = kdict[Syms(Bx)] # todo
|
||||||
|
|OP_KARG2" |BB |R(a) = kdict[Syms(Bx)]; kdict.rm(Syms(b)) # todo
|
||||||
|
|OP_RETURN' |B |return R(a) (normal)
|
||||||
|
|OP_RETURN_BLK' |B |return R(a) (in-block return)
|
||||||
|
|OP_BREAK' |B |break R(a)
|
||||||
|
|OP_BLKPUSH' |BS |R(a) = block (16=5:1:5:1:4)
|
||||||
|
|OP_ADD" |BB |R(a) = R(a)+R(a+1)
|
||||||
|
|OP_ADDI" |BBB |R(a) = R(a)+mrb_int(c)
|
||||||
|
|OP_SUB" |BB |R(a) = R(a)-R(a+1)
|
||||||
|
|OP_SUBI" |BB |R(a) = R(a)-C
|
||||||
|
|OP_MUL" |BB |R(a) = R(a)*R(a+1)
|
||||||
|
|OP_DIV" |BB |R(a) = R(a)/R(a+1)
|
||||||
|
|OP_EQ" |BB |R(a) = R(a)==R(a+1)
|
||||||
|
|OP_LT" |BB |R(a) = R(a)<R(a+1)
|
||||||
|
|OP_LE" |BB |R(a) = R(a)<=R(a+1)
|
||||||
|
|OP_GT" |BB |R(a) = R(a)>R(a+1)
|
||||||
|
|OP_GE" |BB |R(a) = R(a)>=R(a+1)
|
||||||
|
|OP_ARRAY' |BB |R(a) = ary_new(R(a),R(a+1)..R(a+b))
|
||||||
|
|OP_ARRAY2" |BB |R(a) = ary_new(R(b),R(b+1)..R(b+c))
|
||||||
|
|OP_ARYCAT' |B |ary_cat(R(a),R(a+1))
|
||||||
|
|OP_ARYPUSH' |B |ary_push(R(a),R(a+1))
|
||||||
|
|OP_AREF' |BB |R(a) = R(a)[b]
|
||||||
|
|OP_ASET' |BB |R(a)[b] = R(a+1)
|
||||||
|
|OP_APOST' |BB |*R(a),R(A+1)..R(A+C) = R(a)[B..]
|
||||||
|
|OP_STRING" |BB |R(a) = str_dup(Lit(b))
|
||||||
|
|OP_STRCAT' |B |str_cat(R(a),R(a+1))
|
||||||
|
|OP_HASH' |BB |R(a) = hash_new(R(a),R(a+1)..R(a+b))
|
||||||
|
|OP_HASHADD' |BB |R(a) = hash_push(R(a),R(a+1)..R(a+b))
|
||||||
|
|OP_LAMBDA" |BB |R(a) = lambda(SEQ[b],OP_L_LAMBDA)
|
||||||
|
|OP_BLOCK" |BB |R(a) = lambda(SEQ[b],OP_L_BLOCK)
|
||||||
|
|OP_METHOD" |BB |R(a) = lambda(SEQ[b],OP_L_METHOD)
|
||||||
|
|OP_RANGE_INC' |B |R(a) = range_new(R(a),R(a+1),FALSE)
|
||||||
|
|OP_RANGE_EXC' |B |R(a) = range_new(R(a),R(a+1),TRUE)
|
||||||
|
|OP_OCLASS' |B |R(a) = ::Object
|
||||||
|
|OP_CLASS" |BB |R(a) = newclass(R(a),Syms(b),R(a+1))
|
||||||
|
|OP_MODULE" |BB |R(a) = newmodule(R(a),Syms(b))
|
||||||
|
|OP_EXEC" |BB |R(a) = blockexec(R(a),SEQ[b])
|
||||||
|
|OP_DEF" |BB |R(a).newmethod(Syms(b),R(a+1))
|
||||||
|
|OP_ALIAS' |B |alias_method(R(a),R(a+1),R(a+2))
|
||||||
|
|OP_UNDEF" |BB |undef_method(R(a),Syms(b))
|
||||||
|
|OP_SCLASS' |B |R(a) = R(a).singleton_class
|
||||||
|
|OP_TCLASS' |B |R(a) = target_class
|
||||||
|
|OP_ERR' |B |raise(RuntimeError, Lit(Bx))
|
||||||
|
|OP_EXT1 |- |make 1st operand 16bit
|
||||||
|
|OP_EXT2 |- |make 2nd operand 16bit
|
||||||
|
|OP_EXT3 |- |make 1st and 2nd operands 16bit
|
||||||
|
|OP_STOP |- |stop VM
|
||||||
@@ -46,7 +46,6 @@ MRuby::CrossBuild.new("ArduinoDue") do |conf|
|
|||||||
|
|
||||||
#configuration for low memory environment
|
#configuration for low memory environment
|
||||||
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
|
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
|
||||||
cc.defines << %w(MRB_USE_IV_SEGLIST)
|
|
||||||
cc.defines << %w(KHASH_DEFAULT_SIZE=8)
|
cc.defines << %w(KHASH_DEFAULT_SIZE=8)
|
||||||
cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20)
|
cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20)
|
||||||
cc.defines << %w(MRB_GC_STRESS)
|
cc.defines << %w(MRB_GC_STRESS)
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ MRuby::CrossBuild.new("RX630") do |conf|
|
|||||||
#configuration for low memory environment
|
#configuration for low memory environment
|
||||||
cc.defines << %w(MRB_USE_FLOAT)
|
cc.defines << %w(MRB_USE_FLOAT)
|
||||||
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
|
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
|
||||||
cc.defines << %w(MRB_USE_IV_SEGLIST)
|
|
||||||
cc.defines << %w(KHASH_DEFAULT_SIZE=8)
|
cc.defines << %w(KHASH_DEFAULT_SIZE=8)
|
||||||
cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20)
|
cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20)
|
||||||
cc.defines << %w(MRB_GC_STRESS)
|
cc.defines << %w(MRB_GC_STRESS)
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ end
|
|||||||
|
|
||||||
# Requires Android NDK r13 or later.
|
# Requires Android NDK r13 or later.
|
||||||
MRuby::CrossBuild.new('android-arm64-v8a') do |conf|
|
MRuby::CrossBuild.new('android-arm64-v8a') do |conf|
|
||||||
params = {
|
params = {
|
||||||
:arch => 'arm64-v8a',
|
:arch => 'arm64-v8a',
|
||||||
:platform => 'android-24',
|
:platform => 'android-24',
|
||||||
:toolchain => :clang,
|
:toolchain => :clang,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ end
|
|||||||
|
|
||||||
# Requires Android NDK r13 or later.
|
# Requires Android NDK r13 or later.
|
||||||
MRuby::CrossBuild.new('android-armeabi') do |conf|
|
MRuby::CrossBuild.new('android-armeabi') do |conf|
|
||||||
params = {
|
params = {
|
||||||
:arch => 'armeabi',
|
:arch => 'armeabi',
|
||||||
:platform => 'android-24',
|
:platform => 'android-24',
|
||||||
:toolchain => :clang,
|
:toolchain => :clang,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ MRuby::CrossBuild.new("chipKITMax32") do |conf|
|
|||||||
|
|
||||||
#configuration for low memory environment
|
#configuration for low memory environment
|
||||||
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
|
cc.defines << %w(MRB_HEAP_PAGE_SIZE=64)
|
||||||
cc.defines << %w(MRB_USE_IV_SEGLIST)
|
|
||||||
cc.defines << %w(KHASH_DEFAULT_SIZE=8)
|
cc.defines << %w(KHASH_DEFAULT_SIZE=8)
|
||||||
cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20)
|
cc.defines << %w(MRB_STR_BUF_MIN_SIZE=20)
|
||||||
cc.defines << %w(MRB_GC_STRESS)
|
cc.defines << %w(MRB_GC_STRESS)
|
||||||
|
|||||||
+27
-9
@@ -28,13 +28,37 @@
|
|||||||
/* add -DMRB_USE_FLOAT to use float instead of double for floating point numbers */
|
/* add -DMRB_USE_FLOAT to use float instead of double for floating point numbers */
|
||||||
//#define MRB_USE_FLOAT
|
//#define MRB_USE_FLOAT
|
||||||
|
|
||||||
|
/* exclude floating point numbers */
|
||||||
|
//#define MRB_WITHOUT_FLOAT
|
||||||
|
|
||||||
|
/* add -DMRB_METHOD_CACHE to use method cache to improve performance */
|
||||||
|
//#define MRB_METHOD_CACHE
|
||||||
|
/* size of the method cache (need to be the power of 2) */
|
||||||
|
//#define MRB_METHOD_CACHE_SIZE (1<<7)
|
||||||
|
|
||||||
|
/* add -DMRB_METHOD_TABLE_INLINE to reduce the size of method table */
|
||||||
|
/* MRB_METHOD_TABLE_INLINE requires LSB of function pointers to be zero */
|
||||||
|
/* you might need to specify --falign-functions=n (where n>1) */
|
||||||
|
//#define MRB_METHOD_TABLE_INLINE
|
||||||
|
|
||||||
/* add -DMRB_INT16 to use 16bit integer for mrb_int; conflict with MRB_INT64 */
|
/* add -DMRB_INT16 to use 16bit integer for mrb_int; conflict with MRB_INT64 */
|
||||||
//#define MRB_INT16
|
//#define MRB_INT16
|
||||||
|
|
||||||
/* add -DMRB_INT64 to use 64bit integer for mrb_int; conflict with MRB_INT16 */
|
/* add -DMRB_INT64 to use 64bit integer for mrb_int; conflict with MRB_INT16 */
|
||||||
//#define MRB_INT64
|
//#define MRB_INT64
|
||||||
|
|
||||||
/* represent mrb_value in boxed double; conflict with MRB_USE_FLOAT */
|
/* if no specific integer type is chosen */
|
||||||
|
#if !defined(MRB_INT16) && !defined(MRB_INT32) && !defined(MRB_INT64)
|
||||||
|
# if defined(MRB_64BIT) && !defined(MRB_NAN_BOXING)
|
||||||
|
/* Use 64bit integers on 64bit architecture (without MRB_NAN_BOXING) */
|
||||||
|
# define MRB_INT64
|
||||||
|
# else
|
||||||
|
/* Otherwise use 32bit integers */
|
||||||
|
# define MRB_INT32
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* represent mrb_value in boxed double; conflict with MRB_USE_FLOAT and MRB_WITHOUT_FLOAT */
|
||||||
//#define MRB_NAN_BOXING
|
//#define MRB_NAN_BOXING
|
||||||
|
|
||||||
/* define on big endian machines; used by MRB_NAN_BOXING */
|
/* define on big endian machines; used by MRB_NAN_BOXING */
|
||||||
@@ -52,12 +76,6 @@
|
|||||||
/* number of object per heap page */
|
/* number of object per heap page */
|
||||||
//#define MRB_HEAP_PAGE_SIZE 1024
|
//#define MRB_HEAP_PAGE_SIZE 1024
|
||||||
|
|
||||||
/* use segmented list for IV table */
|
|
||||||
//#define MRB_USE_IV_SEGLIST
|
|
||||||
|
|
||||||
/* initial size for IV khash; ignored when MRB_USE_IV_SEGLIST is set */
|
|
||||||
//#define MRB_IVHASH_INIT_SIZE 8
|
|
||||||
|
|
||||||
/* if _etext and _edata available, mruby can reduce memory used by symbols */
|
/* if _etext and _edata available, mruby can reduce memory used by symbols */
|
||||||
//#define MRB_USE_ETEXT_EDATA
|
//#define MRB_USE_ETEXT_EDATA
|
||||||
|
|
||||||
@@ -93,10 +111,10 @@
|
|||||||
//#define MRB_FIXED_STATE_ATEXIT_STACK
|
//#define MRB_FIXED_STATE_ATEXIT_STACK
|
||||||
|
|
||||||
/* -DMRB_DISABLE_XXXX to drop following features */
|
/* -DMRB_DISABLE_XXXX to drop following features */
|
||||||
//#define MRB_DISABLE_STDIO /* use of stdio */
|
//#define MRB_DISABLE_STDIO /* use of stdio */
|
||||||
|
|
||||||
/* -DMRB_ENABLE_XXXX to enable following features */
|
/* -DMRB_ENABLE_XXXX to enable following features */
|
||||||
//#define MRB_ENABLE_DEBUG_HOOK /* hooks for debugger */
|
//#define MRB_ENABLE_DEBUG_HOOK /* hooks for debugger */
|
||||||
|
|
||||||
/* end of configuration */
|
/* end of configuration */
|
||||||
|
|
||||||
|
|||||||
+116
-44
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
** mruby - An embeddable Ruby implementation
|
** mruby - An embeddable Ruby implementation
|
||||||
**
|
**
|
||||||
** Copyright (c) mruby developers 2010-2017
|
** Copyright (c) mruby developers 2010-2018
|
||||||
**
|
**
|
||||||
** Permission is hereby granted, free of charge, to any person obtaining
|
** Permission is hereby granted, free of charge, to any person obtaining
|
||||||
** a copy of this software and associated documentation files (the
|
** a copy of this software and associated documentation files (the
|
||||||
@@ -65,11 +65,23 @@
|
|||||||
|
|
||||||
#include "mrbconf.h"
|
#include "mrbconf.h"
|
||||||
|
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
|
#ifndef FLT_EPSILON
|
||||||
|
#define FLT_EPSILON (1.19209290e-07f)
|
||||||
|
#endif
|
||||||
|
#ifndef DBL_EPSILON
|
||||||
|
#define DBL_EPSILON ((double)2.22044604925031308085e-16L)
|
||||||
|
#endif
|
||||||
|
#ifndef LDBL_EPSILON
|
||||||
|
#define LDBL_EPSILON (1.08420217248550443401e-19L)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MRB_USE_FLOAT
|
#ifdef MRB_USE_FLOAT
|
||||||
#define MRB_FLOAT_EPSILON FLT_EPSILON
|
#define MRB_FLOAT_EPSILON FLT_EPSILON
|
||||||
#else
|
#else
|
||||||
#define MRB_FLOAT_EPSILON DBL_EPSILON
|
#define MRB_FLOAT_EPSILON DBL_EPSILON
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "mruby/common.h"
|
#include "mruby/common.h"
|
||||||
#include <mruby/value.h>
|
#include <mruby/value.h>
|
||||||
@@ -81,7 +93,7 @@
|
|||||||
*/
|
*/
|
||||||
MRB_BEGIN_DECL
|
MRB_BEGIN_DECL
|
||||||
|
|
||||||
typedef uint32_t mrb_code;
|
typedef uint8_t mrb_code;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Required arguments signature type.
|
* Required arguments signature type.
|
||||||
@@ -111,9 +123,8 @@ typedef struct {
|
|||||||
mrb_sym mid;
|
mrb_sym mid;
|
||||||
struct RProc *proc;
|
struct RProc *proc;
|
||||||
mrb_value *stackent;
|
mrb_value *stackent;
|
||||||
int nregs;
|
uint16_t ridx;
|
||||||
int ridx;
|
uint16_t epos;
|
||||||
int epos;
|
|
||||||
struct REnv *env;
|
struct REnv *env;
|
||||||
mrb_code *pc; /* return address */
|
mrb_code *pc; /* return address */
|
||||||
mrb_code *err; /* error position */
|
mrb_code *err; /* error position */
|
||||||
@@ -140,16 +151,46 @@ struct mrb_context {
|
|||||||
mrb_callinfo *ci;
|
mrb_callinfo *ci;
|
||||||
mrb_callinfo *cibase, *ciend;
|
mrb_callinfo *cibase, *ciend;
|
||||||
|
|
||||||
mrb_code **rescue; /* exception handler stack */
|
uint16_t *rescue; /* exception handler stack */
|
||||||
int rsize;
|
uint16_t rsize;
|
||||||
struct RProc **ensure; /* ensure handler stack */
|
struct RProc **ensure; /* ensure handler stack */
|
||||||
int esize, eidx;
|
uint16_t esize, eidx;
|
||||||
|
|
||||||
enum mrb_fiber_state status;
|
enum mrb_fiber_state status;
|
||||||
mrb_bool vmexec;
|
mrb_bool vmexec;
|
||||||
struct RFiber *fib;
|
struct RFiber *fib;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef MRB_METHOD_CACHE_SIZE
|
||||||
|
# define MRB_METHOD_CACHE
|
||||||
|
#else
|
||||||
|
/* default method cache size: 128 */
|
||||||
|
/* cache size needs to be power of 2 */
|
||||||
|
# define MRB_METHOD_CACHE_SIZE (1<<7)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef mrb_value (*mrb_func_t)(struct mrb_state *mrb, mrb_value);
|
||||||
|
|
||||||
|
#ifdef MRB_METHOD_TABLE_INLINE
|
||||||
|
typedef uintptr_t mrb_method_t;
|
||||||
|
#else
|
||||||
|
typedef struct {
|
||||||
|
mrb_bool func_p;
|
||||||
|
union {
|
||||||
|
struct RProc *proc;
|
||||||
|
mrb_func_t func;
|
||||||
|
};
|
||||||
|
} mrb_method_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MRB_METHOD_CACHE
|
||||||
|
struct mrb_cache_entry {
|
||||||
|
struct RClass *c, *c0;
|
||||||
|
mrb_sym mid;
|
||||||
|
mrb_method_t m;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
struct mrb_jmpbuf;
|
struct mrb_jmpbuf;
|
||||||
|
|
||||||
typedef void (*mrb_atexit_func)(struct mrb_state*);
|
typedef void (*mrb_atexit_func)(struct mrb_state*);
|
||||||
@@ -178,8 +219,11 @@ typedef struct mrb_state {
|
|||||||
struct RClass *string_class;
|
struct RClass *string_class;
|
||||||
struct RClass *array_class;
|
struct RClass *array_class;
|
||||||
struct RClass *hash_class;
|
struct RClass *hash_class;
|
||||||
|
struct RClass *range_class;
|
||||||
|
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
struct RClass *float_class;
|
struct RClass *float_class;
|
||||||
|
#endif
|
||||||
struct RClass *fixnum_class;
|
struct RClass *fixnum_class;
|
||||||
struct RClass *true_class;
|
struct RClass *true_class;
|
||||||
struct RClass *false_class;
|
struct RClass *false_class;
|
||||||
@@ -190,6 +234,10 @@ typedef struct mrb_state {
|
|||||||
struct alloca_header *mems;
|
struct alloca_header *mems;
|
||||||
mrb_gc gc;
|
mrb_gc gc;
|
||||||
|
|
||||||
|
#ifdef MRB_METHOD_CACHE
|
||||||
|
struct mrb_cache_entry cache[MRB_METHOD_CACHE_SIZE];
|
||||||
|
#endif
|
||||||
|
|
||||||
mrb_sym symidx;
|
mrb_sym symidx;
|
||||||
struct kh_n2s *name2sym; /* symbol hash */
|
struct kh_n2s *name2sym; /* symbol hash */
|
||||||
struct symbol_name *symtbl; /* symbol table */
|
struct symbol_name *symtbl; /* symbol table */
|
||||||
@@ -219,12 +267,10 @@ typedef struct mrb_state {
|
|||||||
#else
|
#else
|
||||||
mrb_atexit_func *atexit_stack;
|
mrb_atexit_func *atexit_stack;
|
||||||
#endif
|
#endif
|
||||||
mrb_int atexit_stack_len;
|
uint16_t atexit_stack_len;
|
||||||
|
uint16_t ecall_nest; /* prevent infinite recursive ecall() */
|
||||||
} mrb_state;
|
} mrb_state;
|
||||||
|
|
||||||
|
|
||||||
typedef mrb_value (*mrb_func_t)(mrb_state *mrb, mrb_value);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a new class.
|
* Defines a new class.
|
||||||
*
|
*
|
||||||
@@ -340,7 +386,7 @@ MRB_API void mrb_define_class_method(mrb_state *, struct RClass *, const char *,
|
|||||||
MRB_API void mrb_define_singleton_method(mrb_state*, struct RObject*, const char*, mrb_func_t, mrb_aspec);
|
MRB_API void mrb_define_singleton_method(mrb_state*, struct RObject*, const char*, mrb_func_t, mrb_aspec);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a module fuction.
|
* Defines a module function.
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
*
|
*
|
||||||
@@ -440,9 +486,10 @@ MRB_API void mrb_define_const(mrb_state*, struct RClass*, const char *name, mrb_
|
|||||||
* }
|
* }
|
||||||
* @param [mrb_state*] mrb_state* The mruby state reference.
|
* @param [mrb_state*] mrb_state* The mruby state reference.
|
||||||
* @param [struct RClass*] RClass* A class the method will be undefined from.
|
* @param [struct RClass*] RClass* A class the method will be undefined from.
|
||||||
* @param [const char*] constchar* The name of the method to be undefined.
|
* @param [const char] const char* The name of the method to be undefined.
|
||||||
*/
|
*/
|
||||||
MRB_API void mrb_undef_method(mrb_state*, struct RClass*, const char*);
|
MRB_API void mrb_undef_method(mrb_state*, struct RClass*, const char*);
|
||||||
|
MRB_API void mrb_undef_method_id(mrb_state*, struct RClass*, mrb_sym);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Undefine a class method.
|
* Undefine a class method.
|
||||||
@@ -484,7 +531,7 @@ MRB_API void mrb_undef_method(mrb_state*, struct RClass*, const char*);
|
|||||||
MRB_API void mrb_undef_class_method(mrb_state*, struct RClass*, const char*);
|
MRB_API void mrb_undef_class_method(mrb_state*, struct RClass*, const char*);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a new object instace of c class.
|
* Initialize a new object instance of c class.
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
*
|
*
|
||||||
@@ -670,7 +717,6 @@ MRB_API mrb_value mrb_notimplement_m(mrb_state*, mrb_value);
|
|||||||
* @return [mrb_value] The newly duplicated object.
|
* @return [mrb_value] The newly duplicated object.
|
||||||
*/
|
*/
|
||||||
MRB_API mrb_value mrb_obj_dup(mrb_state *mrb, mrb_value obj);
|
MRB_API mrb_value mrb_obj_dup(mrb_state *mrb, mrb_value obj);
|
||||||
MRB_API mrb_value mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if obj responds to the given method. If the method was defined for that
|
* Returns true if obj responds to the given method. If the method was defined for that
|
||||||
@@ -737,7 +783,7 @@ MRB_API struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *o
|
|||||||
#define MRB_ARGS_REQ(n) ((mrb_aspec)((n)&0x1f) << 18)
|
#define MRB_ARGS_REQ(n) ((mrb_aspec)((n)&0x1f) << 18)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Funtion takes n optional arguments
|
* Function takes n optional arguments
|
||||||
*
|
*
|
||||||
* @param n
|
* @param n
|
||||||
* The number of optional arguments.
|
* The number of optional arguments.
|
||||||
@@ -745,7 +791,7 @@ MRB_API struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *o
|
|||||||
#define MRB_ARGS_OPT(n) ((mrb_aspec)((n)&0x1f) << 13)
|
#define MRB_ARGS_OPT(n) ((mrb_aspec)((n)&0x1f) << 13)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Funtion takes n1 mandatory arguments and n2 optional arguments
|
* Function takes n1 mandatory arguments and n2 optional arguments
|
||||||
*
|
*
|
||||||
* @param n1
|
* @param n1
|
||||||
* The number of required arguments.
|
* The number of required arguments.
|
||||||
@@ -783,22 +829,22 @@ MRB_API struct RClass * mrb_define_module_under(mrb_state *mrb, struct RClass *o
|
|||||||
*
|
*
|
||||||
* Must be a C string composed of the following format specifiers:
|
* Must be a C string composed of the following format specifiers:
|
||||||
*
|
*
|
||||||
* | char | Ruby type | C types | Notes |
|
* | char | Ruby type | C types | Notes |
|
||||||
* |:----:|----------------|-------------------|----------------------------------------------------|
|
* |:----:|----------------|-------------------|----------------------------------------------------|
|
||||||
* | `o` | {Object} | {mrb_value} | Could be used to retrieve any type of argument |
|
* | `o` | {Object} | {mrb_value} | Could be used to retrieve any type of argument |
|
||||||
* | `C` | {Class}/{Module} | {mrb_value} | |
|
* | `C` | {Class}/{Module} | {mrb_value} | |
|
||||||
* | `S` | {String} | {mrb_value} | when `!` follows, the value may be `nil` |
|
* | `S` | {String} | {mrb_value} | when `!` follows, the value may be `nil` |
|
||||||
* | `A` | {Array} | {mrb_value} | when `!` follows, the value may be `nil` |
|
* | `A` | {Array} | {mrb_value} | when `!` follows, the value may be `nil` |
|
||||||
* | `H` | {Hash} | {mrb_value} | when `!` follows, the value may be `nil` |
|
* | `H` | {Hash} | {mrb_value} | when `!` follows, the value may be `nil` |
|
||||||
* | `s` | {String} | char *, {mrb_int} | Receive two arguments; `s!` gives (`NULL`,`0`) for `nil` |
|
* | `s` | {String} | char *, {mrb_int} | Receive two arguments; `s!` gives (`NULL`,`0`) for `nil` |
|
||||||
* | `z` | {String} | char * | `NULL` terminated string; `z!` gives `NULL` for `nil` |
|
* | `z` | {String} | char * | `NULL` terminated string; `z!` gives `NULL` for `nil` |
|
||||||
* | `a` | {Array} | {mrb_value} *, {mrb_int} | Receive two arguments; `a!` gives (`NULL`,`0`) for `nil` |
|
* | `a` | {Array} | {mrb_value} *, {mrb_int} | Receive two arguments; `a!` gives (`NULL`,`0`) for `nil` |
|
||||||
* | `f` | {Float} | {mrb_float} | |
|
* | `f` | {Float} | {mrb_float} | |
|
||||||
* | `i` | {Integer} | {mrb_int} | |
|
* | `i` | {Integer} | {mrb_int} | |
|
||||||
* | `b` | boolean | {mrb_bool} | |
|
* | `b` | boolean | {mrb_bool} | |
|
||||||
* | `n` | {Symbol} | {mrb_sym} | |
|
* | `n` | {Symbol} | {mrb_sym} | |
|
||||||
* | `&` | block | {mrb_value} | |
|
* | `&` | block | {mrb_value} | &! raises exception if no block given. |
|
||||||
* | `*` | rest arguments | {mrb_value} *, {mrb_int} | Receive the rest of arguments as an array. |
|
* | `*` | rest arguments | {mrb_value} *, {mrb_int} | Receive the rest of arguments as an array; *! avoid copy of the stack. |
|
||||||
* | | | optional | | After this spec following specs would be optional. |
|
* | | | optional | | After this spec following specs would be optional. |
|
||||||
* | `?` | optional given | {mrb_bool} | `TRUE` if preceding argument is given. Used to check optional argument is given. |
|
* | `?` | optional given | {mrb_bool} | `TRUE` if preceding argument is given. Used to check optional argument is given. |
|
||||||
*
|
*
|
||||||
@@ -809,10 +855,6 @@ typedef const char *mrb_args_format;
|
|||||||
/**
|
/**
|
||||||
* Retrieve arguments from mrb_state.
|
* Retrieve arguments from mrb_state.
|
||||||
*
|
*
|
||||||
* When applicable, implicit conversions (such as `to_str`, `to_ary`, `to_hash`) are
|
|
||||||
* applied to received arguments.
|
|
||||||
* Used inside a function of mrb_func_t type.
|
|
||||||
*
|
|
||||||
* @param mrb The current MRuby state.
|
* @param mrb The current MRuby state.
|
||||||
* @param format [mrb_args_format] is a list of format specifiers
|
* @param format [mrb_args_format] is a list of format specifiers
|
||||||
* @param ... The passing variadic arguments must be a pointer of retrieving type.
|
* @param ... The passing variadic arguments must be a pointer of retrieving type.
|
||||||
@@ -827,11 +869,14 @@ mrb_get_mid(mrb_state *mrb) /* get method symbol */
|
|||||||
return mrb->c->ci->mid;
|
return mrb->c->ci->mid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
/**
|
||||||
mrb_get_argc(mrb_state *mrb) /* get argc */
|
* Retrieve number of arguments from mrb_state.
|
||||||
{
|
*
|
||||||
return mrb->c->ci->argc;
|
* Correctly handles *splat arguments.
|
||||||
}
|
*/
|
||||||
|
MRB_API mrb_int mrb_get_argc(mrb_state *mrb);
|
||||||
|
|
||||||
|
MRB_API mrb_value* mrb_get_argv(mrb_state *mrb);
|
||||||
|
|
||||||
/* `strlen` for character string literals (use with caution or `strlen` instead)
|
/* `strlen` for character string literals (use with caution or `strlen` instead)
|
||||||
Adjacent string literals are concatenated in C/C++ in translation phase 6.
|
Adjacent string literals are concatenated in C/C++ in translation phase 6.
|
||||||
@@ -945,13 +990,13 @@ MRB_API mrb_value mrb_str_new_static(mrb_state *mrb, const char *p, size_t len);
|
|||||||
#define mrb_str_new_lit(mrb, lit) mrb_str_new_static(mrb, (lit), mrb_strlen_lit(lit))
|
#define mrb_str_new_lit(mrb, lit) mrb_str_new_static(mrb, (lit), mrb_strlen_lit(lit))
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
char* mrb_utf8_from_locale(const char *p, size_t len);
|
MRB_API char* mrb_utf8_from_locale(const char *p, int len);
|
||||||
char* mrb_locale_from_utf8(const char *p, size_t len);
|
MRB_API char* mrb_locale_from_utf8(const char *p, int len);
|
||||||
#define mrb_locale_free(p) free(p)
|
#define mrb_locale_free(p) free(p)
|
||||||
#define mrb_utf8_free(p) free(p)
|
#define mrb_utf8_free(p) free(p)
|
||||||
#else
|
#else
|
||||||
#define mrb_utf8_from_locale(p, l) (p)
|
#define mrb_utf8_from_locale(p, l) ((char*)p)
|
||||||
#define mrb_locale_from_utf8(p, l) (p)
|
#define mrb_locale_from_utf8(p, l) ((char*)p)
|
||||||
#define mrb_locale_free(p)
|
#define mrb_locale_free(p)
|
||||||
#define mrb_utf8_free(p)
|
#define mrb_utf8_free(p)
|
||||||
#endif
|
#endif
|
||||||
@@ -1023,17 +1068,32 @@ MRB_API mrb_sym mrb_obj_to_sym(mrb_state *mrb, mrb_value name);
|
|||||||
MRB_API mrb_bool mrb_obj_eq(mrb_state*, mrb_value, mrb_value);
|
MRB_API mrb_bool mrb_obj_eq(mrb_state*, mrb_value, mrb_value);
|
||||||
MRB_API mrb_bool mrb_obj_equal(mrb_state*, mrb_value, mrb_value);
|
MRB_API mrb_bool mrb_obj_equal(mrb_state*, mrb_value, mrb_value);
|
||||||
MRB_API mrb_bool mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2);
|
MRB_API mrb_bool mrb_equal(mrb_state *mrb, mrb_value obj1, mrb_value obj2);
|
||||||
MRB_API mrb_value mrb_convert_to_integer(mrb_state *mrb, mrb_value val, int base);
|
MRB_API mrb_value mrb_convert_to_integer(mrb_state *mrb, mrb_value val, mrb_int base);
|
||||||
MRB_API mrb_value mrb_Integer(mrb_state *mrb, mrb_value val);
|
MRB_API mrb_value mrb_Integer(mrb_state *mrb, mrb_value val);
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
MRB_API mrb_value mrb_Float(mrb_state *mrb, mrb_value val);
|
MRB_API mrb_value mrb_Float(mrb_state *mrb, mrb_value val);
|
||||||
|
#endif
|
||||||
MRB_API mrb_value mrb_inspect(mrb_state *mrb, mrb_value obj);
|
MRB_API mrb_value mrb_inspect(mrb_state *mrb, mrb_value obj);
|
||||||
MRB_API mrb_bool mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2);
|
MRB_API mrb_bool mrb_eql(mrb_state *mrb, mrb_value obj1, mrb_value obj2);
|
||||||
|
|
||||||
|
static inline int mrb_gc_arena_save(mrb_state*);
|
||||||
|
static inline void mrb_gc_arena_restore(mrb_state*,int);
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
mrb_gc_arena_save(mrb_state *mrb)
|
||||||
|
{
|
||||||
|
return mrb->gc.arena_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
mrb_gc_arena_restore(mrb_state *mrb, int idx)
|
||||||
|
{
|
||||||
|
mrb->gc.arena_idx = idx;
|
||||||
|
}
|
||||||
|
|
||||||
MRB_API void mrb_garbage_collect(mrb_state*);
|
MRB_API void mrb_garbage_collect(mrb_state*);
|
||||||
MRB_API void mrb_full_gc(mrb_state*);
|
MRB_API void mrb_full_gc(mrb_state*);
|
||||||
MRB_API void mrb_incremental_gc(mrb_state *);
|
MRB_API void mrb_incremental_gc(mrb_state *);
|
||||||
MRB_API int mrb_gc_arena_save(mrb_state*);
|
|
||||||
MRB_API void mrb_gc_arena_restore(mrb_state*,int);
|
|
||||||
MRB_API void mrb_gc_mark(mrb_state*,struct RBasic*);
|
MRB_API void mrb_gc_mark(mrb_state*,struct RBasic*);
|
||||||
#define mrb_gc_mark_value(mrb,val) do {\
|
#define mrb_gc_mark_value(mrb,val) do {\
|
||||||
if (!mrb_immediate_p(val)) mrb_gc_mark((mrb), mrb_basic_ptr(val)); \
|
if (!mrb_immediate_p(val)) mrb_gc_mark((mrb), mrb_basic_ptr(val)); \
|
||||||
@@ -1097,9 +1157,12 @@ MRB_API void mrb_print_error(mrb_state *mrb);
|
|||||||
#define E_SYNTAX_ERROR (mrb_exc_get(mrb, "SyntaxError"))
|
#define E_SYNTAX_ERROR (mrb_exc_get(mrb, "SyntaxError"))
|
||||||
#define E_LOCALJUMP_ERROR (mrb_exc_get(mrb, "LocalJumpError"))
|
#define E_LOCALJUMP_ERROR (mrb_exc_get(mrb, "LocalJumpError"))
|
||||||
#define E_REGEXP_ERROR (mrb_exc_get(mrb, "RegexpError"))
|
#define E_REGEXP_ERROR (mrb_exc_get(mrb, "RegexpError"))
|
||||||
|
#define E_FROZEN_ERROR (mrb_exc_get(mrb, "FrozenError"))
|
||||||
|
|
||||||
#define E_NOTIMP_ERROR (mrb_exc_get(mrb, "NotImplementedError"))
|
#define E_NOTIMP_ERROR (mrb_exc_get(mrb, "NotImplementedError"))
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
#define E_FLOATDOMAIN_ERROR (mrb_exc_get(mrb, "FloatDomainError"))
|
#define E_FLOATDOMAIN_ERROR (mrb_exc_get(mrb, "FloatDomainError"))
|
||||||
|
#endif
|
||||||
|
|
||||||
#define E_KEY_ERROR (mrb_exc_get(mrb, "KeyError"))
|
#define E_KEY_ERROR (mrb_exc_get(mrb, "KeyError"))
|
||||||
|
|
||||||
@@ -1121,6 +1184,7 @@ MRB_API void mrb_gc_unregister(mrb_state *mrb, mrb_value obj);
|
|||||||
|
|
||||||
MRB_API mrb_value mrb_to_int(mrb_state *mrb, mrb_value val);
|
MRB_API mrb_value mrb_to_int(mrb_state *mrb, mrb_value val);
|
||||||
#define mrb_int(mrb, val) mrb_fixnum(mrb_to_int(mrb, val))
|
#define mrb_int(mrb, val) mrb_fixnum(mrb_to_int(mrb, val))
|
||||||
|
MRB_API mrb_value mrb_to_str(mrb_state *mrb, mrb_value val);
|
||||||
MRB_API void mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t);
|
MRB_API void mrb_check_type(mrb_state *mrb, mrb_value x, enum mrb_vtype t);
|
||||||
|
|
||||||
typedef enum call_type {
|
typedef enum call_type {
|
||||||
@@ -1130,7 +1194,7 @@ typedef enum call_type {
|
|||||||
CALL_TYPE_MAX
|
CALL_TYPE_MAX
|
||||||
} call_type;
|
} call_type;
|
||||||
|
|
||||||
MRB_API void mrb_define_alias(mrb_state *mrb, struct RClass *klass, const char *name1, const char *name2);
|
MRB_API void mrb_define_alias(mrb_state *mrb, struct RClass *c, const char *a, const char *b);
|
||||||
MRB_API const char *mrb_class_name(mrb_state *mrb, struct RClass* klass);
|
MRB_API const char *mrb_class_name(mrb_state *mrb, struct RClass* klass);
|
||||||
MRB_API void mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val);
|
MRB_API void mrb_define_global_const(mrb_state *mrb, const char *name, mrb_value val);
|
||||||
|
|
||||||
@@ -1155,12 +1219,20 @@ MRB_API mrb_value mrb_fiber_resume(mrb_state *mrb, mrb_value fib, mrb_int argc,
|
|||||||
*/
|
*/
|
||||||
MRB_API mrb_value mrb_fiber_yield(mrb_state *mrb, mrb_int argc, const mrb_value *argv);
|
MRB_API mrb_value mrb_fiber_yield(mrb_state *mrb, mrb_int argc, const mrb_value *argv);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if a Fiber is alive
|
||||||
|
*
|
||||||
|
* @mrbgem mruby-fiber
|
||||||
|
*/
|
||||||
|
MRB_API mrb_value mrb_fiber_alive_p(mrb_state *mrb, mrb_value fib);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FiberError reference
|
* FiberError reference
|
||||||
*
|
*
|
||||||
* @mrbgem mruby-fiber
|
* @mrbgem mruby-fiber
|
||||||
*/
|
*/
|
||||||
#define E_FIBER_ERROR (mrb_exc_get(mrb, "FiberError"))
|
#define E_FIBER_ERROR (mrb_exc_get(mrb, "FiberError"))
|
||||||
|
MRB_API void mrb_stack_extend(mrb_state*, mrb_int);
|
||||||
|
|
||||||
/* memory pool implementation */
|
/* memory pool implementation */
|
||||||
typedef struct mrb_pool mrb_pool;
|
typedef struct mrb_pool mrb_pool;
|
||||||
@@ -1183,21 +1255,21 @@ MRB_API mrb_value mrb_format(mrb_state *mrb, const char *format, ...);
|
|||||||
/* use naive memcpy and memset instead */
|
/* use naive memcpy and memset instead */
|
||||||
#undef memcpy
|
#undef memcpy
|
||||||
#undef memset
|
#undef memset
|
||||||
static inline void*
|
static void*
|
||||||
mrbmemcpy(void *dst, const void *src, size_t n)
|
mrbmemcpy(void *dst, const void *src, size_t n)
|
||||||
{
|
{
|
||||||
char *d = dst;
|
char *d = (char*)dst;
|
||||||
const char *s = src;
|
const char *s = (const char*)src;
|
||||||
while (n--)
|
while (n--)
|
||||||
*d++ = *s++;
|
*d++ = *s++;
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
#define memcpy(a,b,c) mrbmemcpy(a,b,c)
|
#define memcpy(a,b,c) mrbmemcpy(a,b,c)
|
||||||
|
|
||||||
static inline void*
|
static void*
|
||||||
mrbmemset(void *s, int c, size_t n)
|
mrbmemset(void *s, int c, size_t n)
|
||||||
{
|
{
|
||||||
char *t = s;
|
char *t = (char*)s;
|
||||||
while (n--)
|
while (n--)
|
||||||
*t++ = c;
|
*t++ = c;
|
||||||
return s;
|
return s;
|
||||||
|
|||||||
+45
-26
@@ -21,22 +21,46 @@ typedef struct mrb_shared_array {
|
|||||||
mrb_value *ptr;
|
mrb_value *ptr;
|
||||||
} mrb_shared_array;
|
} mrb_shared_array;
|
||||||
|
|
||||||
|
#define MRB_ARY_EMBED_LEN_MAX ((mrb_int)(sizeof(void*)*3/sizeof(mrb_value)))
|
||||||
struct RArray {
|
struct RArray {
|
||||||
MRB_OBJECT_HEADER;
|
MRB_OBJECT_HEADER;
|
||||||
mrb_int len;
|
|
||||||
union {
|
union {
|
||||||
mrb_int capa;
|
struct {
|
||||||
mrb_shared_array *shared;
|
mrb_int len;
|
||||||
} aux;
|
union {
|
||||||
mrb_value *ptr;
|
mrb_int capa;
|
||||||
|
mrb_shared_array *shared;
|
||||||
|
} aux;
|
||||||
|
mrb_value *ptr;
|
||||||
|
} heap;
|
||||||
|
mrb_value embed[MRB_ARY_EMBED_LEN_MAX];
|
||||||
|
} as;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define mrb_ary_ptr(v) ((struct RArray*)(mrb_ptr(v)))
|
#define mrb_ary_ptr(v) ((struct RArray*)(mrb_ptr(v)))
|
||||||
#define mrb_ary_value(p) mrb_obj_value((void*)(p))
|
#define mrb_ary_value(p) mrb_obj_value((void*)(p))
|
||||||
#define RARRAY(v) ((struct RArray*)(mrb_ptr(v)))
|
#define RARRAY(v) ((struct RArray*)(mrb_ptr(v)))
|
||||||
|
|
||||||
#define RARRAY_LEN(a) (RARRAY(a)->len)
|
#define MRB_ARY_EMBED_MASK 7
|
||||||
#define RARRAY_PTR(a) ((const mrb_value*)RARRAY(a)->ptr)
|
#define ARY_EMBED_P(a) ((a)->flags & MRB_ARY_EMBED_MASK)
|
||||||
|
#define ARY_UNSET_EMBED_FLAG(a) ((a)->flags &= ~(MRB_ARY_EMBED_MASK))
|
||||||
|
#define ARY_EMBED_LEN(a) ((mrb_int)(((a)->flags & MRB_ARY_EMBED_MASK) - 1))
|
||||||
|
#define ARY_SET_EMBED_LEN(a,len) ((a)->flags = ((a)->flags&~MRB_ARY_EMBED_MASK) | ((uint32_t)(len) + 1))
|
||||||
|
#define ARY_EMBED_PTR(a) (&((a)->as.embed[0]))
|
||||||
|
|
||||||
|
#define ARY_LEN(a) (ARY_EMBED_P(a)?ARY_EMBED_LEN(a):(a)->as.heap.len)
|
||||||
|
#define ARY_PTR(a) (ARY_EMBED_P(a)?ARY_EMBED_PTR(a):(a)->as.heap.ptr)
|
||||||
|
#define RARRAY_LEN(a) ARY_LEN(RARRAY(a))
|
||||||
|
#define RARRAY_PTR(a) ARY_PTR(RARRAY(a))
|
||||||
|
#define ARY_SET_LEN(a,n) do {\
|
||||||
|
if (ARY_EMBED_P(a)) {\
|
||||||
|
mrb_assert((n) <= MRB_ARY_EMBED_LEN_MAX); \
|
||||||
|
ARY_SET_EMBED_LEN(a,n);\
|
||||||
|
}\
|
||||||
|
else\
|
||||||
|
(a)->as.heap.len = (n);\
|
||||||
|
} while (0)
|
||||||
|
#define ARY_CAPA(a) (ARY_EMBED_P(a)?MRB_ARY_EMBED_LEN_MAX:(a)->as.heap.aux.capa)
|
||||||
#define MRB_ARY_SHARED 256
|
#define MRB_ARY_SHARED 256
|
||||||
#define ARY_SHARED_P(a) ((a)->flags & MRB_ARY_SHARED)
|
#define ARY_SHARED_P(a) ((a)->flags & MRB_ARY_SHARED)
|
||||||
#define ARY_SET_SHARED_FLAG(a) ((a)->flags |= MRB_ARY_SHARED)
|
#define ARY_SET_SHARED_FLAG(a) ((a)->flags |= MRB_ARY_SHARED)
|
||||||
@@ -175,10 +199,11 @@ MRB_API void mrb_ary_set(mrb_state *mrb, mrb_value ary, mrb_int n, mrb_value val
|
|||||||
* @param other The array to replace it with.
|
* @param other The array to replace it with.
|
||||||
*/
|
*/
|
||||||
MRB_API void mrb_ary_replace(mrb_state *mrb, mrb_value self, mrb_value other);
|
MRB_API void mrb_ary_replace(mrb_state *mrb, mrb_value self, mrb_value other);
|
||||||
|
MRB_API mrb_value mrb_ensure_array_type(mrb_state *mrb, mrb_value self);
|
||||||
MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self);
|
MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unshift an element into an array
|
* Unshift an element into the array
|
||||||
*
|
*
|
||||||
* Equivalent to:
|
* Equivalent to:
|
||||||
*
|
*
|
||||||
@@ -189,6 +214,17 @@ MRB_API mrb_value mrb_check_array_type(mrb_state *mrb, mrb_value self);
|
|||||||
* @param item The item to unshift.
|
* @param item The item to unshift.
|
||||||
*/
|
*/
|
||||||
MRB_API mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item);
|
MRB_API mrb_value mrb_ary_unshift(mrb_state *mrb, mrb_value self, mrb_value item);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get nth element in the array
|
||||||
|
*
|
||||||
|
* Equivalent to:
|
||||||
|
*
|
||||||
|
* ary[offset]
|
||||||
|
*
|
||||||
|
* @param ary The target array.
|
||||||
|
* @param offset The element position (negative counts from the tail).
|
||||||
|
*/
|
||||||
MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset);
|
MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -205,7 +241,7 @@ MRB_API mrb_value mrb_ary_entry(mrb_value ary, mrb_int offset);
|
|||||||
MRB_API mrb_value mrb_ary_shift(mrb_state *mrb, mrb_value self);
|
MRB_API mrb_value mrb_ary_shift(mrb_state *mrb, mrb_value self);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Removes all elements from this array
|
* Removes all elements from the array
|
||||||
*
|
*
|
||||||
* Equivalent to:
|
* Equivalent to:
|
||||||
*
|
*
|
||||||
@@ -239,23 +275,6 @@ MRB_API mrb_value mrb_ary_join(mrb_state *mrb, mrb_value ary, mrb_value sep);
|
|||||||
*/
|
*/
|
||||||
MRB_API mrb_value mrb_ary_resize(mrb_state *mrb, mrb_value ary, mrb_int new_len);
|
MRB_API mrb_value mrb_ary_resize(mrb_state *mrb, mrb_value ary, mrb_int new_len);
|
||||||
|
|
||||||
static inline mrb_int
|
|
||||||
mrb_ary_len(mrb_state *mrb, mrb_value ary)
|
|
||||||
{
|
|
||||||
(void)mrb;
|
|
||||||
mrb_assert(mrb_array_p(ary));
|
|
||||||
return RARRAY_LEN(ary);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline mrb_value
|
|
||||||
ary_elt(mrb_value ary, mrb_int offset)
|
|
||||||
{
|
|
||||||
if (offset < 0 || RARRAY_LEN(ary) <= offset) {
|
|
||||||
return mrb_nil_value();
|
|
||||||
}
|
|
||||||
return RARRAY_PTR(ary)[offset];
|
|
||||||
}
|
|
||||||
|
|
||||||
MRB_END_DECL
|
MRB_END_DECL
|
||||||
|
|
||||||
#endif /* MRUBY_ARRAY_H */
|
#endif /* MRUBY_ARRAY_H */
|
||||||
|
|||||||
@@ -11,6 +11,10 @@
|
|||||||
# error ---->> MRB_NAN_BOXING and MRB_USE_FLOAT conflict <<----
|
# error ---->> MRB_NAN_BOXING and MRB_USE_FLOAT conflict <<----
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MRB_WITHOUT_FLOAT
|
||||||
|
# error ---->> MRB_NAN_BOXING and MRB_WITHOUT_FLOAT conflict <<----
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MRB_INT64
|
#ifdef MRB_INT64
|
||||||
# error ---->> MRB_NAN_BOXING and MRB_INT64 conflict <<----
|
# error ---->> MRB_NAN_BOXING and MRB_INT64 conflict <<----
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -12,7 +12,9 @@
|
|||||||
|
|
||||||
typedef struct mrb_value {
|
typedef struct mrb_value {
|
||||||
union {
|
union {
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
mrb_float f;
|
mrb_float f;
|
||||||
|
#endif
|
||||||
void *p;
|
void *p;
|
||||||
mrb_int i;
|
mrb_int i;
|
||||||
mrb_sym sym;
|
mrb_sym sym;
|
||||||
@@ -20,11 +22,15 @@ typedef struct mrb_value {
|
|||||||
enum mrb_vtype tt;
|
enum mrb_vtype tt;
|
||||||
} mrb_value;
|
} mrb_value;
|
||||||
|
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
#define mrb_float_pool(mrb,f) mrb_float_value(mrb,f)
|
#define mrb_float_pool(mrb,f) mrb_float_value(mrb,f)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define mrb_ptr(o) (o).value.p
|
#define mrb_ptr(o) (o).value.p
|
||||||
#define mrb_cptr(o) mrb_ptr(o)
|
#define mrb_cptr(o) mrb_ptr(o)
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
#define mrb_float(o) (o).value.f
|
#define mrb_float(o) (o).value.f
|
||||||
|
#endif
|
||||||
#define mrb_fixnum(o) (o).value.i
|
#define mrb_fixnum(o) (o).value.i
|
||||||
#define mrb_symbol(o) (o).value.sym
|
#define mrb_symbol(o) (o).value.sym
|
||||||
#define mrb_type(o) (o).tt
|
#define mrb_type(o) (o).tt
|
||||||
@@ -39,7 +45,9 @@ typedef struct mrb_value {
|
|||||||
#define SET_TRUE_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_TRUE, value.i, 1)
|
#define SET_TRUE_VALUE(r) BOXNIX_SET_VALUE(r, MRB_TT_TRUE, value.i, 1)
|
||||||
#define SET_BOOL_VALUE(r,b) BOXNIX_SET_VALUE(r, b ? MRB_TT_TRUE : MRB_TT_FALSE, value.i, 1)
|
#define SET_BOOL_VALUE(r,b) BOXNIX_SET_VALUE(r, b ? MRB_TT_TRUE : MRB_TT_FALSE, value.i, 1)
|
||||||
#define SET_INT_VALUE(r,n) BOXNIX_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n))
|
#define SET_INT_VALUE(r,n) BOXNIX_SET_VALUE(r, MRB_TT_FIXNUM, value.i, (n))
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
#define SET_FLOAT_VALUE(mrb,r,v) BOXNIX_SET_VALUE(r, MRB_TT_FLOAT, value.f, (v))
|
#define SET_FLOAT_VALUE(mrb,r,v) BOXNIX_SET_VALUE(r, MRB_TT_FLOAT, value.f, (v))
|
||||||
|
#endif
|
||||||
#define SET_SYM_VALUE(r,v) BOXNIX_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v))
|
#define SET_SYM_VALUE(r,v) BOXNIX_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v))
|
||||||
#define SET_OBJ_VALUE(r,v) BOXNIX_SET_VALUE(r, (((struct RObject*)(v))->tt), value.p, (v))
|
#define SET_OBJ_VALUE(r,v) BOXNIX_SET_VALUE(r, (((struct RObject*)(v))->tt), value.p, (v))
|
||||||
#define SET_CPTR_VALUE(mrb,r,v) BOXNIX_SET_VALUE(r, MRB_TT_CPTR, value.p, v)
|
#define SET_CPTR_VALUE(mrb,r,v) BOXNIX_SET_VALUE(r, MRB_TT_CPTR, value.p, v)
|
||||||
|
|||||||
@@ -15,10 +15,12 @@
|
|||||||
#error MRB_INT64 cannot be used with MRB_WORD_BOXING in 32-bit mode.
|
#error MRB_INT64 cannot be used with MRB_WORD_BOXING in 32-bit mode.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
struct RFloat {
|
struct RFloat {
|
||||||
MRB_OBJECT_HEADER;
|
MRB_OBJECT_HEADER;
|
||||||
mrb_float f;
|
mrb_float f;
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
struct RCptr {
|
struct RCptr {
|
||||||
MRB_OBJECT_HEADER;
|
MRB_OBJECT_HEADER;
|
||||||
@@ -26,7 +28,11 @@ struct RCptr {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define MRB_FIXNUM_SHIFT 1
|
#define MRB_FIXNUM_SHIFT 1
|
||||||
|
#ifdef MRB_WITHOUT_FLOAT
|
||||||
|
#define MRB_TT_HAS_BASIC MRB_TT_CPTR
|
||||||
|
#else
|
||||||
#define MRB_TT_HAS_BASIC MRB_TT_FLOAT
|
#define MRB_TT_HAS_BASIC MRB_TT_FLOAT
|
||||||
|
#endif
|
||||||
|
|
||||||
enum mrb_special_consts {
|
enum mrb_special_consts {
|
||||||
MRB_Qnil = 0,
|
MRB_Qnil = 0,
|
||||||
@@ -39,6 +45,14 @@ enum mrb_special_consts {
|
|||||||
#define MRB_SYMBOL_FLAG 0x0e
|
#define MRB_SYMBOL_FLAG 0x0e
|
||||||
#define MRB_SPECIAL_SHIFT 8
|
#define MRB_SPECIAL_SHIFT 8
|
||||||
|
|
||||||
|
#if defined(MRB_64BIT)
|
||||||
|
#define MRB_SYMBOL_BITSIZE (sizeof(mrb_sym) * CHAR_BIT)
|
||||||
|
#define MRB_SYMBOL_MAX UINT32_MAX
|
||||||
|
#else
|
||||||
|
#define MRB_SYMBOL_BITSIZE (sizeof(mrb_sym) * CHAR_BIT - MRB_SPECIAL_SHIFT)
|
||||||
|
#define MRB_SYMBOL_MAX (UINT32_MAX >> MRB_SPECIAL_SHIFT)
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef union mrb_value {
|
typedef union mrb_value {
|
||||||
union {
|
union {
|
||||||
void *p;
|
void *p;
|
||||||
@@ -48,24 +62,32 @@ typedef union mrb_value {
|
|||||||
};
|
};
|
||||||
struct {
|
struct {
|
||||||
unsigned int sym_flag : MRB_SPECIAL_SHIFT;
|
unsigned int sym_flag : MRB_SPECIAL_SHIFT;
|
||||||
mrb_sym sym : (sizeof(mrb_sym) * CHAR_BIT);
|
mrb_sym sym : MRB_SYMBOL_BITSIZE;
|
||||||
};
|
};
|
||||||
struct RBasic *bp;
|
struct RBasic *bp;
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
struct RFloat *fp;
|
struct RFloat *fp;
|
||||||
|
#endif
|
||||||
struct RCptr *vp;
|
struct RCptr *vp;
|
||||||
} value;
|
} value;
|
||||||
unsigned long w;
|
unsigned long w;
|
||||||
} mrb_value;
|
} mrb_value;
|
||||||
|
|
||||||
MRB_API mrb_value mrb_word_boxing_cptr_value(struct mrb_state*, void*);
|
MRB_API mrb_value mrb_word_boxing_cptr_value(struct mrb_state*, void*);
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
MRB_API mrb_value mrb_word_boxing_float_value(struct mrb_state*, mrb_float);
|
MRB_API mrb_value mrb_word_boxing_float_value(struct mrb_state*, mrb_float);
|
||||||
MRB_API mrb_value mrb_word_boxing_float_pool(struct mrb_state*, mrb_float);
|
MRB_API mrb_value mrb_word_boxing_float_pool(struct mrb_state*, mrb_float);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
#define mrb_float_pool(mrb,f) mrb_word_boxing_float_pool(mrb,f)
|
#define mrb_float_pool(mrb,f) mrb_word_boxing_float_pool(mrb,f)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define mrb_ptr(o) (o).value.p
|
#define mrb_ptr(o) (o).value.p
|
||||||
#define mrb_cptr(o) (o).value.vp->p
|
#define mrb_cptr(o) (o).value.vp->p
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
#define mrb_float(o) (o).value.fp->f
|
#define mrb_float(o) (o).value.fp->f
|
||||||
|
#endif
|
||||||
#define mrb_fixnum(o) ((mrb_int)(o).value.i)
|
#define mrb_fixnum(o) ((mrb_int)(o).value.i)
|
||||||
#define mrb_symbol(o) (o).value.sym
|
#define mrb_symbol(o) (o).value.sym
|
||||||
|
|
||||||
@@ -106,7 +128,9 @@ mrb_type(mrb_value o)
|
|||||||
}\
|
}\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
#define SET_FLOAT_VALUE(mrb,r,v) r = mrb_word_boxing_float_value(mrb, v)
|
#define SET_FLOAT_VALUE(mrb,r,v) r = mrb_word_boxing_float_value(mrb, v)
|
||||||
|
#endif
|
||||||
#define SET_CPTR_VALUE(mrb,r,v) r = mrb_word_boxing_cptr_value(mrb, v)
|
#define SET_CPTR_VALUE(mrb,r,v) r = mrb_word_boxing_cptr_value(mrb, v)
|
||||||
#define SET_NIL_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_FALSE, value.i, 0)
|
#define SET_NIL_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_FALSE, value.i, 0)
|
||||||
#define SET_FALSE_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_FALSE, value.i, 1)
|
#define SET_FALSE_VALUE(r) BOXWORD_SET_VALUE(r, MRB_TT_FALSE, value.i, 1)
|
||||||
|
|||||||
+21
-14
@@ -22,9 +22,6 @@ struct RClass {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define mrb_class_ptr(v) ((struct RClass*)(mrb_ptr(v)))
|
#define mrb_class_ptr(v) ((struct RClass*)(mrb_ptr(v)))
|
||||||
#define RCLASS_SUPER(v) (((struct RClass*)(mrb_ptr(v)))->super)
|
|
||||||
#define RCLASS_IV_TBL(v) (((struct RClass*)(mrb_ptr(v)))->iv)
|
|
||||||
#define RCLASS_M_TBL(v) (((struct RClass*)(mrb_ptr(v)))->mt)
|
|
||||||
|
|
||||||
static inline struct RClass*
|
static inline struct RClass*
|
||||||
mrb_class(mrb_state *mrb, mrb_value v)
|
mrb_class(mrb_state *mrb, mrb_value v)
|
||||||
@@ -40,8 +37,10 @@ mrb_class(mrb_state *mrb, mrb_value v)
|
|||||||
return mrb->symbol_class;
|
return mrb->symbol_class;
|
||||||
case MRB_TT_FIXNUM:
|
case MRB_TT_FIXNUM:
|
||||||
return mrb->fixnum_class;
|
return mrb->fixnum_class;
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
case MRB_TT_FLOAT:
|
case MRB_TT_FLOAT:
|
||||||
return mrb->float_class;
|
return mrb->float_class;
|
||||||
|
#endif
|
||||||
case MRB_TT_CPTR:
|
case MRB_TT_CPTR:
|
||||||
return mrb->object_class;
|
return mrb->object_class;
|
||||||
case MRB_TT_ENV:
|
case MRB_TT_ENV:
|
||||||
@@ -51,18 +50,25 @@ mrb_class(mrb_state *mrb, mrb_value v)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: figure out where to put user flags */
|
/* flags:
|
||||||
#define MRB_FLAG_IS_FROZEN (1 << 18)
|
20: frozen
|
||||||
#define MRB_FLAG_IS_PREPENDED (1 << 19)
|
19: is_prepended
|
||||||
#define MRB_FLAG_IS_ORIGIN (1 << 20)
|
18: is_origin
|
||||||
|
17: is_inherited (used by method cache)
|
||||||
|
16: unused
|
||||||
|
0-15: instance type
|
||||||
|
*/
|
||||||
|
#define MRB_FL_CLASS_IS_PREPENDED (1 << 19)
|
||||||
|
#define MRB_FL_CLASS_IS_ORIGIN (1 << 18)
|
||||||
#define MRB_CLASS_ORIGIN(c) do {\
|
#define MRB_CLASS_ORIGIN(c) do {\
|
||||||
if (c->flags & MRB_FLAG_IS_PREPENDED) {\
|
if (c->flags & MRB_FL_CLASS_IS_PREPENDED) {\
|
||||||
c = c->super;\
|
c = c->super;\
|
||||||
while (!(c->flags & MRB_FLAG_IS_ORIGIN)) {\
|
while (!(c->flags & MRB_FL_CLASS_IS_ORIGIN)) {\
|
||||||
c = c->super;\
|
c = c->super;\
|
||||||
}\
|
}\
|
||||||
}\
|
}\
|
||||||
} while (0)
|
} while (0)
|
||||||
|
#define MRB_FL_CLASS_IS_INHERITED (1 << 17)
|
||||||
#define MRB_INSTANCE_TT_MASK (0xFF)
|
#define MRB_INSTANCE_TT_MASK (0xFF)
|
||||||
#define MRB_SET_INSTANCE_TT(c, tt) c->flags = ((c->flags & ~MRB_INSTANCE_TT_MASK) | (char)tt)
|
#define MRB_SET_INSTANCE_TT(c, tt) c->flags = ((c->flags & ~MRB_INSTANCE_TT_MASK) | (char)tt)
|
||||||
#define MRB_INSTANCE_TT(c) (enum mrb_vtype)(c->flags & MRB_INSTANCE_TT_MASK)
|
#define MRB_INSTANCE_TT(c) (enum mrb_vtype)(c->flags & MRB_INSTANCE_TT_MASK)
|
||||||
@@ -71,16 +77,17 @@ MRB_API struct RClass* mrb_define_class_id(mrb_state*, mrb_sym, struct RClass*);
|
|||||||
MRB_API struct RClass* mrb_define_module_id(mrb_state*, mrb_sym);
|
MRB_API struct RClass* mrb_define_module_id(mrb_state*, mrb_sym);
|
||||||
MRB_API struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb_sym);
|
MRB_API struct RClass *mrb_vm_define_class(mrb_state*, mrb_value, mrb_value, mrb_sym);
|
||||||
MRB_API struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym);
|
MRB_API struct RClass *mrb_vm_define_module(mrb_state*, mrb_value, mrb_sym);
|
||||||
MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, struct RProc *);
|
MRB_API void mrb_define_method_raw(mrb_state*, struct RClass*, mrb_sym, mrb_method_t);
|
||||||
MRB_API void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec);
|
MRB_API void mrb_define_method_id(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_func_t func, mrb_aspec aspec);
|
||||||
MRB_API void mrb_alias_method(mrb_state *mrb, struct RClass *c, mrb_sym a, mrb_sym b);
|
MRB_API void mrb_alias_method(mrb_state*, struct RClass *c, mrb_sym a, mrb_sym b);
|
||||||
|
|
||||||
MRB_API struct RClass *mrb_class_outer_module(mrb_state*, struct RClass *);
|
MRB_API mrb_method_t mrb_method_search_vm(mrb_state*, struct RClass**, mrb_sym);
|
||||||
MRB_API struct RProc *mrb_method_search_vm(mrb_state*, struct RClass**, mrb_sym);
|
MRB_API mrb_method_t mrb_method_search(mrb_state*, struct RClass*, mrb_sym);
|
||||||
MRB_API struct RProc *mrb_method_search(mrb_state*, struct RClass*, mrb_sym);
|
|
||||||
|
|
||||||
MRB_API struct RClass* mrb_class_real(struct RClass* cl);
|
MRB_API struct RClass* mrb_class_real(struct RClass* cl);
|
||||||
|
|
||||||
|
void mrb_class_name_class(mrb_state*, struct RClass*, struct RClass*, mrb_sym);
|
||||||
|
mrb_value mrb_class_find_path(mrb_state*, struct RClass*);
|
||||||
void mrb_gc_mark_mt(mrb_state*, struct RClass*);
|
void mrb_gc_mark_mt(mrb_state*, struct RClass*);
|
||||||
size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*);
|
size_t mrb_gc_mark_mt_size(mrb_state*, struct RClass*);
|
||||||
void mrb_gc_free_mt(mrb_state*, struct RClass*);
|
void mrb_gc_free_mt(mrb_state*, struct RClass*);
|
||||||
|
|||||||
@@ -7,6 +7,11 @@
|
|||||||
#ifndef MRUBY_COMMON_H
|
#ifndef MRUBY_COMMON_H
|
||||||
#define MRUBY_COMMON_H
|
#define MRUBY_COMMON_H
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#ifndef __TARGETCONDITIONALS__
|
||||||
|
#include "TargetConditionals.h"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#ifdef MRB_ENABLE_CXX_ABI
|
#ifdef MRB_ENABLE_CXX_ABI
|
||||||
@@ -14,7 +19,7 @@
|
|||||||
#define MRB_END_DECL
|
#define MRB_END_DECL
|
||||||
#else
|
#else
|
||||||
# define MRB_BEGIN_DECL extern "C" {
|
# define MRB_BEGIN_DECL extern "C" {
|
||||||
# define MRB_END_DECL }
|
# define MRB_END_DECL }
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
/** Start declarations in C mode */
|
/** Start declarations in C mode */
|
||||||
|
|||||||
+10
-8
@@ -33,6 +33,9 @@ typedef struct mrbc_context {
|
|||||||
mrb_bool no_exec:1;
|
mrb_bool no_exec:1;
|
||||||
mrb_bool keep_lv:1;
|
mrb_bool keep_lv:1;
|
||||||
mrb_bool no_optimize:1;
|
mrb_bool no_optimize:1;
|
||||||
|
mrb_bool on_eval:1;
|
||||||
|
|
||||||
|
size_t parser_nerr;
|
||||||
} mrbc_context;
|
} mrbc_context;
|
||||||
|
|
||||||
MRB_API mrbc_context* mrbc_context_new(mrb_state *mrb);
|
MRB_API mrbc_context* mrbc_context_new(mrb_state *mrb);
|
||||||
@@ -136,11 +139,10 @@ struct mrb_parser_state {
|
|||||||
int tidx;
|
int tidx;
|
||||||
int tsiz;
|
int tsiz;
|
||||||
|
|
||||||
mrb_ast_node *all_heredocs; /* list of mrb_parser_heredoc_info* */
|
mrb_ast_node *all_heredocs; /* list of mrb_parser_heredoc_info* */
|
||||||
mrb_ast_node *heredocs_from_nextline;
|
mrb_ast_node *heredocs_from_nextline;
|
||||||
mrb_ast_node *parsing_heredoc;
|
mrb_ast_node *parsing_heredoc;
|
||||||
mrb_ast_node *lex_strterm_before_heredoc;
|
mrb_ast_node *lex_strterm_before_heredoc;
|
||||||
mrb_bool heredoc_end_now:1; /* for mirb */
|
|
||||||
|
|
||||||
void *ylval;
|
void *ylval;
|
||||||
|
|
||||||
@@ -149,13 +151,14 @@ struct mrb_parser_state {
|
|||||||
mrb_ast_node *tree;
|
mrb_ast_node *tree;
|
||||||
|
|
||||||
mrb_bool no_optimize:1;
|
mrb_bool no_optimize:1;
|
||||||
|
mrb_bool on_eval:1;
|
||||||
mrb_bool capture_errors:1;
|
mrb_bool capture_errors:1;
|
||||||
struct mrb_parser_message error_buffer[10];
|
struct mrb_parser_message error_buffer[10];
|
||||||
struct mrb_parser_message warn_buffer[10];
|
struct mrb_parser_message warn_buffer[10];
|
||||||
|
|
||||||
mrb_sym* filename_table;
|
mrb_sym* filename_table;
|
||||||
size_t filename_table_length;
|
uint16_t filename_table_length;
|
||||||
int current_filename_index;
|
uint16_t current_filename_index;
|
||||||
|
|
||||||
struct mrb_jmpbuf* jmp;
|
struct mrb_jmpbuf* jmp;
|
||||||
};
|
};
|
||||||
@@ -163,7 +166,6 @@ struct mrb_parser_state {
|
|||||||
MRB_API struct mrb_parser_state* mrb_parser_new(mrb_state*);
|
MRB_API struct mrb_parser_state* mrb_parser_new(mrb_state*);
|
||||||
MRB_API void mrb_parser_free(struct mrb_parser_state*);
|
MRB_API void mrb_parser_free(struct mrb_parser_state*);
|
||||||
MRB_API void mrb_parser_parse(struct mrb_parser_state*,mrbc_context*);
|
MRB_API void mrb_parser_parse(struct mrb_parser_state*,mrbc_context*);
|
||||||
MRB_API double mrb_float_read(const char*, char**);
|
|
||||||
|
|
||||||
MRB_API void mrb_parser_set_filename(struct mrb_parser_state*, char const*);
|
MRB_API void mrb_parser_set_filename(struct mrb_parser_state*, char const*);
|
||||||
MRB_API char const* mrb_parser_get_filename(struct mrb_parser_state*, uint16_t idx);
|
MRB_API char const* mrb_parser_get_filename(struct mrb_parser_state*, uint16_t idx);
|
||||||
@@ -173,7 +175,7 @@ MRB_API char const* mrb_parser_get_filename(struct mrb_parser_state*, uint16_t i
|
|||||||
MRB_API struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*);
|
MRB_API struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*);
|
||||||
#endif
|
#endif
|
||||||
MRB_API struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*,mrbc_context*);
|
MRB_API struct mrb_parser_state* mrb_parse_string(mrb_state*,const char*,mrbc_context*);
|
||||||
MRB_API struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,int,mrbc_context*);
|
MRB_API struct mrb_parser_state* mrb_parse_nstring(mrb_state*,const char*,size_t,mrbc_context*);
|
||||||
MRB_API struct RProc* mrb_generate_code(mrb_state*, struct mrb_parser_state*);
|
MRB_API struct RProc* mrb_generate_code(mrb_state*, struct mrb_parser_state*);
|
||||||
MRB_API mrb_value mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c);
|
MRB_API mrb_value mrb_load_exec(mrb_state *mrb, struct mrb_parser_state *p, mrbc_context *c);
|
||||||
|
|
||||||
@@ -183,9 +185,9 @@ MRB_API mrb_value mrb_load_file(mrb_state*,FILE*);
|
|||||||
MRB_API mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrbc_context *cxt);
|
MRB_API mrb_value mrb_load_file_cxt(mrb_state*,FILE*, mrbc_context *cxt);
|
||||||
#endif
|
#endif
|
||||||
MRB_API mrb_value mrb_load_string(mrb_state *mrb, const char *s);
|
MRB_API mrb_value mrb_load_string(mrb_state *mrb, const char *s);
|
||||||
MRB_API mrb_value mrb_load_nstring(mrb_state *mrb, const char *s, int len);
|
MRB_API mrb_value mrb_load_nstring(mrb_state *mrb, const char *s, size_t len);
|
||||||
MRB_API mrb_value mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *cxt);
|
MRB_API mrb_value mrb_load_string_cxt(mrb_state *mrb, const char *s, mrbc_context *cxt);
|
||||||
MRB_API mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *s, int len, mrbc_context *cxt);
|
MRB_API mrb_value mrb_load_nstring_cxt(mrb_state *mrb, const char *s, size_t len, mrbc_context *cxt);
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
MRB_END_DECL
|
MRB_END_DECL
|
||||||
|
|||||||
@@ -47,18 +47,19 @@ typedef struct mrb_irep_debug_info {
|
|||||||
* get line from irep's debug info and program counter
|
* get line from irep's debug info and program counter
|
||||||
* @return returns NULL if not found
|
* @return returns NULL if not found
|
||||||
*/
|
*/
|
||||||
MRB_API const char *mrb_debug_get_filename(mrb_irep *irep, uint32_t pc);
|
MRB_API const char *mrb_debug_get_filename(mrb_irep *irep, ptrdiff_t pc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get line from irep's debug info and program counter
|
* get line from irep's debug info and program counter
|
||||||
* @return returns -1 if not found
|
* @return returns -1 if not found
|
||||||
*/
|
*/
|
||||||
MRB_API int32_t mrb_debug_get_line(mrb_irep *irep, uint32_t pc);
|
MRB_API int32_t mrb_debug_get_line(mrb_irep *irep, ptrdiff_t pc);
|
||||||
|
|
||||||
MRB_API mrb_irep_debug_info_file *mrb_debug_info_append_file(
|
|
||||||
mrb_state *mrb, mrb_irep *irep,
|
|
||||||
uint32_t start_pos, uint32_t end_pos);
|
|
||||||
MRB_API mrb_irep_debug_info *mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep);
|
MRB_API mrb_irep_debug_info *mrb_debug_info_alloc(mrb_state *mrb, mrb_irep *irep);
|
||||||
|
MRB_API mrb_irep_debug_info_file *mrb_debug_info_append_file(
|
||||||
|
mrb_state *mrb, mrb_irep_debug_info *info,
|
||||||
|
const char *filename, uint16_t *lines,
|
||||||
|
uint32_t start_pos, uint32_t end_pos);
|
||||||
MRB_API void mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d);
|
MRB_API void mrb_debug_info_free(mrb_state *mrb, mrb_irep_debug_info *d);
|
||||||
|
|
||||||
MRB_END_DECL
|
MRB_END_DECL
|
||||||
|
|||||||
@@ -52,11 +52,11 @@ MRB_API mrb_irep *mrb_read_irep(mrb_state*, const uint8_t*);
|
|||||||
/* Rite Binary File header */
|
/* Rite Binary File header */
|
||||||
#define RITE_BINARY_IDENT "RITE"
|
#define RITE_BINARY_IDENT "RITE"
|
||||||
#define RITE_BINARY_IDENT_LIL "ETIR"
|
#define RITE_BINARY_IDENT_LIL "ETIR"
|
||||||
#define RITE_BINARY_FORMAT_VER "0004"
|
#define RITE_BINARY_FORMAT_VER "0005"
|
||||||
#define RITE_COMPILER_NAME "MATZ"
|
#define RITE_COMPILER_NAME "MATZ"
|
||||||
#define RITE_COMPILER_VERSION "0000"
|
#define RITE_COMPILER_VERSION "0000"
|
||||||
|
|
||||||
#define RITE_VM_VER "0000"
|
#define RITE_VM_VER "0002"
|
||||||
|
|
||||||
#define RITE_BINARY_EOF "END\0"
|
#define RITE_BINARY_EOF "END\0"
|
||||||
#define RITE_SECTION_IREP_IDENT "IREP"
|
#define RITE_SECTION_IREP_IDENT "IREP"
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ struct RException {
|
|||||||
MRB_API void mrb_sys_fail(mrb_state *mrb, const char *mesg);
|
MRB_API void mrb_sys_fail(mrb_state *mrb, const char *mesg);
|
||||||
MRB_API mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str);
|
MRB_API mrb_value mrb_exc_new_str(mrb_state *mrb, struct RClass* c, mrb_value str);
|
||||||
#define mrb_exc_new_str_lit(mrb, c, lit) mrb_exc_new_str(mrb, c, mrb_str_new_lit(mrb, lit))
|
#define mrb_exc_new_str_lit(mrb, c, lit) mrb_exc_new_str(mrb, c, mrb_str_new_lit(mrb, lit))
|
||||||
MRB_API mrb_value mrb_make_exception(mrb_state *mrb, int argc, const mrb_value *argv);
|
MRB_API mrb_value mrb_make_exception(mrb_state *mrb, mrb_int argc, const mrb_value *argv);
|
||||||
MRB_API mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc);
|
MRB_API mrb_value mrb_exc_backtrace(mrb_state *mrb, mrb_value exc);
|
||||||
MRB_API mrb_value mrb_get_backtrace(mrb_state *mrb);
|
MRB_API mrb_value mrb_get_backtrace(mrb_state *mrb);
|
||||||
MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, const char *fmt, ...);
|
MRB_API mrb_noreturn void mrb_no_method_error(mrb_state *mrb, mrb_sym id, mrb_value args, const char *fmt, ...);
|
||||||
@@ -34,7 +34,6 @@ MRB_API mrb_value mrb_f_raise(mrb_state*, mrb_value);
|
|||||||
|
|
||||||
struct RBreak {
|
struct RBreak {
|
||||||
MRB_OBJECT_HEADER;
|
MRB_OBJECT_HEADER;
|
||||||
struct iv_tbl *iv;
|
|
||||||
struct RProc *proc;
|
struct RProc *proc;
|
||||||
mrb_value val;
|
mrb_value val;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,6 +33,13 @@ typedef enum {
|
|||||||
MRB_GC_STATE_SWEEP
|
MRB_GC_STATE_SWEEP
|
||||||
} mrb_gc_state;
|
} mrb_gc_state;
|
||||||
|
|
||||||
|
/* Disable MSVC warning "C4200: nonstandard extension used: zero-sized array
|
||||||
|
* in struct/union" when in C++ mode */
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4200)
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct mrb_heap_page {
|
typedef struct mrb_heap_page {
|
||||||
struct RBasic *freelist;
|
struct RBasic *freelist;
|
||||||
struct mrb_heap_page *prev;
|
struct mrb_heap_page *prev;
|
||||||
@@ -43,6 +50,10 @@ typedef struct mrb_heap_page {
|
|||||||
void *objects[];
|
void *objects[];
|
||||||
} mrb_heap_page;
|
} mrb_heap_page;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct mrb_gc {
|
typedef struct mrb_gc {
|
||||||
mrb_heap_page *heaps; /* heaps for GC */
|
mrb_heap_page *heaps; /* heaps for GC */
|
||||||
mrb_heap_page *sweeps;
|
mrb_heap_page *sweeps;
|
||||||
|
|||||||
+38
-5
@@ -18,13 +18,15 @@ MRB_BEGIN_DECL
|
|||||||
struct RHash {
|
struct RHash {
|
||||||
MRB_OBJECT_HEADER;
|
MRB_OBJECT_HEADER;
|
||||||
struct iv_tbl *iv;
|
struct iv_tbl *iv;
|
||||||
struct kh_ht *ht;
|
struct htable *ht;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define mrb_hash_ptr(v) ((struct RHash*)(mrb_ptr(v)))
|
#define mrb_hash_ptr(v) ((struct RHash*)(mrb_ptr(v)))
|
||||||
#define mrb_hash_value(p) mrb_obj_value((void*)(p))
|
#define mrb_hash_value(p) mrb_obj_value((void*)(p))
|
||||||
|
|
||||||
MRB_API mrb_value mrb_hash_new_capa(mrb_state*, mrb_int);
|
MRB_API mrb_value mrb_hash_new_capa(mrb_state*, mrb_int);
|
||||||
|
MRB_API mrb_value mrb_ensure_hash_type(mrb_state *mrb, mrb_value hash);
|
||||||
|
MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initializes a new hash.
|
* Initializes a new hash.
|
||||||
@@ -74,7 +76,7 @@ MRB_API mrb_value mrb_hash_get(mrb_state *mrb, mrb_value hash, mrb_value key);
|
|||||||
*
|
*
|
||||||
* Equivalent to:
|
* Equivalent to:
|
||||||
*
|
*
|
||||||
* hash.hash_key?(key) ? hash[key] : def
|
* hash.key?(key) ? hash[key] : def
|
||||||
*
|
*
|
||||||
* @param mrb The mruby state reference.
|
* @param mrb The mruby state reference.
|
||||||
* @param hash The target hash.
|
* @param hash The target hash.
|
||||||
@@ -110,7 +112,19 @@ MRB_API mrb_value mrb_hash_delete_key(mrb_state *mrb, mrb_value hash, mrb_value
|
|||||||
* @return An array with the keys of the hash.
|
* @return An array with the keys of the hash.
|
||||||
*/
|
*/
|
||||||
MRB_API mrb_value mrb_hash_keys(mrb_state *mrb, mrb_value hash);
|
MRB_API mrb_value mrb_hash_keys(mrb_state *mrb, mrb_value hash);
|
||||||
MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash);
|
/*
|
||||||
|
* Check if the hash has the key.
|
||||||
|
*
|
||||||
|
* Equivalent to:
|
||||||
|
*
|
||||||
|
* hash.key?(key)
|
||||||
|
*
|
||||||
|
* @param mrb The mruby state reference.
|
||||||
|
* @param hash The target hash.
|
||||||
|
* @param key The key to check existence.
|
||||||
|
* @return True if the hash has the key
|
||||||
|
*/
|
||||||
|
MRB_API mrb_bool mrb_hash_key_p(mrb_state *mrb, mrb_value hash, mrb_value key);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the hash is empty
|
* Check if the hash is empty
|
||||||
@@ -123,7 +137,7 @@ MRB_API mrb_value mrb_check_hash_type(mrb_state *mrb, mrb_value hash);
|
|||||||
* @param self The target hash.
|
* @param self The target hash.
|
||||||
* @return True if the hash is empty, false otherwise.
|
* @return True if the hash is empty, false otherwise.
|
||||||
*/
|
*/
|
||||||
MRB_API mrb_value mrb_hash_empty_p(mrb_state *mrb, mrb_value self);
|
MRB_API mrb_bool mrb_hash_empty_p(mrb_state *mrb, mrb_value self);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Gets an array of values.
|
* Gets an array of values.
|
||||||
@@ -151,6 +165,26 @@ MRB_API mrb_value mrb_hash_values(mrb_state *mrb, mrb_value hash);
|
|||||||
*/
|
*/
|
||||||
MRB_API mrb_value mrb_hash_clear(mrb_state *mrb, mrb_value hash);
|
MRB_API mrb_value mrb_hash_clear(mrb_state *mrb, mrb_value hash);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copies the hash.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param mrb The mruby state reference.
|
||||||
|
* @param hash The target hash.
|
||||||
|
* @return The copy of the hash
|
||||||
|
*/
|
||||||
|
MRB_API mrb_value mrb_hash_dup(mrb_state *mrb, mrb_value hash);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Merges two hashes. The first hash will be modified by the
|
||||||
|
* second hash.
|
||||||
|
*
|
||||||
|
* @param mrb The mruby state reference.
|
||||||
|
* @param hash1 The target hash.
|
||||||
|
* @param hash2 Updating hash
|
||||||
|
*/
|
||||||
|
MRB_API void mrb_hash_merge(mrb_state *mrb, mrb_value hash1, mrb_value hash2);
|
||||||
|
|
||||||
/* declaration of struct kh_ht */
|
/* declaration of struct kh_ht */
|
||||||
/* be careful when you touch the internal */
|
/* be careful when you touch the internal */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -165,7 +199,6 @@ KHASH_DECLARE(ht, mrb_value, mrb_hash_value, TRUE)
|
|||||||
#define RHASH_TBL(h) (RHASH(h)->ht)
|
#define RHASH_TBL(h) (RHASH(h)->ht)
|
||||||
#define RHASH_IFNONE(h) mrb_iv_get(mrb, (h), mrb_intern_lit(mrb, "ifnone"))
|
#define RHASH_IFNONE(h) mrb_iv_get(mrb, (h), mrb_intern_lit(mrb, "ifnone"))
|
||||||
#define RHASH_PROCDEFAULT(h) RHASH_IFNONE(h)
|
#define RHASH_PROCDEFAULT(h) RHASH_IFNONE(h)
|
||||||
MRB_API struct kh_ht * mrb_hash_tbl(mrb_state *mrb, mrb_value hash);
|
|
||||||
|
|
||||||
#define MRB_HASH_DEFAULT 1
|
#define MRB_HASH_DEFAULT 1
|
||||||
#define MRB_HASH_PROC_DEFAULT 2
|
#define MRB_HASH_PROC_DEFAULT 2
|
||||||
|
|||||||
+18
-4
@@ -39,22 +39,36 @@ typedef struct mrb_irep {
|
|||||||
|
|
||||||
struct mrb_locals *lv;
|
struct mrb_locals *lv;
|
||||||
/* debug info */
|
/* debug info */
|
||||||
mrb_bool own_filename;
|
|
||||||
const char *filename;
|
|
||||||
uint16_t *lines;
|
|
||||||
struct mrb_irep_debug_info* debug_info;
|
struct mrb_irep_debug_info* debug_info;
|
||||||
|
|
||||||
size_t ilen, plen, slen, rlen, refcnt;
|
uint16_t ilen, plen, slen, rlen;
|
||||||
|
uint32_t refcnt;
|
||||||
} mrb_irep;
|
} mrb_irep;
|
||||||
|
|
||||||
#define MRB_ISEQ_NO_FREE 1
|
#define MRB_ISEQ_NO_FREE 1
|
||||||
|
|
||||||
MRB_API mrb_irep *mrb_add_irep(mrb_state *mrb);
|
MRB_API mrb_irep *mrb_add_irep(mrb_state *mrb);
|
||||||
|
|
||||||
|
/* @param [const uint8_t*] irep code, expected as a literal */
|
||||||
MRB_API mrb_value mrb_load_irep(mrb_state*, const uint8_t*);
|
MRB_API mrb_value mrb_load_irep(mrb_state*, const uint8_t*);
|
||||||
|
|
||||||
|
/* @param [const uint8_t*] irep code, expected as a literal */
|
||||||
MRB_API mrb_value mrb_load_irep_cxt(mrb_state*, const uint8_t*, mrbc_context*);
|
MRB_API mrb_value mrb_load_irep_cxt(mrb_state*, const uint8_t*, mrbc_context*);
|
||||||
|
|
||||||
void mrb_irep_free(mrb_state*, struct mrb_irep*);
|
void mrb_irep_free(mrb_state*, struct mrb_irep*);
|
||||||
void mrb_irep_incref(mrb_state*, struct mrb_irep*);
|
void mrb_irep_incref(mrb_state*, struct mrb_irep*);
|
||||||
void mrb_irep_decref(mrb_state*, struct mrb_irep*);
|
void mrb_irep_decref(mrb_state*, struct mrb_irep*);
|
||||||
|
void mrb_irep_cutref(mrb_state*, struct mrb_irep*);
|
||||||
|
void mrb_irep_remove_lv(mrb_state *mrb, mrb_irep *irep);
|
||||||
|
|
||||||
|
struct mrb_insn_data {
|
||||||
|
uint8_t insn;
|
||||||
|
uint16_t a;
|
||||||
|
uint16_t b;
|
||||||
|
uint8_t c;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mrb_insn_data mrb_decode_insn(mrb_code *pc);
|
||||||
|
|
||||||
MRB_END_DECL
|
MRB_END_DECL
|
||||||
|
|
||||||
|
|||||||
+13
-9
@@ -16,21 +16,25 @@
|
|||||||
*/
|
*/
|
||||||
MRB_BEGIN_DECL
|
MRB_BEGIN_DECL
|
||||||
|
|
||||||
#define POSFIXABLE(f) ((f) <= MRB_INT_MAX)
|
#define TYPED_POSFIXABLE(f,t) ((f) <= (t)MRB_INT_MAX)
|
||||||
#define NEGFIXABLE(f) ((f) >= MRB_INT_MIN)
|
#define TYPED_NEGFIXABLE(f,t) ((f) >= (t)MRB_INT_MIN)
|
||||||
#define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f))
|
#define TYPED_FIXABLE(f,t) (TYPED_POSFIXABLE(f,t) && TYPED_NEGFIXABLE(f,t))
|
||||||
|
#define POSFIXABLE(f) TYPED_POSFIXABLE(f,mrb_int)
|
||||||
#ifdef MRB_INT64
|
#define NEGFIXABLE(f) TYPED_NEGFIXABLE(f,mrb_int)
|
||||||
#define FIXABLE_FLOAT(f) FIXABLE((mrb_int)(f))
|
#define FIXABLE(f) TYPED_FIXABLE(f,mrb_int)
|
||||||
#else
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
#define FIXABLE_FLOAT(f) FIXABLE(f)
|
#define FIXABLE_FLOAT(f) TYPED_FIXABLE(f,double)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
MRB_API mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val);
|
MRB_API mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val);
|
||||||
MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base);
|
#endif
|
||||||
|
MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base);
|
||||||
/* ArgumentError if format string doesn't match /%(\.[0-9]+)?[aAeEfFgG]/ */
|
/* ArgumentError if format string doesn't match /%(\.[0-9]+)?[aAeEfFgG]/ */
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt);
|
MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt);
|
||||||
MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x);
|
MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x);
|
||||||
|
#endif
|
||||||
|
|
||||||
mrb_value mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y);
|
mrb_value mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||||
mrb_value mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y);
|
mrb_value mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y);
|
||||||
|
|||||||
@@ -22,9 +22,10 @@ struct RBasic {
|
|||||||
};
|
};
|
||||||
#define mrb_basic_ptr(v) ((struct RBasic*)(mrb_ptr(v)))
|
#define mrb_basic_ptr(v) ((struct RBasic*)(mrb_ptr(v)))
|
||||||
|
|
||||||
#define MRB_FROZEN_P(o) ((o)->flags & MRB_FLAG_IS_FROZEN)
|
#define MRB_FL_OBJ_IS_FROZEN (1 << 20)
|
||||||
#define MRB_SET_FROZEN_FLAG(o) ((o)->flags |= MRB_FLAG_IS_FROZEN)
|
#define MRB_FROZEN_P(o) ((o)->flags & MRB_FL_OBJ_IS_FROZEN)
|
||||||
#define MRB_UNSET_FROZEN_FLAG(o) ((o)->flags &= ~MRB_FLAG_IS_FROZEN)
|
#define MRB_SET_FROZEN_FLAG(o) ((o)->flags |= MRB_FL_OBJ_IS_FROZEN)
|
||||||
|
#define MRB_UNSET_FROZEN_FLAG(o) ((o)->flags &= ~MRB_FL_OBJ_IS_FROZEN)
|
||||||
|
|
||||||
struct RObject {
|
struct RObject {
|
||||||
MRB_OBJECT_HEADER;
|
MRB_OBJECT_HEADER;
|
||||||
|
|||||||
+47
-139
@@ -7,145 +7,10 @@
|
|||||||
#ifndef MRUBY_OPCODE_H
|
#ifndef MRUBY_OPCODE_H
|
||||||
#define MRUBY_OPCODE_H
|
#define MRUBY_OPCODE_H
|
||||||
|
|
||||||
#define MAXARG_Bx (0xffff)
|
enum mrb_insn {
|
||||||
#define MAXARG_sBx (MAXARG_Bx>>1) /* 'sBx' is signed */
|
#define OPCODE(x,_) OP_ ## x,
|
||||||
|
#include "mruby/ops.h"
|
||||||
/* instructions: packed 32 bit */
|
#undef OPCODE
|
||||||
/* ------------------------------- */
|
|
||||||
/* A:B:C:OP = 9: 9: 7: 7 */
|
|
||||||
/* A:Bx:OP = 9:16: 7 */
|
|
||||||
/* Ax:OP = 25: 7 */
|
|
||||||
/* A:Bz:Cz:OP = 9:14: 2: 7 */
|
|
||||||
|
|
||||||
#define GET_OPCODE(i) ((int)(((mrb_code)(i)) & 0x7f))
|
|
||||||
#define GETARG_A(i) ((int)((((mrb_code)(i)) >> 23) & 0x1ff))
|
|
||||||
#define GETARG_B(i) ((int)((((mrb_code)(i)) >> 14) & 0x1ff))
|
|
||||||
#define GETARG_C(i) ((int)((((mrb_code)(i)) >> 7) & 0x7f))
|
|
||||||
#define GETARG_Bx(i) ((int)((((mrb_code)(i)) >> 7) & 0xffff))
|
|
||||||
#define GETARG_sBx(i) ((int)(GETARG_Bx(i)-MAXARG_sBx))
|
|
||||||
#define GETARG_Ax(i) ((int32_t)((((mrb_code)(i)) >> 7) & 0x1ffffff))
|
|
||||||
#define GETARG_UNPACK_b(i,n1,n2) ((int)((((mrb_code)(i)) >> (7+(n2))) & (((1<<(n1))-1))))
|
|
||||||
#define GETARG_UNPACK_c(i,n1,n2) ((int)((((mrb_code)(i)) >> 7) & (((1<<(n2))-1))))
|
|
||||||
#define GETARG_b(i) GETARG_UNPACK_b(i,14,2)
|
|
||||||
#define GETARG_c(i) GETARG_UNPACK_c(i,14,2)
|
|
||||||
|
|
||||||
#define MKOPCODE(op) ((op) & 0x7f)
|
|
||||||
#define MKARG_A(c) ((mrb_code)((c) & 0x1ff) << 23)
|
|
||||||
#define MKARG_B(c) ((mrb_code)((c) & 0x1ff) << 14)
|
|
||||||
#define MKARG_C(c) (((c) & 0x7f) << 7)
|
|
||||||
#define MKARG_Bx(v) ((mrb_code)((v) & 0xffff) << 7)
|
|
||||||
#define MKARG_sBx(v) MKARG_Bx((v)+MAXARG_sBx)
|
|
||||||
#define MKARG_Ax(v) ((mrb_code)((v) & 0x1ffffff) << 7)
|
|
||||||
#define MKARG_PACK(b,n1,c,n2) ((((b) & ((1<<n1)-1)) << (7+n2))|(((c) & ((1<<n2)-1)) << 7))
|
|
||||||
#define MKARG_bc(b,c) MKARG_PACK(b,14,c,2)
|
|
||||||
|
|
||||||
#define MKOP_A(op,a) (MKOPCODE(op)|MKARG_A(a))
|
|
||||||
#define MKOP_AB(op,a,b) (MKOP_A(op,a)|MKARG_B(b))
|
|
||||||
#define MKOP_ABC(op,a,b,c) (MKOP_AB(op,a,b)|MKARG_C(c))
|
|
||||||
#define MKOP_ABx(op,a,bx) (MKOP_A(op,a)|MKARG_Bx(bx))
|
|
||||||
#define MKOP_Bx(op,bx) (MKOPCODE(op)|MKARG_Bx(bx))
|
|
||||||
#define MKOP_sBx(op,sbx) (MKOPCODE(op)|MKARG_sBx(sbx))
|
|
||||||
#define MKOP_AsBx(op,a,sbx) (MKOP_A(op,a)|MKARG_sBx(sbx))
|
|
||||||
#define MKOP_Ax(op,ax) (MKOPCODE(op)|MKARG_Ax(ax))
|
|
||||||
#define MKOP_Abc(op,a,b,c) (MKOP_A(op,a)|MKARG_bc(b,c))
|
|
||||||
|
|
||||||
enum {
|
|
||||||
/*-----------------------------------------------------------------------
|
|
||||||
operation code operand description
|
|
||||||
------------------------------------------------------------------------*/
|
|
||||||
OP_NOP=0,/* */
|
|
||||||
OP_MOVE,/* A B R(A) := R(B) */
|
|
||||||
OP_LOADL,/* A Bx R(A) := Pool(Bx) */
|
|
||||||
OP_LOADI,/* A sBx R(A) := sBx */
|
|
||||||
OP_LOADSYM,/* A Bx R(A) := Syms(Bx) */
|
|
||||||
OP_LOADNIL,/* A R(A) := nil */
|
|
||||||
OP_LOADSELF,/* A R(A) := self */
|
|
||||||
OP_LOADT,/* A R(A) := true */
|
|
||||||
OP_LOADF,/* A R(A) := false */
|
|
||||||
|
|
||||||
OP_GETGLOBAL,/* A Bx R(A) := getglobal(Syms(Bx)) */
|
|
||||||
OP_SETGLOBAL,/* A Bx setglobal(Syms(Bx), R(A)) */
|
|
||||||
OP_GETSPECIAL,/*A Bx R(A) := Special[Bx] */
|
|
||||||
OP_SETSPECIAL,/*A Bx Special[Bx] := R(A) */
|
|
||||||
OP_GETIV,/* A Bx R(A) := ivget(Syms(Bx)) */
|
|
||||||
OP_SETIV,/* A Bx ivset(Syms(Bx),R(A)) */
|
|
||||||
OP_GETCV,/* A Bx R(A) := cvget(Syms(Bx)) */
|
|
||||||
OP_SETCV,/* A Bx cvset(Syms(Bx),R(A)) */
|
|
||||||
OP_GETCONST,/* A Bx R(A) := constget(Syms(Bx)) */
|
|
||||||
OP_SETCONST,/* A Bx constset(Syms(Bx),R(A)) */
|
|
||||||
OP_GETMCNST,/* A Bx R(A) := R(A)::Syms(Bx) */
|
|
||||||
OP_SETMCNST,/* A Bx R(A+1)::Syms(Bx) := R(A) */
|
|
||||||
OP_GETUPVAR,/* A B C R(A) := uvget(B,C) */
|
|
||||||
OP_SETUPVAR,/* A B C uvset(B,C,R(A)) */
|
|
||||||
|
|
||||||
OP_JMP,/* sBx pc+=sBx */
|
|
||||||
OP_JMPIF,/* A sBx if R(A) pc+=sBx */
|
|
||||||
OP_JMPNOT,/* A sBx if !R(A) pc+=sBx */
|
|
||||||
OP_ONERR,/* sBx rescue_push(pc+sBx) */
|
|
||||||
OP_RESCUE,/* A B C if A (if C exc=R(A) else R(A) := exc);
|
|
||||||
if B R(B) := exc.isa?(R(B)); clear(exc) */
|
|
||||||
OP_POPERR,/* A A.times{rescue_pop()} */
|
|
||||||
OP_RAISE,/* A raise(R(A)) */
|
|
||||||
OP_EPUSH,/* Bx ensure_push(SEQ[Bx]) */
|
|
||||||
OP_EPOP,/* A A.times{ensure_pop().call} */
|
|
||||||
|
|
||||||
OP_SEND,/* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C)) */
|
|
||||||
OP_SENDB,/* A B C R(A) := call(R(A),Syms(B),R(A+1),...,R(A+C),&R(A+C+1))*/
|
|
||||||
OP_FSEND,/* A B C R(A) := fcall(R(A),Syms(B),R(A+1),...,R(A+C-1)) */
|
|
||||||
OP_CALL,/* A R(A) := self.call(frame.argc, frame.argv) */
|
|
||||||
OP_SUPER,/* A C R(A) := super(R(A+1),... ,R(A+C+1)) */
|
|
||||||
OP_ARGARY,/* A Bx R(A) := argument array (16=6:1:5:4) */
|
|
||||||
OP_ENTER,/* Ax arg setup according to flags (23=5:5:1:5:5:1:1) */
|
|
||||||
OP_KARG,/* A B C R(A) := kdict[Syms(B)]; if C kdict.rm(Syms(B)) */
|
|
||||||
OP_KDICT,/* A C R(A) := kdict */
|
|
||||||
|
|
||||||
OP_RETURN,/* A B return R(A) (B=normal,in-block return/break) */
|
|
||||||
OP_TAILCALL,/* A B C return call(R(A),Syms(B),*R(C)) */
|
|
||||||
OP_BLKPUSH,/* A Bx R(A) := block (16=6:1:5:4) */
|
|
||||||
|
|
||||||
OP_ADD,/* A B C R(A) := R(A)+R(A+1) (Syms[B]=:+,C=1) */
|
|
||||||
OP_ADDI,/* A B C R(A) := R(A)+C (Syms[B]=:+) */
|
|
||||||
OP_SUB,/* A B C R(A) := R(A)-R(A+1) (Syms[B]=:-,C=1) */
|
|
||||||
OP_SUBI,/* A B C R(A) := R(A)-C (Syms[B]=:-) */
|
|
||||||
OP_MUL,/* A B C R(A) := R(A)*R(A+1) (Syms[B]=:*,C=1) */
|
|
||||||
OP_DIV,/* A B C R(A) := R(A)/R(A+1) (Syms[B]=:/,C=1) */
|
|
||||||
OP_EQ,/* A B C R(A) := R(A)==R(A+1) (Syms[B]=:==,C=1) */
|
|
||||||
OP_LT,/* A B C R(A) := R(A)<R(A+1) (Syms[B]=:<,C=1) */
|
|
||||||
OP_LE,/* A B C R(A) := R(A)<=R(A+1) (Syms[B]=:<=,C=1) */
|
|
||||||
OP_GT,/* A B C R(A) := R(A)>R(A+1) (Syms[B]=:>,C=1) */
|
|
||||||
OP_GE,/* A B C R(A) := R(A)>=R(A+1) (Syms[B]=:>=,C=1) */
|
|
||||||
|
|
||||||
OP_ARRAY,/* A B C R(A) := ary_new(R(B),R(B+1)..R(B+C)) */
|
|
||||||
OP_ARYCAT,/* A B ary_cat(R(A),R(B)) */
|
|
||||||
OP_ARYPUSH,/* A B ary_push(R(A),R(B)) */
|
|
||||||
OP_AREF,/* A B C R(A) := R(B)[C] */
|
|
||||||
OP_ASET,/* A B C R(B)[C] := R(A) */
|
|
||||||
OP_APOST,/* A B C *R(A),R(A+1)..R(A+C) := R(A) */
|
|
||||||
|
|
||||||
OP_STRING,/* A Bx R(A) := str_dup(Lit(Bx)) */
|
|
||||||
OP_STRCAT,/* A B str_cat(R(A),R(B)) */
|
|
||||||
|
|
||||||
OP_HASH,/* A B C R(A) := hash_new(R(B),R(B+1)..R(B+C)) */
|
|
||||||
OP_LAMBDA,/* A Bz Cz R(A) := lambda(SEQ[Bz],Cz) */
|
|
||||||
OP_RANGE,/* A B C R(A) := range_new(R(B),R(B+1),C) */
|
|
||||||
|
|
||||||
OP_OCLASS,/* A R(A) := ::Object */
|
|
||||||
OP_CLASS,/* A B R(A) := newclass(R(A),Syms(B),R(A+1)) */
|
|
||||||
OP_MODULE,/* A B R(A) := newmodule(R(A),Syms(B)) */
|
|
||||||
OP_EXEC,/* A Bx R(A) := blockexec(R(A),SEQ[Bx]) */
|
|
||||||
OP_METHOD,/* A B R(A).newmethod(Syms(B),R(A+1)) */
|
|
||||||
OP_SCLASS,/* A B R(A) := R(B).singleton_class */
|
|
||||||
OP_TCLASS,/* A R(A) := target_class */
|
|
||||||
|
|
||||||
OP_DEBUG,/* A B C print R(A),R(B),R(C) */
|
|
||||||
OP_STOP,/* stop VM */
|
|
||||||
OP_ERR,/* Bx raise RuntimeError with message Lit(Bx) */
|
|
||||||
|
|
||||||
OP_RSVD1,/* reserved instruction #1 */
|
|
||||||
OP_RSVD2,/* reserved instruction #2 */
|
|
||||||
OP_RSVD3,/* reserved instruction #3 */
|
|
||||||
OP_RSVD4,/* reserved instruction #4 */
|
|
||||||
OP_RSVD5,/* reserved instruction #5 */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define OP_L_STRICT 1
|
#define OP_L_STRICT 1
|
||||||
@@ -158,4 +23,47 @@ enum {
|
|||||||
#define OP_R_BREAK 1
|
#define OP_R_BREAK 1
|
||||||
#define OP_R_RETURN 2
|
#define OP_R_RETURN 2
|
||||||
|
|
||||||
|
#define PEEK_B(pc) (*(pc))
|
||||||
|
#define PEEK_S(pc) ((pc)[0]<<8|(pc)[1])
|
||||||
|
#define PEEK_W(pc) ((pc)[0]<<16|(pc)[1]<<8|(pc)[2])
|
||||||
|
|
||||||
|
#define READ_B() PEEK_B(pc++)
|
||||||
|
#define READ_S() (pc+=2, PEEK_S(pc-2))
|
||||||
|
#define READ_W() (pc+=3, PEEK_W(pc-3))
|
||||||
|
|
||||||
|
#define FETCH_Z() /* nothing */
|
||||||
|
#define FETCH_B() do {a=READ_B();} while (0)
|
||||||
|
#define FETCH_BB() do {a=READ_B(); b=READ_B();} while (0)
|
||||||
|
#define FETCH_BBB() do {a=READ_B(); b=READ_B(); c=READ_B();} while (0)
|
||||||
|
#define FETCH_BS() do {a=READ_B(); b=READ_S();} while (0)
|
||||||
|
#define FETCH_S() do {a=READ_S();} while (0)
|
||||||
|
#define FETCH_W() do {a=READ_W();} while (0)
|
||||||
|
|
||||||
|
/* with OP_EXT1 (1st 16bit) */
|
||||||
|
#define FETCH_Z_1() FETCH_Z()
|
||||||
|
#define FETCH_B_1() FETCH_S()
|
||||||
|
#define FETCH_BB_1() do {a=READ_S(); b=READ_B();} while (0)
|
||||||
|
#define FETCH_BBB_1() do {a=READ_S(); b=READ_B(); c=READ_B();} while (0)
|
||||||
|
#define FETCH_BS_1() do {a=READ_S(); b=READ_S();} while (0)
|
||||||
|
#define FETCH_S_1() FETCH_S()
|
||||||
|
#define FETCH_W_1() FETCH_W()
|
||||||
|
|
||||||
|
/* with OP_EXT2 (2nd 16bit) */
|
||||||
|
#define FETCH_Z_2() FETCH_Z()
|
||||||
|
#define FETCH_B_2() FETCH_B()
|
||||||
|
#define FETCH_BB_2() do {a=READ_B(); b=READ_S();} while (0)
|
||||||
|
#define FETCH_BBB_2() do {a=READ_B(); b=READ_S(); c=READ_B();} while (0)
|
||||||
|
#define FETCH_BS_2() FETCH_BS()
|
||||||
|
#define FETCH_S_2() FETCH_S()
|
||||||
|
#define FETCH_W_2() FETCH_W()
|
||||||
|
|
||||||
|
/* with OP_EXT3 (1st & 2nd 16bit) */
|
||||||
|
#define FETCH_Z_3() FETCH_Z()
|
||||||
|
#define FETCH_B_3() FETCH_B()
|
||||||
|
#define FETCH_BB_3() do {a=READ_S(); b=READ_S();} while (0)
|
||||||
|
#define FETCH_BBB_3() do {a=READ_S(); b=READ_S(); c=READ_B();} while (0)
|
||||||
|
#define FETCH_BS_3() do {a=READ_S(); b=READ_S();} while (0)
|
||||||
|
#define FETCH_S_3() FETCH_S()
|
||||||
|
#define FETCH_W_3() FETCH_W()
|
||||||
|
|
||||||
#endif /* MRUBY_OPCODE_H */
|
#endif /* MRUBY_OPCODE_H */
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
/* operand types:
|
||||||
|
+ Z: no operand (Z,Z,Z,Z)
|
||||||
|
+ B: 8bit (B,S,B,B)
|
||||||
|
+ BB: 8+8bit (BB,SB,BS,SS)
|
||||||
|
+ BBB: 8+8+8bit (BBB,SBB,BSB,SSB)
|
||||||
|
+ BS: 8+16bit (BS,SS,BS,BS)
|
||||||
|
+ S: 16bit (S,S,S,S)
|
||||||
|
+ W: 24bit (W,W,W,W)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------
|
||||||
|
operation code operands semantics
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
OPCODE(NOP, Z) /* no operation */
|
||||||
|
OPCODE(MOVE, BB) /* R(a) = R(b) */
|
||||||
|
OPCODE(LOADL, BB) /* R(a) = Pool(b) */
|
||||||
|
OPCODE(LOADI, BB) /* R(a) = mrb_int(b) */
|
||||||
|
OPCODE(LOADINEG, BB) /* R(a) = mrb_int(-b) */
|
||||||
|
OPCODE(LOADI__1, B) /* R(a) = mrb_int(-1) */
|
||||||
|
OPCODE(LOADI_0, B) /* R(a) = mrb_int(0) */
|
||||||
|
OPCODE(LOADI_1, B) /* R(a) = mrb_int(1) */
|
||||||
|
OPCODE(LOADI_2, B) /* R(a) = mrb_int(2) */
|
||||||
|
OPCODE(LOADI_3, B) /* R(a) = mrb_int(3) */
|
||||||
|
OPCODE(LOADI_4, B) /* R(a) = mrb_int(4) */
|
||||||
|
OPCODE(LOADI_5, B) /* R(a) = mrb_int(5) */
|
||||||
|
OPCODE(LOADI_6, B) /* R(a) = mrb_int(6) */
|
||||||
|
OPCODE(LOADI_7, B) /* R(a) = mrb_int(7) */
|
||||||
|
OPCODE(LOADSYM, BB) /* R(a) = Syms(b) */
|
||||||
|
OPCODE(LOADNIL, B) /* R(a) = nil */
|
||||||
|
OPCODE(LOADSELF, B) /* R(a) = self */
|
||||||
|
OPCODE(LOADT, B) /* R(a) = true */
|
||||||
|
OPCODE(LOADF, B) /* R(a) = false */
|
||||||
|
OPCODE(GETGV, BB) /* R(a) = getglobal(Syms(b)) */
|
||||||
|
OPCODE(SETGV, BB) /* setglobal(Syms(b), R(a)) */
|
||||||
|
OPCODE(GETSV, BB) /* R(a) = Special[Syms(b)] */
|
||||||
|
OPCODE(SETSV, BB) /* Special[Syms(b)] = R(a) */
|
||||||
|
OPCODE(GETIV, BB) /* R(a) = ivget(Syms(b)) */
|
||||||
|
OPCODE(SETIV, BB) /* ivset(Syms(b),R(a)) */
|
||||||
|
OPCODE(GETCV, BB) /* R(a) = cvget(Syms(b)) */
|
||||||
|
OPCODE(SETCV, BB) /* cvset(Syms(b),R(a)) */
|
||||||
|
OPCODE(GETCONST, BB) /* R(a) = constget(Syms(b)) */
|
||||||
|
OPCODE(SETCONST, BB) /* constset(Syms(b),R(a)) */
|
||||||
|
OPCODE(GETMCNST, BB) /* R(a) = R(a)::Syms(b) */
|
||||||
|
OPCODE(SETMCNST, BB) /* R(a+1)::Syms(b) = R(a) */
|
||||||
|
OPCODE(GETUPVAR, BBB) /* R(a) = uvget(b,c) */
|
||||||
|
OPCODE(SETUPVAR, BBB) /* uvset(b,c,R(a)) */
|
||||||
|
OPCODE(JMP, S) /* pc=a */
|
||||||
|
OPCODE(JMPIF, BS) /* if R(b) pc=a */
|
||||||
|
OPCODE(JMPNOT, BS) /* if !R(b) pc=a */
|
||||||
|
OPCODE(JMPNIL, BS) /* if R(b)==nil pc=a */
|
||||||
|
OPCODE(ONERR, S) /* rescue_push(a) */
|
||||||
|
OPCODE(EXCEPT, B) /* R(a) = exc */
|
||||||
|
OPCODE(RESCUE, BB) /* R(b) = R(a).isa?(R(b)) */
|
||||||
|
OPCODE(POPERR, B) /* a.times{rescue_pop()} */
|
||||||
|
OPCODE(RAISE, B) /* raise(R(a)) */
|
||||||
|
OPCODE(EPUSH, B) /* ensure_push(SEQ[a]) */
|
||||||
|
OPCODE(EPOP, B) /* A.times{ensure_pop().call} */
|
||||||
|
OPCODE(SENDV, BB) /* R(a) = call(R(a),Syms(b),*R(a+1)) */
|
||||||
|
OPCODE(SENDVB, BB) /* R(a) = call(R(a),Syms(b),*R(a+1),&R(a+2)) */
|
||||||
|
OPCODE(SEND, BBB) /* R(a) = call(R(a),Syms(b),R(a+1),...,R(a+c)) */
|
||||||
|
OPCODE(SENDB, BBB) /* R(a) = call(R(a),Syms(Bx),R(a+1),...,R(a+c),&R(a+c+1)) */
|
||||||
|
OPCODE(CALL, Z) /* R(0) = self.call(frame.argc, frame.argv) */
|
||||||
|
OPCODE(SUPER, BB) /* R(a) = super(R(a+1),... ,R(a+b+1)) */
|
||||||
|
OPCODE(ARGARY, BS) /* R(a) = argument array (16=m5:r1:m5:d1:lv4) */
|
||||||
|
OPCODE(ENTER, W) /* arg setup according to flags (23=m5:o5:r1:m5:k5:d1:b1) */
|
||||||
|
OPCODE(KEY_P, BB) /* R(a) = kdict.key?(Syms(b)) # todo */
|
||||||
|
OPCODE(KEYEND, Z) /* raise unless kdict.empty? # todo */
|
||||||
|
OPCODE(KARG, BB) /* R(a) = kdict[Syms(b)]; kdict.delete(Syms(b)) # todo */
|
||||||
|
OPCODE(RETURN, B) /* return R(a) (normal) */
|
||||||
|
OPCODE(RETURN_BLK, B) /* return R(a) (in-block return) */
|
||||||
|
OPCODE(BREAK, B) /* break R(a) */
|
||||||
|
OPCODE(BLKPUSH, BS) /* R(a) = block (16=m5:r1:m5:d1:lv4) */
|
||||||
|
OPCODE(ADD, B) /* R(a) = R(a)+R(a+1) */
|
||||||
|
OPCODE(ADDI, BB) /* R(a) = R(a)+mrb_int(c) */
|
||||||
|
OPCODE(SUB, B) /* R(a) = R(a)-R(a+1) */
|
||||||
|
OPCODE(SUBI, BB) /* R(a) = R(a)-C */
|
||||||
|
OPCODE(MUL, B) /* R(a) = R(a)*R(a+1) */
|
||||||
|
OPCODE(DIV, B) /* R(a) = R(a)/R(a+1) */
|
||||||
|
OPCODE(EQ, B) /* R(a) = R(a)==R(a+1) */
|
||||||
|
OPCODE(LT, B) /* R(a) = R(a)<R(a+1) */
|
||||||
|
OPCODE(LE, B) /* R(a) = R(a)<=R(a+1) */
|
||||||
|
OPCODE(GT, B) /* R(a) = R(a)>R(a+1) */
|
||||||
|
OPCODE(GE, B) /* R(a) = R(a)>=R(a+1) */
|
||||||
|
OPCODE(ARRAY, BB) /* R(a) = ary_new(R(a),R(a+1)..R(a+b)) */
|
||||||
|
OPCODE(ARRAY2, BBB) /* R(a) = ary_new(R(b),R(b+1)..R(b+c)) */
|
||||||
|
OPCODE(ARYCAT, B) /* ary_cat(R(a),R(a+1)) */
|
||||||
|
OPCODE(ARYPUSH, B) /* ary_push(R(a),R(a+1)) */
|
||||||
|
OPCODE(ARYDUP, B) /* R(a) = ary_dup(R(a)) */
|
||||||
|
OPCODE(AREF, BBB) /* R(a) = R(b)[c] */
|
||||||
|
OPCODE(ASET, BBB) /* R(a)[c] = R(b) */
|
||||||
|
OPCODE(APOST, BBB) /* *R(a),R(a+1)..R(a+C) = R(a)[b..] */
|
||||||
|
OPCODE(INTERN, B) /* R(a) = intern(R(a)) */
|
||||||
|
OPCODE(STRING, BB) /* R(a) = str_dup(Lit(b)) */
|
||||||
|
OPCODE(STRCAT, B) /* str_cat(R(a),R(a+1)) */
|
||||||
|
OPCODE(HASH, BB) /* R(a) = hash_new(R(a),R(a+1)..R(a+b)) */
|
||||||
|
OPCODE(HASHADD, BB) /* R(a) = hash_push(R(a),R(a+1)..R(a+b)) */
|
||||||
|
OPCODE(HASHCAT, B) /* R(a) = hash_cat(R(a),R(a+1)) */
|
||||||
|
OPCODE(LAMBDA, BB) /* R(a) = lambda(SEQ[b],L_LAMBDA) */
|
||||||
|
OPCODE(BLOCK, BB) /* R(a) = lambda(SEQ[b],L_BLOCK) */
|
||||||
|
OPCODE(METHOD, BB) /* R(a) = lambda(SEQ[b],L_METHOD) */
|
||||||
|
OPCODE(RANGE_INC, B) /* R(a) = range_new(R(a),R(a+1),FALSE) */
|
||||||
|
OPCODE(RANGE_EXC, B) /* R(a) = range_new(R(a),R(a+1),TRUE) */
|
||||||
|
OPCODE(OCLASS, B) /* R(a) = ::Object */
|
||||||
|
OPCODE(CLASS, BB) /* R(a) = newclass(R(a),Syms(b),R(a+1)) */
|
||||||
|
OPCODE(MODULE, BB) /* R(a) = newmodule(R(a),Syms(b)) */
|
||||||
|
OPCODE(EXEC, BB) /* R(a) = blockexec(R(a),SEQ[b]) */
|
||||||
|
OPCODE(DEF, BB) /* R(a).newmethod(Syms(b),R(a+1)) */
|
||||||
|
OPCODE(ALIAS, BB) /* alias_method(target_class,Syms(a),Syms(b)) */
|
||||||
|
OPCODE(UNDEF, B) /* undef_method(target_class,Syms(a)) */
|
||||||
|
OPCODE(SCLASS, B) /* R(a) = R(a).singleton_class */
|
||||||
|
OPCODE(TCLASS, B) /* R(a) = target_class */
|
||||||
|
OPCODE(DEBUG, BBB) /* print a,b,c */
|
||||||
|
OPCODE(ERR, B) /* raise(LocalJumpError, Lit(a)) */
|
||||||
|
OPCODE(EXT1, Z) /* make 1st operand 16bit */
|
||||||
|
OPCODE(EXT2, Z) /* make 2nd operand 16bit */
|
||||||
|
OPCODE(EXT3, Z) /* make 1st and 2nd operands 16bit */
|
||||||
|
OPCODE(STOP, Z) /* stop VM */
|
||||||
+64
-16
@@ -18,19 +18,20 @@ MRB_BEGIN_DECL
|
|||||||
struct REnv {
|
struct REnv {
|
||||||
MRB_OBJECT_HEADER;
|
MRB_OBJECT_HEADER;
|
||||||
mrb_value *stack;
|
mrb_value *stack;
|
||||||
ptrdiff_t cioff;
|
struct mrb_context *cxt;
|
||||||
union {
|
mrb_sym mid;
|
||||||
mrb_sym mid;
|
|
||||||
struct mrb_context *c;
|
|
||||||
} cxt;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MRB_SET_ENV_STACK_LEN(e,len) (e)->flags = (unsigned int)(len)
|
/* flags (21bits): 1(shared flag):10(cioff/bidx):10(stack_len) */
|
||||||
#define MRB_ENV_STACK_LEN(e) ((mrb_int)(e)->flags)
|
#define MRB_ENV_SET_STACK_LEN(e,len) (e)->flags = (((e)->flags & ~0x3ff)|((unsigned int)(len) & 0x3ff))
|
||||||
#define MRB_ENV_UNSHARE_STACK(e) ((e)->cioff = -1)
|
#define MRB_ENV_STACK_LEN(e) ((mrb_int)((e)->flags & 0x3ff))
|
||||||
#define MRB_ENV_STACK_SHARED_P(e) ((e)->cioff >= 0)
|
#define MRB_ENV_STACK_UNSHARED (1<<20)
|
||||||
|
#define MRB_ENV_UNSHARE_STACK(e) (e)->flags |= MRB_ENV_STACK_UNSHARED
|
||||||
|
#define MRB_ENV_STACK_SHARED_P(e) (((e)->flags & MRB_ENV_STACK_UNSHARED) == 0)
|
||||||
|
#define MRB_ENV_BIDX(e) (((e)->flags >> 10) & 0x3ff)
|
||||||
|
#define MRB_ENV_SET_BIDX(e,idx) (e)->flags = (((e)->flags & ~(0x3ff<<10))|((unsigned int)(idx) & 0x3ff)<<10)
|
||||||
|
|
||||||
MRB_API void mrb_env_unshare(mrb_state*, struct REnv*);
|
void mrb_env_unshare(mrb_state*, struct REnv*);
|
||||||
|
|
||||||
struct RProc {
|
struct RProc {
|
||||||
MRB_OBJECT_HEADER;
|
MRB_OBJECT_HEADER;
|
||||||
@@ -38,8 +39,11 @@ struct RProc {
|
|||||||
mrb_irep *irep;
|
mrb_irep *irep;
|
||||||
mrb_func_t func;
|
mrb_func_t func;
|
||||||
} body;
|
} body;
|
||||||
struct RClass *target_class;
|
struct RProc *upper;
|
||||||
struct REnv *env;
|
union {
|
||||||
|
struct RClass *target_class;
|
||||||
|
struct REnv *env;
|
||||||
|
} e;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* aspec access */
|
/* aspec access */
|
||||||
@@ -51,12 +55,29 @@ struct RProc {
|
|||||||
#define MRB_ASPEC_KDICT(a) ((a) & (1<<1))
|
#define MRB_ASPEC_KDICT(a) ((a) & (1<<1))
|
||||||
#define MRB_ASPEC_BLOCK(a) ((a) & 1)
|
#define MRB_ASPEC_BLOCK(a) ((a) & 1)
|
||||||
|
|
||||||
#define MRB_PROC_CFUNC 128
|
#define MRB_PROC_CFUNC_FL 128
|
||||||
#define MRB_PROC_CFUNC_P(p) (((p)->flags & MRB_PROC_CFUNC) != 0)
|
#define MRB_PROC_CFUNC_P(p) (((p)->flags & MRB_PROC_CFUNC_FL) != 0)
|
||||||
|
#define MRB_PROC_CFUNC(p) (p)->body.func
|
||||||
#define MRB_PROC_STRICT 256
|
#define MRB_PROC_STRICT 256
|
||||||
#define MRB_PROC_STRICT_P(p) (((p)->flags & MRB_PROC_STRICT) != 0)
|
#define MRB_PROC_STRICT_P(p) (((p)->flags & MRB_PROC_STRICT) != 0)
|
||||||
#define MRB_PROC_ORPHAN 512
|
#define MRB_PROC_ORPHAN 512
|
||||||
#define MRB_PROC_ORPHAN_P(p) (((p)->flags & MRB_PROC_ORPHAN) != 0)
|
#define MRB_PROC_ORPHAN_P(p) (((p)->flags & MRB_PROC_ORPHAN) != 0)
|
||||||
|
#define MRB_PROC_ENVSET 1024
|
||||||
|
#define MRB_PROC_ENV_P(p) (((p)->flags & MRB_PROC_ENVSET) != 0)
|
||||||
|
#define MRB_PROC_ENV(p) (MRB_PROC_ENV_P(p) ? (p)->e.env : NULL)
|
||||||
|
#define MRB_PROC_TARGET_CLASS(p) (MRB_PROC_ENV_P(p) ? (p)->e.env->c : (p)->e.target_class)
|
||||||
|
#define MRB_PROC_SET_TARGET_CLASS(p,tc) do {\
|
||||||
|
if (MRB_PROC_ENV_P(p)) {\
|
||||||
|
(p)->e.env->c = (tc);\
|
||||||
|
mrb_field_write_barrier(mrb, (struct RBasic*)(p)->e.env, (struct RBasic*)tc);\
|
||||||
|
}\
|
||||||
|
else {\
|
||||||
|
(p)->e.target_class = (tc);\
|
||||||
|
mrb_field_write_barrier(mrb, (struct RBasic*)p, (struct RBasic*)tc);\
|
||||||
|
}\
|
||||||
|
} while (0)
|
||||||
|
#define MRB_PROC_SCOPE 2048
|
||||||
|
#define MRB_PROC_SCOPE_P(p) (((p)->flags & MRB_PROC_SCOPE) != 0)
|
||||||
|
|
||||||
#define mrb_proc_ptr(v) ((struct RProc*)(mrb_ptr(v)))
|
#define mrb_proc_ptr(v) ((struct RProc*)(mrb_ptr(v)))
|
||||||
|
|
||||||
@@ -67,7 +88,7 @@ MRB_API struct RProc *mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int
|
|||||||
void mrb_proc_copy(struct RProc *a, struct RProc *b);
|
void mrb_proc_copy(struct RProc *a, struct RProc *b);
|
||||||
|
|
||||||
/* implementation of #send method */
|
/* implementation of #send method */
|
||||||
MRB_API mrb_value mrb_f_send(mrb_state *mrb, mrb_value self);
|
mrb_value mrb_f_send(mrb_state *mrb, mrb_value self);
|
||||||
|
|
||||||
/* following functions are defined in mruby-proc-ext so please include it when using */
|
/* following functions are defined in mruby-proc-ext so please include it when using */
|
||||||
MRB_API struct RProc *mrb_proc_new_cfunc_with_env(mrb_state*, mrb_func_t, mrb_int, const mrb_value*);
|
MRB_API struct RProc *mrb_proc_new_cfunc_with_env(mrb_state*, mrb_func_t, mrb_int, const mrb_value*);
|
||||||
@@ -75,8 +96,35 @@ MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state*, mrb_int);
|
|||||||
/* old name */
|
/* old name */
|
||||||
#define mrb_cfunc_env_get(mrb, idx) mrb_proc_cfunc_env_get(mrb, idx)
|
#define mrb_cfunc_env_get(mrb, idx) mrb_proc_cfunc_env_get(mrb, idx)
|
||||||
|
|
||||||
|
#ifdef MRB_METHOD_TABLE_INLINE
|
||||||
|
|
||||||
|
#define MRB_METHOD_FUNC_FL ((uintptr_t)1)
|
||||||
|
#define MRB_METHOD_FUNC_P(m) (((uintptr_t)(m))&MRB_METHOD_FUNC_FL)
|
||||||
|
#define MRB_METHOD_FUNC(m) ((mrb_func_t)((uintptr_t)(m)&(~MRB_METHOD_FUNC_FL)))
|
||||||
|
#define MRB_METHOD_FROM_FUNC(m,fn) m=(mrb_method_t)((struct RProc*)((uintptr_t)(fn)|MRB_METHOD_FUNC_FL))
|
||||||
|
#define MRB_METHOD_FROM_PROC(m,pr) m=(mrb_method_t)(struct RProc*)(pr)
|
||||||
|
#define MRB_METHOD_PROC_P(m) (!MRB_METHOD_FUNC_P(m))
|
||||||
|
#define MRB_METHOD_PROC(m) ((struct RProc*)(m))
|
||||||
|
#define MRB_METHOD_UNDEF_P(m) ((m)==0)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define MRB_METHOD_FUNC_P(m) ((m).func_p)
|
||||||
|
#define MRB_METHOD_FUNC(m) ((m).func)
|
||||||
|
#define MRB_METHOD_FROM_FUNC(m,fn) do{(m).func_p=TRUE;(m).func=(fn);}while(0)
|
||||||
|
#define MRB_METHOD_FROM_PROC(m,pr) do{(m).func_p=FALSE;(m).proc=(pr);}while(0)
|
||||||
|
#define MRB_METHOD_PROC_P(m) (!MRB_METHOD_FUNC_P(m))
|
||||||
|
#define MRB_METHOD_PROC(m) ((m).proc)
|
||||||
|
#define MRB_METHOD_UNDEF_P(m) ((m).proc==NULL)
|
||||||
|
|
||||||
|
#endif /* MRB_METHOD_TABLE_INLINE */
|
||||||
|
|
||||||
|
#define MRB_METHOD_CFUNC_P(m) (MRB_METHOD_FUNC_P(m)?TRUE:(MRB_METHOD_PROC(m)?(MRB_PROC_CFUNC_P(MRB_METHOD_PROC(m))):FALSE))
|
||||||
|
#define MRB_METHOD_CFUNC(m) (MRB_METHOD_FUNC_P(m)?MRB_METHOD_FUNC(m):((MRB_METHOD_PROC(m)&&MRB_PROC_CFUNC_P(MRB_METHOD_PROC(m)))?MRB_PROC_CFUNC(MRB_METHOD_PROC(m)):NULL))
|
||||||
|
|
||||||
|
|
||||||
#include <mruby/khash.h>
|
#include <mruby/khash.h>
|
||||||
KHASH_DECLARE(mt, mrb_sym, struct RProc*, TRUE)
|
KHASH_DECLARE(mt, mrb_sym, mrb_method_t, TRUE)
|
||||||
|
|
||||||
MRB_END_DECL
|
MRB_END_DECL
|
||||||
|
|
||||||
|
|||||||
+35
-13
@@ -26,6 +26,7 @@ struct RString {
|
|||||||
union {
|
union {
|
||||||
mrb_int capa;
|
mrb_int capa;
|
||||||
struct mrb_shared_string *shared;
|
struct mrb_shared_string *shared;
|
||||||
|
struct RString *fshared;
|
||||||
} aux;
|
} aux;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
} heap;
|
} heap;
|
||||||
@@ -59,10 +60,17 @@ struct RString {
|
|||||||
#define RSTR_SET_SHARED_FLAG(s) ((s)->flags |= MRB_STR_SHARED)
|
#define RSTR_SET_SHARED_FLAG(s) ((s)->flags |= MRB_STR_SHARED)
|
||||||
#define RSTR_UNSET_SHARED_FLAG(s) ((s)->flags &= ~MRB_STR_SHARED)
|
#define RSTR_UNSET_SHARED_FLAG(s) ((s)->flags &= ~MRB_STR_SHARED)
|
||||||
|
|
||||||
|
#define RSTR_FSHARED_P(s) ((s)->flags & MRB_STR_FSHARED)
|
||||||
|
#define RSTR_SET_FSHARED_FLAG(s) ((s)->flags |= MRB_STR_FSHARED)
|
||||||
|
#define RSTR_UNSET_FSHARED_FLAG(s) ((s)->flags &= ~MRB_STR_FSHARED)
|
||||||
|
|
||||||
#define RSTR_NOFREE_P(s) ((s)->flags & MRB_STR_NOFREE)
|
#define RSTR_NOFREE_P(s) ((s)->flags & MRB_STR_NOFREE)
|
||||||
#define RSTR_SET_NOFREE_FLAG(s) ((s)->flags |= MRB_STR_NOFREE)
|
#define RSTR_SET_NOFREE_FLAG(s) ((s)->flags |= MRB_STR_NOFREE)
|
||||||
#define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE)
|
#define RSTR_UNSET_NOFREE_FLAG(s) ((s)->flags &= ~MRB_STR_NOFREE)
|
||||||
|
|
||||||
|
#define RSTR_POOL_P(s) ((s)->flags & MRB_STR_POOL)
|
||||||
|
#define RSTR_SET_POOL_FLAG(s) ((s)->flags |= MRB_STR_POOL)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns a pointer from a Ruby string
|
* Returns a pointer from a Ruby string
|
||||||
*/
|
*/
|
||||||
@@ -76,16 +84,25 @@ struct RString {
|
|||||||
MRB_API mrb_int mrb_str_strlen(mrb_state*, struct RString*);
|
MRB_API mrb_int mrb_str_strlen(mrb_state*, struct RString*);
|
||||||
|
|
||||||
#define MRB_STR_SHARED 1
|
#define MRB_STR_SHARED 1
|
||||||
#define MRB_STR_NOFREE 2
|
#define MRB_STR_FSHARED 2
|
||||||
#define MRB_STR_NO_UTF 8
|
#define MRB_STR_NOFREE 4
|
||||||
#define MRB_STR_EMBED 16
|
#define MRB_STR_POOL 8
|
||||||
#define MRB_STR_EMBED_LEN_MASK 0x3e0
|
#define MRB_STR_NO_UTF 16
|
||||||
#define MRB_STR_EMBED_LEN_SHIFT 5
|
#define MRB_STR_EMBED 32
|
||||||
|
#define MRB_STR_EMBED_LEN_MASK 0x7c0
|
||||||
|
#define MRB_STR_EMBED_LEN_SHIFT 6
|
||||||
|
|
||||||
void mrb_gc_free_str(mrb_state*, struct RString*);
|
void mrb_gc_free_str(mrb_state*, struct RString*);
|
||||||
MRB_API void mrb_str_modify(mrb_state*, struct RString*);
|
MRB_API void mrb_str_modify(mrb_state*, struct RString*);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Appends self to other. Returns self as a concatnated string.
|
* Finds the index of a substring in a string
|
||||||
|
*/
|
||||||
|
MRB_API mrb_int mrb_str_index(mrb_state*, mrb_value, const char*, mrb_int, mrb_int);
|
||||||
|
#define mrb_str_index_lit(mrb, str, lit, off) mrb_str_index(mrb, str, lit, mrb_strlen_lit(lit), off);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Appends self to other. Returns self as a concatenated string.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Example:
|
* Example:
|
||||||
@@ -109,10 +126,10 @@ MRB_API void mrb_str_modify(mrb_state*, struct RString*);
|
|||||||
* str1 = mrb_str_new_lit(mrb, "abc");
|
* str1 = mrb_str_new_lit(mrb, "abc");
|
||||||
* str2 = mrb_str_new_lit(mrb, "def");
|
* str2 = mrb_str_new_lit(mrb, "def");
|
||||||
*
|
*
|
||||||
* // Concatnates str2 to str1.
|
* // Concatenates str2 to str1.
|
||||||
* mrb_str_concat(mrb, str1, str2);
|
* mrb_str_concat(mrb, str1, str2);
|
||||||
*
|
*
|
||||||
* // Prints new Concatnated Ruby string.
|
* // Prints new Concatenated Ruby string.
|
||||||
* mrb_p(mrb, str1);
|
* mrb_p(mrb, str1);
|
||||||
*
|
*
|
||||||
* mrb_close(mrb);
|
* mrb_close(mrb);
|
||||||
@@ -161,10 +178,10 @@ MRB_API void mrb_str_concat(mrb_state*, mrb_value, mrb_value);
|
|||||||
* mrb_p(mrb, a);
|
* mrb_p(mrb, a);
|
||||||
* mrb_p(mrb, b);
|
* mrb_p(mrb, b);
|
||||||
*
|
*
|
||||||
* // Concatnates both Ruby strings.
|
* // Concatenates both Ruby strings.
|
||||||
* c = mrb_str_plus(mrb, a, b);
|
* c = mrb_str_plus(mrb, a, b);
|
||||||
*
|
*
|
||||||
* // Prints new Concatnated Ruby string.
|
* // Prints new Concatenated Ruby string.
|
||||||
* mrb_p(mrb, c);
|
* mrb_p(mrb, c);
|
||||||
*
|
*
|
||||||
* mrb_close(mrb);
|
* mrb_close(mrb);
|
||||||
@@ -176,7 +193,7 @@ MRB_API void mrb_str_concat(mrb_state*, mrb_value, mrb_value);
|
|||||||
*
|
*
|
||||||
* => "abc" # First string
|
* => "abc" # First string
|
||||||
* => "def" # Second string
|
* => "def" # Second string
|
||||||
* => "abcdef" # First & Second concatnated.
|
* => "abcdef" # First & Second concatenated.
|
||||||
*
|
*
|
||||||
* @param [mrb_state] mrb The current mruby state.
|
* @param [mrb_state] mrb The current mruby state.
|
||||||
* @param [mrb_value] a First string to concatenate.
|
* @param [mrb_value] a First string to concatenate.
|
||||||
@@ -294,9 +311,13 @@ MRB_API mrb_value mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb
|
|||||||
* @param [mrb_value] str Ruby string.
|
* @param [mrb_value] str Ruby string.
|
||||||
* @return [mrb_value] A Ruby string.
|
* @return [mrb_value] A Ruby string.
|
||||||
*/
|
*/
|
||||||
|
MRB_API mrb_value mrb_ensure_string_type(mrb_state *mrb, mrb_value str);
|
||||||
|
MRB_API mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str);
|
||||||
|
/* obsolete: use mrb_ensure_string_type() instead */
|
||||||
MRB_API mrb_value mrb_string_type(mrb_state *mrb, mrb_value str);
|
MRB_API mrb_value mrb_string_type(mrb_state *mrb, mrb_value str);
|
||||||
|
|
||||||
MRB_API mrb_value mrb_check_string_type(mrb_state *mrb, mrb_value str);
|
|
||||||
|
MRB_API mrb_value mrb_str_new_capa(mrb_state *mrb, size_t capa);
|
||||||
MRB_API mrb_value mrb_str_buf_new(mrb_state *mrb, size_t capa);
|
MRB_API mrb_value mrb_str_buf_new(mrb_state *mrb, size_t capa);
|
||||||
|
|
||||||
MRB_API const char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr);
|
MRB_API const char *mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr);
|
||||||
@@ -335,6 +356,7 @@ MRB_API double mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck);
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns a converted string type.
|
* Returns a converted string type.
|
||||||
|
* For type checking, non converting `mrb_to_str` is recommended.
|
||||||
*/
|
*/
|
||||||
MRB_API mrb_value mrb_str_to_str(mrb_state *mrb, mrb_value str);
|
MRB_API mrb_value mrb_str_to_str(mrb_state *mrb, mrb_value str);
|
||||||
|
|
||||||
@@ -401,7 +423,7 @@ MRB_API int mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2);
|
|||||||
MRB_API char *mrb_str_to_cstr(mrb_state *mrb, mrb_value str);
|
MRB_API char *mrb_str_to_cstr(mrb_state *mrb, mrb_value str);
|
||||||
|
|
||||||
mrb_value mrb_str_pool(mrb_state *mrb, mrb_value str);
|
mrb_value mrb_str_pool(mrb_state *mrb, mrb_value str);
|
||||||
mrb_int mrb_str_hash(mrb_state *mrb, mrb_value str);
|
uint32_t mrb_str_hash(mrb_state *mrb, mrb_value str);
|
||||||
mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str);
|
mrb_value mrb_str_dump(mrb_state *mrb, mrb_value str);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -15,9 +15,9 @@
|
|||||||
|
|
||||||
#if defined(MRB_ENABLE_CXX_EXCEPTION) && defined(__cplusplus)
|
#if defined(MRB_ENABLE_CXX_EXCEPTION) && defined(__cplusplus)
|
||||||
|
|
||||||
#define MRB_TRY(buf) do { try {
|
#define MRB_TRY(buf) try {
|
||||||
#define MRB_CATCH(buf) } catch(mrb_jmpbuf_impl e) { if (e != (buf)->impl) { throw e; }
|
#define MRB_CATCH(buf) } catch(mrb_jmpbuf_impl e) { if (e != (buf)->impl) { throw e; }
|
||||||
#define MRB_END_EXC(buf) } } while(0)
|
#define MRB_END_EXC(buf) }
|
||||||
|
|
||||||
#define MRB_THROW(buf) throw((buf)->impl)
|
#define MRB_THROW(buf) throw((buf)->impl)
|
||||||
typedef mrb_int mrb_jmpbuf_impl;
|
typedef mrb_int mrb_jmpbuf_impl;
|
||||||
@@ -34,9 +34,9 @@ typedef mrb_int mrb_jmpbuf_impl;
|
|||||||
#define MRB_LONGJMP longjmp
|
#define MRB_LONGJMP longjmp
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MRB_TRY(buf) do { if (MRB_SETJMP((buf)->impl) == 0) {
|
#define MRB_TRY(buf) if (MRB_SETJMP((buf)->impl) == 0) {
|
||||||
#define MRB_CATCH(buf) } else {
|
#define MRB_CATCH(buf) } else {
|
||||||
#define MRB_END_EXC(buf) } } while(0)
|
#define MRB_END_EXC(buf) }
|
||||||
|
|
||||||
#define MRB_THROW(buf) MRB_LONGJMP((buf)->impl, 1);
|
#define MRB_THROW(buf) MRB_LONGJMP((buf)->impl, 1);
|
||||||
#define mrb_jmpbuf_impl jmp_buf
|
#define mrb_jmpbuf_impl jmp_buf
|
||||||
|
|||||||
@@ -63,12 +63,14 @@ struct mrb_state;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
MRB_API double mrb_float_read(const char*, char**);
|
MRB_API double mrb_float_read(const char*, char**);
|
||||||
#ifdef MRB_USE_FLOAT
|
#ifdef MRB_USE_FLOAT
|
||||||
typedef float mrb_float;
|
typedef float mrb_float;
|
||||||
#else
|
#else
|
||||||
typedef double mrb_float;
|
typedef double mrb_float;
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined _MSC_VER && _MSC_VER < 1900
|
#if defined _MSC_VER && _MSC_VER < 1900
|
||||||
# ifndef __cplusplus
|
# ifndef __cplusplus
|
||||||
@@ -79,7 +81,7 @@ MRB_API int mrb_msvc_vsnprintf(char *s, size_t n, const char *format, va_list ar
|
|||||||
MRB_API int mrb_msvc_snprintf(char *s, size_t n, const char *format, ...);
|
MRB_API int mrb_msvc_snprintf(char *s, size_t n, const char *format, ...);
|
||||||
# define vsnprintf(s, n, format, arg) mrb_msvc_vsnprintf(s, n, format, arg)
|
# define vsnprintf(s, n, format, arg) mrb_msvc_vsnprintf(s, n, format, arg)
|
||||||
# define snprintf(s, n, format, ...) mrb_msvc_snprintf(s, n, format, __VA_ARGS__)
|
# define snprintf(s, n, format, ...) mrb_msvc_snprintf(s, n, format, __VA_ARGS__)
|
||||||
# if _MSC_VER < 1800
|
# if _MSC_VER < 1800 && !defined MRB_WITHOUT_FLOAT
|
||||||
# include <float.h>
|
# include <float.h>
|
||||||
# define isfinite(n) _finite(n)
|
# define isfinite(n) _finite(n)
|
||||||
# define isnan _isnan
|
# define isnan _isnan
|
||||||
@@ -158,7 +160,9 @@ typedef void mrb_value;
|
|||||||
#ifndef mrb_bool
|
#ifndef mrb_bool
|
||||||
#define mrb_bool(o) (mrb_type(o) != MRB_TT_FALSE)
|
#define mrb_bool(o) (mrb_type(o) != MRB_TT_FALSE)
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
#define mrb_float_p(o) (mrb_type(o) == MRB_TT_FLOAT)
|
#define mrb_float_p(o) (mrb_type(o) == MRB_TT_FLOAT)
|
||||||
|
#endif
|
||||||
#define mrb_symbol_p(o) (mrb_type(o) == MRB_TT_SYMBOL)
|
#define mrb_symbol_p(o) (mrb_type(o) == MRB_TT_SYMBOL)
|
||||||
#define mrb_array_p(o) (mrb_type(o) == MRB_TT_ARRAY)
|
#define mrb_array_p(o) (mrb_type(o) == MRB_TT_ARRAY)
|
||||||
#define mrb_string_p(o) (mrb_type(o) == MRB_TT_STRING)
|
#define mrb_string_p(o) (mrb_type(o) == MRB_TT_STRING)
|
||||||
@@ -171,6 +175,7 @@ MRB_API mrb_bool mrb_regexp_p(struct mrb_state*, mrb_value);
|
|||||||
/*
|
/*
|
||||||
* Returns a float in Ruby.
|
* Returns a float in Ruby.
|
||||||
*/
|
*/
|
||||||
|
#ifndef MRB_WITHOUT_FLOAT
|
||||||
MRB_INLINE mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f)
|
MRB_INLINE mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f)
|
||||||
{
|
{
|
||||||
mrb_value v;
|
mrb_value v;
|
||||||
@@ -178,6 +183,7 @@ MRB_INLINE mrb_value mrb_float_value(struct mrb_state *mrb, mrb_float f)
|
|||||||
SET_FLOAT_VALUE(mrb, v, f);
|
SET_FLOAT_VALUE(mrb, v, f);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline mrb_value
|
static inline mrb_value
|
||||||
mrb_cptr_value(struct mrb_state *mrb, void *p)
|
mrb_cptr_value(struct mrb_state *mrb, void *p)
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ struct global_entry {
|
|||||||
|
|
||||||
mrb_value mrb_vm_special_get(mrb_state*, mrb_sym);
|
mrb_value mrb_vm_special_get(mrb_state*, mrb_sym);
|
||||||
void mrb_vm_special_set(mrb_state*, mrb_sym, mrb_value);
|
void mrb_vm_special_set(mrb_state*, mrb_sym, mrb_value);
|
||||||
mrb_value mrb_vm_iv_get(mrb_state*, mrb_sym);
|
|
||||||
void mrb_vm_iv_set(mrb_state*, mrb_sym, mrb_value);
|
|
||||||
mrb_value mrb_vm_cv_get(mrb_state*, mrb_sym);
|
mrb_value mrb_vm_cv_get(mrb_state*, mrb_sym);
|
||||||
void mrb_vm_cv_set(mrb_state*, mrb_sym, mrb_value);
|
void mrb_vm_cv_set(mrb_state*, mrb_sym, mrb_value);
|
||||||
mrb_value mrb_vm_const_get(mrb_state*, mrb_sym);
|
mrb_value mrb_vm_const_get(mrb_state*, mrb_sym);
|
||||||
@@ -42,12 +40,11 @@ MRB_API void mrb_const_set(mrb_state*, mrb_value, mrb_sym, mrb_value);
|
|||||||
MRB_API mrb_bool mrb_const_defined(mrb_state*, mrb_value, mrb_sym);
|
MRB_API mrb_bool mrb_const_defined(mrb_state*, mrb_value, mrb_sym);
|
||||||
MRB_API void mrb_const_remove(mrb_state*, mrb_value, mrb_sym);
|
MRB_API void mrb_const_remove(mrb_state*, mrb_value, mrb_sym);
|
||||||
|
|
||||||
MRB_API mrb_bool mrb_iv_p(mrb_state *mrb, mrb_sym sym);
|
MRB_API mrb_bool mrb_iv_name_sym_p(mrb_state *mrb, mrb_sym sym);
|
||||||
MRB_API void mrb_iv_check(mrb_state *mrb, mrb_sym sym);
|
MRB_API void mrb_iv_name_sym_check(mrb_state *mrb, mrb_sym sym);
|
||||||
MRB_API mrb_value mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
|
MRB_API mrb_value mrb_obj_iv_get(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
|
||||||
MRB_API void mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
|
MRB_API void mrb_obj_iv_set(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
|
||||||
MRB_API mrb_bool mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
|
MRB_API mrb_bool mrb_obj_iv_defined(mrb_state *mrb, struct RObject *obj, mrb_sym sym);
|
||||||
MRB_API void mrb_obj_iv_ifnone(mrb_state *mrb, struct RObject *obj, mrb_sym sym, mrb_value v);
|
|
||||||
MRB_API mrb_value mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym);
|
MRB_API mrb_value mrb_iv_get(mrb_state *mrb, mrb_value obj, mrb_sym sym);
|
||||||
MRB_API void mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v);
|
MRB_API void mrb_iv_set(mrb_state *mrb, mrb_value obj, mrb_sym sym, mrb_value v);
|
||||||
MRB_API mrb_bool mrb_iv_defined(mrb_state*, mrb_value, mrb_sym);
|
MRB_API mrb_bool mrb_iv_defined(mrb_state*, mrb_value, mrb_sym);
|
||||||
@@ -126,7 +123,6 @@ mrb_value mrb_obj_instance_variables(mrb_state*, mrb_value);
|
|||||||
mrb_value mrb_mod_class_variables(mrb_state*, mrb_value);
|
mrb_value mrb_mod_class_variables(mrb_state*, mrb_value);
|
||||||
mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym);
|
mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym);
|
||||||
mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym);
|
mrb_bool mrb_mod_cv_defined(mrb_state *mrb, struct RClass * c, mrb_sym sym);
|
||||||
mrb_sym mrb_class_sym(mrb_state *mrb, struct RClass *c, struct RClass *outer);
|
|
||||||
|
|
||||||
/* GC functions */
|
/* GC functions */
|
||||||
void mrb_gc_mark_gv(mrb_state*);
|
void mrb_gc_mark_gv(mrb_state*);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ MRB_BEGIN_DECL
|
|||||||
/*
|
/*
|
||||||
* The version of Ruby used by mruby.
|
* The version of Ruby used by mruby.
|
||||||
*/
|
*/
|
||||||
#define MRUBY_RUBY_VERSION "1.9"
|
#define MRUBY_RUBY_VERSION "2.0"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ruby engine.
|
* Ruby engine.
|
||||||
@@ -37,12 +37,12 @@ MRB_BEGIN_DECL
|
|||||||
/*
|
/*
|
||||||
* Major release version number.
|
* Major release version number.
|
||||||
*/
|
*/
|
||||||
#define MRUBY_RELEASE_MAJOR 1
|
#define MRUBY_RELEASE_MAJOR 2
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Minor release version number.
|
* Minor release version number.
|
||||||
*/
|
*/
|
||||||
#define MRUBY_RELEASE_MINOR 3
|
#define MRUBY_RELEASE_MINOR 0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tiny release version number.
|
* Tiny release version number.
|
||||||
@@ -62,17 +62,17 @@ MRB_BEGIN_DECL
|
|||||||
/*
|
/*
|
||||||
* Release year.
|
* Release year.
|
||||||
*/
|
*/
|
||||||
#define MRUBY_RELEASE_YEAR 2017
|
#define MRUBY_RELEASE_YEAR 2018
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Release month.
|
* Release month.
|
||||||
*/
|
*/
|
||||||
#define MRUBY_RELEASE_MONTH 7
|
#define MRUBY_RELEASE_MONTH 12
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Release day.
|
* Release day.
|
||||||
*/
|
*/
|
||||||
#define MRUBY_RELEASE_DAY 4
|
#define MRUBY_RELEASE_DAY 11
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Release date as a string.
|
* Release date as a string.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
load "#{MRUBY_ROOT}/tasks/mruby_build_gem.rake"
|
require "mruby/build/load_gems"
|
||||||
load "#{MRUBY_ROOT}/tasks/mruby_build_commands.rake"
|
require "mruby/build/command"
|
||||||
|
|
||||||
module MRuby
|
module MRuby
|
||||||
class << self
|
class << self
|
||||||
@@ -45,9 +45,11 @@ module MRuby
|
|||||||
include Rake::DSL
|
include Rake::DSL
|
||||||
include LoadGems
|
include LoadGems
|
||||||
attr_accessor :name, :bins, :exts, :file_separator, :build_dir, :gem_clone_dir
|
attr_accessor :name, :bins, :exts, :file_separator, :build_dir, :gem_clone_dir
|
||||||
attr_reader :libmruby, :gems, :toolchains
|
attr_reader :libmruby_objs, :gems, :toolchains
|
||||||
attr_writer :enable_bintest, :enable_test
|
attr_writer :enable_bintest, :enable_test
|
||||||
|
|
||||||
|
alias libmruby libmruby_objs
|
||||||
|
|
||||||
COMPILERS = %w(cc cxx objc asm)
|
COMPILERS = %w(cc cxx objc asm)
|
||||||
COMMANDS = COMPILERS + %w(linker archiver yacc gperf git exts mrbc)
|
COMMANDS = COMPILERS + %w(linker archiver yacc gperf git exts mrbc)
|
||||||
attr_block MRuby::Build::COMMANDS
|
attr_block MRuby::Build::COMMANDS
|
||||||
@@ -81,7 +83,7 @@ module MRuby
|
|||||||
@mrbc = Command::Mrbc.new(self)
|
@mrbc = Command::Mrbc.new(self)
|
||||||
|
|
||||||
@bins = []
|
@bins = []
|
||||||
@gems, @libmruby = MRuby::Gem::List.new, []
|
@gems, @libmruby_objs = MRuby::Gem::List.new, []
|
||||||
@build_mrbtest_lib_only = false
|
@build_mrbtest_lib_only = false
|
||||||
@cxx_exception_enabled = false
|
@cxx_exception_enabled = false
|
||||||
@cxx_exception_disabled = false
|
@cxx_exception_disabled = false
|
||||||
@@ -100,6 +102,10 @@ module MRuby
|
|||||||
build_mrbtest if test_enabled?
|
build_mrbtest if test_enabled?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def debug_enabled?
|
||||||
|
@enable_debug
|
||||||
|
end
|
||||||
|
|
||||||
def enable_debug
|
def enable_debug
|
||||||
compilers.each do |c|
|
compilers.each do |c|
|
||||||
c.defines += %w(MRB_DEBUG)
|
c.defines += %w(MRB_DEBUG)
|
||||||
@@ -108,6 +114,8 @@ module MRuby
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
@mrbc.compile_options += ' -g'
|
@mrbc.compile_options += ' -g'
|
||||||
|
|
||||||
|
@enable_debug = true
|
||||||
end
|
end
|
||||||
|
|
||||||
def disable_cxx_exception
|
def disable_cxx_exception
|
||||||
@@ -241,7 +249,7 @@ EOS
|
|||||||
else
|
else
|
||||||
compiler.defines += %w(DISABLE_GEMS)
|
compiler.defines += %w(DISABLE_GEMS)
|
||||||
end
|
end
|
||||||
compiler.define_rules build_dir, File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
compiler.define_rules build_dir, File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -293,18 +301,21 @@ EOS
|
|||||||
@build_mrbtest_lib_only
|
@build_mrbtest_lib_only
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def verbose_flag
|
||||||
|
$verbose ? ' -v' : ''
|
||||||
|
end
|
||||||
|
|
||||||
def run_test
|
def run_test
|
||||||
puts ">>> Test #{name} <<<"
|
puts ">>> Test #{name} <<<"
|
||||||
mrbtest = exefile("#{build_dir}/bin/mrbtest")
|
mrbtest = exefile("#{build_dir}/bin/mrbtest")
|
||||||
sh "#{filename mrbtest.relative_path}#{$verbose ? ' -v' : ''}"
|
sh "#{filename mrbtest.relative_path}#{verbose_flag}"
|
||||||
puts
|
puts
|
||||||
run_bintest if bintest_enabled?
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_bintest
|
def run_bintest
|
||||||
targets = @gems.select { |v| File.directory? "#{v.dir}/bintest" }.map { |v| filename v.dir }
|
targets = @gems.select { |v| File.directory? "#{v.dir}/bintest" }.map { |v| filename v.dir }
|
||||||
targets << filename(".") if File.directory? "./bintest"
|
targets << filename(".") if File.directory? "./bintest"
|
||||||
sh "ruby test/bintest.rb #{targets.join ' '}"
|
sh "ruby test/bintest.rb#{verbose_flag} #{targets.join ' '}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def print_build_summary
|
def print_build_summary
|
||||||
@@ -324,6 +335,18 @@ EOS
|
|||||||
puts "================================================"
|
puts "================================================"
|
||||||
puts
|
puts
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def libmruby_static
|
||||||
|
libfile("#{build_dir}/lib/libmruby")
|
||||||
|
end
|
||||||
|
|
||||||
|
def libmruby_core_static
|
||||||
|
libfile("#{build_dir}/lib/libmruby_core")
|
||||||
|
end
|
||||||
|
|
||||||
|
def libraries
|
||||||
|
[libmruby_static]
|
||||||
|
end
|
||||||
end # Build
|
end # Build
|
||||||
|
|
||||||
class CrossBuild < Build
|
class CrossBuild < Build
|
||||||
@@ -334,6 +357,7 @@ EOS
|
|||||||
attr_accessor :host_target, :build_target
|
attr_accessor :host_target, :build_target
|
||||||
|
|
||||||
def initialize(name, build_dir=nil, &block)
|
def initialize(name, build_dir=nil, &block)
|
||||||
|
@endian = nil
|
||||||
@test_runner = Command::CrossTestRunner.new(self)
|
@test_runner = Command::CrossTestRunner.new(self)
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
@@ -343,6 +367,7 @@ EOS
|
|||||||
end
|
end
|
||||||
|
|
||||||
def run_test
|
def run_test
|
||||||
|
@test_runner.runner_options << ' -v' if $verbose
|
||||||
mrbtest = exefile("#{build_dir}/bin/mrbtest")
|
mrbtest = exefile("#{build_dir}/bin/mrbtest")
|
||||||
if (@test_runner.command == nil)
|
if (@test_runner.command == nil)
|
||||||
puts "You should run #{mrbtest} on target device."
|
puts "You should run #{mrbtest} on target device."
|
||||||
@@ -351,5 +376,26 @@ EOS
|
|||||||
@test_runner.run(mrbtest)
|
@test_runner.run(mrbtest)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def big_endian
|
||||||
|
if @endian
|
||||||
|
puts "Endian has already specified as #{@endian}."
|
||||||
|
return
|
||||||
|
end
|
||||||
|
@endian = :big
|
||||||
|
@mrbc.compile_options += ' -E'
|
||||||
|
compilers.each do |c|
|
||||||
|
c.defines += %w(MRB_ENDIAN_BIG)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def little_endian
|
||||||
|
if @endian
|
||||||
|
puts "Endian has already specified as #{@endian}."
|
||||||
|
return
|
||||||
|
end
|
||||||
|
@endian = :little
|
||||||
|
@mrbc.compile_options += ' -e'
|
||||||
|
end
|
||||||
end # CrossBuild
|
end # CrossBuild
|
||||||
end # MRuby
|
end # MRuby
|
||||||
@@ -76,9 +76,6 @@ module MRuby
|
|||||||
|
|
||||||
if params[:core]
|
if params[:core]
|
||||||
gemdir = "#{root}/mrbgems/#{params[:core]}"
|
gemdir = "#{root}/mrbgems/#{params[:core]}"
|
||||||
elsif params[:path]
|
|
||||||
require 'pathname'
|
|
||||||
gemdir = Pathname.new(params[:path]).absolute? ? params[:path] : "#{root}/#{params[:path]}"
|
|
||||||
elsif params[:git]
|
elsif params[:git]
|
||||||
url = params[:git]
|
url = params[:git]
|
||||||
gemdir = "#{gem_clone_dir}/#{url.match(/([-\w]+)(\.[-\w]+|)$/).to_a[1]}"
|
gemdir = "#{gem_clone_dir}/#{url.match(/([-\w]+)(\.[-\w]+|)$/).to_a[1]}"
|
||||||
@@ -108,6 +105,11 @@ module MRuby
|
|||||||
# Jump to the top of the branch
|
# Jump to the top of the branch
|
||||||
git.run_checkout gemdir, branch if $pull_gems
|
git.run_checkout gemdir, branch if $pull_gems
|
||||||
end
|
end
|
||||||
|
|
||||||
|
gemdir << "/#{params[:path]}" if params[:path]
|
||||||
|
elsif params[:path]
|
||||||
|
require 'pathname'
|
||||||
|
gemdir = Pathname.new(params[:path]).absolute? ? params[:path] : "#{root}/#{params[:path]}"
|
||||||
else
|
else
|
||||||
fail "unknown gem option #{params}"
|
fail "unknown gem option #{params}"
|
||||||
end
|
end
|
||||||
@@ -63,10 +63,7 @@ module MRuby
|
|||||||
objfile(f.relative_path_from(@dir).to_s.pathmap("#{build_dir}/%X"))
|
objfile(f.relative_path_from(@dir).to_s.pathmap("#{build_dir}/%X"))
|
||||||
end
|
end
|
||||||
|
|
||||||
@generate_functions = !(@rbfiles.empty? && @objs.empty?)
|
@test_rbfiles = Dir.glob("#{dir}/test/**/*.rb").sort
|
||||||
@objs << objfile("#{build_dir}/gem_init") if @generate_functions
|
|
||||||
|
|
||||||
@test_rbfiles = Dir.glob("#{dir}/test/**/*.rb")
|
|
||||||
@test_objs = Dir.glob("#{dir}/test/*.{c,cpp,cxx,cc,m,asm,s,S}").map do |f|
|
@test_objs = Dir.glob("#{dir}/test/*.{c,cpp,cxx,cc,m,asm,s,S}").map do |f|
|
||||||
objfile(f.relative_path_from(dir).to_s.pathmap("#{build_dir}/%X"))
|
objfile(f.relative_path_from(dir).to_s.pathmap("#{build_dir}/%X"))
|
||||||
end
|
end
|
||||||
@@ -83,11 +80,14 @@ module MRuby
|
|||||||
|
|
||||||
instance_eval(&@initializer)
|
instance_eval(&@initializer)
|
||||||
|
|
||||||
|
@generate_functions = !(@rbfiles.empty? && @objs.empty?)
|
||||||
|
@objs << objfile("#{build_dir}/gem_init") if @generate_functions
|
||||||
|
|
||||||
if !name || !licenses || !authors
|
if !name || !licenses || !authors
|
||||||
fail "#{name || dir} required to set name, license(s) and author(s)"
|
fail "#{name || dir} required to set name, license(s) and author(s)"
|
||||||
end
|
end
|
||||||
|
|
||||||
build.libmruby << @objs
|
build.libmruby_objs << @objs
|
||||||
|
|
||||||
instance_eval(&@build_config_initializer) if @build_config_initializer
|
instance_eval(&@build_config_initializer) if @build_config_initializer
|
||||||
end
|
end
|
||||||
@@ -176,6 +176,7 @@ module MRuby
|
|||||||
f.puts %Q[ mrb_load_irep(mrb, gem_mrblib_irep_#{funcname});]
|
f.puts %Q[ mrb_load_irep(mrb, gem_mrblib_irep_#{funcname});]
|
||||||
f.puts %Q[ if (mrb->exc) {]
|
f.puts %Q[ if (mrb->exc) {]
|
||||||
f.puts %Q[ mrb_print_error(mrb);]
|
f.puts %Q[ mrb_print_error(mrb);]
|
||||||
|
f.puts %Q[ mrb_close(mrb);]
|
||||||
f.puts %Q[ exit(EXIT_FAILURE);]
|
f.puts %Q[ exit(EXIT_FAILURE);]
|
||||||
f.puts %Q[ }]
|
f.puts %Q[ }]
|
||||||
end
|
end
|
||||||
@@ -323,20 +324,22 @@ module MRuby
|
|||||||
@ary.empty?
|
@ary.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def default_gem_params dep
|
||||||
|
if dep[:default]; dep
|
||||||
|
elsif File.exist? "#{MRUBY_ROOT}/mrbgems/#{dep[:gem]}" # check core
|
||||||
|
{ :gem => dep[:gem], :default => { :core => dep[:gem] } }
|
||||||
|
else # fallback to mgem-list
|
||||||
|
{ :gem => dep[:gem], :default => { :mgem => dep[:gem] } }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def generate_gem_table build
|
def generate_gem_table build
|
||||||
gem_table = @ary.reduce({}) { |res,v| res[v.name] = v; res }
|
gem_table = @ary.reduce({}) { |res,v| res[v.name] = v; res }
|
||||||
|
|
||||||
default_gems = []
|
default_gems = []
|
||||||
each do |g|
|
each do |g|
|
||||||
g.dependencies.each do |dep|
|
g.dependencies.each do |dep|
|
||||||
unless gem_table.key? dep[:gem]
|
default_gems << default_gem_params(dep) unless gem_table.key? dep[:gem]
|
||||||
if dep[:default]; default_gems << dep
|
|
||||||
elsif File.exist? "#{MRUBY_ROOT}/mrbgems/#{dep[:gem]}" # check core
|
|
||||||
default_gems << { :gem => dep[:gem], :default => { :core => dep[:gem] } }
|
|
||||||
else # fallback to mgem-list
|
|
||||||
default_gems << { :gem => dep[:gem], :default => { :mgem => dep[:gem] } }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -348,11 +351,7 @@ module MRuby
|
|||||||
spec.setup
|
spec.setup
|
||||||
|
|
||||||
spec.dependencies.each do |dep|
|
spec.dependencies.each do |dep|
|
||||||
unless gem_table.key? dep[:gem]
|
default_gems << default_gem_params(dep) unless gem_table.key? dep[:gem]
|
||||||
if dep[:default]; default_gems << dep
|
|
||||||
else default_gems << { :gem => dep[:gem], :default => { :mgem => dep[:gem] } }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
gem_table[spec.name] = spec
|
gem_table[spec.name] = spec
|
||||||
end
|
end
|
||||||
@@ -455,5 +454,6 @@ module MRuby
|
|||||||
def new(&block); block.call(self); end
|
def new(&block); block.call(self); end
|
||||||
def config=(obj); @config = obj; end
|
def config=(obj); @config = obj; end
|
||||||
def gem(gemdir, &block); @config.gem(gemdir, &block); end
|
def gem(gemdir, &block); @config.gem(gemdir, &block); end
|
||||||
|
def gembox(gemfile); @config.gembox(gemfile); end
|
||||||
end # GemBox
|
end # GemBox
|
||||||
end # MRuby
|
end # MRuby
|
||||||
@@ -7,6 +7,10 @@
|
|||||||
require 'getoptlong'
|
require 'getoptlong'
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
|
|
||||||
|
$rake_fiber_table = {}
|
||||||
|
$rake_jobs = 1
|
||||||
|
$rake_failed = []
|
||||||
|
|
||||||
class String
|
class String
|
||||||
def ext(newext='')
|
def ext(newext='')
|
||||||
return self.dup if ['.', '..'].include? self
|
return self.dup if ['.', '..'].include? self
|
||||||
@@ -86,14 +90,36 @@ module MiniRake
|
|||||||
@name.to_s
|
@name.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
# Invoke the task if it is needed. Prerequites are invoked first.
|
def done?; @done end
|
||||||
|
def running?; @running end
|
||||||
|
|
||||||
|
# Invoke the task if it is needed. Prerequisites are invoked first.
|
||||||
def invoke
|
def invoke
|
||||||
puts "Invoke #{name} (already=[#{@already_invoked}], needed=[#{needed?}])" if $trace
|
puts "Invoke #{name} (already=[#{@already_invoked}], needed=[#{needed?}])" if $trace
|
||||||
return if @already_invoked
|
return if @already_invoked
|
||||||
@already_invoked = true
|
|
||||||
prerequisites = @prerequisites.collect{ |n| n.is_a?(Proc) ? n.call(name) : n }.flatten
|
prerequisites = @prerequisites.collect{ |n| n.is_a?(Proc) ? n.call(name) : n }.flatten
|
||||||
prerequisites.each { |n| Task[n].invoke }
|
prerequisites.each do |n|
|
||||||
execute if needed?
|
t = Task[n]
|
||||||
|
unless t.done?
|
||||||
|
return prerequisites.select{|v| v = Task[v]; v && (!v.done? || !v.running?) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@already_invoked = true
|
||||||
|
|
||||||
|
if needed?
|
||||||
|
@running = true
|
||||||
|
if $rake_root_fiber
|
||||||
|
return Fiber.new do
|
||||||
|
self.execute
|
||||||
|
$rake_root_fiber.transfer
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.execute
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@done = true
|
||||||
end
|
end
|
||||||
|
|
||||||
# Execute the actions associated with this task.
|
# Execute the actions associated with this task.
|
||||||
@@ -103,6 +129,8 @@ module MiniRake
|
|||||||
unless $dryrun
|
unless $dryrun
|
||||||
@actions.each { |act| act.call(self) }
|
@actions.each { |act| act.call(self) }
|
||||||
end
|
end
|
||||||
|
@done = true
|
||||||
|
@running = false
|
||||||
end
|
end
|
||||||
|
|
||||||
# Is this task needed?
|
# Is this task needed?
|
||||||
@@ -281,7 +309,19 @@ module MiniRake
|
|||||||
# Run the system command +cmd+.
|
# Run the system command +cmd+.
|
||||||
def sh(cmd)
|
def sh(cmd)
|
||||||
puts cmd if $verbose
|
puts cmd if $verbose
|
||||||
system(cmd) or fail "Command Failed: [#{cmd}]"
|
|
||||||
|
if !$rake_root_fiber || Fiber.current == $rake_root_fiber
|
||||||
|
system(cmd) or fail "Command Failed: [#{cmd}]"
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
pid = Process.spawn(cmd)
|
||||||
|
$rake_fiber_table[pid] = {
|
||||||
|
fiber: Fiber.current,
|
||||||
|
command: cmd,
|
||||||
|
process_waiter: Process.detach(pid)
|
||||||
|
}
|
||||||
|
$rake_root_fiber.transfer
|
||||||
end
|
end
|
||||||
|
|
||||||
def desc(text)
|
def desc(text)
|
||||||
@@ -329,7 +369,9 @@ class RakeApp
|
|||||||
['--verbose', '-v', GetoptLong::NO_ARGUMENT,
|
['--verbose', '-v', GetoptLong::NO_ARGUMENT,
|
||||||
"Log message to standard output."],
|
"Log message to standard output."],
|
||||||
['--directory', '-C', GetoptLong::REQUIRED_ARGUMENT,
|
['--directory', '-C', GetoptLong::REQUIRED_ARGUMENT,
|
||||||
"Change executing directory of rakefiles."]
|
"Change executing directory of rakefiles."],
|
||||||
|
['--jobs', '-j', GetoptLong::REQUIRED_ARGUMENT,
|
||||||
|
'Execute rake with parallel jobs.']
|
||||||
]
|
]
|
||||||
|
|
||||||
# Create a RakeApp object.
|
# Create a RakeApp object.
|
||||||
@@ -422,6 +464,8 @@ class RakeApp
|
|||||||
exit
|
exit
|
||||||
when '--directory'
|
when '--directory'
|
||||||
Dir.chdir value
|
Dir.chdir value
|
||||||
|
when '--jobs'
|
||||||
|
$rake_jobs = [value.to_i, 1].max
|
||||||
else
|
else
|
||||||
fail "Unknown option: #{opt}"
|
fail "Unknown option: #{opt}"
|
||||||
end
|
end
|
||||||
@@ -438,6 +482,12 @@ class RakeApp
|
|||||||
# Run the +rake+ application.
|
# Run the +rake+ application.
|
||||||
def run
|
def run
|
||||||
handle_options
|
handle_options
|
||||||
|
|
||||||
|
if $rake_root_fiber
|
||||||
|
require 'fiber'
|
||||||
|
$rake_root_fiber = Fiber.current
|
||||||
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
here = Dir.pwd
|
here = Dir.pwd
|
||||||
while ! have_rakefile
|
while ! have_rakefile
|
||||||
@@ -447,12 +497,12 @@ class RakeApp
|
|||||||
end
|
end
|
||||||
here = Dir.pwd
|
here = Dir.pwd
|
||||||
end
|
end
|
||||||
tasks = []
|
root_tasks = []
|
||||||
ARGV.each do |task_name|
|
ARGV.each do |task_name|
|
||||||
if /^(\w+)=(.*)/.match(task_name)
|
if /^(\w+)=(.*)/.match(task_name)
|
||||||
ENV[$1] = $2
|
ENV[$1] = $2
|
||||||
else
|
else
|
||||||
tasks << task_name
|
root_tasks << task_name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
puts "(in #{Dir.pwd})"
|
puts "(in #{Dir.pwd})"
|
||||||
@@ -461,22 +511,93 @@ class RakeApp
|
|||||||
if $show_tasks
|
if $show_tasks
|
||||||
display_tasks
|
display_tasks
|
||||||
else
|
else
|
||||||
tasks.push("default") if tasks.size == 0
|
root_tasks.push("default") if root_tasks.empty?
|
||||||
tasks.each do |task_name|
|
# revese tasks for popping
|
||||||
MiniRake::Task[task_name].invoke
|
root_tasks.reverse!
|
||||||
|
|
||||||
|
tasks = []
|
||||||
|
until root_tasks.empty?
|
||||||
|
root_name = root_tasks.pop
|
||||||
|
tasks << root_name
|
||||||
|
until tasks.empty?
|
||||||
|
task_name = tasks.pop
|
||||||
|
t = MiniRake::Task[task_name]
|
||||||
|
f = t.invoke
|
||||||
|
|
||||||
|
# append additional tasks to task queue
|
||||||
|
if f.kind_of?(Array)
|
||||||
|
tasks.push(*f)
|
||||||
|
tasks.uniq!
|
||||||
|
end
|
||||||
|
|
||||||
|
unless f.kind_of? Fiber
|
||||||
|
tasks.insert 0, task_name unless t.done?
|
||||||
|
if root_name == task_name
|
||||||
|
wait_process
|
||||||
|
end
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
wait_process while $rake_fiber_table.size >= $rake_jobs
|
||||||
|
|
||||||
|
f.transfer
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
wait_process until $rake_fiber_table.empty?
|
||||||
end
|
end
|
||||||
rescue Exception => ex
|
rescue Exception => e
|
||||||
puts "rake aborted!"
|
begin
|
||||||
|
$rake_failed << e
|
||||||
|
wait_process until $rake_fiber_table.empty?
|
||||||
|
rescue Exception => next_e
|
||||||
|
e = next_e
|
||||||
|
retry
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return if $rake_failed.empty?
|
||||||
|
|
||||||
|
puts "rake aborted!"
|
||||||
|
$rake_failed.each do |ex|
|
||||||
puts ex.message
|
puts ex.message
|
||||||
if $trace
|
if $trace || $verbose
|
||||||
puts ex.backtrace.join("\n")
|
puts ex.backtrace.join("\n")
|
||||||
else
|
else
|
||||||
puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
|
puts ex.backtrace.find {|str| str =~ /#{@rakefile}/ } || ""
|
||||||
end
|
end
|
||||||
exit 1
|
|
||||||
end
|
end
|
||||||
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def wait_process(count = 0)
|
||||||
|
dur = [0.0001 * (10 ** count), 1].min
|
||||||
|
sleep dur
|
||||||
|
|
||||||
|
exited = []
|
||||||
|
$rake_fiber_table.each do |pid, v|
|
||||||
|
exited << pid unless v[:process_waiter].alive?
|
||||||
|
end
|
||||||
|
|
||||||
|
exited.each do |pid|
|
||||||
|
ent = $rake_fiber_table.delete pid
|
||||||
|
st = ent[:process_waiter].value
|
||||||
|
|
||||||
|
# ignore process that isn't created by `sh` method
|
||||||
|
return if ent.nil?
|
||||||
|
|
||||||
|
if st.exitstatus != 0
|
||||||
|
raise "Command Failed: [#{ent[:command]}]"
|
||||||
|
end
|
||||||
|
|
||||||
|
fail 'task scheduling bug!' if $rake_fiber_table.size >= $rake_jobs
|
||||||
|
|
||||||
|
ent[:fiber].transfer
|
||||||
|
end
|
||||||
|
|
||||||
|
wait_process(count + 1) if !$rake_fiber_table.empty? && exited.empty?
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if __FILE__ == $0 then
|
if __FILE__ == $0 then
|
||||||
|
|||||||
@@ -1,4 +1,13 @@
|
|||||||
MRuby::GemBox.new do |conf|
|
MRuby::GemBox.new do |conf|
|
||||||
|
# Meta-programming features
|
||||||
|
conf.gem :core => "mruby-metaprog"
|
||||||
|
|
||||||
|
# Use standard IO/File class
|
||||||
|
conf.gem :core => "mruby-io"
|
||||||
|
|
||||||
|
# Use standard Array#pack, String#unpack methods
|
||||||
|
conf.gem :core => "mruby-pack"
|
||||||
|
|
||||||
# Use standard Kernel#sprintf method
|
# Use standard Kernel#sprintf method
|
||||||
conf.gem :core => "mruby-sprintf"
|
conf.gem :core => "mruby-sprintf"
|
||||||
|
|
||||||
@@ -14,6 +23,9 @@ MRuby::GemBox.new do |conf|
|
|||||||
# Use standard Struct class
|
# Use standard Struct class
|
||||||
conf.gem :core => "mruby-struct"
|
conf.gem :core => "mruby-struct"
|
||||||
|
|
||||||
|
# Use Comparable module extension
|
||||||
|
conf.gem :core => "mruby-compar-ext"
|
||||||
|
|
||||||
# Use Enumerable module extension
|
# Use Enumerable module extension
|
||||||
conf.gem :core => "mruby-enum-ext"
|
conf.gem :core => "mruby-enum-ext"
|
||||||
|
|
||||||
|
|||||||
@@ -2,4 +2,5 @@ MRuby::Gem::Specification.new('mruby-array-ext') do |spec|
|
|||||||
spec.license = 'MIT'
|
spec.license = 'MIT'
|
||||||
spec.author = 'mruby developers'
|
spec.author = 'mruby developers'
|
||||||
spec.summary = 'Array class extension'
|
spec.summary = 'Array class extension'
|
||||||
|
spec.add_test_dependency 'mruby-enumerator', core: 'mruby-enumerator'
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,29 +1,4 @@
|
|||||||
class Array
|
class Array
|
||||||
##
|
|
||||||
# call-seq:
|
|
||||||
# Array.try_convert(obj) -> array or nil
|
|
||||||
#
|
|
||||||
# Tries to convert +obj+ into an array, using +to_ary+ method.
|
|
||||||
# converted array or +nil+ if +obj+ cannot be converted for any reason.
|
|
||||||
# This method can be used to check if an argument is an array.
|
|
||||||
#
|
|
||||||
# Array.try_convert([1]) #=> [1]
|
|
||||||
# Array.try_convert("1") #=> nil
|
|
||||||
#
|
|
||||||
# if tmp = Array.try_convert(arg)
|
|
||||||
# # the argument is an array
|
|
||||||
# elsif tmp = String.try_convert(arg)
|
|
||||||
# # the argument is a string
|
|
||||||
# end
|
|
||||||
#
|
|
||||||
def self.try_convert(obj)
|
|
||||||
if obj.respond_to?(:to_ary)
|
|
||||||
obj.to_ary
|
|
||||||
else
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# call-seq:
|
# call-seq:
|
||||||
# ary.uniq! -> ary or nil
|
# ary.uniq! -> ary or nil
|
||||||
@@ -41,23 +16,19 @@ class Array
|
|||||||
# c.uniq! { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]
|
# c.uniq! { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]
|
||||||
#
|
#
|
||||||
def uniq!(&block)
|
def uniq!(&block)
|
||||||
ary = self.dup
|
hash = {}
|
||||||
result = []
|
|
||||||
if block
|
if block
|
||||||
hash = {}
|
self.each do |val|
|
||||||
while ary.size > 0
|
|
||||||
val = ary.shift
|
|
||||||
key = block.call(val)
|
key = block.call(val)
|
||||||
hash[key] = val unless hash.has_key?(key)
|
hash[key] = val unless hash.key?(key)
|
||||||
end
|
|
||||||
hash.each_value do |value|
|
|
||||||
result << value
|
|
||||||
end
|
end
|
||||||
|
result = hash.values
|
||||||
else
|
else
|
||||||
while ary.size > 0
|
hash = {}
|
||||||
result << ary.shift
|
self.each do |val|
|
||||||
ary.delete(result.last)
|
hash[val] = val
|
||||||
end
|
end
|
||||||
|
result = hash.keys
|
||||||
end
|
end
|
||||||
if result.size == self.size
|
if result.size == self.size
|
||||||
nil
|
nil
|
||||||
@@ -81,11 +52,7 @@ class Array
|
|||||||
#
|
#
|
||||||
def uniq(&block)
|
def uniq(&block)
|
||||||
ary = self.dup
|
ary = self.dup
|
||||||
if block
|
ary.uniq!(&block)
|
||||||
ary.uniq!(&block)
|
|
||||||
else
|
|
||||||
ary.uniq!
|
|
||||||
end
|
|
||||||
ary
|
ary
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -105,8 +72,19 @@ class Array
|
|||||||
|
|
||||||
hash = {}
|
hash = {}
|
||||||
array = []
|
array = []
|
||||||
elem.each { |x| hash[x] = true }
|
idx = 0
|
||||||
self.each { |x| array << x unless hash[x] }
|
len = elem.size
|
||||||
|
while idx < len
|
||||||
|
hash[elem[idx]] = true
|
||||||
|
idx += 1
|
||||||
|
end
|
||||||
|
idx = 0
|
||||||
|
len = size
|
||||||
|
while idx < len
|
||||||
|
v = self[idx]
|
||||||
|
array << v unless hash[v]
|
||||||
|
idx += 1
|
||||||
|
end
|
||||||
array
|
array
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -127,6 +105,25 @@ class Array
|
|||||||
ary.uniq! or ary
|
ary.uniq! or ary
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# call-seq:
|
||||||
|
# ary.union(other_ary,...) -> new_ary
|
||||||
|
#
|
||||||
|
# Set Union---Returns a new array by joining this array with
|
||||||
|
# <i>other_ary</i>, removing duplicates.
|
||||||
|
#
|
||||||
|
# ["a", "b", "c"].union(["c", "d", "a"], ["a", "c", "e"])
|
||||||
|
# #=> ["a", "b", "c", "d", "e"]
|
||||||
|
#
|
||||||
|
def union(*args)
|
||||||
|
ary = self.dup
|
||||||
|
args.each do |x|
|
||||||
|
ary.concat(x)
|
||||||
|
ary.uniq!
|
||||||
|
end
|
||||||
|
ary
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# call-seq:
|
# call-seq:
|
||||||
# ary & other_ary -> new_ary
|
# ary & other_ary -> new_ary
|
||||||
@@ -141,12 +138,21 @@ class Array
|
|||||||
|
|
||||||
hash = {}
|
hash = {}
|
||||||
array = []
|
array = []
|
||||||
elem.each{|v| hash[v] = true }
|
idx = 0
|
||||||
self.each do |v|
|
len = elem.size
|
||||||
|
while idx < len
|
||||||
|
hash[elem[idx]] = true
|
||||||
|
idx += 1
|
||||||
|
end
|
||||||
|
idx = 0
|
||||||
|
len = size
|
||||||
|
while idx < len
|
||||||
|
v = self[idx]
|
||||||
if hash[v]
|
if hash[v]
|
||||||
array << v
|
array << v
|
||||||
hash.delete v
|
hash.delete v
|
||||||
end
|
end
|
||||||
|
idx += 1
|
||||||
end
|
end
|
||||||
array
|
array
|
||||||
end
|
end
|
||||||
@@ -169,15 +175,9 @@ class Array
|
|||||||
# a.flatten(1) #=> [1, 2, 3, [4, 5]]
|
# a.flatten(1) #=> [1, 2, 3, [4, 5]]
|
||||||
#
|
#
|
||||||
def flatten(depth=nil)
|
def flatten(depth=nil)
|
||||||
ar = []
|
res = dup
|
||||||
self.each do |e|
|
res.flatten! depth
|
||||||
if e.is_a?(Array) && (depth.nil? || depth > 0)
|
res
|
||||||
ar += e.flatten(depth.nil? ? nil : depth - 1)
|
|
||||||
else
|
|
||||||
ar << e
|
|
||||||
end
|
|
||||||
end
|
|
||||||
ar
|
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -200,13 +200,17 @@ class Array
|
|||||||
def flatten!(depth=nil)
|
def flatten!(depth=nil)
|
||||||
modified = false
|
modified = false
|
||||||
ar = []
|
ar = []
|
||||||
self.each do |e|
|
idx = 0
|
||||||
|
len = size
|
||||||
|
while idx < len
|
||||||
|
e = self[idx]
|
||||||
if e.is_a?(Array) && (depth.nil? || depth > 0)
|
if e.is_a?(Array) && (depth.nil? || depth > 0)
|
||||||
ar += e.flatten(depth.nil? ? nil : depth - 1)
|
ar += e.flatten(depth.nil? ? nil : depth - 1)
|
||||||
modified = true
|
modified = true
|
||||||
else
|
else
|
||||||
ar << e
|
ar << e
|
||||||
end
|
end
|
||||||
|
idx += 1
|
||||||
end
|
end
|
||||||
if modified
|
if modified
|
||||||
self.replace(ar)
|
self.replace(ar)
|
||||||
@@ -252,7 +256,7 @@ class Array
|
|||||||
|
|
||||||
# for efficiency
|
# for efficiency
|
||||||
def reverse_each(&block)
|
def reverse_each(&block)
|
||||||
return to_enum :reverse_each unless block_given?
|
return to_enum :reverse_each unless block
|
||||||
|
|
||||||
i = self.size - 1
|
i = self.size - 1
|
||||||
while i>=0
|
while i>=0
|
||||||
@@ -287,7 +291,7 @@ class Array
|
|||||||
# #=> "100 is out of bounds"
|
# #=> "100 is out of bounds"
|
||||||
#
|
#
|
||||||
|
|
||||||
def fetch(n=nil, ifnone=NONE, &block)
|
def fetch(n, ifnone=NONE, &block)
|
||||||
warn "block supersedes default value argument" if !n.nil? && ifnone != NONE && block
|
warn "block supersedes default value argument" if !n.nil? && ifnone != NONE && block
|
||||||
|
|
||||||
idx = n
|
idx = n
|
||||||
@@ -474,7 +478,7 @@ class Array
|
|||||||
# scores.delete_if {|score| score < 80 } #=> [97]
|
# scores.delete_if {|score| score < 80 } #=> [97]
|
||||||
|
|
||||||
def delete_if(&block)
|
def delete_if(&block)
|
||||||
return to_enum :delete_if unless block_given?
|
return to_enum :delete_if unless block
|
||||||
|
|
||||||
idx = 0
|
idx = 0
|
||||||
while idx < self.size do
|
while idx < self.size do
|
||||||
@@ -503,7 +507,7 @@ class Array
|
|||||||
# If no block is given, an Enumerator is returned instead.
|
# If no block is given, an Enumerator is returned instead.
|
||||||
|
|
||||||
def reject!(&block)
|
def reject!(&block)
|
||||||
return to_enum :reject! unless block_given?
|
return to_enum :reject! unless block
|
||||||
|
|
||||||
len = self.size
|
len = self.size
|
||||||
idx = 0
|
idx = 0
|
||||||
@@ -593,33 +597,60 @@ class Array
|
|||||||
# undefined which value is actually picked up at each iteration.
|
# undefined which value is actually picked up at each iteration.
|
||||||
|
|
||||||
def bsearch(&block)
|
def bsearch(&block)
|
||||||
return to_enum :bsearch unless block_given?
|
return to_enum :bsearch unless block
|
||||||
|
|
||||||
|
if idx = bsearch_index(&block)
|
||||||
|
self[idx]
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# call-seq:
|
||||||
|
# ary.bsearch_index {|x| block } -> int or nil
|
||||||
|
#
|
||||||
|
# By using binary search, finds an index of a value from this array which
|
||||||
|
# meets the given condition in O(log n) where n is the size of the array.
|
||||||
|
#
|
||||||
|
# It supports two modes, depending on the nature of the block and they are
|
||||||
|
# exactly the same as in the case of #bsearch method with the only difference
|
||||||
|
# being that this method returns the index of the element instead of the
|
||||||
|
# element itself. For more details consult the documentation for #bsearch.
|
||||||
|
|
||||||
|
def bsearch_index(&block)
|
||||||
|
return to_enum :bsearch_index unless block
|
||||||
|
|
||||||
low = 0
|
low = 0
|
||||||
high = self.size
|
high = size
|
||||||
satisfied = false
|
satisfied = false
|
||||||
|
|
||||||
while low < high
|
while low < high
|
||||||
mid = low + ((high - low) / 2).truncate
|
mid = ((low+high)/2).truncate
|
||||||
val = self[mid]
|
res = block.call self[mid]
|
||||||
v = block.call(val)
|
|
||||||
if v.is_a?(Integer)
|
case res
|
||||||
return val if v == 0
|
when 0 # find-any mode: Found!
|
||||||
smaller = v < 0
|
return mid
|
||||||
elsif v == true
|
when Numeric # find-any mode: Continue...
|
||||||
|
in_lower_half = res < 0
|
||||||
|
when true # find-min mode
|
||||||
|
in_lower_half = true
|
||||||
satisfied = true
|
satisfied = true
|
||||||
smaller = true
|
when false, nil # find-min mode
|
||||||
elsif v == false || v.nil?
|
in_lower_half = false
|
||||||
smaller = false
|
else
|
||||||
|
raise TypeError, 'invalid block result (must be numeric, true, false or nil)'
|
||||||
end
|
end
|
||||||
if smaller
|
|
||||||
|
if in_lower_half
|
||||||
high = mid
|
high = mid
|
||||||
else
|
else
|
||||||
low = mid + 1
|
low = mid + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return nil if low == self.size
|
|
||||||
return nil unless satisfied
|
satisfied ? low : nil
|
||||||
self[low]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -640,7 +671,7 @@ class Array
|
|||||||
# scores.delete_if {|score| score < 80 } #=> [97]
|
# scores.delete_if {|score| score < 80 } #=> [97]
|
||||||
|
|
||||||
def delete_if(&block)
|
def delete_if(&block)
|
||||||
return to_enum :delete_if unless block_given?
|
return to_enum :delete_if unless block
|
||||||
|
|
||||||
idx = 0
|
idx = 0
|
||||||
while idx < self.size do
|
while idx < self.size do
|
||||||
@@ -669,7 +700,7 @@ class Array
|
|||||||
# a.keep_if { |val| val > 3 } #=> [4, 5]
|
# a.keep_if { |val| val > 3 } #=> [4, 5]
|
||||||
|
|
||||||
def keep_if(&block)
|
def keep_if(&block)
|
||||||
return to_enum :keep_if unless block_given?
|
return to_enum :keep_if unless block
|
||||||
|
|
||||||
idx = 0
|
idx = 0
|
||||||
len = self.size
|
len = self.size
|
||||||
@@ -698,13 +729,17 @@ class Array
|
|||||||
# If no block is given, an Enumerator is returned instead.
|
# If no block is given, an Enumerator is returned instead.
|
||||||
|
|
||||||
def select!(&block)
|
def select!(&block)
|
||||||
return to_enum :select! unless block_given?
|
return to_enum :select! unless block
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
self.each do |x|
|
idx = 0
|
||||||
result << x if block.call(x)
|
len = size
|
||||||
|
while idx < len
|
||||||
|
elem = self[idx]
|
||||||
|
result << elem if block.call(elem)
|
||||||
|
idx += 1
|
||||||
end
|
end
|
||||||
return nil if self.size == result.size
|
return nil if len == result.size
|
||||||
self.replace(result)
|
self.replace(result)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -726,8 +761,9 @@ class Array
|
|||||||
|
|
||||||
if block
|
if block
|
||||||
idx = 0
|
idx = 0
|
||||||
self.each do |*e|
|
len = size
|
||||||
return idx if block.call(*e)
|
while idx < len
|
||||||
|
return idx if block.call self[idx]
|
||||||
idx += 1
|
idx += 1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@@ -736,16 +772,6 @@ class Array
|
|||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
|
||||||
# call-seq:
|
|
||||||
# ary.to_ary -> ary
|
|
||||||
#
|
|
||||||
# Returns +self+.
|
|
||||||
#
|
|
||||||
def to_ary
|
|
||||||
self
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# call-seq:
|
# call-seq:
|
||||||
# ary.dig(idx, ...) -> object
|
# ary.dig(idx, ...) -> object
|
||||||
@@ -762,4 +788,153 @@ class Array
|
|||||||
n
|
n
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# call-seq:
|
||||||
|
# ary.permutation { |p| block } -> ary
|
||||||
|
# ary.permutation -> Enumerator
|
||||||
|
# ary.permutation(n) { |p| block } -> ary
|
||||||
|
# ary.permutation(n) -> Enumerator
|
||||||
|
#
|
||||||
|
# When invoked with a block, yield all permutations of length +n+ of the
|
||||||
|
# elements of the array, then return the array itself.
|
||||||
|
#
|
||||||
|
# If +n+ is not specified, yield all permutations of all elements.
|
||||||
|
#
|
||||||
|
# The implementation makes no guarantees about the order in which the
|
||||||
|
# permutations are yielded.
|
||||||
|
#
|
||||||
|
# If no block is given, an Enumerator is returned instead.
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
#
|
||||||
|
# a = [1, 2, 3]
|
||||||
|
# a.permutation.to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
|
||||||
|
# a.permutation(1).to_a #=> [[1],[2],[3]]
|
||||||
|
# a.permutation(2).to_a #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
|
||||||
|
# a.permutation(3).to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
|
||||||
|
# a.permutation(0).to_a #=> [[]] # one permutation of length 0
|
||||||
|
# a.permutation(4).to_a #=> [] # no permutations of length 4
|
||||||
|
def permutation(n=self.size, &block)
|
||||||
|
size = self.size
|
||||||
|
return to_enum(:permutation, n) unless block
|
||||||
|
return if n > size
|
||||||
|
if n == 0
|
||||||
|
yield []
|
||||||
|
else
|
||||||
|
i = 0
|
||||||
|
while i<size
|
||||||
|
result = [self[i]]
|
||||||
|
if n-1 > 0
|
||||||
|
ary = self[0...i] + self[i+1..-1]
|
||||||
|
ary.permutation(n-1) do |c|
|
||||||
|
yield result + c
|
||||||
|
end
|
||||||
|
else
|
||||||
|
yield result
|
||||||
|
end
|
||||||
|
i += 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# call-seq:
|
||||||
|
# ary.combination(n) { |c| block } -> ary
|
||||||
|
# ary.combination(n) -> Enumerator
|
||||||
|
#
|
||||||
|
# When invoked with a block, yields all combinations of length +n+ of elements
|
||||||
|
# from the array and then returns the array itself.
|
||||||
|
#
|
||||||
|
# The implementation makes no guarantees about the order in which the
|
||||||
|
# combinations are yielded.
|
||||||
|
#
|
||||||
|
# If no block is given, an Enumerator is returned instead.
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
#
|
||||||
|
# a = [1, 2, 3, 4]
|
||||||
|
# a.combination(1).to_a #=> [[1],[2],[3],[4]]
|
||||||
|
# a.combination(2).to_a #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
|
||||||
|
# a.combination(3).to_a #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
|
||||||
|
# a.combination(4).to_a #=> [[1,2,3,4]]
|
||||||
|
# a.combination(0).to_a #=> [[]] # one combination of length 0
|
||||||
|
# a.combination(5).to_a #=> [] # no combinations of length 5
|
||||||
|
|
||||||
|
def combination(n, &block)
|
||||||
|
size = self.size
|
||||||
|
return to_enum(:combination, n) unless block
|
||||||
|
return if n > size
|
||||||
|
if n == 0
|
||||||
|
yield []
|
||||||
|
elsif n == 1
|
||||||
|
i = 0
|
||||||
|
while i<size
|
||||||
|
yield [self[i]]
|
||||||
|
i += 1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
i = 0
|
||||||
|
while i<size
|
||||||
|
result = [self[i]]
|
||||||
|
self[i+1..-1].combination(n-1) do |c|
|
||||||
|
yield result + c
|
||||||
|
end
|
||||||
|
i += 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# call-seq:
|
||||||
|
# ary.transpose -> new_ary
|
||||||
|
#
|
||||||
|
# Assumes that self is an array of arrays and transposes the rows and columns.
|
||||||
|
#
|
||||||
|
# If the length of the subarrays don't match, an IndexError is raised.
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
#
|
||||||
|
# a = [[1,2], [3,4], [5,6]]
|
||||||
|
# a.transpose #=> [[1, 3, 5], [2, 4, 6]]
|
||||||
|
|
||||||
|
def transpose
|
||||||
|
return [] if empty?
|
||||||
|
|
||||||
|
column_count = nil
|
||||||
|
self.each do |row|
|
||||||
|
raise TypeError unless row.is_a?(Array)
|
||||||
|
column_count ||= row.count
|
||||||
|
raise IndexError, 'element size differs' unless column_count == row.count
|
||||||
|
end
|
||||||
|
|
||||||
|
Array.new(column_count) do |column_index|
|
||||||
|
self.map { |row| row[column_index] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# call-seq:
|
||||||
|
# ary.to_h -> Hash
|
||||||
|
# ary.to_h{|item| ... } -> Hash
|
||||||
|
#
|
||||||
|
# Returns the result of interpreting <i>aray</i> as an array of
|
||||||
|
# <tt>[key, value]</tt> pairs. If a block is given, it should
|
||||||
|
# return <tt>[key, value]</tt> pairs to construct a hash.
|
||||||
|
#
|
||||||
|
# [[:foo, :bar], [1, 2]].to_h
|
||||||
|
# # => {:foo => :bar, 1 => 2}
|
||||||
|
# [1, 2].to_h{|x| [x, x*2]}
|
||||||
|
# # => {1 => 2, 2 => 4}
|
||||||
|
#
|
||||||
|
def to_h(&blk)
|
||||||
|
h = {}
|
||||||
|
self.each do |v|
|
||||||
|
v = blk.call(v) if blk
|
||||||
|
raise TypeError, "wrong element type #{v.class}" unless Array === v
|
||||||
|
raise ArgumentError, "wrong array length (expected 2, was #{v.length})" unless v.length == 2
|
||||||
|
h[v[0]] = v[1]
|
||||||
|
end
|
||||||
|
h
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -106,48 +106,6 @@ mrb_ary_values_at(mrb_state *mrb, mrb_value self)
|
|||||||
return mrb_get_values_at(mrb, self, RARRAY_LEN(self), argc, argv, mrb_ary_ref);
|
return mrb_get_values_at(mrb, self, RARRAY_LEN(self), argc, argv, mrb_ary_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* call-seq:
|
|
||||||
* ary.to_h -> Hash
|
|
||||||
*
|
|
||||||
* Returns the result of interpreting <i>aray</i> as an array of
|
|
||||||
* <tt>[key, value]</tt> paris.
|
|
||||||
*
|
|
||||||
* [[:foo, :bar], [1, 2]].to_h
|
|
||||||
* # => {:foo => :bar, 1 => 2}
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
static mrb_value
|
|
||||||
mrb_ary_to_h(mrb_state *mrb, mrb_value ary)
|
|
||||||
{
|
|
||||||
mrb_int i;
|
|
||||||
mrb_value v, hash;
|
|
||||||
|
|
||||||
hash = mrb_hash_new_capa(mrb, 0);
|
|
||||||
|
|
||||||
for (i = 0; i < RARRAY_LEN(ary); ++i) {
|
|
||||||
v = mrb_check_array_type(mrb, RARRAY_PTR(ary)[i]);
|
|
||||||
|
|
||||||
if (mrb_nil_p(v)) {
|
|
||||||
mrb_raisef(mrb, E_TYPE_ERROR, "wrong element type %S at %S (expected array)",
|
|
||||||
mrb_str_new_cstr(mrb, mrb_obj_classname(mrb, ary_elt(ary, i))),
|
|
||||||
mrb_fixnum_value(i)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RARRAY_LEN(v) != 2) {
|
|
||||||
mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong array length at %S (expected 2, was %S)",
|
|
||||||
mrb_fixnum_value(i),
|
|
||||||
mrb_fixnum_value(RARRAY_LEN(v))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
mrb_hash_set(mrb, hash, RARRAY_PTR(v)[0], RARRAY_PTR(v)[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
@@ -174,18 +132,20 @@ static mrb_value
|
|||||||
mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
|
mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
|
||||||
{
|
{
|
||||||
struct RArray *a = mrb_ary_ptr(self);
|
struct RArray *a = mrb_ary_ptr(self);
|
||||||
mrb_int i, j, k, len;
|
mrb_int i, j, k, len, alen;
|
||||||
mrb_value index;
|
|
||||||
mrb_value val;
|
mrb_value val;
|
||||||
mrb_value *ptr;
|
mrb_value *ptr;
|
||||||
mrb_value ary;
|
mrb_value ary;
|
||||||
|
|
||||||
mrb_ary_modify(mrb, a);
|
mrb_ary_modify(mrb, a);
|
||||||
|
|
||||||
if (mrb_get_args(mrb, "o|i", &index, &len) == 1) {
|
if (mrb_get_argc(mrb) == 1) {
|
||||||
|
mrb_value index;
|
||||||
|
|
||||||
|
mrb_get_args(mrb, "o|i", &index, &len);
|
||||||
switch (mrb_type(index)) {
|
switch (mrb_type(index)) {
|
||||||
case MRB_TT_RANGE:
|
case MRB_TT_RANGE:
|
||||||
if (mrb_range_beg_len(mrb, index, &i, &len, a->len, TRUE) == 1) {
|
if (mrb_range_beg_len(mrb, index, &i, &len, ARY_LEN(a), TRUE) == 1) {
|
||||||
goto delete_pos_len;
|
goto delete_pos_len;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -200,27 +160,28 @@ mrb_ary_slice_bang(mrb_state *mrb, mrb_value self)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i = mrb_fixnum(index);
|
mrb_get_args(mrb, "ii", &i, &len);
|
||||||
delete_pos_len:
|
delete_pos_len:
|
||||||
if (i < 0) i += a->len;
|
alen = ARY_LEN(a);
|
||||||
if (i < 0 || a->len < i) return mrb_nil_value();
|
if (i < 0) i += alen;
|
||||||
|
if (i < 0 || alen < i) return mrb_nil_value();
|
||||||
if (len < 0) return mrb_nil_value();
|
if (len < 0) return mrb_nil_value();
|
||||||
if (a->len == i) return mrb_ary_new(mrb);
|
if (alen == i) return mrb_ary_new(mrb);
|
||||||
if (len > a->len - i) len = a->len - i;
|
if (len > alen - i) len = alen - i;
|
||||||
|
|
||||||
ary = mrb_ary_new_capa(mrb, len);
|
ary = mrb_ary_new_capa(mrb, len);
|
||||||
|
ptr = ARY_PTR(a);
|
||||||
for (j = i, k = 0; k < len; ++j, ++k) {
|
for (j = i, k = 0; k < len; ++j, ++k) {
|
||||||
mrb_ary_push(mrb, ary, a->ptr[j]);
|
mrb_ary_push(mrb, ary, ptr[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = a->ptr + i;
|
ptr += i;
|
||||||
for (j = i; j < a->len - len; ++j) {
|
for (j = i; j < alen - len; ++j) {
|
||||||
*ptr = *(ptr+len);
|
*ptr = *(ptr+len);
|
||||||
++ptr;
|
++ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
mrb_ary_resize(mrb, self, a->len - len);
|
mrb_ary_resize(mrb, self, alen - len);
|
||||||
return ary;
|
return ary;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +194,6 @@ mrb_mruby_array_ext_gem_init(mrb_state* mrb)
|
|||||||
mrb_define_method(mrb, a, "at", mrb_ary_at, MRB_ARGS_REQ(1));
|
mrb_define_method(mrb, a, "at", mrb_ary_at, MRB_ARGS_REQ(1));
|
||||||
mrb_define_method(mrb, a, "rassoc", mrb_ary_rassoc, MRB_ARGS_REQ(1));
|
mrb_define_method(mrb, a, "rassoc", mrb_ary_rassoc, MRB_ARGS_REQ(1));
|
||||||
mrb_define_method(mrb, a, "values_at", mrb_ary_values_at, MRB_ARGS_ANY());
|
mrb_define_method(mrb, a, "values_at", mrb_ary_values_at, MRB_ARGS_ANY());
|
||||||
mrb_define_method(mrb, a, "to_h", mrb_ary_to_h, MRB_ARGS_REQ(0));
|
|
||||||
mrb_define_method(mrb, a, "slice!", mrb_ary_slice_bang, MRB_ARGS_ANY());
|
mrb_define_method(mrb, a, "slice!", mrb_ary_slice_bang, MRB_ARGS_ANY());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
##
|
##
|
||||||
# Array(Ext) Test
|
# Array(Ext) Test
|
||||||
|
|
||||||
assert("Array.try_convert") do
|
|
||||||
assert_nil Array.try_convert(0)
|
|
||||||
assert_nil Array.try_convert(nil)
|
|
||||||
assert_equal [], Array.try_convert([])
|
|
||||||
assert_equal [1,2,3], Array.try_convert([1,2,3])
|
|
||||||
end
|
|
||||||
|
|
||||||
assert("Array#assoc") do
|
assert("Array#assoc") do
|
||||||
s1 = [ "colors", "red", "blue", "green" ]
|
s1 = [ "colors", "red", "blue", "green" ]
|
||||||
s2 = [ "letters", "a", "b", "c" ]
|
s2 = [ "letters", "a", "b", "c" ]
|
||||||
@@ -75,6 +68,14 @@ assert("Array#|") do
|
|||||||
assert_equal [1, 2, 3, 1], a
|
assert_equal [1, 2, 3, 1], a
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assert("Array#union") do
|
||||||
|
a = [1, 2, 3, 1]
|
||||||
|
b = [1, 4]
|
||||||
|
c = [1, 5]
|
||||||
|
|
||||||
|
assert_equal [1, 2, 3, 4, 5], a.union(b,c)
|
||||||
|
end
|
||||||
|
|
||||||
assert("Array#&") do
|
assert("Array#&") do
|
||||||
a = [1, 2, 3, 1]
|
a = [1, 2, 3, 1]
|
||||||
b = [1, 4]
|
b = [1, 4]
|
||||||
@@ -228,18 +229,47 @@ end
|
|||||||
|
|
||||||
assert("Array#bsearch") do
|
assert("Array#bsearch") do
|
||||||
# Find minimum mode
|
# Find minimum mode
|
||||||
a = [0, 4, 7, 10, 12]
|
a = [0, 2, 4]
|
||||||
assert_include [4, 7], a.bsearch {|x| x >= 4 }
|
assert_equal 0, a.bsearch{ |x| x >= -1 }
|
||||||
assert_equal 7, a.bsearch {|x| x >= 6 }
|
assert_equal 0, a.bsearch{ |x| x >= 0 }
|
||||||
assert_equal 0, a.bsearch {|x| x >= -1 }
|
assert_equal 2, a.bsearch{ |x| x >= 1 }
|
||||||
assert_nil a.bsearch {|x| x >= 100 }
|
assert_equal 2, a.bsearch{ |x| x >= 2 }
|
||||||
|
assert_equal 4, a.bsearch{ |x| x >= 3 }
|
||||||
|
assert_equal 4, a.bsearch{ |x| x >= 4 }
|
||||||
|
assert_nil a.bsearch{ |x| x >= 5 }
|
||||||
|
|
||||||
# Find any mode
|
# Find any mode
|
||||||
a = [0, 4, 7, 10, 12]
|
a = [0, 4, 8]
|
||||||
assert_include [4, 7], a.bsearch {|x| 1 - (x / 4).truncate }
|
def between(lo, x, hi)
|
||||||
assert_nil a.bsearch {|x| 4 - (x / 2).truncate }
|
if x < lo
|
||||||
assert_equal(nil, a.bsearch {|x| 1 })
|
1
|
||||||
assert_equal(nil, a.bsearch {|x| -1 })
|
elsif x > hi
|
||||||
|
-1
|
||||||
|
else
|
||||||
|
0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
assert_nil a.bsearch{ |x| between(-3, x, -1) }
|
||||||
|
assert_equal 0, a.bsearch{ |x| between(-1, x, 1) }
|
||||||
|
assert_nil a.bsearch{ |x| between( 1, x, 3) }
|
||||||
|
assert_equal 4, a.bsearch{ |x| between( 3, x, 5) }
|
||||||
|
assert_nil a.bsearch{ |x| between( 5, x, 7) }
|
||||||
|
assert_equal 8, a.bsearch{ |x| between( 7, x, 9) }
|
||||||
|
assert_nil a.bsearch{ |x| between( 9, x, 11) }
|
||||||
|
|
||||||
|
assert_equal 0, a.bsearch{ |x| between( 0, x, 3) }
|
||||||
|
assert_equal 4, a.bsearch{ |x| between( 0, x, 4) }
|
||||||
|
assert_equal 4, a.bsearch{ |x| between( 4, x, 8) }
|
||||||
|
assert_equal 8, a.bsearch{ |x| between( 5, x, 8) }
|
||||||
|
|
||||||
|
# Invalid block result
|
||||||
|
assert_raise TypeError, 'invalid block result (must be numeric, true, false or nil)' do
|
||||||
|
a.bsearch{ 'I like to watch the world burn' }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert("Array#bsearch_index") do
|
||||||
|
# tested through Array#bsearch
|
||||||
end
|
end
|
||||||
|
|
||||||
assert("Array#delete_if") do
|
assert("Array#delete_if") do
|
||||||
@@ -301,27 +331,11 @@ assert('Array#to_h') do
|
|||||||
assert_raise(ArgumentError) { [[1]].to_h }
|
assert_raise(ArgumentError) { [[1]].to_h }
|
||||||
end
|
end
|
||||||
|
|
||||||
assert('Array#to_h (Modified)') do
|
|
||||||
class A
|
|
||||||
def to_ary
|
|
||||||
$a.clear
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
$a = [A.new]
|
|
||||||
assert_raise(TypeError) { $a.to_h }
|
|
||||||
end
|
|
||||||
|
|
||||||
assert("Array#index (block)") do
|
assert("Array#index (block)") do
|
||||||
assert_nil (1..10).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
|
assert_nil (1..10).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
|
||||||
assert_equal 34, (1..100).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
|
assert_equal 34, (1..100).to_a.index { |i| i % 5 == 0 and i % 7 == 0 }
|
||||||
end
|
end
|
||||||
|
|
||||||
assert("Array#to_ary") do
|
|
||||||
assert_equal [], [].to_ary
|
|
||||||
assert_equal [1,2,3], [1,2,3].to_ary
|
|
||||||
end
|
|
||||||
|
|
||||||
assert("Array#dig") do
|
assert("Array#dig") do
|
||||||
h = [[[1]], 0]
|
h = [[[1]], 0]
|
||||||
assert_equal(1, h.dig(0, 0, 0))
|
assert_equal(1, h.dig(0, 0, 0))
|
||||||
@@ -352,3 +366,42 @@ assert("Array#slice!") do
|
|||||||
assert_equal(i, [1, 2, 3])
|
assert_equal(i, [1, 2, 3])
|
||||||
assert_equal(j, nil)
|
assert_equal(j, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assert("Array#permutation") do
|
||||||
|
a = [1, 2, 3]
|
||||||
|
assert_equal([[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]],
|
||||||
|
a.permutation.to_a)
|
||||||
|
assert_equal([[1],[2],[3]],
|
||||||
|
a.permutation(1).to_a)
|
||||||
|
assert_equal([[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]],
|
||||||
|
a.permutation(2).to_a)
|
||||||
|
assert_equal([[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]],
|
||||||
|
a.permutation(3).to_a)
|
||||||
|
assert_equal([[]], a.permutation(0).to_a)
|
||||||
|
assert_equal([], a.permutation(4).to_a)
|
||||||
|
end
|
||||||
|
|
||||||
|
assert("Array#combination") do
|
||||||
|
a = [1, 2, 3, 4]
|
||||||
|
assert_equal([[1],[2],[3],[4]],
|
||||||
|
a.combination(1).to_a)
|
||||||
|
assert_equal([[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]],
|
||||||
|
a.combination(2).to_a)
|
||||||
|
assert_equal([[1,2,3],[1,2,4],[1,3,4],[2,3,4]],
|
||||||
|
a.combination(3).to_a)
|
||||||
|
assert_equal([[1,2,3,4]],
|
||||||
|
a.combination(4).to_a)
|
||||||
|
assert_equal([[]], a.combination(0).to_a)
|
||||||
|
assert_equal([], a.combination(5).to_a)
|
||||||
|
end
|
||||||
|
|
||||||
|
assert('Array#transpose') do
|
||||||
|
assert_equal([].transpose, [])
|
||||||
|
assert_equal([[]].transpose, [])
|
||||||
|
assert_equal([[1]].transpose, [[1]])
|
||||||
|
assert_equal([[1,2,3]].transpose, [[1], [2], [3]])
|
||||||
|
assert_equal([[1], [2], [3]].transpose, [[1,2,3]])
|
||||||
|
assert_equal([[1,2], [3,4], [5,6]].transpose, [[1,3,5], [2,4,6]])
|
||||||
|
assert_raise(TypeError) { [1].transpose }
|
||||||
|
assert_raise(IndexError) { [[1], [2,3,4]].transpose }
|
||||||
|
end
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ assert('mruby-bin-debugger(print) error') do
|
|||||||
# test case
|
# test case
|
||||||
tc = []
|
tc = []
|
||||||
tc << {:cmd=>"p (1+2", :exp=>'$1 = SyntaxError'}
|
tc << {:cmd=>"p (1+2", :exp=>'$1 = SyntaxError'}
|
||||||
tc << {:cmd=>"p bar", :exp=>'$2 = NoMethodError'}
|
tc << {:cmd=>"p bar", :exp=>'$2 = (eval):2: undefined method'}
|
||||||
|
|
||||||
BinTest_MrubyBinDebugger.test(src, tc)
|
BinTest_MrubyBinDebugger.test(src, tc)
|
||||||
end
|
end
|
||||||
@@ -317,7 +317,7 @@ TestConstNameSubClass.new.m()
|
|||||||
bp = nil
|
bp = nil
|
||||||
SRC
|
SRC
|
||||||
|
|
||||||
# todo: wait for 'break' to be implimented
|
# todo: wait for 'break' to be implemented
|
||||||
tc = []
|
tc = []
|
||||||
9.times { tc << {:cmd=>"s"} }
|
9.times { tc << {:cmd=>"s"} }
|
||||||
tc << {:cmd=>"p CONST", :exp=>"super class"}
|
tc << {:cmd=>"p CONST", :exp=>"super class"}
|
||||||
@@ -341,13 +341,13 @@ assert('mruby-bin-debugger(print) Literal:Numeric') do
|
|||||||
tc << {:cmd=>"p +0100", :exp=>'$3 = 64'}
|
tc << {:cmd=>"p +0100", :exp=>'$3 = 64'}
|
||||||
tc << {:cmd=>"p 0x100", :exp=>'$4 = 256'}
|
tc << {:cmd=>"p 0x100", :exp=>'$4 = 256'}
|
||||||
tc << {:cmd=>"p 1_234", :exp=>'$5 = 1234'}
|
tc << {:cmd=>"p 1_234", :exp=>'$5 = 1234'}
|
||||||
tc << {:cmd=>"p 0b1000_0000", :exp=>"$6 = #{0b1000_0000.to_s}"}
|
tc << {:cmd=>"p 0b1000_0000", :exp=>"$6 = #{0b1000_0000}"}
|
||||||
tc << {:cmd=>"p 0x1000_0000", :exp=>"$7 = #{0x1000_0000.to_s}"}
|
tc << {:cmd=>"p 0x1000_0000", :exp=>"$7 = #{0x1000_0000}"}
|
||||||
|
|
||||||
tc << {:cmd=>"p 3.14", :exp=>'$8 = 3.14'}
|
tc << {:cmd=>"p 3.14", :exp=>'$8 = 3.14'}
|
||||||
tc << {:cmd=>"p -12.3", :exp=>'$9 = -12.3'}
|
tc << {:cmd=>"p -12.3", :exp=>'$9 = -12.3'}
|
||||||
tc << {:cmd=>"p +12.000", :exp=>'$10 = 12.0'}
|
tc << {:cmd=>"p +12.000", :exp=>'$10 = 12'}
|
||||||
tc << {:cmd=>"p 1e4", :exp=>'$11 = 10000.0'}
|
tc << {:cmd=>"p 1e4", :exp=>'$11 = 10000'}
|
||||||
tc << {:cmd=>"p -0.1e-2", :exp=>'$12 = -0.001'}
|
tc << {:cmd=>"p -0.1e-2", :exp=>'$12 = -0.001'}
|
||||||
|
|
||||||
BinTest_MrubyBinDebugger.test(src, tc)
|
BinTest_MrubyBinDebugger.test(src, tc)
|
||||||
@@ -368,28 +368,28 @@ SRC
|
|||||||
|
|
||||||
tc << {:cmd=>'p "str"', :exp=>'$1 = "str"'}
|
tc << {:cmd=>'p "str"', :exp=>'$1 = "str"'}
|
||||||
tc << {:cmd=>'p "s\tt\rr\n"', :exp=>'$2 = "s\\tt\\rr\\n"'}
|
tc << {:cmd=>'p "s\tt\rr\n"', :exp=>'$2 = "s\\tt\\rr\\n"'}
|
||||||
tc << {:cmd=>'p "\C-a\C-z"', :exp=>'$3 = "\\001\\032"'}
|
tc << {:cmd=>'p "\C-a\C-z"', :exp=>'$3 = "\\x01\\x1a"'}
|
||||||
tc << {:cmd=>'p "#{foo+bar}"', :exp=>'$4 = "foobar"'}
|
tc << {:cmd=>'p "#{foo+bar}"', :exp=>'$4 = "foobar"'}
|
||||||
|
|
||||||
tc << {:cmd=>'p \'str\'', :exp=>'$5 = "str"'}
|
tc << {:cmd=>'p \'str\'', :exp=>'$5 = "str"'}
|
||||||
tc << {:cmd=>'p \'s\\tt\\rr\\n\'', :exp=>'$6 = "s\\\\tt\\\\rr\\\\n"'}
|
tc << {:cmd=>'p \'s\\tt\\rr\\n\'', :exp=>'$6 = "s\\\\tt\\\\rr\\\\n"'}
|
||||||
tc << {:cmd=>'p \'\\C-a\\C-z\'', :exp=>'$7 = "\\\\C-a\\\\C-z"'}
|
tc << {:cmd=>'p \'\\C-a\\C-z\'', :exp=>'$7 = "\\\\C-a\\\\C-z"'}
|
||||||
tc << {:cmd=>'p \'#{foo+bar}\'', :exp=>'$8 = "#{foo+bar}"'}
|
tc << {:cmd=>'p \'#{foo+bar}\'', :exp=>'$8 = "\\#{foo+bar}"'}
|
||||||
|
|
||||||
tc << {:cmd=>'p %!str!', :exp=>'$9 = "str"'}
|
tc << {:cmd=>'p %!str!', :exp=>'$9 = "str"'}
|
||||||
tc << {:cmd=>'p %!s\tt\rr\n!', :exp=>'$10 = "s\\tt\\rr\\n"'}
|
tc << {:cmd=>'p %!s\tt\rr\n!', :exp=>'$10 = "s\\tt\\rr\\n"'}
|
||||||
tc << {:cmd=>'p %!\C-a\C-z!', :exp=>'$11 = "\\001\\032"'}
|
tc << {:cmd=>'p %!\C-a\C-z!', :exp=>'$11 = "\\x01\\x1a"'}
|
||||||
tc << {:cmd=>'p %!#{foo+bar}!', :exp=>'$12 = "foobar"'}
|
tc << {:cmd=>'p %!#{foo+bar}!', :exp=>'$12 = "foobar"'}
|
||||||
|
|
||||||
tc << {:cmd=>'p %Q!str!', :exp=>'$13 = "str"'}
|
tc << {:cmd=>'p %Q!str!', :exp=>'$13 = "str"'}
|
||||||
tc << {:cmd=>'p %Q!s\tt\rr\n!', :exp=>'$14 = "s\\tt\\rr\\n"'}
|
tc << {:cmd=>'p %Q!s\tt\rr\n!', :exp=>'$14 = "s\\tt\\rr\\n"'}
|
||||||
tc << {:cmd=>'p %Q!\C-a\C-z!', :exp=>'$15 = "\\001\\032"'}
|
tc << {:cmd=>'p %Q!\C-a\C-z!', :exp=>'$15 = "\\x01\\x1a"'}
|
||||||
tc << {:cmd=>'p %Q!#{foo+bar}!', :exp=>'$16 = "foobar"'}
|
tc << {:cmd=>'p %Q!#{foo+bar}!', :exp=>'$16 = "foobar"'}
|
||||||
|
|
||||||
tc << {:cmd=>'p %q!str!', :exp=>'$17 = "str"'}
|
tc << {:cmd=>'p %q!str!', :exp=>'$17 = "str"'}
|
||||||
tc << {:cmd=>'p %q!s\\tt\\rr\\n!', :exp=>'$18 = "s\\\\tt\\\\rr\\\\n"'}
|
tc << {:cmd=>'p %q!s\\tt\\rr\\n!', :exp=>'$18 = "s\\\\tt\\\\rr\\\\n"'}
|
||||||
tc << {:cmd=>'p %q!\\C-a\\C-z!', :exp=>'$19 = "\\\\C-a\\\\C-z"'}
|
tc << {:cmd=>'p %q!\\C-a\\C-z!', :exp=>'$19 = "\\\\C-a\\\\C-z"'}
|
||||||
tc << {:cmd=>'p %q!#{foo+bar}!', :exp=>'$20 = "#{foo+bar}"'}
|
tc << {:cmd=>'p %q!#{foo+bar}!', :exp=>'$20 = "\\#{foo+bar}"'}
|
||||||
|
|
||||||
BinTest_MrubyBinDebugger.test(src, tc)
|
BinTest_MrubyBinDebugger.test(src, tc)
|
||||||
end
|
end
|
||||||
@@ -410,7 +410,7 @@ SRC
|
|||||||
tc << {:cmd=>'p []', :exp=>'$1 = []'}
|
tc << {:cmd=>'p []', :exp=>'$1 = []'}
|
||||||
tc << {:cmd=>'p [ 5, 12, 8, 10, ]', :exp=>'$2 = [5, 12, 8, 10]'}
|
tc << {:cmd=>'p [ 5, 12, 8, 10, ]', :exp=>'$2 = [5, 12, 8, 10]'}
|
||||||
tc << {:cmd=>'p [1,2.5,"#{foo+bar}"]', :exp=>'$3 = [1, 2.5, "foobar"]'}
|
tc << {:cmd=>'p [1,2.5,"#{foo+bar}"]', :exp=>'$3 = [1, 2.5, "foobar"]'}
|
||||||
tc << {:cmd=>'p %w[3.14 A\ &\ B #{foo}]', :exp=>'$4 = ["3.14", "A & B", "#{foo}"]'}
|
tc << {:cmd=>'p %w[3.14 A\ &\ B #{foo}]', :exp=>'$4 = ["3.14", "A & B", "\#{foo}"]'}
|
||||||
tc << {:cmd=>'p %W[3.14 A\ &\ B #{foo}]', :exp=>'$5 = ["3.14", "A & B", "foo"]'}
|
tc << {:cmd=>'p %W[3.14 A\ &\ B #{foo}]', :exp=>'$5 = ["3.14", "A & B", "foo"]'}
|
||||||
|
|
||||||
BinTest_MrubyBinDebugger.test(src, tc)
|
BinTest_MrubyBinDebugger.test(src, tc)
|
||||||
@@ -588,7 +588,7 @@ SRC
|
|||||||
tc << {:cmd=>'p foo=[foo,bar,baz]', :exp=>'$2 = ["foo", "bar", "baz"]'}
|
tc << {:cmd=>'p foo=[foo,bar,baz]', :exp=>'$2 = ["foo", "bar", "baz"]'}
|
||||||
|
|
||||||
tc << {:cmd=>'p undefined=-1', :exp=>'$3 = -1'}
|
tc << {:cmd=>'p undefined=-1', :exp=>'$3 = -1'}
|
||||||
tc << {:cmd=>'p "#{undefined}"', :exp=>'$4 = NoMethodError'}
|
tc << {:cmd=>'p "#{undefined}"', :exp=>'$4 = (eval):2: undefined method'}
|
||||||
|
|
||||||
BinTest_MrubyBinDebugger.test(src, tc)
|
BinTest_MrubyBinDebugger.test(src, tc)
|
||||||
end
|
end
|
||||||
@@ -626,7 +626,7 @@ SRC
|
|||||||
tc << {:cmd=>'p [a,b]', :exp=>'$13 = [20, 10]'}
|
tc << {:cmd=>'p [a,b]', :exp=>'$13 = [20, 10]'}
|
||||||
|
|
||||||
tc << {:cmd=>'p undefined=-1', :exp=>'$14 = -1'}
|
tc << {:cmd=>'p undefined=-1', :exp=>'$14 = -1'}
|
||||||
tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = NoMethodError'}
|
tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = (eval):2: undefined method'}
|
||||||
|
|
||||||
BinTest_MrubyBinDebugger.test(src, tc)
|
BinTest_MrubyBinDebugger.test(src, tc)
|
||||||
end
|
end
|
||||||
@@ -694,7 +694,7 @@ SRC
|
|||||||
tc << {:cmd=>'p [a,b]', :exp=>'$13 = [20, 10]'}
|
tc << {:cmd=>'p [a,b]', :exp=>'$13 = [20, 10]'}
|
||||||
|
|
||||||
tc << {:cmd=>'p undefined=-1', :exp=>'$14 = -1'}
|
tc << {:cmd=>'p undefined=-1', :exp=>'$14 = -1'}
|
||||||
tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = NoMethodError'}
|
tc << {:cmd=>'p "#{undefined}"', :exp=>'$15 = (eval):2: undefined method'}
|
||||||
|
|
||||||
BinTest_MrubyBinDebugger.test(src, tc)
|
BinTest_MrubyBinDebugger.test(src, tc)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -112,23 +112,12 @@ check_file_lineno(struct mrb_irep *irep, const char *file, uint16_t lineno)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char*
|
|
||||||
get_class_name(mrb_state *mrb, struct RClass *class_obj)
|
|
||||||
{
|
|
||||||
struct RClass *outer;
|
|
||||||
mrb_sym class_sym;
|
|
||||||
|
|
||||||
outer = mrb_class_outer_module(mrb, class_obj);
|
|
||||||
class_sym = mrb_class_sym(mrb, class_obj, outer);
|
|
||||||
return mrb_sym2name(mrb, class_sym);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t
|
static int32_t
|
||||||
compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *class_obj, mrb_sym method_sym, mrb_bool* isCfunc)
|
compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *class_obj, mrb_sym method_sym, mrb_bool* isCfunc)
|
||||||
{
|
{
|
||||||
const char* class_name;
|
const char* class_name;
|
||||||
const char* method_name;
|
const char* method_name;
|
||||||
struct RProc* m;
|
mrb_method_t m;
|
||||||
struct RClass* sc;
|
struct RClass* sc;
|
||||||
const char* sn;
|
const char* sn;
|
||||||
mrb_sym ssym;
|
mrb_sym ssym;
|
||||||
@@ -139,7 +128,7 @@ compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *cl
|
|||||||
|
|
||||||
method_p = &bp->point.methodpoint;
|
method_p = &bp->point.methodpoint;
|
||||||
if (strcmp(method_p->method_name, method_name) == 0) {
|
if (strcmp(method_p->method_name, method_name) == 0) {
|
||||||
class_name = get_class_name(mrb, class_obj);
|
class_name = mrb_class_name(mrb, class_obj);
|
||||||
if (class_name == NULL) {
|
if (class_name == NULL) {
|
||||||
if (method_p->class_name == NULL) {
|
if (method_p->class_name == NULL) {
|
||||||
return bp->bpno;
|
return bp->bpno;
|
||||||
@@ -147,10 +136,10 @@ compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *cl
|
|||||||
}
|
}
|
||||||
else if (method_p->class_name != NULL) {
|
else if (method_p->class_name != NULL) {
|
||||||
m = mrb_method_search_vm(mrb, &class_obj, method_sym);
|
m = mrb_method_search_vm(mrb, &class_obj, method_sym);
|
||||||
if (m == NULL) {
|
if (MRB_METHOD_UNDEF_P(m)) {
|
||||||
return MRB_DEBUG_OK;
|
return MRB_DEBUG_OK;
|
||||||
}
|
}
|
||||||
if (MRB_PROC_CFUNC_P(m)) {
|
if (MRB_METHOD_CFUNC_P(m)) {
|
||||||
*isCfunc = TRUE;
|
*isCfunc = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,12 +151,12 @@ compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *cl
|
|||||||
sc = mrb_class_get(mrb, method_p->class_name);
|
sc = mrb_class_get(mrb, method_p->class_name);
|
||||||
ssym = mrb_symbol(mrb_check_intern_cstr(mrb, method_p->method_name));
|
ssym = mrb_symbol(mrb_check_intern_cstr(mrb, method_p->method_name));
|
||||||
m = mrb_method_search_vm(mrb, &sc, ssym);
|
m = mrb_method_search_vm(mrb, &sc, ssym);
|
||||||
if (m == NULL) {
|
if (MRB_METHOD_UNDEF_P(m)) {
|
||||||
return MRB_DEBUG_OK;
|
return MRB_DEBUG_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
class_name = get_class_name(mrb, class_obj);
|
class_name = mrb_class_name(mrb, class_obj);
|
||||||
sn = get_class_name(mrb, sc);
|
sn = mrb_class_name(mrb, sc);
|
||||||
if (strcmp(sn, class_name) == 0) {
|
if (strcmp(sn, class_name) == 0) {
|
||||||
return bp->bpno;
|
return bp->bpno;
|
||||||
}
|
}
|
||||||
@@ -204,7 +193,7 @@ mrb_debug_set_break_line(mrb_state *mrb, mrb_debug_context *dbg, const char *fil
|
|||||||
return MRB_DEBUG_BREAK_INVALID_LINENO;
|
return MRB_DEBUG_BREAK_INVALID_LINENO;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_file = mrb_malloc(mrb, strlen(file) + 1);
|
set_file = (char*)mrb_malloc(mrb, strlen(file) + 1);
|
||||||
|
|
||||||
index = dbg->bpnum;
|
index = dbg->bpnum;
|
||||||
dbg->bp[index].bpno = dbg->next_bpno;
|
dbg->bp[index].bpno = dbg->next_bpno;
|
||||||
@@ -241,14 +230,14 @@ mrb_debug_set_break_method(mrb_state *mrb, mrb_debug_context *dbg, const char *c
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (class_name != NULL) {
|
if (class_name != NULL) {
|
||||||
set_class = mrb_malloc(mrb, strlen(class_name) + 1);
|
set_class = (char*)mrb_malloc(mrb, strlen(class_name) + 1);
|
||||||
strncpy(set_class, class_name, strlen(class_name) + 1);
|
strncpy(set_class, class_name, strlen(class_name) + 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
set_class = NULL;
|
set_class = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_method = mrb_malloc(mrb, strlen(method_name) + 1);
|
set_method = (char*)mrb_malloc(mrb, strlen(method_name) + 1);
|
||||||
|
|
||||||
strncpy(set_method, method_name, strlen(method_name) + 1);
|
strncpy(set_method, method_name, strlen(method_name) + 1);
|
||||||
|
|
||||||
@@ -440,7 +429,7 @@ static mrb_bool
|
|||||||
check_start_pc_for_line(mrb_irep *irep, mrb_code *pc, uint16_t line)
|
check_start_pc_for_line(mrb_irep *irep, mrb_code *pc, uint16_t line)
|
||||||
{
|
{
|
||||||
if (pc > irep->iseq) {
|
if (pc > irep->iseq) {
|
||||||
if (line == mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq - 1))) {
|
if (line == mrb_debug_get_line(irep, pc - irep->iseq - 1)) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -514,5 +503,3 @@ mrb_debug_check_breakpoint_method(mrb_state *mrb, mrb_debug_context *dbg, struct
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ build_path(mrb_state *mrb, const char *dir, const char *base)
|
|||||||
len += strlen(dir) + sizeof("/") - 1;
|
len += strlen(dir) + sizeof("/") - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
path = mrb_malloc(mrb, len);
|
path = (char*)mrb_malloc(mrb, len);
|
||||||
memset(path, 0, len);
|
memset(path, 0, len);
|
||||||
|
|
||||||
if (strcmp(dir, ".")) {
|
if (strcmp(dir, ".")) {
|
||||||
@@ -64,7 +64,8 @@ static char*
|
|||||||
dirname(mrb_state *mrb, const char *path)
|
dirname(mrb_state *mrb, const char *path)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
char *p, *dir;
|
const char *p;
|
||||||
|
char *dir;
|
||||||
|
|
||||||
if (path == NULL) {
|
if (path == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -73,7 +74,7 @@ dirname(mrb_state *mrb, const char *path)
|
|||||||
p = strrchr(path, '/');
|
p = strrchr(path, '/');
|
||||||
len = p != NULL ? (size_t)(p - path) : strlen(path);
|
len = p != NULL ? (size_t)(p - path) : strlen(path);
|
||||||
|
|
||||||
dir = mrb_malloc(mrb, len + 1);
|
dir = (char*)mrb_malloc(mrb, len + 1);
|
||||||
strncpy(dir, path, len);
|
strncpy(dir, path, len);
|
||||||
dir[len] = '\0';
|
dir[len] = '\0';
|
||||||
|
|
||||||
@@ -83,9 +84,9 @@ dirname(mrb_state *mrb, const char *path)
|
|||||||
static source_file*
|
static source_file*
|
||||||
source_file_new(mrb_state *mrb, mrb_debug_context *dbg, char *filename)
|
source_file_new(mrb_state *mrb, mrb_debug_context *dbg, char *filename)
|
||||||
{
|
{
|
||||||
source_file *file = NULL;
|
source_file *file;
|
||||||
|
|
||||||
file = mrb_malloc(mrb, sizeof(source_file));
|
file = (source_file*)mrb_malloc(mrb, sizeof(source_file));
|
||||||
|
|
||||||
memset(file, '\0', sizeof(source_file));
|
memset(file, '\0', sizeof(source_file));
|
||||||
file->fp = fopen(filename, "rb");
|
file->fp = fopen(filename, "rb");
|
||||||
@@ -96,7 +97,7 @@ source_file_new(mrb_state *mrb, mrb_debug_context *dbg, char *filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
file->lineno = 1;
|
file->lineno = 1;
|
||||||
file->path = mrb_malloc(mrb, strlen(filename) + 1);
|
file->path = (char*)mrb_malloc(mrb, strlen(filename) + 1);
|
||||||
strcpy(file->path, filename);
|
strcpy(file->path, filename);
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
@@ -174,9 +175,13 @@ mrb_debug_get_source(mrb_state *mrb, mrdb_state *mrdb, const char *srcpath, cons
|
|||||||
FILE *fp;
|
FILE *fp;
|
||||||
const char *search_path[3];
|
const char *search_path[3];
|
||||||
char *path = NULL;
|
char *path = NULL;
|
||||||
|
const char *srcname = strrchr(filename, '/');
|
||||||
|
|
||||||
|
if (srcname) srcname++;
|
||||||
|
else srcname = filename;
|
||||||
|
|
||||||
search_path[0] = srcpath;
|
search_path[0] = srcpath;
|
||||||
search_path[1] = dirname(mrb, mrb_debug_get_filename(mrdb->dbg->root_irep, 0));
|
search_path[1] = dirname(mrb, mrb_debug_get_filename(mrdb->dbg->irep, 0));
|
||||||
search_path[2] = ".";
|
search_path[2] = ".";
|
||||||
|
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
@@ -184,7 +189,7 @@ mrb_debug_get_source(mrb_state *mrb, mrdb_state *mrdb, const char *srcpath, cons
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((path = build_path(mrb, search_path[i], filename)) == NULL) {
|
if ((path = build_path(mrb, search_path[i], srcname)) == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ mrdb_check_syntax(mrb_state *mrb, mrb_debug_context *dbg, const char *expr, size
|
|||||||
c = mrbc_context_new(mrb);
|
c = mrbc_context_new(mrb);
|
||||||
c->no_exec = TRUE;
|
c->no_exec = TRUE;
|
||||||
c->capture_errors = TRUE;
|
c->capture_errors = TRUE;
|
||||||
c->filename = (char*)dbg->prvfile;
|
mrbc_filename(mrb, c, (const char*)dbg->prvfile);
|
||||||
c->lineno = dbg->prvline;
|
c->lineno = dbg->prvline;
|
||||||
|
|
||||||
/* Load program */
|
/* Load program */
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ parse_breakcommand(mrdb_state *mrdb, const char **file, uint32_t *line, char **c
|
|||||||
STRTOUL(l, body);
|
STRTOUL(l, body);
|
||||||
if (l <= 65535) {
|
if (l <= 65535) {
|
||||||
*line = l;
|
*line = l;
|
||||||
*file = (body == args)? mrb_debug_get_filename(dbg->irep, (uint32_t)(dbg->pc - dbg->irep->iseq)): args;
|
*file = (body == args)? mrb_debug_get_filename(dbg->irep, dbg->pc - dbg->irep->iseq): args;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
puts(BREAK_ERR_MSG_RANGEOVER);
|
puts(BREAK_ERR_MSG_RANGEOVER);
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ typedef struct listcmd_parser_state {
|
|||||||
static listcmd_parser_state*
|
static listcmd_parser_state*
|
||||||
listcmd_parser_state_new(mrb_state *mrb)
|
listcmd_parser_state_new(mrb_state *mrb)
|
||||||
{
|
{
|
||||||
listcmd_parser_state *st = mrb_malloc(mrb, sizeof(listcmd_parser_state));
|
listcmd_parser_state *st = (listcmd_parser_state*)mrb_malloc(mrb, sizeof(listcmd_parser_state));
|
||||||
memset(st, 0, sizeof(listcmd_parser_state));
|
memset(st, 0, sizeof(listcmd_parser_state));
|
||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
@@ -227,7 +227,7 @@ parse_filename(mrb_state *mrb, char **sp, listcmd_parser_state *st)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
st->filename = mrb_malloc(mrb, len + 1);
|
st->filename = (char*)mrb_malloc(mrb, len + 1);
|
||||||
strncpy(st->filename, *sp, len);
|
strncpy(st->filename, *sp, len);
|
||||||
st->filename[len] = '\0';
|
st->filename[len] = '\0';
|
||||||
*sp += len;
|
*sp += len;
|
||||||
@@ -242,7 +242,8 @@ char*
|
|||||||
replace_ext(mrb_state *mrb, const char *filename, const char *ext)
|
replace_ext(mrb_state *mrb, const char *filename, const char *ext)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
char *p, *s;
|
const char *p;
|
||||||
|
char *s;
|
||||||
|
|
||||||
if (filename == NULL) {
|
if (filename == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -255,7 +256,7 @@ replace_ext(mrb_state *mrb, const char *filename, const char *ext)
|
|||||||
len = strlen(filename);
|
len = strlen(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
s = mrb_malloc(mrb, len + strlen(ext) + 1);
|
s = (char*)mrb_malloc(mrb, len + strlen(ext) + 1);
|
||||||
memset(s, '\0', len + strlen(ext) + 1);
|
memset(s, '\0', len + strlen(ext) + 1);
|
||||||
strncpy(s, filename, len);
|
strncpy(s, filename, len);
|
||||||
strcat(s, ext);
|
strcat(s, ext);
|
||||||
@@ -325,7 +326,7 @@ parse_listcmd_args(mrb_state *mrb, mrdb_state *mrdb, listcmd_parser_state *st)
|
|||||||
static mrb_bool
|
static mrb_bool
|
||||||
check_cmd_pattern(const char *pattern, const char *cmd)
|
check_cmd_pattern(const char *pattern, const char *cmd)
|
||||||
{
|
{
|
||||||
char *lbracket, *rbracket, *p, *q;
|
const char *lbracket, *rbracket, *p, *q;
|
||||||
|
|
||||||
if (pattern == NULL && cmd == NULL) {
|
if (pattern == NULL && cmd == NULL) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ cleanup(mrb_state *mrb, struct _args *args)
|
|||||||
static mrb_debug_context*
|
static mrb_debug_context*
|
||||||
mrb_debug_context_new(mrb_state *mrb)
|
mrb_debug_context_new(mrb_state *mrb)
|
||||||
{
|
{
|
||||||
mrb_debug_context *dbg = mrb_malloc(mrb, sizeof(mrb_debug_context));
|
mrb_debug_context *dbg = (mrb_debug_context*)mrb_malloc(mrb, sizeof(mrb_debug_context));
|
||||||
|
|
||||||
memset(dbg, 0, sizeof(mrb_debug_context));
|
memset(dbg, 0, sizeof(mrb_debug_context));
|
||||||
|
|
||||||
@@ -223,12 +223,12 @@ mrb_debug_context_free(mrb_state *mrb)
|
|||||||
static mrdb_state*
|
static mrdb_state*
|
||||||
mrdb_state_new(mrb_state *mrb)
|
mrdb_state_new(mrb_state *mrb)
|
||||||
{
|
{
|
||||||
mrdb_state *mrdb = mrb_malloc(mrb, sizeof(mrdb_state));
|
mrdb_state *mrdb = (mrdb_state*)mrb_malloc(mrb, sizeof(mrdb_state));
|
||||||
|
|
||||||
memset(mrdb, 0, sizeof(mrdb_state));
|
memset(mrdb, 0, sizeof(mrdb_state));
|
||||||
|
|
||||||
mrdb->dbg = mrb_debug_context_get(mrb);
|
mrdb->dbg = mrb_debug_context_get(mrb);
|
||||||
mrdb->command = mrb_malloc(mrb, MAX_COMMAND_LINE+1);
|
mrdb->command = (char*)mrb_malloc(mrb, MAX_COMMAND_LINE+1);
|
||||||
mrdb->print_no = 1;
|
mrdb->print_no = 1;
|
||||||
|
|
||||||
return mrdb;
|
return mrdb;
|
||||||
@@ -510,6 +510,7 @@ check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value
|
|||||||
mrb_sym sym;
|
mrb_sym sym;
|
||||||
int32_t bpno;
|
int32_t bpno;
|
||||||
mrb_bool isCfunc;
|
mrb_bool isCfunc;
|
||||||
|
struct mrb_insn_data insn;
|
||||||
|
|
||||||
mrb_debug_context *dbg = mrb_debug_context_get(mrb);
|
mrb_debug_context *dbg = mrb_debug_context_get(mrb);
|
||||||
|
|
||||||
@@ -517,11 +518,12 @@ check_method_breakpoint(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value
|
|||||||
bpno = dbg->method_bpno;
|
bpno = dbg->method_bpno;
|
||||||
dbg->method_bpno = 0;
|
dbg->method_bpno = 0;
|
||||||
|
|
||||||
switch(GET_OPCODE(*pc)) {
|
insn = mrb_decode_insn(pc);
|
||||||
|
switch(insn.insn) {
|
||||||
case OP_SEND:
|
case OP_SEND:
|
||||||
case OP_SENDB:
|
case OP_SENDB:
|
||||||
c = mrb_class(mrb, regs[GETARG_A(*pc)]);
|
c = mrb_class(mrb, regs[insn.a]);
|
||||||
sym = irep->syms[GETARG_B(*pc)];
|
sym = irep->syms[insn.b];
|
||||||
break;
|
break;
|
||||||
case OP_SUPER:
|
case OP_SUPER:
|
||||||
c = mrb->c->ci->target_class->super;
|
c = mrb->c->ci->target_class->super;
|
||||||
@@ -566,8 +568,8 @@ mrb_code_fetch_hook(mrb_state *mrb, mrb_irep *irep, mrb_code *pc, mrb_value *reg
|
|||||||
dbg->xphase = DBG_PHASE_RUNNING;
|
dbg->xphase = DBG_PHASE_RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
file = mrb_debug_get_filename(irep, (uint32_t)(pc - irep->iseq));
|
file = mrb_debug_get_filename(irep, pc - irep->iseq);
|
||||||
line = mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq));
|
line = mrb_debug_get_line(irep, pc - irep->iseq);
|
||||||
|
|
||||||
switch (dbg->xm) {
|
switch (dbg->xm) {
|
||||||
case DBG_STEP:
|
case DBG_STEP:
|
||||||
|
|||||||
@@ -10,3 +10,25 @@ assert('regression for #1563') do
|
|||||||
o, s = Open3.capture2('bin/mirb', :stdin_data => "a=1;b=2;c=3\nb\nc")
|
o, s = Open3.capture2('bin/mirb', :stdin_data => "a=1;b=2;c=3\nb\nc")
|
||||||
assert_true o.include?('=> 3')
|
assert_true o.include?('=> 3')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assert('mirb -d option') do
|
||||||
|
o, _ = Open3.capture2('bin/mirb', :stdin_data => "p $DEBUG\n")
|
||||||
|
assert_true o.include?('=> false')
|
||||||
|
o, _ = Open3.capture2('bin/mirb -d', :stdin_data => "p $DEBUG\n")
|
||||||
|
assert_true o.include?('=> true')
|
||||||
|
end
|
||||||
|
|
||||||
|
assert('mirb -r option') do
|
||||||
|
lib = Tempfile.new('lib.rb')
|
||||||
|
lib.write <<EOS
|
||||||
|
class Hoge
|
||||||
|
def hoge
|
||||||
|
:hoge
|
||||||
|
end
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
lib.flush
|
||||||
|
|
||||||
|
o, _ = Open3.capture2("bin/mirb -r #{lib.path}", :stdin_data => "Hoge.new.hoge\n")
|
||||||
|
assert_true o.include?('=> :hoge')
|
||||||
|
end
|
||||||
|
|||||||
@@ -19,6 +19,12 @@
|
|||||||
#include <readline/history.h>
|
#include <readline/history.h>
|
||||||
#define MIRB_ADD_HISTORY(line) add_history(line)
|
#define MIRB_ADD_HISTORY(line) add_history(line)
|
||||||
#define MIRB_READLINE(ch) readline(ch)
|
#define MIRB_READLINE(ch) readline(ch)
|
||||||
|
#if !defined(RL_READLINE_VERSION) || RL_READLINE_VERSION < 0x600
|
||||||
|
/* libedit & older readline do not have rl_free() */
|
||||||
|
#define MIRB_LINE_FREE(line) free(line)
|
||||||
|
#else
|
||||||
|
#define MIRB_LINE_FREE(line) rl_free(line)
|
||||||
|
#endif
|
||||||
#define MIRB_WRITE_HISTORY(path) write_history(path)
|
#define MIRB_WRITE_HISTORY(path) write_history(path)
|
||||||
#define MIRB_READ_HISTORY(path) read_history(path)
|
#define MIRB_READ_HISTORY(path) read_history(path)
|
||||||
#define MIRB_USING_HISTORY() using_history()
|
#define MIRB_USING_HISTORY() using_history()
|
||||||
@@ -27,6 +33,7 @@
|
|||||||
#include <linenoise.h>
|
#include <linenoise.h>
|
||||||
#define MIRB_ADD_HISTORY(line) linenoiseHistoryAdd(line)
|
#define MIRB_ADD_HISTORY(line) linenoiseHistoryAdd(line)
|
||||||
#define MIRB_READLINE(ch) linenoise(ch)
|
#define MIRB_READLINE(ch) linenoise(ch)
|
||||||
|
#define MIRB_LINE_FREE(line) linenoiseFree(line)
|
||||||
#define MIRB_WRITE_HISTORY(path) linenoiseHistorySave(path)
|
#define MIRB_WRITE_HISTORY(path) linenoiseHistorySave(path)
|
||||||
#define MIRB_READ_HISTORY(path) linenoiseHistoryLoad(history_path)
|
#define MIRB_READ_HISTORY(path) linenoiseHistoryLoad(history_path)
|
||||||
#define MIRB_USING_HISTORY()
|
#define MIRB_USING_HISTORY()
|
||||||
@@ -46,7 +53,10 @@
|
|||||||
#include <mruby/array.h>
|
#include <mruby/array.h>
|
||||||
#include <mruby/proc.h>
|
#include <mruby/proc.h>
|
||||||
#include <mruby/compile.h>
|
#include <mruby/compile.h>
|
||||||
|
#include <mruby/dump.h>
|
||||||
#include <mruby/string.h>
|
#include <mruby/string.h>
|
||||||
|
#include <mruby/variable.h>
|
||||||
|
#include <mruby/throw.h>
|
||||||
|
|
||||||
#ifdef ENABLE_READLINE
|
#ifdef ENABLE_READLINE
|
||||||
|
|
||||||
@@ -88,6 +98,7 @@ static void
|
|||||||
p(mrb_state *mrb, mrb_value obj, int prompt)
|
p(mrb_state *mrb, mrb_value obj, int prompt)
|
||||||
{
|
{
|
||||||
mrb_value val;
|
mrb_value val;
|
||||||
|
char* msg;
|
||||||
|
|
||||||
val = mrb_funcall(mrb, obj, "inspect", 0);
|
val = mrb_funcall(mrb, obj, "inspect", 0);
|
||||||
if (prompt) {
|
if (prompt) {
|
||||||
@@ -101,7 +112,9 @@ p(mrb_state *mrb, mrb_value obj, int prompt)
|
|||||||
if (!mrb_string_p(val)) {
|
if (!mrb_string_p(val)) {
|
||||||
val = mrb_obj_as_string(mrb, obj);
|
val = mrb_obj_as_string(mrb, obj);
|
||||||
}
|
}
|
||||||
fwrite(RSTRING_PTR(val), RSTRING_LEN(val), 1, stdout);
|
msg = mrb_locale_from_utf8(RSTRING_PTR(val), (int)RSTRING_LEN(val));
|
||||||
|
fwrite(msg, strlen(msg), 1, stdout);
|
||||||
|
mrb_locale_free(msg);
|
||||||
putc('\n', stdout);
|
putc('\n', stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,10 +127,6 @@ is_code_block_open(struct mrb_parser_state *parser)
|
|||||||
|
|
||||||
/* check for heredoc */
|
/* check for heredoc */
|
||||||
if (parser->parsing_heredoc != NULL) return TRUE;
|
if (parser->parsing_heredoc != NULL) return TRUE;
|
||||||
if (parser->heredoc_end_now) {
|
|
||||||
parser->heredoc_end_now = FALSE;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check for unterminated string */
|
/* check for unterminated string */
|
||||||
if (parser->lex_strterm) return TRUE;
|
if (parser->lex_strterm) return TRUE;
|
||||||
@@ -209,8 +218,11 @@ is_code_block_open(struct mrb_parser_state *parser)
|
|||||||
struct _args {
|
struct _args {
|
||||||
FILE *rfp;
|
FILE *rfp;
|
||||||
mrb_bool verbose : 1;
|
mrb_bool verbose : 1;
|
||||||
|
mrb_bool debug : 1;
|
||||||
int argc;
|
int argc;
|
||||||
char** argv;
|
char** argv;
|
||||||
|
int libc;
|
||||||
|
char **libv;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -218,6 +230,8 @@ usage(const char *name)
|
|||||||
{
|
{
|
||||||
static const char *const usage_msg[] = {
|
static const char *const usage_msg[] = {
|
||||||
"switches:",
|
"switches:",
|
||||||
|
"-d set $DEBUG to true (same as `mruby -d`)",
|
||||||
|
"-r library same as `mruby -r`",
|
||||||
"-v print version number, then run in verbose mode",
|
"-v print version number, then run in verbose mode",
|
||||||
"--verbose run in verbose mode",
|
"--verbose run in verbose mode",
|
||||||
"--version print the version",
|
"--version print the version",
|
||||||
@@ -231,9 +245,19 @@ usage(const char *name)
|
|||||||
printf(" %s\n", *p++);
|
printf(" %s\n", *p++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
dup_arg_item(mrb_state *mrb, const char *item)
|
||||||
|
{
|
||||||
|
size_t buflen = strlen(item) + 1;
|
||||||
|
char *buf = (char*)mrb_malloc(mrb, buflen);
|
||||||
|
memcpy(buf, item, buflen);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
|
parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
|
||||||
{
|
{
|
||||||
|
char **origargv = argv;
|
||||||
static const struct _args args_zero = { 0 };
|
static const struct _args args_zero = { 0 };
|
||||||
|
|
||||||
*args = args_zero;
|
*args = args_zero;
|
||||||
@@ -244,6 +268,26 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
|
|||||||
|
|
||||||
item = argv[0] + 1;
|
item = argv[0] + 1;
|
||||||
switch (*item++) {
|
switch (*item++) {
|
||||||
|
case 'd':
|
||||||
|
args->debug = TRUE;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
if (!item[0]) {
|
||||||
|
if (argc <= 1) {
|
||||||
|
printf("%s: No library specified for -r\n", *origargv);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
argc--; argv++;
|
||||||
|
item = argv[0];
|
||||||
|
}
|
||||||
|
if (args->libc == 0) {
|
||||||
|
args->libv = (char**)mrb_malloc(mrb, sizeof(char*));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
args->libv = (char**)mrb_realloc(mrb, args->libv, sizeof(char*) * (args->libc + 1));
|
||||||
|
}
|
||||||
|
args->libv[args->libc++] = dup_arg_item(mrb, item);
|
||||||
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
if (!args->verbose) mrb_show_version(mrb);
|
if (!args->verbose) mrb_show_version(mrb);
|
||||||
args->verbose = TRUE;
|
args->verbose = TRUE;
|
||||||
@@ -289,6 +333,12 @@ cleanup(mrb_state *mrb, struct _args *args)
|
|||||||
if (args->rfp)
|
if (args->rfp)
|
||||||
fclose(args->rfp);
|
fclose(args->rfp);
|
||||||
mrb_free(mrb, args->argv);
|
mrb_free(mrb, args->argv);
|
||||||
|
if (args->libc) {
|
||||||
|
while (args->libc--) {
|
||||||
|
mrb_free(mrb, args->libv[args->libc]);
|
||||||
|
}
|
||||||
|
mrb_free(mrb, args->libv);
|
||||||
|
}
|
||||||
mrb_close(mrb);
|
mrb_close(mrb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,6 +453,7 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mrb_define_global_const(mrb, "ARGV", ARGV);
|
mrb_define_global_const(mrb, "ARGV", ARGV);
|
||||||
|
mrb_gv_set(mrb, mrb_intern_lit(mrb, "$DEBUG"), mrb_bool_value(args.debug));
|
||||||
|
|
||||||
#ifdef ENABLE_READLINE
|
#ifdef ENABLE_READLINE
|
||||||
history_path = get_history_path(mrb);
|
history_path = get_history_path(mrb);
|
||||||
@@ -419,6 +470,19 @@ main(int argc, char **argv)
|
|||||||
print_hint();
|
print_hint();
|
||||||
|
|
||||||
cxt = mrbc_context_new(mrb);
|
cxt = mrbc_context_new(mrb);
|
||||||
|
|
||||||
|
/* Load libraries */
|
||||||
|
for (i = 0; i < args.libc; i++) {
|
||||||
|
FILE *lfp = fopen(args.libv[i], "r");
|
||||||
|
if (lfp == NULL) {
|
||||||
|
printf("Cannot open library file. (%s)\n", args.libv[i]);
|
||||||
|
cleanup(mrb, &args);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
mrb_load_file_cxt(mrb, lfp, cxt);
|
||||||
|
fclose(lfp);
|
||||||
|
}
|
||||||
|
|
||||||
cxt->capture_errors = TRUE;
|
cxt->capture_errors = TRUE;
|
||||||
cxt->lineno = 1;
|
cxt->lineno = 1;
|
||||||
mrbc_filename(mrb, cxt, "(mirb)");
|
mrbc_filename(mrb, cxt, "(mirb)");
|
||||||
@@ -428,7 +492,10 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
char *utf8;
|
char *utf8;
|
||||||
|
struct mrb_jmpbuf c_jmp;
|
||||||
|
|
||||||
|
MRB_TRY(&c_jmp);
|
||||||
|
mrb->jmp = &c_jmp;
|
||||||
if (args.rfp) {
|
if (args.rfp) {
|
||||||
if (fgets(last_code_line, sizeof(last_code_line)-1, args.rfp) != NULL)
|
if (fgets(last_code_line, sizeof(last_code_line)-1, args.rfp) != NULL)
|
||||||
goto done;
|
goto done;
|
||||||
@@ -489,11 +556,10 @@ main(int argc, char **argv)
|
|||||||
strcpy(last_code_line, line);
|
strcpy(last_code_line, line);
|
||||||
strcat(last_code_line, "\n");
|
strcat(last_code_line, "\n");
|
||||||
MIRB_ADD_HISTORY(line);
|
MIRB_ADD_HISTORY(line);
|
||||||
free(line);
|
MIRB_LINE_FREE(line);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
if (code_block_open) {
|
if (code_block_open) {
|
||||||
if (strlen(ruby_code)+strlen(last_code_line) > sizeof(ruby_code)-1) {
|
if (strlen(ruby_code)+strlen(last_code_line) > sizeof(ruby_code)-1) {
|
||||||
fputs("concatenated input string too long\n", stderr);
|
fputs("concatenated input string too long\n", stderr);
|
||||||
@@ -528,9 +594,17 @@ done:
|
|||||||
/* no evaluation of code */
|
/* no evaluation of code */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (0 < parser->nwarn) {
|
||||||
|
/* warning */
|
||||||
|
char* msg = mrb_locale_from_utf8(parser->warn_buffer[0].message, -1);
|
||||||
|
printf("line %d: %s\n", parser->warn_buffer[0].lineno, msg);
|
||||||
|
mrb_locale_free(msg);
|
||||||
|
}
|
||||||
if (0 < parser->nerr) {
|
if (0 < parser->nerr) {
|
||||||
/* syntax error */
|
/* syntax error */
|
||||||
printf("line %d: %s\n", parser->error_buffer[0].lineno, parser->error_buffer[0].message);
|
char* msg = mrb_locale_from_utf8(parser->error_buffer[0].message, -1);
|
||||||
|
printf("line %d: %s\n", parser->error_buffer[0].lineno, msg);
|
||||||
|
mrb_locale_free(msg);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* generate bytecode */
|
/* generate bytecode */
|
||||||
@@ -544,6 +618,13 @@ done:
|
|||||||
if (args.verbose) {
|
if (args.verbose) {
|
||||||
mrb_codedump_all(mrb, proc);
|
mrb_codedump_all(mrb, proc);
|
||||||
}
|
}
|
||||||
|
/* adjust stack length of toplevel environment */
|
||||||
|
if (mrb->c->cibase->env) {
|
||||||
|
struct REnv *e = mrb->c->cibase->env;
|
||||||
|
if (e && MRB_ENV_STACK_LEN(e) < proc->body.irep->nlocals) {
|
||||||
|
MRB_ENV_SET_STACK_LEN(e, proc->body.irep->nlocals);
|
||||||
|
}
|
||||||
|
}
|
||||||
/* pass a proc for evaluation */
|
/* pass a proc for evaluation */
|
||||||
/* evaluate the bytecode */
|
/* evaluate the bytecode */
|
||||||
result = mrb_vm_run(mrb,
|
result = mrb_vm_run(mrb,
|
||||||
@@ -570,6 +651,11 @@ done:
|
|||||||
}
|
}
|
||||||
mrb_parser_free(parser);
|
mrb_parser_free(parser);
|
||||||
cxt->lineno++;
|
cxt->lineno++;
|
||||||
|
MRB_CATCH(&c_jmp) {
|
||||||
|
p(mrb, mrb_obj_value(mrb->exc), 0);
|
||||||
|
mrb->exc = 0;
|
||||||
|
}
|
||||||
|
MRB_END_EXC(&c_jmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_READLINE
|
#ifdef ENABLE_READLINE
|
||||||
@@ -577,6 +663,14 @@ done:
|
|||||||
mrb_free(mrb, history_path);
|
mrb_free(mrb, history_path);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (args.rfp) fclose(args.rfp);
|
||||||
|
mrb_free(mrb, args.argv);
|
||||||
|
if (args.libv) {
|
||||||
|
for (i = 0; i < args.libc; ++i) {
|
||||||
|
mrb_free(mrb, args.libv[i]);
|
||||||
|
}
|
||||||
|
mrb_free(mrb, args.libv);
|
||||||
|
}
|
||||||
mrbc_context_free(mrb, cxt);
|
mrbc_context_free(mrb, cxt);
|
||||||
mrb_close(mrb);
|
mrb_close(mrb);
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ MRuby::Gem::Specification.new 'mruby-bin-mrbc' do |spec|
|
|||||||
exec = exefile("#{build.build_dir}/bin/mrbc")
|
exec = exefile("#{build.build_dir}/bin/mrbc")
|
||||||
mrbc_objs = Dir.glob("#{spec.dir}/tools/mrbc/*.c").map { |f| objfile(f.pathmap("#{spec.build_dir}/tools/mrbc/%n")) }.flatten
|
mrbc_objs = Dir.glob("#{spec.dir}/tools/mrbc/*.c").map { |f| objfile(f.pathmap("#{spec.build_dir}/tools/mrbc/%n")) }.flatten
|
||||||
|
|
||||||
file exec => mrbc_objs + [libfile("#{build.build_dir}/lib/libmruby_core")] do |t|
|
file exec => mrbc_objs + [build.libmruby_core_static] do |t|
|
||||||
build.linker.run t.name, t.prerequisites
|
build.linker.run t.name, t.prerequisites
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ struct mrbc_args {
|
|||||||
const char *initname;
|
const char *initname;
|
||||||
mrb_bool check_syntax : 1;
|
mrb_bool check_syntax : 1;
|
||||||
mrb_bool verbose : 1;
|
mrb_bool verbose : 1;
|
||||||
|
mrb_bool remove_lv : 1;
|
||||||
unsigned int flags : 4;
|
unsigned int flags : 4;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -33,6 +34,7 @@ usage(const char *name)
|
|||||||
"-B<symbol> binary <symbol> output in C language format",
|
"-B<symbol> binary <symbol> output in C language format",
|
||||||
"-e generate little endian iseq data",
|
"-e generate little endian iseq data",
|
||||||
"-E generate big endian iseq data",
|
"-E generate big endian iseq data",
|
||||||
|
"--remove-lv remove local variables",
|
||||||
"--verbose run at verbose mode",
|
"--verbose run at verbose mode",
|
||||||
"--version print the version",
|
"--version print the version",
|
||||||
"--copyright print the copyright",
|
"--copyright print the copyright",
|
||||||
@@ -142,6 +144,10 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
|
|||||||
mrb_show_copyright(mrb);
|
mrb_show_copyright(mrb);
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
else if (strcmp(argv[i] + 2, "remove-lv") == 0) {
|
||||||
|
args->remove_lv = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
default:
|
default:
|
||||||
return i;
|
return i;
|
||||||
@@ -232,6 +238,9 @@ dump_file(mrb_state *mrb, FILE *wfp, const char *outfile, struct RProc *proc, st
|
|||||||
int n = MRB_DUMP_OK;
|
int n = MRB_DUMP_OK;
|
||||||
mrb_irep *irep = proc->body.irep;
|
mrb_irep *irep = proc->body.irep;
|
||||||
|
|
||||||
|
if (args->remove_lv) {
|
||||||
|
mrb_irep_remove_lv(mrb, irep);
|
||||||
|
}
|
||||||
if (args->initname) {
|
if (args->initname) {
|
||||||
n = mrb_dump_irep_cfunc(mrb, irep, args->flags, wfp, args->initname);
|
n = mrb_dump_irep_cfunc(mrb, irep, args->flags, wfp, args->initname);
|
||||||
if (n == MRB_DUMP_INVALID_ARGUMENT) {
|
if (n == MRB_DUMP_INVALID_ARGUMENT) {
|
||||||
|
|||||||
@@ -19,9 +19,10 @@ MRuby.each_target do
|
|||||||
mruby_config_path = "#{build_dir}/bin/#{mruby_config}"
|
mruby_config_path = "#{build_dir}/bin/#{mruby_config}"
|
||||||
@bins << mruby_config
|
@bins << mruby_config
|
||||||
|
|
||||||
file mruby_config_path => libfile("#{build_dir}/lib/libmruby") do |t|
|
make_cfg = "#{build_dir}/lib/libmruby.flags.mak"
|
||||||
|
file mruby_config_path => [libmruby_static, make_cfg] do |t|
|
||||||
FileUtils.copy "#{File.dirname(__FILE__)}/#{mruby_config}", t.name
|
FileUtils.copy "#{File.dirname(__FILE__)}/#{mruby_config}", t.name
|
||||||
config = Hash[open("#{build_dir}/lib/libmruby.flags.mak").read.split("\n").map {|x| a = x.split(/\s*=\s*/, 2); [a[0], a[1].gsub('\\"', '"') ]}]
|
config = Hash[open(make_cfg).read.split("\n").map {|x| a = x.split(/\s*=\s*/, 2); [a[0], a[1].gsub('\\"', '"') ]}]
|
||||||
IO.write(t.name, File.open(t.name) {|f|
|
IO.write(t.name, File.open(t.name) {|f|
|
||||||
f.read.gsub (/echo (MRUBY_CFLAGS|MRUBY_LIBS|MRUBY_LDFLAGS_BEFORE_LIBS|MRUBY_LDFLAGS|MRUBY_LIBMRUBY_PATH)/) {|x| config[$1].empty? ? '' : "echo #{config[$1]}"}
|
f.read.gsub (/echo (MRUBY_CFLAGS|MRUBY_LIBS|MRUBY_LDFLAGS_BEFORE_LIBS|MRUBY_LDFLAGS|MRUBY_LIBMRUBY_PATH)/) {|x| config[$1].empty? ? '' : "echo #{config[$1]}"}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -58,3 +58,33 @@ RUBY
|
|||||||
assert_equal "NilClass", `#{cmd('mruby')} #{script.path}`
|
assert_equal "NilClass", `#{cmd('mruby')} #{script.path}`
|
||||||
assert_equal 0, $?.exitstatus
|
assert_equal 0, $?.exitstatus
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assert('mruby -d option') do
|
||||||
|
o = `#{cmd('mruby')} -e #{shellquote('p $DEBUG')}`
|
||||||
|
assert_equal "false\n", o
|
||||||
|
o = `#{cmd('mruby')} -d -e #{shellquote('p $DEBUG')}`
|
||||||
|
assert_equal "true\n", o
|
||||||
|
end
|
||||||
|
|
||||||
|
assert('mruby -r option') do
|
||||||
|
lib = Tempfile.new('lib.rb')
|
||||||
|
lib.write <<EOS
|
||||||
|
class Hoge
|
||||||
|
def hoge
|
||||||
|
:hoge
|
||||||
|
end
|
||||||
|
end
|
||||||
|
EOS
|
||||||
|
lib.flush
|
||||||
|
|
||||||
|
script = Tempfile.new('test.rb')
|
||||||
|
script.write <<EOS
|
||||||
|
print Hoge.new.hoge
|
||||||
|
EOS
|
||||||
|
script.flush
|
||||||
|
assert_equal 'hoge', `#{cmd('mruby')} -r #{lib.path} #{script.path}`
|
||||||
|
assert_equal 0, $?.exitstatus
|
||||||
|
|
||||||
|
assert_equal 'hogeClass', `#{cmd('mruby')} -r #{lib.path} -r #{script.path} -e #{shellquote('print Hoge.class')}`
|
||||||
|
assert_equal 0, $?.exitstatus
|
||||||
|
end
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ MRuby::Gem::Specification.new('mruby-bin-mruby') do |spec|
|
|||||||
spec.add_dependency('mruby-error', :core => 'mruby-error')
|
spec.add_dependency('mruby-error', :core => 'mruby-error')
|
||||||
|
|
||||||
if build.cxx_exception_enabled?
|
if build.cxx_exception_enabled?
|
||||||
@objs << build.compile_as_cxx("#{spec.dir}/tools/mruby/mruby.c", "#{spec.build_dir}/tools/mruby/mruby.cxx")
|
build.compile_as_cxx("#{spec.dir}/tools/mruby/mruby.c", "#{spec.build_dir}/tools/mruby/mruby.cxx")
|
||||||
@objs.delete_if { |v| v == objfile("#{spec.build_dir}/tools/mruby/mruby") }
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -27,8 +27,11 @@ struct _args {
|
|||||||
mrb_bool mrbfile : 1;
|
mrb_bool mrbfile : 1;
|
||||||
mrb_bool check_syntax : 1;
|
mrb_bool check_syntax : 1;
|
||||||
mrb_bool verbose : 1;
|
mrb_bool verbose : 1;
|
||||||
|
mrb_bool debug : 1;
|
||||||
int argc;
|
int argc;
|
||||||
char** argv;
|
char** argv;
|
||||||
|
int libc;
|
||||||
|
char **libv;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -38,7 +41,9 @@ usage(const char *name)
|
|||||||
"switches:",
|
"switches:",
|
||||||
"-b load and execute RiteBinary (mrb) file",
|
"-b load and execute RiteBinary (mrb) file",
|
||||||
"-c check syntax only",
|
"-c check syntax only",
|
||||||
|
"-d set debugging flags (set $DEBUG to true)",
|
||||||
"-e 'command' one line of script",
|
"-e 'command' one line of script",
|
||||||
|
"-r library load the library before executing your script",
|
||||||
"-v print version number, then run in verbose mode",
|
"-v print version number, then run in verbose mode",
|
||||||
"--verbose run in verbose mode",
|
"--verbose run in verbose mode",
|
||||||
"--version print the version",
|
"--version print the version",
|
||||||
@@ -52,6 +57,15 @@ usage(const char *name)
|
|||||||
printf(" %s\n", *p++);
|
printf(" %s\n", *p++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
dup_arg_item(mrb_state *mrb, const char *item)
|
||||||
|
{
|
||||||
|
size_t buflen = strlen(item) + 1;
|
||||||
|
char *buf = (char*)mrb_malloc(mrb, buflen);
|
||||||
|
memcpy(buf, item, buflen);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
|
parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
|
||||||
{
|
{
|
||||||
@@ -78,6 +92,9 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
|
|||||||
case 'c':
|
case 'c':
|
||||||
args->check_syntax = TRUE;
|
args->check_syntax = TRUE;
|
||||||
break;
|
break;
|
||||||
|
case 'd':
|
||||||
|
args->debug = TRUE;
|
||||||
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
if (item[0]) {
|
if (item[0]) {
|
||||||
goto append_cmdline;
|
goto append_cmdline;
|
||||||
@@ -87,13 +104,7 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct _args *args)
|
|||||||
item = argv[0];
|
item = argv[0];
|
||||||
append_cmdline:
|
append_cmdline:
|
||||||
if (!args->cmdline) {
|
if (!args->cmdline) {
|
||||||
size_t buflen;
|
args->cmdline = dup_arg_item(mrb, item);
|
||||||
char *buf;
|
|
||||||
|
|
||||||
buflen = strlen(item) + 1;
|
|
||||||
buf = (char *)mrb_malloc(mrb, buflen);
|
|
||||||
memcpy(buf, item, buflen);
|
|
||||||
args->cmdline = buf;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
size_t cmdlinelen;
|
size_t cmdlinelen;
|
||||||
@@ -112,6 +123,23 @@ append_cmdline:
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'r':
|
||||||
|
if (!item[0]) {
|
||||||
|
if (argc <= 1) {
|
||||||
|
printf("%s: No library specified for -r\n", *origargv);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
argc--; argv++;
|
||||||
|
item = argv[0];
|
||||||
|
}
|
||||||
|
if (args->libc == 0) {
|
||||||
|
args->libv = (char**)mrb_malloc(mrb, sizeof(char*));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
args->libv = (char**)mrb_realloc(mrb, args->libv, sizeof(char*) * (args->libc + 1));
|
||||||
|
}
|
||||||
|
args->libv[args->libc++] = dup_arg_item(mrb, item);
|
||||||
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
if (!args->verbose) mrb_show_version(mrb);
|
if (!args->verbose) mrb_show_version(mrb);
|
||||||
args->verbose = TRUE;
|
args->verbose = TRUE;
|
||||||
@@ -162,6 +190,12 @@ cleanup(mrb_state *mrb, struct _args *args)
|
|||||||
if (!args->fname)
|
if (!args->fname)
|
||||||
mrb_free(mrb, args->cmdline);
|
mrb_free(mrb, args->cmdline);
|
||||||
mrb_free(mrb, args->argv);
|
mrb_free(mrb, args->argv);
|
||||||
|
if (args->libc) {
|
||||||
|
while (args->libc--) {
|
||||||
|
mrb_free(mrb, args->libv[args->libc]);
|
||||||
|
}
|
||||||
|
mrb_free(mrb, args->libv);
|
||||||
|
}
|
||||||
mrb_close(mrb);
|
mrb_close(mrb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,6 +233,7 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mrb_define_global_const(mrb, "ARGV", ARGV);
|
mrb_define_global_const(mrb, "ARGV", ARGV);
|
||||||
|
mrb_gv_set(mrb, mrb_intern_lit(mrb, "$DEBUG"), mrb_bool_value(args.debug));
|
||||||
|
|
||||||
c = mrbc_context_new(mrb);
|
c = mrbc_context_new(mrb);
|
||||||
if (args.verbose)
|
if (args.verbose)
|
||||||
@@ -219,6 +254,24 @@ main(int argc, char **argv)
|
|||||||
mrb_gv_set(mrb, zero_sym, mrb_str_new_lit(mrb, "-e"));
|
mrb_gv_set(mrb, zero_sym, mrb_str_new_lit(mrb, "-e"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Load libraries */
|
||||||
|
for (i = 0; i < args.libc; i++) {
|
||||||
|
FILE *lfp = fopen(args.libv[i], args.mrbfile ? "rb" : "r");
|
||||||
|
if (lfp == NULL) {
|
||||||
|
printf("Cannot open library file: %s\n", args.libv[i]);
|
||||||
|
mrbc_context_free(mrb, c);
|
||||||
|
cleanup(mrb, &args);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if (args.mrbfile) {
|
||||||
|
v = mrb_load_irep_file_cxt(mrb, lfp, c);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v = mrb_load_file_cxt(mrb, lfp, c);
|
||||||
|
}
|
||||||
|
fclose(lfp);
|
||||||
|
}
|
||||||
|
|
||||||
/* Load program */
|
/* Load program */
|
||||||
if (args.mrbfile) {
|
if (args.mrbfile) {
|
||||||
v = mrb_load_irep_file_cxt(mrb, args.rfp, c);
|
v = mrb_load_irep_file_cxt(mrb, args.rfp, c);
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ EOS
|
|||||||
|
|
||||||
`#{cmd('mruby-strip')} -l #{without_lv.path}`
|
`#{cmd('mruby-strip')} -l #{without_lv.path}`
|
||||||
assert_true without_lv.size < with_lv.size
|
assert_true without_lv.size < with_lv.size
|
||||||
|
#
|
||||||
assert_equal '[:a, :b]', `#{cmd('mruby')} -b #{with_lv.path}`.chomp
|
# assert_equal '[:a, :b]', `#{cmd('mruby')} -b #{with_lv.path}`.chomp
|
||||||
assert_equal '[]', `#{cmd('mruby')} -b #{without_lv.path}`.chomp
|
# assert_equal '[]', `#{cmd('mruby')} -b #{without_lv.path}`.chomp
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -12,22 +12,6 @@ struct strip_args {
|
|||||||
mrb_bool lvar;
|
mrb_bool lvar;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
irep_remove_lv(mrb_state *mrb, mrb_irep *irep)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (irep->lv) {
|
|
||||||
mrb_free(mrb, irep->lv);
|
|
||||||
irep->lv = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < irep->rlen; ++i) {
|
|
||||||
irep_remove_lv(mrb, irep->reps[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_usage(const char *f)
|
print_usage(const char *f)
|
||||||
{
|
{
|
||||||
@@ -99,7 +83,7 @@ strip(mrb_state *mrb, struct strip_args *args)
|
|||||||
|
|
||||||
/* clear lv if --lvar is enabled */
|
/* clear lv if --lvar is enabled */
|
||||||
if (args->lvar) {
|
if (args->lvar) {
|
||||||
irep_remove_lv(mrb, irep);
|
mrb_irep_remove_lv(mrb, irep);
|
||||||
}
|
}
|
||||||
|
|
||||||
wfile = fopen(filename, "wb");
|
wfile = fopen(filename, "wb");
|
||||||
|
|||||||
@@ -9,12 +9,57 @@ mrb_mod_name(mrb_state *mrb, mrb_value self)
|
|||||||
return mrb_nil_p(name)? name : mrb_str_dup(mrb, name);
|
return mrb_nil_p(name)? name : mrb_str_dup(mrb, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static mrb_value
|
||||||
|
mrb_mod_singleton_class_p(mrb_state *mrb, mrb_value self)
|
||||||
|
{
|
||||||
|
return mrb_bool_value(mrb_type(self) == MRB_TT_SCLASS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* module_exec(arg...) {|var...| block } -> obj
|
||||||
|
* class_exec(arg...) {|var...| block } -> obj
|
||||||
|
*
|
||||||
|
* Evaluates the given block in the context of the
|
||||||
|
* class/module. The method defined in the block will belong
|
||||||
|
* to the receiver. Any arguments passed to the method will be
|
||||||
|
* passed to the block. This can be used if the block needs to
|
||||||
|
* access instance variables.
|
||||||
|
*
|
||||||
|
* class Thing
|
||||||
|
* end
|
||||||
|
* Thing.class_exec{
|
||||||
|
* def hello() "Hello there!" end
|
||||||
|
* }
|
||||||
|
* puts Thing.new.hello()
|
||||||
|
*/
|
||||||
|
|
||||||
|
static mrb_value
|
||||||
|
mrb_mod_module_exec(mrb_state *mrb, mrb_value self)
|
||||||
|
{
|
||||||
|
const mrb_value *argv;
|
||||||
|
mrb_int argc;
|
||||||
|
mrb_value blk;
|
||||||
|
|
||||||
|
mrb_get_args(mrb, "*&", &argv, &argc, &blk);
|
||||||
|
|
||||||
|
if (mrb_nil_p(blk)) {
|
||||||
|
mrb_raise(mrb, E_ARGUMENT_ERROR, "no block given");
|
||||||
|
}
|
||||||
|
|
||||||
|
mrb->c->ci->target_class = mrb_class_ptr(self);
|
||||||
|
return mrb_yield_cont(mrb, blk, self, argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
mrb_mruby_class_ext_gem_init(mrb_state *mrb)
|
mrb_mruby_class_ext_gem_init(mrb_state *mrb)
|
||||||
{
|
{
|
||||||
struct RClass *mod = mrb->module_class;
|
struct RClass *mod = mrb->module_class;
|
||||||
|
|
||||||
mrb_define_method(mrb, mod, "name", mrb_mod_name, MRB_ARGS_NONE());
|
mrb_define_method(mrb, mod, "name", mrb_mod_name, MRB_ARGS_NONE());
|
||||||
|
mrb_define_method(mrb, mod, "singleton_class?", mrb_mod_singleton_class_p, MRB_ARGS_NONE());
|
||||||
|
mrb_define_method(mrb, mod, "module_exec", mrb_mod_module_exec, MRB_ARGS_ANY()|MRB_ARGS_BLOCK());
|
||||||
|
mrb_define_method(mrb, mod, "class_exec", mrb_mod_module_exec, MRB_ARGS_ANY()|MRB_ARGS_BLOCK());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -1,10 +1,55 @@
|
|||||||
assert 'Module#name' do
|
assert 'Module#name' do
|
||||||
module A
|
module Outer
|
||||||
class B
|
class Inner; end
|
||||||
end
|
const_set :SetInner, Class.new
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_nil A::B.singleton_class.name
|
assert_equal 'Outer', Outer.name
|
||||||
assert_equal 'Fixnum', Fixnum.name
|
assert_equal 'Outer::Inner', Outer::Inner.name
|
||||||
assert_equal 'A::B', A::B.name
|
assert_equal 'Outer::SetInner', Outer::SetInner.name
|
||||||
|
|
||||||
|
outer = Module.new do
|
||||||
|
const_set :SetInner, Class.new
|
||||||
|
end
|
||||||
|
Object.const_set :SetOuter, outer
|
||||||
|
|
||||||
|
assert_equal 'SetOuter', SetOuter.name
|
||||||
|
assert_equal 'SetOuter::SetInner', SetOuter::SetInner.name
|
||||||
|
|
||||||
|
mod = Module.new
|
||||||
|
cls = Class.new
|
||||||
|
|
||||||
|
assert_nil mod.name
|
||||||
|
assert_nil cls.name
|
||||||
|
end
|
||||||
|
|
||||||
|
assert 'Module#singleton_class?' do
|
||||||
|
mod = Module.new
|
||||||
|
cls = Class.new
|
||||||
|
scl = (class <<cls; self; end)
|
||||||
|
|
||||||
|
assert_false mod.singleton_class?
|
||||||
|
assert_false cls.singleton_class?
|
||||||
|
assert_true scl.singleton_class?
|
||||||
|
end
|
||||||
|
|
||||||
|
assert 'Module#module_eval' do
|
||||||
|
mod = Module.new
|
||||||
|
mod.class_exec(1,2,3) do |a,b,c|
|
||||||
|
assert_equal([1,2,3], [a,b,c])
|
||||||
|
def hi
|
||||||
|
"hi"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
cls = Class.new
|
||||||
|
cls.class_exec(42) do |x|
|
||||||
|
assert_equal(42, x)
|
||||||
|
include mod
|
||||||
|
def hello
|
||||||
|
"hello"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
obj = cls.new
|
||||||
|
assert_equal("hi", obj.hi)
|
||||||
|
assert_equal("hello", obj.hello)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
MRuby::Gem::Specification.new('mruby-compar-ext') do |spec|
|
||||||
|
spec.license = 'MIT'
|
||||||
|
spec.author = 'mruby developers'
|
||||||
|
spec.summary = 'Enumerable module extension'
|
||||||
|
end
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
module Comparable
|
||||||
|
##
|
||||||
|
# Returns <i>min</i> if <i>obj</i> <code><=></code> <i>min</i> is less
|
||||||
|
# than zero, <i>max</i> if <i>obj</i> <code><=></code> <i>max</i> is
|
||||||
|
# greater than zero and <i>obj</i> otherwise.
|
||||||
|
#
|
||||||
|
# 12.clamp(0, 100) #=> 12
|
||||||
|
# 523.clamp(0, 100) #=> 100
|
||||||
|
# -3.123.clamp(0, 100) #=> 0
|
||||||
|
#
|
||||||
|
# 'd'.clamp('a', 'f') #=> 'd'
|
||||||
|
# 'z'.clamp('a', 'f') #=> 'f'
|
||||||
|
#
|
||||||
|
def clamp(min, max)
|
||||||
|
if (min <=> max) > 0
|
||||||
|
raise ArgumentError, "min argument must be smaller than max argument"
|
||||||
|
end
|
||||||
|
c = self <=> min
|
||||||
|
if c == 0
|
||||||
|
return self
|
||||||
|
elsif c < 0
|
||||||
|
return min
|
||||||
|
end
|
||||||
|
c = self <=> max
|
||||||
|
if c > 0
|
||||||
|
return max
|
||||||
|
else
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
+1011
-810
File diff suppressed because it is too large
Load Diff
@@ -52,7 +52,7 @@ inline
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
static unsigned int
|
static unsigned int
|
||||||
hash (register const char *str, register unsigned int len)
|
hash (const char *str, unsigned int len)
|
||||||
{
|
{
|
||||||
static const unsigned char asso_values[] =
|
static const unsigned char asso_values[] =
|
||||||
{
|
{
|
||||||
@@ -83,7 +83,7 @@ hash (register const char *str, register unsigned int len)
|
|||||||
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
|
51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
|
||||||
51, 51, 51, 51, 51, 51
|
51, 51, 51, 51, 51, 51
|
||||||
};
|
};
|
||||||
register int hval = len;
|
int hval = len;
|
||||||
|
|
||||||
switch (hval)
|
switch (hval)
|
||||||
{
|
{
|
||||||
@@ -105,7 +105,7 @@ __attribute__ ((__gnu_inline__))
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
const struct kwtable *
|
const struct kwtable *
|
||||||
mrb_reserved_word (register const char *str, register unsigned int len)
|
mrb_reserved_word (const char *str, unsigned int len)
|
||||||
{
|
{
|
||||||
static const struct kwtable wordlist[] =
|
static const struct kwtable wordlist[] =
|
||||||
{
|
{
|
||||||
@@ -196,11 +196,11 @@ mrb_reserved_word (register const char *str, register unsigned int len)
|
|||||||
|
|
||||||
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
|
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
|
||||||
{
|
{
|
||||||
register int key = hash (str, len);
|
int key = hash (str, len);
|
||||||
|
|
||||||
if (key <= MAX_HASH_VALUE && key >= 0)
|
if (key <= MAX_HASH_VALUE && key >= 0)
|
||||||
{
|
{
|
||||||
register const char *s = wordlist[key].name;
|
const char *s = wordlist[key].name;
|
||||||
|
|
||||||
if (*str == *s && !strcmp (str + 1, s + 1))
|
if (*str == *s && !strcmp (str + 1, s + 1))
|
||||||
return &wordlist[key];
|
return &wordlist[key];
|
||||||
@@ -209,4 +209,3 @@ mrb_reserved_word (register const char *str, register unsigned int len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#line 50 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
#line 50 "/home/matz/work/mruby/mrbgems/mruby-compiler/core/keywords"
|
||||||
|
|
||||||
|
|||||||
@@ -9,14 +9,11 @@
|
|||||||
|
|
||||||
enum node_type {
|
enum node_type {
|
||||||
NODE_METHOD,
|
NODE_METHOD,
|
||||||
NODE_FBODY,
|
|
||||||
NODE_CFUNC,
|
|
||||||
NODE_SCOPE,
|
NODE_SCOPE,
|
||||||
NODE_BLOCK,
|
NODE_BLOCK,
|
||||||
NODE_IF,
|
NODE_IF,
|
||||||
NODE_CASE,
|
NODE_CASE,
|
||||||
NODE_WHEN,
|
NODE_WHEN,
|
||||||
NODE_OPT_N,
|
|
||||||
NODE_WHILE,
|
NODE_WHILE,
|
||||||
NODE_UNTIL,
|
NODE_UNTIL,
|
||||||
NODE_ITER,
|
NODE_ITER,
|
||||||
@@ -40,12 +37,12 @@ enum node_type {
|
|||||||
NODE_CALL,
|
NODE_CALL,
|
||||||
NODE_SCALL,
|
NODE_SCALL,
|
||||||
NODE_FCALL,
|
NODE_FCALL,
|
||||||
NODE_VCALL,
|
|
||||||
NODE_SUPER,
|
NODE_SUPER,
|
||||||
NODE_ZSUPER,
|
NODE_ZSUPER,
|
||||||
NODE_ARRAY,
|
NODE_ARRAY,
|
||||||
NODE_ZARRAY,
|
NODE_ZARRAY,
|
||||||
NODE_HASH,
|
NODE_HASH,
|
||||||
|
NODE_KW_HASH,
|
||||||
NODE_RETURN,
|
NODE_RETURN,
|
||||||
NODE_YIELD,
|
NODE_YIELD,
|
||||||
NODE_LVAR,
|
NODE_LVAR,
|
||||||
@@ -57,8 +54,6 @@ enum node_type {
|
|||||||
NODE_NTH_REF,
|
NODE_NTH_REF,
|
||||||
NODE_BACK_REF,
|
NODE_BACK_REF,
|
||||||
NODE_MATCH,
|
NODE_MATCH,
|
||||||
NODE_MATCH2,
|
|
||||||
NODE_MATCH3,
|
|
||||||
NODE_INT,
|
NODE_INT,
|
||||||
NODE_FLOAT,
|
NODE_FLOAT,
|
||||||
NODE_NEGATE,
|
NODE_NEGATE,
|
||||||
@@ -71,10 +66,10 @@ enum node_type {
|
|||||||
NODE_REGX,
|
NODE_REGX,
|
||||||
NODE_DREGX,
|
NODE_DREGX,
|
||||||
NODE_DREGX_ONCE,
|
NODE_DREGX_ONCE,
|
||||||
NODE_LIST,
|
|
||||||
NODE_ARG,
|
NODE_ARG,
|
||||||
NODE_ARGSCAT,
|
NODE_ARGS_TAIL,
|
||||||
NODE_ARGSPUSH,
|
NODE_KW_ARG,
|
||||||
|
NODE_KW_REST_ARGS,
|
||||||
NODE_SPLAT,
|
NODE_SPLAT,
|
||||||
NODE_TO_ARY,
|
NODE_TO_ARY,
|
||||||
NODE_SVALUE,
|
NODE_SVALUE,
|
||||||
@@ -88,26 +83,15 @@ enum node_type {
|
|||||||
NODE_SCLASS,
|
NODE_SCLASS,
|
||||||
NODE_COLON2,
|
NODE_COLON2,
|
||||||
NODE_COLON3,
|
NODE_COLON3,
|
||||||
NODE_CREF,
|
|
||||||
NODE_DOT2,
|
NODE_DOT2,
|
||||||
NODE_DOT3,
|
NODE_DOT3,
|
||||||
NODE_FLIP2,
|
|
||||||
NODE_FLIP3,
|
|
||||||
NODE_ATTRSET,
|
|
||||||
NODE_SELF,
|
NODE_SELF,
|
||||||
NODE_NIL,
|
NODE_NIL,
|
||||||
NODE_TRUE,
|
NODE_TRUE,
|
||||||
NODE_FALSE,
|
NODE_FALSE,
|
||||||
NODE_DEFINED,
|
NODE_DEFINED,
|
||||||
NODE_NEWLINE,
|
|
||||||
NODE_POSTEXE,
|
NODE_POSTEXE,
|
||||||
NODE_ALLOCA,
|
|
||||||
NODE_DMETHOD,
|
|
||||||
NODE_BMETHOD,
|
|
||||||
NODE_MEMO,
|
|
||||||
NODE_IFUNC,
|
|
||||||
NODE_DSYM,
|
NODE_DSYM,
|
||||||
NODE_ATTRASGN,
|
|
||||||
NODE_HEREDOC,
|
NODE_HEREDOC,
|
||||||
NODE_LITERAL_DELIM,
|
NODE_LITERAL_DELIM,
|
||||||
NODE_WORDS,
|
NODE_WORDS,
|
||||||
|
|||||||
+481
-301
File diff suppressed because it is too large
Load Diff
@@ -23,10 +23,10 @@ MRuby::Gem::Specification.new 'mruby-compiler' do |spec|
|
|||||||
cc.run t.name, t.prerequisites.first, [], ["#{current_dir}/core"]
|
cc.run t.name, t.prerequisites.first, [], ["#{current_dir}/core"]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
file objfile("#{current_build_dir}/core/y.tab") => lex_def
|
|
||||||
|
|
||||||
# Parser
|
# Parser
|
||||||
file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y"] do |t|
|
file "#{current_build_dir}/core/y.tab.c" => ["#{current_dir}/core/parse.y", lex_def] do |t|
|
||||||
|
FileUtils.mkdir_p File.dirname t.name
|
||||||
yacc.run t.name, t.prerequisites.first
|
yacc.run t.name, t.prerequisites.first
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -35,6 +35,6 @@ MRuby::Gem::Specification.new 'mruby-compiler' do |spec|
|
|||||||
gperf.run t.name, t.prerequisites.first
|
gperf.run t.name, t.prerequisites.first
|
||||||
end
|
end
|
||||||
|
|
||||||
file libfile("#{build.build_dir}/lib/libmruby_core") => core_objs
|
file build.libmruby_core_static => core_objs
|
||||||
build.libmruby << core_objs
|
build.libmruby << core_objs
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -13,10 +13,9 @@ module Enumerable
|
|||||||
# a.drop(3) #=> [4, 5, 0]
|
# a.drop(3) #=> [4, 5, 0]
|
||||||
|
|
||||||
def drop(n)
|
def drop(n)
|
||||||
raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
|
n = n.__to_int
|
||||||
raise ArgumentError, "attempt to drop negative size" if n < 0
|
raise ArgumentError, "attempt to drop negative size" if n < 0
|
||||||
|
|
||||||
n = n.to_int
|
|
||||||
ary = []
|
ary = []
|
||||||
self.each {|*val| n == 0 ? ary << val.__svalue : n -= 1 }
|
self.each {|*val| n == 0 ? ary << val.__svalue : n -= 1 }
|
||||||
ary
|
ary
|
||||||
@@ -57,8 +56,8 @@ module Enumerable
|
|||||||
# a.take(3) #=> [1, 2, 3]
|
# a.take(3) #=> [1, 2, 3]
|
||||||
|
|
||||||
def take(n)
|
def take(n)
|
||||||
raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
|
n = n.__to_int
|
||||||
i = n.to_int
|
i = n.to_i
|
||||||
raise ArgumentError, "attempt to take negative size" if i < 0
|
raise ArgumentError, "attempt to take negative size" if i < 0
|
||||||
ary = []
|
ary = []
|
||||||
return ary if i == 0
|
return ary if i == 0
|
||||||
@@ -113,12 +112,12 @@ module Enumerable
|
|||||||
# [8, 9, 10]
|
# [8, 9, 10]
|
||||||
|
|
||||||
def each_cons(n, &block)
|
def each_cons(n, &block)
|
||||||
raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
|
n = n.__to_int
|
||||||
raise ArgumentError, "invalid size" if n <= 0
|
raise ArgumentError, "invalid size" if n <= 0
|
||||||
|
|
||||||
return to_enum(:each_cons,n) unless block
|
return to_enum(:each_cons,n) unless block
|
||||||
ary = []
|
ary = []
|
||||||
n = n.to_int
|
n = n.to_i
|
||||||
self.each do |*val|
|
self.each do |*val|
|
||||||
ary.shift if ary.size == n
|
ary.shift if ary.size == n
|
||||||
ary << val.__svalue
|
ary << val.__svalue
|
||||||
@@ -141,12 +140,12 @@ module Enumerable
|
|||||||
# [10]
|
# [10]
|
||||||
|
|
||||||
def each_slice(n, &block)
|
def each_slice(n, &block)
|
||||||
raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
|
n = n.__to_int
|
||||||
raise ArgumentError, "invalid slice size" if n <= 0
|
raise ArgumentError, "invalid slice size" if n <= 0
|
||||||
|
|
||||||
return to_enum(:each_slice,n) unless block
|
return to_enum(:each_slice,n) unless block
|
||||||
ary = []
|
ary = []
|
||||||
n = n.to_int
|
n = n.to_i
|
||||||
self.each do |*val|
|
self.each do |*val|
|
||||||
ary << val.__svalue
|
ary << val.__svalue
|
||||||
if ary.size == n
|
if ary.size == n
|
||||||
@@ -201,9 +200,7 @@ module Enumerable
|
|||||||
ary.push([block.call(e), i])
|
ary.push([block.call(e), i])
|
||||||
}
|
}
|
||||||
if ary.size > 1
|
if ary.size > 1
|
||||||
__sort_sub__(ary, ::Array.new(ary.size), 0, 0, ary.size - 1) do |a,b|
|
ary.sort!
|
||||||
a <=> b
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
ary.collect{|e,i| orig[i]}
|
ary.collect{|e,i| orig[i]}
|
||||||
end
|
end
|
||||||
@@ -225,9 +222,7 @@ module Enumerable
|
|||||||
end
|
end
|
||||||
return nil
|
return nil
|
||||||
when 1
|
when 1
|
||||||
n = args[0]
|
i = args[0].__to_int
|
||||||
raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int)
|
|
||||||
i = n.to_int
|
|
||||||
raise ArgumentError, "attempt to take negative size" if i < 0
|
raise ArgumentError, "attempt to take negative size" if i < 0
|
||||||
ary = []
|
ary = []
|
||||||
return ary if i == 0
|
return ary if i == 0
|
||||||
@@ -451,20 +446,30 @@ module Enumerable
|
|||||||
##
|
##
|
||||||
# call-seq:
|
# call-seq:
|
||||||
# enum.none? [{ |obj| block }] -> true or false
|
# enum.none? [{ |obj| block }] -> true or false
|
||||||
|
# enum.none?(pattern) -> true or false
|
||||||
#
|
#
|
||||||
# Passes each element of the collection to the given block. The method
|
# Passes each element of the collection to the given block. The method
|
||||||
# returns <code>true</code> if the block never returns <code>true</code>
|
# returns <code>true</code> if the block never returns <code>true</code>
|
||||||
# for all elements. If the block is not given, <code>none?</code> will return
|
# for all elements. If the block is not given, <code>none?</code> will return
|
||||||
# <code>true</code> only if none of the collection members is true.
|
# <code>true</code> only if none of the collection members is true.
|
||||||
#
|
#
|
||||||
|
# If a pattern is supplied instead, the method returns whether
|
||||||
|
# <code>pattern === element</code> for none of the collection members.
|
||||||
|
#
|
||||||
# %w(ant bear cat).none? { |word| word.length == 5 } #=> true
|
# %w(ant bear cat).none? { |word| word.length == 5 } #=> true
|
||||||
# %w(ant bear cat).none? { |word| word.length >= 4 } #=> false
|
# %w(ant bear cat).none? { |word| word.length >= 4 } #=> false
|
||||||
|
# %w{ant bear cat}.none?(/d/) #=> true
|
||||||
|
# [1, 3.14, 42].none?(Float) #=> false
|
||||||
# [].none? #=> true
|
# [].none? #=> true
|
||||||
# [nil, false].none? #=> true
|
# [nil, false].none? #=> true
|
||||||
# [nil, true].none? #=> false
|
# [nil, true].none? #=> false
|
||||||
|
|
||||||
def none?(&block)
|
def none?(pat=NONE, &block)
|
||||||
if block
|
if pat != NONE
|
||||||
|
self.each do |*val|
|
||||||
|
return false if pat === val.__svalue
|
||||||
|
end
|
||||||
|
elsif block
|
||||||
self.each do |*val|
|
self.each do |*val|
|
||||||
return false if block.call(*val)
|
return false if block.call(*val)
|
||||||
end
|
end
|
||||||
@@ -479,6 +484,7 @@ module Enumerable
|
|||||||
##
|
##
|
||||||
# call-seq:
|
# call-seq:
|
||||||
# enum.one? [{ |obj| block }] -> true or false
|
# enum.one? [{ |obj| block }] -> true or false
|
||||||
|
# enum.one?(pattern) -> true or false
|
||||||
#
|
#
|
||||||
# Passes each element of the collection to the given block. The method
|
# Passes each element of the collection to the given block. The method
|
||||||
# returns <code>true</code> if the block returns <code>true</code>
|
# returns <code>true</code> if the block returns <code>true</code>
|
||||||
@@ -486,16 +492,26 @@ module Enumerable
|
|||||||
# <code>true</code> only if exactly one of the collection members is
|
# <code>true</code> only if exactly one of the collection members is
|
||||||
# true.
|
# true.
|
||||||
#
|
#
|
||||||
|
# If a pattern is supplied instead, the method returns whether
|
||||||
|
# <code>pattern === element</code> for exactly one collection member.
|
||||||
|
#
|
||||||
# %w(ant bear cat).one? { |word| word.length == 4 } #=> true
|
# %w(ant bear cat).one? { |word| word.length == 4 } #=> true
|
||||||
# %w(ant bear cat).one? { |word| word.length > 4 } #=> false
|
# %w(ant bear cat).one? { |word| word.length > 4 } #=> false
|
||||||
# %w(ant bear cat).one? { |word| word.length < 4 } #=> false
|
# %w(ant bear cat).one? { |word| word.length < 4 } #=> false
|
||||||
|
# %w{ant bear cat}.one?(/t/) #=> false
|
||||||
# [nil, true, 99].one? #=> false
|
# [nil, true, 99].one? #=> false
|
||||||
# [nil, true, false].one? #=> true
|
# [nil, true, false].one? #=> true
|
||||||
#
|
# [ nil, true, 99 ].one?(Integer) #=> true
|
||||||
|
# [].one? #=> false
|
||||||
|
|
||||||
def one?(&block)
|
def one?(pat=NONE, &block)
|
||||||
count = 0
|
count = 0
|
||||||
if block
|
if pat!=NONE
|
||||||
|
self.each do |*val|
|
||||||
|
count += 1 if pat === val.__svalue
|
||||||
|
return false if count > 1
|
||||||
|
end
|
||||||
|
elsif block
|
||||||
self.each do |*val|
|
self.each do |*val|
|
||||||
count += 1 if block.call(*val)
|
count += 1 if block.call(*val)
|
||||||
return false if count > 1
|
return false if count > 1
|
||||||
@@ -510,6 +526,71 @@ module Enumerable
|
|||||||
count == 1 ? true : false
|
count == 1 ? true : false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# ISO 15.3.2.2.1
|
||||||
|
# call-seq:
|
||||||
|
# enum.all? [{ |obj| block } ] -> true or false
|
||||||
|
# enum.all?(pattern) -> true or false
|
||||||
|
#
|
||||||
|
# Passes each element of the collection to the given block. The method
|
||||||
|
# returns <code>true</code> if the block never returns
|
||||||
|
# <code>false</code> or <code>nil</code>. If the block is not given,
|
||||||
|
# Ruby adds an implicit block of <code>{ |obj| obj }</code> which will
|
||||||
|
# cause #all? to return +true+ when none of the collection members are
|
||||||
|
# +false+ or +nil+.
|
||||||
|
#
|
||||||
|
# If a pattern is supplied instead, the method returns whether
|
||||||
|
# <code>pattern === element</code> for every collection member.
|
||||||
|
#
|
||||||
|
# %w[ant bear cat].all? { |word| word.length >= 3 } #=> true
|
||||||
|
# %w[ant bear cat].all? { |word| word.length >= 4 } #=> false
|
||||||
|
# %w[ant bear cat].all?(/t/) #=> false
|
||||||
|
# [1, 2i, 3.14].all?(Numeric) #=> true
|
||||||
|
# [nil, true, 99].all? #=> false
|
||||||
|
#
|
||||||
|
def all?(pat=NONE, &block)
|
||||||
|
if pat != NONE
|
||||||
|
self.each{|*val| return false unless pat === val.__svalue}
|
||||||
|
elsif block
|
||||||
|
self.each{|*val| return false unless block.call(*val)}
|
||||||
|
else
|
||||||
|
self.each{|*val| return false unless val.__svalue}
|
||||||
|
end
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
# ISO 15.3.2.2.2
|
||||||
|
# call-seq:
|
||||||
|
# enum.any? [{ |obj| block }] -> true or false
|
||||||
|
# enum.any?(pattern) -> true or false
|
||||||
|
#
|
||||||
|
# Passes each element of the collection to the given block. The method
|
||||||
|
# returns <code>true</code> if the block ever returns a value other
|
||||||
|
# than <code>false</code> or <code>nil</code>. If the block is not
|
||||||
|
# given, Ruby adds an implicit block of <code>{ |obj| obj }</code> that
|
||||||
|
# will cause #any? to return +true+ if at least one of the collection
|
||||||
|
# members is not +false+ or +nil+.
|
||||||
|
#
|
||||||
|
# If a pattern is supplied instead, the method returns whether
|
||||||
|
# <code>pattern === element</code> for any collection member.
|
||||||
|
#
|
||||||
|
# %w[ant bear cat].any? { |word| word.length >= 3 } #=> true
|
||||||
|
# %w[ant bear cat].any? { |word| word.length >= 4 } #=> true
|
||||||
|
# %w[ant bear cat].any?(/d/) #=> false
|
||||||
|
# [nil, true, 99].any?(Integer) #=> true
|
||||||
|
# [nil, true, 99].any? #=> true
|
||||||
|
# [].any? #=> false
|
||||||
|
#
|
||||||
|
def any?(pat=NONE, &block)
|
||||||
|
if pat != NONE
|
||||||
|
self.each{|*val| return true if pat === val.__svalue}
|
||||||
|
elsif block
|
||||||
|
self.each{|*val| return true if block.call(*val)}
|
||||||
|
else
|
||||||
|
self.each{|*val| return true if val.__svalue}
|
||||||
|
end
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# call-seq:
|
# call-seq:
|
||||||
# enum.each_with_object(obj) { |(*args), memo_obj| ... } -> obj
|
# enum.each_with_object(obj) { |(*args), memo_obj| ... } -> obj
|
||||||
@@ -524,9 +605,7 @@ module Enumerable
|
|||||||
# #=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
|
# #=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
|
||||||
#
|
#
|
||||||
|
|
||||||
def each_with_object(obj=nil, &block)
|
def each_with_object(obj, &block)
|
||||||
raise ArgumentError, "wrong number of arguments (0 for 1)" if obj.nil?
|
|
||||||
|
|
||||||
return to_enum(:each_with_object, obj) unless block
|
return to_enum(:each_with_object, obj) unless block
|
||||||
|
|
||||||
self.each {|*val| block.call(val.__svalue, obj) }
|
self.each {|*val| block.call(val.__svalue, obj) }
|
||||||
@@ -591,13 +670,7 @@ module Enumerable
|
|||||||
if nv.nil?
|
if nv.nil?
|
||||||
n = -1
|
n = -1
|
||||||
else
|
else
|
||||||
unless nv.respond_to?(:to_int)
|
n = nv.__to_int
|
||||||
raise TypeError, "no implicit conversion of #{nv.class} into Integer"
|
|
||||||
end
|
|
||||||
n = nv.to_int
|
|
||||||
unless n.kind_of?(Integer)
|
|
||||||
raise TypeError, "no implicit conversion of #{nv.class} into Integer"
|
|
||||||
end
|
|
||||||
return nil if n <= 0
|
return nil if n <= 0
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -656,18 +729,39 @@ module Enumerable
|
|||||||
##
|
##
|
||||||
# call-seq:
|
# call-seq:
|
||||||
# enum.zip(arg, ...) -> an_array_of_array
|
# enum.zip(arg, ...) -> an_array_of_array
|
||||||
|
# enum.zip(arg, ...) { |arr| block } -> nil
|
||||||
#
|
#
|
||||||
# Takes one element from <i>enum</i> and merges corresponding
|
# Takes one element from <i>enum</i> and merges corresponding
|
||||||
# elements from each <i>args</i>. This generates a sequence of
|
# elements from each <i>args</i>. This generates a sequence of
|
||||||
# <em>n</em>-element arrays, where <em>n</em> is one more than the
|
# <em>n</em>-element arrays, where <em>n</em> is one more than the
|
||||||
# count of arguments. The length of the resulting sequence will be
|
# count of arguments. The length of the resulting sequence will be
|
||||||
# <code>enum#size</code>. If the size of any argument is less than
|
# <code>enum#size</code>. If the size of any argument is less than
|
||||||
# <code>enum#size</code>, <code>nil</code> values are supplied.
|
# <code>enum#size</code>, <code>nil</code> values are supplied. If
|
||||||
|
# a block is given, it is invoked for each output array, otherwise
|
||||||
|
# an array of arrays is returned.
|
||||||
|
#
|
||||||
|
# a = [ 4, 5, 6 ]
|
||||||
|
# b = [ 7, 8, 9 ]
|
||||||
|
#
|
||||||
|
# a.zip(b) #=> [[4, 7], [5, 8], [6, 9]]
|
||||||
|
# [1, 2, 3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
|
||||||
|
# [1, 2].zip(a, b) #=> [[1, 4, 7], [2, 5, 8]]
|
||||||
|
# a.zip([1, 2], [8]) #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]
|
||||||
|
#
|
||||||
|
# c = []
|
||||||
|
# a.zip(b) { |x, y| c << x + y } #=> nil
|
||||||
|
# c #=> [11, 13, 15]
|
||||||
#
|
#
|
||||||
|
|
||||||
def zip(*arg)
|
def zip(*arg, &block)
|
||||||
ary = []
|
result = block ? nil : []
|
||||||
arg = arg.map{|a|a.to_a}
|
arg = arg.map do |a|
|
||||||
|
unless a.respond_to?(:to_a)
|
||||||
|
raise TypeError, "wrong argument type #{a.class} (must respond to :to_a)"
|
||||||
|
end
|
||||||
|
a.to_a
|
||||||
|
end
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
self.each do |*val|
|
self.each do |*val|
|
||||||
a = []
|
a = []
|
||||||
@@ -677,10 +771,14 @@ module Enumerable
|
|||||||
a.push(arg[idx][i])
|
a.push(arg[idx][i])
|
||||||
idx += 1
|
idx += 1
|
||||||
end
|
end
|
||||||
ary.push(a)
|
|
||||||
i += 1
|
i += 1
|
||||||
|
if result.nil?
|
||||||
|
block.call(a)
|
||||||
|
else
|
||||||
|
result.push(a)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
ary
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -694,13 +792,22 @@ module Enumerable
|
|||||||
# # => {:hello => 0, :world => 1}
|
# # => {:hello => 0, :world => 1}
|
||||||
#
|
#
|
||||||
|
|
||||||
def to_h
|
def to_h(&blk)
|
||||||
h = {}
|
h = {}
|
||||||
self.each do |*v|
|
if blk
|
||||||
v = v.__svalue
|
self.each do |v|
|
||||||
raise TypeError, "wrong element type #{v.class} (expected Array)" unless v.is_a? Array
|
v = blk.call(v)
|
||||||
raise ArgumentError, "element has wrong array length (expected 2, was #{v.size})" if v.size != 2
|
raise TypeError, "wrong element type #{v.class} (expected Array)" unless v.is_a? Array
|
||||||
h[v[0]] = v[1]
|
raise ArgumentError, "element has wrong array length (expected 2, was #{v.size})" if v.size != 2
|
||||||
|
h[v[0]] = v[1]
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.each do |*v|
|
||||||
|
v = v.__svalue
|
||||||
|
raise TypeError, "wrong element type #{v.class} (expected Array)" unless v.is_a? Array
|
||||||
|
raise ArgumentError, "element has wrong array length (expected 2, was #{v.size})" if v.size != 2
|
||||||
|
h[v[0]] = v[1]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
h
|
h
|
||||||
end
|
end
|
||||||
@@ -708,4 +815,20 @@ module Enumerable
|
|||||||
def nil.to_h
|
def nil.to_h
|
||||||
{}
|
{}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def uniq(&block)
|
||||||
|
hash = {}
|
||||||
|
if block
|
||||||
|
self.each do|*v|
|
||||||
|
v = v.__svalue
|
||||||
|
hash[block.call(v)] ||= v
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.each do|*v|
|
||||||
|
v = v.__svalue
|
||||||
|
hash[v] ||= v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
hash.values
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ end
|
|||||||
assert("Enumerable#none?") do
|
assert("Enumerable#none?") do
|
||||||
assert_true %w(ant bear cat).none? { |word| word.length == 5 }
|
assert_true %w(ant bear cat).none? { |word| word.length == 5 }
|
||||||
assert_false %w(ant bear cat).none? { |word| word.length >= 4 }
|
assert_false %w(ant bear cat).none? { |word| word.length >= 4 }
|
||||||
|
assert_false [1, 3.14, 42].none?(Float)
|
||||||
assert_true [].none?
|
assert_true [].none?
|
||||||
assert_true [nil, false].none?
|
assert_true [nil, false].none?
|
||||||
assert_false [nil, true].none?
|
assert_false [nil, true].none?
|
||||||
@@ -109,8 +110,21 @@ assert("Enumerable#one?") do
|
|||||||
assert_true %w(ant bear cat).one? { |word| word.length == 4 }
|
assert_true %w(ant bear cat).one? { |word| word.length == 4 }
|
||||||
assert_false %w(ant bear cat).one? { |word| word.length > 4 }
|
assert_false %w(ant bear cat).one? { |word| word.length > 4 }
|
||||||
assert_false %w(ant bear cat).one? { |word| word.length < 4 }
|
assert_false %w(ant bear cat).one? { |word| word.length < 4 }
|
||||||
|
assert_true [1, 3.14, 42].one?(Float)
|
||||||
assert_false [nil, true, 99].one?
|
assert_false [nil, true, 99].one?
|
||||||
assert_true [nil, true, false].one?
|
assert_true [nil, true, false].one?
|
||||||
|
assert_true [ nil, true, 99 ].one?(Integer)
|
||||||
|
assert_false [].one?
|
||||||
|
end
|
||||||
|
|
||||||
|
assert("Enumerable#all? (enhancement)") do
|
||||||
|
assert_false [1, 2, 3.14].all?(Integer)
|
||||||
|
assert_true [1, 2, 3.14].all?(Numeric)
|
||||||
|
end
|
||||||
|
|
||||||
|
assert("Enumerable#any? (enhancement)") do
|
||||||
|
assert_false [1, 2, 3].all?(Float)
|
||||||
|
assert_true [nil, true, 99].any?(Integer)
|
||||||
end
|
end
|
||||||
|
|
||||||
assert("Enumerable#each_with_object") do
|
assert("Enumerable#each_with_object") do
|
||||||
@@ -152,6 +166,12 @@ assert("Enumerable#zip") do
|
|||||||
assert_equal [[1, 4, 7], [2, 5, 8], [3, 6, 9]], [1, 2, 3].zip(a, b)
|
assert_equal [[1, 4, 7], [2, 5, 8], [3, 6, 9]], [1, 2, 3].zip(a, b)
|
||||||
assert_equal [[1, 4, 7], [2, 5, 8]], [1, 2].zip(a, b)
|
assert_equal [[1, 4, 7], [2, 5, 8]], [1, 2].zip(a, b)
|
||||||
assert_equal [[4, 1, 8], [5, 2, nil], [6, nil, nil]], a.zip([1, 2], [8])
|
assert_equal [[4, 1, 8], [5, 2, nil], [6, nil, nil]], a.zip([1, 2], [8])
|
||||||
|
|
||||||
|
ret = []
|
||||||
|
assert_equal nil, a.zip([1, 2], [8]) { |i| ret << i }
|
||||||
|
assert_equal [[4, 1, 8], [5, 2, nil], [6, nil, nil]], ret
|
||||||
|
|
||||||
|
assert_raise(TypeError) { [1].zip(1) }
|
||||||
end
|
end
|
||||||
|
|
||||||
assert("Enumerable#to_h") do
|
assert("Enumerable#to_h") do
|
||||||
@@ -168,4 +188,6 @@ assert("Enumerable#to_h") do
|
|||||||
assert_equal h0, h
|
assert_equal h0, h
|
||||||
# mruby-enum-ext also provides nil.to_h
|
# mruby-enum-ext also provides nil.to_h
|
||||||
assert_equal Hash.new, nil.to_h
|
assert_equal Hash.new, nil.to_h
|
||||||
|
|
||||||
|
assert_equal({1=>4,3=>8}, c.new.to_h{|k,v|[k,v*2]})
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ class Enumerator
|
|||||||
end
|
end
|
||||||
|
|
||||||
def to_enum(meth=:each, *args, &block)
|
def to_enum(meth=:each, *args, &block)
|
||||||
|
unless self.respond_to?(meth)
|
||||||
|
raise ArgumentError, "undefined method #{meth}"
|
||||||
|
end
|
||||||
lz = Lazy.new(self, &block)
|
lz = Lazy.new(self, &block)
|
||||||
lz.obj = self
|
lz.obj = self
|
||||||
lz.meth = meth
|
lz.meth = meth
|
||||||
@@ -69,7 +72,7 @@ class Enumerator
|
|||||||
|
|
||||||
def reject(&block)
|
def reject(&block)
|
||||||
Lazy.new(self){|yielder, val|
|
Lazy.new(self){|yielder, val|
|
||||||
if not block.call(val)
|
unless block.call(val)
|
||||||
yielder << val
|
yielder << val
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
@@ -155,6 +158,21 @@ class Enumerator
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def uniq(&block)
|
||||||
|
hash = {}
|
||||||
|
Lazy.new(self){|yielder, val|
|
||||||
|
if block
|
||||||
|
v = block.call(val)
|
||||||
|
else
|
||||||
|
v = val
|
||||||
|
end
|
||||||
|
unless hash.include?(v)
|
||||||
|
yielder << val
|
||||||
|
hash[v] = val
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
alias force to_a
|
alias force to_a
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ assert("Enumerator::Lazy laziness") do
|
|||||||
assert_equal [10,20], a.b
|
assert_equal [10,20], a.b
|
||||||
end
|
end
|
||||||
|
|
||||||
assert("Enumrator::Lazy#to_enum") do
|
assert("Enumerator::Lazy#to_enum") do
|
||||||
lazy_enum = (0..Float::INFINITY).lazy.to_enum(:each_slice, 2)
|
lazy_enum = (0..Float::INFINITY).lazy.to_enum(:each_slice, 2)
|
||||||
assert_kind_of Enumerator::Lazy, lazy_enum
|
assert_kind_of Enumerator::Lazy, lazy_enum
|
||||||
assert_equal [0*1, 2*3, 4*5, 6*7], lazy_enum.map { |a| a.first * a.last }.first(4)
|
assert_equal [0*1, 2*3, 4*5, 6*7], lazy_enum.map { |a| a.first * a.last }.first(4)
|
||||||
|
|||||||
@@ -110,11 +110,14 @@ class Enumerator
|
|||||||
# p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
|
# p fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
|
||||||
#
|
#
|
||||||
def initialize(obj=nil, meth=:each, *args, &block)
|
def initialize(obj=nil, meth=:each, *args, &block)
|
||||||
if block_given?
|
if block
|
||||||
obj = Generator.new(&block)
|
obj = Generator.new(&block)
|
||||||
else
|
else
|
||||||
raise ArgumentError unless obj
|
raise ArgumentError unless obj
|
||||||
end
|
end
|
||||||
|
if @obj and !self.respond_to?(meth)
|
||||||
|
raise NoMethodError, "undefined method #{meth}"
|
||||||
|
end
|
||||||
|
|
||||||
@obj = obj
|
@obj = obj
|
||||||
@meth = meth
|
@meth = meth
|
||||||
@@ -151,20 +154,19 @@ class Enumerator
|
|||||||
#
|
#
|
||||||
# +offset+:: the starting index to use
|
# +offset+:: the starting index to use
|
||||||
#
|
#
|
||||||
def with_index(offset=0)
|
def with_index(offset=0, &block)
|
||||||
return to_enum :with_index, offset unless block_given?
|
return to_enum :with_index, offset unless block
|
||||||
offset = if offset.nil?
|
|
||||||
0
|
if offset.nil?
|
||||||
elsif offset.respond_to?(:to_int)
|
offset = 0
|
||||||
offset.to_int
|
|
||||||
else
|
else
|
||||||
raise TypeError, "no implicit conversion of #{offset.class} into Integer"
|
offset = offset.__to_int
|
||||||
end
|
end
|
||||||
|
|
||||||
n = offset - 1
|
n = offset - 1
|
||||||
enumerator_block_call do |*i|
|
enumerator_block_call do |*i|
|
||||||
n += 1
|
n += 1
|
||||||
yield i.__svalue, n
|
block.call i.__svalue, n
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -209,11 +211,11 @@ class Enumerator
|
|||||||
# # => foo:1
|
# # => foo:1
|
||||||
# # => foo:2
|
# # => foo:2
|
||||||
#
|
#
|
||||||
def with_object(object)
|
def with_object(object, &block)
|
||||||
return to_enum(:with_object, object) unless block_given?
|
return to_enum(:with_object, object) unless block
|
||||||
|
|
||||||
enumerator_block_call do |i|
|
enumerator_block_call do |i|
|
||||||
yield [i,object]
|
block.call [i,object]
|
||||||
end
|
end
|
||||||
object
|
object
|
||||||
end
|
end
|
||||||
@@ -277,7 +279,7 @@ class Enumerator
|
|||||||
end
|
end
|
||||||
obj.args = args
|
obj.args = args
|
||||||
end
|
end
|
||||||
return obj unless block_given?
|
return obj unless block
|
||||||
enumerator_block_call(&block)
|
enumerator_block_call(&block)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -538,7 +540,7 @@ class Enumerator
|
|||||||
# just for internal
|
# just for internal
|
||||||
class Yielder
|
class Yielder
|
||||||
def initialize(&block)
|
def initialize(&block)
|
||||||
raise LocalJumpError, "no block given" unless block_given?
|
raise LocalJumpError, "no block given" unless block
|
||||||
|
|
||||||
@proc = block
|
@proc = block
|
||||||
end
|
end
|
||||||
@@ -610,32 +612,48 @@ module Kernel
|
|||||||
# enum.first(4) # => [1, 1, 1, 2]
|
# enum.first(4) # => [1, 1, 1, 2]
|
||||||
#
|
#
|
||||||
def to_enum(meth=:each, *args)
|
def to_enum(meth=:each, *args)
|
||||||
|
unless self.respond_to?(meth)
|
||||||
|
raise ArgumentError, "undefined method #{meth}"
|
||||||
|
end
|
||||||
Enumerator.new self, meth, *args
|
Enumerator.new self, meth, *args
|
||||||
end
|
end
|
||||||
alias :enum_for :to_enum
|
alias enum_for to_enum
|
||||||
end
|
end
|
||||||
|
|
||||||
module Enumerable
|
module Enumerable
|
||||||
# use Enumerator to use infinite sequence
|
# use Enumerator to use infinite sequence
|
||||||
def zip(*arg)
|
def zip(*args, &block)
|
||||||
ary = []
|
args = args.map do |a|
|
||||||
arg = arg.map{|a|a.each}
|
if a.respond_to?(:each)
|
||||||
i = 0
|
a.to_enum(:each)
|
||||||
self.each do |*val|
|
else
|
||||||
a = []
|
raise TypeError, "wrong argument type #{a.class} (must respond to :each)"
|
||||||
a.push(val.__svalue)
|
|
||||||
idx = 0
|
|
||||||
while idx < arg.size
|
|
||||||
begin
|
|
||||||
a.push(arg[idx].next)
|
|
||||||
rescue StopIteration
|
|
||||||
a.push(nil)
|
|
||||||
end
|
|
||||||
idx += 1
|
|
||||||
end
|
end
|
||||||
ary.push(a)
|
|
||||||
i += 1
|
|
||||||
end
|
end
|
||||||
ary
|
|
||||||
|
result = block ? nil : []
|
||||||
|
|
||||||
|
each do |*val|
|
||||||
|
tmp = [val.__svalue]
|
||||||
|
args.each do |arg|
|
||||||
|
v = if arg.nil?
|
||||||
|
nil
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
arg.next
|
||||||
|
rescue StopIteration
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
tmp.push(v)
|
||||||
|
end
|
||||||
|
if result.nil?
|
||||||
|
block.call(tmp)
|
||||||
|
else
|
||||||
|
result.push(tmp)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
result
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ assert 'Enumerator.new' do
|
|||||||
assert_equal [1,2,3], Enumerator.new(@obj, :foo, 1,2,3).to_a
|
assert_equal [1,2,3], Enumerator.new(@obj, :foo, 1,2,3).to_a
|
||||||
assert_equal [1,2,3], Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.take(3)
|
assert_equal [1,2,3], Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.take(3)
|
||||||
assert_raise(ArgumentError) { Enumerator.new }
|
assert_raise(ArgumentError) { Enumerator.new }
|
||||||
enum = @obj.to_enum
|
assert_raise(ArgumentError) { @obj.to_enum }
|
||||||
assert_raise(NoMethodError) { enum.each {} }
|
|
||||||
|
|
||||||
# examples
|
# examples
|
||||||
fib = Enumerator.new do |y|
|
fib = Enumerator.new do |y|
|
||||||
@@ -33,7 +32,7 @@ assert 'Enumerator.new' do
|
|||||||
a, b = b, a + b
|
a, b = b, a + b
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
assert_equal fib.take(10), [1,1,2,3,5,8,13,21,34,55]
|
assert_equal [1,1,2,3,5,8,13,21,34,55], fib.take(10)
|
||||||
end
|
end
|
||||||
|
|
||||||
assert 'Enumerator#initialize_copy' do
|
assert 'Enumerator#initialize_copy' do
|
||||||
@@ -55,12 +54,6 @@ assert 'Enumerator#with_index' do
|
|||||||
assert_equal [[[1, 10], 20], [[2, 11], 21], [[3, 12], 22]], a
|
assert_equal [[[1, 10], 20], [[2, 11], 21], [[3, 12], 22]], a
|
||||||
end
|
end
|
||||||
|
|
||||||
assert 'Enumerator#with_index nonnum offset' do
|
|
||||||
s = Object.new
|
|
||||||
def s.to_int; 1 end
|
|
||||||
assert_equal([[1,1],[2,2],[3,3]], @obj.to_enum(:foo, 1, 2, 3).with_index(s).to_a)
|
|
||||||
end
|
|
||||||
|
|
||||||
assert 'Enumerator#with_index string offset' do
|
assert 'Enumerator#with_index string offset' do
|
||||||
assert_raise(TypeError){ @obj.to_enum(:foo, 1, 2, 3).with_index('1').to_a }
|
assert_raise(TypeError){ @obj.to_enum(:foo, 1, 2, 3).with_index('1').to_a }
|
||||||
end
|
end
|
||||||
@@ -509,28 +502,28 @@ end
|
|||||||
|
|
||||||
assert 'Hash#select' do
|
assert 'Hash#select' do
|
||||||
h = {1=>2,3=>4,5=>6}
|
h = {1=>2,3=>4,5=>6}
|
||||||
hret = h.select.with_index {|a,b| a[1] == 4}
|
hret = h.select.with_index {|a,_b| a[1] == 4}
|
||||||
assert_equal({3=>4}, hret)
|
assert_equal({3=>4}, hret)
|
||||||
assert_equal({1=>2,3=>4,5=>6}, h)
|
assert_equal({1=>2,3=>4,5=>6}, h)
|
||||||
end
|
end
|
||||||
|
|
||||||
assert 'Hash#select!' do
|
assert 'Hash#select!' do
|
||||||
h = {1=>2,3=>4,5=>6}
|
h = {1=>2,3=>4,5=>6}
|
||||||
hret = h.select!.with_index {|a,b| a[1] == 4}
|
hret = h.select!.with_index {|a,_b| a[1] == 4}
|
||||||
assert_equal h, hret
|
assert_equal h, hret
|
||||||
assert_equal({3=>4}, h)
|
assert_equal({3=>4}, h)
|
||||||
end
|
end
|
||||||
|
|
||||||
assert 'Hash#reject' do
|
assert 'Hash#reject' do
|
||||||
h = {1=>2,3=>4,5=>6}
|
h = {1=>2,3=>4,5=>6}
|
||||||
hret = h.reject.with_index {|a,b| a[1] == 4}
|
hret = h.reject.with_index {|a,_b| a[1] == 4}
|
||||||
assert_equal({1=>2,5=>6}, hret)
|
assert_equal({1=>2,5=>6}, hret)
|
||||||
assert_equal({1=>2,3=>4,5=>6}, h)
|
assert_equal({1=>2,3=>4,5=>6}, h)
|
||||||
end
|
end
|
||||||
|
|
||||||
assert 'Hash#reject!' do
|
assert 'Hash#reject!' do
|
||||||
h = {1=>2,3=>4,5=>6}
|
h = {1=>2,3=>4,5=>6}
|
||||||
hret = h.reject!.with_index {|a,b| a[1] == 4}
|
hret = h.reject!.with_index {|a,_b| a[1] == 4}
|
||||||
assert_equal h, hret
|
assert_equal h, hret
|
||||||
assert_equal({1=>2,5=>6}, h)
|
assert_equal({1=>2,5=>6}, h)
|
||||||
end
|
end
|
||||||
@@ -544,3 +537,13 @@ assert 'Range#each' do
|
|||||||
end
|
end
|
||||||
assert_equal [1,2,3,4,5], c
|
assert_equal [1,2,3,4,5], c
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assert 'Enumerable#zip' do
|
||||||
|
assert_equal [[1, 10], [2, 11], [3, 12]], [1,2,3].zip(10..Float::INFINITY)
|
||||||
|
|
||||||
|
ret = []
|
||||||
|
assert_equal nil, [1,2,3].zip(10..Float::INFINITY) { |i| ret << i }
|
||||||
|
assert_equal [[1, 10], [2, 11], [3, 12]], ret
|
||||||
|
|
||||||
|
assert_raise(TypeError) { [1].zip(1) }
|
||||||
|
end
|
||||||
|
|||||||
+183
-79
@@ -12,35 +12,39 @@ mrb_value mrb_obj_instance_eval(mrb_state *mrb, mrb_value self);
|
|||||||
static struct mrb_irep *
|
static struct mrb_irep *
|
||||||
get_closure_irep(mrb_state *mrb, int level)
|
get_closure_irep(mrb_state *mrb, int level)
|
||||||
{
|
{
|
||||||
struct mrb_context *c = mrb->c;
|
struct RProc *proc = mrb->c->ci[-1].proc;
|
||||||
struct REnv *e = c->ci[-1].proc->env;
|
|
||||||
struct RProc *proc;
|
|
||||||
|
|
||||||
if (level == 0) {
|
while (level--) {
|
||||||
proc = c->ci[-1].proc;
|
if (!proc) return NULL;
|
||||||
if (MRB_PROC_CFUNC_P(proc)) {
|
proc = proc->upper;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return proc->body.irep;
|
|
||||||
}
|
}
|
||||||
|
if (!proc) return NULL;
|
||||||
while (--level) {
|
if (MRB_PROC_CFUNC_P(proc)) {
|
||||||
e = (struct REnv*)e->c;
|
|
||||||
if (!e) return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!e) return NULL;
|
|
||||||
if (!MRB_ENV_STACK_SHARED_P(e)) return NULL;
|
|
||||||
c = e->cxt.c;
|
|
||||||
proc = c->cibase[e->cioff].proc;
|
|
||||||
|
|
||||||
if (!proc || MRB_PROC_CFUNC_P(proc)) {
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return proc->body.irep;
|
return proc->body.irep;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline mrb_code
|
/* search for irep lev above the bottom */
|
||||||
|
static mrb_irep*
|
||||||
|
search_irep(mrb_irep *top, int bnest, int lev, mrb_irep *bottom)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i<top->rlen; i++) {
|
||||||
|
mrb_irep* tmp = top->reps[i];
|
||||||
|
|
||||||
|
if (tmp == bottom) return top;
|
||||||
|
tmp = search_irep(tmp, bnest-1, lev, bottom);
|
||||||
|
if (tmp) {
|
||||||
|
if (bnest == lev) return top;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t
|
||||||
search_variable(mrb_state *mrb, mrb_sym vsym, int bnest)
|
search_variable(mrb_state *mrb, mrb_sym vsym, int bnest)
|
||||||
{
|
{
|
||||||
mrb_irep *virep;
|
mrb_irep *virep;
|
||||||
@@ -48,12 +52,12 @@ search_variable(mrb_state *mrb, mrb_sym vsym, int bnest)
|
|||||||
int pos;
|
int pos;
|
||||||
|
|
||||||
for (level = 0; (virep = get_closure_irep(mrb, level)); level++) {
|
for (level = 0; (virep = get_closure_irep(mrb, level)); level++) {
|
||||||
if (!virep || virep->lv == NULL) {
|
if (virep->lv == NULL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (pos = 0; pos < virep->nlocals - 1; pos++) {
|
for (pos = 0; pos < virep->nlocals - 1; pos++) {
|
||||||
if (vsym == virep->lv[pos].name) {
|
if (vsym == virep->lv[pos].name) {
|
||||||
return (MKARG_B(pos + 1) | MKARG_C(level + bnest));
|
return (pos+1)<<8 | (level+bnest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,6 +65,20 @@ search_variable(mrb_state *mrb, mrb_sym vsym, int bnest)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
irep_argc(mrb_irep *irep)
|
||||||
|
{
|
||||||
|
mrb_code c;
|
||||||
|
|
||||||
|
c = irep->iseq[0];
|
||||||
|
if (c == OP_ENTER) {
|
||||||
|
mrb_aspec ax = PEEK_W(irep->iseq+1);
|
||||||
|
/* extra 1 means a slot for block */
|
||||||
|
return MRB_ASPEC_REQ(ax)+MRB_ASPEC_OPT(ax)+MRB_ASPEC_REST(ax)+MRB_ASPEC_POST(ax)+1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static mrb_bool
|
static mrb_bool
|
||||||
potential_upvar_p(struct mrb_locals *lv, uint16_t v, int argc, uint16_t nlocals)
|
potential_upvar_p(struct mrb_locals *lv, uint16_t v, int argc, uint16_t nlocals)
|
||||||
{
|
{
|
||||||
@@ -70,99 +88,159 @@ potential_upvar_p(struct mrb_locals *lv, uint16_t v, int argc, uint16_t nlocals)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern uint8_t mrb_insn_size[];
|
||||||
|
extern uint8_t mrb_insn_size1[];
|
||||||
|
extern uint8_t mrb_insn_size2[];
|
||||||
|
extern uint8_t mrb_insn_size3[];
|
||||||
|
|
||||||
static void
|
static void
|
||||||
patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest)
|
patch_irep(mrb_state *mrb, mrb_irep *irep, int bnest, mrb_irep *top)
|
||||||
{
|
{
|
||||||
size_t i;
|
int i;
|
||||||
mrb_code c;
|
uint32_t a;
|
||||||
int argc = 0;
|
uint16_t b;
|
||||||
|
uint8_t c;
|
||||||
for (i = 0; i < irep->ilen; i++) {
|
mrb_code insn;
|
||||||
c = irep->iseq[i];
|
int argc = irep_argc(irep);
|
||||||
switch(GET_OPCODE(c)){
|
|
||||||
case OP_ENTER:
|
|
||||||
{
|
|
||||||
mrb_aspec ax = GETARG_Ax(c);
|
|
||||||
/* extra 1 means a slot for block */
|
|
||||||
argc = MRB_ASPEC_REQ(ax)+MRB_ASPEC_OPT(ax)+MRB_ASPEC_REST(ax)+MRB_ASPEC_POST(ax)+1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
for (i = 0; i < irep->ilen; ) {
|
||||||
|
insn = irep->iseq[i];
|
||||||
|
switch(insn){
|
||||||
case OP_EPUSH:
|
case OP_EPUSH:
|
||||||
patch_irep(mrb, irep->reps[GETARG_Bx(c)], bnest + 1);
|
b = PEEK_S(irep->iseq+i+1);
|
||||||
|
patch_irep(mrb, irep->reps[b], bnest + 1, top);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_LAMBDA:
|
case OP_LAMBDA:
|
||||||
{
|
case OP_BLOCK:
|
||||||
int arg_c = GETARG_c(c);
|
a = PEEK_B(irep->iseq+i+1);
|
||||||
if (arg_c & OP_L_CAPTURE) {
|
b = PEEK_B(irep->iseq+i+2);
|
||||||
patch_irep(mrb, irep->reps[GETARG_b(c)], bnest + 1);
|
patch_irep(mrb, irep->reps[b], bnest + 1, top);
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_SEND:
|
case OP_SEND:
|
||||||
if (GETARG_C(c) != 0) {
|
b = PEEK_B(irep->iseq+i+2);
|
||||||
|
c = PEEK_B(irep->iseq+i+3);
|
||||||
|
if (c != 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
{
|
else {
|
||||||
mrb_code arg = search_variable(mrb, irep->syms[GETARG_B(c)], bnest);
|
uint16_t arg = search_variable(mrb, irep->syms[b], bnest);
|
||||||
if (arg != 0) {
|
if (arg != 0) {
|
||||||
/* must replace */
|
/* must replace */
|
||||||
irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
|
irep->iseq[i] = OP_GETUPVAR;
|
||||||
|
irep->iseq[i+2] = arg >> 8;
|
||||||
|
irep->iseq[i+3] = arg & 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_MOVE:
|
case OP_MOVE:
|
||||||
|
a = PEEK_B(irep->iseq+i+1);
|
||||||
|
b = PEEK_B(irep->iseq+i+2);
|
||||||
/* src part */
|
/* src part */
|
||||||
if (potential_upvar_p(irep->lv, GETARG_B(c), argc, irep->nlocals)) {
|
if (potential_upvar_p(irep->lv, b, argc, irep->nlocals)) {
|
||||||
mrb_code arg = search_variable(mrb, irep->lv[GETARG_B(c) - 1].name, bnest);
|
uint16_t arg = search_variable(mrb, irep->lv[b - 1].name, bnest);
|
||||||
if (arg != 0) {
|
if (arg != 0) {
|
||||||
/* must replace */
|
/* must replace */
|
||||||
irep->iseq[i] = MKOPCODE(OP_GETUPVAR) | MKARG_A(GETARG_A(c)) | arg;
|
irep->iseq[i] = insn = OP_GETUPVAR;
|
||||||
|
irep->iseq[i+2] = arg >> 8;
|
||||||
|
irep->iseq[i+3] = arg & 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* dst part */
|
/* dst part */
|
||||||
if (potential_upvar_p(irep->lv, GETARG_A(c), argc, irep->nlocals)) {
|
if (potential_upvar_p(irep->lv, a, argc, irep->nlocals)) {
|
||||||
mrb_code arg = search_variable(mrb, irep->lv[GETARG_A(c) - 1].name, bnest);
|
uint16_t arg = search_variable(mrb, irep->lv[a - 1].name, bnest);
|
||||||
if (arg != 0) {
|
if (arg != 0) {
|
||||||
/* must replace */
|
/* must replace */
|
||||||
irep->iseq[i] = MKOPCODE(OP_SETUPVAR) | MKARG_A(GETARG_B(c)) | arg;
|
irep->iseq[i] = insn = OP_SETUPVAR;
|
||||||
|
irep->iseq[i+1] = (mrb_code)b;
|
||||||
|
irep->iseq[i+2] = arg >> 8;
|
||||||
|
irep->iseq[i+3] = arg & 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_STOP:
|
case OP_GETUPVAR:
|
||||||
if (mrb->c->ci->acc >= 0) {
|
a = PEEK_B(irep->iseq+i+1);
|
||||||
irep->iseq[i] = MKOP_AB(OP_RETURN, irep->nlocals, OP_R_NORMAL);
|
b = PEEK_B(irep->iseq+i+2);
|
||||||
|
c = PEEK_B(irep->iseq+i+3);
|
||||||
|
{
|
||||||
|
int lev = c+1;
|
||||||
|
mrb_irep *tmp = search_irep(top, bnest, lev, irep);
|
||||||
|
if (potential_upvar_p(tmp->lv, b, irep_argc(tmp), tmp->nlocals)) {
|
||||||
|
uint16_t arg = search_variable(mrb, tmp->lv[b-1].name, bnest);
|
||||||
|
if (arg != 0) {
|
||||||
|
/* must replace */
|
||||||
|
irep->iseq[i] = OP_GETUPVAR;
|
||||||
|
irep->iseq[i+2] = arg >> 8;
|
||||||
|
irep->iseq[i+3] = arg & 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OP_SETUPVAR:
|
||||||
|
a = PEEK_B(irep->iseq+i+1);
|
||||||
|
b = PEEK_B(irep->iseq+i+2);
|
||||||
|
c = PEEK_B(irep->iseq+i+3);
|
||||||
|
{
|
||||||
|
int lev = c+1;
|
||||||
|
mrb_irep *tmp = search_irep(top, bnest, lev, irep);
|
||||||
|
if (potential_upvar_p(tmp->lv, b, irep_argc(tmp), tmp->nlocals)) {
|
||||||
|
uint16_t arg = search_variable(mrb, tmp->lv[b-1].name, bnest);
|
||||||
|
if (arg != 0) {
|
||||||
|
/* must replace */
|
||||||
|
irep->iseq[i] = OP_SETUPVAR;
|
||||||
|
irep->iseq[i+1] = a;
|
||||||
|
irep->iseq[i+2] = arg >> 8;
|
||||||
|
irep->iseq[i+3] = arg & 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OP_EXT1:
|
||||||
|
insn = PEEK_B(irep->iseq+i+1);
|
||||||
|
i += mrb_insn_size1[insn]+1;
|
||||||
|
continue;
|
||||||
|
case OP_EXT2:
|
||||||
|
insn = PEEK_B(irep->iseq+i+1);
|
||||||
|
i += mrb_insn_size2[insn]+1;
|
||||||
|
continue;
|
||||||
|
case OP_EXT3:
|
||||||
|
insn = PEEK_B(irep->iseq+i+1);
|
||||||
|
i += mrb_insn_size3[insn]+1;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
i+=mrb_insn_size[insn];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mrb_codedump_all(mrb_state*, struct RProc*);
|
void mrb_codedump_all(mrb_state*, struct RProc*);
|
||||||
|
|
||||||
static struct RProc*
|
static struct RProc*
|
||||||
create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, const char *file, mrb_int line)
|
create_proc_from_string(mrb_state *mrb, char *s, mrb_int len, mrb_value binding, const char *file, mrb_int line)
|
||||||
{
|
{
|
||||||
mrbc_context *cxt;
|
mrbc_context *cxt;
|
||||||
struct mrb_parser_state *p;
|
struct mrb_parser_state *p;
|
||||||
struct RProc *proc;
|
struct RProc *proc;
|
||||||
struct REnv *e;
|
struct REnv *e;
|
||||||
struct mrb_context *c = mrb->c;
|
mrb_callinfo *ci; /* callinfo of eval caller */
|
||||||
|
struct RClass *target_class = NULL;
|
||||||
|
int bidx;
|
||||||
|
|
||||||
if (!mrb_nil_p(binding)) {
|
if (!mrb_nil_p(binding)) {
|
||||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "Binding of eval must be nil.");
|
mrb_raise(mrb, E_ARGUMENT_ERROR, "Binding of eval must be nil.");
|
||||||
}
|
}
|
||||||
|
|
||||||
cxt = mrbc_context_new(mrb);
|
cxt = mrbc_context_new(mrb);
|
||||||
cxt->lineno = line;
|
cxt->lineno = (short)line;
|
||||||
|
|
||||||
mrbc_filename(mrb, cxt, file ? file : "(eval)");
|
mrbc_filename(mrb, cxt, file ? file : "(eval)");
|
||||||
cxt->capture_errors = TRUE;
|
cxt->capture_errors = TRUE;
|
||||||
cxt->no_optimize = TRUE;
|
cxt->no_optimize = TRUE;
|
||||||
|
cxt->on_eval = TRUE;
|
||||||
|
|
||||||
p = mrb_parse_nstring(mrb, s, len, cxt);
|
p = mrb_parse_nstring(mrb, s, len, cxt);
|
||||||
|
|
||||||
@@ -198,20 +276,40 @@ create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, con
|
|||||||
mrbc_context_free(mrb, cxt);
|
mrbc_context_free(mrb, cxt);
|
||||||
mrb_raise(mrb, E_SCRIPT_ERROR, "codegen error");
|
mrb_raise(mrb, E_SCRIPT_ERROR, "codegen error");
|
||||||
}
|
}
|
||||||
if (c->ci[-1].proc->target_class) {
|
if (mrb->c->ci > mrb->c->cibase) {
|
||||||
proc->target_class = c->ci[-1].proc->target_class;
|
ci = &mrb->c->ci[-1];
|
||||||
}
|
}
|
||||||
e = c->ci[-1].proc->env;
|
else {
|
||||||
if (!e) e = c->ci[-1].env;
|
ci = mrb->c->cibase;
|
||||||
e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV, (struct RClass*)e);
|
}
|
||||||
e->cxt.c = c;
|
if (ci->proc) {
|
||||||
e->cioff = c->ci - c->cibase;
|
target_class = MRB_PROC_TARGET_CLASS(ci->proc);
|
||||||
e->stack = c->ci->stackent;
|
}
|
||||||
MRB_SET_ENV_STACK_LEN(e, c->ci->proc->body.irep->nlocals);
|
if (ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) {
|
||||||
c->ci->target_class = proc->target_class;
|
if (ci->env) {
|
||||||
c->ci->env = 0;
|
e = ci->env;
|
||||||
proc->env = e;
|
}
|
||||||
patch_irep(mrb, proc->body.irep, 0);
|
else {
|
||||||
|
e = (struct REnv*)mrb_obj_alloc(mrb, MRB_TT_ENV,
|
||||||
|
(struct RClass*)target_class);
|
||||||
|
e->mid = ci->mid;
|
||||||
|
e->stack = ci[1].stackent;
|
||||||
|
e->cxt = mrb->c;
|
||||||
|
MRB_ENV_SET_STACK_LEN(e, ci->proc->body.irep->nlocals);
|
||||||
|
bidx = ci->argc;
|
||||||
|
if (ci->argc < 0) bidx = 2;
|
||||||
|
else bidx += 1;
|
||||||
|
MRB_ENV_SET_BIDX(e, bidx);
|
||||||
|
ci->env = e;
|
||||||
|
}
|
||||||
|
proc->e.env = e;
|
||||||
|
proc->flags |= MRB_PROC_ENVSET;
|
||||||
|
mrb_field_write_barrier(mrb, (struct RBasic*)proc, (struct RBasic*)e);
|
||||||
|
}
|
||||||
|
proc->upper = ci->proc;
|
||||||
|
mrb->c->ci->target_class = target_class;
|
||||||
|
patch_irep(mrb, proc->body.irep, 0, proc->body.irep);
|
||||||
|
/* mrb_codedump_all(mrb, proc); */
|
||||||
|
|
||||||
mrb_parser_free(p);
|
mrb_parser_free(p);
|
||||||
mrbc_context_free(mrb, cxt);
|
mrbc_context_free(mrb, cxt);
|
||||||
@@ -222,13 +320,19 @@ create_proc_from_string(mrb_state *mrb, char *s, int len, mrb_value binding, con
|
|||||||
static mrb_value
|
static mrb_value
|
||||||
exec_irep(mrb_state *mrb, mrb_value self, struct RProc *proc)
|
exec_irep(mrb_state *mrb, mrb_value self, struct RProc *proc)
|
||||||
{
|
{
|
||||||
|
/* no argument passed from eval() */
|
||||||
|
mrb->c->ci->argc = 0;
|
||||||
if (mrb->c->ci->acc < 0) {
|
if (mrb->c->ci->acc < 0) {
|
||||||
mrb_value ret = mrb_top_run(mrb, proc, mrb->c->stack[0], 0);
|
ptrdiff_t cioff = mrb->c->ci - mrb->c->cibase;
|
||||||
|
mrb_value ret = mrb_top_run(mrb, proc, self, 0);
|
||||||
if (mrb->exc) {
|
if (mrb->exc) {
|
||||||
mrb_exc_raise(mrb, mrb_obj_value(mrb->exc));
|
mrb_exc_raise(mrb, mrb_obj_value(mrb->exc));
|
||||||
}
|
}
|
||||||
|
mrb->c->ci = mrb->c->cibase + cioff;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
/* clear block */
|
||||||
|
mrb->c->stack[1] = mrb_nil_value();
|
||||||
return mrb_exec_irep(mrb, self, proc);
|
return mrb_exec_irep(mrb, self, proc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,7 +359,7 @@ f_instance_eval(mrb_state *mrb, mrb_value self)
|
|||||||
mrb_value b;
|
mrb_value b;
|
||||||
mrb_int argc; mrb_value *argv;
|
mrb_int argc; mrb_value *argv;
|
||||||
|
|
||||||
mrb_get_args(mrb, "*&", &argv, &argc, &b);
|
mrb_get_args(mrb, "*!&", &argv, &argc, &b);
|
||||||
|
|
||||||
if (mrb_nil_p(b)) {
|
if (mrb_nil_p(b)) {
|
||||||
char *s;
|
char *s;
|
||||||
@@ -268,9 +372,9 @@ f_instance_eval(mrb_state *mrb, mrb_value self)
|
|||||||
mrb_get_args(mrb, "s|zi", &s, &len, &file, &line);
|
mrb_get_args(mrb, "s|zi", &s, &len, &file, &line);
|
||||||
cv = mrb_singleton_class(mrb, self);
|
cv = mrb_singleton_class(mrb, self);
|
||||||
proc = create_proc_from_string(mrb, s, len, mrb_nil_value(), file, line);
|
proc = create_proc_from_string(mrb, s, len, mrb_nil_value(), file, line);
|
||||||
proc->target_class = mrb_class_ptr(cv);
|
MRB_PROC_SET_TARGET_CLASS(proc, mrb_class_ptr(cv));
|
||||||
mrb->c->ci->env = NULL;
|
|
||||||
mrb_assert(!MRB_PROC_CFUNC_P(proc));
|
mrb_assert(!MRB_PROC_CFUNC_P(proc));
|
||||||
|
mrb->c->ci->target_class = mrb_class_ptr(cv);
|
||||||
return exec_irep(mrb, self, proc);
|
return exec_irep(mrb, self, proc);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ assert('Kernel.eval', '15.3.1.2.3') do
|
|||||||
}
|
}
|
||||||
assert_equal(2) {
|
assert_equal(2) {
|
||||||
a = 10
|
a = 10
|
||||||
Kernel.eval 'def f(a); b=a.send(:+, 1); end'
|
Kernel.eval 'def f(a); b=a+1; end'
|
||||||
f(1)
|
f(1)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
@@ -58,7 +58,7 @@ end
|
|||||||
|
|
||||||
assert('String instance_eval') do
|
assert('String instance_eval') do
|
||||||
obj = Object.new
|
obj = Object.new
|
||||||
obj.instance_variable_set :@test, 'test'
|
obj.instance_eval{ @test = 'test' }
|
||||||
assert_raise(ArgumentError) { obj.instance_eval(0) { } }
|
assert_raise(ArgumentError) { obj.instance_eval(0) { } }
|
||||||
assert_raise(ArgumentError) { obj.instance_eval('0', 'test', 0, 'test') }
|
assert_raise(ArgumentError) { obj.instance_eval('0', 'test', 0, 'test') }
|
||||||
assert_equal(['test.rb', 10]) { obj.instance_eval('[__FILE__, __LINE__]', 'test.rb', 10)}
|
assert_equal(['test.rb', 10]) { obj.instance_eval('[__FILE__, __LINE__]', 'test.rb', 10)}
|
||||||
@@ -99,3 +99,34 @@ assert('Object#instance_eval with begin-rescue-ensure execution order') do
|
|||||||
hell_raiser = HellRaiser.new
|
hell_raiser = HellRaiser.new
|
||||||
assert_equal([:enter_raise_hell, :begin, :rescue, :ensure], hell_raiser.raise_hell)
|
assert_equal([:enter_raise_hell, :begin, :rescue, :ensure], hell_raiser.raise_hell)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assert('Kernel#instance_eval() to define singleton methods Issue #3141') do
|
||||||
|
foo_class = Class.new do
|
||||||
|
def bar(x)
|
||||||
|
instance_eval "def baz; #{x}; end"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
f1 = foo_class.new
|
||||||
|
f2 = foo_class.new
|
||||||
|
f1.bar 1
|
||||||
|
f2.bar 2
|
||||||
|
assert_equal(1){f1.baz}
|
||||||
|
assert_equal(2){f2.baz}
|
||||||
|
end
|
||||||
|
|
||||||
|
assert('Kernel.#eval(string) Issue #4021') do
|
||||||
|
assert_equal('FOO') { (eval <<'EOS').call }
|
||||||
|
foo = "FOO"
|
||||||
|
Proc.new { foo }
|
||||||
|
EOS
|
||||||
|
assert_equal('FOO') {
|
||||||
|
def do_eval(code)
|
||||||
|
eval(code)
|
||||||
|
end
|
||||||
|
do_eval(<<'EOS').call
|
||||||
|
foo = "FOO"
|
||||||
|
Proc.new { foo }
|
||||||
|
EOS
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ f_exit(mrb_state *mrb, mrb_value self)
|
|||||||
mrb_int i = EXIT_SUCCESS;
|
mrb_int i = EXIT_SUCCESS;
|
||||||
|
|
||||||
mrb_get_args(mrb, "|i", &i);
|
mrb_get_args(mrb, "|i", &i);
|
||||||
exit(i);
|
exit((int)i);
|
||||||
/* not reached */
|
/* not reached */
|
||||||
return mrb_nil_value();
|
return mrb_nil_value();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,10 +123,10 @@ fiber_init(mrb_state *mrb, mrb_value self)
|
|||||||
|
|
||||||
/* adjust return callinfo */
|
/* adjust return callinfo */
|
||||||
ci = c->ci;
|
ci = c->ci;
|
||||||
ci->target_class = p->target_class;
|
ci->target_class = MRB_PROC_TARGET_CLASS(p);
|
||||||
ci->proc = p;
|
ci->proc = p;
|
||||||
|
mrb_field_write_barrier(mrb, (struct RBasic*)mrb_obj_ptr(self), (struct RBasic*)p);
|
||||||
ci->pc = p->body.irep->iseq;
|
ci->pc = p->body.irep->iseq;
|
||||||
ci->nregs = p->body.irep->nregs;
|
|
||||||
ci[1] = ci[0];
|
ci[1] = ci[0];
|
||||||
c->ci++; /* push dummy callinfo */
|
c->ci++; /* push dummy callinfo */
|
||||||
|
|
||||||
@@ -186,38 +186,41 @@ fiber_switch(mrb_state *mrb, mrb_value self, mrb_int len, const mrb_value *a, mr
|
|||||||
{
|
{
|
||||||
struct mrb_context *c = fiber_check(mrb, self);
|
struct mrb_context *c = fiber_check(mrb, self);
|
||||||
struct mrb_context *old_c = mrb->c;
|
struct mrb_context *old_c = mrb->c;
|
||||||
|
enum mrb_fiber_state status;
|
||||||
mrb_value value;
|
mrb_value value;
|
||||||
|
|
||||||
fiber_check_cfunc(mrb, c);
|
fiber_check_cfunc(mrb, c);
|
||||||
if (resume && c->status == MRB_FIBER_TRANSFERRED) {
|
status = c->status;
|
||||||
|
if (resume && status == MRB_FIBER_TRANSFERRED) {
|
||||||
mrb_raise(mrb, E_FIBER_ERROR, "resuming transferred fiber");
|
mrb_raise(mrb, E_FIBER_ERROR, "resuming transferred fiber");
|
||||||
}
|
}
|
||||||
if (c->status == MRB_FIBER_RUNNING || c->status == MRB_FIBER_RESUMED) {
|
if (status == MRB_FIBER_RUNNING || status == MRB_FIBER_RESUMED) {
|
||||||
mrb_raise(mrb, E_FIBER_ERROR, "double resume (fib)");
|
mrb_raise(mrb, E_FIBER_ERROR, "double resume");
|
||||||
}
|
}
|
||||||
if (c->status == MRB_FIBER_TERMINATED) {
|
if (status == MRB_FIBER_TERMINATED) {
|
||||||
mrb_raise(mrb, E_FIBER_ERROR, "resuming dead fiber");
|
mrb_raise(mrb, E_FIBER_ERROR, "resuming dead fiber");
|
||||||
}
|
}
|
||||||
mrb->c->status = resume ? MRB_FIBER_RESUMED : MRB_FIBER_TRANSFERRED;
|
old_c->status = resume ? MRB_FIBER_RESUMED : MRB_FIBER_TRANSFERRED;
|
||||||
c->prev = resume ? mrb->c : (c->prev ? c->prev : mrb->root_c);
|
c->prev = resume ? mrb->c : (c->prev ? c->prev : mrb->root_c);
|
||||||
if (c->status == MRB_FIBER_CREATED) {
|
fiber_switch_context(mrb, c);
|
||||||
|
if (status == MRB_FIBER_CREATED) {
|
||||||
mrb_value *b, *e;
|
mrb_value *b, *e;
|
||||||
|
|
||||||
if (len >= c->stend - c->stack) {
|
if (!c->ci->proc) {
|
||||||
mrb_raise(mrb, E_FIBER_ERROR, "too many arguments to fiber");
|
mrb_raise(mrb, E_FIBER_ERROR, "double resume (current)");
|
||||||
}
|
}
|
||||||
|
mrb_stack_extend(mrb, len+2); /* for receiver and (optional) block */
|
||||||
b = c->stack+1;
|
b = c->stack+1;
|
||||||
e = b + len;
|
e = b + len;
|
||||||
while (b<e) {
|
while (b<e) {
|
||||||
*b++ = *a++;
|
*b++ = *a++;
|
||||||
}
|
}
|
||||||
c->cibase->argc = len;
|
c->cibase->argc = (int)len;
|
||||||
value = c->stack[0] = c->ci->proc->env->stack[0];
|
value = c->stack[0] = MRB_PROC_ENV(c->ci->proc)->stack[0];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
value = fiber_result(mrb, a, len);
|
value = fiber_result(mrb, a, len);
|
||||||
}
|
}
|
||||||
fiber_switch_context(mrb, c);
|
|
||||||
|
|
||||||
if (vmexec) {
|
if (vmexec) {
|
||||||
c->vmexec = TRUE;
|
c->vmexec = TRUE;
|
||||||
@@ -252,7 +255,7 @@ fiber_resume(mrb_state *mrb, mrb_value self)
|
|||||||
mrb_int len;
|
mrb_int len;
|
||||||
mrb_bool vmexec = FALSE;
|
mrb_bool vmexec = FALSE;
|
||||||
|
|
||||||
mrb_get_args(mrb, "*", &a, &len);
|
mrb_get_args(mrb, "*!", &a, &len);
|
||||||
if (mrb->c->ci->acc < 0) {
|
if (mrb->c->ci->acc < 0) {
|
||||||
vmexec = TRUE;
|
vmexec = TRUE;
|
||||||
}
|
}
|
||||||
@@ -273,12 +276,13 @@ mrb_fiber_resume(mrb_state *mrb, mrb_value fib, mrb_int len, const mrb_value *a)
|
|||||||
* Returns true if the fiber can still be resumed. After finishing
|
* Returns true if the fiber can still be resumed. After finishing
|
||||||
* execution of the fiber block this method will always return false.
|
* execution of the fiber block this method will always return false.
|
||||||
*/
|
*/
|
||||||
static mrb_value
|
MRB_API mrb_value
|
||||||
fiber_alive_p(mrb_state *mrb, mrb_value self)
|
mrb_fiber_alive_p(mrb_state *mrb, mrb_value self)
|
||||||
{
|
{
|
||||||
struct mrb_context *c = fiber_check(mrb, self);
|
struct mrb_context *c = fiber_check(mrb, self);
|
||||||
return mrb_bool_value(c->status != MRB_FIBER_TERMINATED);
|
return mrb_bool_value(c->status != MRB_FIBER_TERMINATED);
|
||||||
}
|
}
|
||||||
|
#define fiber_alive_p mrb_fiber_alive_p
|
||||||
|
|
||||||
static mrb_value
|
static mrb_value
|
||||||
fiber_eq(mrb_state *mrb, mrb_value self)
|
fiber_eq(mrb_state *mrb, mrb_value self)
|
||||||
@@ -312,7 +316,7 @@ fiber_transfer(mrb_state *mrb, mrb_value self)
|
|||||||
mrb_int len;
|
mrb_int len;
|
||||||
|
|
||||||
fiber_check_cfunc(mrb, mrb->c);
|
fiber_check_cfunc(mrb, mrb->c);
|
||||||
mrb_get_args(mrb, "*", &a, &len);
|
mrb_get_args(mrb, "*!", &a, &len);
|
||||||
|
|
||||||
if (c == mrb->root_c) {
|
if (c == mrb->root_c) {
|
||||||
mrb->c->status = MRB_FIBER_TRANSFERRED;
|
mrb->c->status = MRB_FIBER_TRANSFERRED;
|
||||||
@@ -370,7 +374,7 @@ fiber_yield(mrb_state *mrb, mrb_value self)
|
|||||||
mrb_value *a;
|
mrb_value *a;
|
||||||
mrb_int len;
|
mrb_int len;
|
||||||
|
|
||||||
mrb_get_args(mrb, "*", &a, &len);
|
mrb_get_args(mrb, "*!", &a, &len);
|
||||||
return mrb_fiber_yield(mrb, len, a);
|
return mrb_fiber_yield(mrb, len, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ MRuby::Gem::Specification.new('mruby-hash-ext') do |spec|
|
|||||||
spec.license = 'MIT'
|
spec.license = 'MIT'
|
||||||
spec.author = 'mruby developers'
|
spec.author = 'mruby developers'
|
||||||
spec.summary = 'Hash class extension'
|
spec.summary = 'Hash class extension'
|
||||||
spec.add_dependency 'mruby-enum-ext', :core => 'mruby-enum-ext'
|
spec.add_dependency 'mruby-enum-ext', core: 'mruby-enum-ext'
|
||||||
spec.add_dependency 'mruby-array-ext', :core => 'mruby-array-ext'
|
spec.add_dependency 'mruby-array-ext', core: 'mruby-array-ext'
|
||||||
|
spec.add_test_dependency 'mruby-enumerator', core: 'mruby-enumerator'
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ class Hash
|
|||||||
length = object.length
|
length = object.length
|
||||||
if length == 1
|
if length == 1
|
||||||
o = object[0]
|
o = object[0]
|
||||||
if o.respond_to?(:to_hash)
|
if Hash === o
|
||||||
h = self.new
|
h = self.new
|
||||||
object[0].to_hash.each { |k, v| h[k] = v }
|
o.each { |k, v| h[k] = v }
|
||||||
return h
|
return h
|
||||||
elsif o.respond_to?(:to_a)
|
elsif o.respond_to?(:to_a)
|
||||||
h = self.new
|
h = self.new
|
||||||
@@ -60,25 +60,6 @@ class Hash
|
|||||||
h
|
h
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
|
||||||
# call-seq:
|
|
||||||
# Hash.try_convert(obj) -> hash or nil
|
|
||||||
#
|
|
||||||
# Try to convert <i>obj</i> into a hash, using to_hash method.
|
|
||||||
# Returns converted hash or nil if <i>obj</i> cannot be converted
|
|
||||||
# for any reason.
|
|
||||||
#
|
|
||||||
# Hash.try_convert({1=>2}) # => {1=>2}
|
|
||||||
# Hash.try_convert("1=>2") # => nil
|
|
||||||
#
|
|
||||||
def self.try_convert(obj)
|
|
||||||
if obj.respond_to?(:to_hash)
|
|
||||||
obj.to_hash
|
|
||||||
else
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# call-seq:
|
# call-seq:
|
||||||
# hsh.merge!(other_hash) -> hsh
|
# hsh.merge!(other_hash) -> hsh
|
||||||
@@ -101,7 +82,7 @@ class Hash
|
|||||||
#
|
#
|
||||||
|
|
||||||
def merge!(other, &block)
|
def merge!(other, &block)
|
||||||
raise TypeError, "can't convert argument into Hash" unless other.respond_to?(:to_hash)
|
raise TypeError, "Hash required (#{other.class} given)" unless Hash === other
|
||||||
if block
|
if block
|
||||||
other.each_key{|k|
|
other.each_key{|k|
|
||||||
self[k] = (self.has_key?(k))? block.call(k, self[k], other[k]): other[k]
|
self[k] = (self.has_key?(k))? block.call(k, self[k], other[k]): other[k]
|
||||||
@@ -114,6 +95,51 @@ class Hash
|
|||||||
|
|
||||||
alias update merge!
|
alias update merge!
|
||||||
|
|
||||||
|
##
|
||||||
|
# call-seq:
|
||||||
|
# hsh.compact! -> hsh
|
||||||
|
#
|
||||||
|
# Removes all nil values from the hash. Returns the hash.
|
||||||
|
# Returns nil if the hash does not contain nil values.
|
||||||
|
#
|
||||||
|
# h = { a: 1, b: false, c: nil }
|
||||||
|
# h.compact! #=> { a: 1, b: false }
|
||||||
|
#
|
||||||
|
|
||||||
|
def compact!
|
||||||
|
keys = self.keys
|
||||||
|
nk = keys.select{|k|
|
||||||
|
self[k] != nil
|
||||||
|
}
|
||||||
|
return nil if (keys.size == nk.size)
|
||||||
|
h = {}
|
||||||
|
nk.each {|k|
|
||||||
|
h[k] = self[k]
|
||||||
|
}
|
||||||
|
h
|
||||||
|
self.replace(h)
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# call-seq:
|
||||||
|
# hsh.compact -> new_hsh
|
||||||
|
#
|
||||||
|
# Returns a new hash with the nil values/key pairs removed
|
||||||
|
#
|
||||||
|
# h = { a: 1, b: false, c: nil }
|
||||||
|
# h.compact #=> { a: 1, b: false }
|
||||||
|
# h #=> { a: 1, b: false, c: nil }
|
||||||
|
#
|
||||||
|
def compact
|
||||||
|
h = {}
|
||||||
|
self.keys.select{|k|
|
||||||
|
self[k] != nil
|
||||||
|
}.each {|k|
|
||||||
|
h[k] = self[k]
|
||||||
|
}
|
||||||
|
h
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# call-seq:
|
# call-seq:
|
||||||
# hsh.fetch(key [, default] ) -> obj
|
# hsh.fetch(key [, default] ) -> obj
|
||||||
@@ -149,7 +175,7 @@ class Hash
|
|||||||
elsif none != NONE
|
elsif none != NONE
|
||||||
none
|
none
|
||||||
else
|
else
|
||||||
raise KeyError, "Key not found: #{key}"
|
raise KeyError, "Key not found: #{key.inspect}"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self[key]
|
self[key]
|
||||||
@@ -171,7 +197,7 @@ class Hash
|
|||||||
#
|
#
|
||||||
|
|
||||||
def delete_if(&block)
|
def delete_if(&block)
|
||||||
return to_enum :delete_if unless block_given?
|
return to_enum :delete_if unless block
|
||||||
|
|
||||||
self.each do |k, v|
|
self.each do |k, v|
|
||||||
self.delete(k) if block.call(k, v)
|
self.delete(k) if block.call(k, v)
|
||||||
@@ -228,7 +254,7 @@ class Hash
|
|||||||
#
|
#
|
||||||
|
|
||||||
def keep_if(&block)
|
def keep_if(&block)
|
||||||
return to_enum :keep_if unless block_given?
|
return to_enum :keep_if unless block
|
||||||
|
|
||||||
keys = []
|
keys = []
|
||||||
self.each do |k, v|
|
self.each do |k, v|
|
||||||
@@ -284,11 +310,7 @@ class Hash
|
|||||||
# h1 < h1 #=> false
|
# h1 < h1 #=> false
|
||||||
#
|
#
|
||||||
def <(hash)
|
def <(hash)
|
||||||
begin
|
raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash
|
||||||
hash = hash.to_hash
|
|
||||||
rescue NoMethodError
|
|
||||||
raise TypeError, "can't convert #{hash.class} to Hash"
|
|
||||||
end
|
|
||||||
size < hash.size and all? {|key, val|
|
size < hash.size and all? {|key, val|
|
||||||
hash.key?(key) and hash[key] == val
|
hash.key?(key) and hash[key] == val
|
||||||
}
|
}
|
||||||
@@ -308,11 +330,7 @@ class Hash
|
|||||||
# h1 <= h1 #=> true
|
# h1 <= h1 #=> true
|
||||||
#
|
#
|
||||||
def <=(hash)
|
def <=(hash)
|
||||||
begin
|
raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash
|
||||||
hash = hash.to_hash
|
|
||||||
rescue NoMethodError
|
|
||||||
raise TypeError, "can't convert #{hash.class} to Hash"
|
|
||||||
end
|
|
||||||
size <= hash.size and all? {|key, val|
|
size <= hash.size and all? {|key, val|
|
||||||
hash.key?(key) and hash[key] == val
|
hash.key?(key) and hash[key] == val
|
||||||
}
|
}
|
||||||
@@ -332,11 +350,7 @@ class Hash
|
|||||||
# h1 > h1 #=> false
|
# h1 > h1 #=> false
|
||||||
#
|
#
|
||||||
def >(hash)
|
def >(hash)
|
||||||
begin
|
raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash
|
||||||
hash = hash.to_hash
|
|
||||||
rescue NoMethodError
|
|
||||||
raise TypeError, "can't convert #{hash.class} to Hash"
|
|
||||||
end
|
|
||||||
size > hash.size and hash.all? {|key, val|
|
size > hash.size and hash.all? {|key, val|
|
||||||
key?(key) and self[key] == val
|
key?(key) and self[key] == val
|
||||||
}
|
}
|
||||||
@@ -356,11 +370,7 @@ class Hash
|
|||||||
# h1 >= h1 #=> true
|
# h1 >= h1 #=> true
|
||||||
#
|
#
|
||||||
def >=(hash)
|
def >=(hash)
|
||||||
begin
|
raise TypeError, "can't convert #{hash.class} to Hash" unless Hash === hash
|
||||||
hash = hash.to_hash
|
|
||||||
rescue NoMethodError
|
|
||||||
raise TypeError, "can't convert #{hash.class} to Hash"
|
|
||||||
end
|
|
||||||
size >= hash.size and hash.all? {|key, val|
|
size >= hash.size and hash.all? {|key, val|
|
||||||
key?(key) and self[key] == val
|
key?(key) and self[key] == val
|
||||||
}
|
}
|
||||||
@@ -382,4 +392,106 @@ class Hash
|
|||||||
n
|
n
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# call-seq:
|
||||||
|
# hsh.transform_keys {|key| block } -> new_hash
|
||||||
|
# hsh.transform_keys -> an_enumerator
|
||||||
|
#
|
||||||
|
# Returns a new hash, with the keys computed from running the block
|
||||||
|
# once for each key in the hash, and the values unchanged.
|
||||||
|
#
|
||||||
|
# If no block is given, an enumerator is returned instead.
|
||||||
|
#
|
||||||
|
def transform_keys(&block)
|
||||||
|
return to_enum :transform_keys unless block
|
||||||
|
hash = {}
|
||||||
|
self.keys.each do |k|
|
||||||
|
new_key = block.call(k)
|
||||||
|
hash[new_key] = self[k]
|
||||||
|
end
|
||||||
|
hash
|
||||||
|
end
|
||||||
|
##
|
||||||
|
# call-seq:
|
||||||
|
# hsh.transform_keys! {|key| block } -> hsh
|
||||||
|
# hsh.transform_keys! -> an_enumerator
|
||||||
|
#
|
||||||
|
# Invokes the given block once for each key in <i>hsh</i>, replacing it
|
||||||
|
# with the new key returned by the block, and then returns <i>hsh</i>.
|
||||||
|
#
|
||||||
|
# If no block is given, an enumerator is returned instead.
|
||||||
|
#
|
||||||
|
def transform_keys!(&block)
|
||||||
|
return to_enum :transform_keys! unless block
|
||||||
|
self.keys.each do |k|
|
||||||
|
value = self[k]
|
||||||
|
self.__delete(k)
|
||||||
|
k = block.call(k) if block
|
||||||
|
self[k] = value
|
||||||
|
end
|
||||||
|
self
|
||||||
|
end
|
||||||
|
##
|
||||||
|
# call-seq:
|
||||||
|
# hsh.transform_values {|value| block } -> new_hash
|
||||||
|
# hsh.transform_values -> an_enumerator
|
||||||
|
#
|
||||||
|
# Returns a new hash with the results of running the block once for
|
||||||
|
# every value.
|
||||||
|
# This method does not change the keys.
|
||||||
|
#
|
||||||
|
# If no block is given, an enumerator is returned instead.
|
||||||
|
#
|
||||||
|
def transform_values(&b)
|
||||||
|
return to_enum :transform_values unless block_given?
|
||||||
|
hash = {}
|
||||||
|
self.keys.each do |k|
|
||||||
|
hash[k] = yield(self[k])
|
||||||
|
end
|
||||||
|
hash
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# call-seq:
|
||||||
|
# hsh.transform_values! {|key| block } -> hsh
|
||||||
|
# hsh.transform_values! -> an_enumerator
|
||||||
|
#
|
||||||
|
# Invokes the given block once for each value in the hash, replacing
|
||||||
|
# with the new value returned by the block, and then returns <i>hsh</i>.
|
||||||
|
#
|
||||||
|
# If no block is given, an enumerator is returned instead.
|
||||||
|
#
|
||||||
|
def transform_values!(&b)
|
||||||
|
return to_enum :transform_values! unless block_given?
|
||||||
|
self.keys.each do |k|
|
||||||
|
self[k] = yield(self[k])
|
||||||
|
end
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_proc
|
||||||
|
->x{self[x]}
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# call-seq:
|
||||||
|
# hsh.fetch_values(key, ...) -> array
|
||||||
|
# hsh.fetch_values(key, ...) { |key| block } -> array
|
||||||
|
#
|
||||||
|
# Returns an array containing the values associated with the given keys
|
||||||
|
# but also raises <code>KeyError</code> when one of keys can't be found.
|
||||||
|
# Also see <code>Hash#values_at</code> and <code>Hash#fetch</code>.
|
||||||
|
#
|
||||||
|
# h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
|
||||||
|
#
|
||||||
|
# h.fetch_values("cow", "cat") #=> ["bovine", "feline"]
|
||||||
|
# h.fetch_values("cow", "bird") # raises KeyError
|
||||||
|
# h.fetch_values("cow", "bird") { |k| k.upcase } #=> ["bovine", "BIRD"]
|
||||||
|
#
|
||||||
|
def fetch_values(*keys, &block)
|
||||||
|
keys.map do |k|
|
||||||
|
self.fetch(k, &block)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -36,6 +36,39 @@ hash_values_at(mrb_state *mrb, mrb_value hash)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* hsh.slice(*keys) -> a_hash
|
||||||
|
*
|
||||||
|
* Returns a hash containing only the given keys and their values.
|
||||||
|
*
|
||||||
|
* h = { a: 100, b: 200, c: 300 }
|
||||||
|
* h.slice(:a) #=> {:a=>100}
|
||||||
|
* h.slice(:b, :c, :d) #=> {:b=>200, :c=>300}
|
||||||
|
*/
|
||||||
|
static mrb_value
|
||||||
|
hash_slice(mrb_state *mrb, mrb_value hash)
|
||||||
|
{
|
||||||
|
mrb_value *argv, result;
|
||||||
|
mrb_int argc, i;
|
||||||
|
|
||||||
|
mrb_get_args(mrb, "*", &argv, &argc);
|
||||||
|
if (argc == 0) {
|
||||||
|
return mrb_hash_new_capa(mrb, argc);
|
||||||
|
}
|
||||||
|
result = mrb_hash_new_capa(mrb, argc);
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
mrb_value key = argv[i];
|
||||||
|
mrb_value val;
|
||||||
|
|
||||||
|
val = mrb_hash_fetch(mrb, hash, key, mrb_undef_value());
|
||||||
|
if (!mrb_undef_p(val)) {
|
||||||
|
mrb_hash_set(mrb, result, key, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
mrb_mruby_hash_ext_gem_init(mrb_state *mrb)
|
mrb_mruby_hash_ext_gem_init(mrb_state *mrb)
|
||||||
{
|
{
|
||||||
@@ -43,6 +76,7 @@ mrb_mruby_hash_ext_gem_init(mrb_state *mrb)
|
|||||||
|
|
||||||
h = mrb->hash_class;
|
h = mrb->hash_class;
|
||||||
mrb_define_method(mrb, h, "values_at", hash_values_at, MRB_ARGS_ANY());
|
mrb_define_method(mrb, h, "values_at", hash_values_at, MRB_ARGS_ANY());
|
||||||
|
mrb_define_method(mrb, h, "slice", hash_slice, MRB_ARGS_ANY());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -45,12 +45,6 @@ assert('Hash.[] for sub class') do
|
|||||||
assert_equal(sub_hash_class, sub_hash.class)
|
assert_equal(sub_hash_class, sub_hash.class)
|
||||||
end
|
end
|
||||||
|
|
||||||
assert('Hash.try_convert') do
|
|
||||||
assert_nil Hash.try_convert(nil)
|
|
||||||
assert_nil Hash.try_convert("{1=>2}")
|
|
||||||
assert_equal({1=>2}, Hash.try_convert({1=>2}))
|
|
||||||
end
|
|
||||||
|
|
||||||
assert('Hash#merge!') do
|
assert('Hash#merge!') do
|
||||||
a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' }
|
a = { 'abc_key' => 'abc_value', 'cba_key' => 'cba_value' }
|
||||||
b = { 'cba_key' => 'XXX', 'xyz_key' => 'xyz_value' }
|
b = { 'cba_key' => 'XXX', 'xyz_key' => 'xyz_value' }
|
||||||
@@ -82,6 +76,20 @@ assert('Hash#values_at') do
|
|||||||
assert_equal keys, h.values_at(*keys)
|
assert_equal keys, h.values_at(*keys)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assert('Hash#compact') do
|
||||||
|
h = { "cat" => "feline", "dog" => nil, "cow" => false }
|
||||||
|
|
||||||
|
assert_equal({ "cat" => "feline", "cow" => false }, h.compact)
|
||||||
|
assert_equal({ "cat" => "feline", "dog" => nil, "cow" => false }, h)
|
||||||
|
end
|
||||||
|
|
||||||
|
assert('Hash#compact!') do
|
||||||
|
h = { "cat" => "feline", "dog" => nil, "cow" => false }
|
||||||
|
|
||||||
|
h.compact!
|
||||||
|
assert_equal({ "cat" => "feline", "cow" => false }, h)
|
||||||
|
end
|
||||||
|
|
||||||
assert('Hash#fetch') do
|
assert('Hash#fetch') do
|
||||||
h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
|
h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
|
||||||
assert_equal "feline", h.fetch("cat")
|
assert_equal "feline", h.fetch("cat")
|
||||||
@@ -254,3 +262,33 @@ assert("Hash#dig") do
|
|||||||
assert_equal(1, h.dig(:a, :b, :c))
|
assert_equal(1, h.dig(:a, :b, :c))
|
||||||
assert_nil(h.dig(:d))
|
assert_nil(h.dig(:d))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assert("Hash#transform_keys") do
|
||||||
|
h = {"1" => 100, "2" => 200}
|
||||||
|
assert_equal({"1!" => 100, "2!" => 200},
|
||||||
|
h.transform_keys{|k| k+"!"})
|
||||||
|
assert_equal({1 => 100, 2 => 200},
|
||||||
|
h.transform_keys{|k|k.to_i})
|
||||||
|
assert_equal({"1.0" => 100, "2.1" => 200},
|
||||||
|
h.transform_keys.with_index{|k, i| "#{k}.#{i}"})
|
||||||
|
assert_equal(h, h.transform_keys!{|k|k.to_i})
|
||||||
|
assert_equal(h, {1 => 100, 2 => 200})
|
||||||
|
end
|
||||||
|
|
||||||
|
assert("Hash#transform_values") do
|
||||||
|
h = {a: 1, b: 2, c: 3}
|
||||||
|
assert_equal({a: 2, b: 5, c: 10},
|
||||||
|
h.transform_values{|v| v * v + 1})
|
||||||
|
assert_equal({a: "1", b: "2", c: "3"},
|
||||||
|
h.transform_values{|v|v.to_s})
|
||||||
|
assert_equal({a: "1.0", b: "2.1", c: "3.2"},
|
||||||
|
h.transform_values.with_index{|v, i| "#{v}.#{i}"})
|
||||||
|
assert_equal(h, h.transform_values!{|v|v.to_s})
|
||||||
|
assert_equal({a: "1", b: "2", c: "3"}, h)
|
||||||
|
end
|
||||||
|
|
||||||
|
assert("Hash#slice") do
|
||||||
|
h = { a: 100, b: 200, c: 300 }
|
||||||
|
assert_equal({:a=>100}, h.slice(:a))
|
||||||
|
assert_equal({:b=>200, :c=>300}, h.slice(:b, :c, :d))
|
||||||
|
end
|
||||||
|
|||||||
@@ -11,17 +11,17 @@ istruct_test_initialize(mrb_state *mrb, mrb_value self)
|
|||||||
mrb_value object;
|
mrb_value object;
|
||||||
mrb_get_args(mrb, "o", &object);
|
mrb_get_args(mrb, "o", &object);
|
||||||
|
|
||||||
if (mrb_float_p(object))
|
if (mrb_float_p(object)) {
|
||||||
{
|
strncpy(string, "float", size-1);
|
||||||
snprintf(string, size, "float(%.3f)", mrb_float(object));
|
|
||||||
}
|
}
|
||||||
else if (mrb_fixnum_p(object))
|
else if (mrb_fixnum_p(object)) {
|
||||||
{
|
strncpy(string, "fixnum", size-1);
|
||||||
snprintf(string, size, "fixnum(%" MRB_PRId ")", mrb_fixnum(object));
|
|
||||||
}
|
}
|
||||||
else if (mrb_string_p(object))
|
else if (mrb_string_p(object)) {
|
||||||
{
|
strncpy(string, "string", size-1);
|
||||||
snprintf(string, size, "string(%s)", mrb_string_value_cstr(mrb, &object));
|
}
|
||||||
|
else {
|
||||||
|
strncpy(string, "anything", size-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
string[size - 1] = 0; // force NULL at the end
|
string[size - 1] = 0; // force NULL at the end
|
||||||
@@ -47,7 +47,7 @@ istruct_test_test_receive(mrb_state *mrb, mrb_value self)
|
|||||||
mrb_get_args(mrb, "o", &object);
|
mrb_get_args(mrb, "o", &object);
|
||||||
if (mrb_obj_class(mrb, object) != mrb_class_get(mrb, "InlineStructTest"))
|
if (mrb_obj_class(mrb, object) != mrb_class_get(mrb, "InlineStructTest"))
|
||||||
{
|
{
|
||||||
mrb_raisef(mrb, E_TYPE_ERROR, "Expected InlineStructTest");
|
mrb_raise(mrb, E_TYPE_ERROR, "Expected InlineStructTest");
|
||||||
}
|
}
|
||||||
return mrb_bool_value(((char*)mrb_istruct_ptr(object))[0] == 's');
|
return mrb_bool_value(((char*)mrb_istruct_ptr(object))[0] == 's');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ end
|
|||||||
|
|
||||||
assert('InlineStructTest#dup') do
|
assert('InlineStructTest#dup') do
|
||||||
obj = InlineStructTest.new(1)
|
obj = InlineStructTest.new(1)
|
||||||
assert_equal obj.to_s, 'fixnum(1)'
|
assert_equal obj.to_s, 'fixnum'
|
||||||
assert_equal obj.dup.to_s, 'fixnum(1)'
|
assert_equal obj.dup.to_s, 'fixnum'
|
||||||
end
|
end
|
||||||
|
|
||||||
assert('InlineStructTest#clone') do
|
assert('InlineStructTest#clone') do
|
||||||
obj = InlineStructTest.new(1)
|
obj = InlineStructTest.new(1)
|
||||||
assert_equal obj.to_s, 'fixnum(1)'
|
assert_equal obj.to_s, 'fixnum'
|
||||||
assert_equal obj.clone.to_s, 'fixnum(1)'
|
assert_equal obj.clone.to_s, 'fixnum'
|
||||||
end
|
end
|
||||||
|
|
||||||
assert('InlineStruct#object_id') do
|
assert('InlineStruct#object_id') do
|
||||||
@@ -38,22 +38,22 @@ end
|
|||||||
|
|
||||||
assert('InlineStructTest#mutate (dup)') do
|
assert('InlineStructTest#mutate (dup)') do
|
||||||
obj1 = InlineStructTest.new("foo")
|
obj1 = InlineStructTest.new("foo")
|
||||||
assert_equal obj1.to_s, "string(foo)"
|
assert_equal obj1.to_s, "string"
|
||||||
obj2 = obj1.dup
|
obj2 = obj1.dup
|
||||||
assert_equal obj2.to_s, "string(foo)"
|
assert_equal obj2.to_s, "string"
|
||||||
obj1.mutate
|
obj1.mutate
|
||||||
assert_equal obj1.to_s, "mutate(foo)"
|
assert_equal obj1.to_s, "mutate"
|
||||||
assert_equal obj2.to_s, "string(foo)"
|
assert_equal obj2.to_s, "string"
|
||||||
end
|
end
|
||||||
|
|
||||||
assert('InlineStructTest#mutate (clone)') do
|
assert('InlineStructTest#mutate (clone)') do
|
||||||
obj1 = InlineStructTest.new("foo")
|
obj1 = InlineStructTest.new("foo")
|
||||||
assert_equal obj1.to_s, "string(foo)"
|
assert_equal obj1.to_s, "string"
|
||||||
obj2 = obj1.clone
|
obj2 = obj1.clone
|
||||||
assert_equal obj2.to_s, "string(foo)"
|
assert_equal obj2.to_s, "string"
|
||||||
obj1.mutate
|
obj1.mutate
|
||||||
assert_equal obj1.to_s, "mutate(foo)"
|
assert_equal obj1.to_s, "mutate"
|
||||||
assert_equal obj2.to_s, "string(foo)"
|
assert_equal obj2.to_s, "string"
|
||||||
end
|
end
|
||||||
|
|
||||||
assert('InlineStructTest#test_receive(string)') do
|
assert('InlineStructTest#test_receive(string)') do
|
||||||
@@ -101,26 +101,6 @@ if InlineStructTest.length == 24
|
|||||||
assert('InlineStructTest length [64 bit]') do
|
assert('InlineStructTest length [64 bit]') do
|
||||||
assert_equal InlineStructTest.length, 3 * 8
|
assert_equal InlineStructTest.length, 3 * 8
|
||||||
end
|
end
|
||||||
|
|
||||||
assert('InlineStructTest w/float [64 bit]') do
|
|
||||||
obj = InlineStructTest.new(1.25)
|
|
||||||
assert_equal obj.to_s, "float(1.250)"
|
|
||||||
end
|
|
||||||
|
|
||||||
assert('InlineStructTest w/fixnum [64 bit]') do
|
|
||||||
obj = InlineStructTest.new(42)
|
|
||||||
assert_equal obj.to_s, "fixnum(42)"
|
|
||||||
end
|
|
||||||
|
|
||||||
assert('InlineStructTest w/string [64 bit]') do
|
|
||||||
obj = InlineStructTest.new("hello")
|
|
||||||
assert_equal obj.to_s, "string(hello)"
|
|
||||||
end
|
|
||||||
|
|
||||||
assert('InlineStructTest w/long string [64 bit]') do
|
|
||||||
obj = InlineStructTest.new("this won't fit in 3 * 8 bytes available for the structure")
|
|
||||||
assert_equal obj.to_s, "string(this won't fit i"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# 32-bit mode
|
# 32-bit mode
|
||||||
@@ -128,24 +108,11 @@ if InlineStructTest.length == 12
|
|||||||
assert('InlineStructTest length [32 bit]') do
|
assert('InlineStructTest length [32 bit]') do
|
||||||
assert_equal InlineStructTest.length, 3 * 4
|
assert_equal InlineStructTest.length, 3 * 4
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
assert('InlineStructTest w/float [32 bit]') do
|
# 16-bit mode
|
||||||
obj = InlineStructTest.new(1.25)
|
if InlineStructTest.length == 6
|
||||||
assert_equal obj.to_s, "float(1.250"
|
assert('InlineStructTest length [16 bit]') do
|
||||||
end
|
assert_equal InlineStructTest.length, 3 * 2
|
||||||
|
|
||||||
assert('InlineStructTest w/fixnum [32 bit]') do
|
|
||||||
obj = InlineStructTest.new(42)
|
|
||||||
assert_equal obj.to_s, "fixnum(42)"
|
|
||||||
end
|
|
||||||
|
|
||||||
assert('InlineStructTest w/string [32 bit]') do
|
|
||||||
obj = InlineStructTest.new("hello")
|
|
||||||
assert_equal obj.to_s, "string(hell"
|
|
||||||
end
|
|
||||||
|
|
||||||
assert('InlineStructTest w/long string [32 bit]') do
|
|
||||||
obj = InlineStructTest.new("this won't fit in 3 * 4 bytes available for the structure")
|
|
||||||
assert_equal obj.to_s, "string(this"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user