mirror of
				https://github.com/irmen/prog8.git
				synced 2025-10-31 00:16:08 +00:00 
			
		
		
		
	Compare commits
	
		
			4827 Commits
		
	
	
		
			v1.70
			...
			v12.0-beta
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 513ee25432 | ||
|  | be74290ddc | ||
|  | a36501a9ed | ||
|  | ee5d33a230 | ||
|  | a8fd66cfdb | ||
|  | f5ce744748 | ||
|  | 68066acdec | ||
|  | 6286035d89 | ||
|  | 9a37eb9146 | ||
|  | 307796f115 | ||
|  | e962431139 | ||
|  | b7620abc9a | ||
|  | d2719d23f5 | ||
|  | d69eead6d8 | ||
|  | 6db3611d93 | ||
|  | a84320c7e2 | ||
|  | dfc720557c | ||
|  | 32149d073a | ||
|  | fc38be6376 | ||
|  | 13f6efc1d1 | ||
|  | 8296002887 | ||
|  | 424b89f357 | ||
|  | 4f5590fbff | ||
|  | 598e70c49a | ||
|  | a6d051b496 | ||
|  | 796d3242e1 | ||
|  | 1e8ff6f82a | ||
|  | 07bb5c36bd | ||
|  | 7e26ecb0b6 | ||
|  | 0c59ad70d4 | ||
|  | 53ce688cc5 | ||
|  | bb8b44d9d0 | ||
|  | 51ae32d23e | ||
|  | c873fac0dc | ||
|  | f0a67fff8a | ||
|  | f85ccd837d | ||
|  | 396fcbc927 | ||
|  | 0f564b301d | ||
|  | f4f34fc2ed | ||
|  | f7639cb78f | ||
|  | f5f5aef722 | ||
|  | d6e30d8468 | ||
|  | 37afdf5a18 | ||
|  | 5eb7074172 | ||
|  | 9aff280d10 | ||
|  | 44741a8e32 | ||
|  | 37535f2913 | ||
|  | ec9475c308 | ||
|  | b961ce97d6 | ||
|  | 4ed92d71a7 | ||
|  | 3e1386a987 | ||
|  | 4195e3968a | ||
|  | 961095bfec | ||
|  | 3ea8ca59b7 | ||
|  | 71ffbe2ba7 | ||
|  | e63921009c | ||
|  | db1aa3f257 | ||
|  | 8abdb837b2 | ||
|  | cdeabd4b66 | ||
|  | efff74c0f1 | ||
|  | 0e177cb531 | ||
|  | 35b921b062 | ||
|  | a7d98e43b8 | ||
|  | 845ee2dd83 | ||
|  | f9b0bfe31b | ||
|  | f303d15628 | ||
|  | 67f7ffa52d | ||
|  | 88c5d9783a | ||
|  | e7fc0360ad | ||
|  | cd1862dd9f | ||
|  | 045c4909a8 | ||
|  | f1bfe619b2 | ||
|  | e0107bacbd | ||
|  | b3bd2a6a09 | ||
|  | ff1f58e022 | ||
|  | 557b12668d | ||
|  | b058f1c7c2 | ||
|  | 3e07b6ca70 | ||
|  | d66dc664de | ||
|  | a2b9d78cf3 | ||
|  | 44f70da113 | ||
|  | c87eaf576d | ||
|  | c09b1395f6 | ||
|  | d6a8201291 | ||
|  | 4187f97f7a | ||
|  | 9d3b2f12fd | ||
|  | 87c1bbbf40 | ||
|  | a7ad6abdb9 | ||
|  | a611406020 | ||
|  | 75da38224d | ||
|  | 8d6f3301c8 | ||
|  | 86b52a1c5e | ||
|  | 2c8b1c2022 | ||
|  | ab1f065752 | ||
|  | 2c7256a443 | ||
|  | 97420b28e5 | ||
|  | 1467c7039d | ||
|  | d319badc6c | ||
|  | 65d6c1c438 | ||
|  | abeefb5655 | ||
|  | 50fecbcebe | ||
|  | 4fe8b72d42 | ||
|  | f3b060df51 | ||
|  | 09d1cb6925 | ||
|  | 54fa72fa98 | ||
|  | fd62fe7511 | ||
|  | bfb34dff62 | ||
|  | 817b623596 | ||
|  | f6dbeb1f63 | ||
|  | c4b9bdd33f | ||
|  | 68e0d5f1b5 | ||
|  | 4939e3df55 | ||
|  | 19f19f3880 | ||
|  | ad0c767ea8 | ||
|  | ed5f4d5855 | ||
|  | c2f5d37486 | ||
|  | 231b50dacb | ||
|  | a71895cbe8 | ||
|  | a8bede17b2 | ||
|  | f6c8e693a5 | ||
|  | 9461e4088c | ||
|  | efd73fd10d | ||
|  | ddf6e84a1a | ||
|  | 633d6c34e2 | ||
|  | 6e7fbc6683 | ||
|  | 124ea1230b | ||
|  | 8b48a295b6 | ||
|  | d285d37fdb | ||
|  | 8bb927b483 | ||
|  | 1af4cd0d63 | ||
|  | db2f28c4cd | ||
|  | 5d9fbd2ccc | ||
|  | 7efc709538 | ||
|  | 79419a98d0 | ||
|  | 1c77d5d5e7 | ||
|  | c6854e22a3 | ||
|  | 83acc2f285 | ||
|  | 6de95f7a3b | ||
|  | 82839a2d82 | ||
|  | e5fc9b3132 | ||
|  | ced4c5944a | ||
|  | d4c460072b | ||
|  | 0b9384b556 | ||
|  | 6c3277e3e3 | ||
|  | d9ff1eb38a | ||
|  | e178097735 | ||
|  | a1ab8ed208 | ||
|  | 6ababbf8f4 | ||
|  | 79629befc1 | ||
|  | 8022c0772a | ||
|  | 8ad2b4638b | ||
|  | 3a0392df8a | ||
|  | beb28b061d | ||
|  | c39acc5031 | ||
|  | f54a29c415 | ||
|  | 783b111059 | ||
|  | fb286f8b54 | ||
|  | 5999110e3f | ||
|  | 52a757ea78 | ||
|  | 28df08eea8 | ||
|  | 79505308ba | ||
|  | a7e9d8e14b | ||
|  | 08f3abe5bf | ||
|  | 3ef09d7d9a | ||
|  | a9142b9ce5 | ||
|  | 13e6f64d3b | ||
|  | 4a1256c772 | ||
|  | ff9bec90ec | ||
|  | a6fee1e510 | ||
|  | 80538f101e | ||
|  | aee53b14c7 | ||
|  | 5eb2fc8d86 | ||
|  | 98f91bbf88 | ||
|  | b48b36ef18 | ||
|  | 221a093e5f | ||
|  | 2ca1820d4e | ||
|  | d58737d5be | ||
|  | b52cee3154 | ||
|  | 9a76941e10 | ||
|  | 0285a4cce1 | ||
|  | 5a3aa1bd25 | ||
|  | 0f79351de9 | ||
|  | 3cdb25ce8e | ||
|  | b7193bd0c6 | ||
|  | 10ff6a0095 | ||
|  | d30f58004e | ||
|  | 17bdb22e4f | ||
|  | a68209be37 | ||
|  | 7b40eade44 | ||
|  | 8a717c74b9 | ||
|  | aa72ded21e | ||
|  | 8e53c83844 | ||
|  | e2a2db1256 | ||
|  | 2afd2d4dae | ||
|  | fad17cc094 | ||
|  | f93d957999 | ||
|  | 8db0344cee | ||
|  | 32e531f951 | ||
|  | a4769702f9 | ||
|  | cf19fb8df1 | ||
|  | 79b8bb5c9f | ||
|  | fc5889ec0b | ||
|  | 369303c46d | ||
|  | d65670cc7b | ||
|  | f74eeaee0f | ||
|  | 826fb3e9c2 | ||
|  | a3d7b8a899 | ||
|  | 0cc36ed6e4 | ||
|  | 976bd52972 | ||
|  | 4a8d5def84 | ||
|  | 2f60716082 | ||
|  | 729efb04e1 | ||
|  | 4ea8b4d445 | ||
|  | e800c165f9 | ||
|  | fd9bd23449 | ||
|  | 8880ed1393 | ||
|  | f7fde070ca | ||
|  | 5ada80779d | ||
|  | 8972235a0e | ||
|  | e56f533e38 | ||
|  | 324fb7dbf7 | ||
|  | 44285b9b5d | ||
|  | a68f477d61 | ||
|  | ae9f99448e | ||
|  | 7c0fb10197 | ||
|  | 9e85571a7b | ||
|  | 9e10c15e2e | ||
|  | 6bd7752bac | ||
|  | 83ec437e8a | ||
|  | 4a1d05dd46 | ||
|  | aa324e355a | ||
|  | 5cb8bcead7 | ||
|  | bbd06c0c99 | ||
|  | 651830ea82 | ||
|  | c70146f1dc | ||
|  | d4e83b28bb | ||
|  | bc58a25765 | ||
|  | 38645022c9 | ||
|  | 647cd0fbe1 | ||
|  | ea8935a346 | ||
|  | 7ea80babfc | ||
|  | dee761a99e | ||
|  | 88ee7a8187 | ||
|  | eb8b408b82 | ||
|  | 3d10882f57 | ||
|  | 1988496512 | ||
|  | 88b074c208 | ||
|  | c4c5636a81 | ||
|  | c39d570b72 | ||
|  | 4ccd7f9f3a | ||
|  | 1c9c5aeef7 | ||
|  | 23ad540aa5 | ||
|  | 08810c2749 | ||
|  | a52966f327 | ||
|  | 624220e9a3 | ||
|  | 842b11ed9e | ||
|  | 82267b3f56 | ||
|  | 67fb45a55b | ||
|  | 11186f1dbe | ||
|  | 0116fac201 | ||
|  | 817f4f8e7c | ||
|  | 866313209b | ||
|  | 28e351daab | ||
|  | 893e16d814 | ||
|  | 33470c47fc | ||
|  | 63f7b87572 | ||
|  | e2901cca1b | ||
|  | ce8006992a | ||
|  | 0b5413ad83 | ||
|  | dd7adde387 | ||
|  | 23058b51a1 | ||
|  | 2f90c53ad0 | ||
|  | c3be7ab4b3 | ||
|  | a9b8fbc6c6 | ||
|  | 720988ae72 | ||
|  | b0981a5fae | ||
|  | ea5deeefbd | ||
|  | 054c98da7c | ||
|  | dc434d034a | ||
|  | a4a1b563aa | ||
|  | 3f34b83e0d | ||
|  | 9c63ef39c7 | ||
|  | 9f6106452e | ||
|  | f9fbfe30e3 | ||
|  | 9a9bf170c6 | ||
|  | 7dd64b4f13 | ||
|  | b6c0bac96f | ||
|  | 8ede098154 | ||
|  | 2a4a3b786e | ||
|  | b4e0a2019e | ||
|  | e14c3f8b59 | ||
|  | c81f76226d | ||
|  | edc353cc24 | ||
|  | dcce519c69 | ||
|  | 0a16dcafc0 | ||
|  | 54d41b7f6f | ||
|  | 0541b84d09 | ||
|  | 1b420f7fe7 | ||
|  | 6a9a82ff9d | ||
|  | aa36e6b19f | ||
|  | 51cb6aad50 | ||
|  | b5ce409592 | ||
|  | 2119817e4a | ||
|  | 1efdfe8ea1 | ||
|  | 67d4180825 | ||
|  | be31e190d2 | ||
|  | a68cf3c812 | ||
|  | c2bf9024f8 | ||
|  | bd72eaad4c | ||
|  | b5d1575823 | ||
|  | 1d306e5cdc | ||
|  | b137164fe6 | ||
|  | 67d4ad50e1 | ||
|  | c71066af4c | ||
|  | 6f0a0981bd | ||
|  | 49a4d9ba37 | ||
|  | fcdfa741b9 | ||
|  | e3e395836d | ||
|  | 3bab177d50 | ||
|  | 12abafb917 | ||
|  | 8dc2e47507 | ||
|  | 0be90dedf2 | ||
|  | daf7c3357c | ||
|  | e6bab3ceeb | ||
|  | 59387b2ae8 | ||
|  | e8795859c5 | ||
|  | bebe60b687 | ||
|  | ddceec364e | ||
|  | f8f20440d3 | ||
|  | f8722faa4e | ||
|  | d067fa4b73 | ||
|  | 26fbbf48a4 | ||
|  | d5cc414221 | ||
|  | b5e51ab937 | ||
|  | 552e55c29f | ||
|  | a228908c1a | ||
|  | 15fc3b6c04 | ||
|  | 0456badd02 | ||
|  | d28f154f1c | ||
|  | 399cf5118d | ||
|  | a87f2640d3 | ||
|  | a90ef274d7 | ||
|  | 1c02179c5c | ||
|  | 77584493fd | ||
|  | a36709e638 | ||
|  | 341778ba67 | ||
|  | 8d63cce749 | ||
|  | ec50b5a007 | ||
|  | 8e7bbcdbe0 | ||
|  | 37ecdc47b3 | ||
|  | 112ca3cc53 | ||
|  | 33b3a1664c | ||
|  | 8a0c02e264 | ||
|  | 31d84c8921 | ||
|  | 34bedbeef1 | ||
|  | 3b1b0985c1 | ||
|  | e40ace9dea | ||
|  | 4c0e6e2640 | ||
|  | 08b314c37d | ||
|  | 86da9d3c7e | ||
|  | 4e61e25c02 | ||
|  | 5097d52d99 | ||
|  | 368387e1a7 | ||
|  | 09d2185bb1 | ||
|  | 5c02e2bd71 | ||
|  | fb01389b3d | ||
|  | aaa81210ce | ||
|  | 51269257ea | ||
|  | 23a853db1e | ||
|  | 9da430ffeb | ||
|  | cc063124cf | ||
|  | 3b37b89951 | ||
|  | 844b537d1e | ||
|  | caf1d4a22a | ||
|  | d8e244df99 | ||
|  | 548e421e27 | ||
|  | 322fa7ea69 | ||
|  | db6c887795 | ||
|  | cf7bea0985 | ||
|  | 61fe55168a | ||
|  | 25d7f8808f | ||
|  | 1c4999ec87 | ||
|  | c726d3f937 | ||
|  | f70341df1b | ||
|  | f0b791452e | ||
|  | adf5600a9b | ||
|  | 6d4ccc5feb | ||
|  | 5f3829d5cc | ||
|  | 770ebdcd4a | ||
|  | 96f690e749 | ||
|  | eabdd3a8f3 | ||
|  | 50650b966b | ||
|  | 65e34d4989 | ||
|  | 05dad5ab5f | ||
|  | 1a69a2f1bc | ||
|  | 435faafaad | ||
|  | 686b32dc29 | ||
|  | 0e64a22910 | ||
|  | 4f0839f27e | ||
|  | bb1953267d | ||
|  | acc630972a | ||
|  | 6a33be3fd8 | ||
|  | cd8aae4681 | ||
|  | 11456496bd | ||
|  | f5fc4e345c | ||
|  | 86eef7039f | ||
|  | f4b2264fcf | ||
|  | 9b36ae2277 | ||
|  | 913ab03963 | ||
|  | 38448e471c | ||
|  | 67231af623 | ||
|  | e31ef6f06f | ||
|  | 09d188106a | ||
|  | d8e2116481 | ||
|  | 435dfbb932 | ||
|  | ba93966474 | ||
|  | ea8d17cdb2 | ||
|  | 082265fb25 | ||
|  | d138a7a567 | ||
|  | ea27d732ab | ||
|  | 9e557ce8ac | ||
|  | 924e28e9b3 | ||
|  | e5d9af75de | ||
|  | 31c1bf8bc5 | ||
|  | 37d4055036 | ||
|  | 78b1076110 | ||
|  | 0a3c748e41 | ||
|  | ebf79ef9e2 | ||
|  | 60a73248cd | ||
|  | abbb7d7ba3 | ||
|  | 59c378089e | ||
|  | 0b789b5f0b | ||
|  | 4382b96a9a | ||
|  | 246e4f35a6 | ||
|  | 99b9370178 | ||
|  | 506062c6b6 | ||
|  | d634061cd9 | ||
|  | 8353c689ca | ||
|  | d59d8ff1fe | ||
|  | e98e6f70ac | ||
|  | 53e442d509 | ||
|  | 134352ed7c | ||
|  | f7cbfdff06 | ||
|  | b28ee0819f | ||
|  | 5de626aab8 | ||
|  | 7aad5d486e | ||
|  | 701f155951 | ||
|  | 8c324d7514 | ||
|  | 522958e0e9 | ||
|  | 97390db5f5 | ||
|  | af920d1427 | ||
|  | 779ebc0537 | ||
|  | 38949b82c3 | ||
|  | d11386ef26 | ||
|  | 0e0377d1f0 | ||
|  | 55e0dbab27 | ||
|  | 4dc82f2c83 | ||
|  | 1ba5587404 | ||
|  | 835c4b6da3 | ||
|  | dbd955b61e | ||
|  | d20e2fd88c | ||
|  | e0dea89477 | ||
|  | ccc6b56e35 | ||
|  | 6fc2902895 | ||
|  | c96e4b40d4 | ||
|  | 37da3e2170 | ||
|  | 2661d3c489 | ||
|  | b89bbb9281 | ||
|  | 696bf636ed | ||
|  | 40952a788a | ||
|  | 0162e7a0c1 | ||
|  | 6ce099f176 | ||
|  | 476a4bac8e | ||
|  | 63a410a6df | ||
|  | cca27faa3b | ||
|  | 803e6bd81a | ||
|  | 88269628a2 | ||
|  | b920d553a0 | ||
|  | 5e2d0d0dfc | ||
|  | 2ae3bd68eb | ||
|  | 9c183f27eb | ||
|  | 8046023e82 | ||
|  | e328520588 | ||
|  | 7eb079050c | ||
|  | 2fdd5543b2 | ||
|  | d04164c0a6 | ||
|  | b047731f82 | ||
|  | 4d91f92a2e | ||
|  | 98505d27b1 | ||
|  | cd63a58ad9 | ||
|  | 170f8dd092 | ||
|  | 619dcb6a84 | ||
|  | 99ae8ea52e | ||
|  | dc031c30eb | ||
|  | 1e702439b7 | ||
|  | 8debc42381 | ||
|  | 532d719089 | ||
|  | b40860aca4 | ||
|  | 2cbe6b5f7f | ||
|  | d2cc7ccdfa | ||
|  | 2cb183c6d8 | ||
|  | 84026b105f | ||
|  | a4d0589f10 | ||
|  | e375f6afce | ||
|  | 5a7bc04816 | ||
|  | bd1894580e | ||
|  | 9e694c0337 | ||
|  | c82586db28 | ||
|  | dd2d466350 | ||
|  | 830da8de0a | ||
|  | 4e5ee333c8 | ||
|  | 9df899eb63 | ||
|  | ca7491a702 | ||
|  | 1a07129865 | ||
|  | 4fbd67ff99 | ||
|  | 5bc6c50f42 | ||
|  | 063de3801d | ||
|  | ae65266a4a | ||
|  | 8ed2401e0b | ||
|  | d2e8ee8269 | ||
|  | 1f996e3b8b | ||
|  | 7108b74105 | ||
|  | 801fe1b604 | ||
|  | fb44c87597 | ||
|  | 6b9cdbd482 | ||
|  | 0ab98033b5 | ||
|  | 14a2b96609 | ||
|  | f829b689db | ||
|  | dfda8b7ed5 | ||
|  | 4388466451 | ||
|  | 5c2f509a52 | ||
|  | 59582f5210 | ||
|  | e2a8bdbdfb | ||
|  | 0916b943da | ||
|  | 9c7ebc883c | ||
|  | 0ee42b9aa0 | ||
|  | 37b3868ca3 | ||
|  | a6835ce3f0 | ||
|  | 69c96ad99b | ||
|  | b72877d59d | ||
|  | 05eb15d4f7 | ||
|  | f1fec37c79 | ||
|  | 73f6880ff8 | ||
|  | 8a53742f31 | ||
|  | 9be40e85ff | ||
|  | 61079c1eb7 | ||
|  | 1075ee8fc3 | ||
|  | a28b265197 | ||
|  | 20e534c468 | ||
|  | da7aa5dc49 | ||
|  | 8f2a43ca0a | ||
|  | d0909d7810 | ||
|  | 1641999d20 | ||
|  | e16452037c | ||
|  | 344d79684a | ||
|  | 573a1d9b7b | ||
|  | 25ab57580c | ||
|  | a332e0e3d1 | ||
|  | 376f1cb139 | ||
|  | 90f80558d7 | ||
|  | e281994898 | ||
|  | 29fac122e1 | ||
|  | 1dc412eb90 | ||
|  | 3770a4fe0c | ||
|  | 79cda544c8 | ||
|  | f04b97d890 | ||
|  | 3e9b4ccc45 | ||
|  | 2c3d838dd8 | ||
|  | 7668a3c660 | ||
|  | 5dd45b714a | ||
|  | 8b08895d0f | ||
|  | 8f8d99e3ed | ||
|  | 23474360ec | ||
|  | 81c255c450 | ||
|  | ef23d52ed7 | ||
|  | 220ab773aa | ||
|  | e3e5bff7bb | ||
|  | 7b9a841b2a | ||
|  | 40423911ef | ||
|  | 582a70b046 | ||
|  | 5b63590ebf | ||
|  | 2b6510dc19 | ||
|  | 9d49589d73 | ||
|  | 125b66c929 | ||
|  | 5255f1c052 | ||
|  | a6ba05d60c | ||
|  | 41e963b04b | ||
|  | 6ff75bef29 | ||
|  | 72c16d0d32 | ||
|  | 94653e5c8c | ||
|  | 3e2b2a698d | ||
|  | ae04f5aee8 | ||
|  | 5c56267662 | ||
|  | e55ce5504e | ||
|  | fb1e89d9ef | ||
|  | bc550a4549 | ||
|  | ebdea9cf76 | ||
|  | 09ec508f82 | ||
|  | d06e9ea7f6 | ||
|  | a36bdc54fd | ||
|  | 0814ea9711 | ||
|  | daefe839d8 | ||
|  | e6088dd315 | ||
|  | fc03d6f332 | ||
|  | 2aeb7a838e | ||
|  | 99ff5dd078 | ||
|  | 49982b49b6 | ||
|  | fd39c22616 | ||
|  | 9e79722a7f | ||
|  | 17334a1c58 | ||
|  | c7f0ff11ac | ||
|  | cd2cc89e6a | ||
|  | 069143092d | ||
|  | efd41260f2 | ||
|  | 8d2410622c | ||
|  | 60554389b3 | ||
|  | a940dc7d43 | ||
|  | 06ca68a625 | ||
|  | 5b58e5b158 | ||
|  | 74dd8fe80b | ||
|  | 75ddcda5f3 | ||
|  | 216825b98a | ||
|  | a96defab86 | ||
|  | 0864b0a1b7 | ||
|  | 8b158d9240 | ||
|  | f335251c2b | ||
|  | 67bc0b6931 | ||
|  | e646dd1ed1 | ||
|  | 2b7947f9b0 | ||
|  | ec0cfb4b3f | ||
|  | 9cdf53019c | ||
|  | 1a04a3eb3a | ||
|  | 105d3995e0 | ||
|  | 8ce3204f93 | ||
|  | d0f15f1285 | ||
|  | 66d6f67120 | ||
|  | a106c88054 | ||
|  | ee784e1ccc | ||
|  | bb75be0b44 | ||
|  | 2478aea316 | ||
|  | 1e17df5296 | ||
|  | 8583a96519 | ||
|  | d0c184c7de | ||
|  | 0191acb2b3 | ||
|  | 277a1a32b2 | ||
|  | 7a13f57ab0 | ||
|  | 0c882836d9 | ||
|  | 228be5cd04 | ||
|  | 08cd2fd6e8 | ||
|  | bc7b086f0f | ||
|  | e8f3af6981 | ||
|  | f9c7c7dab7 | ||
|  | 09a17743ad | ||
|  | 4f096a7511 | ||
|  | 2ab2130000 | ||
|  | 66558f7638 | ||
|  | a6f9ed07e7 | ||
|  | 7268a8736f | ||
|  | 8f6b5676d7 | ||
|  | ca9422bbe9 | ||
|  | 35d9412559 | ||
|  | f071c07dd9 | ||
|  | e5ff3c1ff3 | ||
|  | f0e8ff0326 | ||
|  | 3b5cda85ff | ||
|  | 420793f9e2 | ||
|  | cf1dbaf0d8 | ||
|  | d187cef6b7 | ||
|  | 3b3616afda | ||
|  | 0ffebc25d0 | ||
|  | 478e2b4ebd | ||
|  | a56ae7539a | ||
|  | 407773bda2 | ||
|  | 823eaa8918 | ||
|  | a2be42c5ca | ||
|  | a76b8d66ff | ||
|  | b7f47d354f | ||
|  | 5d33c93af9 | ||
|  | 4db6859f3f | ||
|  | 45fe1bb16e | ||
|  | b014facbd3 | ||
|  | 3b4b37f16b | ||
|  | 68d5983a14 | ||
|  | f2cfcfdf31 | ||
|  | 10b9162dc5 | ||
|  | c84cc8f8c9 | ||
|  | 78c71bbf0e | ||
|  | 37c2c1bf0b | ||
|  | c8996418da | ||
|  | 76b29aa629 | ||
|  | ee521793f8 | ||
|  | f42e12bc13 | ||
|  | 427451a23f | ||
|  | af7930d494 | ||
|  | e2882d37bf | ||
|  | 942d3ee640 | ||
|  | 7b4a82b91a | ||
|  | 056c0a24d9 | ||
|  | 827df04b32 | ||
|  | e174b31344 | ||
|  | 49959af752 | ||
|  | c86c0912f8 | ||
|  | 268b0c9365 | ||
|  | 099fe280ba | ||
|  | f786f60e9c | ||
|  | f40e1eb1f2 | ||
|  | 8b9da65357 | ||
|  | 2cbbe0d48a | ||
|  | b6e1fb3ba8 | ||
|  | bdccffbb8e | ||
|  | 5a85474712 | ||
|  | f50899c6fa | ||
|  | 4daa909f32 | ||
|  | 4555edf369 | ||
|  | 529ea5bf58 | ||
|  | fe011de934 | ||
|  | 0653d430a7 | ||
|  | a587f6e9a0 | ||
|  | 3850e1dbb5 | ||
|  | 91cde072e0 | ||
|  | 2ca4aed566 | ||
|  | 5071da6784 | ||
|  | 4c1e2f3110 | ||
|  | 2727a4dcb3 | ||
|  | 126d4c69e6 | ||
|  | 7657edcb7d | ||
|  | 580e786952 | ||
|  | c0ae35b3a3 | ||
|  | c3dc74788a | ||
|  | 379d241a0d | ||
|  | 1f49e8fe75 | ||
|  | d70cfbb661 | ||
|  | 5482ac0302 | ||
|  | 131d5ceb4f | ||
|  | 512ddd1694 | ||
|  | 14a213bff9 | ||
|  | d586846bc5 | ||
|  | ef4efcb112 | ||
|  | b01555d75e | ||
|  | 3804fba0f1 | ||
|  | f93b7e3303 | ||
|  | 73baaeff1f | ||
|  | 7c79cdbd2f | ||
|  | 8ea032ed66 | ||
|  | e7a0cb636c | ||
|  | 02f3f5d0f5 | ||
|  | 1e9bbd662b | ||
|  | 8644a4ae91 | ||
|  | 1e85f7812f | ||
|  | 80d88b3c61 | ||
|  | d2827a7431 | ||
|  | 28c721fa7d | ||
|  | 8f799567cf | ||
|  | 9e8cc8b54d | ||
|  | cc59069876 | ||
|  | 697d54e10a | ||
|  | 1679ca79b4 | ||
|  | 124ec77b58 | ||
|  | 3675d7961b | ||
|  | f8aaa2d13c | ||
|  | b7afda781a | ||
|  | 535ec13072 | ||
|  | 26d0a174db | ||
|  | b2e821755c | ||
|  | 2e303041c1 | ||
|  | 96bed8f57f | ||
|  | 86d4a4309f | ||
|  | 1a1ab0dac6 | ||
|  | ba8c3d14f7 | ||
|  | 617ea15c3a | ||
|  | ef192a5778 | ||
|  | 565973c520 | ||
|  | 25b1043572 | ||
|  | 1ebfff7c7b | ||
|  | 8341f9c066 | ||
|  | 28cac291de | ||
|  | 8fa14a10e2 | ||
|  | 55dbd095ed | ||
|  | 31ad8bdd8d | ||
|  | 181f3e9eb1 | ||
|  | 50c3d809dc | ||
|  | 58f696d00a | ||
|  | f603c543d3 | ||
|  | 6aaa0f928e | ||
|  | feb8aa435e | ||
|  | 310e8f15cd | ||
|  | da03941582 | ||
|  | dcbb36a3bd | ||
|  | 53558f5c1d | ||
|  | 189399d5f8 | ||
|  | 5406a992f5 | ||
|  | bc9683cc54 | ||
|  | 2eed75f602 | ||
|  | d58f9f56c4 | ||
|  | 2e35f3c3a3 | ||
|  | 5c6bd9c091 | ||
|  | 857d2eefca | ||
|  | 90f1e7fd6a | ||
|  | 18e37accf9 | ||
|  | cc53d698bf | ||
|  | cb86206698 | ||
|  | d77b1944fb | ||
|  | a58cb43c4a | ||
|  | 88574c87c4 | ||
|  | 3a7a7091c0 | ||
|  | 906b137a7c | ||
|  | 42e2c5f605 | ||
|  | cc13a51493 | ||
|  | f569ce6141 | ||
|  | 4958463e75 | ||
|  | 2360625927 | ||
|  | 8badc40883 | ||
|  | 844c97930f | ||
|  | 5c09dc10ae | ||
|  | 9fd9e9ab5f | ||
|  | 35c477b5a6 | ||
|  | ae0cadb383 | ||
|  | 984230e8fa | ||
|  | a874aec6a1 | ||
|  | ea1daa97d3 | ||
|  | fb0d9b46b0 | ||
|  | 9da70bdf05 | ||
|  | d640cfbe13 | ||
|  | 51a05ec4b7 | ||
|  | 1f5706bbeb | ||
|  | 25c9b2fea4 | ||
|  | 154f9b300f | ||
|  | d78ce77536 | ||
|  | b4fb43bc80 | ||
|  | e0e01f794e | ||
|  | 08865dbb4e | ||
|  | b9ad7e0e55 | ||
|  | 07158a6f1a | ||
|  | 957c42bc1d | ||
|  | f784da2da6 | ||
|  | c080fbe59a | ||
|  | d70b8303b1 | ||
|  | 1d38c3582a | ||
|  | 9438e996d7 | ||
|  | 3b4a5e27f7 | ||
|  | 648d9fc269 | ||
|  | 54fccec7d7 | ||
|  | 4f9693055e | ||
|  | 555c50ee10 | ||
|  | bf98ceca2c | ||
|  | 573cecb087 | ||
|  | 1b528491c2 | ||
|  | 4bdabe1961 | ||
|  | a3fa527378 | ||
|  | 84f5ffa426 | ||
|  | 25d2b42283 | ||
|  | 300d1a871c | ||
|  | 2fcb83a39f | ||
|  | 3ba1d00a7c | ||
|  | 64164c1c72 | ||
|  | 3ee6058524 | ||
|  | 93a0a41e73 | ||
|  | e7ab7b6d7a | ||
|  | 7d4dc3c063 | ||
|  | a50400b7d1 | ||
|  | f89f1a84d0 | ||
|  | 688dce6145 | ||
|  | b88f550c5b | ||
|  | 9864abd393 | ||
|  | c702c4a6df | ||
|  | 77e376f6bf | ||
|  | 491e5dbcfb | ||
|  | a5c7393561 | ||
|  | 7fd3e9bb7d | ||
|  | 459e9f8f3b | ||
|  | 5b1143bcb3 | ||
|  | fddd390d31 | ||
|  | e514eeba17 | ||
|  | c11a52b278 | ||
|  | 85e87dfe2e | ||
|  | cb47e2c149 | ||
|  | 0fc9aa6b2d | ||
|  | 155896c4c7 | ||
|  | 178e60bba0 | ||
|  | 9f84aa5fb2 | ||
|  | 66fc109ce5 | ||
|  | a231872821 | ||
|  | 7cfb33a448 | ||
|  | 3b798097b9 | ||
|  | 6fb05bdefc | ||
|  | 64ea72ed4d | ||
|  | 89425088ce | ||
|  | 925b9d845d | ||
|  | ad074076c2 | ||
|  | a2194c43a6 | ||
|  | 4b23b1dc86 | ||
|  | 9005c7994a | ||
|  | 4a47e15b1c | ||
|  | 09cbdf410a | ||
|  | df6a43c7f0 | ||
|  | 4ce130dc8b | ||
|  | 94d76aa82c | ||
|  | 73609636c5 | ||
|  | 66b06d6c40 | ||
|  | eeeb8d81f4 | ||
|  | 6f727aff88 | ||
|  | 518e5a30c2 | ||
|  | bbba4b3d60 | ||
|  | 967adb9a87 | ||
|  | 040a6c62de | ||
|  | 483d193ced | ||
|  | 62458216c9 | ||
|  | 76b05cb5fd | ||
|  | 570b574b93 | ||
|  | a82f211f9a | ||
|  | 504c80cddf | ||
|  | 4b4af9b527 | ||
|  | 28b383f888 | ||
|  | 40ce7725a1 | ||
|  | 1f2d46628e | ||
|  | c9535049c8 | ||
|  | 9317cf8a35 | ||
|  | 1cd754f05d | ||
|  | 97b8cb748d | ||
|  | 84d9040b57 | ||
|  | fdd18c615c | ||
|  | c14f6cfc2b | ||
|  | 326eab3dd1 | ||
|  | 6da1f7eb4c | ||
|  | 1e82483152 | ||
|  | 6e2fd41a8b | ||
|  | 9927af1095 | ||
|  | 7585b6ef6f | ||
|  | a6159702da | ||
|  | 0247fb0d84 | ||
|  | 6de760885f | ||
|  | 9851d14fb9 | ||
|  | d5fc69d3e4 | ||
|  | a40d120f2a | ||
|  | fcdd9414d9 | ||
|  | 272a1001a8 | ||
|  | 2a52241f1c | ||
|  | d8f1822c12 | ||
|  | ce7d094adb | ||
|  | a0cf1889a3 | ||
|  | 38ef394e15 | ||
|  | abbf7c7cb0 | ||
|  | ca5f7ae32f | ||
|  | cbc4b75e50 | ||
|  | 65ddcf91d0 | ||
|  | 5280e1b449 | ||
|  | b6ffb81909 | ||
|  | e9edffa9f0 | ||
|  | 0dd1c17ff4 | ||
|  | aef211e5f3 | ||
|  | 66829203d8 | ||
|  | 7a0eaf3148 | ||
|  | fa5479ee5f | ||
|  | 03412cacba | ||
|  | 01a38a0b11 | ||
|  | f43c14bd78 | ||
|  | fb23452383 | ||
|  | ab7dde1450 | ||
|  | 8d9bc2f5ff | ||
|  | 7651ccc84e | ||
|  | 1a6b95b388 | ||
|  | 78ec1e7512 | ||
|  | 7e38d26c33 | ||
|  | ed09dd4e9e | ||
|  | 5731b79554 | ||
|  | eaa22a9d13 | ||
|  | b2bdfe8482 | ||
|  | fea531be9a | ||
|  | 7c69d38588 | ||
|  | a088ee56b0 | ||
|  | ae669af904 | ||
|  | d1ddf05e38 | ||
|  | 51279a98b3 | ||
|  | bf33a4f82d | ||
|  | fff0d741c3 | ||
|  | e83d0ee820 | ||
|  | 09f3eecf56 | ||
|  | 2bd4326ff6 | ||
|  | c13168b60c | ||
|  | ea3871d0c4 | ||
|  | 70a2b11271 | ||
|  | 3cf39e072e | ||
|  | 413b86cc4a | ||
|  | a6107fcfdf | ||
|  | a064ade1e0 | ||
|  | df35aa7942 | ||
|  | cd49c5f88d | ||
|  | 1541ad2160 | ||
|  | c78b7b1a24 | ||
|  | 9c7a645e18 | ||
|  | 4acf38031a | ||
|  | 4cd7271e30 | ||
|  | 3f630ab1b0 | ||
|  | 04cb684fd4 | ||
|  | 4c843571ea | ||
|  | 1326498802 | ||
|  | b7ebd8c4a6 | ||
|  | 24e0a69480 | ||
|  | 4bcb2bdede | ||
|  | d27f3eb8a4 | ||
|  | d3e4481112 | ||
|  | 1d1d6b3d98 | ||
|  | 90b8a22a71 | ||
|  | 8dbfb8ab76 | ||
|  | e29ff1c848 | ||
|  | 585f6ffc9b | ||
|  | 46b94c17d6 | ||
|  | 7af8007447 | ||
|  | 16a2b2f566 | ||
|  | ea2a90c3c5 | ||
|  | 5cda750e5e | ||
|  | 4e143d45c8 | ||
|  | 4c50980d81 | ||
|  | 2954f5f04d | ||
|  | cac4c1eb1e | ||
|  | 0b1f30d98c | ||
|  | c7b1e8d772 | ||
|  | a4f7512d44 | ||
|  | 0d3ad80659 | ||
|  | aba1a73e28 | ||
|  | dca31b2ca3 | ||
|  | 0cb378ca31 | ||
|  | cf551d2cc7 | ||
|  | ac0c8a68f6 | ||
|  | 5986dcdd2f | ||
|  | 6be6eb2227 | ||
|  | d34015eec5 | ||
|  | 255c5bfaca | ||
|  | 01c6754928 | ||
|  | 8eaf884f69 | ||
|  | 699a2bb7ab | ||
|  | 4a2dcd20d1 | ||
|  | 4e98fb75d6 | ||
|  | 64e66e732f | ||
|  | 7aec627f6b | ||
|  | 59a2fec176 | ||
|  | edc5a5a94f | ||
|  | c5b7edad82 | ||
|  | 124ffac4e4 | ||
|  | 6d2a36fb2b | ||
|  | 28b43b3e1d | ||
|  | f7feaf158d | ||
|  | 2396f707c6 | ||
|  | d4d8e1b1ba | ||
|  | 44fec2c729 | ||
|  | a80a6913e3 | ||
|  | 0eac04c220 | ||
|  | 29dd758302 | ||
|  | 5c45adc7f0 | ||
|  | ad22cf08cd | ||
|  | 2c2ae64194 | ||
|  | 97c2dadd16 | ||
|  | b36e1e3baf | ||
|  | 2da35fec17 | ||
|  | bdeac74cfc | ||
|  | 6516d7cb15 | ||
|  | 31cf76042d | ||
|  | c4c4dcf2b3 | ||
|  | 03145630f8 | ||
|  | e2fcac322f | ||
|  | beaff4d650 | ||
|  | 79af96ddde | ||
|  | e439720c9d | ||
|  | 48d0185ea4 | ||
|  | e2592b4e0b | ||
|  | 2967866e3d | ||
|  | b566ea5c3f | ||
|  | 8f6eaeac2c | ||
|  | b4facaeb3c | ||
|  | d12b7ccc6b | ||
|  | 453e8bd0a0 | ||
|  | 9204d390ae | ||
|  | b70ce0015c | ||
|  | d113827753 | ||
|  | c67f877857 | ||
|  | 0ec719e429 | ||
|  | 17f7b11148 | ||
|  | 966b017670 | ||
|  | 4c98070b3c | ||
|  | 3681d6ee1c | ||
|  | 0af17cdc33 | ||
|  | 2aae1f5e30 | ||
|  | d18f2a7bfd | ||
|  | 9046fe8d3a | ||
|  | 78c7ee247a | ||
|  | d5adb85e5b | ||
|  | 69f953fd9b | ||
|  | 484677b4b1 | ||
|  | b10a8e728f | ||
|  | 25f25a8767 | ||
|  | 0c053e4a2c | ||
|  | 3f6521cc9b | ||
|  | a074491d5b | ||
|  | a291164953 | ||
|  | 43c55b58d2 | ||
|  | e7298f8162 | ||
|  | ddf990296b | ||
|  | ead8aa7800 | ||
|  | 7a9dd1ac9b | ||
|  | 1c97c22eff | ||
|  | bbf621a8c4 | ||
|  | 8efa89165c | ||
|  | 4f8aaf9244 | ||
|  | a97edef380 | ||
|  | eefae24aa3 | ||
|  | 54bffc91ae | ||
|  | 63f5ef9e14 | ||
|  | 034f27a8dd | ||
|  | c2f6311367 | ||
|  | 6f00a48772 | ||
|  | b3dba67405 | ||
|  | c9a4235669 | ||
|  | ae0d52274c | ||
|  | 8973763866 | ||
|  | 3d799ae7fe | ||
|  | 8b10115390 | ||
|  | d2e010c439 | ||
|  | 15867ab423 | ||
|  | 22c9e99fa3 | ||
|  | ee262f6aad | ||
|  | af64af2397 | ||
|  | 1feead2260 | ||
|  | d3dcd24b4d | ||
|  | fd1e6796ef | ||
|  | 3ea0f0cbaa | ||
|  | f3e3311598 | ||
|  | 0dc50a93a4 | ||
|  | fda8e61be4 | ||
|  | ac1d4b4a7a | ||
|  | c719e274d5 | ||
|  | e4990f8ec5 | ||
|  | 62afd3342e | ||
|  | 6e8a89e6f1 | ||
|  | aa2437cfb8 | ||
|  | 4a710ecdfc | ||
|  | 3ef5bdfeda | ||
|  | 7915dda35f | ||
|  | 9120e16683 | ||
|  | a1ebc7090d | ||
|  | 054b4636e0 | ||
|  | e3e7b060b7 | ||
|  | 5ac9c75521 | ||
|  | 07710e0995 | ||
|  | d6a67f5f2b | ||
|  | 2675623aea | ||
|  | 94263c43d0 | ||
|  | d8ec03874f | ||
|  | a7247f5b8b | ||
|  | 4d37581694 | ||
|  | 5d7ddebcad | ||
|  | 53df0eb707 | ||
|  | 8babad9c7c | ||
|  | 8db7aa07bd | ||
|  | 42f4b06ac8 | ||
|  | f4b50368ba | ||
|  | db80417bd7 | ||
|  | 7a6f2ecc8c | ||
|  | f5d556a7f9 | ||
|  | 2aae46d632 | ||
|  | 19ebc6d6b3 | ||
|  | f88c29e083 | ||
|  | 6ed9899dc7 | ||
|  | 9de7698a5c | ||
|  | 112d2d6058 | ||
|  | ddb8346711 | ||
|  | 8dd3faf395 | ||
|  | 35f3e8708b | ||
|  | cfe3fcc9e7 | ||
|  | 66a6659a6e | ||
|  | 88ae3daa42 | ||
|  | 08b8fe01ab | ||
|  | 731132d4b3 | ||
|  | 98acff802f | ||
|  | 5f11f485a2 | ||
|  | 34f3169dda | ||
|  | a3ef8f814b | ||
|  | 385dd6fc23 | ||
|  | 9af4168ae2 | ||
|  | a5e0e31b74 | ||
|  | b385dc8c26 | ||
|  | 92c012b55a | ||
|  | 641f6c05d8 | ||
|  | 788f6b44a6 | ||
|  | 63a4525f06 | ||
|  | 3e34a3ef72 | ||
|  | 0c5e8ca199 | ||
|  | ff23fb0086 | ||
|  | 56f41d5e34 | ||
|  | 4700a239b9 | ||
|  | bd5abfb969 | ||
|  | b93fa75377 | ||
|  | 681ce9c60c | ||
|  | dd0f0fe415 | ||
|  | 119040fc50 | ||
|  | 551e5688da | ||
|  | 56c1035581 | ||
|  | ba1e907c79 | ||
|  | 2a3a27c56d | ||
|  | 647af34f5b | ||
|  | 993be6394e | ||
|  | 9a27505315 | ||
|  | 2e37f5dee3 | ||
|  | 03e486c082 | ||
|  | edc83305a4 | ||
|  | 66e7c51064 | ||
|  | 60244aaf16 | ||
|  | 443391c700 | ||
|  | 47dbafacd4 | ||
|  | 5b6811d073 | ||
|  | 7516116bb7 | ||
|  | e6014ea4dd | ||
|  | 362abfe284 | ||
|  | ad4880997a | ||
|  | 592becc126 | ||
|  | c38765301e | ||
|  | 5f27426f59 | ||
|  | d924f8bff8 | ||
|  | d14c61b160 | ||
|  | fe2b67998c | ||
|  | 04df3c9f7f | ||
|  | de3d0b40dc | ||
|  | 4db4a5f1b2 | ||
|  | 5a0524ff4d | ||
|  | 5b7801eea1 | ||
|  | fbe231793b | ||
|  | 6a9269111e | ||
|  | a94cfd34f5 | ||
|  | 28eae5a0fd | ||
|  | 1818738fc8 | ||
|  | 7e1e7a0780 | ||
|  | 1fc79ff6dd | ||
|  | 3535c1acda | ||
|  | 33c8caac8f | ||
|  | 51d708bbdd | ||
|  | a5a918df84 | ||
|  | 820541e427 | ||
|  | e63a8f0c01 | ||
|  | c11a9b8709 | ||
|  | 80f39e8097 | ||
|  | 2a8b65e29c | ||
|  | 4bdf50145e | ||
|  | 3a9919a377 | ||
|  | eef8ae00b8 | ||
|  | ed15fac691 | ||
|  | f739e679e4 | ||
|  | fc0fae8caf | ||
|  | f46896fd74 | ||
|  | 52649a8e4f | ||
|  | bdfb01f6a0 | ||
|  | 1137e57393 | ||
|  | 267ea13e8c | ||
|  | 04f7b772a3 | ||
|  | 42c7569791 | ||
|  | 6d29b00a80 | ||
|  | 9f1bd2d7d6 | ||
|  | 9826d7c494 | ||
|  | c6bf57b390 | ||
|  | bfcf07c1a2 | ||
|  | 4d7e96d423 | ||
|  | 449461e412 | ||
|  | 607275ec66 | ||
|  | e55cde2a81 | ||
|  | 84afb374e6 | ||
|  | da1620807f | ||
|  | f39ef8f565 | ||
|  | fe8b6e820c | ||
|  | f29d24e96a | ||
|  | 620ffe54ec | ||
|  | ceaa4cd07d | ||
|  | af17f903ee | ||
|  | c532e28841 | ||
|  | dba0846866 | ||
|  | bed629998a | ||
|  | bc2ede76bf | ||
|  | 2a1fec2ed2 | ||
|  | 004048e5a7 | ||
|  | b941d6f1e4 | ||
|  | 37b346740b | ||
|  | f5e332daf7 | ||
|  | fe9a9fc5cb | ||
|  | cc57477b99 | ||
|  | a1574a7187 | ||
|  | a5110b1f96 | ||
|  | 006713fe13 | ||
|  | 7868e672e0 | ||
|  | e1a133c2c0 | ||
|  | c77cd0da39 | ||
|  | 577333f2c4 | ||
|  | 7d8cdcbfea | ||
|  | c5c4c6f111 | ||
|  | 73be754680 | ||
|  | acd841dbb6 | ||
|  | 6b52ba9397 | ||
|  | 10d12f73d6 | ||
|  | cd9119655c | ||
|  | 41afeccd51 | ||
|  | 6b87cbb703 | ||
|  | 32afcbfe42 | ||
|  | bc2b38daf4 | ||
|  | f40b7b62bb | ||
|  | 1ca3f64bf0 | ||
|  | 92527b4c1d | ||
|  | c48012c385 | ||
|  | a282b17286 | ||
|  | 58d9463f16 | ||
|  | 047decd552 | ||
|  | 82e0877e64 | ||
|  | 040d75dafa | ||
|  | 4e1686f6e3 | ||
|  | b5e691f367 | ||
|  | 325f55f22d | ||
|  | 9724f2db7d | ||
|  | 5f20f321f0 | ||
|  | d4b087ea3f | ||
|  | 8ff10724d1 | ||
|  | 1581381467 | ||
|  | 96b5a30f60 | ||
|  | 0e17a0474a | ||
|  | b27368175d | ||
|  | aba36f7c92 | ||
|  | a3fa946300 | ||
|  | 01bbc2234e | ||
|  | 58e1864144 | ||
|  | 88458f5355 | ||
|  | a4f697bae1 | ||
|  | 8201408f16 | ||
|  | 8b8caa1c2e | ||
|  | 4dc50cb551 | ||
|  | 5522a305ab | ||
|  | d7f72056fc | ||
|  | 64c9c9b7fe | ||
|  | 98e1c843e4 | ||
|  | 906d9d858c | ||
|  | 16c1309df1 | ||
|  | 6eacf1bddd | ||
|  | 6c8c8e11cc | ||
|  | e941d2665a | ||
|  | 68669dbef0 | ||
|  | 6a48de9a9f | ||
|  | 9d6d98930b | ||
|  | 3cc858db12 | ||
|  | 386a391fd9 | ||
|  | d33aed4ed5 | ||
|  | 73ec8c31ad | ||
|  | 24944ad49e | ||
|  | 26ed231f61 | ||
|  | 8485b8429f | ||
|  | 358215e4dd | ||
|  | f874942075 | ||
|  | 2cadb546d5 | ||
|  | 344a1b9eb8 | ||
|  | 3c77f8a020 | ||
|  | 8e00408e3e | ||
|  | abcdfd8e28 | ||
|  | b0f5b6925d | ||
|  | ef79d0c43e | ||
|  | 78b4288005 | ||
|  | 680f5d21ee | ||
|  | c71aa0895f | ||
|  | 9f8e61789a | ||
|  | 932035cdc5 | ||
|  | ef198f1493 | ||
|  | 48ef856c0b | ||
|  | 9aea2b22c4 | ||
|  | e0055bc431 | ||
|  | 9553248ed6 | ||
|  | 39d2194d8f | ||
|  | 0800033b47 | ||
|  | 64d8943b7d | ||
|  | 444e97b00b | ||
|  | 1816bda7ea | ||
|  | d4a2031c07 | ||
|  | 8cf0b6cf51 | ||
|  | f2010bf7a5 | ||
|  | 8f56a7fe69 | ||
|  | 64c132ee0a | ||
|  | 84a7e86fe3 | ||
|  | a8c09d6144 | ||
|  | 87c46ba730 | ||
|  | 0f83dc6491 | ||
|  | cc22861719 | ||
|  | a14c192ea3 | ||
|  | b3d98be862 | ||
|  | 43027a4728 | ||
|  | 03831a7394 | ||
|  | fdbbd181ea | ||
|  | 69075376dc | ||
|  | 504d1440cc | ||
|  | 9e33b8b8da | ||
|  | 0cfcc5cd29 | ||
|  | e0de662f8e | ||
|  | 66a836d094 | ||
|  | 80095f4962 | ||
|  | 828d83dbef | ||
|  | 7de665d1e4 | ||
|  | 0a356ba73a | ||
|  | 41de8caa13 | ||
|  | 968609d06d | ||
|  | 3b199a2a87 | ||
|  | 0c1018ec61 | ||
|  | bc3f2db3de | ||
|  | 06bedb7adb | ||
|  | 45a9751217 | ||
|  | e8da62aa29 | ||
|  | ddb2ff4216 | ||
|  | f27e3478b9 | ||
|  | 38dc7fb7bd | ||
|  | aa4cd13c31 | ||
|  | 4a4b6c04a1 | ||
|  | 37fa3b34a2 | ||
|  | f8084e7955 | ||
|  | 4d5119ce3e | ||
|  | d85c347a6c | ||
|  | 7dd758a753 | ||
|  | 806654fc44 | ||
|  | 8e6b91cb9e | ||
|  | 334e6dca28 | ||
|  | f2daa17b92 | ||
|  | 6d9fccacb1 | ||
|  | 37638e7ed0 | ||
|  | 8a0e650511 | ||
|  | 8ba5a0d90c | ||
|  | bfd3edb617 | ||
|  | 56ba24962c | ||
|  | 19a2110ba2 | ||
|  | 242a3eec63 | ||
|  | fee46f2e54 | ||
|  | 6aed7e429a | ||
|  | 517ea82b99 | ||
|  | 99c29343de | ||
|  | 892fa76883 | ||
|  | d446b57d05 | ||
|  | 0e086d788b | ||
|  | 498841d45d | ||
|  | d1f8ee1e56 | ||
|  | 07feb5c925 | ||
|  | 75fd263e85 | ||
|  | 1e1f444cab | ||
|  | 89cc7e5fa9 | ||
|  | 265e7aefbf | ||
|  | 1c55a6c6dc | ||
|  | 8f18b5b8a7 | ||
|  | f790182f0b | ||
|  | 813007a5d8 | ||
|  | d03ff1e4d0 | ||
|  | 932bbd0381 | ||
|  | 01bd648cb2 | ||
|  | 779a5606a7 | ||
|  | ccc11e49d2 | ||
|  | d28c994ecd | ||
|  | 5d88717f32 | ||
|  | e35cfd4971 | ||
|  | bcc4bf5c2b | ||
|  | a0594cbce3 | ||
|  | 078bfefe41 | ||
|  | 9c1b11d605 | ||
|  | 44d82f9190 | ||
|  | 37fcde30d6 | ||
|  | 09c6cb4d6b | ||
|  | b428343c2a | ||
|  | dfce292294 | ||
|  | 2b8f613a00 | ||
|  | 2eb137618e | ||
|  | 4bb2b8ca9b | ||
|  | 5179562fb2 | ||
|  | 0a4de45453 | ||
|  | ffdc658dc8 | ||
|  | 7530f4407b | ||
|  | 73864c8101 | ||
|  | f948917124 | ||
|  | 0d44492086 | ||
|  | 38a22fbc99 | ||
|  | 8ae435549d | ||
|  | 9b113c0cbb | ||
|  | 0e0fac8c4b | ||
|  | 4cd9bb8f99 | ||
|  | ad9eaeafeb | ||
|  | 6cd392909c | ||
|  | 49ec430592 | ||
|  | 09f3fbeb38 | ||
|  | e7698686fa | ||
|  | 66d939df0d | ||
|  | 6bc079c7b7 | ||
|  | 299419917e | ||
|  | 69f6afe420 | ||
|  | b7279a3d9e | ||
|  | e14b854d7b | ||
|  | 8bd7c601c0 | ||
|  | 997288fa03 | ||
|  | 0f26b39997 | ||
|  | ae66fcac1e | ||
|  | 43944a94eb | ||
|  | eba0bde6f3 | ||
|  | 4544af441b | ||
|  | a8be94de6b | ||
|  | b24df31c2b | ||
|  | 332ba8ed7e | ||
|  | 58400f53bc | ||
|  | 01c2112881 | ||
|  | a546c2247d | ||
|  | 0da9142009 | ||
|  | 796add0ee2 | ||
|  | 00b32f64e6 | ||
|  | f97b3f23e2 | ||
|  | 08a079a96e | ||
|  | e98e951834 | ||
|  | 2668bf8519 | ||
|  | dd4c073e18 | ||
|  | c7c72f00c7 | ||
|  | ef1c665b9a | ||
|  | d56565be25 | ||
|  | e076b3aedc | ||
|  | ae3b2ddf5f | ||
|  | 1bdc427d73 | ||
|  | 6a639ce533 | ||
|  | d91ca8b197 | ||
|  | a01c0a283d | ||
|  | 5c393091a0 | ||
|  | 01b680504b | ||
|  | 8e4319cd5a | ||
|  | 5a776dd690 | ||
|  | cce08d95db | ||
|  | 28c1b208c1 | ||
|  | 3844bf1f72 | ||
|  | 745d192563 | ||
|  | ee782e92ac | ||
|  | afbc91d1fc | ||
|  | f998888d6d | ||
|  | 7d8b42d63e | ||
|  | 6ebd4e821f | ||
|  | d1806bfdc3 | ||
|  | 1d2d7155da | ||
|  | b09e0a05bf | ||
|  | c609e982fe | ||
|  | 2b227b43fe | ||
|  | 48f09f71ab | ||
|  | ead8c59bda | ||
|  | db52a9466c | ||
|  | 1509de390e | ||
|  | 88a1aa4f3d | ||
|  | 172e78e8f2 | ||
|  | 36bfef567d | ||
|  | e40ebd75a2 | ||
|  | 992732f2cb | ||
|  | b58a3ba1bb | ||
|  | afe521b0c9 | ||
|  | 5d9caef45f | ||
|  | 278e2f5605 | ||
|  | 1e299bf360 | ||
|  | 8dfa0bc38c | ||
|  | fde136fb7b | ||
|  | ee4da1a757 | ||
|  | ae2d96c455 | ||
|  | 6d8fbe0877 | ||
|  | 2fa1d8f2e8 | ||
|  | 533090a68e | ||
|  | 1dff59e1d6 | ||
|  | 44d232f52a | ||
|  | 5f6cff739a | ||
|  | 2764d235a9 | ||
|  | 45debff89f | ||
|  | c45fbe6310 | ||
|  | 9ef9c24388 | ||
|  | 6a40f23578 | ||
|  | 6a0a6b4751 | ||
|  | 0bee6f6b41 | ||
|  | 82a15b5a16 | ||
|  | 11b7c4459e | ||
|  | 98570ac456 | ||
|  | 1b2296ad5b | ||
|  | 16851746d6 | ||
|  | 935450a45f | ||
|  | ba67fd318b | ||
|  | 08ac459a41 | ||
|  | a83e9d9a0a | ||
|  | 62d3f01948 | ||
|  | af5ca2d0b8 | ||
|  | ab4bcdf12d | ||
|  | a6756d2cea | ||
|  | f81061dd42 | ||
|  | 8e2c304b3c | ||
|  | f21adaa3ef | ||
|  | 2637939e62 | ||
|  | faf05582f8 | ||
|  | 161c02ced3 | ||
|  | ff8de8e42d | ||
|  | 09d506194f | ||
|  | 42db3085df | ||
|  | ad14c88fde | ||
|  | 0c9daf6eaf | ||
|  | 86c6530e46 | ||
|  | 159f80d629 | ||
|  | aa949165c7 | ||
|  | d22359b6e7 | ||
|  | d73709653d | ||
|  | 405926e811 | ||
|  | 36758f41a4 | ||
|  | 7ebc9c79cf | ||
|  | e0668b55b9 | ||
|  | 76c09da961 | ||
|  | 7e3b8c2c59 | ||
|  | ecca854c7c | ||
|  | 3b0d7ea960 | ||
|  | f70fa42eac | ||
|  | 5698de6cf4 | ||
|  | c5a333a904 | ||
|  | ff324955dd | ||
|  | 70436f5dca | ||
|  | 31177a2b1b | ||
|  | 4de012fc49 | ||
|  | ee2888e744 | ||
|  | efe4df92dc | ||
|  | 723ab54f97 | ||
|  | d9389afc66 | ||
|  | e7178ee496 | ||
|  | d5f35bb3fb | ||
|  | 72f1a779f2 | ||
|  | 3277544295 | ||
|  | 98d2c64d5d | ||
|  | f68b46fc60 | ||
|  | d54ab856e7 | ||
|  | 16b24fadea | ||
|  | b3803cbdf1 | ||
|  | 2ceaa25181 | ||
|  | 513611c5a6 | ||
|  | 7ec4ba40ad | ||
|  | 92374e122b | ||
|  | 94f12732ab | ||
|  | 0904712a00 | ||
|  | 32becdbced | ||
|  | 34aa21f7d9 | ||
|  | cc81dd7d3e | ||
|  | 335213b55f | ||
|  | 13ab4166c0 | ||
|  | 3dc5a0e7f8 | ||
|  | e15c5cde53 | ||
|  | d88c09b098 | ||
|  | 893b383bdf | ||
|  | dd7c9d62e6 | ||
|  | 97c5c90eff | ||
|  | 1fb94e7a7b | ||
|  | daca87c6d0 | ||
|  | 203ec5fa46 | ||
|  | 9ea69c07b8 | ||
|  | 68539d6cc9 | ||
|  | f75fd0811e | ||
|  | 836bc9d456 | ||
|  | a37769aafe | ||
|  | 68e62e4bd2 | ||
|  | a5cd3728c9 | ||
|  | a48ce35f0b | ||
|  | e1835b5775 | ||
|  | 433832b329 | ||
|  | ee81da14d6 | ||
|  | 6395d1908e | ||
|  | 989a5a2f8a | ||
|  | b7a622c68e | ||
|  | a8507b437d | ||
|  | e505bf9ccf | ||
|  | a289b32053 | ||
|  | c3f1f09ad1 | ||
|  | 70ee2026ff | ||
|  | 690782bf60 | ||
|  | 755cc4835e | ||
|  | a684ea46e4 | ||
|  | 8fbe13f99d | ||
|  | 452e9e275f | ||
|  | cd40088636 | ||
|  | 9b9e6f4af5 | ||
|  | ae6eeadf54 | ||
|  | 5268b05060 | ||
|  | 390263a34e | ||
|  | 55646edc3e | ||
|  | 8d177beb78 | ||
|  | 1da0c59182 | ||
|  | 36e8f10d2b | ||
|  | cdf5a8f20f | ||
|  | eb64d92333 | ||
|  | eb55da63ef | ||
|  | 918302f79b | ||
|  | 9d7131d9f6 | ||
|  | 229c1114dd | ||
|  | 885df9156f | ||
|  | c319233ddc | ||
|  | 958b5c0780 | ||
|  | 880c0a5da8 | ||
|  | 237c6dc856 | ||
|  | ccf6e32bf9 | ||
|  | a1874f6f00 | ||
|  | 95e4490a8a | ||
|  | 31c132c2eb | ||
|  | 00b0ec58b4 | ||
|  | a1d0e5bb65 | ||
|  | 03e0d4b2e8 | ||
|  | 6afdd4e6fd | ||
|  | b500a0d477 | ||
|  | dd2463a440 | ||
|  | 23a8bebd9e | ||
|  | 3caf9108ad | ||
|  | bde4be8231 | ||
|  | 0bbbb12ed2 | ||
|  | b570bdaed7 | ||
|  | 8c0843cc87 | ||
|  | 31458ffd81 | ||
|  | c15c10a94e | ||
|  | 9fca978725 | ||
|  | b125901717 | ||
|  | eb018ae660 | ||
|  | 7e5a9474fe | ||
|  | 525a9b5036 | ||
|  | c3fbdf34ca | ||
|  | 48bd51e1a5 | ||
|  | 10d0b03a90 | ||
|  | e1b3582f08 | ||
|  | 95be1c9e22 | ||
|  | 1ce8fe06d5 | ||
|  | 15c649024e | ||
|  | e97303c226 | ||
|  | 3b786c819d | ||
|  | 04959dbd8b | ||
|  | 5cd4b874ea | ||
|  | f14ea1b3de | ||
|  | 9cc0cda0fb | ||
|  | 09a7a4bbe5 | ||
|  | cfea8b3745 | ||
|  | 28bf0b61ce | ||
|  | 2dc2429735 | ||
|  | 83d4592526 | ||
|  | 2d528c26ae | ||
|  | 66b3dce794 | ||
|  | 93f77a1045 | ||
|  | aa4d23a3d5 | ||
|  | 2d7ebff8e9 | ||
|  | bad9dd3b3b | ||
|  | 2f4e517857 | ||
|  | ff35ba3696 | ||
|  | 72768e7fad | ||
|  | 77f3852cdc | ||
|  | 66857ca477 | ||
|  | 75514fc7af | ||
|  | be06d871b6 | ||
|  | f98ee326b4 | ||
|  | bc8126eb16 | ||
|  | 4c8beefdcb | ||
|  | bbb6c53457 | ||
|  | d8991894e3 | ||
|  | c7b7dcfd03 | ||
|  | 2c9e50873c | ||
|  | 923367296d | ||
|  | 151a206617 | ||
|  | e403c4cf99 | ||
|  | e3fbe37f9f | ||
|  | dc870cd5ea | ||
|  | 584be44743 | ||
|  | 5fffd35ec1 | ||
|  | b92e22e4a6 | ||
|  | 3e6d16a7a8 | ||
|  | ecbcc277b8 | ||
|  | dff1d9e4dd | ||
|  | 7c0bde7310 | ||
|  | a82d21ac05 | ||
|  | 0bf8378fcb | ||
|  | 017ef8a837 | ||
|  | 0d63cdcb96 | ||
|  | 68a6f99c9f | ||
|  | 60781bcfc4 | ||
|  | 77fa2e2722 | ||
|  | c36afd872e | ||
|  | 7e58a4c130 | ||
|  | 19a4bf1088 | ||
|  | 9678bbae4b | ||
|  | a4d093afa1 | ||
|  | ba788bcf0f | ||
|  | f2c62bee7e | ||
|  | 548721e306 | ||
|  | 1ae950a638 | ||
|  | c9385e93fe | ||
|  | 9bb16e293c | ||
|  | c223702ea0 | ||
|  | 9167ba499d | ||
|  | 2d7e95e1b6 | ||
|  | 0cba736446 | ||
|  | 0816a57032 | ||
|  | a0ab0bd3e2 | ||
|  | b89ad4b328 | ||
|  | 6cda76a116 | ||
|  | c112b327ab | ||
|  | 46c12a8899 | ||
|  | c5219dfb3f | ||
|  | 4a8ee6815a | ||
|  | e1b6bb154a | ||
|  | b19c282269 | ||
|  | e520921746 | ||
|  | 970642244b | ||
|  | 3b90be2d9e | ||
|  | 2f756f1e3a | ||
|  | 78e84182f0 | ||
|  | 65a7a8caf8 | ||
|  | 4c6a2f5df9 | ||
|  | fea297e409 | ||
|  | 7cf6aba625 | ||
|  | 3bbc00cc8c | ||
|  | 70ed2b4203 | ||
|  | 0adce9b9c6 | ||
|  | 0e781d18fa | ||
|  | 4575a8fffe | ||
|  | 10d0ff252b | ||
|  | c7d54570cc | ||
|  | 7136b33f2e | ||
|  | 70a78e74f6 | ||
|  | d5707b7bf3 | ||
|  | 9f247901d4 | ||
|  | 5659742d97 | ||
|  | 450eaf7c4a | ||
|  | 47485e4b49 | ||
|  | 64254e758d | ||
|  | c1aa5d4e47 | ||
|  | ab8173637a | ||
|  | 3841cef497 | ||
|  | b717f1c7eb | ||
|  | da57f76de3 | ||
|  | 4784f1c65a | ||
|  | 41af63b333 | ||
|  | e2bb0de24d | ||
|  | b791fae9ce | ||
|  | 6033a9e20c | ||
|  | 9e8c8973d8 | ||
|  | 3933bf5c1a | ||
|  | 708e296774 | ||
|  | 84925ab69c | ||
|  | b3cb9b7fe2 | ||
|  | 9cb61fa34d | ||
|  | 7c219d235c | ||
|  | 6938c79f88 | ||
|  | b8284a147d | ||
|  | 15ee90e99c | ||
|  | 795f80b4ec | ||
|  | 6b6427492d | ||
|  | 6055b8c3dc | ||
|  | a98cb50d55 | ||
|  | e98bbc1c52 | ||
|  | 7245aece4f | ||
|  | 60cbb02822 | ||
|  | 4e863ecdac | ||
|  | 5037033fcf | ||
|  | e6b158bc97 | ||
|  | 4cc0dfa10b | ||
|  | 4ced8889d3 | ||
|  | d26967a87d | ||
|  | fc8955941b | ||
|  | 071a80360f | ||
|  | d2154f5f2e | ||
|  | 334d382bfa | ||
|  | 90c4b00f74 | ||
|  | 71261525e8 | ||
|  | 3126959576 | ||
|  | 02e51d8282 | ||
|  | ffb2027a19 | ||
|  | 70c9ab9074 | ||
|  | 6d1fdf1ba6 | ||
|  | 1f7180d9a8 | ||
|  | b4e94ae4dd | ||
|  | 07c606bfc9 | ||
|  | e705a8bd89 | ||
|  | b3bdfb7f1f | ||
|  | 5af1aeb092 | ||
|  | be64fa674a | ||
|  | 204f5591a9 | ||
|  | ee3e3a3a40 | ||
|  | f9200a2b75 | ||
|  | f570b70827 | ||
|  | 0db141eeac | ||
|  | acb2ee53bb | ||
|  | c544b7f5ba | ||
|  | c0024e97e5 | ||
|  | bdf8aa9168 | ||
|  | de5ce0f515 | ||
|  | bb95484c8a | ||
|  | cad18b8a3a | ||
|  | 0f6a98751a | ||
|  | aac5a4c27f | ||
|  | d3f6415387 | ||
|  | 04da44eb98 | ||
|  | 7649be97b1 | ||
|  | c9ef777e0f | ||
|  | c0cb2438d5 | ||
|  | 30c531b39e | ||
|  | bf703a8a66 | ||
|  | e7b631b087 | ||
|  | a9f5dc036c | ||
|  | 0a83b51e00 | ||
|  | eab63ecc6c | ||
|  | b0794cf35e | ||
|  | 5b9e71a27d | ||
|  | eae41de27d | ||
|  | e9163aa3a7 | ||
|  | 8c617515ba | ||
|  | 04e4e71f2e | ||
|  | a587482edf | ||
|  | 0aac9350d5 | ||
|  | f56c12ee4e | ||
|  | 4bb9ae61f2 | ||
|  | ff7f3484e4 | ||
|  | 5da3abe6b4 | ||
|  | c0b398e0ce | ||
|  | 3de10adac2 | ||
|  | 1b573d6552 | ||
|  | 2a96f93919 | ||
|  | c6b2639ca4 | ||
|  | b9abf37a7e | ||
|  | 373cbb4144 | ||
|  | a521982576 | ||
|  | a77fde577c | ||
|  | ea6926e57d | ||
|  | ba25b7fee6 | ||
|  | 7ee162d98b | ||
|  | 380f557c45 | ||
|  | 1bdae53f4e | ||
|  | 9314c346da | ||
|  | bfaad1388c | ||
|  | 0b580ad05d | ||
|  | bb35a80177 | ||
|  | 24fc95ac81 | ||
|  | 8f864417c4 | ||
|  | bb9d29b061 | ||
|  | b9d8ec1463 | ||
|  | 1842a7660d | ||
|  | 5caa2f5536 | ||
|  | d6078be8b7 | ||
|  | cf60723f14 | ||
|  | f7ff0a2b1d | ||
|  | cc49664b2f | ||
|  | 99fe74f026 | ||
|  | b021869eeb | ||
|  | b8806d163b | ||
|  | 1116aae1de | ||
|  | 5e5f60253b | ||
|  | bbc02752c9 | ||
|  | 9896bc110e | ||
|  | ca60f8ecdd | ||
|  | 544acd1e35 | ||
|  | 6e07602d77 | ||
|  | 82898f7bba | ||
|  | d61283a8bc | ||
|  | 1ee3f826cc | ||
|  | 4a00a5ba9e | ||
|  | 39eda67867 | ||
|  | a99d38fdaa | ||
|  | 0eb2d437e2 | ||
|  | 3ac9036c79 | ||
|  | c94e292176 | ||
|  | 91d87c2d9b | ||
|  | ff472f69c0 | ||
|  | e18119e24c | ||
|  | 4a592dc64c | ||
|  | d9e13201dd | ||
|  | 5c75b19c5d | ||
|  | 52a77db60f | ||
|  | 0513c250fb | ||
|  | 48864ad6cf | ||
|  | cdbccad21e | ||
|  | e15bc68c9b | ||
|  | 8bffd7672d | ||
|  | 61df5b3060 | ||
|  | b5255444cd | ||
|  | 0c94e377fc | ||
|  | 8e5c67b4b2 | ||
|  | b24f2f1756 | ||
|  | c69c17de42 | ||
|  | 061617122a | ||
|  | 125ce3240f | ||
|  | 7215efe167 | ||
|  | 06d1570142 | ||
|  | 093c370faa | ||
|  | aec9574737 | ||
|  | 7ceb76cff5 | ||
|  | 300e2fe9f8 | ||
|  | 91e1643627 | ||
|  | 91421b0c62 | ||
|  | 40f611664f | ||
|  | dcba4f4098 | ||
|  | c098ad2b3b | ||
|  | b43223cb7a | ||
|  | e243531dab | ||
|  | 1af38e62bc | ||
|  | f37f062cdc | ||
|  | 7e734214dc | ||
|  | 05d152746f | ||
|  | dea7f37553 | ||
|  | 415c599310 | ||
|  | 70cd4fedbe | ||
|  | 1e6d7673bc | ||
|  | b4963b725b | ||
|  | 0371ffa4ce | ||
|  | 6a664a7e15 | ||
|  | 88ce9300bc | ||
|  | 85cf0e311c | ||
|  | 0e3d75cfeb | ||
|  | 630c8a5faa | ||
|  | 905921a684 | ||
|  | 1e469b3b0f | ||
|  | bff3c4f95c | ||
|  | bd2bcb6994 | ||
|  | 4c8898a639 | ||
|  | 97df33ab1a | ||
|  | ef46fb2685 | ||
|  | d5d6dd3614 | ||
|  | 6c233c6a0a | ||
|  | 6db715d879 | ||
|  | ab02e8a546 | ||
|  | 8cbfe64f19 | ||
|  | fd1e9971e4 | ||
|  | 68336a76c5 | ||
|  | 393e914a86 | ||
|  | ffb54110e9 | ||
|  | 533d825f1a | ||
|  | c65279b672 | ||
|  | f9926beeef | ||
|  | add8a777d8 | ||
|  | 21bc505d85 | ||
|  | 3fc49c001e | ||
|  | 3d69a95c49 | ||
|  | d81fdf6d6b | ||
|  | 87d3109ffb | ||
|  | 180dbbb521 | ||
|  | 24aac7cee5 | ||
|  | 53e18a5387 | ||
|  | 92062d056d | ||
|  | 06368ab0a1 | ||
|  | 38efe25c68 | ||
|  | 319079de7a | ||
|  | 025bf900a5 | ||
|  | 2885f4f7b1 | ||
|  | c07eda15b1 | ||
|  | 4274296cf3 | ||
|  | 76a203d4df | ||
|  | 24f37e2062 | ||
|  | f465b2e2a0 | ||
|  | ce00e49a89 | ||
|  | d494f9d66b | ||
|  | c35a183a64 | ||
|  | 9cdd5fe7f2 | ||
|  | c21428215e | ||
|  | 64d5af46f5 | ||
|  | 25846ea18a | ||
|  | 798383596d | ||
|  | 9ca71bc937 | ||
|  | 5407429ec0 | ||
|  | ee5c94f6db | ||
|  | 91045afbee | ||
|  | 3f64782023 | ||
|  | f8d35f9502 | ||
|  | ea78d3ec9a | ||
|  | e056a28316 | ||
|  | 0bea721c2e | ||
|  | e1b89494d0 | ||
|  | cd8e7f3912 | ||
|  | 50604c25c2 | ||
|  | aa6b2357d8 | ||
|  | 5b2d29bef6 | ||
|  | a296d26328 | ||
|  | d01a26ec61 | ||
|  | efd7d6f0c0 | ||
|  | b55be093be | ||
|  | 7c1d5cadd7 | ||
|  | dd1592b03b | ||
|  | 9b37ac483f | ||
|  | 090820958e | ||
|  | ac21e1be5c | ||
|  | 5196443b26 | ||
|  | c8531cbeb1 | ||
|  | c560abedba | ||
|  | 9b952fbc44 | ||
|  | ccdf05e922 | ||
|  | c3d74f2ae9 | ||
|  | f47498888c | ||
|  | 5665a7f0cb | ||
|  | b8178c6c8d | ||
|  | 4a0f15eb88 | ||
|  | c4f53fe525 | ||
|  | 8c93ec52de | ||
|  | befe0fff2a | ||
|  | b6a837cbea | ||
|  | 4861973899 | ||
|  | c593e4b500 | ||
|  | 5bf78c20d4 | ||
|  | 5c672130e6 | ||
|  | d8214d4f12 | ||
|  | 64d1f09ce0 | ||
|  | 47d0f0ea40 | ||
|  | 2d85fd093e | ||
|  | d936568b76 | ||
|  | 4598a83e8e | ||
|  | f4bf00ad31 | ||
|  | 07fde7f6cc | ||
|  | 729209574e | ||
|  | f28206d989 | ||
|  | 0c81b32cac | ||
|  | 11216017cb | ||
|  | a7b9f53967 | ||
|  | 1fa2e2e37d | ||
|  | f67d5faeb7 | ||
|  | 5cbf859458 | ||
|  | 629ed74d09 | ||
|  | ca2af2ca63 | ||
|  | 52ab089615 | ||
|  | 01461a196d | ||
|  | 04832f052a | ||
|  | c8b2c8ae50 | ||
|  | 1b81c7fb22 | ||
|  | 9ccda0247e | ||
|  | a7df4dcf25 | ||
|  | d91f47c791 | ||
|  | a9ac4e7f44 | ||
|  | fc3ec57437 | ||
|  | 266f6ab919 | ||
|  | 6218c1c00b | ||
|  | cc81d6fe82 | ||
|  | 69f9102f2d | ||
|  | beb9275982 | ||
|  | abe48713f2 | ||
|  | 82cfaf2fbb | ||
|  | 3d3bc4738f | ||
|  | 2d0746f5a4 | ||
|  | 9c71e2f1c8 | ||
|  | 134fd62da8 | ||
|  | 2afd283582 | ||
|  | c66734bab0 | ||
|  | 8e56a61f95 | ||
|  | d265271148 | ||
|  | b40e397b28 | ||
|  | 35ff1d996a | ||
|  | deea0b05cb | ||
|  | c50c9ca545 | ||
|  | a819b4a5a5 | ||
|  | df2d7d4734 | ||
|  | 79ce4098cf | ||
|  | 374464a1f8 | ||
|  | c8d0bf27af | ||
|  | 6e4ae034b2 | ||
|  | 52b560e72d | ||
|  | 9b971ad222 | ||
|  | 3613162d09 | ||
|  | 3a272e998d | ||
|  | d4c750beb4 | ||
|  | 84b31e65e1 | ||
|  | 7b802bfd3d | ||
|  | f9c4632b8d | ||
|  | e4764cd8a6 | ||
|  | dd78a3a686 | ||
|  | 94c06e13f4 | ||
|  | e8bebe5a75 | ||
|  | 5b0e1b4f9e | ||
|  | 8c0a93779b | ||
|  | 9241479da4 | ||
|  | 8ffca93cd5 | ||
|  | 7fea0c124a | ||
|  | 20dbdb20d2 | ||
|  | e6b8e2e8be | ||
|  | 7c5b7f77cc | ||
|  | de84547a21 | ||
|  | 44676756ae | ||
|  | b399b0f182 | ||
|  | 1152191f48 | ||
|  | af1b07ad44 | ||
|  | b8113fff1e | ||
|  | ff6948cf2d | ||
|  | fd25e85d59 | ||
|  | c07cd72e85 | ||
|  | e2c101206c | ||
|  | 92276b5769 | ||
|  | a2133f61a8 | ||
|  | 199adbbcf0 | ||
|  | dc316fd7b4 | ||
|  | 025183602f | ||
|  | db4619a9d9 | ||
|  | 451e527b7c | ||
|  | 54dd3a00df | ||
|  | 03c5dab79d | ||
|  | 1fdee861e8 | ||
|  | c12bf991b3 | ||
|  | 78a097585d | ||
|  | 39132327cc | ||
|  | dc32318cec | ||
|  | 592f74124c | ||
|  | e5e63cc5ac | ||
|  | f40e0f786d | ||
|  | ebd9f1471b | ||
|  | d76547ead4 | ||
|  | 4600772e05 | ||
|  | ed597423cd | ||
|  | f20ca06f85 | ||
|  | a636d3f394 | ||
|  | 043df18daa | ||
|  | 96996bf18e | ||
|  | f350137a14 | ||
|  | b7a6f3ec75 | ||
|  | 6c34672549 | ||
|  | e779a07bce | ||
|  | 9a36e8ba3b | ||
|  | c968bacb01 | ||
|  | 25199dfb43 | ||
|  | 48fed4e6fb | ||
|  | fc253237c9 | ||
|  | 589948c7f4 | ||
|  | 7e69690605 | ||
|  | 95f498ba9b | ||
|  | fd07ae5225 | ||
|  | 8acd94fc89 | ||
|  | 1436480eab | ||
|  | 448d176c24 | ||
|  | fd269453a4 | ||
|  | b3b380964c | ||
|  | 6e9025ebf2 | ||
|  | 3922691b3c | ||
|  | 0545b77cf4 | ||
|  | 6b3f39fa1a | ||
|  | 3114ab87dc | ||
|  | 00bc99cc7b | ||
|  | 540b3ae2f4 | ||
|  | dbfe4140e1 | ||
|  | d3675ec254 | ||
|  | ded2483fc0 | ||
|  | e62ea388e0 | ||
|  | f20356e9be | ||
|  | d282a2d846 | ||
|  | 4641ac46e7 | ||
|  | ba9268a09e | ||
|  | fb9902c536 | ||
|  | 5318ba6c6e | ||
|  | fd5ebef488 | ||
|  | d9e4f39ddc | ||
|  | 435b9d8973 | ||
|  | 0ea70ba656 | ||
|  | 92a07b87d2 | ||
|  | c3c82282ba | ||
|  | adc15c24ef | ||
|  | dddf9a9396 | ||
|  | 9ca6860ffa | ||
|  | f7dd388954 | ||
|  | 6012839f0e | ||
|  | 8e9cbab053 | ||
|  | aaf375a57b | ||
|  | 3cce985f03 | ||
|  | c59df6ec20 | ||
|  | 5c3f41f64d | ||
|  | cf3523f49f | ||
|  | db794752cb | ||
|  | bceaebe856 | ||
|  | 3916de2921 | ||
|  | 9e0f8c1a97 | ||
|  | 0cbc56b82e | ||
|  | b95608f68a | ||
|  | b6e5dbd06c | ||
|  | 914f19be86 | ||
|  | f09bcf3fcf | ||
|  | d0b18dec8e | ||
|  | 75d486b124 | ||
|  | 4914609485 | ||
|  | 75bd66326a | ||
|  | 8f904f75bb | ||
|  | 549c598f51 | ||
|  | ed68d604d6 | ||
|  | f83752f43b | ||
|  | 86c22636eb | ||
|  | 30d20a453b | ||
|  | fe29d8a23f | ||
|  | 694d088160 | ||
|  | 6aabbffc62 | ||
|  | 7b59bc8d12 | ||
|  | 79d0fb0b52 | ||
|  | edf56d34f8 | ||
|  | 623329fb33 | ||
|  | 9f0074eef9 | ||
|  | 6733253826 | ||
|  | f117805129 | ||
|  | c75b1581d2 | ||
|  | 109e118aba | ||
|  | 201b77d5b6 | ||
|  | a5ca08f33d | ||
|  | 86210c4513 | ||
|  | 988a3e4446 | ||
|  | 0f5cd22bb7 | ||
|  | 2f5bed36b3 | ||
|  | 5b6534bb28 | ||
|  | e31e5b2477 | ||
|  | 07d5fafe2e | ||
|  | e08da659e5 | ||
|  | 8a4979f44c | ||
|  | e67464325f | ||
|  | 94c9b0d23b | ||
|  | e9ec310d8a | ||
|  | c78d1e3c39 | ||
|  | e94319145f | ||
|  | 3f3b01b5f6 | ||
|  | 19a2791c65 | ||
|  | 4e8ccf0ef3 | ||
|  | f1a7d5ecf7 | ||
|  | 8b05abb80d | ||
|  | 48c9349ce9 | ||
|  | 117d848466 | ||
|  | 9a2df072cc | ||
|  | 99c62aab36 | ||
|  | 224278e07a | ||
|  | 74b69e191e | ||
|  | 8cda8a727c | ||
|  | a3c0c7c96f | ||
|  | 4403e4ed62 | ||
|  | 9b209823f6 | ||
|  | b2cb125bd4 | ||
|  | 5e8f767642 | ||
|  | 6ee270d9d8 | ||
|  | 44fa309d20 | ||
|  | 58d88f3dd4 | ||
|  | e980c23177 | ||
|  | 75224321bb | ||
|  | 801af05b20 | ||
|  | 7611dbbddc | ||
|  | 6d40ca15bc | ||
|  | 32c1c19224 | ||
|  | bbf6357222 | ||
|  | dc16629c24 | ||
|  | 3718b9d768 | ||
|  | c25eb088ec | ||
|  | 3feb3e52f8 | ||
|  | 8e730ef93d | ||
|  | e0913a39ab | ||
|  | 7a27fbc001 | ||
|  | ee0dbdad35 | ||
|  | 9225f88f89 | ||
|  | a04839dd6b | ||
|  | 002006517a | ||
|  | f5b202d438 | ||
|  | a7df094ff4 | ||
|  | 1e6fa77633 | ||
|  | eb4cff202c | ||
|  | 7ee777f405 | ||
|  | 81bd5c784e | ||
|  | b526e132a7 | ||
|  | 1860f66de5 | ||
|  | ded9ada9bc | ||
|  | d0e6a2eb8b | ||
|  | 4e103a1963 | ||
|  | 475e927178 | ||
|  | ca7932c4f0 | ||
|  | 8ab47d3321 | ||
|  | def7e87151 | ||
|  | 27568c2bef | ||
|  | 0694a187d7 | ||
|  | 832601b36b | ||
|  | 578969c34c | ||
|  | d1d0115aed | ||
|  | c89e6ebfab | ||
|  | ca1089b881 | ||
|  | a1d04f2aad | ||
|  | bf0604133c | ||
|  | a82b2da16e | ||
|  | f2273c0acc | ||
|  | 17bedac96c | ||
|  | 4831fad27a | ||
|  | 5e896cf582 | ||
|  | add3491c57 | ||
|  | f470576822 | ||
|  | 10760a53a8 | ||
|  | eee805183c | ||
|  | b8fb391022 | ||
|  | 3c698f1584 | ||
|  | 2fad52d684 | ||
|  | ec64a68a71 | ||
|  | db55562f6a | ||
|  | d8409a9d2b | ||
|  | 0d0ce6eec1 | ||
|  | 483f313eda | ||
|  | 7b6c742178 | ||
|  | d4a35ba6ff | ||
|  | 68b112837a | ||
|  | e2f20ebf94 | ||
|  | f870e4965a | ||
|  | 7ebcb219d6 | ||
|  | c21913a66b | ||
|  | 77e956a29f | ||
|  | 08275c406a | ||
|  | 2931e1b87b | ||
|  | 153b422496 | ||
|  | 0f6a6d6fea | ||
|  | 91fdb3e2d4 | ||
|  | d8e87bd881 | ||
|  | 922033c1b2 | ||
|  | df1793efbf | ||
|  | 836a2700f2 | ||
|  | 8f3aaf77a1 | ||
|  | 00c059e5b1 | ||
|  | f4f355c74a | ||
|  | b465fc5aaf | ||
|  | 2d78eaa48d | ||
|  | d08451bccc | ||
|  | d8e785aed0 | ||
|  | 267b6f49b5 | ||
|  | e6688f4b9d | ||
|  | 9d7b9771c2 | ||
|  | 136a9a39de | ||
|  | 3dcf628fdb | ||
|  | e614e9787a | ||
|  | e426fc0922 | ||
|  | 5d4bfffc7e | ||
|  | 207cdaf7a4 | ||
|  | 7315b581ce | ||
|  | 38efaae7b2 | ||
|  | 469e042216 | ||
|  | 0f1a4b9d8f | ||
|  | 7303c00296 | ||
|  | fc55b34d84 | ||
|  | 6f67fc0e02 | ||
|  | 562d722ad5 | ||
|  | 144c1ba3a6 | ||
|  | 06b032af91 | ||
|  | 3603140114 | ||
|  | e094785cbd | ||
|  | e7408224ac | ||
|  | e67c05c274 | ||
|  | b22804efaf | ||
|  | 890f55f91a | ||
|  | cc5fc0b892 | ||
|  | 5efe2b027a | ||
|  | 5b6569d0f9 | ||
|  | 0eda7ac498 | ||
|  | a5ef353484 | ||
|  | 67a36d8d31 | ||
|  | 7cc3cc3990 | ||
|  | dc0edc4c2b | ||
|  | 71d2f091e5 | ||
|  | c2f062a391 | ||
|  | 224f490455 | ||
|  | 5b35232ab4 | ||
|  | 6d6db70e42 | ||
|  | 6830e15b4e | ||
|  | 3f07cad35d | ||
|  | e951340033 | ||
|  | db8912a735 | ||
|  | 0e297731a3 | ||
|  | f20c4f98ac | ||
|  | 05e60cc7c0 | ||
|  | 55b4469767 | ||
|  | f15516e478 | ||
|  | 17ceadbadf | ||
|  | 8c25b2b316 | ||
|  | 8b1ae404a3 | ||
|  | 13534cd4a9 | ||
|  | abfb345503 | ||
|  | 42ae935496 | ||
|  | 434515d957 | ||
|  | 094f7803b7 | ||
|  | b0c7bad391 | ||
|  | e9a4a905ef | ||
|  | 7b6cd0cfbe | ||
|  | b718b12083 | ||
|  | cfa7258ff4 | ||
|  | b70e0a0870 | ||
|  | da8eb464b8 | ||
|  | 8f9d1cfa30 | ||
|  | 585009ac5c | ||
|  | 30ee65fd14 | ||
|  | 76428b16f0 | ||
|  | 0d7b14e2d8 | ||
|  | a9d19d02b3 | ||
|  | adcbe55307 | ||
|  | aa99a7df64 | ||
|  | 00afa1ce52 | ||
|  | e94bf4c63c | ||
|  | ec5adffdc2 | ||
|  | 733c17ad3a | ||
|  | 53b0b562e6 | ||
|  | fabae6e970 | ||
|  | a9f9c40d8a | ||
|  | 6fc89607d3 | ||
|  | 2340760f53 | ||
|  | 39d6d2857e | ||
|  | 7b722a0001 | ||
|  | e7682119e0 | ||
|  | af6be44676 | ||
|  | 5a8f97a0b6 | ||
|  | 0d4dd385b8 | ||
|  | 94f0f3e966 | ||
|  | 43e31765e5 | ||
|  | 7c1bdfe713 | ||
|  | 9f09784b55 | ||
|  | e7a3a89bfb | ||
|  | 7ea7e63f44 | ||
|  | 1d2ce2cbeb | ||
|  | 06cf2e0bd7 | ||
|  | 9d219ae4b9 | ||
|  | 71f5a6c50e | ||
|  | 90b2be2bf4 | ||
|  | db1aa8fcbd | ||
|  | 11c000f764 | ||
|  | 4d6dcbd173 | ||
|  | 0da117efd2 | ||
|  | 533c368e32 | ||
|  | 8883513b0e | ||
|  | dcc9a71455 | ||
|  | 1a56743bb1 | ||
|  | 387a4b7c35 | ||
|  | 1d65d63bd9 | ||
|  | dda19c29fe | ||
|  | ca41669f4f | ||
|  | 0e1886e6bd | ||
|  | c26e116f0e | ||
|  | 5c9c7f2c5e | ||
|  | ca2fb6cef3 | ||
|  | 46dac909ef | ||
|  | b1e4347e10 | ||
|  | 97aa91c75e | ||
|  | 4f8fb32136 | ||
|  | e0fbce0087 | ||
|  | fb22f78fb3 | ||
|  | d6393cdbe5 | ||
|  | 5167fdb3f0 | ||
|  | ab00822764 | ||
|  | b4352ad38b | ||
|  | d07d00fa41 | ||
|  | 11d87e4725 | ||
|  | 627ed51a1b | ||
|  | c8f3bfa726 | ||
|  | 3091e3a1c8 | ||
|  | 2f3e7d1c27 | ||
|  | 0e831d4b92 | ||
|  | 7294ec9a3c | ||
|  | e34bab9585 | ||
|  | 7dd14955c1 | ||
|  | 6428ced157 | ||
|  | 30a42ec1bd | ||
|  | aacea3e9db | ||
|  | 6886b61186 | ||
|  | 0744c9fa29 | ||
|  | 502a665ffc | ||
|  | 3c315703c0 | ||
|  | 12ed07a607 | ||
|  | 101b33c381 | ||
|  | 97f4316653 | ||
|  | b0704e86f0 | ||
|  | a182b13e5a | ||
|  | 80b630a1e4 | ||
|  | 475efbe007 | ||
|  | 3ab5e5ac48 | ||
|  | c6c5ff2089 | ||
|  | 176ec8ac7d | ||
|  | dcdd4b3255 | ||
|  | fc0a0105b3 | ||
|  | f3960d21a8 | ||
|  | a44d853c1b | ||
|  | 6b41734d6a | ||
|  | c33dc0f3be | ||
|  | bb5ffb24a8 | ||
|  | a878c9a61d | ||
|  | 6454bf8ec4 | ||
|  | 40aa733ea7 | ||
|  | f37a822725 | ||
|  | f249ccd414 | ||
|  | 7ef4ddf0f3 | ||
|  | d8e18df3a1 | ||
|  | 78d3d9d27d | ||
|  | 0aa0ec5abd | ||
|  | b6eef3612f | ||
|  | 666d62dd7a | ||
|  | 44ee4b989f | ||
|  | 18790d867c | ||
|  | d6b8936376 | ||
|  | 4d840c7db8 | ||
|  | 4d2b21816d | ||
|  | 2d34fdd28f | ||
|  | 68abda1219 | ||
|  | f778f08f76 | ||
|  | ac1bd2fb7b | ||
|  | 4b7b1379d9 | ||
|  | e560e2ab3f | ||
|  | 1e441c2ddf | ||
|  | 93ce74eeb1 | ||
|  | f718f4251b | ||
|  | 4644c9b621 | ||
|  | 197081f10d | ||
|  | 00b717cde8 | ||
|  | 34aa917ca4 | ||
|  | a38ddcb364 | ||
|  | 5b9576df4e | ||
|  | 310219e5d7 | ||
|  | a0deb463c9 | ||
|  | 90ddec2ad8 | ||
|  | f6b03d5a78 | ||
|  | f531daa872 | ||
|  | 046dceb5c2 | ||
|  | dcc1f00048 | ||
|  | 05f935b598 | ||
|  | f2d27403c5 | ||
|  | 473efbe67a | ||
|  | aeabf0f324 | ||
|  | 80ab552ad8 | ||
|  | 7d4695c5b2 | ||
|  | 5189eaca36 | ||
|  | cfb31377fc | ||
|  | a07c52e112 | ||
|  | 8e1071aa89 | ||
|  | 7cb9a6ba60 | ||
|  | 350dc731f1 | ||
|  | f690f58bd4 | ||
|  | 4bc65e9ef7 | ||
|  | 2d600da8b6 | ||
|  | 35af53828a | ||
|  | 10ddd5b127 | ||
|  | f46e131f18 | ||
|  | feb5c8be95 | ||
|  | edf12bec71 | ||
|  | ff1fc28287 | ||
|  | 314398ba4c | ||
|  | 840331347b | ||
|  | 6181b12ab8 | ||
|  | 68da661edc | ||
|  | 88cbb6913d | ||
|  | 7a26646e1b | ||
|  | 92eb3b0bf6 | ||
|  | fb63434eee | ||
|  | 97f90d9684 | ||
|  | f91786367f | ||
|  | 6a57337a68 | ||
|  | 211e2bb37a | ||
|  | d2d08bf143 | ||
|  | 8acb37b6c2 | ||
|  | 81b3d2db4f | ||
|  | 9633c0b07a | ||
|  | 1dfa8ee7d8 | ||
|  | 1163543a98 | ||
|  | bdb7de34be | ||
|  | 9500fc11ac | ||
|  | 65daf29acd | ||
|  | 298b25cf7d | ||
|  | 41f4e22a17 | ||
|  | 288c57c144 | ||
|  | 7ff8923569 | ||
|  | b41779bd02 | ||
|  | beea6bc794 | ||
|  | fee58e98c5 | ||
|  | c51c1da618 | ||
|  | ea2812f50f | ||
|  | 3ec05709d5 | ||
|  | 4bdac7404a | ||
|  | cc41218d37 | ||
|  | 4b336b1853 | ||
|  | e1c77ce236 | ||
|  | 064d412ec8 | ||
|  | 7fff4f249d | ||
|  | 7a3745f642 | ||
|  | f8658f6afa | ||
|  | 223b725a10 | ||
|  | 25aad8d7be | ||
|  | b2c9b7635d | ||
|  | 24d13dd120 | ||
|  | 965340ff90 | ||
|  | 8e36fe6bef | ||
|  | 2eb41a8caf | ||
|  | fb989ae62f | ||
|  | 7901ec2a64 | ||
|  | f675dbc726 | ||
|  | 2ad4fdbbb9 | ||
|  | 97cb0cbd08 | ||
|  | 4ca0805de1 | ||
|  | 4b358abbb7 | ||
|  | dc82a0fc16 | ||
|  | 435d6f6f3f | ||
|  | ef92451d1a | ||
|  | 06184bdcb1 | ||
|  | af98d01053 | ||
|  | bb1cda0916 | ||
|  | a6d0ea347c | ||
|  | 0fcd57192b | ||
|  | a6ffa5738b | ||
|  | c75bd97537 | ||
|  | eea09f4de5 | ||
|  | 5656ec11d3 | ||
|  | eb53e44cb0 | ||
|  | 69f3106062 | ||
|  | 8ab99f6129 | ||
|  | 53a3c59a91 | ||
|  | df36983049 | ||
|  | bda016bb3b | ||
|  | cc174b7b85 | ||
|  | bf9d120081 | ||
|  | 775c85fc18 | ||
|  | 5a756aaed9 | ||
|  | dca092fd7c | ||
|  | c6e92ecac4 | ||
|  | 93008ff605 | ||
|  | 43c7b935df | ||
|  | 8f9a0a244a | ||
|  | fd13bd864e | ||
|  | 710f27afa9 | ||
|  | f537793b0b | ||
|  | f7183e38ee | ||
|  | 0a65dfdd10 | ||
|  | 3075578245 | ||
|  | b042b7705e | ||
|  | d56eb397f9 | ||
|  | 3054a1d32d | ||
|  | 0a3cd652b0 | ||
|  | f70b914779 | ||
|  | 46ca0ac10d | ||
|  | 031f647952 | ||
|  | 8f1c86f550 | ||
|  | 926fdecd13 | ||
|  | af2ca7a67e | ||
|  | 9e3e2ff81a | ||
|  | a9fe6472d9 | ||
|  | a862a81480 | ||
|  | dbb92881a1 | ||
|  | 10bf7f5d07 | ||
|  | 1e61d84fd1 | ||
|  | 8618ba1b60 | ||
|  | 3c8c44155d | ||
|  | 2002412026 | ||
|  | 7f69517fd4 | ||
|  | 851f8645b5 | ||
|  | c40cfaa388 | ||
|  | 0349d1d57c | ||
|  | 53049c02ee | ||
|  | 73a3a61729 | ||
|  | 5fe6aa2800 | ||
|  | c7eafd7c79 | ||
|  | 10b5fb5d72 | ||
|  | c4eaa944e2 | ||
|  | a735939d1e | ||
|  | 6ed5f04970 | ||
|  | b459b09b2f | ||
|  | 3f5877dbcc | ||
|  | e659b91c4d | ||
|  | e09f054058 | ||
|  | b646f50265 | ||
|  | 0a48ef3030 | ||
|  | ba614801ee | ||
|  | fd6eb47e68 | ||
|  | e69aeb8b98 | ||
|  | 26ea1da146 | ||
|  | c9e8c7a290 | ||
|  | 5e4eb92443 | ||
|  | 461b6499ef | ||
|  | c769920b6e | ||
|  | 181b98ef9e | ||
|  | 4e1184a400 | ||
|  | e52d9e3210 | ||
|  | dc6475c91b | ||
|  | 52f9956e92 | ||
|  | 0bf00d1ca4 | ||
|  | d1a707df57 | ||
|  | 4dc9b45297 | ||
|  | 6e31eebfb5 | ||
|  | a7df828932 | ||
|  | 517cf61d11 | ||
|  | 4be7bc8323 | ||
|  | 74c05d00a9 | ||
|  | 677613d30a | ||
|  | bacba629a5 | ||
|  | 14e36f1362 | ||
|  | d43ad849d1 | ||
|  | 627aa61184 | ||
|  | dad5b17ac8 | ||
|  | fef52c0112 | ||
|  | 8c4765b386 | ||
|  | 7c121bfc01 | ||
|  | 942c5cc04b | ||
|  | 348b3036ff | ||
|  | 09d3451d9d | ||
|  | b1a49e5f29 | ||
|  | da01a5b4dc | ||
|  | 3f9cdd9b56 | ||
|  | 0f9e87d7bb | ||
|  | 0869789214 | ||
|  | 10c8cc35c5 | ||
|  | 30c2e3e8ff | ||
|  | 86cc2f1075 | ||
|  | fa357a450b | ||
|  | b32641db87 | ||
|  | 0ee790969d | ||
|  | 7844ace934 | ||
|  | f4993d6e5d | ||
|  | 0fab806f36 | ||
|  | be2113d291 | ||
|  | 625d5b2313 | ||
|  | 6471c0c536 | ||
|  | 47c53fa60a | ||
|  | cf50e4f6ec | ||
|  | 7eea97d741 | ||
|  | 88b55ab93e | ||
|  | ee36d47c27 | ||
|  | 6f2fdbe447 | ||
|  | 0f36be0001 | ||
|  | 0f4a197e34 | ||
|  | 7dbff5b9e6 | ||
|  | 220246278a | ||
|  | 349e5a15e9 | ||
|  | bf7f4bba7b | ||
|  | ab1766a559 | ||
|  | 51bf33040a | ||
|  | a2c7273801 | ||
|  | ec6ac5bf24 | ||
|  | ec7501782d | ||
|  | 890b1c2d52 | ||
|  | c25d07259a | ||
|  | c960246eee | ||
|  | a01aee3111 | ||
|  | e2e951efdf | ||
|  | 3f6393f732 | ||
|  | b6eb343234 | ||
|  | 207a7e5160 | ||
|  | a0face4a28 | ||
|  | a8cf9f5cc4 | ||
|  | 461b38e653 | ||
|  | 8e4c0f7c22 | ||
|  | d78bfcc35c | ||
|  | 2b7c09e6ee | ||
|  | 036d9dbe59 | ||
|  | 1d342cc6af | ||
|  | 62b32b2211 | ||
|  | ae45ce517e | ||
|  | 5b3ccab7dc | ||
|  | 95f16c38a9 | ||
|  | d616cb283b | ||
|  | 9874fe2c23 | ||
|  | 520a142992 | ||
|  | 6ff56dc0bb | ||
|  | 1e63615592 | ||
|  | 3e62ffed0a | ||
|  | b133d51a83 | ||
|  | 037b89f018 | ||
|  | 20d06d9f9d | ||
|  | 156cf7315c | ||
|  | e2886e5303 | ||
|  | c6cf330e70 | ||
|  | 6be3b62d78 | ||
|  | c57af5e81b | ||
|  | f7431f809e | ||
|  | ea43c34de8 | ||
|  | fb6e9fa58f | ||
|  | b2ce1e8029 | ||
|  | d90c51220f | ||
|  | d1b14b68fa | ||
|  | d911728611 | ||
|  | 86a7200012 | ||
|  | 6ddb7453e1 | ||
|  | ad2355f8d3 | ||
|  | 582c498fe3 | ||
|  | 0a0c58d450 | ||
|  | 0dc592b819 | ||
|  | f46300016d | ||
|  | 3e1a7c6102 | ||
|  | f07065bf84 | ||
|  | 6d79903eb3 | ||
|  | e166329f34 | ||
|  | bb1bf6a88c | ||
|  | 30cbb6c9a8 | ||
|  | 4e33ab1e89 | ||
|  | 5494f309c0 | ||
|  | 3b6e7eccdd | ||
|  | e41d6787bb | ||
|  | ed30108961 | ||
|  | 12712ef812 | ||
|  | 0307f6b42c | ||
|  | 3e44620966 | ||
|  | 7424f1f768 | ||
|  | b5331d821c | ||
|  | 27f6d47efa | ||
|  | dbc7ad2ec4 | ||
|  | 7b27d270a2 | ||
|  | 97b3a0b093 | ||
|  | 06b38506d1 | ||
|  | fd581ffc37 | ||
|  | ff57c5e9d3 | ||
|  | 9b16d7c786 | ||
|  | 4c1bb18956 | ||
|  | 7d2bf892b1 | ||
|  | a99e77093f | ||
|  | 92737bb695 | ||
|  | 9b81955544 | ||
|  | 4a0031080a | ||
|  | 40e9fba312 | ||
|  | e227cc92ff | ||
|  | 73dbdbcbe6 | ||
|  | 3961f26635 | ||
|  | e51c274a18 | ||
|  | e75d0c58a9 | ||
|  | 9a798360f4 | ||
|  | 844ad09464 | ||
|  | 1e1d1efd90 | ||
|  | 240e6835c2 | ||
|  | 61398ee8f8 | ||
|  | e6e84859b7 | ||
|  | abcdd331db | ||
|  | 775d136b91 | ||
|  | dc93691fd9 | ||
|  | 48d782c69c | ||
|  | 0a04e626d7 | ||
|  | e7c4bf5ebf | ||
|  | 546a416f7e | ||
|  | 179a7a2792 | ||
|  | 251b6fcf70 | ||
|  | ab1fffb721 | ||
|  | da352a322c | ||
|  | 7d20458e82 | ||
|  | 5a54066f81 | ||
|  | a58e5a3399 | ||
|  | 9872f43cbf | ||
|  | 1078cc4642 | ||
|  | db7ae028b2 | ||
|  | 2b6f5dbd59 | ||
|  | f7aa0c45df | ||
|  | a72d58cdf9 | ||
|  | 067283834a | ||
|  | cf362c4a61 | ||
|  | 496245c801 | ||
|  | 859ab36347 | ||
|  | 1d740c7c36 | ||
|  | a03c4c3659 | ||
|  | 094ecceaac | ||
|  | 2812736ae5 | ||
|  | 6f87f8706c | ||
|  | 38beebe720 | ||
|  | fc1c3c6808 | ||
|  | 96ba895b84 | ||
|  | df35dfe3bf | ||
|  | c5504c6657 | ||
|  | 530e109433 | ||
|  | 6cce47b2f1 | ||
|  | 6185d5eca1 | ||
|  | 685ad1746e | ||
|  | 891f870ec0 | ||
|  | ad9933f0f6 | ||
|  | 1b86117754 | ||
|  | eeb3c968d6 | ||
|  | 406658a10f | ||
|  | 6a0551cea1 | ||
|  | 553f3b45d2 | ||
|  | 064a8e785c | ||
|  | 21e9723bb2 | ||
|  | 60b2c44a44 | ||
|  | c4fe3ecc0a | ||
|  | 2f18a8f6d0 | ||
|  | 5ac784e18a | ||
|  | 7a2164b4d0 | ||
|  | 0a43eae184 | ||
|  | 3117e2b2a3 | ||
|  | 41fece4643 | ||
|  | 7aa807ec7f | ||
|  | 4d16e1e14a | ||
|  | 73fc18099e | ||
|  | e34dac8dbb | ||
|  | af0e7f7187 | ||
|  | a3a6812608 | ||
|  | 2725c4ad4d | ||
|  | c8cd6e9460 | ||
|  | 0cd27d6129 | ||
|  | b47fc1c020 | ||
|  | de6ef7ef5e | ||
|  | f95fe8f1da | ||
|  | bd0dee5db5 | ||
|  | c13b7fd883 | ||
|  | f7e74b3088 | ||
|  | 343f01d5e1 | ||
|  | 08bacdd090 | ||
|  | 41b1c80492 | ||
|  | e5d7316e5d | ||
|  | b043c3a6da | ||
|  | 98b2855b9c | ||
|  | f3c52c409f | ||
|  | 1307bdc612 | ||
|  | 8c2e6971fc | ||
|  | 1903990f30 | ||
|  | 7d67005709 | ||
|  | 9acc2f92d1 | ||
|  | 72dfb0bda3 | ||
|  | 1635612430 | ||
|  | abda837d2f | ||
|  | 101fb0b8aa | ||
|  | 10de7dc1f9 | ||
|  | d2309b8114 | ||
|  | 6bdd81623f | ||
|  | f538c9f0c3 | ||
|  | 8ae3bad6f7 | ||
|  | 77de99b383 | ||
|  | 312949f336 | ||
|  | 1ab635bd7e | ||
|  | b35abd548c | ||
|  | 30e1c3307c | ||
|  | 08e052380a | ||
|  | 0e824c35cc | ||
|  | 548374ac2d | ||
|  | 9ad79fefc9 | ||
|  | 49d37c016e | ||
|  | 7c70c79a84 | ||
|  | 6916b8bff7 | ||
|  | 73dfb5f443 | ||
|  | 69b9dfa468 | ||
|  | ab61b8ba0a | ||
|  | 5c8c64242f | ||
|  | ddf96943f0 | ||
|  | e773be2f58 | ||
|  | f965804e6d | ||
|  | ec078eba72 | ||
|  | 1815cb1bc3 | ||
|  | 7b3cd71085 | ||
|  | 06128b5d07 | ||
|  | 990c8e1f18 | ||
|  | a170506356 | ||
|  | 5ecf2a3357 | ||
|  | fa48746ba9 | ||
|  | e2b8c069d7 | ||
|  | 14407bd1aa | ||
|  | 08db72903c | ||
|  | 46f9fab140 | ||
|  | b7d06f2c0a | ||
|  | 118196a0bf | ||
|  | 586ce1fc80 | ||
|  | adb979df38 | ||
|  | 3401cb5b4a | ||
|  | ebf1f12e97 | ||
|  | 5766208207 | ||
|  | 4bf4771f08 | ||
|  | 0e87db9eb7 | ||
|  | 1e053783f3 | ||
|  | 7afc96112b | ||
|  | 7bb41a30ed | ||
|  | 3d1b0eb843 | ||
|  | 5b9af0b5ae | ||
|  | 9219ec539d | ||
|  | c8bd57cd4d | ||
|  | 53bf8c09fd | ||
|  | 651c383668 | ||
|  | 9ed7587e3e | ||
|  | 674295e800 | ||
|  | 6b02f2eea0 | ||
|  | 5237e55326 | ||
|  | 3b59592110 | ||
|  | 72640ae058 | ||
|  | d916027e75 | ||
|  | 8966d2aa06 | ||
|  | de7ea04f54 | ||
|  | bf71fabe0e | ||
|  | b3368acb33 | ||
|  | 87220c6697 | ||
|  | a3b5c2ad71 | ||
|  | fb4c1473c5 | ||
|  | 2bb2502d20 | ||
|  | fe51698579 | ||
|  | 0f0f40bff3 | ||
|  | a798fe72d3 | ||
|  | fba98d03a5 | ||
|  | 7dd2517f67 | ||
|  | 641477d6f6 | ||
|  | 8e56656c8d | ||
|  | 564a6a1f62 | ||
|  | 69f0c80cd7 | ||
|  | 6fcb51cea2 | ||
|  | c58b8a4973 | ||
|  | c8f4ab4f06 | ||
|  | e425c4cca8 | ||
|  | 056ec986c2 | ||
|  | de3b2fb95b | ||
|  | 789e39c719 | ||
|  | b29c3152db | ||
|  | 3831679772 | ||
|  | 596f9566d8 | ||
|  | 124befe9d6 | ||
|  | 895534f32b | ||
|  | 50c16fe6de | ||
|  | b092d1a5d3 | ||
|  | a9b45630d7 | ||
|  | c1a39c269e | ||
|  | 6fa3f0b6cd | ||
|  | 9e5e3d1559 | ||
|  | 7135205299 | ||
|  | d99d977d2b | ||
|  | 7dd7e562bc | ||
|  | 75d857027e | ||
|  | 17694c1d01 | ||
|  | 749ad700d8 | ||
|  | 8f3df3039a | ||
|  | 02c315c194 | ||
|  | b697375573 | ||
|  | c57ef7725e | ||
|  | 3ae07503f2 | ||
|  | 9a0341adde | ||
|  | 96225efd96 | ||
|  | c3bd904f41 | ||
|  | 74257163b1 | ||
|  | 7bc75fd220 | ||
|  | a23281afab | ||
|  | 9e90dbdde6 | ||
|  | 1e8d8e40a2 | ||
|  | 583e208c1e | ||
|  | 9b91c427a1 | ||
|  | 196c5e9c24 | ||
|  | d8f7feb672 | ||
|  | 7c889f17b9 | ||
|  | c15a75556d | ||
|  | 5275c2e35f | ||
|  | 5267e06969 | ||
|  | b62183adcb | ||
|  | 5d2dec1803 | ||
|  | 4a98dab948 | ||
|  | 9f8c70b326 | ||
|  | a65404e63a | ||
|  | 05a1ddad05 | ||
|  | 4be3d63c0e | ||
|  | de6ce4a46e | ||
|  | 7a9e5afb93 | ||
|  | b2876b0a03 | ||
|  | b66f66fe6a | ||
|  | 30f04962d4 | ||
|  | 0feeb88024 | ||
|  | b799f2e05b | ||
|  | 56d21de001 | ||
|  | 7b54aa0c7d | ||
|  | 6e11b8ada1 | ||
|  | 98d25fc4e9 | ||
|  | 79405f47f6 | ||
|  | 1c7c4fc3b0 | ||
|  | 97e84d0977 | ||
|  | 9906b58818 | ||
|  | 371f084884 | ||
|  | 1c10839c14 | ||
|  | c55fdd9834 | ||
|  | 67b0890a6e | ||
|  | 4da4f96669 | ||
|  | 60a64c2558 | ||
|  | d4153da8b9 | ||
|  | fc33ab8905 | ||
|  | a123c64f59 | ||
|  | a090fe3834 | ||
|  | 8fa84de28e | ||
|  | 3e3da38de1 | ||
|  | a3be8ccc87 | ||
|  | cdfef30c22 | ||
|  | cabf1e82e8 | ||
|  | 608dc5e284 | ||
|  | 836d40072f | ||
|  | 431401d90e | ||
|  | 6da83e2bd7 | ||
|  | 7bccfc0006 | ||
|  | e051e09c1d | ||
|  | 1462c57d0c | ||
|  | 77c2b2b326 | ||
|  | 3cf9b9d9a5 | ||
|  | 629117e594 | ||
|  | 08f87c321f | ||
|  | 1ff13723fe | ||
|  | 510bda1b28 | ||
|  | 890327b381 | ||
|  | b21f7411dd | ||
|  | 5df623bd2e | ||
|  | 1e9d249f71 | ||
|  | a7b5949e6a | ||
|  | 02010170ce | ||
|  | 35998142fe | ||
|  | 75ea453bf4 | ||
|  | 33061aaa0d | ||
|  | e342311bef | ||
|  | 3d743a1ba1 | ||
|  | abca618008 | ||
|  | 0d2c3901a3 | ||
|  | d901a1531f | ||
|  | d8d56b195f | ||
|  | a52699717c | ||
|  | 98315de723 | ||
|  | 68d2f7d4c0 | ||
|  | c812b5ee09 | ||
|  | dcf487bdc1 | ||
|  | 547b1d3720 | ||
|  | 84f75f4156 | ||
|  | ff69da3fa2 | ||
|  | edffe92a24 | ||
|  | b6fe40ada4 | ||
|  | 837804b231 | ||
|  | 81deed143b | ||
|  | 900cdd3fa1 | ||
|  | 0018dc6ce7 | ||
|  | c92f914081 | ||
|  | 0498444ef2 | ||
|  | ce3c34e458 | ||
|  | 20401b99d8 | ||
|  | 397f98513b | ||
|  | e545ea9504 | ||
|  | b867d8f731 | ||
|  | 9a68864b67 | ||
|  | 72d7178762 | ||
|  | fbcd9a0c1d | ||
|  | c3144a20db | ||
|  | 5b56e0462d | ||
|  | b7fffbb6df | ||
|  | 1f346230e3 | ||
|  | a2860a7c8c | ||
|  | df997e5d3b | ||
|  | a67a82c921 | ||
|  | ea0fe8d3d2 | ||
|  | 2560042ac7 | ||
|  | 3d1d0696b9 | ||
|  | 83f893f50b | ||
|  | 9ecf95b075 | ||
|  | 7748c261da | ||
|  | a2db44f80c | ||
|  | b438d8aec0 | ||
|  | 4ac169b210 | ||
|  | 56dc6d7f1e | ||
|  | 45b8762188 | ||
|  | cafab98d10 | ||
|  | 9256f910f0 | ||
|  | 32068a832a | ||
|  | 47c2c0376a | ||
|  | f0dadc4a43 | ||
|  | 960b60cd2d | ||
|  | d6abd72e55 | ||
|  | 0a568f2530 | ||
|  | c52aa648c0 | ||
|  | 3d23b39f4c | ||
|  | f3a4048ebf | ||
|  | 1b07637cc4 | ||
|  | 68b75fd558 | ||
|  | 7c5ec1853d | ||
|  | e8f4686430 | ||
|  | 02348924d0 | ||
|  | 69dcb4dbda | ||
|  | c838821615 | ||
|  | 8b4ac7801f | ||
|  | 64a411628d | ||
|  | e8e25c6fd6 | ||
|  | 62485b6851 | ||
|  | 54025d2bf5 | ||
|  | f5ebf79e71 | ||
|  | 66d5490702 | ||
|  | 42fe052f9f | ||
|  | 58d9c46a9b | ||
|  | e4648e2138 | ||
|  | 110e047681 | ||
|  | 17d403d812 | ||
|  | 0a53bd4956 | ||
|  | e52d05c7db | ||
|  | b00db4f8a2 | ||
|  | 0c2f30fd45 | ||
|  | e08871c637 | ||
|  | ff715881bc | ||
|  | 0e2e5ffa52 | ||
|  | 8095c4c155 | ||
|  | e86246a985 | ||
|  | 625aaa02eb | ||
|  | 787e35c9f3 | ||
|  | 8887e6af91 | ||
|  | dde4c751da | ||
|  | 3c39baf1d6 | ||
|  | b292124f3c | ||
|  | c0035ba1a2 | ||
|  | 2491509c6a | ||
|  | 107935ed31 | ||
|  | 31491c62c5 | ||
|  | eacf8b896a | ||
|  | 7936fc5bd8 | ||
|  | adfaddbcf4 | ||
|  | 74db5c6be7 | ||
|  | f9399bcce7 | ||
|  | 87600b23db | ||
|  | cedfb17b18 | ||
|  | fa4c83df6b | ||
|  | 42c8720e8b | ||
|  | b334d89715 | ||
|  | 4f5d36a84d | ||
|  | 8f379e2262 | ||
|  | fa11a6e18b | ||
|  | 52bedce8f4 | ||
|  | 4c82af36e6 | ||
|  | dafa0d9138 | ||
|  | 2e0450d7ed | ||
|  | 6af3209d4d | ||
|  | 5d362047e2 | ||
|  | f48d6ca9f8 | ||
|  | 964e8e0a17 | ||
|  | 1f60a2d8b9 | ||
|  | 5fd83f2757 | ||
|  | c80df4140b | ||
|  | 53e1729e2f | ||
|  | ab2d1122a9 | ||
|  | 5190594c8a | ||
|  | c858ceeb58 | ||
|  | f0f52b9166 | ||
|  | 00c6f74481 | ||
|  | 2177ba0ed2 | ||
|  | 3483515346 | ||
|  | 75a06d2a40 | ||
|  | 53ac11983b | ||
|  | 69f4a4d4f8 | ||
|  | 222bcb808f | ||
|  | 686483f51a | ||
|  | 8df3da11e3 | ||
|  | 84dafda0e4 | ||
|  | b909facfe5 | ||
|  | 7780d94de1 | ||
|  | f2c440e466 | ||
|  | 4937e004b5 | ||
|  | 4cb383dccb | ||
|  | c8a4b6f23c | ||
|  | 857724c7e6 | ||
|  | a9b0400d13 | ||
|  | 2d1e5bbc7e | ||
|  | 60627ce756 | ||
|  | 7961a09d16 | ||
|  | 613efcacc7 | ||
|  | 7e8db16e18 | ||
|  | 1fbbed7e23 | ||
|  | 984272beb4 | ||
|  | b9ce94bb68 | ||
|  | f4c4ee78d9 | ||
|  | 793596614e | ||
|  | 136280100c | ||
|  | 29f1e4d2c9 | ||
|  | 72a7e61fd0 | ||
|  | 381cfca67f | ||
|  | f40620aa25 | ||
|  | 57a9fed42b | ||
|  | 18d820da94 | ||
|  | 26e66f046f | ||
|  | 4270c04856 | ||
|  | 74456d1135 | ||
|  | 62dc824bc0 | ||
|  | 1605791f1b | ||
|  | 37a46aa2cf | ||
|  | 1d2d217b94 | ||
|  | 23961f695d | ||
|  | 730b208617 | ||
|  | f09c04eeac | ||
|  | be73739c62 | ||
|  | eea3fb48a8 | ||
|  | b4fa72c058 | ||
|  | b0a865b0f1 | ||
|  | 7f49731618 | ||
|  | 3410aea788 | ||
|  | bc0a133bb1 | ||
|  | 7e287a5359 | ||
|  | 1110bd0851 | ||
|  | 1b576f826d | ||
|  | fe17566370 | ||
|  | e3c00669c1 | ||
|  | 33d17afc32 | ||
|  | 2388359a99 | ||
|  | 2df0c9503c | ||
|  | 61fa3bc77c | ||
|  | 03ac9b6956 | ||
|  | dfbef8495d | ||
|  | 7b17c49d8f | ||
|  | 4b3f31c2ee | ||
|  | 9ccc65bf8f | ||
|  | f9e22add03 | ||
|  | 846951cda7 | ||
|  | 97836e18b2 | ||
|  | 7b69df4db2 | ||
|  | 3767b4bbe7 | ||
|  | d7d2eefa4f | ||
|  | 6737f28d1e | ||
|  | 3da9404c2d | ||
|  | 4d5bd0fa32 | ||
|  | 1137da37c3 | ||
|  | 495a18805c | ||
|  | a226b82d0b | ||
|  | 0b5ddcdc9b | ||
|  | 82da8f4946 | ||
|  | 5ff481ce3c | ||
|  | f21dcaa6fb | ||
|  | 2c940de598 | ||
|  | ce75b776bb | ||
|  | 7d22b9b9f9 | ||
|  | 6cb8b3b5cd | ||
|  | 2bf4017f2b | ||
|  | 08d2f8568b | ||
|  | ac5f45d2d4 | ||
|  | 3cc7ad7d20 | ||
|  | d4513364fb | ||
|  | 9684f4e42a | ||
|  | f4186981fd | ||
|  | 141689e697 | ||
|  | 743c8b44a2 | ||
|  | 5e1459564a | ||
|  | 69a8813a3d | ||
|  | 17175df835 | ||
|  | 6b32535cb6 | ||
|  | 7f8fe75ab2 | ||
|  | 2815a14bb5 | ||
|  | f4dfa60790 | ||
|  | 35e88dd529 | ||
|  | 4d5094a517 | ||
|  | dd5abae721 | ||
|  | 8f2fb20934 | ||
|  | 44143f481a | ||
|  | 440abf4998 | ||
|  | 3c10427e04 | ||
|  | 74555a32ed | ||
|  | 85956b5828 | ||
|  | 41e40cad03 | ||
|  | df2d5c6585 | ||
|  | 1a111b706e | ||
|  | f696fce187 | ||
|  | 82d3d81bb2 | ||
|  | 4668932bac | ||
|  | e6c41eac93 | ||
|  | f0cff661df | ||
|  | 82d20dea39 | ||
|  | 804bb06859 | ||
|  | 5afa7e53f8 | ||
|  | 7f15b7b716 | ||
|  | 552e0c2248 | ||
|  | e5b9e1f5e7 | ||
|  | 502bf90007 | ||
|  | 40bf117497 | ||
|  | 4011dce31b | ||
|  | 9e881e32f8 | ||
|  | 14aad2358f | ||
|  | 637a8899c5 | ||
|  | cf0e395921 | ||
|  | 6ef438ce50 | ||
|  | 46e4b977a4 | ||
|  | 9626c5dead | ||
|  | aea364e43d | ||
|  | 06defd0cb0 | ||
|  | 0f80897c50 | ||
|  | 57bb1c2c0d | ||
|  | 7b35b414e8 | ||
|  | 761aac7a23 | ||
|  | 15a02d7664 | ||
|  | 16ed68c1ec | ||
|  | e63cf660c6 | ||
|  | aaff484306 | ||
|  | 3281d9a215 | ||
|  | 0fcd61e00f | ||
|  | c4523ea470 | ||
|  | 0447b3e4cc | ||
|  | 4d27c2901b | ||
|  | 855e18b31c | ||
|  | d790878af6 | ||
|  | 85b244df2f | ||
|  | 6070afa6b6 | ||
|  | 975594703d | ||
|  | 6b8c3ef614 | ||
|  | 9b22f05381 | ||
|  | ca3a990f9e | ||
|  | 557f4f689f | ||
|  | 66574d058a | ||
|  | 1c7c67060d | ||
|  | 9827ee97ad | ||
|  | 71a9a84211 | ||
|  | 367a2a4cee | ||
|  | 4f7465ba44 | ||
|  | f891fc698c | ||
|  | 36bec62c9a | ||
|  | dd5a2c8315 | ||
|  | 56bff46481 | ||
|  | b83a0adb19 | ||
|  | 92ffefe656 | ||
|  | 51b2e41879 | ||
|  | ef43bc9208 | ||
|  | 33733a4001 | ||
|  | e5a1b37981 | ||
|  | 30aa72dc8e | ||
|  | 2c2d474059 | ||
|  | c55ac0450f | ||
|  | 2d26b9c994 | ||
|  | f38fe092ee | ||
|  | 7a33eb163b | ||
|  | 5db0408b9f | ||
|  | 3557d38ce0 | ||
|  | 7de4e9e66a | ||
|  | 73838ccb8b | ||
|  | 0509de76d5 | ||
|  | f4b3d19059 | ||
|  | f37fb82d53 | ||
|  | dbe98f3fa5 | ||
|  | 371d4768e6 | ||
|  | 562d8386ec | ||
|  | 1625e4eb85 | ||
|  | 2365a076ac | ||
|  | 9898791771 | ||
|  | a1c658274d | ||
|  | be9998b48b | ||
|  | e8f308f654 | ||
|  | 07132a2c42 | ||
|  | 9c4582e283 | ||
|  | 0204002d9b | ||
|  | b3107cfad0 | ||
|  | 91ae68c07e | ||
|  | 06b3bf27b5 | ||
|  | fbef63e150 | ||
|  | bb8ee9bb3e | ||
|  | 25677a4126 | ||
|  | 3aeca0a770 | ||
|  | 4bd4733e52 | ||
|  | 9acec4d952 | ||
|  | 8388adcd1d | ||
|  | 5988ba76b5 | ||
|  | 1a06e7a16e | ||
|  | 7241cef7a5 | ||
|  | 5145296486 | ||
|  | 2cbf2d2226 | ||
|  | 754664aefa | ||
|  | af99173cd7 | ||
|  | fd1f30f92b | ||
|  | d9ab2f8b90 | ||
|  | bd6c60cf8a | ||
|  | f0c150d93b | ||
|  | c2986eaf47 | ||
|  | ef0c4797bb | ||
|  | ac02a99934 | ||
|  | fb67d1155f | ||
|  | eb46852bb9 | ||
|  | 007d8d2811 | ||
|  | ebe04fc114 | ||
|  | d7dd7f70c0 | ||
|  | f2cb89a128 | ||
|  | b8fade23de | ||
|  | 3b97a17648 | ||
|  | 0d06e3ff22 | ||
|  | c914f7bbcf | ||
|  | 1b451180c1 | ||
|  | ed061b362b | ||
|  | e1026584c8 | ||
|  | 4c615e4fac | ||
|  | 7c9d48833b | ||
|  | b60b195aec | ||
|  | db76c8d7f4 | ||
|  | de92740e87 | ||
|  | 522bf91c30 | ||
|  | 48d3abc1fe | ||
|  | 3f6f25e06f | ||
|  | 34ba07ee3b | ||
|  | ac37319d20 | ||
|  | b2c6274f74 | ||
|  | 402884b5ce | ||
|  | 23c99002c0 | ||
|  | ee115b3337 | ||
|  | 82f5a141ed | ||
|  | 0567168ea9 | ||
|  | c80a15846d | ||
|  | 5e194536a8 | ||
|  | 43c5ab8ecc | ||
|  | cd295228ef | ||
|  | 6c42221620 | ||
|  | 0d73a7cd07 | ||
|  | 39d5b7edb0 | ||
|  | 6fa50a699f | ||
|  | ddaef3e5d5 | ||
|  | c3e9d4a9f8 | ||
|  | 7530fb67c8 | ||
|  | 19bb56df47 | ||
|  | b0073ac933 | ||
|  | 137a89da15 | ||
|  | 44da7a302f | ||
|  | 4096aae8d4 | ||
|  | d3e026d82a | ||
|  | fa5ecd6495 | ||
|  | af209ad50e | ||
|  | 7b89228fa7 | ||
|  | d31a88206c | ||
|  | cd4ed8765b | ||
|  | b6f780d70d | ||
|  | b071a58ca7 | ||
|  | ce554f7718 | ||
|  | 99b1cec2e1 | ||
|  | 46911a8905 | ||
|  | 4eb61529f6 | ||
|  | 81abf29bec | ||
|  | 85897ef8cd | ||
|  | b824c0b125 | ||
|  | 6367c6d116 | ||
|  | a7736d88a9 | ||
|  | 049dbf5a78 | ||
|  | 4ac92caeb5 | ||
|  | 7af3da2a97 | ||
|  | 95a62fcdd1 | ||
|  | 7872d20554 | ||
|  | a598eb7e98 | ||
|  | c786acc39b | ||
|  | 07d8052a57 | ||
|  | db9edb477e | ||
|  | 9bd3a6758a | ||
|  | 2cb1560bbd | ||
|  | 006059438f | ||
|  | 84ea3b9788 | ||
|  | b667abde10 | ||
|  | aa10997171 | ||
|  | 7880ac1909 | ||
|  | f53848b4b9 | ||
|  | 82f2f38680 | ||
|  | dcc2549574 | ||
|  | cfe4753913 | ||
|  | fcb1a7e4d4 | ||
|  | ce76a7dfa5 | ||
|  | 7c1de81861 | ||
|  | eddad20acc | ||
|  | 7daad57862 | ||
|  | 1468049fe9 | ||
|  | 3b91e59a79 | ||
|  | 3496a30528 | ||
|  | 32bad5df15 | ||
|  | 3f58eca1be | ||
|  | 2350843d1d | ||
|  | a2588a178c | ||
|  | e5292696c4 | ||
|  | 34b2a65ccb | ||
|  | 3aa3659bc7 | ||
|  | b8117394c0 | ||
|  | fd2bbd2b59 | ||
|  | 127c470746 | ||
|  | f2844bdf1a | ||
|  | c5bfef4264 | ||
|  | 73863acc12 | ||
|  | 19e99204b9 | ||
|  | 13f5b94c3e | ||
|  | 3a2498401d | ||
|  | 53b20ba625 | ||
|  | e7f6f0950f | ||
|  | 9fbe1b38a5 | ||
|  | 078485134d | ||
|  | 67b1766e32 | ||
|  | d4b69ac79c | ||
|  | e61a2d7083 | ||
|  | c03f6604af | ||
|  | 572bb38ddb | ||
|  | 42c5c0cb9f | ||
|  | e145d2255e | ||
|  | 442fa07dd4 | ||
|  | 31ae9e1243 | ||
|  | d7f83f8df2 | ||
|  | 29e2d4e0c8 | ||
|  | 2732d2c844 | ||
|  | c4a037b277 | ||
|  | 0e614ad6fc | ||
|  | ca1a8cd617 | ||
|  | ba96a637be | ||
|  | c2cac772e3 | ||
|  | 6b7216f4ec | ||
|  | e4fb5946dd | ||
|  | ca61248861 | ||
|  | 68d7b4649e | ||
|  | 0416aacbbd | ||
|  | bc731e6f8e | ||
|  | ae5d7705bb | ||
|  | b9bd541532 | ||
|  | 83639c2535 | ||
|  | 25d80f4df1 | ||
|  | 74f918d911 | ||
|  | a20efa56eb | ||
|  | f4d83075be | ||
|  | 254592c383 | ||
|  | ee23ac0537 | ||
|  | a48cf0bb24 | ||
|  | dae59238cd | ||
|  | 8736da1a21 | ||
|  | 09a1de69e7 | ||
|  | 63d67bc6cb | ||
|  | 7099245204 | ||
|  | 4d097d2139 | ||
|  | 6485bf9ad9 | ||
|  | b7c5b1bfc7 | ||
|  | 2b7546e827 | ||
|  | 3549ccf4b3 | ||
|  | e2f5752d9a | ||
|  | 1a59019fc8 | ||
|  | 7bac7bdc3e | ||
|  | 19fe58dbac | ||
|  | 0a5b30e21c | ||
|  | 664818fd29 | ||
|  | d5214e2505 | ||
|  | d906fcea0e | ||
|  | 29c8e8b740 | ||
|  | 71fec4c555 | ||
|  | 5ee36c897d | ||
|  | 4aba0c7405 | ||
|  | ed7479c854 | ||
|  | 8d3d5f726a | ||
|  | a9a7068818 | ||
|  | 1bde7c7718 | ||
|  | 17068130bb | ||
|  | 81a91d62cb | ||
|  | 2575263438 | ||
|  | 7f0e25cb50 | ||
|  | a1e4e9c50f | ||
|  | 98eff2701b | ||
|  | 8b84f87217 | ||
|  | 306a1b7bc2 | ||
|  | 481214c46e | ||
|  | a5961cbeab | ||
|  | 3bf335e0a0 | ||
|  | 68f696d165 | ||
|  | 1170aed026 | ||
|  | bf1b2066b6 | ||
|  | 4c080afb76 | ||
|  | ee1c43ca91 | ||
|  | 1c2e6f9e4c | ||
|  | dd379430d9 | ||
|  | 42033ebd35 | ||
|  | a086d6e009 | ||
|  | c70bbdab26 | ||
|  | 3d956ef554 | ||
|  | 329f491c30 | ||
|  | e93701f50e | ||
|  | e680de05ea | ||
|  | 56fec674c5 | ||
|  | 54d92a027a | ||
|  | 319ac3a641 | ||
|  | 0a03c46351 | ||
|  | ae1b62e147 | ||
|  | 8d567f6b06 | ||
|  | b1ef09675b | ||
|  | 2b7b925090 | ||
|  | e0454e95db | ||
|  | 91e421d961 | ||
|  | c853afe769 | ||
|  | 1a64cb38d5 | ||
|  | ccebd22856 | ||
|  | a1f3b82333 | ||
|  | 3dda29781e | ||
|  | a9d297ee31 | ||
|  | e5ff61f201 | ||
|  | d116eb7655 | ||
|  | bc726c6334 | ||
|  | 123473dfc8 | ||
|  | d9eccd4fba | ||
|  | 5b890847e5 | ||
|  | 64c85b9617 | ||
|  | 3e3b0bcd8b | ||
|  | 4c1eb1b12a | ||
|  | 530d03d284 | ||
|  | 619fa9b65e | ||
|  | 0032235933 | ||
|  | 61d1f1ea87 | ||
|  | 238d27acdc | ||
|  | 2f62271453 | ||
|  | 75d5117a2d | ||
|  | b4700af2f5 | ||
|  | 374e2b311d | ||
|  | 49036abbaf | ||
|  | 38ccbac97c | ||
|  | 6b4896b8f5 | ||
|  | d582d1cc42 | ||
|  | 9e2b8a2aa9 | ||
|  | 6fdc733941 | ||
|  | 422b390c48 | ||
|  | 67a9d1285c | ||
|  | 8e26e38ecc | ||
|  | 02e12d8575 | ||
|  | fe2954ce08 | ||
|  | 1fe4439395 | ||
|  | 2ff04d2abd | ||
|  | 3f30d3aa89 | ||
|  | 129e17b33a | ||
|  | bf2d8c3f4b | ||
|  | b29f04ce01 | ||
|  | d185ebad48 | ||
|  | 605df7c91c | ||
|  | ec60cad8bb | ||
|  | 6aa0f5a392 | ||
|  | 4cae2c56ec | ||
|  | d840975054 | ||
|  | 1b14da6c03 | ||
|  | 292640b17a | ||
|  | 112a7b09f2 | ||
|  | 863ec9ce8a | ||
|  | 2eb346a205 | ||
|  | 8092355acb | ||
|  | e7ef2ed31b | ||
|  | af4de6d2fc | ||
|  | 69f73dd779 | ||
|  | 9706b46012 | ||
|  | 6d75dd3bb8 | ||
|  | bd295ffc99 | ||
|  | 07ce3e3c9d | ||
|  | cbc3e37a89 | ||
|  | 3626828ceb | ||
|  | 24b77fb5a5 | ||
|  | 1505fe686a | ||
|  | 0991131fa8 | ||
|  | 2e928bd3c2 | ||
|  | ca868ae19e | ||
|  | 3e286dd14c | ||
|  | 11247d52b1 | ||
|  | 1dbc902513 | ||
|  | 330e691b78 | ||
|  | 6780d4f562 | ||
|  | b30b8b7368 | ||
|  | 3df182b8c3 | ||
|  | 7f21d89fea | ||
|  | 2b267b4ba1 | ||
|  | ef64881528 | ||
|  | 9a6bd760bd | ||
|  | 00b9766aea | ||
|  | 6381d2b6ac | ||
|  | d2ab5f230d | ||
|  | 824b41d457 | ||
|  | b5523c7077 | ||
|  | eb3594b18c | ||
|  | 852d85d010 | ||
|  | 5e0aef04fe | ||
|  | a00c693f93 | ||
|  | c943da1448 | ||
|  | b630fae580 | ||
|  | 38e40084f1 | ||
|  | bf23ad78e6 | ||
|  | ded1d19737 | ||
|  | 496a3b0d2c | ||
|  | 6922333755 | ||
|  | a00c39e9cf | ||
|  | 1c1da8e38e | ||
|  | 50a306f492 | ||
|  | 6995ee2d17 | ||
|  | 6c60ea9cac | ||
|  | 2431ed811a | ||
|  | 6bd205c02a | ||
|  | 62ec77e148 | ||
|  | 9120e1de88 | ||
|  | 60e169bd87 | ||
|  | e4bca5fe47 | ||
|  | a1729b65ab | ||
|  | 2950d26c8e | ||
|  | 4f8d4a9585 | ||
|  | d787795759 | ||
|  | cf74e73e27 | ||
|  | 2770254fd9 | ||
|  | de04bd8cfa | ||
|  | 076a547f91 | ||
|  | dffd0a2706 | ||
|  | 6c66f86103 | ||
|  | 26502c949a | ||
|  | 8dfe510883 | ||
|  | 96ba9f5902 | ||
|  | 3a6ba0ab71 | ||
|  | 32d894d6b6 | ||
|  | 543efa4299 | ||
|  | eba0708099 | ||
|  | 51e6bf0d45 | ||
|  | 07b5c44a54 | ||
|  | 9fe32c1c34 | ||
|  | 0e0278c84a | ||
|  | dea775a9cd | ||
|  | 7e3e18a5c7 | ||
|  | 8e3ebc84f0 | ||
|  | e6079dfd71 | ||
|  | 2b435fe6a5 | ||
|  | 4e640b11fd | ||
|  | 8b1e1e68fa | ||
|  | fd11927708 | ||
|  | cd500fee8c | ||
|  | 1bd32c0f19 | ||
|  | 7aefca3de0 | ||
|  | f275ed96ea | ||
|  | d14dac3872 | ||
|  | b0213b0565 | ||
|  | c677f0a875 | ||
|  | 6e65cb2c0a | ||
|  | e65c5402d7 | ||
|  | 334f86480a | ||
|  | 0e62f5b759 | ||
|  | edf9a500d3 | ||
|  | 001d01fdaf | ||
|  | a95677564e | ||
|  | 4aca8bb8df | ||
|  | 5540482888 | ||
|  | 00d735249b | ||
|  | b5289511ba | ||
|  | b6ded8501f | ||
|  | 781915d2cf | ||
|  | f4cef3eaf2 | ||
|  | d23c2eed86 | ||
|  | 15695a304e | ||
|  | 6319269976 | ||
|  | 0ed3d951a7 | ||
|  | 2aa39757b4 | ||
|  | 39d32a3600 | ||
|  | 219d17de34 | ||
|  | 9bb5b454e4 | ||
|  | 2412f8c531 | ||
|  | 8701d684e6 | ||
|  | b543cc34cd | ||
|  | 791dbbab9b | ||
|  | ac0b1da3fc | ||
|  | 2f97aedc3c | ||
|  | ab544ee965 | ||
|  | fa527f8624 | ||
|  | 92ee0aefee | ||
|  | 99759ae853 | ||
|  | 81930312ff | ||
|  | 194fbcdd91 | ||
|  | 1e3930aae2 | ||
|  | 62dda4d891 | ||
|  | 2b870fb9f7 | ||
|  | 53f0318187 | ||
|  | 5e6e711f33 | ||
|  | 78af2cd4dc | ||
|  | 02cb237623 | ||
|  | cc0f19653e | ||
|  | 4fff150c7b | ||
|  | f6136891cc | ||
|  | 1e22170302 | ||
|  | bdda6f502a | ||
|  | 1bbd77fddb | ||
|  | 321fdd10d1 | ||
|  | 9867dfcdeb | ||
|  | 7c09ac632c | ||
|  | 3502f65332 | ||
|  | 628390c3b5 | ||
|  | bc37097df2 | ||
|  | 7d98275763 | ||
|  | d6ffb549f6 | ||
|  | bcd0db984d | ||
|  | d9244f22c2 | ||
|  | c97d76dbf2 | ||
|  | 9e05e97d7f | ||
|  | 1070dedd7c | ||
|  | ccd1516637 | ||
|  | f1f51a01c6 | ||
|  | be75b8dbe5 | ||
|  | 02fae0e722 | ||
|  | e35b739579 | ||
|  | 34aa6cc8a2 | ||
|  | d7a6b20028 | ||
|  | eb2d5bb1f8 | ||
|  | cefef3d1be | ||
|  | cc96ab7a9b | ||
|  | 49ea31c0a4 | ||
|  | f1478d776b | ||
|  | 40e4cfb686 | ||
|  | 76f459ee95 | ||
|  | c478718019 | ||
|  | c27248a58b | ||
|  | 51bc539468 | ||
|  | 2395863e7e | ||
|  | 69c459c8ac | ||
|  | c8855b2b10 | ||
|  | a910c0fddb | ||
|  | fd55611cac | ||
|  | 52f6be2bb0 | ||
|  | 857f930dc2 | ||
|  | dd2c436dc6 | ||
|  | 9f047ba752 | ||
|  | 9d4ec4a9b2 | ||
|  | cdc6d9aa65 | ||
|  | 997bc21feb | ||
|  | 975af4764d | ||
|  | bf69219f98 | ||
|  | f34f9329f1 | ||
|  | 90271d0dcd | ||
|  | 195cd7597d | ||
|  | 4a81406262 | ||
|  | f9fd426843 | ||
|  | e612056ecd | ||
|  | 6f0103398b | ||
|  | afb60db382 | ||
|  | 5731b876ff | ||
|  | 055f917a2e | ||
|  | 4ed7fb771c | ||
|  | c328e9018c | ||
|  | b270f6f713 | ||
|  | 5c13918f11 | ||
|  | 40cc216557 | ||
|  | 1481f92cb0 | ||
|  | 76d54fbe5c | ||
|  | 9f72779cdc | ||
|  | 3dcef89a74 | ||
|  | 46373717b6 | ||
|  | 7277c08fa6 | ||
|  | 04e75455c4 | ||
|  | 8ac17ae14e | ||
|  | cb5d6ddf80 | ||
|  | e0794db33a | ||
|  | b128b79132 | ||
|  | 79e6d4b8dd | ||
|  | b9ddde0f12 | ||
|  | a0ec37b35b | ||
|  | 506ac8014c | ||
|  | 72b4198301 | ||
|  | 24eee0cb34 | ||
|  | 9fc0c3f849 | ||
|  | db314ed903 | ||
|  | 1ef9b8be61 | ||
|  | 79782ad547 | ||
|  | 4b6d045df1 | ||
|  | b4d1d545a8 | ||
|  | f61682cdc7 | ||
|  | d61420f1c6 | ||
|  | 3d09d605e1 | ||
|  | 025dde264a | ||
|  | 87cee7a0fd | ||
|  | 61784a03bb | ||
|  | 9d9ca0f08d | ||
|  | 58f37513e7 | ||
|  | ee7f9d457d | ||
|  | bec2224c3d | ||
|  | 4305984168 | ||
|  | 07dd64958f | ||
|  | 76101d7f8d | ||
|  | 7d6a0ab256 | ||
|  | 4309a0dc68 | ||
|  | dde6919446 | ||
|  | 54fc9c91ac | ||
|  | 41658c97a3 | ||
|  | 45c9cc97d9 | ||
|  | 6fa7debee5 | ||
|  | ee9f662016 | ||
|  | 3550e1214c | ||
|  | 8dcb43ad1c | ||
|  | e6a1442296 | ||
|  | cb65480c6c | ||
|  | 3e7c7ab497 | ||
|  | f0930d8a18 | ||
|  | 5a846bdeb5 | ||
|  | baf9dfb46c | ||
|  | edd3a22848 | ||
|  | 583428b19c | ||
|  | 08d44ae553 | ||
|  | b3b2541c1e | ||
|  | 8e927e0b73 | ||
|  | 8e3e996f4a | ||
|  | b6fa361bcc | ||
|  | ca83092aed | ||
|  | 3cda92331e | ||
|  | c989abe265 | ||
|  | 89230ade7a | ||
|  | b4931c9a1f | ||
|  | ddfcf45d40 | ||
|  | ee12236d53 | ||
|  | df6698c98f | ||
|  | c3b82f2cfa | ||
|  | 64c89f1c8f | ||
|  | e09b65ea94 | ||
|  | c81952c356 | ||
|  | f80e462d25 | ||
|  | 51f32677b7 | ||
|  | 4b366358c4 | ||
|  | 3378586098 | ||
|  | 6777d952c1 | ||
|  | 6c8b18ddbd | ||
|  | 69780ecde9 | ||
|  | 9e2c52e1ec | ||
|  | 6cb0e6a936 | ||
|  | dd82e550d5 | ||
|  | cdcda27d07 | ||
|  | ffffcdd50a | ||
|  | d37d62574c | ||
|  | f2380457d6 | ||
|  | efa42d5d96 | ||
|  | e17c18b653 | ||
|  | 7607d3d64a | ||
|  | d7d7147d43 | ||
|  | b40e1eabb9 | ||
|  | 3b8e18004c | ||
|  | 4c03950c28 | ||
|  | 170a0183f8 | ||
|  | c62ff16f8b | ||
|  | ab495fe6e1 | ||
|  | c2a8dc23d0 | ||
|  | 6734ae3c88 | ||
|  | 4c1c595f14 | ||
|  | 9002c67639 | ||
|  | b91aabd3c0 | ||
|  | 3307f673f6 | ||
|  | 07b00bec61 | ||
|  | e0d2b60d8b | ||
|  | 45bfecee73 | ||
|  | 80e3a11268 | ||
|  | 38a6c6a866 | ||
|  | 8f224afed9 | ||
|  | 48a4c46a6c | ||
|  | 7d08380c7f | ||
|  | b3b3cf3807 | ||
|  | f0f6150e18 | ||
|  | dc600cc3ed | ||
|  | ae648b8a0a | ||
|  | 583af3bd4f | ||
|  | d65cfbf093 | ||
|  | 118aed2e31 | ||
|  | 85abf4d123 | ||
|  | 44b8291540 | ||
|  | d6444bba66 | ||
|  | 5a2f8fdfe1 | ||
|  | bba4f84503 | ||
|  | 684e081399 | ||
|  | 96c700ee46 | ||
|  | 5f15794c3b | ||
|  | a40b3134f4 | ||
|  | c70b4daf87 | ||
|  | 928611eb20 | ||
|  | f1d55c688a | ||
|  | d22df22f7d | ||
|  | 061e1be0a4 | ||
|  | 950bc4b937 | ||
|  | dcb81e6bea | ||
|  | daaa83ee7d | ||
|  | b7c1450121 | ||
|  | 787f52d1f8 | ||
|  | 50213f146a | ||
|  | 7f2aea60c9 | ||
|  | 168621f7c2 | ||
|  | 8b630798d8 | ||
|  | 52e8a44517 | ||
|  | 59f33658ad | ||
|  | e0315bffdc | ||
|  | cd28d0c0e0 | ||
|  | 0baa2c8b23 | ||
|  | 4977d1fbd5 | ||
|  | 3b7a92f1b4 | ||
|  | f6920172dd | ||
|  | 93bfc8f5f4 | ||
|  | 39b7655264 | ||
|  | 8b75ceb412 | ||
|  | c39fc4010d | ||
|  | 8df778a515 | ||
|  | 5134ea76bf | ||
|  | 3ba37df29d | ||
|  | e221d674d9 | ||
|  | 251f947293 | ||
|  | 41e1e1cbb0 | ||
|  | da1bc351d2 | ||
|  | 43c0afdea0 | ||
|  | add5bfa2ec | ||
|  | 34babfb5de | ||
|  | 4f6c45c86c | ||
|  | e6220a464c | ||
|  | 8dcd49934a | ||
|  | bedc3bdb56 | ||
|  | 83ceb0fde9 | ||
|  | 1d299c56e0 | ||
|  | 0d735c2ccc | ||
|  | 4094f89d4a | ||
|  | cf1e8b194a | ||
|  | 74e5644f55 | ||
|  | b5dc5fc615 | ||
|  | 7a7270d769 | ||
|  | 7549ddcd2b | ||
|  | 08f0303178 | ||
|  | 0d7a291b81 | ||
|  | 2265ae9600 | ||
|  | cba502e87a | ||
|  | ac94236614 | ||
|  | ddf1be2a13 | ||
|  | b7694686c2 | ||
|  | 63332c0530 | ||
|  | 8a504f8eee | ||
|  | 106fc5daa4 | ||
|  | 7accb73993 | ||
|  | e9aa6a0956 | ||
|  | df20467e03 | ||
|  | ecbd9d739e | ||
|  | 8af17c295a | ||
|  | 329b28cad1 | ||
|  | 452c29574d | ||
|  | 5bedc1b333 | ||
|  | 0bf6d2f72c | ||
|  | c09b8af491 | ||
|  | 260bcd3a55 | ||
|  | 6b5211ad12 | ||
|  | a92ec14989 | ||
|  | b3348eb22b | ||
|  | bec5a261e5 | ||
|  | 4b53641e1d | ||
|  | 00071d53d5 | ||
|  | 6902834568 | ||
|  | fa2d87f3dd | ||
|  | 44019d1a61 | ||
|  | 6f74fb49bd | ||
|  | a303b39cf0 | ||
|  | 3e63a29c59 | ||
|  | 261c0fc9b6 | ||
|  | 895b30f7e5 | ||
|  | b985604e22 | ||
|  | f7953e4ef3 | ||
|  | 63483d1f0e | ||
|  | 8b981f03bf | ||
|  | d0d0910bf2 | ||
|  | 57ac820767 | ||
|  | b8bda867b6 | ||
|  | 05d3a2450c | ||
|  | d40788adfa | ||
|  | 83fbf86b1c | ||
|  | e876008427 | ||
|  | 2b43353eb4 | ||
|  | a74403c347 | ||
|  | 2f4c6c8697 | ||
|  | 238d8197f5 | ||
|  | 53a600d87b | ||
|  | 2a0ffaf45d | ||
|  | 936b046ed9 | ||
|  | 378dcfe351 | ||
|  | 0a330b9288 | ||
|  | a88b40d6c1 | ||
|  | 09f25ffbd9 | ||
|  | ab1232d742 | ||
|  | a7f56fe0fc | ||
|  | 58a9452c36 | ||
|  | 6d8c4f403f | ||
|  | 88b80fed90 | ||
|  | acdbd0c391 | ||
|  | d9a8cfed8c | ||
|  | 122796fbba | ||
|  | 510ca042c9 | ||
|  | 125f6205f2 | ||
|  | 8136f3df5c | ||
|  | 38d06a7e94 | ||
|  | 49db10539a | ||
|  | 8efe4c6267 | ||
|  | 04d8bb8fbf | ||
|  | 08aa13c90c | ||
|  | d1febc0208 | ||
|  | 5980e58ac6 | ||
|  | e1dc283d4b | ||
|  | 8be234973c | ||
|  | 7def8ff2cd | ||
|  | 340b1c2e42 | ||
|  | 7e0f7ba438 | ||
|  | fefd9b52a8 | ||
|  | afd155ac4f | ||
|  | ee724eb4f1 | ||
|  | 2f1f20ea11 | ||
|  | 063bcf17d8 | ||
|  | 72509eef44 | ||
|  | 2da28864e9 | ||
|  | 4278f64682 | ||
|  | 59ae3c3fcd | ||
|  | 7fa21fbdff | ||
|  | e95af7498e | ||
|  | 79c75adac1 | ||
|  | d212f69d89 | ||
|  | edf5e69d39 | ||
|  | 574eb0d174 | ||
|  | 8bd4914e2f | ||
|  | 5ebaaff64b | ||
|  | 5c9e0c9f51 | ||
|  | 8132edbb08 | ||
|  | d29ce78c86 | ||
|  | 94bc9d7a69 | ||
|  | e8faec0932 | ||
|  | 69ca4fe304 | ||
|  | cd99fe46fd | ||
|  | 4825b4dc68 | ||
|  | 8d0607ef58 | ||
|  | 225295a7d8 | ||
|  | 4cd74daf53 | ||
|  | 6eb9118197 | ||
|  | d0bd2f522c | ||
|  | 661c757236 | ||
|  | aaa20093ef | ||
|  | 1eecdd6fa3 | ||
|  | 800b5b2a43 | ||
|  | 9d17421c66 | ||
|  | 0edd50e956 | ||
|  | 288d4f08b3 | ||
|  | 526e4b8bdc | ||
|  | e0c5ccc16b | ||
|  | ebc2c614d7 | ||
|  | 29f5a85158 | ||
|  | 8af2380a47 | ||
|  | 431f2a2088 | ||
|  | e05ea887f6 | ||
|  | 95c0425151 | ||
|  | 47cbc7b1f9 | ||
|  | e7b75d591c | ||
|  | 99f7d469f4 | ||
|  | 8a6ef17fbf | ||
|  | 5f337a0bd9 | ||
|  | 87862f772a | ||
|  | 3ab641aa21 | ||
|  | 3efa8da8e0 | ||
|  | 3e28ed4fe4 | ||
|  | 44949460ed | ||
|  | 83cc19ad6f | ||
|  | 66bb98c479 | ||
|  | ff3f985658 | ||
|  | 2ba6c9ccbe | ||
|  | 3eaf111e7d | ||
|  | 30da26b9a9 | ||
|  | e35ad0cc8f | ||
|  | 1a36302cf1 | ||
|  | 82a28bb555 | ||
|  | c1ce0be451 | ||
|  | c0a5f8fef0 | ||
|  | 702cf304d0 | ||
|  | 4dee8b6048 | ||
|  | ec665e0cc1 | ||
|  | aec3b82476 | ||
|  | e83796b5b9 | ||
|  | 8eb69d6eda | ||
|  | 74b5124a42 | ||
|  | b9706a180b | ||
|  | 8aeb8a9bb7 | ||
|  | 8f2e166a22 | ||
|  | fdd91170dc | ||
|  | c40ddb061b | ||
|  | 353d6cfc55 | ||
|  | f37564c49c | ||
|  | 157484d94b | ||
|  | 7626c9fff7 | ||
|  | 1f55f9fc49 | ||
|  | 2554bc7ef8 | ||
|  | 7cb4100419 | ||
|  | 2d3b7eb878 | ||
|  | 4d01a78731 | ||
|  | a03e36828a | ||
|  | 260fb65b06 | ||
|  | 9fb8526136 | ||
|  | 26fc5ff5e2 | ||
|  | 5060f0bb19 | ||
|  | beaf6d449b | ||
|  | 4d68b508a2 | ||
|  | cd825e386d | ||
|  | 095c8b2309 | ||
|  | 8b6eb74c58 | ||
|  | aba437e5a2 | ||
|  | efe3ed499b | ||
|  | 5595564a1f | ||
|  | 439761cb67 | ||
|  | bee6c65293 | ||
|  | 10145b946b | ||
|  | ebf4b50059 | ||
|  | 07cce3b3fc | ||
|  | f2c19afd95 | ||
|  | d159e70e1c | ||
|  | ac693a2541 | ||
|  | 1e988116ce | ||
|  | ec9e722927 | ||
|  | 4cd5e8c378 | ||
|  | b759d5e06a | ||
|  | 1469033c1e | ||
|  | c15fd75df7 | ||
|  | 73524e01a6 | ||
|  | 9e54e11113 | ||
|  | 01ac5f29db | ||
|  | 67a2241e32 | ||
|  | 72b6dc3de7 | ||
|  | 6f5b645995 | ||
|  | 458ad1de57 | ||
|  | 216f48b7c1 | ||
|  | b2d1757e5a | ||
|  | 6e53eb9d5c | ||
|  | e5ee5be9c5 | ||
|  | bd237b2b95 | ||
|  | d31cf766eb | ||
|  | 56d530ff04 | ||
|  | 0bbb2240f2 | ||
|  | 1c8e4dba73 | ||
|  | 4a9956c4a4 | ||
|  | 59c0e6ae32 | ||
|  | 94c30fc21e | ||
|  | 8bb3b3be20 | ||
|  | 85e3c2c5a2 | ||
|  | 4be381c597 | ||
|  | 6ff5470cf1 | ||
|  | 151dcfdef9 | ||
|  | c282b4cb9f | ||
|  | c426f4626c | ||
|  | 0e3c92626e | ||
|  | 5099525e24 | ||
|  | e22b4cbb67 | ||
|  | 2b48828179 | ||
|  | 3e181362dd | ||
|  | 71fd98e39e | ||
|  | 71cd8b6d51 | ||
|  | ad75fcbf7e | ||
|  | f8b04a6357 | ||
|  | d8fcbb78d3 | ||
|  | 8408bf3789 | ||
|  | 3e1185658e | ||
|  | d778cdcd61 | ||
|  | 90b303fc03 | ||
|  | eb86b1270d | ||
|  | a1f0cc878b | ||
|  | f2e2720b15 | ||
|  | ec8cfe1591 | ||
|  | 22eac159e5 | ||
|  | 956b0c3fa7 | ||
|  | a6427e0949 | ||
|  | 22031f39b0 | ||
|  | c4673d3a67 | ||
|  | e83e021541 | ||
|  | c1f2ecd413 | ||
|  | 46fbe01df9 | ||
|  | 8647a8290e | ||
|  | bac51f4b31 | ||
|  | 582aab180a | ||
|  | 5fb714fcb2 | ||
|  | 3994de77d0 | ||
|  | 24c8d1f1f4 | ||
|  | 110f877dcc | ||
|  | 9cd3a9f8e8 | ||
|  | 1464050bf5 | ||
|  | 95e9e1b550 | ||
|  | bda1c1c1eb | ||
|  | d020a7974a | ||
|  | a51fad3aab | ||
|  | 3cd32778bb | ||
|  | 8d67056f84 | ||
|  | e986973b5e | ||
|  | 448c934cba | ||
|  | 96ef7ba55d | ||
|  | 4372de1e7e | ||
|  | af0fb88adf | ||
|  | 066233eee8 | ||
|  | b6f85d10b0 | ||
|  | 6f75413c09 | ||
|  | d45fe4ce74 | ||
|  | e828c013e6 | ||
|  | 988459f744 | ||
|  | 7c701bdf3f | ||
|  | 446fc35d5c | ||
|  | bec9cc7047 | ||
|  | 961380acb6 | ||
|  | 84c0685a60 | ||
|  | 629222f103 | ||
|  | 8c448e5bc2 | ||
|  | b5fa6c2d0a | ||
|  | 680b2df08a | ||
|  | 09bd47f98b | ||
|  | 7f69f9ce4f | ||
|  | 4179b4e543 | ||
|  | 66364554c4 | ||
|  | 43f2448789 | ||
|  | 130cee1e70 | ||
|  | b976360248 | ||
|  | 225bfc4164 | ||
|  | d7ceda4d82 | ||
|  | 14d091e60a | ||
|  | 2809668ef4 | ||
|  | bafb86e00b | ||
|  | f5db31b8ff | ||
|  | e1d0dbed0c | ||
|  | 1d1fe364d0 | ||
|  | 2b9316c4ff | ||
|  | c50cbbb526 | ||
|  | b93d9ecd7e | ||
|  | 96243db88b | ||
|  | 4daf75a8cc | ||
|  | 8c63d7cf5b | ||
|  | 6f78a32e64 | ||
|  | af6731c9c8 | ||
|  | 25cf0d2b94 | ||
|  | 9389791d91 | ||
|  | aa8191d0a1 | ||
|  | 0d5c78e875 | ||
|  | e8679ae03b | ||
|  | d1d224b7fc | ||
|  | df995f7bc9 | ||
|  | af39502450 | ||
|  | ffa38955d6 | ||
|  | 8d82fb6d8f | ||
|  | 306770331a | ||
|  | d3f433c8cf | ||
|  | cf49cbd1f8 | ||
|  | 8a99e75299 | ||
|  | 2dbf849c82 | ||
|  | ba3dce0b4c | ||
|  | ca9588380a | ||
|  | ae2619602d | ||
|  | de06353194 | ||
|  | 3ff3f5e1cc | ||
|  | 4b747859b3 | ||
|  | 2201765366 | ||
|  | dfa1d5e398 | ||
|  | ce9a90f626 | ||
|  | 2deb18beb2 | ||
|  | 0f7454059c | ||
|  | f9ba09ac4d | ||
|  | 4e74873eae | ||
|  | f0cd03d14f | ||
|  | f2b069c562 | ||
|  | bc89306dc1 | ||
|  | bf4da1655b | ||
|  | d819aa270f | ||
|  | e6d945f835 | ||
|  | 4fe408f1fd | ||
|  | c376e42092 | ||
|  | 63a653cdf0 | ||
|  | 5d900800f2 | ||
|  | def06dbc0b | ||
|  | 9b66a597bb | ||
|  | f1ee3b4e60 | ||
|  | 6395e39d63 | ||
|  | 2a6d9d7e31 | ||
|  | 32a7cd31da | ||
|  | dd4a56cb5f | ||
|  | d110d1cb5f | ||
|  | 48858019b7 | ||
|  | aff6b1fca5 | ||
|  | d260182ef3 | ||
|  | e39a38b0d9 | ||
|  | 82d7179c92 | ||
|  | f42746ba06 | ||
|  | 1f69deaccd | ||
|  | ea8b7ab193 | ||
|  | 9938959026 | ||
|  | d5e5485d2e | ||
|  | 97b9c8f320 | ||
|  | 35aebbc209 | ||
|  | 81f7419f70 | ||
|  | 2f951bd54d | ||
|  | 18f5963b09 | ||
|  | 836509c1d1 | ||
|  | 949d536e42 | ||
|  | f69b17e165 | ||
|  | 49a0584c54 | ||
|  | e21aa2c8f0 | ||
|  | 40071b1431 | ||
|  | 02e29e6990 | ||
|  | e19de0901e | ||
|  | 137d506e42 | ||
|  | 90c4a26d52 | ||
|  | f378a8997b | ||
|  | 1377bed988 | ||
|  | 8f9f947c42 | ||
|  | 37f6c2858f | ||
|  | 13d7f239ab | ||
|  | a6f3c84e28 | ||
|  | fe4e0e9835 | ||
|  | 809917f13b | ||
|  | 2b35498370 | ||
|  | f45eabdd9e | ||
|  | 438f3ee8d2 | ||
|  | 4bea31f051 | ||
|  | 5eae7a2b93 | ||
|  | 364ef3e55c | ||
|  | e61818f194 | ||
|  | 0f9ce319d4 | ||
|  | 5d90871789 | ||
|  | 88a9e09918 | ||
|  | c50ecf6055 | ||
|  | a18de75da9 | ||
|  | e112dfd910 | ||
|  | 9154d8bd37 | ||
|  | 0b55372b3b | ||
|  | 3ad7fb010f | ||
|  | 3f64d1bb5a | ||
|  | a6f564ad88 | ||
|  | d97da3bb7b | ||
|  | a77d3c92ad | ||
|  | 6d17e5307c | ||
|  | c2205e473a | ||
|  | 4ffb194847 | ||
|  | 744cd6ec42 | ||
|  | f08fc18ab5 | ||
|  | 462af76770 | ||
|  | 9cec554f7c | ||
|  | 08b25e610d | ||
|  | e896d5a1a6 | ||
|  | b939562062 | ||
|  | 256781bba5 | ||
|  | 19705196d6 | ||
|  | 3ce692bb10 | ||
|  | 78bdbde3ae | ||
|  | 8d8c066447 | ||
|  | 5da9379c37 | ||
|  | 032d20ff37 | ||
|  | d19b17cbfe | ||
|  | 4a4f8ff5db | ||
|  | 60a9209a14 | ||
|  | 0f9e167df3 | ||
|  | 2e2b8c498e | ||
|  | 144199730f | ||
|  | 4bb4eab3b2 | ||
|  | cf9151f669 | ||
|  | aef4598cec | ||
|  | 3ada0fdf84 | ||
|  | a5d97b326e | ||
|  | 2640015fb1 | ||
|  | 6cd42ddafe | ||
|  | 1f17c22132 | ||
|  | 5c62f612cc | ||
|  | b9ca1c2e2c | ||
|  | 93b2ff2e52 | ||
|  | 3991d23a69 | ||
|  | 1be139759c | ||
|  | d0674ad688 | ||
|  | ffb47458ff | ||
|  | 84ec1be8a4 | ||
|  | f4dafec645 | ||
|  | 97ce72521d | ||
|  | d2f0e74879 | ||
|  | d9e3895c45 | ||
|  | 5075901830 | ||
|  | f1193bb5a0 | ||
|  | d3dc279105 | ||
|  | acc942f690 | ||
|  | e947067dcf | ||
|  | bd9ebf4603 | ||
|  | f41192a52a | ||
|  | ff54d6abd7 | ||
|  | f40bcc219f | ||
|  | 679965410a | ||
|  | c6e13ae2a3 | ||
|  | 20cdcc673b | ||
|  | 89f46222d9 | ||
|  | b27cbfac5e | ||
|  | 31c946aeeb | ||
|  | bfc8a26381 | ||
|  | 9d98746501 | ||
|  | 63b03ba70c | ||
|  | 70bab76b36 | ||
|  | 15d24d4308 | ||
|  | 9ec62eb045 | ||
|  | 12f841e30d | ||
|  | 335599ed22 | ||
|  | 0b717f9e76 | ||
|  | e941f6ecca | ||
|  | ef7744dbda | ||
|  | c83a61c460 | ||
|  | 335684caf7 | ||
|  | 8d6220ce51 | ||
|  | 39ea5c5f99 | ||
|  | b03597ac13 | ||
|  | 58f323c087 | ||
|  | 513a68584c | ||
|  | 88d5c68b32 | ||
|  | 14f9382cf9 | ||
|  | cffb582568 | ||
|  | e1812ce16c | ||
|  | 7a3163f59a | ||
|  | 6f3b2749b0 | ||
|  | c144d4e501 | ||
|  | edfd9d55ba | ||
|  | 774897260e | ||
|  | 65ba91411d | ||
|  | 9cbb8e1a64 | ||
|  | 53e9ad5088 | ||
|  | cf6ea63fa6 | ||
|  | 1de0ebb7bc | ||
|  | 77c1376d6d | ||
|  | 353f1954a5 | ||
|  | 8bf3406cf8 | ||
|  | 936bf9a05c | ||
|  | 4487499663 | ||
|  | 3976cc26a2 | ||
|  | e6ff87ecd0 | ||
|  | c0887b5f08 | ||
|  | f14dda4eca | ||
|  | bd7f75c130 | ||
|  | fbe3ce008b | ||
|  | 7ac6c8f2d1 | ||
|  | fdfbb7bdf0 | ||
|  | 1c16bbb742 | ||
|  | 9735527062 | ||
|  | 402827497e | ||
|  | f81aa0d867 | ||
|  | d32a970101 | ||
|  | cd651aa416 | ||
|  | 8a3189123a | ||
|  | b37231d0f5 | ||
|  | 3c55719bf1 | ||
|  | af8279a9b9 | ||
|  | c38508c262 | ||
|  | b0e8738ab8 | ||
|  | cae480768e | ||
|  | a70276c190 | ||
|  | 0c461ffe2e | ||
|  | 237511f2d6 | ||
|  | cdcb652033 | ||
|  | 71e678b382 | ||
|  | 3050156325 | ||
|  | 4bfdbad2e4 | ||
|  | 06137ecdc4 | ||
|  | d89f5b0df8 | ||
|  | b6e2b36692 | ||
|  | a6d789cfbc | ||
|  | c07907e7bd | ||
|  | 7d8496c874 | ||
|  | 164ac56db1 | ||
|  | fdddb8ca64 | ||
|  | a9d4b8b0fa | ||
|  | ec7b9f54c2 | ||
|  | 307558a7e7 | ||
|  | febf423eab | ||
|  | a999c23014 | ||
|  | 69f1ade595 | ||
|  | b166576e54 | ||
|  | ee2ba5f398 | ||
|  | cb9825484d | ||
|  | 76cda82e23 | ||
|  | 37b61d9e6b | ||
|  | 52f0222a6d | ||
|  | 75ccac2f2c | ||
|  | 5c771a91f7 | ||
|  | a242ad10e6 | ||
|  | b5086b6a8f | ||
|  | 3e47dad12a | ||
|  | 235610f40c | ||
|  | 6b59559c65 | ||
|  | 23e954f716 | ||
|  | 983c899cad | ||
|  | c2f9385965 | ||
|  | ceb2c9e4f8 | ||
|  | 68a7f9c665 | ||
|  | ffd8d9c7c1 | ||
|  | c66fc8630c | ||
|  | 9ca1c66f2b | ||
|  | 33647a29d0 | ||
|  | 02b12cc762 | ||
|  | 3280993e2a | ||
|  | 3723c22054 | ||
|  | 0a2c4ea0c4 | ||
|  | 58a83c0439 | ||
|  | d665489054 | ||
|  | 9200992024 | ||
|  | 6408cc46a8 | ||
|  | 961bcdb7ae | ||
|  | edee70cf31 | ||
|  | 1978a9815a | ||
|  | f5e6db9d66 | ||
|  | a94bc40ab0 | ||
|  | 534b5ced8f | ||
|  | 5ebd9b54e4 | ||
|  | cc4e272526 | ||
|  | 295e199bfa | ||
|  | df3371b0f0 | ||
|  | e4fe1d2b8d | ||
|  | b8b9244ffa | ||
|  | 3be3989e1c | ||
|  | ed54cf680a | ||
|  | 95e76058d3 | ||
|  | a6bee6a860 | ||
|  | d22780ee44 | ||
|  | f8b0b9575d | ||
|  | 4274fd168e | ||
|  | be7f5957f3 | ||
|  | f2e5d987a9 | ||
|  | f01173d8db | ||
|  | 15e8e0bf6d | ||
|  | 2c59cbdece | ||
|  | b73da4ed02 | ||
|  | 267adb4612 | ||
|  | 05c73fa8bc | ||
|  | bfe9f442e6 | ||
|  | 0deadb694b | ||
|  | bed34378be | ||
|  | 5927cf2d43 | ||
|  | fffe36e358 | ||
|  | fac2a2d7cb | ||
|  | 0af5582ca7 | ||
|  | 582d31263c | ||
|  | 4108a528e1 | ||
|  | ab7d7c2907 | ||
|  | 152888ee93 | ||
|  | 22f8f4f359 | ||
|  | 5f3a9e189a | ||
|  | b734dc44fd | ||
|  | fab224f509 | ||
|  | 2f05ebb966 | ||
|  | a335ba519a | ||
|  | 8805693ed2 | ||
|  | f2bb238e9b | ||
|  | 131fe670a4 | ||
|  | 11e9539416 | ||
|  | 3881ebe429 | ||
|  | 29d1b8802e | ||
|  | bcc75732e9 | ||
|  | 50a85ee6b0 | ||
|  | 2c7424fd43 | ||
|  | 7426587c38 | ||
|  | 1f39749a5e | ||
|  | ca63051c71 | ||
|  | 6dd44aaf0d | ||
|  | f89457ba68 | ||
|  | efef205fcf | ||
|  | 0c561d8528 | ||
|  | 8bfa2c4c02 | ||
|  | f0d4c3aba9 | ||
|  | 3a99115070 | ||
|  | 7232134931 | ||
|  | 954e911eb3 | ||
|  | 63c073c93f | ||
|  | 78feef9d59 | ||
|  | 4fbdd6d570 | ||
|  | 4929c198ba | ||
|  | 9409f17372 | ||
|  | 43781c02d0 | ||
|  | 824f06e17f | ||
|  | 21dbc6da97 | ||
|  | 270ea54ff7 | ||
|  | 771ac7aba7 | ||
|  | 97d36243f2 | ||
|  | 511b47bac4 | ||
|  | f265199fbe | ||
|  | a191ec71a4 | ||
|  | 82dce2dd53 | ||
|  | 29ac160811 | ||
|  | 5e50ea14f8 | ||
|  | 40e6091506 | ||
|  | 0ee4d420b1 | ||
|  | 66acce9e8e | ||
|  | 6c23ae14ab | ||
|  | 6f000d0d26 | ||
|  | 9d7eb3be5a | ||
|  | 835555171e | ||
|  | 68ce4a1bf0 | ||
|  | a995867deb | ||
|  | 6bd99d63b4 | ||
|  | baf5d3041a | ||
|  | a326ffa00a | ||
|  | d28dd92b47 | ||
|  | 1de328b2e8 | ||
|  | 51bb902162 | ||
|  | 4fd14f1366 | ||
|  | 91d9559f79 | ||
|  | 3245a9b157 | ||
|  | 2b28493bba | ||
|  | 1382728bd2 | ||
|  | 0422ad080a | ||
|  | 64d682bfde | ||
|  | b182f7e693 | ||
|  | e6be428589 | ||
|  | 85c7f8314b | ||
|  | 796d07a7f8 | ||
|  | 2af86a10b2 | ||
|  | 7fbe486dff | ||
|  | 87e5a9859a | ||
|  | b036e5ed72 | ||
|  | 5f1ec80ae0 | ||
|  | fbecedaf41 | ||
|  | aa36acd65a | ||
|  | 8d1a4588d3 | ||
|  | 66d2af4453 | ||
|  | ef6c731bb3 | ||
|  | 98a638a2f3 | ||
|  | 96d8a7f0d7 | ||
|  | 3162b10392 | ||
|  | e2358de27c | 
							
								
								
									
										17
									
								
								.aiignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								.aiignore
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | |||||||
|  | # An .aiignore file follows the same syntax as a .gitignore file. | ||||||
|  | # .gitignore documentation: https://git-scm.com/docs/gitignore | ||||||
|  |  | ||||||
|  | # you can ignore files | ||||||
|  | .DS_Store | ||||||
|  | *.log | ||||||
|  | *.tmp | ||||||
|  | *.bin | ||||||
|  | *.prg | ||||||
|  |  | ||||||
|  | # or folders | ||||||
|  | dist/ | ||||||
|  | build/ | ||||||
|  | out/ | ||||||
|  | output/ | ||||||
|  | .gradle/ | ||||||
|  | .kotlin/ | ||||||
							
								
								
									
										14
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | # These are supported funding model platforms | ||||||
|  |  | ||||||
|  | #github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] | ||||||
|  | #patreon: # Replace with a single Patreon username | ||||||
|  | #open_collective: # Replace with a single Open Collective username | ||||||
|  | ko_fi: irmen | ||||||
|  | #tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel | ||||||
|  | #community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry | ||||||
|  | #liberapay: # Replace with a single Liberapay username | ||||||
|  | #issuehunt: # Replace with a single IssueHunt username | ||||||
|  | #otechie: # Replace with a single Otechie username | ||||||
|  | #lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry | ||||||
|  | #custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] | ||||||
|  | custom: ['https://paypal.me/irmendejong'] | ||||||
							
								
								
									
										41
									
								
								.github/workflows/all-ci.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								.github/workflows/all-ci.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | name: Build and Test the Prog8 compiler | ||||||
|  |  | ||||||
|  | on: | ||||||
|  |   push: | ||||||
|  |   workflow_dispatch: | ||||||
|  |  | ||||||
|  | jobs: | ||||||
|  |   build: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |  | ||||||
|  |     steps: | ||||||
|  |       - name: Checkout code | ||||||
|  |         uses: actions/checkout@v4 | ||||||
|  |  | ||||||
|  |       - name: build and install recent 64tass | ||||||
|  |         run: | | ||||||
|  |           sudo apt-get install -y make build-essential | ||||||
|  |           git clone --depth=1 https://github.com/irmen/64tass | ||||||
|  |           cd 64tass | ||||||
|  |           make -j4 | ||||||
|  |           sudo make install           | ||||||
|  |  | ||||||
|  |       - name: Set up JDK 17 | ||||||
|  |         uses: actions/setup-java@v4 | ||||||
|  |         with: | ||||||
|  |           java-version: 17 | ||||||
|  |           distribution: temurin | ||||||
|  |  | ||||||
|  |       - name: Build and test with Gradle | ||||||
|  |         run: | | ||||||
|  |           ./gradlew build shadowJar --no-daemon | ||||||
|  |           sha256sum -b compiler/build/libs/*-all.jar > compiler/build/libs/hash.txt | ||||||
|  |          | ||||||
|  |       - name: Create compiler shadowJar artifact | ||||||
|  |         uses: actions/upload-artifact@v4 | ||||||
|  |         with: | ||||||
|  |           name: prog8-compiler-jar-zipped | ||||||
|  |           path: | | ||||||
|  |             compiler/build/libs/*-all.jar | ||||||
|  |             compiler/build/libs/hash.txt | ||||||
|  |  | ||||||
							
								
								
									
										28
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,32 +1,42 @@ | |||||||
| .idea/workspace.xml | .idea/workspace.xml | ||||||
| .idea/discord.xml | .idea/discord.xml | ||||||
| /build/ | .idea/developer-tools.xml | ||||||
| /dist/ | .idea/usage.statistics.xml | ||||||
| /output/ | .idea/shelf/ | ||||||
|  | build/ | ||||||
|  | dist/ | ||||||
|  | output/ | ||||||
|  | out/ | ||||||
|  | out-new/ | ||||||
|  | out-old/ | ||||||
| .*cache/ | .*cache/ | ||||||
| *.directory | *.directory | ||||||
| *.prg | *.prg | ||||||
| *.bin | *.bin | ||||||
|  | *.p8ir | ||||||
| *.labels.txt | *.labels.txt | ||||||
| *.vm.txt | *.vm.txt | ||||||
| *.vice-mon-list | *.vice-mon-list | ||||||
| docs/build | docs/build | ||||||
| out/ | parser/**/*.interp | ||||||
| **/*.interp | parser/**/*.tokens | ||||||
| **/*.tokens | parser/**/*.java | ||||||
|  | compiler/src/prog8/buildversion/* | ||||||
| *.py[cod] | *.py[cod] | ||||||
| *.egg | *.egg | ||||||
| *.egg-info | *.egg-info | ||||||
| .eggs/ | .eggs/ | ||||||
| /MANIFEST | /MANIFEST | ||||||
| .tox/ | .tox/ | ||||||
|  | .kotlin/ | ||||||
| __pycache__/ | __pycache__/ | ||||||
| parser.out | parser.out | ||||||
| parsetab.py | parsetab.py | ||||||
| .pytest_cache/ | .pytest_cache/ | ||||||
| .attach_pid* | .attach_pid* | ||||||
|  | compiler/lib/ | ||||||
|  |  | ||||||
| .gradle | .gradle | ||||||
| build/ | sd*.img | ||||||
| /prog8compiler.jar | *.d64 | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								.idea/codeInsightSettings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.idea/codeInsightSettings.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project version="4"> | ||||||
|  |   <component name="JavaProjectCodeInsightSettings"> | ||||||
|  |     <excluded-names> | ||||||
|  |       <name>kotlin.Result</name> | ||||||
|  |     </excluded-names> | ||||||
|  |   </component> | ||||||
|  | </project> | ||||||
							
								
								
									
										10
									
								
								.idea/codeStyles/Project.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								.idea/codeStyles/Project.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | <component name="ProjectCodeStyleConfiguration"> | ||||||
|  |   <code_scheme name="Project" version="173"> | ||||||
|  |     <JetCodeStyleSettings> | ||||||
|  |       <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> | ||||||
|  |     </JetCodeStyleSettings> | ||||||
|  |     <codeStyleSettings language="kotlin"> | ||||||
|  |       <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> | ||||||
|  |     </codeStyleSettings> | ||||||
|  |   </code_scheme> | ||||||
|  | </component> | ||||||
							
								
								
									
										5
									
								
								.idea/codeStyles/codeStyleConfig.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.idea/codeStyles/codeStyleConfig.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | <component name="ProjectCodeStyleConfiguration"> | ||||||
|  |   <state> | ||||||
|  |     <option name="USE_PER_PROJECT_SETTINGS" value="true" /> | ||||||
|  |   </state> | ||||||
|  | </component> | ||||||
							
								
								
									
										7
									
								
								.idea/compiler.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								.idea/compiler.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <project version="4"> | ||||||
|  |   <component name="CompilerConfiguration"> | ||||||
|  |     <option name="BUILD_PROCESS_HEAP_SIZE" value="3000" /> | ||||||
|  |     <bytecodeTargetLevel target="11" /> | ||||||
|  |   </component> | ||||||
|  | </project> | ||||||
							
								
								
									
										1587
									
								
								.idea/inspectionProfiles/Project_Default.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1587
									
								
								.idea/inspectionProfiles/Project_Default.xml
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										15
									
								
								.idea/kotlinc.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										15
									
								
								.idea/kotlinc.xml
									
									
									
										generated
									
									
									
								
							| @@ -1,6 +1,19 @@ | |||||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||||
| <project version="4"> | <project version="4"> | ||||||
|  |   <component name="Kotlin2JsCompilerArguments"> | ||||||
|  |     <option name="moduleKind" value="plain" /> | ||||||
|  |   </component> | ||||||
|   <component name="Kotlin2JvmCompilerArguments"> |   <component name="Kotlin2JvmCompilerArguments"> | ||||||
|     <option name="jvmTarget" value="1.8" /> |     <option name="jvmTarget" value="11" /> | ||||||
|  |   </component> | ||||||
|  |   <component name="KotlinCommonCompilerArguments"> | ||||||
|  |     <option name="apiVersion" value="2.2" /> | ||||||
|  |     <option name="languageVersion" value="2.2" /> | ||||||
|  |   </component> | ||||||
|  |   <component name="KotlinCompilerSettings"> | ||||||
|  |     <option name="additionalArguments" value="-Xwhen-guards -jvm-default=no-compatibility" /> | ||||||
|  |   </component> | ||||||
|  |   <component name="KotlinJpsPluginSettings"> | ||||||
|  |     <option name="version" value="2.2.0" /> | ||||||
|   </component> |   </component> | ||||||
| </project> | </project> | ||||||
							
								
								
									
										28
									
								
								.idea/libraries/KotlinJavaRuntime.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										28
									
								
								.idea/libraries/KotlinJavaRuntime.xml
									
									
									
										generated
									
									
									
								
							| @@ -1,19 +1,23 @@ | |||||||
| <component name="libraryTable"> | <component name="libraryTable"> | ||||||
|   <library name="KotlinJavaRuntime"> |   <library name="KotlinJavaRuntime" type="repository"> | ||||||
|  |     <properties maven-id="org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.2.20" /> | ||||||
|     <CLASSES> |     <CLASSES> | ||||||
|       <root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-stdlib.jar!/" /> |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/2.2.20/kotlin-stdlib-jdk8-2.2.20.jar!/" /> | ||||||
|       <root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-reflect.jar!/" /> |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.2.20/kotlin-stdlib-2.2.20.jar!/" /> | ||||||
|       <root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-test.jar!/" /> |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar!/" /> | ||||||
|       <root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-stdlib-jdk7.jar!/" /> |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/2.2.20/kotlin-stdlib-jdk7-2.2.20.jar!/" /> | ||||||
|       <root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-stdlib-jdk8.jar!/" /> |  | ||||||
|     </CLASSES> |     </CLASSES> | ||||||
|     <JAVADOC /> |     <JAVADOC> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/2.2.20/kotlin-stdlib-jdk8-2.2.20-javadoc.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.2.20/kotlin-stdlib-2.2.20-javadoc.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0-javadoc.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/2.2.20/kotlin-stdlib-jdk7-2.2.20-javadoc.jar!/" /> | ||||||
|  |     </JAVADOC> | ||||||
|     <SOURCES> |     <SOURCES> | ||||||
|       <root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-stdlib-sources.jar!/" /> |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/2.2.20/kotlin-stdlib-jdk8-2.2.20-sources.jar!/" /> | ||||||
|       <root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-reflect-sources.jar!/" /> |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.2.20/kotlin-stdlib-2.2.20-sources.jar!/" /> | ||||||
|       <root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-test-sources.jar!/" /> |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0-sources.jar!/" /> | ||||||
|       <root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-stdlib-jdk7-sources.jar!/" /> |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/2.2.20/kotlin-stdlib-jdk7-2.2.20-sources.jar!/" /> | ||||||
|       <root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-stdlib-jdk8-sources.jar!/" /> |  | ||||||
|     </SOURCES> |     </SOURCES> | ||||||
|   </library> |   </library> | ||||||
| </component> | </component> | ||||||
							
								
								
									
										9
									
								
								.idea/libraries/antlr_4_7_2_complete.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										9
									
								
								.idea/libraries/antlr_4_7_2_complete.xml
									
									
									
										generated
									
									
									
								
							| @@ -1,9 +0,0 @@ | |||||||
| <component name="libraryTable"> |  | ||||||
|   <library name="antlr-4.7.2-complete"> |  | ||||||
|     <CLASSES> |  | ||||||
|       <root url="jar://$PROJECT_DIR$/parser/antlr/lib/antlr-4.7.2-complete.jar!/" /> |  | ||||||
|     </CLASSES> |  | ||||||
|     <JAVADOC /> |  | ||||||
|     <SOURCES /> |  | ||||||
|   </library> |  | ||||||
| </component> |  | ||||||
							
								
								
									
										9
									
								
								.idea/libraries/antlr_4_8_complete.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										9
									
								
								.idea/libraries/antlr_4_8_complete.xml
									
									
									
										generated
									
									
									
								
							| @@ -1,9 +0,0 @@ | |||||||
| <component name="libraryTable"> |  | ||||||
|   <library name="antlr-4.8-complete"> |  | ||||||
|     <CLASSES> |  | ||||||
|       <root url="jar://$PROJECT_DIR$/parser/antlr/lib/antlr-4.8-complete.jar!/" /> |  | ||||||
|     </CLASSES> |  | ||||||
|     <JAVADOC /> |  | ||||||
|     <SOURCES /> |  | ||||||
|   </library> |  | ||||||
| </component> |  | ||||||
							
								
								
									
										18
									
								
								.idea/libraries/antlr_antlr4.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								.idea/libraries/antlr_antlr4.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | <component name="libraryTable"> | ||||||
|  |   <library name="antlr.antlr4" type="repository"> | ||||||
|  |     <properties maven-id="org.antlr:antlr4:4.13.2"> | ||||||
|  |       <exclude> | ||||||
|  |         <dependency maven-id="com.ibm.icu:icu4j" /> | ||||||
|  |       </exclude> | ||||||
|  |     </properties> | ||||||
|  |     <CLASSES> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4/4.13.2/antlr4-4.13.2.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr4-runtime/4.13.2/antlr4-runtime-4.13.2.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/antlr/antlr-runtime/3.5.3/antlr-runtime-3.5.3.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/antlr/ST4/4.3.4/ST4-4.3.4.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/abego/treelayout/org.abego.treelayout.core/1.0.3/org.abego.treelayout.core-1.0.3.jar!/" /> | ||||||
|  |     </CLASSES> | ||||||
|  |     <JAVADOC /> | ||||||
|  |     <SOURCES /> | ||||||
|  |   </library> | ||||||
|  | </component> | ||||||
							
								
								
									
										9
									
								
								.idea/libraries/antlr_runtime_4_7_2.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										9
									
								
								.idea/libraries/antlr_runtime_4_7_2.xml
									
									
									
										generated
									
									
									
								
							| @@ -1,9 +0,0 @@ | |||||||
| <component name="libraryTable"> |  | ||||||
|   <library name="antlr-runtime-4.7.2"> |  | ||||||
|     <CLASSES> |  | ||||||
|       <root url="jar://$PROJECT_DIR$/parser/antlr/lib/antlr-runtime-4.7.2.jar!/" /> |  | ||||||
|     </CLASSES> |  | ||||||
|     <JAVADOC /> |  | ||||||
|     <SOURCES /> |  | ||||||
|   </library> |  | ||||||
| </component> |  | ||||||
							
								
								
									
										9
									
								
								.idea/libraries/antlr_runtime_4_8.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										9
									
								
								.idea/libraries/antlr_runtime_4_8.xml
									
									
									
										generated
									
									
									
								
							| @@ -1,9 +0,0 @@ | |||||||
| <component name="libraryTable"> |  | ||||||
|   <library name="antlr-runtime-4.8"> |  | ||||||
|     <CLASSES> |  | ||||||
|       <root url="jar://$PROJECT_DIR$/parser/antlr/lib/antlr-runtime-4.8.jar!/" /> |  | ||||||
|     </CLASSES> |  | ||||||
|     <JAVADOC /> |  | ||||||
|     <SOURCES /> |  | ||||||
|   </library> |  | ||||||
| </component> |  | ||||||
							
								
								
									
										13
									
								
								.idea/libraries/eclipse_lsp4j.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.idea/libraries/eclipse_lsp4j.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | <component name="libraryTable"> | ||||||
|  |   <library name="eclipse.lsp4j" type="repository"> | ||||||
|  |     <properties maven-id="org.eclipse.lsp4j:org.eclipse.lsp4j:0.24.0" /> | ||||||
|  |     <CLASSES> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/eclipse/lsp4j/org.eclipse.lsp4j/0.24.0/org.eclipse.lsp4j-0.24.0.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/eclipse/lsp4j/org.eclipse.lsp4j.jsonrpc/0.24.0/org.eclipse.lsp4j.jsonrpc-0.24.0.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/com/google/code/gson/gson/2.13.1/gson-2.13.1.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/com/google/errorprone/error_prone_annotations/2.38.0/error_prone_annotations-2.38.0.jar!/" /> | ||||||
|  |     </CLASSES> | ||||||
|  |     <JAVADOC /> | ||||||
|  |     <SOURCES /> | ||||||
|  |   </library> | ||||||
|  | </component> | ||||||
							
								
								
									
										23
									
								
								.idea/libraries/io_kotest_framework_datatest.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								.idea/libraries/io_kotest_framework_datatest.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | <component name="libraryTable"> | ||||||
|  |   <library name="io.kotest.framework.datatest" type="repository"> | ||||||
|  |     <properties maven-id="io.kotest:kotest-framework-datatest:5.9.1" /> | ||||||
|  |     <CLASSES> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/kotest/kotest-framework-datatest/5.9.1/kotest-framework-datatest-5.9.1.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/kotest/kotest-framework-datatest-jvm/5.9.1/kotest-framework-datatest-jvm-5.9.1.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.9.23/kotlin-stdlib-1.9.23.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.8.0/kotlinx-coroutines-core-jvm-1.8.0.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/kotest/kotest-common-jvm/5.9.1/kotest-common-jvm-5.9.1.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.9.23/kotlin-reflect-1.9.23.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/kotest/kotest-framework-api-jvm/5.9.1/kotest-framework-api-jvm-5.9.1.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/kotest/kotest-assertions-shared-jvm/5.9.1/kotest-assertions-shared-jvm-5.9.1.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/kotest/kotest-assertions-api-jvm/5.9.1/kotest-assertions-api-jvm-5.9.1.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlinx/kotlinx-coroutines-jdk8/1.8.0/kotlinx-coroutines-jdk8-1.8.0.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/github/java-diff-utils/java-diff-utils/4.12/java-diff-utils-4.12.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/opentest4j/opentest4j/1.3.0/opentest4j-1.3.0.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlinx/kotlinx-coroutines-test-jvm/1.8.0/kotlinx-coroutines-test-jvm-1.8.0.jar!/" /> | ||||||
|  |     </CLASSES> | ||||||
|  |     <JAVADOC /> | ||||||
|  |     <SOURCES /> | ||||||
|  |   </library> | ||||||
|  | </component> | ||||||
							
								
								
									
										41
									
								
								.idea/libraries/io_kotest_runner_junit5_jvm.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								.idea/libraries/io_kotest_runner_junit5_jvm.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | <component name="libraryTable"> | ||||||
|  |   <library name="io.kotest.runner.junit5.jvm" type="repository"> | ||||||
|  |     <properties maven-id="io.kotest:kotest-runner-junit5-jvm:5.9.1" /> | ||||||
|  |     <CLASSES> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/kotest/kotest-runner-junit5-jvm/5.9.1/kotest-runner-junit5-jvm-5.9.1.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/kotest/kotest-framework-api-jvm/5.9.1/kotest-framework-api-jvm-5.9.1.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/kotest/kotest-assertions-shared-jvm/5.9.1/kotest-assertions-shared-jvm-5.9.1.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/github/java-diff-utils/java-diff-utils/4.12/java-diff-utils-4.12.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlinx/kotlinx-coroutines-test-jvm/1.8.0/kotlinx-coroutines-test-jvm-1.8.0.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/kotest/kotest-common-jvm/5.9.1/kotest-common-jvm-5.9.1.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/kotest/kotest-framework-engine-jvm/5.9.1/kotest-framework-engine-jvm-5.9.1.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/github/classgraph/classgraph/4.8.172/classgraph-4.8.172.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/com/github/ajalt/mordant/1.2.1/mordant-1.2.1.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/com/github/ajalt/colormath/1.2.0/colormath-1.2.0.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/opentest4j/opentest4j/1.3.0/opentest4j-1.3.0.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlinx/kotlinx-coroutines-debug/1.8.0/kotlinx-coroutines-debug-1.8.0.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/net/java/dev/jna/jna/5.9.0/jna-5.9.0.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/net/java/dev/jna/jna-platform/5.9.0/jna-platform-5.9.0.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/net/bytebuddy/byte-buddy/1.10.9/byte-buddy-1.10.9.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/net/bytebuddy/byte-buddy-agent/1.10.9/byte-buddy-agent-1.10.9.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/kotest/kotest-framework-discovery-jvm/5.9.1/kotest-framework-discovery-jvm-5.9.1.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/kotest/kotest-assertions-core-jvm/5.9.1/kotest-assertions-core-jvm-5.9.1.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlinx/kotlinx-coroutines-jdk8/1.8.0/kotlinx-coroutines-jdk8-1.8.0.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/kotest/kotest-assertions-api-jvm/5.9.1/kotest-assertions-api-jvm-5.9.1.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/kotest/kotest-extensions-jvm/5.9.1/kotest-extensions-jvm-5.9.1.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/io/kotest/kotest-framework-concurrency-jvm/5.9.1/kotest-framework-concurrency-jvm-5.9.1.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlinx/kotlinx-coroutines-core-jvm/1.8.0/kotlinx-coroutines-core-jvm-1.8.0.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/23.0.0/annotations-23.0.0.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/junit/platform/junit-platform-engine/1.8.2/junit-platform-engine-1.8.2.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/junit/platform/junit-platform-commons/1.8.2/junit-platform-commons-1.8.2.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/junit/platform/junit-platform-suite-api/1.8.2/junit-platform-suite-api-1.8.2.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/junit/platform/junit-platform-launcher/1.8.2/junit-platform-launcher-1.8.2.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/junit/jupiter/junit-jupiter-api/5.8.2/junit-jupiter-api-5.8.2.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/1.9.23/kotlin-stdlib-1.9.23.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.9.23/kotlin-reflect-1.9.23.jar!/" /> | ||||||
|  |     </CLASSES> | ||||||
|  |     <JAVADOC /> | ||||||
|  |     <SOURCES /> | ||||||
|  |   </library> | ||||||
|  | </component> | ||||||
							
								
								
									
										10
									
								
								.idea/libraries/jetbrains_kotlinx_cli_jvm.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								.idea/libraries/jetbrains_kotlinx_cli_jvm.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | <component name="libraryTable"> | ||||||
|  |   <library name="jetbrains.kotlinx.cli.jvm" type="repository"> | ||||||
|  |     <properties include-transitive-deps="false" maven-id="org.jetbrains.kotlinx:kotlinx-cli-jvm:0.3.6" /> | ||||||
|  |     <CLASSES> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlinx/kotlinx-cli-jvm/0.3.6/kotlinx-cli-jvm-0.3.6.jar!/" /> | ||||||
|  |     </CLASSES> | ||||||
|  |     <JAVADOC /> | ||||||
|  |     <SOURCES /> | ||||||
|  |   </library> | ||||||
|  | </component> | ||||||
							
								
								
									
										9
									
								
								.idea/libraries/kotlinx_cli_jvm_0_1_0_dev_5.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										9
									
								
								.idea/libraries/kotlinx_cli_jvm_0_1_0_dev_5.xml
									
									
									
										generated
									
									
									
								
							| @@ -1,9 +0,0 @@ | |||||||
| <component name="libraryTable"> |  | ||||||
|   <library name="kotlinx-cli-jvm-0.1.0-dev-5"> |  | ||||||
|     <CLASSES> |  | ||||||
|       <root url="jar://$PROJECT_DIR$/compiler/lib/kotlinx-cli-jvm-0.1.0-dev-5.jar!/" /> |  | ||||||
|     </CLASSES> |  | ||||||
|     <JAVADOC /> |  | ||||||
|     <SOURCES /> |  | ||||||
|   </library> |  | ||||||
| </component> |  | ||||||
							
								
								
									
										20
									
								
								.idea/libraries/michael_bull_kotlin_result_jvm.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								.idea/libraries/michael_bull_kotlin_result_jvm.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | <component name="libraryTable"> | ||||||
|  |   <library name="michael.bull.kotlin.result.jvm" type="repository"> | ||||||
|  |     <properties maven-id="com.michael-bull.kotlin-result:kotlin-result-jvm:2.1.0" /> | ||||||
|  |     <CLASSES> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/com/michael-bull/kotlin-result/kotlin-result-jvm/2.1.0/kotlin-result-jvm-2.1.0.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.2.0/kotlin-stdlib-2.2.0.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar!/" /> | ||||||
|  |     </CLASSES> | ||||||
|  |     <JAVADOC> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/com/michael-bull/kotlin-result/kotlin-result-jvm/2.1.0/kotlin-result-jvm-2.1.0-javadoc.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.2.0/kotlin-stdlib-2.2.0-javadoc.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0-javadoc.jar!/" /> | ||||||
|  |     </JAVADOC> | ||||||
|  |     <SOURCES> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/com/michael-bull/kotlin-result/kotlin-result-jvm/2.1.0/kotlin-result-jvm-2.1.0-sources.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.2.0/kotlin-stdlib-2.2.0-sources.jar!/" /> | ||||||
|  |       <root url="jar://$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0-sources.jar!/" /> | ||||||
|  |     </SOURCES> | ||||||
|  |   </library> | ||||||
|  | </component> | ||||||
							
								
								
									
										10
									
								
								.idea/libraries/unittest_libs.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										10
									
								
								.idea/libraries/unittest_libs.xml
									
									
									
										generated
									
									
									
								
							| @@ -1,10 +0,0 @@ | |||||||
| <component name="libraryTable"> |  | ||||||
|   <library name="unittest-libs"> |  | ||||||
|     <CLASSES> |  | ||||||
|       <root url="file://$PROJECT_DIR$/compiler/lib" /> |  | ||||||
|     </CLASSES> |  | ||||||
|     <JAVADOC /> |  | ||||||
|     <SOURCES /> |  | ||||||
|     <jarDirectory url="file://$PROJECT_DIR$/compiler/lib" recursive="false" /> |  | ||||||
|   </library> |  | ||||||
| </component> |  | ||||||
							
								
								
									
										16
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										16
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
								
							| @@ -4,19 +4,29 @@ | |||||||
|     <option name="perGrammarGenerationSettings"> |     <option name="perGrammarGenerationSettings"> | ||||||
|       <list> |       <list> | ||||||
|         <PerGrammarGenerationSettings> |         <PerGrammarGenerationSettings> | ||||||
|           <option name="fileName" value="$PROJECT_DIR$/parser/antlr/prog8.g4" /> |           <option name="fileName" value="$PROJECT_DIR$/parser/src/main/antlr/Prog8ANTLR.g4" /> | ||||||
|           <option name="autoGen" value="true" /> |           <option name="autoGen" value="true" /> | ||||||
|           <option name="outputDir" value="$PROJECT_DIR$/parser/src/prog8/parser" /> |           <option name="outputDir" value="$PROJECT_DIR$/parser/src/prog8/parser" /> | ||||||
|           <option name="libDir" value="" /> |           <option name="libDir" value="" /> | ||||||
|           <option name="encoding" value="" /> |           <option name="encoding" value="" /> | ||||||
|           <option name="pkg" value="" /> |           <option name="pkg" value="" /> | ||||||
|           <option name="language" value="" /> |           <option name="language" value="Java" /> | ||||||
|           <option name="generateListener" value="false" /> |           <option name="generateListener" value="false" /> | ||||||
|  |           <option name="generateVisitor" value="true" /> | ||||||
|         </PerGrammarGenerationSettings> |         </PerGrammarGenerationSettings> | ||||||
|       </list> |       </list> | ||||||
|     </option> |     </option> | ||||||
|   </component> |   </component> | ||||||
|   <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" project-jdk-name="Kotlin SDK" project-jdk-type="KotlinSDK"> |   <component name="Black"> | ||||||
|  |     <option name="sdkName" value="Python 3.11" /> | ||||||
|  |   </component> | ||||||
|  |   <component name="FrameworkDetectionExcludesConfiguration"> | ||||||
|  |     <type id="Python" /> | ||||||
|  |   </component> | ||||||
|  |   <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="openjdk-21" project-jdk-type="JavaSDK"> | ||||||
|     <output url="file://$PROJECT_DIR$/out" /> |     <output url="file://$PROJECT_DIR$/out" /> | ||||||
|   </component> |   </component> | ||||||
|  |   <component name="PythonCompatibilityInspectionAdvertiser"> | ||||||
|  |     <option name="version" value="3" /> | ||||||
|  |   </component> | ||||||
| </project> | </project> | ||||||
							
								
								
									
										14
									
								
								.idea/modules.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										14
									
								
								.idea/modules.xml
									
									
									
										generated
									
									
									
								
							| @@ -2,10 +2,24 @@ | |||||||
| <project version="4"> | <project version="4"> | ||||||
|   <component name="ProjectModuleManager"> |   <component name="ProjectModuleManager"> | ||||||
|     <modules> |     <modules> | ||||||
|  |       <module fileurl="file://$PROJECT_DIR$/beanshell/beanshell.iml" filepath="$PROJECT_DIR$/beanshell/beanshell.iml" /> | ||||||
|  |       <module fileurl="file://$PROJECT_DIR$/benchmark-program/benchmark-program.iml" filepath="$PROJECT_DIR$/benchmark-program/benchmark-program.iml" /> | ||||||
|  |       <module fileurl="file://$PROJECT_DIR$/codeCore/codeCore.iml" filepath="$PROJECT_DIR$/codeCore/codeCore.iml" /> | ||||||
|  |       <module fileurl="file://$PROJECT_DIR$/codeGenCpu6502/codeGenCpu6502.iml" filepath="$PROJECT_DIR$/codeGenCpu6502/codeGenCpu6502.iml" /> | ||||||
|  |       <module fileurl="file://$PROJECT_DIR$/codeGenExperimental/codeGenExperimental.iml" filepath="$PROJECT_DIR$/codeGenExperimental/codeGenExperimental.iml" /> | ||||||
|  |       <module fileurl="file://$PROJECT_DIR$/codeGenIntermediate/codeGenIntermediate.iml" filepath="$PROJECT_DIR$/codeGenIntermediate/codeGenIntermediate.iml" /> | ||||||
|  |       <module fileurl="file://$PROJECT_DIR$/codeGenVirtual/codeGenVirtual.iml" filepath="$PROJECT_DIR$/codeGenVirtual/codeGenVirtual.iml" /> | ||||||
|  |       <module fileurl="file://$PROJECT_DIR$/codeOptimizers/codeOptimizers.iml" filepath="$PROJECT_DIR$/codeOptimizers/codeOptimizers.iml" /> | ||||||
|       <module fileurl="file://$PROJECT_DIR$/compiler/compiler.iml" filepath="$PROJECT_DIR$/compiler/compiler.iml" /> |       <module fileurl="file://$PROJECT_DIR$/compiler/compiler.iml" filepath="$PROJECT_DIR$/compiler/compiler.iml" /> | ||||||
|  |       <module fileurl="file://$PROJECT_DIR$/compilerAst/compilerAst.iml" filepath="$PROJECT_DIR$/compilerAst/compilerAst.iml" /> | ||||||
|       <module fileurl="file://$PROJECT_DIR$/docs/docs.iml" filepath="$PROJECT_DIR$/docs/docs.iml" /> |       <module fileurl="file://$PROJECT_DIR$/docs/docs.iml" filepath="$PROJECT_DIR$/docs/docs.iml" /> | ||||||
|       <module fileurl="file://$PROJECT_DIR$/examples/examples.iml" filepath="$PROJECT_DIR$/examples/examples.iml" /> |       <module fileurl="file://$PROJECT_DIR$/examples/examples.iml" filepath="$PROJECT_DIR$/examples/examples.iml" /> | ||||||
|  |       <module fileurl="file://$PROJECT_DIR$/intermediate/intermediate.iml" filepath="$PROJECT_DIR$/intermediate/intermediate.iml" /> | ||||||
|  |       <module fileurl="file://$PROJECT_DIR$/languageServer/languageServer.iml" filepath="$PROJECT_DIR$/languageServer/languageServer.iml" /> | ||||||
|       <module fileurl="file://$PROJECT_DIR$/parser/parser.iml" filepath="$PROJECT_DIR$/parser/parser.iml" /> |       <module fileurl="file://$PROJECT_DIR$/parser/parser.iml" filepath="$PROJECT_DIR$/parser/parser.iml" /> | ||||||
|  |       <module fileurl="file://$PROJECT_DIR$/.idea/modules/prog8.iml" filepath="$PROJECT_DIR$/.idea/modules/prog8.iml" /> | ||||||
|  |       <module fileurl="file://$PROJECT_DIR$/simpleAst/simpleAst.iml" filepath="$PROJECT_DIR$/simpleAst/simpleAst.iml" /> | ||||||
|  |       <module fileurl="file://$PROJECT_DIR$/virtualmachine/virtualmachine.iml" filepath="$PROJECT_DIR$/virtualmachine/virtualmachine.iml" /> | ||||||
|     </modules> |     </modules> | ||||||
|   </component> |   </component> | ||||||
| </project> | </project> | ||||||
							
								
								
									
										27
									
								
								.readthedocs.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								.readthedocs.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | # .readthedocs.yaml | ||||||
|  | # Read the Docs configuration file | ||||||
|  | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details | ||||||
|  |  | ||||||
|  | # Required | ||||||
|  | version: 2 | ||||||
|  |  | ||||||
|  | # Set the version of Python and other tools you might need | ||||||
|  | build: | ||||||
|  |   os: ubuntu-22.04 | ||||||
|  |   tools: | ||||||
|  |     python: "3.12" | ||||||
|  |  | ||||||
|  | # Optionally declare the Python requirements required to build your docs | ||||||
|  | python: | ||||||
|  |   install: | ||||||
|  |     - requirements: docs/requirements.txt | ||||||
|  |  | ||||||
|  | # Build documentation in the docs/ directory with Sphinx | ||||||
|  | sphinx: | ||||||
|  |   configuration: docs/source/conf.py | ||||||
|  |   fail_on_warning: true | ||||||
|  |  | ||||||
|  | # If using Sphinx, optionally build your docs in additional formats such as PDF | ||||||
|  | formats: | ||||||
|  |   - pdf | ||||||
|  |   - epub | ||||||
							
								
								
									
										11
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								.travis.yml
									
									
									
									
									
								
							| @@ -1,11 +0,0 @@ | |||||||
| language: java |  | ||||||
| sudo: false |  | ||||||
| # jdk: openjdk8 |  | ||||||
| # dist: xenial |  | ||||||
|  |  | ||||||
| before_install: |  | ||||||
|   - chmod +x gradlew |  | ||||||
|  |  | ||||||
| script: |  | ||||||
|   - gradle test |  | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								LICENSE
									
									
									
									
									
								
							| @@ -1,3 +1,13 @@ | |||||||
|  |  | ||||||
|  | This sofware license is for Prog8 the compiler + associated library files. | ||||||
|  |  | ||||||
|  | Exception: All output files generated by the compiler (intermediary files | ||||||
|  | and compiled binary programs) are excluded from this; you can do with those | ||||||
|  | whatever you want. | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|                     GNU GENERAL PUBLIC LICENSE |                     GNU GENERAL PUBLIC LICENSE | ||||||
|                        Version 3, 29 June 2007 |                        Version 3, 29 June 2007 | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | # super simple Makefile to lauch the main gradle targets to build and/or test the prog8 compiler | ||||||
|  |  | ||||||
|  | .PHONY: all test | ||||||
|  |  | ||||||
|  | all: | ||||||
|  | 	gradle installdist installshadowdist | ||||||
|  | 	@echo "compiler launch script can be found here: compiler/build/install/compiler-shadow/bin/prog8c" | ||||||
|  |  | ||||||
|  | test: | ||||||
|  | 	gradle build | ||||||
|  | 	@echo "compiler launch script can be found here: compiler/build/install/compiler-shadow/bin/prog8c" | ||||||
|  |  | ||||||
							
								
								
									
										186
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										186
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,63 +1,126 @@ | |||||||
| [](https://saythanks.io/to/irmen) | [](https://ko-fi.com/H2H6S0FFF) | ||||||
| [](https://travis-ci.org/irmen/prog8) |  | ||||||
|  |  | ||||||
| Prog8 - Structured Programming Language for 8-bit 6502/6510 microprocessors | PayPal: [](https://paypal.me/irmendejong) | ||||||
| =========================================================================== |  | ||||||
|  | [](https://prog8.readthedocs.io/) | ||||||
|  |  | ||||||
|  | Prog8 - Structured Programming Language for 8-bit 6502/65c02 microprocessors | ||||||
|  | ============================================================================ | ||||||
|  |  | ||||||
| *Written by Irmen de Jong (irmen@razorvine.net)* | *Written by Irmen de Jong (irmen@razorvine.net)* | ||||||
|  |  | ||||||
| *Software license: GNU GPL 3.0, see file LICENSE* | This is a structured programming language for the 8-bit 6502/6510/65c02 microprocessor from the late 1970's and 1980's | ||||||
|  |  | ||||||
|  |  | ||||||
| This is a structured programming language for the 8-bit 6502/6510 microprocessor from the late 1970's and 1980's |  | ||||||
| as used in many home computers from that era. It is a medium to low level programming language, | as used in many home computers from that era. It is a medium to low level programming language, | ||||||
| which aims to provide many conveniences over raw assembly code (even when using a macro assembler): | which aims to provide many conveniences over raw assembly code (even when using a macro assembler). | ||||||
|  |  | ||||||
| - reduction of source code length | **Want to buy me a coffee or a pizza perhaps?** | ||||||
| - modularity, symbol scoping, subroutines |  | ||||||
|  | This project was created over the last couple of years by dedicating thousands of hours of my free time to it, to make it the best I possibly can. | ||||||
|  | If you like Prog8, and think it's worth a nice cup of hot coffee or a delicious pizza,  | ||||||
|  | you can help me out a little bit over at [ko-fi.com/irmen](https://ko-fi.com/irmen) or [PayPal](https://paypal.me/irmendejong) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Documentation | ||||||
|  | ------------- | ||||||
|  | Full documentation (syntax reference, how to use the language and the compiler, etc.) can be found at: | ||||||
|  | https://prog8.readthedocs.io/ | ||||||
|  |  | ||||||
|  | How to get it/build it | ||||||
|  | ---------------------- | ||||||
|  |  | ||||||
|  | - Download the latest [official release](https://github.com/irmen/prog8/releases) from github. | ||||||
|  | - Or, if you want/need a bleeding edge development version, you can: | ||||||
|  |   - download a build artifact zipfile from a recent [github action build](https://github.com/irmen/prog8/actions). | ||||||
|  |   - you can also compile it yourself from source. [Instructions here](https://prog8.readthedocs.io/en/latest/compiling.html). | ||||||
|  |     Note that if you are not using *gradle* to build it, you might have to perform some manual | ||||||
|  |     tasks once to make it compile fully. These are explained in the linked instructions.  | ||||||
|  | - Alternatively, you can also install the compiler as a package on some linux distros: | ||||||
|  |   - Arch (via AUR): [`prog8`](https://aur.archlinux.org/packages/prog8) | ||||||
|  |  | ||||||
|  | Community | ||||||
|  | --------- | ||||||
|  | Most of the development on Prog8 and the use of it is currently centered around  | ||||||
|  | the [Commander X16](https://www.commanderx16.com/) retro computer. Their [discord server](https://discord.gg/nS2PqEC) contains a small channel | ||||||
|  | dedicated to Prog8. Other than that, use the issue tracker on github. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Software license | ||||||
|  | ---------------- | ||||||
|  | GNU GPL 3.0 (see file LICENSE), with exception for generated code: | ||||||
|  |  | ||||||
|  | - The compiler and its libraries are free to use according to the terms of the GNU GPL 3.0 | ||||||
|  | - *exception:* the resulting files (intermediate source codes and resulting binary program) created by the compiler | ||||||
|  |   are excluded from the GPL and are free to use in whatever way desired, commercially or not. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | What does Prog8 provide? | ||||||
|  | ------------------------ | ||||||
|  |  | ||||||
|  | - all advantages of a higher level language over having to write assembly code manually | ||||||
|  | - programs run very fast because it's compiled to native machine code | ||||||
|  | - code often is smaller and faster than equivalent C code compiled with CC65 or even LLVM-MOS | ||||||
|  | - modularity, symbol scoping, subroutines. No need for forward declarations. | ||||||
| - various data types other than just bytes (16-bit words, floats, strings) | - various data types other than just bytes (16-bit words, floats, strings) | ||||||
| - automatic variable allocations, automatic string and array variables and string sharing | - Structs and typed pointers | ||||||
| - subroutines with a input- and output parameter signature | - floating point math is supported on certain targets | ||||||
| - constant folding in expressions | - access to most Kernal ROM routines as external subroutine definitions you can call normally | ||||||
| - conditional branches | - tight control over Zeropage usage | ||||||
| - 'when' statement to provide a concise jump table alternative to if/elseif chains | - programs can be run multiple times without reloading because of automatic variable (re)initializations. | ||||||
| - structs to group together sets of variables and manipulate them at once | - programs can be configured to execute in ROM | ||||||
| - floating point operations  (requires the C64 Basic ROM routines for this) | - strings can contain escaped characters but also many symbols directly if they have a petscii equivalent, such as "♠♥♣♦π▚●○╳". Characters like ^, _, \, {, } and | are also accepted and converted to the closest petscii equivalents. | ||||||
| - abstracting away low level aspects such as ZeroPage handling, program startup, explicit memory addresses | - automatic static variable allocations, automatic string and array variables and string sharing | ||||||
| - various code optimizations (code structure, logical and numerical expressions, unused code removal...) | - high-level program optimizations | ||||||
|  | - conditional branches that map 1:1 to cpu status flags | ||||||
|  | - ``when`` statement to provide a concise jump table alternative to if/elseif chains | ||||||
|  | - ``on .. goto`` statement for fast jump tables | ||||||
|  | - ``in`` expression for concise and efficient multi-value/containment check  | ||||||
|  | - ``defer`` statement to help write concise and robust subroutine cleanup logic | ||||||
|  | - several specialized built-in functions such as ``lsb``, ``msb``, ``min``, ``max``, ``rol``, ``ror`` | ||||||
|  | - various powerful built-in libraries to do I/O, number conversions, graphics and more   | ||||||
|  | - subroutines can return more than one result value | ||||||
| - inline assembly allows you to have full control when every cycle or byte matters | - inline assembly allows you to have full control when every cycle or byte matters | ||||||
| - many built-in functions such as ``sin``, ``cos``, ``rnd``, ``abs``, ``min``, ``max``, ``sqrt``, ``msb``, ``rol``, ``ror``, ``swap``, ``memset``, ``memcopy``, ``sort`` and ``reverse`` | - supports the sixteen 'virtual' 16-bit registers R0 - R15 from the Commander X16 (also available on other targets) | ||||||
|  | - encode strings and characters into petscii or screencodes or even other encodings | ||||||
|  | - Automatic ROM/RAM bank switching on certain compiler targets when calling routines in other banks | ||||||
|  | - 50 Kb of available program RAM size on the C64 by default; because Basic ROM is banked out altogether  | ||||||
|  |  | ||||||
| Rapid edit-compile-run-debug cycle: | *Rapid edit-compile-run-debug cycle:* | ||||||
|  |  | ||||||
| - use modern PC to work on | - use a modern PC to do the work on, use nice editors and enjoy quick compilation times | ||||||
| - quick compilation times (seconds) | - can automatically run the program in the Vice emulator after succesful compilation | ||||||
| - option to automatically run the program in the Vice emulator |  | ||||||
| - breakpoints, that let the Vice emulator drop into the monitor if execution hits them | - breakpoints, that let the Vice emulator drop into the monitor if execution hits them | ||||||
| - source code labels automatically loaded in Vice emulator so it can show them in disassembly | - source code labels automatically loaded in Vice emulator so it can show them in disassembly | ||||||
| - virtual machine that can execute compiled code directy on the host system, |  | ||||||
|   without having to actually convert it to assembly to run on a real 6502 |  | ||||||
|  |  | ||||||
| It is mainly targeted at the Commodore-64 machine at this time. | *Multiple supported compiler targets* (contributions to improve these or to add support for other machines are welcome!): | ||||||
| Contributions to add support for other 8-bit (or other?!) machines are welcome. |  | ||||||
|  |  | ||||||
| Documentation/manual | - "cx16": [CommanderX16](https://www.commanderx16.com)  (65c02 CPU) | ||||||
| -------------------- | - "c64": Commodore-64  (6502 like CPU) | ||||||
| This describes the language, but also how to build and run the compiler. See https://prog8.readthedocs.io/ | - "c128": Commodore-128  (6502 like CPU - the Z80 cpu mode is not supported) | ||||||
|  | - "pet32": Commodore PET (limited support) | ||||||
|  | - via external configurable targets: Atari 800 XL, Neo6502, NES, C64 OS, Foenix F256, ... | ||||||
|  | - If you only use standard kernal and prog8 library routines, it is possible to compile the *exact same program* for different machines (just change the compiler target flag) | ||||||
|  |  | ||||||
| Required tools |  | ||||||
| -------------- |  | ||||||
|  | Additional required tools | ||||||
|  | ------------------------- | ||||||
|  |  | ||||||
| [64tass](https://sourceforge.net/projects/tass64/) - cross assembler. Install this on your shell path. | [64tass](https://sourceforge.net/projects/tass64/) - cross assembler. Install this on your shell path. | ||||||
| A recent .exe version of this tool for Windows can be obtained from my [clone](https://github.com/irmen/64tass/releases) of this project. | A recent .exe version of this tool for Windows can be obtained from my [clone](https://github.com/irmen/64tass/releases) of this project. | ||||||
| For other platforms it is very easy to compile it yourself (make ; make install). | For other platforms it is very easy to compile it yourself (make ; make install). | ||||||
|  |  | ||||||
| A **Java runtime (jre or jdk), version 8 or newer**  is required to run a prepackaged version of the compiler. | A **Java runtime (jre or jdk), version 11 or newer**  is required to run a prepackaged version of the compiler. | ||||||
| If you want to build it from source, you'll need a Java SDK + Kotlin 1.3.x SDK (or for instance, | If you want to build it from source, you'll need a Java SDK + Kotlin 1.3.x SDK (or for instance, | ||||||
| IntelliJ IDEA with the Kotlin plugin). | IntelliJ IDEA with the Kotlin plugin). | ||||||
|  |  | ||||||
| It's handy to have a C-64 emulator or a real C-64 to run the programs on. The compiler assumes the presence | It's handy to have an emulator (or a real machine perhaps!) to run the programs on. The compiler assumes the presence | ||||||
| of the [Vice emulator](http://vice-emu.sourceforge.net/) | of the [Vice emulator](http://vice-emu.sourceforge.net/)  for the C64 target, | ||||||
|  | and a recent emulator version (R42 or newer) for the CommanderX16, such as [x16emu](https://cx16forum.com/forum/viewforum.php?f=30)  | ||||||
|  | (preferred, this is the official emulator. If required, source code is [here](https://github.com/X16Community/x16-emulator/)). | ||||||
|  | There is also [Box16](https://github.com/indigodarkwolf/box16) which has powerful debugging features. | ||||||
|  |  | ||||||
|  | **Syntax highlighting:** for a few different editors, syntax highlighting definition files are provided. | ||||||
|  | Look in the [syntax-files](https://github.com/irmen/prog8/tree/master/syntax-files) directory in the github repository to find them. | ||||||
|  |  | ||||||
|  |  | ||||||
| Example code | Example code | ||||||
| @@ -65,44 +128,42 @@ Example code | |||||||
|  |  | ||||||
| This code calculates prime numbers using the Sieve of Eratosthenes algorithm:: | This code calculates prime numbers using the Sieve of Eratosthenes algorithm:: | ||||||
|  |  | ||||||
|     %import c64utils |     %import textio | ||||||
|     %zeropage basicsafe |     %zeropage basicsafe | ||||||
|  |  | ||||||
|     main { |     main { | ||||||
|  |         bool[256] sieve | ||||||
|         ubyte[256] sieve |         ubyte candidate_prime = 2       ; is increased in the loop | ||||||
|         ubyte candidate_prime = 2 |  | ||||||
|      |      | ||||||
|         sub start() { |         sub start() { | ||||||
|             memset(sieve, 256, false) |             sys.memset(sieve, 256, 0)   ; clear the sieve | ||||||
|  |             txt.print("prime numbers up to 255:\n\n") | ||||||
|             c64scr.print("prime numbers up to 255:\n\n") |  | ||||||
|             ubyte amount=0 |             ubyte amount=0 | ||||||
|             while true { |             repeat { | ||||||
|                 ubyte prime = find_next_prime() |                 ubyte prime = find_next_prime() | ||||||
|                 if prime==0 |                 if prime==0 | ||||||
|                     break |                     break | ||||||
|                 c64scr.print_ub(prime) |                 txt.print_ub(prime) | ||||||
|                 c64scr.print(", ") |                 txt.print(", ") | ||||||
|                 amount++ |                 amount++ | ||||||
|             } |             } | ||||||
|             c64.CHROUT('\n') |             txt.nl() | ||||||
|             c64scr.print("number of primes (expected 54): ") |             txt.print("number of primes (expected 54): ") | ||||||
|             c64scr.print_ub(amount) |             txt.print_ub(amount) | ||||||
|             c64.CHROUT('\n') |             txt.nl() | ||||||
|         } |         } | ||||||
|      |      | ||||||
|  |  | ||||||
|         sub find_next_prime() -> ubyte { |         sub find_next_prime() -> ubyte { | ||||||
|  |  | ||||||
|             while sieve[candidate_prime] { |             while sieve[candidate_prime] { | ||||||
|                 candidate_prime++ |                 candidate_prime++ | ||||||
|                 if candidate_prime==0 |                 if candidate_prime==0 | ||||||
|                     return 0 |                     return 0        ; we wrapped; no more primes | ||||||
|             } |             } | ||||||
|      |      | ||||||
|  |             ; found next one, mark the multiples and return it. | ||||||
|             sieve[candidate_prime] = true |             sieve[candidate_prime] = true | ||||||
|             uword multiple = candidate_prime |             uword multiple = candidate_prime | ||||||
|  |      | ||||||
|             while multiple < len(sieve) { |             while multiple < len(sieve) { | ||||||
|                 sieve[lsb(multiple)] = true |                 sieve[lsb(multiple)] = true | ||||||
|                 multiple += candidate_prime |                 multiple += candidate_prime | ||||||
| @@ -111,12 +172,10 @@ This code calculates prime numbers using the Sieve of Eratosthenes algorithm:: | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
| when compiled an ran on a C-64 you'll get: | when compiled an ran on a C-64 you'll get: | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| One of the included examples (wizzine.p8) animates a bunch of sprite balloons and looks like this: | One of the included examples (wizzine.p8) animates a bunch of sprite balloons and looks like this: | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -128,3 +187,18 @@ Another example (cube3d-sprites.p8) draws the vertices of a rotating 3d cube: | |||||||
| If you want to play a video game, a fully working Tetris clone is included in the examples: | If you want to play a video game, a fully working Tetris clone is included in the examples: | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | There are a couple of examples specially made for the CommanderX16 compiler target. | ||||||
|  | For instance here's a well known space ship animated in 3D with hidden line removal, | ||||||
|  | in the CommanderX16 emulator: | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | Performance comparison with various C compilers | ||||||
|  | ----------------------------------------------- | ||||||
|  |  | ||||||
|  | Here is a performance comparison with various C compilers for the 6502/C64 so you can get | ||||||
|  | an idea of how Prog8 stacks up. | ||||||
|  |  | ||||||
|  | [comparison](benchmark-c/benchmark.md) | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								beanshell/beanshell.iml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								beanshell/beanshell.iml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <module type="JAVA_MODULE" version="4"> | ||||||
|  |   <component name="NewModuleRootManager" inherit-compiler-output="true"> | ||||||
|  |     <exclude-output /> | ||||||
|  |     <content url="file://$MODULE_DIR$"> | ||||||
|  |       <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> | ||||||
|  |       <excludeFolder url="file://$MODULE_DIR$/build" /> | ||||||
|  |     </content> | ||||||
|  |     <orderEntry type="inheritedJdk" /> | ||||||
|  |     <orderEntry type="sourceFolder" forTests="false" /> | ||||||
|  |     <orderEntry type="library" name="KotlinJavaRuntime" level="project" /> | ||||||
|  |     <orderEntry type="library" name="jetbrains.kotlinx.cli.jvm" level="project" /> | ||||||
|  |     <orderEntry type="library" name="michael.bull.kotlin.result.jvm" level="project" /> | ||||||
|  |     <orderEntry type="module-library"> | ||||||
|  |       <library> | ||||||
|  |         <CLASSES> | ||||||
|  |           <root url="jar://$MODULE_DIR$/lib/bsh-3.0.0-SNAPSHOT.jar!/" /> | ||||||
|  |         </CLASSES> | ||||||
|  |         <JAVADOC /> | ||||||
|  |         <SOURCES /> | ||||||
|  |       </library> | ||||||
|  |     </orderEntry> | ||||||
|  |   </component> | ||||||
|  | </module> | ||||||
							
								
								
									
										65
									
								
								beanshell/build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								beanshell/build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | |||||||
|  | import org.jetbrains.kotlin.gradle.dsl.JvmTarget | ||||||
|  |  | ||||||
|  | plugins { | ||||||
|  |     id("application") | ||||||
|  |     kotlin("jvm") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | val serverMainClassName = "prog8lsp.MainKt" | ||||||
|  | val applicationName = "prog8-beanshell" | ||||||
|  |  | ||||||
|  | application { | ||||||
|  |     mainClass.set(serverMainClassName) | ||||||
|  |     description = "Code completions, diagnostics and more for Prog8" | ||||||
|  |     // applicationDefaultJvmArgs = listOf("-DkotlinLanguageServer.version=$version") | ||||||
|  |     applicationDistribution.into("bin") { | ||||||
|  |         filePermissions { | ||||||
|  |             user { | ||||||
|  |                 read=true | ||||||
|  |                 execute=true | ||||||
|  |                 write=true | ||||||
|  |             } | ||||||
|  |             other.execute = true | ||||||
|  |             group.execute = true | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | repositories { | ||||||
|  |     mavenCentral() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | dependencies { | ||||||
|  |     implementation(files("lib/bsh-3.0.0-SNAPSHOT.jar")) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | configurations.forEach { config -> | ||||||
|  |     config.resolutionStrategy { | ||||||
|  |         preferProjectModules() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | sourceSets.main { | ||||||
|  |     java.srcDir("src") | ||||||
|  |     resources.srcDir("resources") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | tasks.startScripts { | ||||||
|  |     applicationName = "prog8-beanshell" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | tasks.register<Exec>("fixFilePermissions") { | ||||||
|  |     // When running on macOS or Linux the start script | ||||||
|  |     // needs executable permissions to run. | ||||||
|  |  | ||||||
|  |     onlyIf { !System.getProperty("os.name").lowercase().contains("windows") } | ||||||
|  |     commandLine("chmod", "+x", "${tasks.installDist.get().destinationDir}/bin/prog8-beanshell") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | tasks.installDist { | ||||||
|  |     finalizedBy("fixFilePermissions") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | tasks.build { | ||||||
|  |     finalizedBy("installDist") | ||||||
|  | } | ||||||
							
								
								
									
										
											BIN
										
									
								
								beanshell/lib/bsh-3.0.0-SNAPSHOT.jar
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								beanshell/lib/bsh-3.0.0-SNAPSHOT.jar
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										48
									
								
								beanshell/src/prog8beanshell/CommandLineReader.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								beanshell/src/prog8beanshell/CommandLineReader.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | package prog8beanshell | ||||||
|  |  | ||||||
|  | import java.io.FilterReader | ||||||
|  | import java.io.Reader | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class CommandLineReader(val input: Reader): FilterReader(input)  { | ||||||
|  |     private val normal = 0 | ||||||
|  |     private val lastCharNL = 1 | ||||||
|  |     private val sentSemi = 2 | ||||||
|  |     private var state = lastCharNL | ||||||
|  |  | ||||||
|  |     override fun read(): Int { | ||||||
|  |         if (state == sentSemi) { | ||||||
|  |             this.state = lastCharNL | ||||||
|  |             return 10 | ||||||
|  |         } else { | ||||||
|  |             var b = input.read() | ||||||
|  |             while(b==13) b = input.read() | ||||||
|  |  | ||||||
|  |             if (b == 10) { | ||||||
|  |                 if (this.state == lastCharNL) { | ||||||
|  |                     b = 59 | ||||||
|  |                     this.state = sentSemi | ||||||
|  |                 } else { | ||||||
|  |                     this.state = lastCharNL | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 this.state = normal | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return b | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun read(buff: CharArray, off: Int, len: Int): Int { | ||||||
|  |         val b = read() | ||||||
|  |         if (b == -1) { | ||||||
|  |             return -1 | ||||||
|  |         } else { | ||||||
|  |             buff[off] = b.toChar() | ||||||
|  |             return 1 | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										23
									
								
								beanshell/src/prog8beanshell/Main.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								beanshell/src/prog8beanshell/Main.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | package prog8beanshell | ||||||
|  |  | ||||||
|  | import bsh.FileReader | ||||||
|  | import bsh.Interpreter | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class BeanshellInterpreter { | ||||||
|  |  | ||||||
|  |     fun run(symbols: Map<String, Any>) { | ||||||
|  |         val interpreter = Interpreter(CommandLineReader(FileReader(System.`in`)), System.out, System.err, true) | ||||||
|  |         interpreter.setExitOnEOF(false) | ||||||
|  |         symbols.forEach { (name, value) -> interpreter.set(name, value) } | ||||||
|  |         interpreter.run() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fun main(args: Array<String>) { | ||||||
|  |     val i = BeanshellInterpreter() | ||||||
|  |     i.run(mapOf( | ||||||
|  |         "env" to System.getenv(), | ||||||
|  |         "args" to args | ||||||
|  |     )) | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								benchmark-c/benchmark.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								benchmark-c/benchmark.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | # C-Bench-64 comparison | ||||||
|  |  | ||||||
|  | Several benchmarks of https://thred.github.io/c-bench-64/ | ||||||
|  | have been ported to equivalent Prog8 code and the benchmark results have been penciled in in the graphs below. | ||||||
|  |  | ||||||
|  | Maybe one day I'll try to integrate the prog8 data properly but their benchmark site is comparing C compilers, which Prog8 clearly is not. | ||||||
|  |  | ||||||
|  | However conclusions so far (note: these are micro benchmarks so interpret the results as you will!) | ||||||
|  |  | ||||||
|  | * Prog8 program size is consistently the smallest by a fair bit. | ||||||
|  | * Prog8 execution speed places it more or less in the middle of the stack. | ||||||
|  |  | ||||||
|  | Measured with Prog8 V12.0 . | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										71
									
								
								benchmark-c/crc16.p8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								benchmark-c/crc16.p8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | |||||||
|  | %import textio | ||||||
|  | %import floats | ||||||
|  |  | ||||||
|  | ; note: Prog8 has a complete CRC16 routine in its library: math.crc16 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | main { | ||||||
|  |     sub start() { | ||||||
|  |         txt.lowercase() | ||||||
|  |         test.benchmark_name() | ||||||
|  |         cbm.SETTIM(0,0,0) | ||||||
|  |         test.benchmark() | ||||||
|  |         txt.print_f(floats.time() / 60) | ||||||
|  |         txt.print(" seconds\n") | ||||||
|  |         void test.benchmark_check() | ||||||
|  |         repeat {} | ||||||
|  |     }     | ||||||
|  | } | ||||||
|  |  | ||||||
|  | test { | ||||||
|  |  | ||||||
|  |     const uword EXPECTED = $ffd0 | ||||||
|  |     uword crc_result | ||||||
|  |  | ||||||
|  |     sub benchmark_name() | ||||||
|  |     { | ||||||
|  |         txt.print("crc16.p8\n") | ||||||
|  |         txt.print("Calculates the CRC16 of the C64 Kernal\n") | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub benchmark() | ||||||
|  |     { | ||||||
|  |         crc_result = CRC16($e000, $2000) | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     sub benchmark_check() -> bool | ||||||
|  |     { | ||||||
|  |         txt.print("CRC=") | ||||||
|  |         txt.print_uwhex(crc_result, true) | ||||||
|  |  | ||||||
|  |         if crc_result == EXPECTED | ||||||
|  |         { | ||||||
|  |             txt.print(" [OK]") | ||||||
|  |             return false | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         txt.print(" [FAIL] - expected ") | ||||||
|  |         txt.print_uwhex(EXPECTED, true) | ||||||
|  |         return true | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     sub CRC16(^^ubyte data, uword length) -> uword { | ||||||
|  |         ; CRC-16/XMODEM | ||||||
|  |         uword crc | ||||||
|  |  | ||||||
|  |         repeat length | ||||||
|  |         { | ||||||
|  |             crc ^= mkword(@(data),0)     ; currently there's no easy way to affect only the MSB of the variable | ||||||
|  |  | ||||||
|  |             repeat 8 | ||||||
|  |             { | ||||||
|  |                 crc <<=1 | ||||||
|  |                 if_cs | ||||||
|  |                     crc ^= $1021 | ||||||
|  |             } | ||||||
|  |             data++ | ||||||
|  |         } | ||||||
|  |         return crc | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										72
									
								
								benchmark-c/crc32.p8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								benchmark-c/crc32.p8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | |||||||
|  | %import textio | ||||||
|  | %import floats | ||||||
|  |  | ||||||
|  | ; note: Prog8 has a complete CRC32 routine in its library: math.crc32 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | main { | ||||||
|  |     sub start() { | ||||||
|  |         txt.lowercase() | ||||||
|  |         test.benchmark_name() | ||||||
|  |         cbm.SETTIM(0,0,0) | ||||||
|  |         test.benchmark() | ||||||
|  |         txt.print_f(floats.time() / 60) | ||||||
|  |         txt.print(" seconds\n") | ||||||
|  |         void test.benchmark_check() | ||||||
|  |         repeat {} | ||||||
|  |     }     | ||||||
|  | } | ||||||
|  |  | ||||||
|  | test { | ||||||
|  |  | ||||||
|  |     const long EXPECTED = $e1fa84c6 | ||||||
|  |     long crc_result | ||||||
|  |  | ||||||
|  |     sub benchmark_name() | ||||||
|  |     { | ||||||
|  |         txt.print("crc32.p8\n") | ||||||
|  |         txt.print("Calculates the CRC32 of the C64 Kernal\n") | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub benchmark() | ||||||
|  |     { | ||||||
|  |         crc_result = CRC32($e000, $2000) | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     sub benchmark_check() -> bool | ||||||
|  |     { | ||||||
|  |         txt.print("CRC=") | ||||||
|  |         txt.print_ulhex(crc_result, true) | ||||||
|  |  | ||||||
|  |         if crc_result == EXPECTED | ||||||
|  |         { | ||||||
|  |             txt.print(" [OK]") | ||||||
|  |             return false | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         txt.print(" [FAIL] - expected ") | ||||||
|  |         txt.print_ulhex(EXPECTED, true) | ||||||
|  |         return true | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     sub CRC32(^^ubyte data, uword length) -> long { | ||||||
|  |         ; CRC-32/CKSUM | ||||||
|  |         long crc | ||||||
|  |  | ||||||
|  |         repeat length | ||||||
|  |         { | ||||||
|  |             crc ^= (@(data) as long)<<24     ; currently there's no easy way to affect only the MSB of the variable | ||||||
|  |  | ||||||
|  |             repeat 8 | ||||||
|  |             { | ||||||
|  |                 crc <<=1 | ||||||
|  |                 if_cs | ||||||
|  |                     crc ^= $04c11db7 | ||||||
|  |             } | ||||||
|  |             data++ | ||||||
|  |         } | ||||||
|  |         crc ^= $ffffffff | ||||||
|  |         return crc | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										72
									
								
								benchmark-c/crc8.p8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								benchmark-c/crc8.p8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | |||||||
|  | %import textio | ||||||
|  | %import floats | ||||||
|  |  | ||||||
|  |  | ||||||
|  | main { | ||||||
|  |     sub start() { | ||||||
|  |         txt.lowercase() | ||||||
|  |         test.benchmark_name() | ||||||
|  |         cbm.SETTIM(0,0,0) | ||||||
|  |         test.benchmark() | ||||||
|  |         txt.print_f(floats.time() / 60) | ||||||
|  |         txt.print(" seconds\n") | ||||||
|  |         void test.benchmark_check() | ||||||
|  |         repeat {} | ||||||
|  |     }     | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | test { | ||||||
|  |  | ||||||
|  |     sub benchmark_name() | ||||||
|  |     { | ||||||
|  |         txt.print("crc8.p8\n") | ||||||
|  |         txt.print("Calculates the CRC8 of the C64 Kernal\n") | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub benchmark() | ||||||
|  |     { | ||||||
|  |         crc_result = CRC8($e000, $2000) | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     sub benchmark_check() -> bool | ||||||
|  |     { | ||||||
|  |         txt.print("CRC=") | ||||||
|  |         txt.print_ubhex(crc_result, true) | ||||||
|  |  | ||||||
|  |         if crc_result == EXPECTED | ||||||
|  |         { | ||||||
|  |             txt.print(" [OK]") | ||||||
|  |             return false | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         txt.print(" [FAIL] - expected ") | ||||||
|  |         txt.print_ubhex(EXPECTED, true) | ||||||
|  |         return true | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |  | ||||||
|  |     const ubyte EXPECTED = $a2 | ||||||
|  |     ubyte crc_result | ||||||
|  |  | ||||||
|  |     sub CRC8(^^ubyte data, uword length) -> ubyte | ||||||
|  |     { | ||||||
|  |         ; CRC-8/GSM-A | ||||||
|  |         ubyte crc | ||||||
|  |  | ||||||
|  |         repeat length | ||||||
|  |         { | ||||||
|  |             crc ^= @(data) | ||||||
|  |  | ||||||
|  |             repeat 8 | ||||||
|  |             { | ||||||
|  |                 if (crc & $80) != 0 | ||||||
|  |                     crc = (crc << 1) ^ $1d | ||||||
|  |                 else | ||||||
|  |                     crc <<= 1 | ||||||
|  |             } | ||||||
|  |             data++ | ||||||
|  |         } | ||||||
|  |         return crc | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										93
									
								
								benchmark-c/pow.p8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								benchmark-c/pow.p8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | |||||||
|  | %import textio | ||||||
|  | %import floats | ||||||
|  |  | ||||||
|  |  | ||||||
|  | main { | ||||||
|  |     sub start() { | ||||||
|  |         txt.lowercase() | ||||||
|  |         test.benchmark_name() | ||||||
|  |         cbm.SETTIM(0,0,0) | ||||||
|  |         test.benchmark() | ||||||
|  |         txt.print_f(floats.time() / 60) | ||||||
|  |         txt.print(" seconds\n") | ||||||
|  |         void test.benchmark_check() | ||||||
|  |         repeat {} | ||||||
|  |     }     | ||||||
|  | } | ||||||
|  |  | ||||||
|  | test { | ||||||
|  |  | ||||||
|  |     const ubyte N_ITER = 10 | ||||||
|  |     const ubyte SIZE = 32 | ||||||
|  |     float[SIZE] array | ||||||
|  |  | ||||||
|  |     const float expected = 3614007361536.000000 | ||||||
|  |     const float epsilon = 10000000 | ||||||
|  |     float res | ||||||
|  |  | ||||||
|  |     sub benchmark_name() | ||||||
|  |     { | ||||||
|  |         txt.print("pow.p8\n") | ||||||
|  |         txt.print("Calculates floating point exponential (") | ||||||
|  |         txt.print_uw(N_ITER) | ||||||
|  |         txt.print(" iterations)\n") | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub benchmark() | ||||||
|  |     { | ||||||
|  |         ubyte i,j | ||||||
|  |         res = 0 | ||||||
|  |          | ||||||
|  |         for j in 0 to SIZE-1 { | ||||||
|  |             array[j]=0 | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         for i in 0 to N_ITER-1 { | ||||||
|  |             for j in 0 to SIZE-1 { | ||||||
|  |                 array[j] += testpow(2.5 / ((i + 1) as float), j) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         for j in 0 to SIZE-1 { | ||||||
|  |             res += array[j] | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub testpow(float x, ubyte y) -> float | ||||||
|  |     { | ||||||
|  |         float tmp = x | ||||||
|  |      | ||||||
|  |         if y == 0 | ||||||
|  |             return 1 | ||||||
|  |      | ||||||
|  |         repeat y-1 | ||||||
|  |             tmp *= x | ||||||
|  |      | ||||||
|  |         return tmp | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     sub benchmark_check() -> bool | ||||||
|  |     { | ||||||
|  |         txt.print("res      = ") | ||||||
|  |         txt.print_f(res) | ||||||
|  |         float diff = expected - res; | ||||||
|  |         txt.print("\nexpected = ") | ||||||
|  |         txt.print_f(expected) | ||||||
|  |         txt.print("\nepsilon  = ") | ||||||
|  |         txt.print_f(epsilon) | ||||||
|  |         txt.print("\ndiff     = ") | ||||||
|  |         txt.print_f(diff) | ||||||
|  |  | ||||||
|  |         if (diff < epsilon and diff > -epsilon) | ||||||
|  |         { | ||||||
|  |             txt.print(" [OK]\n") | ||||||
|  |             return false | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         txt.print("[FAIL]\n") | ||||||
|  |         return true | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										
											BIN
										
									
								
								benchmark-c/result-crc16.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								benchmark-c/result-crc16.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 78 KiB | 
							
								
								
									
										
											BIN
										
									
								
								benchmark-c/result-crc32.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								benchmark-c/result-crc32.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 80 KiB | 
							
								
								
									
										
											BIN
										
									
								
								benchmark-c/result-crc8.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								benchmark-c/result-crc8.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 79 KiB | 
							
								
								
									
										
											BIN
										
									
								
								benchmark-c/result-pow.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								benchmark-c/result-pow.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 74 KiB | 
							
								
								
									
										
											BIN
										
									
								
								benchmark-c/result-sieve-bit.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								benchmark-c/result-sieve-bit.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 85 KiB | 
							
								
								
									
										
											BIN
										
									
								
								benchmark-c/result-sieve.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								benchmark-c/result-sieve.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 82 KiB | 
							
								
								
									
										85
									
								
								benchmark-c/sieve.p8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								benchmark-c/sieve.p8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | |||||||
|  | %import textio | ||||||
|  | %import floats | ||||||
|  |  | ||||||
|  |  | ||||||
|  | main { | ||||||
|  |     sub start() { | ||||||
|  |         txt.lowercase() | ||||||
|  |         test.benchmark_name() | ||||||
|  |         cbm.SETTIM(0,0,0) | ||||||
|  |         test.benchmark() | ||||||
|  |         txt.print_f(floats.time() / 60) | ||||||
|  |         txt.print(" seconds\n") | ||||||
|  |         void test.benchmark_check() | ||||||
|  |         repeat {} | ||||||
|  |     }     | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | test { | ||||||
|  |     const ubyte N_ITER = 10 | ||||||
|  |     const uword SIZE = 8191 | ||||||
|  |     const uword EXPECTED = 1900 | ||||||
|  |     uword prime_count | ||||||
|  |     ^^bool @zp flags = memory("flags", SIZE, 0) | ||||||
|  |  | ||||||
|  |     sub benchmark_name() | ||||||
|  |     { | ||||||
|  |         txt.print("sieve.c\n") | ||||||
|  |         txt.print("Calculates the primes from 1 to ") | ||||||
|  |         txt.print_uw(SIZE * 2 + 2) | ||||||
|  |         txt.print(" (") | ||||||
|  |         txt.print_ub(N_ITER) | ||||||
|  |         txt.print(" iterations)\n") | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub benchmark() | ||||||
|  |     { | ||||||
|  |         repeat N_ITER | ||||||
|  |             prime_count = sieve(SIZE) | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     sub benchmark_check() -> bool | ||||||
|  |     { | ||||||
|  |         txt.print("count=") | ||||||
|  |         txt.print_uw(prime_count) | ||||||
|  |  | ||||||
|  |         if prime_count == EXPECTED | ||||||
|  |         { | ||||||
|  |             txt.print(" [OK]") | ||||||
|  |             return false | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         txt.print(" [FAIL] - expected ") | ||||||
|  |         txt.print_uw(EXPECTED) | ||||||
|  |         return true | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |      | ||||||
|  |     sub sieve(uword size) -> uword  | ||||||
|  |     { | ||||||
|  |         uword i, prime, k | ||||||
|  |         uword count = 1 | ||||||
|  |  | ||||||
|  |         for i in 0 to size-1 | ||||||
|  |             flags[i] = true | ||||||
|  |  | ||||||
|  |         for i in 0 to size-1  | ||||||
|  |         { | ||||||
|  |             if flags[i] | ||||||
|  |             { | ||||||
|  |                 prime = i + i + 3 | ||||||
|  |                 k = i + prime | ||||||
|  |                 while k < size | ||||||
|  |                 { | ||||||
|  |                     flags[k] = false | ||||||
|  |                     k += prime | ||||||
|  |                 } | ||||||
|  |                 count++ | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |      | ||||||
|  |         return count | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										107
									
								
								benchmark-c/sieve_bit.p8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								benchmark-c/sieve_bit.p8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,107 @@ | |||||||
|  | %import textio | ||||||
|  | %import floats | ||||||
|  |  | ||||||
|  |  | ||||||
|  | main { | ||||||
|  |     sub start() { | ||||||
|  |         txt.lowercase() | ||||||
|  |         test.benchmark_name() | ||||||
|  |         cbm.SETTIM(0,0,0) | ||||||
|  |         test.benchmark() | ||||||
|  |         txt.print_f(floats.time() / 60) | ||||||
|  |         txt.print(" seconds\n") | ||||||
|  |         void test.benchmark_check() | ||||||
|  |         repeat {} | ||||||
|  |     }     | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | test { | ||||||
|  |     const ubyte N_ITER = 4 | ||||||
|  |     const uword SIZE = 16000 | ||||||
|  |     const uword EXPECTED = 3432 | ||||||
|  |     uword prime_count | ||||||
|  |     ^^ubyte @zp flags = memory("flags", SIZE/8+1, 0) | ||||||
|  |  | ||||||
|  |     sub benchmark_name() | ||||||
|  |     { | ||||||
|  |         txt.print("sieve_bit.p8\n") | ||||||
|  |         txt.print("Calculates the primes from 1 to ") | ||||||
|  |         txt.print_uw(SIZE * 2 + 2) | ||||||
|  |         txt.print(" (") | ||||||
|  |         txt.print_ub(N_ITER) | ||||||
|  |         txt.print(" iterations)\n") | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub benchmark() | ||||||
|  |     { | ||||||
|  |         repeat N_ITER | ||||||
|  |             prime_count = sieve(SIZE) | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     sub benchmark_check() -> bool | ||||||
|  |     { | ||||||
|  |         txt.print("count=") | ||||||
|  |         txt.print_uw(prime_count) | ||||||
|  |  | ||||||
|  |         if prime_count == EXPECTED | ||||||
|  |         { | ||||||
|  |             txt.print(" [OK]") | ||||||
|  |             return false | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         txt.print(" [FAIL] - expected ") | ||||||
|  |         txt.print_uw(EXPECTED) | ||||||
|  |         return true | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ubyte[] bitv = [ | ||||||
|  |         $01,     | ||||||
|  |         $02, | ||||||
|  |         $04, | ||||||
|  |         $08, | ||||||
|  |         $10, | ||||||
|  |         $20, | ||||||
|  |         $40, | ||||||
|  |         $80 | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     sub check_flag(uword idx) -> bool | ||||||
|  |     { | ||||||
|  |         return flags[idx / 8] & bitv[lsb(idx) & 7] != 0 | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub clear_flag(uword idx) | ||||||
|  |     { | ||||||
|  |         flags[idx / 8] &= ~(bitv[lsb(idx) & 7]) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |      | ||||||
|  |     sub sieve(uword size) -> uword  | ||||||
|  |     { | ||||||
|  |         uword i, prime, k | ||||||
|  |         uword count=1 | ||||||
|  |      | ||||||
|  |         for i in 0 to (size / 8) | ||||||
|  |             flags[i] = $ff | ||||||
|  |  | ||||||
|  |         for i in 0 to size-1 | ||||||
|  |         { | ||||||
|  |             if check_flag(i) | ||||||
|  |             { | ||||||
|  |                 prime = i + i + 3 | ||||||
|  |                 k = i + prime; | ||||||
|  |                 while k < size | ||||||
|  |                 { | ||||||
|  |                     clear_flag(k) | ||||||
|  |                     k += prime | ||||||
|  |                 } | ||||||
|  |                 count++ | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     | ||||||
|  |         return count | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										10
									
								
								benchmark-program/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								benchmark-program/Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | .PHONY:  clean run | ||||||
|  |  | ||||||
|  | run: | ||||||
|  | 	prog8c -target cx16 benchmark.p8 | ||||||
|  | 	x16emu -run -prg benchmark.prg -warp | ||||||
|  |  | ||||||
|  | clean: | ||||||
|  | 	rm -f *.prg *.PRG *.asm *.vice-* *.BIN *.PAL *.zip *.7z | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										109
									
								
								benchmark-program/b_3d.p8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								benchmark-program/b_3d.p8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,109 @@ | |||||||
|  | %import textio | ||||||
|  | %import math | ||||||
|  |  | ||||||
|  | rotate3d { | ||||||
|  |     const ubyte WIDTH = 40 | ||||||
|  |     const ubyte HEIGHT = 30 | ||||||
|  |  | ||||||
|  |     sub benchmark(uword max_time) -> uword { | ||||||
|  |  | ||||||
|  |         uword anglex | ||||||
|  |         uword angley | ||||||
|  |         uword anglez | ||||||
|  |         uword frames | ||||||
|  |  | ||||||
|  |         txt.nl() | ||||||
|  |         cbm.SETTIM(0,0,0) | ||||||
|  |  | ||||||
|  |         while cbm.RDTIM16()<max_time { | ||||||
|  |             matrix_math.rotate_vertices(msb(anglex), msb(angley), msb(anglez)) | ||||||
|  |             draw_edges()   ; doesn't really draw anything in the benchmark, but does do the screen calculations | ||||||
|  |             anglex+=500 | ||||||
|  |             angley+=215 | ||||||
|  |             anglez+=453 | ||||||
|  |             frames++ | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return frames | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub draw_edges() { | ||||||
|  |  | ||||||
|  |         ; plot the points of the 3d cube | ||||||
|  |         ; first the points on the back, then the points on the front (painter algorithm) | ||||||
|  |  | ||||||
|  |         ubyte @zp i | ||||||
|  |         word @zp rz | ||||||
|  |         word @zp persp | ||||||
|  |         byte @shared sx | ||||||
|  |         byte @shared sy | ||||||
|  |  | ||||||
|  |         for i in 0 to len(matrix_math.xcoor)-1 { | ||||||
|  |             rz = matrix_math.rotatedz[i] | ||||||
|  |             if rz >= 10 { | ||||||
|  |                 persp = 600 + rz/64 | ||||||
|  |                 sx = matrix_math.rotatedx[i] / persp as byte + WIDTH/2 | ||||||
|  |                 sy = matrix_math.rotatedy[i] / persp as byte + HEIGHT/2 | ||||||
|  |                 ;; txt.setcc(sx as ubyte, sy as ubyte, 46, 7) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         for i in 0 to len(matrix_math.xcoor)-1 { | ||||||
|  |             rz = matrix_math.rotatedz[i] | ||||||
|  |             if rz < 10 { | ||||||
|  |                 persp = 600 + rz/64 | ||||||
|  |                 sx = matrix_math.rotatedx[i] / persp as byte + WIDTH/2 | ||||||
|  |                 sy = matrix_math.rotatedy[i] / persp as byte + HEIGHT/2 | ||||||
|  |                 ;; txt.setcc(sx as ubyte, sy as ubyte, 81, 7) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         txt.chrout('.') | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | matrix_math { | ||||||
|  |     ; vertices | ||||||
|  |     word[] xcoor = [ -40, -40, -40, -40,  40,  40,  40, 40 ] | ||||||
|  |     word[] ycoor = [ -40, -40,  40,  40, -40, -40,  40, 40 ] | ||||||
|  |     word[] zcoor = [ -40,  40, -40,  40, -40,  40, -40, 40 ] | ||||||
|  |  | ||||||
|  |     ; storage for rotated coordinates | ||||||
|  |     word[len(xcoor)] rotatedx | ||||||
|  |     word[len(ycoor)] rotatedy | ||||||
|  |     word[len(zcoor)] rotatedz | ||||||
|  |  | ||||||
|  |     sub rotate_vertices(ubyte ax, ubyte ay, ubyte az) { | ||||||
|  |         ; rotate around origin (0,0,0) | ||||||
|  |  | ||||||
|  |         ; set up the 3d rotation matrix values | ||||||
|  |         word wcosa = math.cos8(ax) | ||||||
|  |         word wsina = math.sin8(ax) | ||||||
|  |         word wcosb = math.cos8(ay) | ||||||
|  |         word wsinb = math.sin8(ay) | ||||||
|  |         word wcosc = math.cos8(az) | ||||||
|  |         word wsinc = math.sin8(az) | ||||||
|  |  | ||||||
|  |         word wcosa_sinb = wcosa*wsinb / 128 | ||||||
|  |         word wsina_sinb = wsina*wsinb / 128 | ||||||
|  |  | ||||||
|  |         word Axx = wcosa*wcosb / 128 | ||||||
|  |         word Axy = (wcosa_sinb*wsinc - wsina*wcosc) / 128 | ||||||
|  |         word Axz = (wcosa_sinb*wcosc + wsina*wsinc) / 128 | ||||||
|  |         word Ayx = wsina*wcosb / 128 | ||||||
|  |         word Ayy = (wsina_sinb*wsinc + wcosa*wcosc) / 128 | ||||||
|  |         word Ayz = (wsina_sinb*wcosc - wcosa*wsinc) / 128 | ||||||
|  |         word Azx = -wsinb | ||||||
|  |         word Azy = wcosb*wsinc / 128 | ||||||
|  |         word Azz = wcosb*wcosc / 128 | ||||||
|  |  | ||||||
|  |         ubyte @zp i | ||||||
|  |         for i in 0 to len(xcoor)-1 { | ||||||
|  |             ; don't normalize by dividing by 128, instead keep some precision for perspective calc later | ||||||
|  |             rotatedx[i] = Axx*xcoor[i] + Axy*ycoor[i] + Axz*zcoor[i] | ||||||
|  |             rotatedy[i] = Ayx*xcoor[i] + Ayy*ycoor[i] + Ayz*zcoor[i] | ||||||
|  |             rotatedz[i] = Azx*xcoor[i] + Azy*ycoor[i] + Azz*zcoor[i] | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										89
									
								
								benchmark-program/b_adpcm.p8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								benchmark-program/b_adpcm.p8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | |||||||
|  | adpcm { | ||||||
|  |  | ||||||
|  |     sub decode_benchmark(uword max_time) -> uword { | ||||||
|  |         uword num_blocks | ||||||
|  |         txt.nl() | ||||||
|  |         cbm.SETTIM(0,0,0) | ||||||
|  |  | ||||||
|  |         while cbm.RDTIM16()<max_time { | ||||||
|  |             adpcm.init(0,0) | ||||||
|  |             uword @requirezp nibbles_ptr = $a000 ; for benchmark purposes, the exact nibbles don't really matter, so we just take the basic ROM as input | ||||||
|  |             repeat 252/2 { | ||||||
|  |                 unroll 2 { | ||||||
|  |                     ubyte @zp nibble = @(nibbles_ptr) | ||||||
|  |                     adpcm.decode_nibble(nibble & 15)     ; first word  (note: upper nibble needs to be zero!) | ||||||
|  |                     adpcm.decode_nibble(nibble>>4)       ; second word  (note: upper nibble is zero, after the shifts.) | ||||||
|  |                     nibbles_ptr++ | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             num_blocks++ | ||||||
|  |             txt.chrout('.') | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return num_blocks | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ; IMA ADPCM decoder.  Supports mono and stereo streams. | ||||||
|  |  | ||||||
|  |     byte[] t_index = [ -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8] | ||||||
|  |     uword[] t_step = [ | ||||||
|  |             7, 8, 9, 10, 11, 12, 13, 14, | ||||||
|  |             16, 17, 19, 21, 23, 25, 28, 31, | ||||||
|  |             34, 37, 41, 45, 50, 55, 60, 66, | ||||||
|  |             73, 80, 88, 97, 107, 118, 130, 143, | ||||||
|  |             157, 173, 190, 209, 230, 253, 279, 307, | ||||||
|  |             337, 371, 408, 449, 494, 544, 598, 658, | ||||||
|  |             724, 796, 876, 963, 1060, 1166, 1282, 1411, | ||||||
|  |             1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, | ||||||
|  |             3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, | ||||||
|  |             7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, | ||||||
|  |             15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, | ||||||
|  |             32767] | ||||||
|  |  | ||||||
|  |     uword @requirezp predict       ; decoded 16 bit pcm sample for first channel. | ||||||
|  |     ubyte @requirezp index | ||||||
|  |     uword @requirezp pstep | ||||||
|  |  | ||||||
|  |     sub init(uword startPredict, ubyte startIndex) { | ||||||
|  |         ; initialize first decoding channel. | ||||||
|  |         predict = startPredict | ||||||
|  |         index = startIndex | ||||||
|  |         pstep = t_step[index] | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub decode_nibble(ubyte @zp nibble) { | ||||||
|  |         ; Decoder for a single nibble for the first channel. (value of 'nibble' needs to be strictly 0-15 !) | ||||||
|  |         ; This is the hotspot of the decoder algorithm! | ||||||
|  |         ; Note that the generated assembly from this is pretty efficient, | ||||||
|  |         ; rewriting it by hand in asm seems to improve it only ~10%. | ||||||
|  |         cx16.r0s = 0                ; difference | ||||||
|  |         if nibble & %0100 !=0 | ||||||
|  |             cx16.r0s += pstep | ||||||
|  |         pstep >>= 1 | ||||||
|  |         if nibble & %0010 !=0 | ||||||
|  |             cx16.r0s += pstep | ||||||
|  |         pstep >>= 1 | ||||||
|  |         if nibble & %0001 !=0 | ||||||
|  |             cx16.r0s += pstep | ||||||
|  |         pstep >>= 1 | ||||||
|  |         cx16.r0s += pstep | ||||||
|  |         if nibble & %1000 !=0 | ||||||
|  |             predict -= cx16.r0 | ||||||
|  |         else | ||||||
|  |             predict += cx16.r0 | ||||||
|  |  | ||||||
|  |         ; NOTE: the original C/Python code uses a 32 bits prediction value and clips it to a 16 bit word | ||||||
|  |         ;       but for speed reasons we only work with 16 bit words here all the time (with possible clipping error) | ||||||
|  |         ; if predicted > 32767: | ||||||
|  |         ;    predicted = 32767 | ||||||
|  |         ; elif predicted < -32767: | ||||||
|  |         ;    predicted = - 32767 | ||||||
|  |  | ||||||
|  |         index += t_index[nibble] as ubyte | ||||||
|  |         if_neg | ||||||
|  |             index = 0 | ||||||
|  |         else if index >= len(t_step)-1 | ||||||
|  |             index = len(t_step)-1 | ||||||
|  |         pstep = t_step[index] | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										234
									
								
								benchmark-program/b_btree.p8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								benchmark-program/b_btree.p8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,234 @@ | |||||||
|  | ; Binary Search Tree. | ||||||
|  | ; It's a simple implementation for test/demonstration purposes of the pointer support; | ||||||
|  | ; no balancing is done and memory is not freed when elements are removed. | ||||||
|  |  | ||||||
|  | %import textio | ||||||
|  |  | ||||||
|  | btree { | ||||||
|  |  | ||||||
|  |     sub benchmark(uword max_time) -> uword { | ||||||
|  |         txt.nl() | ||||||
|  |         cbm.SETTIM(0,0,0) | ||||||
|  |         uword score | ||||||
|  |         while cbm.RDTIM16() < max_time { | ||||||
|  |             bench_operations() | ||||||
|  |             txt.chrout('.') | ||||||
|  |             score++ | ||||||
|  |         } | ||||||
|  |         txt.nl() | ||||||
|  |         return score | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub bench_operations() { | ||||||
|  |         arena.freeall() | ||||||
|  |         btree.root = 0 | ||||||
|  |  | ||||||
|  |         for cx16.r0 in [321, 719, 194, 550, 187, 203, 520, 562, 221, 676, 97, 852, 273, 326, 589, 606, 275, 794, 63, 716] | ||||||
|  |             btree.add(cx16.r0) | ||||||
|  |  | ||||||
|  |         cx16.r0L = btree.size() | ||||||
|  |         btree.process_tree_inorder() | ||||||
|  |         btree.process_tree_preorder() | ||||||
|  |  | ||||||
|  |         void btree.contains(203) | ||||||
|  |         void btree.contains(204) | ||||||
|  |         void btree.contains(605) | ||||||
|  |         void btree.contains(606) | ||||||
|  |  | ||||||
|  |         btree.remove(9999) | ||||||
|  |         btree.remove(97) | ||||||
|  |         btree.remove(187) | ||||||
|  |         btree.remove(203) | ||||||
|  |         btree.remove(275) | ||||||
|  |         btree.remove(321) | ||||||
|  |         btree.remove(520) | ||||||
|  |         btree.remove(562) | ||||||
|  |         btree.remove(606) | ||||||
|  |         btree.remove(719) | ||||||
|  |         btree.remove(794) | ||||||
|  |  | ||||||
|  |         cx16.r0L = btree.size() | ||||||
|  |         btree.process_tree_inorder() | ||||||
|  |         btree.process_tree_preorder() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     struct Node { | ||||||
|  |         ^^Node left | ||||||
|  |         ^^Node right | ||||||
|  |         uword value | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ^^Node root = 0 | ||||||
|  |  | ||||||
|  |     sub add(uword value) { | ||||||
|  |         ^^Node node = arena.alloc(sizeof(Node)) | ||||||
|  |         node.value = value | ||||||
|  |         node.left = node.right = 0 | ||||||
|  |  | ||||||
|  |         if root==0 | ||||||
|  |             root=node | ||||||
|  |         else { | ||||||
|  |             ^^Node parent = root | ||||||
|  |             repeat { | ||||||
|  |                 if parent.value >= value { | ||||||
|  |                     if parent.left!=0 | ||||||
|  |                         parent = parent.left | ||||||
|  |                     else { | ||||||
|  |                         parent.left = node | ||||||
|  |                         return | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     if parent.right!=0 | ||||||
|  |                         parent = parent.right | ||||||
|  |                     else { | ||||||
|  |                         parent.right = node | ||||||
|  |                         return | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub contains(uword value) -> bool { | ||||||
|  |         ^^Node r = root | ||||||
|  |         while r!=0 { | ||||||
|  |             if r.value==value | ||||||
|  |                 return true | ||||||
|  |             if r.value>value | ||||||
|  |                 r = r.left | ||||||
|  |             else | ||||||
|  |                 r = r.right | ||||||
|  |         } | ||||||
|  |         return false | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub size() -> ubyte { | ||||||
|  |         ubyte count | ||||||
|  |  | ||||||
|  |         if root!=0 | ||||||
|  |             count_node(root) | ||||||
|  |  | ||||||
|  |         return count | ||||||
|  |  | ||||||
|  |         sub count_node(^^Node r) { | ||||||
|  |             count++ | ||||||
|  |             if r.left!=0 { | ||||||
|  |                 sys.pushw(r) | ||||||
|  |                 count_node(r.left) | ||||||
|  |                 r = sys.popw() | ||||||
|  |             } | ||||||
|  |             if r.right!=0 { | ||||||
|  |                 sys.pushw(r) | ||||||
|  |                 count_node(r.right) | ||||||
|  |                 r = sys.popw() | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub remove(uword value) { | ||||||
|  |         ; note: we don't deallocate the memory from the node, for simplicity sake | ||||||
|  |         ^^Node n = root | ||||||
|  |         ^^Node parent = 0 | ||||||
|  |         while n!=0 { | ||||||
|  |             if n.value==value { | ||||||
|  |                 if n.left==0 | ||||||
|  |                     replacechild(parent, n, n.right) | ||||||
|  |                 else if n.right==0 | ||||||
|  |                     replacechild(parent, n, n.left) | ||||||
|  |                 else { | ||||||
|  |                     ; Both left & right subtrees are present. | ||||||
|  |                     ; N = node to delete. | ||||||
|  |                     ;    Find N's successor S. (N's right subtree's minimum element) | ||||||
|  |                     ;    Attach N's left subtree to S.left (S doesn't have a left child) | ||||||
|  |                     ;    Attach N's right subtree to Parent in place of N. | ||||||
|  |                     ^^Node successor = find_successor(n) | ||||||
|  |                     successor.left = n.left | ||||||
|  |                     replacechild(parent, n, n.right) | ||||||
|  |                 } | ||||||
|  |                 return | ||||||
|  |             } | ||||||
|  |             parent = n | ||||||
|  |             if n.value>value | ||||||
|  |                 n = n.left | ||||||
|  |             else | ||||||
|  |                 n = n.right | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         sub find_successor(^^Node p) -> ^^Node { | ||||||
|  |             ^^Node succ = p | ||||||
|  |             p = p.right | ||||||
|  |             while p!=0 { | ||||||
|  |                 succ = p | ||||||
|  |                 p = p.left | ||||||
|  |             } | ||||||
|  |             return succ | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         sub replacechild(^^Node p, ^^Node child, ^^Node newchild) { | ||||||
|  |             if p.left==child | ||||||
|  |                 p.left = newchild | ||||||
|  |             else | ||||||
|  |                 p.right = newchild | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     sub process_tree_inorder() { | ||||||
|  |         if root!=0 | ||||||
|  |             process_tree(root) | ||||||
|  |  | ||||||
|  |         sub process_tree(^^Node r) { | ||||||
|  |             if r.left!=0 { | ||||||
|  |                 sys.pushw(r) | ||||||
|  |                 process_tree(r.left) | ||||||
|  |                 r = sys.popw() | ||||||
|  |             } | ||||||
|  |             cx16.r0 = r.value | ||||||
|  |             if r.right!=0 { | ||||||
|  |                 sys.pushw(r) | ||||||
|  |                 process_tree(r.right) | ||||||
|  |                 r = sys.popw() | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     sub process_tree_preorder() { | ||||||
|  |         if root!=0 | ||||||
|  |             process_tree(root,0) | ||||||
|  |  | ||||||
|  |         sub process_tree(^^Node r, ubyte depth) { | ||||||
|  |             cx16.r0 = r.value | ||||||
|  |             if r.left!=0 { | ||||||
|  |                 sys.pushw(r) | ||||||
|  |                 sys.push(depth) | ||||||
|  |                 process_tree(r.left, depth+1) | ||||||
|  |                 depth = sys.pop() | ||||||
|  |                 r = sys.popw() | ||||||
|  |             } | ||||||
|  |             if r.right!=0 { | ||||||
|  |                 sys.pushw(r) | ||||||
|  |                 sys.push(depth) | ||||||
|  |                 process_tree(r.right, depth+1) | ||||||
|  |                 depth = sys.pop() | ||||||
|  |                 r = sys.popw() | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | arena { | ||||||
|  |     ; extremely trivial arena allocator (that never frees) | ||||||
|  |     uword buffer = memory("arena", 2000, 0) | ||||||
|  |     uword next = buffer | ||||||
|  |  | ||||||
|  |     sub alloc(ubyte size) -> uword { | ||||||
|  |         defer next += size | ||||||
|  |         return next | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub freeall() { | ||||||
|  |         next = buffer | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										111
									
								
								benchmark-program/b_circles.p8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								benchmark-program/b_circles.p8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | |||||||
|  | %import gfx_lores | ||||||
|  | %import math | ||||||
|  |  | ||||||
|  | circles { | ||||||
|  |     const ubyte MAX_NUM_CIRCLES = 80 | ||||||
|  |     const ubyte GROWTH_RATE = 4 | ||||||
|  |     uword[MAX_NUM_CIRCLES] circle_x | ||||||
|  |     uword[MAX_NUM_CIRCLES] circle_y | ||||||
|  |     ubyte[MAX_NUM_CIRCLES] circle_radius | ||||||
|  |     ubyte color | ||||||
|  |     uword total_num_circles | ||||||
|  |  | ||||||
|  |     sub draw(bool use_kernal, uword max_time) -> uword { | ||||||
|  |         if use_kernal | ||||||
|  |             cx16.set_screen_mode(128) | ||||||
|  |         else | ||||||
|  |             gfx_lores.graphics_mode() | ||||||
|  |  | ||||||
|  |         math.rndseed(12345,6789) | ||||||
|  |         cbm.SETTIM(0,0,0) | ||||||
|  |  | ||||||
|  |         total_num_circles = 0 | ||||||
|  |         color = 16 | ||||||
|  |  | ||||||
|  |         while cbm.RDTIM16()<max_time { | ||||||
|  |             if use_kernal { | ||||||
|  |                 cx16.GRAPH_set_colors(0,0,0) | ||||||
|  |                 cx16.GRAPH_clear() | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |                 gfx_lores.clear_screen(0) | ||||||
|  |             total_num_circles += draw_circles(use_kernal, max_time) | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if use_kernal | ||||||
|  |             cx16.set_screen_mode(3) | ||||||
|  |         else { | ||||||
|  |             gfx_lores.text_mode() | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return total_num_circles | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub draw_circles(bool use_kernal, uword max_time) -> uword { | ||||||
|  |         uword @zp x | ||||||
|  |         uword @zp y | ||||||
|  |         ubyte @zp radius | ||||||
|  |  | ||||||
|  |         ubyte num_circles | ||||||
|  |  | ||||||
|  |         while num_circles<MAX_NUM_CIRCLES and cbm.RDTIM16()<max_time { | ||||||
|  |             x = math.rndw() % 320 | ||||||
|  |             y = math.rndw() % 240 | ||||||
|  |             radius = GROWTH_RATE | ||||||
|  |             if not_colliding() { | ||||||
|  |                 while not_edge() and not_colliding() { | ||||||
|  |                     radius += GROWTH_RATE | ||||||
|  |                 } | ||||||
|  |                 radius -= GROWTH_RATE | ||||||
|  |                 if radius>0 { | ||||||
|  |                     color++ | ||||||
|  |                     if color==0 | ||||||
|  |                         color=16 | ||||||
|  |                     if use_kernal { | ||||||
|  |                         cx16.GRAPH_set_colors(color, 255-color, 0) | ||||||
|  |                         cx16.GRAPH_draw_oval(x-radius, y-radius, radius*2, radius*2, true) | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                         gfx_lores.disc(x, y as ubyte, radius, color) | ||||||
|  |                     circle_x[num_circles] = x | ||||||
|  |                     circle_y[num_circles] = y | ||||||
|  |                     circle_radius[num_circles] = radius | ||||||
|  |                     num_circles++ | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return num_circles | ||||||
|  |  | ||||||
|  |         sub not_colliding() -> bool { | ||||||
|  |             if num_circles==0 | ||||||
|  |                 return true | ||||||
|  |             ubyte @zp c | ||||||
|  |             for c in 0 to num_circles-1 { | ||||||
|  |                 if distance(c) < (radius as uword) + circle_radius[c] | ||||||
|  |                     return false | ||||||
|  |             } | ||||||
|  |             return true | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         sub distance(ubyte cix) -> uword { | ||||||
|  |             word dx = x as word - circle_x[cix] | ||||||
|  |             word dy = y as word - circle_y[cix] | ||||||
|  |             uword sqx = dx*dx as uword | ||||||
|  |             uword sqy = dy*dy as uword | ||||||
|  |             return sqrt(sqx + sqy) | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         sub not_edge() -> bool { | ||||||
|  |             if x as word - radius < 0 | ||||||
|  |                 return false | ||||||
|  |             if x + radius >= 320 | ||||||
|  |                 return false | ||||||
|  |             if y as word - radius < 0 | ||||||
|  |                 return false | ||||||
|  |             if y + radius >= 240 | ||||||
|  |                 return false | ||||||
|  |             return true | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										123
									
								
								benchmark-program/b_life.p8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								benchmark-program/b_life.p8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,123 @@ | |||||||
|  | ; conway's game of life. | ||||||
|  |  | ||||||
|  | %import math | ||||||
|  | %import textio | ||||||
|  |  | ||||||
|  | life { | ||||||
|  |     const ubyte WIDTH = 40 | ||||||
|  |     const ubyte HEIGHT = 30 | ||||||
|  |     const uword STRIDE = $0002+WIDTH | ||||||
|  |     uword world1 = memory("world1", (WIDTH+2)*(HEIGHT+2), 0) | ||||||
|  |     uword world2 = memory("world2", (WIDTH+2)*(HEIGHT+2), 0) | ||||||
|  |     uword @requirezp active_world = world1 | ||||||
|  |  | ||||||
|  |    sub benchmark(uword max_time) -> uword { | ||||||
|  |         txt.clear_screen() | ||||||
|  |         sys.memset(world1, (WIDTH+2)*(HEIGHT+2), 0) | ||||||
|  |         sys.memset(world2, (WIDTH+2)*(HEIGHT+2), 0) | ||||||
|  |  | ||||||
|  |         set_start_gen() | ||||||
|  |  | ||||||
|  |         uword gen | ||||||
|  |         cbm.SETTIM(0,0,0) | ||||||
|  |  | ||||||
|  |         while cbm.RDTIM16()<max_time { | ||||||
|  |             next_gen() | ||||||
|  |             gen++ | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return gen | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub set_start_gen() { | ||||||
|  |  | ||||||
|  | ; some way to set a custom start generation: | ||||||
|  | ;        str start_gen = "                " + | ||||||
|  | ;                        "                " + | ||||||
|  | ;                        "                " + | ||||||
|  | ;                        "          **    " + | ||||||
|  | ;                        "        *    *  " + | ||||||
|  | ;                        "       *        " + | ||||||
|  | ;                        "       *     *  " + | ||||||
|  | ;                        "       ******   " + | ||||||
|  | ;                        "                " + | ||||||
|  | ;                        "                " + | ||||||
|  | ;                        "                " + | ||||||
|  | ;                        "                " + | ||||||
|  | ;                        "                " + | ||||||
|  | ;                        "                " + | ||||||
|  | ;                        "                " + | ||||||
|  | ;                        "               " | ||||||
|  | ; | ||||||
|  | ;        for y in 0 to 15 { | ||||||
|  | ;            for x in 0 to 15 { | ||||||
|  | ;                if start_gen[y*16 + x]=='*' | ||||||
|  | ;                    active_world[offset + x] = 1 | ||||||
|  | ;            } | ||||||
|  | ;            offset += STRIDE | ||||||
|  | ;        } | ||||||
|  |  | ||||||
|  |         ; randomize whole world | ||||||
|  |         math.rndseed(12345,9999) | ||||||
|  |         uword offset = STRIDE+1 | ||||||
|  |         ubyte x | ||||||
|  |         ubyte y | ||||||
|  |         for y in 0 to HEIGHT-1 { | ||||||
|  |             for x in 0 to WIDTH-1 { | ||||||
|  |                 active_world[offset+x] = math.rnd() & 1 | ||||||
|  |             } | ||||||
|  |             offset += STRIDE | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub next_gen() { | ||||||
|  |         const ubyte DXOFFSET = 0 | ||||||
|  |         const ubyte DYOFFSET = 0 | ||||||
|  |         ubyte[2] cell_chars = [sc:' ', sc:'●'] | ||||||
|  |  | ||||||
|  |         uword @requirezp new_world = world1 | ||||||
|  |         if active_world == world1 | ||||||
|  |             new_world = world2 | ||||||
|  |  | ||||||
|  |         ; To avoid re-calculating word index lookups into the new- and active world arrays, | ||||||
|  |         ; we calculate the required pointer values upfront. | ||||||
|  |         ; Inside the loop we can use ptr+x just fine (results in efficient LDA (ptr),Y instruction because x is a byte type), | ||||||
|  |         ; and for each row we simply add the stride to the pointer. | ||||||
|  |         ; It's more readable to use active_world[offset] etc, but offset is a word value, and this produces | ||||||
|  |         ; inefficient assembly code because we can't use a register indexed mode in this case. Costly inside a loop. | ||||||
|  |  | ||||||
|  |         uword @requirezp new_world_ptr = new_world + STRIDE+1-DXOFFSET | ||||||
|  |         uword @requirezp active_world_ptr = active_world + STRIDE+1-DXOFFSET | ||||||
|  |  | ||||||
|  |         ubyte x | ||||||
|  |         ubyte y | ||||||
|  |         for y in DYOFFSET to HEIGHT+DYOFFSET-1 { | ||||||
|  |  | ||||||
|  |             cx16.vaddr_autoincr(1, $b000 + 256*y, 0, 2)     ;  allows us to use simple Vera data byte assigns later instead of setchr() calls | ||||||
|  |  | ||||||
|  |             for x in DXOFFSET to WIDTH+DXOFFSET-1 { | ||||||
|  |                 ; count the living neighbors | ||||||
|  |                 ubyte cell = @(active_world_ptr + x) | ||||||
|  |                 uword @requirezp ptr = active_world_ptr + x - STRIDE - 1 | ||||||
|  |                 ubyte neighbors = @(ptr) + @(ptr+1) + @(ptr+2) + | ||||||
|  |                                   @(ptr+STRIDE) + cell + @(ptr+STRIDE+2) + | ||||||
|  |                                   @(ptr+STRIDE*2) + @(ptr+STRIDE*2+1) + @(ptr+STRIDE*2+2) | ||||||
|  |  | ||||||
|  |                 ; apply game of life rules | ||||||
|  |                 if neighbors==3 | ||||||
|  |                     cell=1 | ||||||
|  |                 else if neighbors!=4 | ||||||
|  |                     cell=0 | ||||||
|  |                 @(new_world_ptr + x) = cell | ||||||
|  |  | ||||||
|  |                 ; draw new cell | ||||||
|  |                 ; txt.setchr(x,y,cell_chars[cell]) | ||||||
|  |                 cx16.VERA_DATA0 = cell_chars[cell] | ||||||
|  |             } | ||||||
|  |             active_world_ptr += STRIDE | ||||||
|  |             new_world_ptr += STRIDE | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         active_world = new_world | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										54
									
								
								benchmark-program/b_mandelbrot.p8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								benchmark-program/b_mandelbrot.p8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | |||||||
|  | %import textio | ||||||
|  | %import floats | ||||||
|  |  | ||||||
|  | mandelbrot { | ||||||
|  |     const ubyte width = 39 | ||||||
|  |     const ubyte height = 29 | ||||||
|  |     const ubyte max_iter = 15 | ||||||
|  |  | ||||||
|  |     sub calc(uword max_time) -> uword  { | ||||||
|  |         uword num_pixels | ||||||
|  |         ubyte pixelx | ||||||
|  |         ubyte pixely | ||||||
|  |  | ||||||
|  |         txt.home() | ||||||
|  |         cbm.SETTIM(0,0,0) | ||||||
|  |  | ||||||
|  |         while cbm.RDTIM16() < max_time { | ||||||
|  |             for pixely in 0 to height-1 { | ||||||
|  |                 float yy = (pixely as float)/0.40/height - 1.3 | ||||||
|  |  | ||||||
|  |                 for pixelx in 0 to width-1 { | ||||||
|  |                     float xx = (pixelx as float)/0.32/width - 2.2 | ||||||
|  |  | ||||||
|  |                     float xsquared = 0.0 | ||||||
|  |                     float ysquared = 0.0 | ||||||
|  |                     float x = 0.0 | ||||||
|  |                     float y = 0.0 | ||||||
|  |                     ubyte iter = 0 | ||||||
|  |  | ||||||
|  |                     while iter<max_iter and xsquared+ysquared<4.0 { | ||||||
|  |                         y = x*y*2.0 + yy | ||||||
|  |                         x = xsquared - ysquared + xx | ||||||
|  |                         xsquared = x*x | ||||||
|  |                         ysquared = y*y | ||||||
|  |                         iter++ | ||||||
|  |                     } | ||||||
|  |                     txt.color2(1, max_iter-iter) | ||||||
|  |                     txt.spc() | ||||||
|  |                     num_pixels++ | ||||||
|  |  | ||||||
|  |                     if cbm.RDTIM16()>=max_time | ||||||
|  |                         goto finished | ||||||
|  |                 } | ||||||
|  |                 txt.nl() | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             txt.clear_screen() | ||||||
|  |         } | ||||||
|  |  | ||||||
|  | finished: | ||||||
|  |         txt.color2(1, 6) | ||||||
|  |         return num_pixels | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										343
									
								
								benchmark-program/b_maze.p8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										343
									
								
								benchmark-program/b_maze.p8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,343 @@ | |||||||
|  | %import textio | ||||||
|  | %import math | ||||||
|  |  | ||||||
|  | ; Even though prog8 only has support for extremely limited recursion, | ||||||
|  | ; you can write recursive algorithms with a bit of extra work by building your own explicit stack structure. | ||||||
|  | ; This program shows a depth-first maze generation algorithm (1 possible path from start to finish), | ||||||
|  | ; and a depth-first maze solver algorithm, both using a stack to store the path taken. | ||||||
|  |  | ||||||
|  | ; Note: this program can be compiled for multiple target systems. | ||||||
|  |  | ||||||
|  | maze { | ||||||
|  |     uword score | ||||||
|  |  | ||||||
|  |     sub bench(uword max_time) -> uword { | ||||||
|  |         txt.nl() | ||||||
|  |         score=0 | ||||||
|  |         math.rndseed(2345,44332) | ||||||
|  |         cbm.SETTIM(0,0,0) | ||||||
|  |         while cbm.RDTIM16()<max_time { | ||||||
|  |             maze.initialize() | ||||||
|  |             maze.drawStartFinish() | ||||||
|  |             if maze.generate(max_time) { | ||||||
|  |                 maze.openpassages() | ||||||
|  |                 maze.drawStartFinish() | ||||||
|  |                 if maze.solve(max_time) { | ||||||
|  |                     maze.drawStartFinish() | ||||||
|  |                 } else break | ||||||
|  |             } else break | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return score | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const uword screenwidth = 40 | ||||||
|  |     const uword screenheight = 30 | ||||||
|  |  | ||||||
|  |     const ubyte numCellsHoriz = (screenwidth-1) / 2 | ||||||
|  |     const ubyte numCellsVert = (screenheight-1) / 2 | ||||||
|  |  | ||||||
|  |     ; maze start and finish cells | ||||||
|  |     const ubyte startCx = 0 | ||||||
|  |     const ubyte startCy = 0 | ||||||
|  |     const ubyte finishCx = numCellsHoriz-1 | ||||||
|  |     const ubyte finishCy = numCellsVert-1 | ||||||
|  |  | ||||||
|  |     ; cell properties | ||||||
|  |     const ubyte STONE = 128 | ||||||
|  |     const ubyte WALKED = 64 | ||||||
|  |     const ubyte BACKTRACKED = 32 | ||||||
|  |     const ubyte UP = 1 | ||||||
|  |     const ubyte RIGHT = 2 | ||||||
|  |     const ubyte DOWN = 4 | ||||||
|  |     const ubyte LEFT = 8 | ||||||
|  |     const ubyte WALLCOLOR = 12 | ||||||
|  |     const ubyte EMPTYCOLOR = 0 | ||||||
|  |  | ||||||
|  |     ; unfortunately on larger screens (cx16), the number of cells exceeds 256 and doesn't fit in a regular array anymore. | ||||||
|  |     uword cells = memory("cells", numCellsHoriz*numCellsVert, 0) | ||||||
|  |  | ||||||
|  |     ubyte[256] cx_stack | ||||||
|  |     ubyte[256] cy_stack | ||||||
|  |     ubyte stackptr | ||||||
|  |  | ||||||
|  |     ubyte[4] directionflags = [LEFT,RIGHT,UP,DOWN] | ||||||
|  |  | ||||||
|  |     sub generate(uword max_time) -> bool { | ||||||
|  |         ubyte cx = startCx | ||||||
|  |         ubyte cy = startCy | ||||||
|  |  | ||||||
|  |         stackptr = 0 | ||||||
|  |         @(celladdr(cx,cy)) &= ~STONE | ||||||
|  |         drawCell(cx, cy) | ||||||
|  |         uword cells_to_carve = numCellsHoriz * numCellsVert - 1 | ||||||
|  |  | ||||||
|  |         while cbm.RDTIM16()<max_time { | ||||||
|  | carve_restart_after_repath: | ||||||
|  |             ubyte direction = choose_uncarved_direction() | ||||||
|  |             if direction==0 { | ||||||
|  |                 ;backtrack | ||||||
|  |                 stackptr-- | ||||||
|  |                 if stackptr==255 { | ||||||
|  |                     ; stack empty. | ||||||
|  |                     ; repath if we are not done yet. (this is a workaround for the prog8 256 array lenght limit) | ||||||
|  |                     if cells_to_carve!=0 { | ||||||
|  |                         if repath() | ||||||
|  |                             goto carve_restart_after_repath | ||||||
|  |                     } | ||||||
|  |                     return true | ||||||
|  |                 } | ||||||
|  |                 cx = cx_stack[stackptr] | ||||||
|  |                 cy = cy_stack[stackptr] | ||||||
|  |             } else { | ||||||
|  |                 cx_stack[stackptr] = cx | ||||||
|  |                 cy_stack[stackptr] = cy | ||||||
|  |                 stackptr++ | ||||||
|  |                 if stackptr==0 { | ||||||
|  |                     ; stack overflow, we can't track our path any longer. | ||||||
|  |                     ; repath if we are not done yet. (this is a workaround for the prog8 256 array lenght limit) | ||||||
|  |                     if cells_to_carve!=0 { | ||||||
|  |                         if repath() | ||||||
|  |                             goto carve_restart_after_repath | ||||||
|  |                     } | ||||||
|  |                     return true | ||||||
|  |                 } | ||||||
|  |                 @(celladdr(cx,cy)) |= direction | ||||||
|  |                 when direction { | ||||||
|  |                     UP -> { | ||||||
|  |                         cy-- | ||||||
|  |                         @(celladdr(cx,cy)) |= DOWN | ||||||
|  |                     } | ||||||
|  |                     RIGHT -> { | ||||||
|  |                         cx++ | ||||||
|  |                         @(celladdr(cx,cy)) |= LEFT | ||||||
|  |  | ||||||
|  |                         score++ | ||||||
|  |                     } | ||||||
|  |                     DOWN -> { | ||||||
|  |                         cy++ | ||||||
|  |                         @(celladdr(cx,cy)) |= UP | ||||||
|  |                     } | ||||||
|  |                     LEFT -> { | ||||||
|  |                         cx-- | ||||||
|  |                         @(celladdr(cx,cy)) |= RIGHT | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 @(celladdr(cx,cy)) &= ~STONE | ||||||
|  |                 cells_to_carve-- | ||||||
|  |                 drawCell(cx, cy) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return false | ||||||
|  |  | ||||||
|  |         sub repath() -> bool { | ||||||
|  |             ; repath: try to find a new start cell with possible directions. | ||||||
|  |             ; we limit our number of searches so that the algorith doesn't get stuck | ||||||
|  |             ; for too long on bad rng... just accept a few unused cells in that case. | ||||||
|  |             repeat 255 { | ||||||
|  |                 do { | ||||||
|  |                     cx = math.rnd() % numCellsHoriz | ||||||
|  |                     cy = math.rnd() % numCellsVert | ||||||
|  |                 } until @(celladdr(cx, cy)) & STONE ==0 | ||||||
|  |                 if available_uncarved()!=0 | ||||||
|  |                     return true | ||||||
|  |             } | ||||||
|  |             return false | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         sub available_uncarved() -> ubyte { | ||||||
|  |             ubyte candidates = 0 | ||||||
|  |             if cx>0 and @(celladdr(cx-1, cy)) & STONE !=0 | ||||||
|  |                 candidates |= LEFT | ||||||
|  |             if cx<numCellsHoriz-1 and @(celladdr(cx+1, cy)) & STONE !=0 | ||||||
|  |                 candidates |= RIGHT | ||||||
|  |             if cy>0 and @(celladdr(cx, cy-1)) & STONE !=0 | ||||||
|  |                 candidates |= UP | ||||||
|  |             if cy<numCellsVert-1 and @(celladdr(cx, cy+1)) & STONE !=0 | ||||||
|  |                 candidates |= DOWN | ||||||
|  |             return candidates | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         sub choose_uncarved_direction() -> ubyte { | ||||||
|  |             ubyte candidates =  available_uncarved() | ||||||
|  |             if candidates==0 | ||||||
|  |                 return 0 | ||||||
|  |  | ||||||
|  |             repeat { | ||||||
|  |                 ubyte choice = candidates & directionflags[math.rnd() & 3] | ||||||
|  |                 if choice!=0 | ||||||
|  |                     return choice | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub openpassages() { | ||||||
|  |         ; open just a few extra passages, so that multiple routes are possible in theory. | ||||||
|  |         ubyte numpassages | ||||||
|  |         ubyte cx | ||||||
|  |         ubyte cy | ||||||
|  |         do { | ||||||
|  |             do { | ||||||
|  |                 cx = math.rnd() % (numCellsHoriz-2) + 1 | ||||||
|  |                 cy = math.rnd() % (numCellsVert-2) + 1 | ||||||
|  |             } until @(celladdr(cx, cy)) & STONE ==0 | ||||||
|  |             ubyte direction = directionflags[math.rnd() & 3] | ||||||
|  |             if @(celladdr(cx, cy)) & direction == 0 { | ||||||
|  |                 when direction { | ||||||
|  |                     LEFT -> { | ||||||
|  |                         if @(celladdr(cx-1,cy)) & STONE == 0 { | ||||||
|  |                             @(celladdr(cx,cy)) |= LEFT | ||||||
|  |                             drawCell(cx,cy) | ||||||
|  |                             numpassages++ | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     RIGHT -> { | ||||||
|  |                         if @(celladdr(cx+1,cy)) & STONE == 0 { | ||||||
|  |                             @(celladdr(cx,cy)) |= RIGHT | ||||||
|  |                             drawCell(cx,cy) | ||||||
|  |                             numpassages++ | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     UP -> { | ||||||
|  |                         if @(celladdr(cx,cy-1)) & STONE == 0 { | ||||||
|  |                             @(celladdr(cx,cy)) |= UP | ||||||
|  |                             drawCell(cx,cy) | ||||||
|  |                             numpassages++ | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     DOWN -> { | ||||||
|  |                         if @(celladdr(cx,cy+1)) & STONE == 0 { | ||||||
|  |                             @(celladdr(cx,cy)) |= DOWN | ||||||
|  |                             drawCell(cx,cy) | ||||||
|  |                             numpassages++ | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } until numpassages==10 | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub solve(uword max_time) -> bool { | ||||||
|  |         ubyte cx = startCx | ||||||
|  |         ubyte cy = startCy | ||||||
|  |         const uword max_path_length = 1024 | ||||||
|  |  | ||||||
|  |         ; the path through the maze can be longer than 256 so doesn't fit in a regular array.... :( | ||||||
|  |         uword pathstack = memory("pathstack", max_path_length, 0) | ||||||
|  |         uword pathstackptr = 0 | ||||||
|  |  | ||||||
|  |         @(celladdr(cx,cy)) |= WALKED | ||||||
|  |         ; txt.setcc(cx*2+1, cy*2+1, 81, 1) | ||||||
|  |  | ||||||
|  |         while cbm.RDTIM16()<max_time { | ||||||
|  | solve_loop: | ||||||
|  |             if cx==finishCx and cy==finishCy { | ||||||
|  |                 ;txt.home() | ||||||
|  |                 txt.print("found! path length: ") | ||||||
|  |                 txt.print_uw(pathstackptr) | ||||||
|  |                 txt.nl() | ||||||
|  |                 return true | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             ubyte cell = @(celladdr(cx,cy)) | ||||||
|  |             if cell & UP!=0 and @(celladdr(cx,cy-1)) & (WALKED|BACKTRACKED) ==0 { | ||||||
|  |                 @(pathstack + pathstackptr) = UP | ||||||
|  |                 ;txt.setcc(cx*2+1, cy*2, 81, 3) | ||||||
|  |                 cy-- | ||||||
|  |             } | ||||||
|  |             else if cell & DOWN !=0 and @(celladdr(cx,cy+1)) & (WALKED|BACKTRACKED) ==0 { | ||||||
|  |                 @(pathstack + pathstackptr) = DOWN | ||||||
|  |                 ;txt.setcc(cx*2+1, cy*2+2, 81, 3) | ||||||
|  |                 cy++ | ||||||
|  |             } | ||||||
|  |             else if cell & LEFT !=0 and @(celladdr(cx-1,cy)) & (WALKED|BACKTRACKED) ==0 { | ||||||
|  |                 @(pathstack + pathstackptr) = LEFT | ||||||
|  |                 ;txt.setcc(cx*2, cy*2+1, 81, 3) | ||||||
|  |                 cx-- | ||||||
|  |             } | ||||||
|  |             else if cell & RIGHT !=0 and @(celladdr(cx+1,cy)) & (WALKED|BACKTRACKED) ==0 { | ||||||
|  |                 @(pathstack + pathstackptr) = RIGHT | ||||||
|  |                 ;txt.setcc(cx*2+2, cy*2+1, 81, 3) | ||||||
|  |                 cx++ | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|  |                 ; dead end, pop stack | ||||||
|  |                 pathstackptr-- | ||||||
|  |                 if pathstackptr==65535 { | ||||||
|  |                     txt.print("no solution?!\n") | ||||||
|  |                     return true | ||||||
|  |                 } | ||||||
|  |                 @(celladdr(cx,cy)) |= BACKTRACKED | ||||||
|  |                 ;txt.setcc(cx*2+1, cy*2+1, 81, 2) | ||||||
|  |                 when @(pathstack + pathstackptr) { | ||||||
|  |                     UP -> { | ||||||
|  |                         ;txt.setcc(cx*2+1, cy*2+2, 81, 9) | ||||||
|  |                         cy++ | ||||||
|  |                     } | ||||||
|  |                     DOWN -> { | ||||||
|  |                         ;txt.setcc(cx*2+1, cy*2, 81, 9) | ||||||
|  |                         cy-- | ||||||
|  |                     } | ||||||
|  |                     LEFT -> { | ||||||
|  |                         ;txt.setcc(cx*2+2, cy*2+1, 81, 9) | ||||||
|  |                         cx++ | ||||||
|  |                     } | ||||||
|  |                     RIGHT -> { | ||||||
|  |                         ;txt.setcc(cx*2, cy*2+1, 81, 9) | ||||||
|  |                         cx-- | ||||||
|  |  | ||||||
|  |                         score++ | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 goto solve_loop | ||||||
|  |             } | ||||||
|  |             pathstackptr++ | ||||||
|  |             if pathstackptr==max_path_length { | ||||||
|  |                 txt.print("stack overflow, path too long\n") | ||||||
|  |                 return true | ||||||
|  |             } | ||||||
|  |             @(celladdr(cx,cy)) |= WALKED | ||||||
|  |             ;txt.setcc(cx*2+1, cy*2+1, 81, 1) | ||||||
|  |         } | ||||||
|  |         return false | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub celladdr(ubyte cx, ubyte cy) -> uword { | ||||||
|  |         return cells+(numCellsHoriz as uword)*cy+cx | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub drawCell(ubyte cx, ubyte cy) { | ||||||
|  |         return | ||||||
|  | ;        ubyte x = cx * 2 + 1 | ||||||
|  | ;        ubyte y = cy * 2 + 1 | ||||||
|  | ;        ubyte doors = @(celladdr(cx,cy)) | ||||||
|  | ;        if doors & UP !=0 | ||||||
|  | ;            txt.setcc(x, y-1, ' ', EMPTYCOLOR) | ||||||
|  | ;        if doors & RIGHT !=0 | ||||||
|  | ;            txt.setcc(x+1, y, ' ', EMPTYCOLOR) | ||||||
|  | ;        if doors & DOWN !=0 | ||||||
|  | ;            txt.setcc(x, y+1, ' ', EMPTYCOLOR) | ||||||
|  | ;        if doors & LEFT !=0 | ||||||
|  | ;            txt.setcc(x-1, y, ' ', EMPTYCOLOR) | ||||||
|  | ;        if doors & STONE !=0 | ||||||
|  | ;            txt.setcc(x, y, 160, WALLCOLOR) | ||||||
|  | ;        else | ||||||
|  | ;            txt.setcc(x, y, 32, EMPTYCOLOR) | ||||||
|  | ; | ||||||
|  | ;        if doors & WALKED !=0 | ||||||
|  | ;            txt.setcc(x, y, 81, 1) | ||||||
|  | ;        if doors & BACKTRACKED !=0 | ||||||
|  | ;            txt.setcc(x, y, 81, 2) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub initialize() { | ||||||
|  |         sys.memset(cells, numCellsHoriz*numCellsVert, STONE) | ||||||
|  |         ; txt.fill_screen(160, WALLCOLOR) | ||||||
|  |         drawStartFinish() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub drawStartFinish() { | ||||||
|  |         ; txt.setcc(startCx*2+1,startCy*2+1,sc:'s',5) | ||||||
|  |         ; txt.setcc(finishCx*2+1, finishCy*2+1, sc:'f', 13) | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										63
									
								
								benchmark-program/b_queens.p8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								benchmark-program/b_queens.p8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | |||||||
|  | %import textio | ||||||
|  |  | ||||||
|  | ; Recursive N-Queens solver. | ||||||
|  | ; The problem is: find all possible ways to place 8 Queen chess pieces on a chess board, so that none of them attacks any other. | ||||||
|  | ; (this program prints all solutions without taking mirroring and flipping the chess board into account) | ||||||
|  | ; Note: this program can be compiled for multiple target systems. | ||||||
|  |  | ||||||
|  | queens { | ||||||
|  |     const ubyte NUMQUEENS=8 | ||||||
|  |     ubyte[NUMQUEENS] board | ||||||
|  |  | ||||||
|  |     sub could_place(ubyte row, ubyte col) -> bool { | ||||||
|  |         if row==0 | ||||||
|  |             return true | ||||||
|  |         ubyte i | ||||||
|  |         for i in 0 to row-1 { | ||||||
|  |             if board[i]==col or board[i]-i==col-row or board[i]+i==col+row | ||||||
|  |                 return false | ||||||
|  |         } | ||||||
|  |         return true | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     uword solution_count | ||||||
|  |     uword maximum_duration | ||||||
|  |  | ||||||
|  |     sub place_queen(ubyte row) -> bool { | ||||||
|  |         if row == NUMQUEENS { | ||||||
|  |             solution_count++ | ||||||
|  |             txt.chrout('.') | ||||||
|  |             return cbm.RDTIM16()<maximum_duration | ||||||
|  |         } | ||||||
|  |         bool continue_running=true | ||||||
|  |         ubyte col | ||||||
|  |         for col in 0 to NUMQUEENS-1 { | ||||||
|  |             if could_place(row, col) { | ||||||
|  |                 board[row] = col | ||||||
|  |                 ; we need to save the local variables row and col. | ||||||
|  |                 sys.push(row) | ||||||
|  |                 sys.push(col) | ||||||
|  |                 continue_running = place_queen(row + 1) | ||||||
|  |                 ; restore the local variables after the recursive call. | ||||||
|  |                 col = sys.pop() | ||||||
|  |                 row = sys.pop() | ||||||
|  |                 board[row] = 0 | ||||||
|  |  | ||||||
|  |                 if not continue_running | ||||||
|  |                     break | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return continue_running | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub bench(uword max_time) -> uword { | ||||||
|  |         solution_count = 0 | ||||||
|  |         maximum_duration = max_time | ||||||
|  |         txt.nl() | ||||||
|  |         cbm.SETTIM(0,0,0) | ||||||
|  |         while cbm.RDTIM16() < maximum_duration { | ||||||
|  |             void place_queen(0) | ||||||
|  |         } | ||||||
|  |         return solution_count | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										69
									
								
								benchmark-program/b_sprites.p8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								benchmark-program/b_sprites.p8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | |||||||
|  | %import sprites | ||||||
|  | %import coroutines | ||||||
|  | %import math | ||||||
|  |  | ||||||
|  |  | ||||||
|  | animsprites { | ||||||
|  |     uword num_iterations | ||||||
|  |     ubyte[64] sx | ||||||
|  |     ubyte[64] sy | ||||||
|  |     ubyte[64] sc | ||||||
|  |     ubyte[64] dx | ||||||
|  |     ubyte[64] dy | ||||||
|  |     uword maximum_duration | ||||||
|  |  | ||||||
|  |     sub benchmark(uword max_duration) -> uword { | ||||||
|  |         maximum_duration = max_duration | ||||||
|  |         math.rndseed(1122,9876) | ||||||
|  |         cx16.set_screen_mode(3) | ||||||
|  |         cx16.mouse_config2(1) | ||||||
|  |         sprites.set_mousepointer_hand() | ||||||
|  |         repeat 64 | ||||||
|  |             void coroutines.add(animsprite, 0) | ||||||
|  |         cx16.mouse_config2(0) | ||||||
|  |  | ||||||
|  |         cbm.SETTIM(0,0,0) | ||||||
|  |         coroutines.run(supervisor) | ||||||
|  |  | ||||||
|  |         sprites.reset(0, 64) | ||||||
|  |         return num_iterations | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub supervisor() -> bool { | ||||||
|  |         if cbm.RDTIM16() >= maximum_duration { | ||||||
|  |             coroutines.killall() | ||||||
|  |             return false | ||||||
|  |         } | ||||||
|  |         return true | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub animsprite() { | ||||||
|  |         num_iterations++ | ||||||
|  |         ; set up the sprite | ||||||
|  |         ubyte sprnum = coroutines.current() | ||||||
|  |         cx16.r6L, cx16.r7 = sprites.get_data_ptr(0) | ||||||
|  |         sprites.init(sprnum, cx16.r6L, cx16.r7, sprites.SIZE_16, sprites.SIZE_16, sprites.COLORS_256, 0) | ||||||
|  |         sx[sprnum] = math.rnd() | ||||||
|  |         sy[sprnum] = math.rnd() | ||||||
|  |         sc[sprnum] = math.rnd() | ||||||
|  |         dx[sprnum] = if math.rnd()&1 == 1  1 else 255 | ||||||
|  |         dy[sprnum] = if math.rnd()&1 == 1  1 else 255 | ||||||
|  |  | ||||||
|  |         ; move the sprite around | ||||||
|  |         while sc[sprnum]!=0 { | ||||||
|  |             animate(sprnum) | ||||||
|  |             void coroutines.yield() | ||||||
|  |             sprnum = coroutines.current() | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         sub animate(ubyte spr) { | ||||||
|  |             defer sc[spr]-- | ||||||
|  |             sprites.pos(spr, sx[spr], sy[spr]) | ||||||
|  |             sx[spr] += dx[spr] | ||||||
|  |             sy[spr] += dy[spr] | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         ; end the task but replace it with a fresh animated sprite task | ||||||
|  |         void coroutines.add(animsprite, 0) | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										989
									
								
								benchmark-program/b_textelite.p8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										989
									
								
								benchmark-program/b_textelite.p8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,989 @@ | |||||||
|  | %import textio | ||||||
|  | %import conv | ||||||
|  | %import strings | ||||||
|  |  | ||||||
|  |  | ||||||
|  | textelite { | ||||||
|  |  | ||||||
|  |     const ubyte numforLave = 7      ;  Lave is 7th generated planet in galaxy one | ||||||
|  |     const ubyte numforZaonce = 129 | ||||||
|  |     const ubyte numforDiso = 147 | ||||||
|  |     const ubyte numforRiedquat = 46 | ||||||
|  |     uword num_commands | ||||||
|  |  | ||||||
|  |     sub bench(uword max_time) -> uword { | ||||||
|  |         num_commands = 0 | ||||||
|  |         txt.lowercase() | ||||||
|  |         cbm.SETTIM(0,0,0) | ||||||
|  |         while cbm.RDTIM16()<max_time { | ||||||
|  |             reinit() | ||||||
|  |             run_commands(max_time) | ||||||
|  |         } | ||||||
|  |         return num_commands | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub reinit() { | ||||||
|  |         ;txt.clear_screen() | ||||||
|  |         ;txt.print("\n --- TextElite v1.3 ---\n") | ||||||
|  |         txt.print("\nnew game\n") | ||||||
|  |         elite_planet.set_seed(0, 0) | ||||||
|  |         elite_galaxy.travel_to(1, numforLave) | ||||||
|  |         elite_market.init(0)  ;  Lave's market is seeded with 0 | ||||||
|  |         elite_ship.init() | ||||||
|  |         elite_planet.display(false, 0) | ||||||
|  |         input_index = 0 | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub run_commands(uword max_time) { | ||||||
|  |         while cbm.RDTIM16() < max_time { | ||||||
|  |             str input = "????????" | ||||||
|  |             ;txt.print("\nCash: ") | ||||||
|  |             ;elite_util.print_10s(elite_ship.cash) | ||||||
|  |             ;txt.print("\nCommand (?=help): ") | ||||||
|  |             ubyte num_chars = next_input(input) | ||||||
|  |             ;txt.nl() | ||||||
|  |             if num_chars!=0 { | ||||||
|  |                 when input[0] { | ||||||
|  |                     'q' -> { | ||||||
|  |                         bool has_error = false | ||||||
|  |                         if elite_galaxy.number != 2 { | ||||||
|  |                             txt.print("\nERROR: galaxy is not 2: ") | ||||||
|  |                             txt.print_ub(elite_galaxy.number) | ||||||
|  |                             txt.nl() | ||||||
|  |                             has_error=true | ||||||
|  |                         } | ||||||
|  |                         if elite_planet.number != 164 { | ||||||
|  |                             txt.print("\nERROR: planet is not 164: ") | ||||||
|  |                             txt.print_ub(elite_planet.number) | ||||||
|  |                             txt.nl() | ||||||
|  |                             has_error=true | ||||||
|  |                         } | ||||||
|  |                         if elite_planet.x != 116 { | ||||||
|  |                             txt.print("\nERROR: planet.x is not 116: ") | ||||||
|  |                             txt.print_ub(elite_planet.x) | ||||||
|  |                             txt.nl() | ||||||
|  |                             has_error=true | ||||||
|  |                         } | ||||||
|  |                         if elite_planet.y != 201 { | ||||||
|  |                             txt.print("\nERROR: planet.y is not 201: ") | ||||||
|  |                             txt.print_ub(elite_planet.y) | ||||||
|  |                             txt.nl() | ||||||
|  |                             has_error=true | ||||||
|  |                         } | ||||||
|  |                         if "ribeen" != elite_planet.name { | ||||||
|  |                             txt.print("\nERROR: planet.name is not 'ribeen': ") | ||||||
|  |                             txt.print(elite_planet.name) | ||||||
|  |                             txt.nl() | ||||||
|  |                             has_error=true | ||||||
|  |                         } | ||||||
|  |                         if elite_ship.cash != 1212 { | ||||||
|  |                             txt.print("\nERROR: cash is not 1212: ") | ||||||
|  |                             txt.print_uw(elite_ship.cash) | ||||||
|  |                             txt.nl() | ||||||
|  |                             has_error=true | ||||||
|  |                         } | ||||||
|  |                         if elite_ship.fuel != 50 { | ||||||
|  |                             txt.print("\nERROR: fuel is not 50:") | ||||||
|  |                             txt.print_ub(elite_ship.fuel) | ||||||
|  |                             txt.nl() | ||||||
|  |                             has_error=true | ||||||
|  |                         } | ||||||
|  |                         if elite_ship.cargohold[0] != 3 { | ||||||
|  |                             txt.print("\nERROR: food is not 3:") | ||||||
|  |                             txt.print_ub(elite_ship.cargohold[0]) | ||||||
|  |                             txt.nl() | ||||||
|  |                             has_error=true | ||||||
|  |                         } | ||||||
|  |                         if elite_ship.cargohold[1] != 0 { | ||||||
|  |                             txt.print("\nERROR: textiles is not 0:") | ||||||
|  |                             txt.print_ub(elite_ship.cargohold[1]) | ||||||
|  |                             txt.nl() | ||||||
|  |                             has_error=true | ||||||
|  |                         } | ||||||
|  |                         if has_error | ||||||
|  |                             sys.exit(1) | ||||||
|  |                         return | ||||||
|  |                     } | ||||||
|  |                     'b' -> elite_trader.do_buy() | ||||||
|  |                     's' -> elite_trader.do_sell() | ||||||
|  |                     'f' -> elite_trader.do_fuel() | ||||||
|  |                     'j' -> elite_trader.do_jump() | ||||||
|  |                     't' -> elite_trader.do_teleport() | ||||||
|  |                     'g' -> elite_trader.do_next_galaxy() | ||||||
|  |                     'i' -> elite_trader.do_info() | ||||||
|  |                     'm' -> { | ||||||
|  |                         if input[1]=='a' and input[2]=='p' | ||||||
|  |                             elite_trader.do_map() | ||||||
|  |                         else | ||||||
|  |                             elite_trader.do_show_market() | ||||||
|  |                     } | ||||||
|  |                     'l' -> elite_trader.do_local() | ||||||
|  |                     'c' -> elite_trader.do_cash() | ||||||
|  |                     'h' -> elite_trader.do_hold() | ||||||
|  |                 } | ||||||
|  |                 num_commands++ | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     str[] inputs = [ | ||||||
|  |         "i", | ||||||
|  |         "diso", | ||||||
|  |         "i", | ||||||
|  |         "lave", | ||||||
|  |         "m", | ||||||
|  |         "b", | ||||||
|  |         "food", | ||||||
|  |         "15", | ||||||
|  |         "map", | ||||||
|  |         "g", | ||||||
|  |         "map", | ||||||
|  |         "l", | ||||||
|  |         "j", | ||||||
|  |         "zao", | ||||||
|  |         "s", | ||||||
|  |         "food", | ||||||
|  |         "12", | ||||||
|  |         "tele", | ||||||
|  |         "quti", | ||||||
|  |         "tele", | ||||||
|  |         "aro", | ||||||
|  |         "i", | ||||||
|  |         "diso", | ||||||
|  |         "i", | ||||||
|  |         "lave", | ||||||
|  |         "i", | ||||||
|  |         "zao", | ||||||
|  |         "galhyp", | ||||||
|  |         "fuel", | ||||||
|  |         "20", | ||||||
|  |         "j", | ||||||
|  |         "rib", | ||||||
|  |         "i", | ||||||
|  |         "rib", | ||||||
|  |         "i", | ||||||
|  |         "tiri", | ||||||
|  |         "q", | ||||||
|  |         0 | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     ubyte input_index | ||||||
|  |  | ||||||
|  |     sub next_input(str buffer) -> ubyte { | ||||||
|  |         input_index++ | ||||||
|  |         return strings.copy(inputs[input_index], buffer) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | elite_trader { | ||||||
|  |     str input = "??????????" | ||||||
|  |     ubyte num_chars | ||||||
|  |  | ||||||
|  |     sub do_jump() { | ||||||
|  |         ;txt.print("\nJump to what system? ") | ||||||
|  |         jump_to_system() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub do_teleport() { | ||||||
|  |         ;txt.print("\nCheat! Teleport to what system? ") | ||||||
|  |         ubyte fuel = elite_ship.fuel | ||||||
|  |         elite_ship.fuel = 255 | ||||||
|  |         jump_to_system() | ||||||
|  |         elite_ship.fuel = fuel | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub jump_to_system() { | ||||||
|  |         void textelite.next_input(input) | ||||||
|  |         ubyte current_planet = elite_planet.number | ||||||
|  |         ubyte x = elite_planet.x | ||||||
|  |         ubyte y = elite_planet.y | ||||||
|  |         if elite_galaxy.search_closest_planet(input) { | ||||||
|  |             ubyte distance = elite_planet.distance(x, y) | ||||||
|  |             if distance <= elite_ship.fuel { | ||||||
|  |                 elite_galaxy.init_market_for_planet() | ||||||
|  |                 elite_ship.fuel -= distance | ||||||
|  |                 ;txt.print("\n\nHyperspace jump! Arrived at:\n") | ||||||
|  |                 elite_planet.display(true,0 ) | ||||||
|  |                 return | ||||||
|  |             } | ||||||
|  |             ;txt.print("\nInsufficient fuel\n") | ||||||
|  |         } else { | ||||||
|  |             ;txt.print(" Not found!\n") | ||||||
|  |         } | ||||||
|  |         elite_galaxy.travel_to(elite_galaxy.number, current_planet) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub do_buy() { | ||||||
|  |         ;txt.print("\nBuy what commodity? ") | ||||||
|  |         str commodity = "???????????????" | ||||||
|  |         void textelite.next_input(commodity) | ||||||
|  |         ubyte ci = elite_market.match(commodity) | ||||||
|  |         if ci & 128 !=0 { | ||||||
|  |             txt.print("Unknown\n") | ||||||
|  |         } else { | ||||||
|  |             ;txt.print("\nHow much? ") | ||||||
|  |             void textelite.next_input(input) | ||||||
|  |             ubyte amount = conv.str2ubyte(input) | ||||||
|  |             if elite_market.current_quantity[ci] < amount { | ||||||
|  |                 txt.print(" Insufficient supply!\n") | ||||||
|  |             } else { | ||||||
|  |                 uword price = elite_market.current_price[ci] * amount | ||||||
|  |                 ;txt.print(" Total price: ") | ||||||
|  |                 ;elite_util.print_10s(price) | ||||||
|  |                 if price > elite_ship.cash { | ||||||
|  |                     txt.print(" Not enough cash!\n") | ||||||
|  |                 } else { | ||||||
|  |                     elite_ship.cash -= price | ||||||
|  |                     elite_ship.cargohold[ci] += amount | ||||||
|  |                     elite_market.current_quantity[ci] -= amount | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub do_sell() { | ||||||
|  |         ;txt.print("\nSell what commodity? ") | ||||||
|  |         str commodity = "???????????????" | ||||||
|  |         void textelite.next_input(commodity) | ||||||
|  |         ubyte ci = elite_market.match(commodity) | ||||||
|  |         if ci & 128 !=0 { | ||||||
|  |             txt.print("Unknown\n") | ||||||
|  |         } else { | ||||||
|  |             ;txt.print("\nHow much? ") | ||||||
|  |             void textelite.next_input(input) | ||||||
|  |             ubyte amount = conv.str2ubyte(input) | ||||||
|  |             if elite_ship.cargohold[ci] < amount { | ||||||
|  |                 txt.print(" Insufficient supply!\n") | ||||||
|  |             } else { | ||||||
|  |                 uword price = elite_market.current_price[ci] * amount | ||||||
|  |                 ;txt.print(" Total price: ") | ||||||
|  |                 ;elite_util.print_10s(price) | ||||||
|  |                 elite_ship.cash += price | ||||||
|  |                 elite_ship.cargohold[ci] -= amount | ||||||
|  |                 elite_market.current_quantity[ci] += amount | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub do_fuel() { | ||||||
|  |         ;txt.print("\nBuy fuel. Amount? ") | ||||||
|  |         void textelite.next_input(input) | ||||||
|  |         ubyte buy_fuel = 10*conv.str2ubyte(input) | ||||||
|  |         ubyte max_fuel = elite_ship.Max_fuel - elite_ship.fuel | ||||||
|  |         if buy_fuel > max_fuel | ||||||
|  |             buy_fuel = max_fuel | ||||||
|  |         uword price = buy_fuel as uword * elite_ship.Fuel_cost | ||||||
|  |         if price > elite_ship.cash { | ||||||
|  |             txt.print("Not enough cash!\n") | ||||||
|  |         } else { | ||||||
|  |             elite_ship.cash -= price | ||||||
|  |             elite_ship.fuel += buy_fuel | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub do_cash() { | ||||||
|  |         ;txt.print("\nCheat! Set cash amount: ") | ||||||
|  |         void textelite.next_input(input) | ||||||
|  |         elite_ship.cash = conv.str2uword(input) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub do_hold() { | ||||||
|  |         ;txt.print("\nCheat! Set cargohold size: ") | ||||||
|  |         void textelite.next_input(input) | ||||||
|  |         elite_ship.Max_cargo = conv.str2ubyte(input) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub do_next_galaxy() { | ||||||
|  |         txt.print("\n>>>>> Galaxy Hyperjump!\n") | ||||||
|  |         elite_galaxy.travel_to(elite_galaxy.number+1, elite_planet.number) | ||||||
|  |         elite_planet.display(false, 0) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub do_info() { | ||||||
|  |         ;txt.print("\nSystem name (empty=current): ") | ||||||
|  |         num_chars = textelite.next_input(input) | ||||||
|  |         if num_chars!=0 { | ||||||
|  |             ubyte current_planet = elite_planet.number | ||||||
|  |             ubyte x = elite_planet.x | ||||||
|  |             ubyte y = elite_planet.y | ||||||
|  |             if elite_galaxy.search_closest_planet(input) { | ||||||
|  |                 ubyte distance = elite_planet.distance(x, y) | ||||||
|  |                 elite_planet.display(false, distance) | ||||||
|  |             } else { | ||||||
|  |                 ;txt.print(" Not found!") | ||||||
|  |             } | ||||||
|  |             elite_galaxy.travel_to(elite_galaxy.number, current_planet) | ||||||
|  |         } else { | ||||||
|  |             elite_planet.display(false, 0) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub do_local() { | ||||||
|  |         elite_galaxy.local_area() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub do_map() { | ||||||
|  |         ;txt.print("\n(l)ocal or (g)alaxy starmap? ") | ||||||
|  |         num_chars = textelite.next_input(input) | ||||||
|  |         if num_chars!=0 { | ||||||
|  |             elite_galaxy.starmap(input[0]=='l') | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub do_show_market() { | ||||||
|  |         elite_market.display() | ||||||
|  |         ;txt.print("\nFuel: ") | ||||||
|  |         ;elite_util.print_10s(elite_ship.fuel) | ||||||
|  |         ;txt.print("   Cargohold space: ") | ||||||
|  |         ;txt.print_ub(elite_ship.cargo_free()) | ||||||
|  |         ;txt.print("t\n") | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | elite_ship { | ||||||
|  |     const ubyte Max_fuel = 70 | ||||||
|  |     const ubyte Fuel_cost = 2 | ||||||
|  |     ubyte Max_cargo = 20 | ||||||
|  |  | ||||||
|  |     ubyte fuel | ||||||
|  |     uword cash | ||||||
|  |     ubyte[17] cargohold | ||||||
|  |  | ||||||
|  |     sub init() { | ||||||
|  |         sys.memset(cargohold, len(cargohold), 0) | ||||||
|  |         fuel = Max_fuel | ||||||
|  |         cash = 1000 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | elite_market { | ||||||
|  |     ubyte[17] baseprices = [$13, $14, $41, $28, $53, $C4, $EB, $9A, $75, $4E, $7C, $B0, $20, $61, $AB, $2D, $35] | ||||||
|  |     byte[17] gradients = [-$02, -$01, -$03, -$05, -$05, $08, $1D, $0E, $06, $01, $0d, -$09, -$01, -$01, -$02, -$01, $0F] | ||||||
|  |     ubyte[17] basequants = [$06, $0A, $02, $E2, $FB, $36, $08, $38, $28, $11, $1D, $DC, $35, $42, $37, $FA, $C0] | ||||||
|  |     ubyte[17] maskbytes = [$01, $03, $07, $1F, $0F, $03, $78, $03, $07, $1F, $07, $3F, $03, $07, $1F, $0F, $07] | ||||||
|  |     str[17] names = ["Food", "Textiles", "Radioactives", "Slaves", "Liquor/Wines", "Luxuries", "Narcotics", "Computers", | ||||||
|  |                      "Machinery", "Alloys", "Firearms", "Furs", "Minerals", "Gold", "Platinum", "Gem-Stones", "Alien Items"] | ||||||
|  |  | ||||||
|  |     ubyte[17] current_quantity | ||||||
|  |     uword[17] current_price | ||||||
|  |  | ||||||
|  |     sub init(ubyte fluct) { | ||||||
|  |         ; Prices and availabilities are influenced by the planet's economy type | ||||||
|  |         ; (0-7) and a random "fluctuation" byte that was kept within the saved | ||||||
|  |         ; commander position to keep the market prices constant over gamesaves. | ||||||
|  |         ; Availabilities must be saved with the game since the player alters them | ||||||
|  |         ; by buying (and selling(?)) | ||||||
|  |         ; | ||||||
|  |         ; Almost all commands are one byte only and overflow "errors" are | ||||||
|  |         ; extremely frequent and exploited. | ||||||
|  |         ; | ||||||
|  |         ; Trade Item prices are held internally in a single byte=true value/4. | ||||||
|  |         ; The decimal point in prices is introduced only when printing them. | ||||||
|  |         ; Internally, all prices are integers. | ||||||
|  |         ; The player's cash is held in four bytes. | ||||||
|  |         ubyte ci | ||||||
|  |         for ci in 0 to len(names)-1 { | ||||||
|  |             word product | ||||||
|  |             byte changing | ||||||
|  |             product = elite_planet.economy as word * gradients[ci] | ||||||
|  |             changing = fluct & maskbytes[ci]  as byte | ||||||
|  |             ubyte q = (basequants[ci] as word + changing - product) as ubyte | ||||||
|  |             if q & $80 !=0 | ||||||
|  |                 q = 0  ; clip to positive 8-bit | ||||||
|  |             current_quantity[ci] = q & $3f | ||||||
|  |             q = (baseprices[ci] + changing + product) as ubyte | ||||||
|  |             current_price[ci] = q * $0004 | ||||||
|  |         } | ||||||
|  |         current_quantity[16] = 0        ; force nonavailability of Alien Items | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub display() { | ||||||
|  |         return | ||||||
|  | ;        ubyte ci | ||||||
|  | ;        txt.nl() | ||||||
|  | ;        elite_planet.print_name_uppercase() | ||||||
|  | ;        txt.print(" trade market:\n    COMMODITY / PRICE / AVAIL / IN HOLD\n") | ||||||
|  | ;        for ci in 0 to len(names)-1 { | ||||||
|  | ;            elite_util.print_right(13, names[ci]) | ||||||
|  | ;            txt.print("   ") | ||||||
|  | ;            elite_util.print_10s(current_price[ci]) | ||||||
|  | ;            txt.column(24) | ||||||
|  | ;            txt.print_ub(current_quantity[ci]) | ||||||
|  | ;            txt.chrout(' ') | ||||||
|  | ;            when units[ci] { | ||||||
|  | ;                0 -> txt.chrout('t') | ||||||
|  | ;                1 -> txt.print("kg") | ||||||
|  | ;                2 -> txt.chrout('g') | ||||||
|  | ;            } | ||||||
|  | ;            txt.column(32) | ||||||
|  | ;            txt.print_ub(elite_ship.cargohold[ci]) | ||||||
|  | ;            txt.nl() | ||||||
|  | ;        } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub match(uword nameptr) -> ubyte { | ||||||
|  |         ubyte ci | ||||||
|  |         for ci in 0 to len(names)-1 { | ||||||
|  |             if elite_util.prefix_matches(nameptr, names[ci]) | ||||||
|  |                 return ci | ||||||
|  |         } | ||||||
|  |         return 255 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | elite_galaxy { | ||||||
|  |     const uword GALSIZE = 256 | ||||||
|  |     const uword base0 = $5A4A       ; seeds for the first galaxy | ||||||
|  |     const uword base1 = $0248 | ||||||
|  |     const uword base2 = $B753 | ||||||
|  |  | ||||||
|  |     str pn_pairs = "..lexegezacebisousesarmaindirea.eratenberalavetiedorquanteisrion" | ||||||
|  |  | ||||||
|  |     ubyte number | ||||||
|  |  | ||||||
|  |     uword[3] seed | ||||||
|  |  | ||||||
|  |     sub init(ubyte galaxynum) { | ||||||
|  |         number = 1 | ||||||
|  |         elite_planet.number = 255 | ||||||
|  |         seed[0] = base0 | ||||||
|  |         seed[1] = base1 | ||||||
|  |         seed[2] = base2 | ||||||
|  |         repeat galaxynum-1 { | ||||||
|  |             nextgalaxy() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub nextgalaxy() { | ||||||
|  |         textelite.num_commands++ | ||||||
|  |  | ||||||
|  |         seed[0] = twist(seed[0]) | ||||||
|  |         seed[1] = twist(seed[1]) | ||||||
|  |         seed[2] = twist(seed[2]) | ||||||
|  |         number++ | ||||||
|  |         if number==9 | ||||||
|  |             number = 1 | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub travel_to(ubyte galaxynum, ubyte system) { | ||||||
|  |         init(galaxynum) | ||||||
|  |         generate_next_planet()   ; always at least planet 0  (separate to avoid repeat ubyte overflow) | ||||||
|  |         repeat system { | ||||||
|  |             generate_next_planet() | ||||||
|  |             textelite.num_commands++ | ||||||
|  |         } | ||||||
|  |         elite_planet.name = make_current_planet_name() | ||||||
|  |         init_market_for_planet() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub init_market_for_planet() { | ||||||
|  |         elite_market.init(lsb(seed[0])+msb(seed[2])) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub search_closest_planet(uword nameptr) -> bool { | ||||||
|  |         textelite.num_commands++ | ||||||
|  |  | ||||||
|  |         ubyte x = elite_planet.x | ||||||
|  |         ubyte y = elite_planet.y | ||||||
|  |         ubyte current_planet_num = elite_planet.number | ||||||
|  |  | ||||||
|  |         init(number) | ||||||
|  |         bool found = false | ||||||
|  |         ubyte current_closest_pi | ||||||
|  |         ubyte current_distance = 127 | ||||||
|  |         ubyte pi | ||||||
|  |         for pi in 0 to 255 { | ||||||
|  |             generate_next_planet() | ||||||
|  |             elite_planet.name = make_current_planet_name() | ||||||
|  |             if elite_util.prefix_matches(nameptr, elite_planet.name) { | ||||||
|  |                 ubyte distance = elite_planet.distance(x, y) | ||||||
|  |                 if distance < current_distance { | ||||||
|  |                     current_distance = distance | ||||||
|  |                     current_closest_pi = pi | ||||||
|  |                     found = true | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if found | ||||||
|  |             travel_to(number, current_closest_pi) | ||||||
|  |         else | ||||||
|  |             travel_to(number, current_planet_num) | ||||||
|  |  | ||||||
|  |         return found | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub local_area() { | ||||||
|  |         ubyte current_planet = elite_planet.number | ||||||
|  |         ubyte px = elite_planet.x | ||||||
|  |         ubyte py = elite_planet.y | ||||||
|  |         ubyte pn = 0 | ||||||
|  |  | ||||||
|  |         init(number) | ||||||
|  | ;        txt.print("\nGalaxy #") | ||||||
|  | ;        txt.print_ub(number) | ||||||
|  | ;        txt.print(" - systems in vicinity:\n") | ||||||
|  |         do { | ||||||
|  |             generate_next_planet() | ||||||
|  |             ubyte distance = elite_planet.distance(px, py) | ||||||
|  |             if distance <= elite_ship.Max_fuel { | ||||||
|  | ;                if distance <= elite_ship.fuel | ||||||
|  | ;                    txt.chrout('*') | ||||||
|  | ;                else | ||||||
|  | ;                    txt.chrout('-') | ||||||
|  | ;                txt.spc() | ||||||
|  |                 elite_planet.name = make_current_planet_name() | ||||||
|  |                 elite_planet.display(true, distance) | ||||||
|  |             } | ||||||
|  |             pn++ | ||||||
|  |         } until pn==0 | ||||||
|  |  | ||||||
|  |         travel_to(number, current_planet) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub starmap(bool local) { | ||||||
|  |         ubyte current_planet = elite_planet.number | ||||||
|  |         ubyte px = elite_planet.x | ||||||
|  |         ubyte py = elite_planet.y | ||||||
|  |         str current_name = "        "       ; 8 max | ||||||
|  |         ubyte pn = 0 | ||||||
|  |  | ||||||
|  |         current_name = elite_planet.name | ||||||
|  |         init(number) | ||||||
|  | ;        txt.clear_screen() | ||||||
|  | ;        txt.print("Galaxy #") | ||||||
|  | ;        txt.print_ub(number) | ||||||
|  | ;        if local | ||||||
|  | ;            txt.print(" - local systems") | ||||||
|  | ;        else | ||||||
|  | ;            txt.print(" - galaxy") | ||||||
|  | ;        txt.print(" starmap:\n") | ||||||
|  |         ubyte max_distance = 255 | ||||||
|  |         if local | ||||||
|  |             max_distance = elite_ship.Max_fuel | ||||||
|  |         ubyte home_sx | ||||||
|  |         ubyte home_sy | ||||||
|  |         ubyte home_distance | ||||||
|  |  | ||||||
|  |         do { | ||||||
|  |             generate_next_planet() | ||||||
|  |             ubyte distance = elite_planet.distance(px, py) | ||||||
|  |             if distance <= max_distance { | ||||||
|  |                 elite_planet.name = make_current_planet_name() | ||||||
|  |                 elite_planet.name[0] = strings.upperchar(elite_planet.name[0]) | ||||||
|  |                 uword tx = elite_planet.x | ||||||
|  |                 uword ty = elite_planet.y | ||||||
|  |                 if local { | ||||||
|  |                     tx = tx + 24 - px | ||||||
|  |                     ty = ty + 24 - py | ||||||
|  |                 } | ||||||
|  |                 ubyte sx = display_scale_x(tx) | ||||||
|  |                 ubyte sy = display_scale_y(ty) | ||||||
|  |                 ubyte char = '*' | ||||||
|  |                 if elite_planet.number==current_planet | ||||||
|  |                     char = '%' | ||||||
|  |                 if local { | ||||||
|  |                     print_planet_details(elite_planet.name, sx, sy, distance) | ||||||
|  |                 } else if elite_planet.number==current_planet { | ||||||
|  |                     home_distance = distance | ||||||
|  |                     home_sx = sx | ||||||
|  |                     home_sy = sy | ||||||
|  |                 } | ||||||
|  |                 ; txt.setchr(2+sx, 2+sy, char) | ||||||
|  |             } | ||||||
|  |             pn++ | ||||||
|  |         } until pn==0 | ||||||
|  |  | ||||||
|  |         if not local | ||||||
|  |             print_planet_details(current_name, home_sx, home_sy, home_distance) | ||||||
|  |  | ||||||
|  | ;        if local | ||||||
|  | ;            txt.plot(0, display_scale_y(64) + 4) | ||||||
|  | ;        else | ||||||
|  | ;            txt.plot(0, display_scale_y(256) + 4 as ubyte) | ||||||
|  |         travel_to(number, current_planet) | ||||||
|  |  | ||||||
|  |         sub print_planet_details(str name, ubyte screenx, ubyte screeny, ubyte d) { | ||||||
|  |             return | ||||||
|  | ;            txt.plot(2+screenx-2, 2+screeny+1) | ||||||
|  | ;            txt.print(name) | ||||||
|  | ;            if d!=0 { | ||||||
|  | ;                txt.plot(2+screenx-2, 2+screeny+2) | ||||||
|  | ;                elite_util.print_10s(d) | ||||||
|  | ;                txt.print(" LY") | ||||||
|  | ;            } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         sub display_scale_x(uword x) -> ubyte { | ||||||
|  |             if local | ||||||
|  |                 return x/2 as ubyte | ||||||
|  |             return x/8 as ubyte | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         sub display_scale_y(uword y) -> ubyte { | ||||||
|  |             if local | ||||||
|  |                 return y/4 as ubyte | ||||||
|  |             return y/16 as ubyte | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ubyte pn_pair1 | ||||||
|  |     ubyte pn_pair2 | ||||||
|  |     ubyte pn_pair3 | ||||||
|  |     ubyte pn_pair4 | ||||||
|  |     bool longname | ||||||
|  |  | ||||||
|  |     sub generate_next_planet() { | ||||||
|  |         determine_planet_properties() | ||||||
|  |         longname = lsb(seed[0]) & 64 !=0 | ||||||
|  |  | ||||||
|  |         ; Always four iterations of random number | ||||||
|  |         pn_pair1 = (msb(seed[2]) & 31) * 2 | ||||||
|  |         tweakseed() | ||||||
|  |         pn_pair2 = (msb(seed[2]) & 31) * 2 | ||||||
|  |         tweakseed() | ||||||
|  |         pn_pair3 = (msb(seed[2]) & 31) * 2 | ||||||
|  |         tweakseed() | ||||||
|  |         pn_pair4 = (msb(seed[2]) & 31) * 2 | ||||||
|  |         tweakseed() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub make_current_planet_name() -> str { | ||||||
|  |         ubyte ni = 0 | ||||||
|  |         str name = "         "    ; max 8 | ||||||
|  |  | ||||||
|  |         if pn_pairs[pn_pair1] != '.' { | ||||||
|  |             name[ni] = pn_pairs[pn_pair1] | ||||||
|  |             ni++ | ||||||
|  |         } | ||||||
|  |         if pn_pairs[pn_pair1+1] != '.' { | ||||||
|  |             name[ni] = pn_pairs[pn_pair1+1] | ||||||
|  |             ni++ | ||||||
|  |         } | ||||||
|  |         if pn_pairs[pn_pair2] != '.' { | ||||||
|  |             name[ni] = pn_pairs[pn_pair2] | ||||||
|  |             ni++ | ||||||
|  |         } | ||||||
|  |         if pn_pairs[pn_pair2+1] != '.' { | ||||||
|  |             name[ni] = pn_pairs[pn_pair2+1] | ||||||
|  |             ni++ | ||||||
|  |         } | ||||||
|  |         if pn_pairs[pn_pair3] != '.' { | ||||||
|  |             name[ni] = pn_pairs[pn_pair3] | ||||||
|  |             ni++ | ||||||
|  |         } | ||||||
|  |         if pn_pairs[pn_pair3+1] != '.' { | ||||||
|  |             name[ni] = pn_pairs[pn_pair3+1] | ||||||
|  |             ni++ | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if longname { | ||||||
|  |             if pn_pairs[pn_pair4] != '.' { | ||||||
|  |                 name[ni] = pn_pairs[pn_pair4] | ||||||
|  |                 ni++ | ||||||
|  |             } | ||||||
|  |             if pn_pairs[pn_pair4+1] != '.' { | ||||||
|  |                 name[ni] = pn_pairs[pn_pair4+1] | ||||||
|  |                 ni++ | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         name[ni] = 0 | ||||||
|  |         return name | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub determine_planet_properties() { | ||||||
|  |         ; create the planet's characteristics | ||||||
|  |         elite_planet.number++ | ||||||
|  |         elite_planet.x = msb(seed[1]) | ||||||
|  |         elite_planet.y = msb(seed[0]) | ||||||
|  |         elite_planet.govtype = lsb(seed[1]) >> 3 & 7  ; bits 3,4 &5 of w1 | ||||||
|  |         elite_planet.economy = msb(seed[0]) & 7  ; bits 8,9 &A of w0 | ||||||
|  |         if elite_planet.govtype <= 1 | ||||||
|  |             elite_planet.economy = (elite_planet.economy | 2) | ||||||
|  |         elite_planet.techlevel = (msb(seed[1]) & 3) + (elite_planet.economy ^ 7) | ||||||
|  |         elite_planet.techlevel += elite_planet.govtype >> 1 | ||||||
|  |         if elite_planet.govtype & 1 !=0 | ||||||
|  |             elite_planet.techlevel++ | ||||||
|  |         elite_planet.population = 4 * elite_planet.techlevel + elite_planet.economy | ||||||
|  |         elite_planet.population += elite_planet.govtype + 1 | ||||||
|  |         elite_planet.productivity = ((elite_planet.economy ^ 7) + 3) * (elite_planet.govtype + 4) | ||||||
|  |         elite_planet.productivity *= elite_planet.population * 8 | ||||||
|  |         ubyte seed2_msb = msb(seed[2]) | ||||||
|  |         elite_planet.radius = mkword((seed2_msb & 15) + 11, elite_planet.x) | ||||||
|  |         elite_planet.species_is_alien = lsb(seed[2]) & 128 !=0      ; bit 7 of w2_lo | ||||||
|  |         if elite_planet.species_is_alien { | ||||||
|  |             elite_planet.species_size = (seed2_msb >> 2) & 7      ; bits 2-4 of w2_hi | ||||||
|  |             elite_planet.species_color = seed2_msb >> 5           ; bits 5-7 of w2_hi | ||||||
|  |             elite_planet.species_look = (seed2_msb ^ msb(seed[1])) & 7   ;bits 0-2 of (w0_hi EOR w1_hi) | ||||||
|  |             elite_planet.species_kind = (elite_planet.species_look + (seed2_msb & 3)) & 7      ;Add bits 0-1 of w2_hi to A from previous step, and take bits 0-2 of the result | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         elite_planet.goatsoup_seed[0] = lsb(seed[1]) | ||||||
|  |         elite_planet.goatsoup_seed[1] = msb(seed[1]) | ||||||
|  |         elite_planet.goatsoup_seed[2] = lsb(seed[2]) | ||||||
|  |         elite_planet.goatsoup_seed[3] = seed2_msb | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub tweakseed() { | ||||||
|  |         uword temp = seed[0] + seed[1] + seed[2] | ||||||
|  |         seed[0] = seed[1] | ||||||
|  |         seed[1] = seed[2] | ||||||
|  |         seed[2] = temp | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub twist(uword x) -> uword { | ||||||
|  |         ubyte xh = msb(x) | ||||||
|  |         ubyte xl = lsb(x) | ||||||
|  |         xh <<= 1        ; make sure carry flag is not used on first shift! | ||||||
|  |         rol(xl) | ||||||
|  |         return mkword(xh, xl) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | elite_planet { | ||||||
|  |     str[] @nosplit words81 = ["fabled", "notable", "well known", "famous", "noted"] | ||||||
|  |     str[] @nosplit words82 = ["very", "mildly", "most", "reasonably", ""] | ||||||
|  |     str[] @nosplit words83 = ["ancient", "\x95", "great", "vast", "pink"] | ||||||
|  |     str[] @nosplit words84 = ["\x9E \x9D plantations", "mountains", "\x9C", "\x94 forests", "oceans"] | ||||||
|  |     str[] @nosplit words85 = ["shyness", "silliness", "mating traditions", "loathing of \x86", "love for \x86"] | ||||||
|  |     str[] @nosplit words86 = ["food blenders", "tourists", "poetry", "discos", "\x8E"] | ||||||
|  |     str[] @nosplit words87 = ["talking tree", "crab", "bat", "lobst", "\xB2"] | ||||||
|  |     str[] @nosplit words88 = ["beset", "plagued", "ravaged", "cursed", "scourged"] | ||||||
|  |     str[] @nosplit words89 = ["\x96 civil war", "\x9B \x98 \x99s", "a \x9B disease", "\x96 earthquakes", "\x96 solar activity"] | ||||||
|  |     str[] @nosplit words8A = ["its \x83 \x84", "the \xB1 \x98 \x99", "its inhabitants' \x9A \x85", "\xA1", "its \x8D \x8E"] | ||||||
|  |     str[] @nosplit words8B = ["juice", "brandy", "water", "brew", "gargle blasters"] | ||||||
|  |     str[] @nosplit words8C = ["\xB2", "\xB1 \x99", "\xB1 \xB2", "\xB1 \x9B", "\x9B \xB2"] | ||||||
|  |     str[] @nosplit words8D = ["fabulous", "exotic", "hoopy", "unusual", "exciting"] | ||||||
|  |     str[] @nosplit words8E = ["cuisine", "night life", "casinos", "sit coms", " \xA1 "] | ||||||
|  |     str[] @nosplit words8F = ["\xB0", "The planet \xB0", "The world \xB0", "This planet", "This world"] | ||||||
|  |     str[] @nosplit words90 = ["n unremarkable", " boring", " dull", " tedious", " revolting"] | ||||||
|  |     str[] @nosplit words91 = ["planet", "world", "place", "little planet", "dump"] | ||||||
|  |     str[] @nosplit words92 = ["wasp", "moth", "grub", "ant", "\xB2"] | ||||||
|  |     str[] @nosplit words93 = ["poet", "arts graduate", "yak", "snail", "slug"] | ||||||
|  |     str[] @nosplit words94 = ["tropical", "dense", "rain", "impenetrable", "exuberant"] | ||||||
|  |     str[] @nosplit words95 = ["funny", "wierd", "unusual", "strange", "peculiar"] | ||||||
|  |     str[] @nosplit words96 = ["frequent", "occasional", "unpredictable", "dreadful", "deadly"] | ||||||
|  |     str[] @nosplit words97 = ["\x82 \x81 for \x8A", "\x82 \x81 for \x8A and \x8A", "\x88 by \x89", "\x82 \x81 for \x8A but \x88 by \x89", "a\x90 \x91"] | ||||||
|  |     str[] @nosplit words98 = ["\x9B", "mountain", "edible", "tree", "spotted"] | ||||||
|  |     str[] @nosplit words99 = ["\x9F", "\xA0", "\x87oid", "\x93", "\x92"] | ||||||
|  |     str[] @nosplit words9A = ["ancient", "exceptional", "eccentric", "ingrained", "\x95"] | ||||||
|  |     str[] @nosplit words9B = ["killer", "deadly", "evil", "lethal", "vicious"] | ||||||
|  |     str[] @nosplit words9C = ["parking meters", "dust clouds", "ice bergs", "rock formations", "volcanoes"] | ||||||
|  |     str[] @nosplit words9D = ["plant", "tulip", "banana", "corn", "\xB2weed"] | ||||||
|  |     str[] @nosplit words9E = ["\xB2", "\xB1 \xB2", "\xB1 \x9B", "inhabitant", "\xB1 \xB2"] | ||||||
|  |     str[] @nosplit words9F = ["shrew", "beast", "bison", "snake", "wolf"] | ||||||
|  |     str[] @nosplit wordsA0 = ["leopard", "cat", "monkey", "goat", "fish"] | ||||||
|  |     str[] @nosplit wordsA1 = ["\x8C \x8B", "\xB1 \x9F \xA2", "its \x8D \xA0 \xA2", "\xA3 \xA4", "\x8C \x8B"] | ||||||
|  |     str[] @nosplit wordsA2 = ["meat", "cutlet", "steak", "burgers", "soup"] | ||||||
|  |     str[] @nosplit wordsA3 = ["ice", "mud", "Zero-G", "vacuum", "\xB1 ultra"] | ||||||
|  |     str[] @nosplit wordsA4 = ["hockey", "cricket", "karate", "polo", "tennis"] | ||||||
|  |  | ||||||
|  |     uword[] @shared wordlists = [ | ||||||
|  |         words81, words82, words83, words84, words85, words86, words87, words88, | ||||||
|  |         words89, words8A, words8B, words8C, words8D, words8E, words8F, words90, | ||||||
|  |         words91, words92, words93, words94, words95, words96, words97, words98, | ||||||
|  |         words99, words9A, words9B, words9C, words9D, words9E, words9F, wordsA0, | ||||||
|  |         wordsA1, wordsA2, wordsA3, wordsA4] | ||||||
|  |  | ||||||
|  |     str pairs0 = "abouseitiletstonlonuthnoallexegezacebisousesarmaindirea.eratenbe" | ||||||
|  |  | ||||||
|  |     ubyte[4] goatsoup_rnd = [0, 0, 0, 0] | ||||||
|  |     ubyte[4] goatsoup_seed = [0, 0, 0, 0] | ||||||
|  |  | ||||||
|  |     str name = "        "       ; 8 max | ||||||
|  |     ubyte number                ; starts at 0 in new galaxy, then increases by 1 for each generated planet | ||||||
|  |     ubyte x | ||||||
|  |     ubyte y | ||||||
|  |     ubyte economy | ||||||
|  |     ubyte govtype | ||||||
|  |     ubyte techlevel | ||||||
|  |     ubyte population | ||||||
|  |     uword productivity | ||||||
|  |     uword radius | ||||||
|  |     bool species_is_alien      ; otherwise "Human Colonials" | ||||||
|  |     ubyte species_size | ||||||
|  |     ubyte species_color | ||||||
|  |     ubyte species_look | ||||||
|  |     ubyte species_kind | ||||||
|  |  | ||||||
|  |     sub set_seed(uword s1, uword s2) { | ||||||
|  |         goatsoup_seed[0] = lsb(s1) | ||||||
|  |         goatsoup_seed[1] = msb(s1) | ||||||
|  |         goatsoup_seed[2] = lsb(s2) | ||||||
|  |         goatsoup_seed[3] = msb(s2) | ||||||
|  |         reset_rnd() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub reset_rnd() { | ||||||
|  |         goatsoup_rnd[0] = goatsoup_seed[0] | ||||||
|  |         goatsoup_rnd[1] = goatsoup_seed[1] | ||||||
|  |         goatsoup_rnd[2] = goatsoup_seed[2] | ||||||
|  |         goatsoup_rnd[3] = goatsoup_seed[3] | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub random_name() -> str { | ||||||
|  |         ubyte ii | ||||||
|  |         str randname = "        "       ; 8 chars max | ||||||
|  |         ubyte nx = 0 | ||||||
|  |         for ii in 0 to goatsoup_rnd_number() & 3 { | ||||||
|  |             ubyte xx = goatsoup_rnd_number() & $3e | ||||||
|  |             if pairs0[xx] != '.' { | ||||||
|  |                 randname[nx] = pairs0[xx] | ||||||
|  |                 nx++ | ||||||
|  |             } | ||||||
|  |             xx++ | ||||||
|  |             if pairs0[xx] != '.' { | ||||||
|  |                 randname[nx] = pairs0[xx] | ||||||
|  |                 nx++ | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         randname[nx] = 0 | ||||||
|  |         randname[0] = strings.upperchar(randname[0]) | ||||||
|  |         return randname | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub goatsoup_rnd_number() -> ubyte { | ||||||
|  |         ubyte xx = goatsoup_rnd[0] * 2 | ||||||
|  |         uword a = xx as uword + goatsoup_rnd[2] | ||||||
|  |         if goatsoup_rnd[0] > 127 | ||||||
|  |             a ++ | ||||||
|  |         goatsoup_rnd[0] = lsb(a) | ||||||
|  |         goatsoup_rnd[2] = xx | ||||||
|  |         xx = goatsoup_rnd[1] | ||||||
|  |         ubyte ac = xx + goatsoup_rnd[3] + msb(a) | ||||||
|  |         goatsoup_rnd[1] = ac | ||||||
|  |         goatsoup_rnd[3] = xx | ||||||
|  |         return ac | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub distance(ubyte px, ubyte py) -> ubyte { | ||||||
|  |         uword ax | ||||||
|  |         uword ay | ||||||
|  |         if px>x | ||||||
|  |             ax=px-x | ||||||
|  |         else | ||||||
|  |             ax=x-px | ||||||
|  |         if py>y | ||||||
|  |             ay=py-y | ||||||
|  |         else | ||||||
|  |             ay=y-py | ||||||
|  |         ay /= 2 | ||||||
|  |         ubyte d = sqrt(ax*ax + ay*ay) | ||||||
|  |         if d>63 | ||||||
|  |             return 255 | ||||||
|  |         return d*4 | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub soup() -> str { | ||||||
|  |         str planet_result = " " * 160 | ||||||
|  |         uword[6] source_stack | ||||||
|  |         ubyte stack_ptr = 0 | ||||||
|  |         str start_source = "\x8F is \x97." | ||||||
|  |         uword source_ptr = &start_source | ||||||
|  |         uword result_ptr = &planet_result | ||||||
|  |  | ||||||
|  |         reset_rnd() | ||||||
|  |         recursive_soup() | ||||||
|  |         return planet_result | ||||||
|  |  | ||||||
|  |         sub recursive_soup() { | ||||||
|  |             repeat { | ||||||
|  |                 ubyte c = @(source_ptr) | ||||||
|  |                 source_ptr++ | ||||||
|  |                 if c == $00 { | ||||||
|  |                     @(result_ptr) = 0 | ||||||
|  |                     return | ||||||
|  |                 } | ||||||
|  |                 else if c <= $80 { | ||||||
|  |                     @(result_ptr) = c | ||||||
|  |                     result_ptr++ | ||||||
|  |                 } | ||||||
|  |                 else { | ||||||
|  |                     if c <= $a4 { | ||||||
|  |                         ubyte rnr = goatsoup_rnd_number() | ||||||
|  |                         ubyte wordNr = ((rnr >= $33) as ubyte) + ((rnr >= $66) as ubyte) + ((rnr >= $99) as ubyte) + ((rnr >= $CC) as ubyte) | ||||||
|  |                         source_stack[stack_ptr] = source_ptr | ||||||
|  |                         stack_ptr++ | ||||||
|  |                         source_ptr = getword(c, wordNr) | ||||||
|  |                         recursive_soup()    ; RECURSIVE CALL - ignore the warning message from the compiler; we don't use local variables or parameters so we're safe in this case | ||||||
|  |                         stack_ptr-- | ||||||
|  |                         source_ptr = source_stack[stack_ptr] | ||||||
|  |                     } else { | ||||||
|  |                         if c == $b0 { | ||||||
|  |                             @(result_ptr) = strings.upperchar(name[0]) | ||||||
|  |                             result_ptr++ | ||||||
|  |                             concat_string(&name + 1) | ||||||
|  |                         } | ||||||
|  |                         else if c == $b1 { | ||||||
|  |                             @(result_ptr) = strings.upperchar(name[0]) | ||||||
|  |                             result_ptr++ | ||||||
|  |                             ubyte ni | ||||||
|  |                             for ni in 1 to len(name) { | ||||||
|  |                                 ubyte cc = name[ni] | ||||||
|  |                                 if cc in ['e', 'o', 0] | ||||||
|  |                                     break | ||||||
|  |                                 else { | ||||||
|  |                                     @(result_ptr) = cc | ||||||
|  |                                     result_ptr++ | ||||||
|  |                                 } | ||||||
|  |                             } | ||||||
|  |                             @(result_ptr) = 'i' | ||||||
|  |                             result_ptr++ | ||||||
|  |                             @(result_ptr) = 'a' | ||||||
|  |                             result_ptr++ | ||||||
|  |                             @(result_ptr) = 'n' | ||||||
|  |                             result_ptr++ | ||||||
|  |                         } | ||||||
|  |                         else if c == $b2 { | ||||||
|  |                             concat_string(random_name()) | ||||||
|  |                         } | ||||||
|  |                         else { | ||||||
|  |                             @(result_ptr) = c | ||||||
|  |                             result_ptr++ | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         sub concat_string(uword str_ptr) { | ||||||
|  |             repeat { | ||||||
|  |                 ubyte c = @(str_ptr) | ||||||
|  |                 if c==0 | ||||||
|  |                     break | ||||||
|  |                 else { | ||||||
|  |                     @(result_ptr) = c | ||||||
|  |                     str_ptr++ | ||||||
|  |                     result_ptr++ | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub display(bool compressed, ubyte distance) { | ||||||
|  |         txt.print(soup()) | ||||||
|  |         txt.nl() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     sub getword(ubyte listnum, ubyte wordidx) -> uword { | ||||||
|  |         uword list = wordlists[listnum-$81] | ||||||
|  |         return peekw(list + wordidx*2) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | elite_util { | ||||||
|  |     sub prefix_matches(uword prefixptr, uword stringptr) -> bool { | ||||||
|  |         repeat { | ||||||
|  |             ubyte pc = @(prefixptr) | ||||||
|  |             ubyte sc = @(stringptr) | ||||||
|  |             if pc == 0 | ||||||
|  |                 return true | ||||||
|  |             ; to lowercase for case insensitive compare: | ||||||
|  |             if strings.lowerchar(pc)!=strings.lowerchar(sc) | ||||||
|  |                 return false | ||||||
|  |             prefixptr++ | ||||||
|  |             stringptr++ | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										118
									
								
								benchmark-program/benchmark.p8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								benchmark-program/benchmark.p8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | |||||||
|  |  | ||||||
|  | ;  This benchmark program is meant to check for regressions in the | ||||||
|  | ;  Prog8 compiler's code-generator (performance wise). | ||||||
|  | ; | ||||||
|  | ;  As the X16 computer is a more or less fixed system, it's not very useful | ||||||
|  | ;  to benchmark the computer itself with. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | %import textio | ||||||
|  | %import b_adpcm | ||||||
|  | %import b_circles | ||||||
|  | %import b_3d | ||||||
|  | %import b_life | ||||||
|  | %import b_mandelbrot | ||||||
|  | %import b_queens | ||||||
|  | %import b_textelite | ||||||
|  | %import b_maze | ||||||
|  | %import b_sprites | ||||||
|  | %import b_btree | ||||||
|  |  | ||||||
|  | %zeropage basicsafe | ||||||
|  | %option no_sysinit | ||||||
|  |  | ||||||
|  |  | ||||||
|  | main { | ||||||
|  |  | ||||||
|  |     str[20] benchmark_names | ||||||
|  |     uword[20] benchmark_score | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     sub start() { | ||||||
|  |         ubyte benchmark_number | ||||||
|  |  | ||||||
|  |         cx16.set_screen_mode(3) | ||||||
|  |         txt.color2(1, 6) | ||||||
|  |         txt.clear_screen() | ||||||
|  |  | ||||||
|  |         txt.print("\n\n\n  prog8 compiler benchmark tests.\n\n  benchmark version v12\n\n") | ||||||
|  |         sys.wait(60) | ||||||
|  |  | ||||||
|  |         benchmark_number = 0 | ||||||
|  |  | ||||||
|  |         announce_benchmark("maze solver") | ||||||
|  |         benchmark_score[benchmark_number]  = maze.bench(300) | ||||||
|  |         benchmark_number++ | ||||||
|  |  | ||||||
|  |         announce_benchmark("n-queens") | ||||||
|  |         benchmark_score[benchmark_number]  = queens.bench(300) | ||||||
|  |         benchmark_number++ | ||||||
|  |  | ||||||
|  |         announce_benchmark("mandelbrot (floating point)") | ||||||
|  |         benchmark_score[benchmark_number]  = mandelbrot.calc(400) | ||||||
|  |         benchmark_number++ | ||||||
|  |  | ||||||
|  |         announce_benchmark("game of life") | ||||||
|  |         benchmark_score[benchmark_number]  = life.benchmark(300) | ||||||
|  |         benchmark_number++ | ||||||
|  |  | ||||||
|  |         announce_benchmark("3d model rotation") | ||||||
|  |         benchmark_score[benchmark_number]  = rotate3d.benchmark(300) | ||||||
|  |         benchmark_number++ | ||||||
|  |  | ||||||
|  |         announce_benchmark("adpcm audio decoding") | ||||||
|  |         benchmark_score[benchmark_number]  = adpcm.decode_benchmark(300) | ||||||
|  |         benchmark_number++ | ||||||
|  |  | ||||||
|  |         announce_benchmark("circles with gfx_lores") | ||||||
|  |         benchmark_score[benchmark_number]  = circles.draw(false, 400) | ||||||
|  |         benchmark_number++ | ||||||
|  |  | ||||||
|  |         announce_benchmark("text-elite") | ||||||
|  |         benchmark_score[benchmark_number]  = textelite.bench(120) | ||||||
|  |         benchmark_number++ | ||||||
|  |  | ||||||
|  |         announce_benchmark("sprites-coroutines-defer") | ||||||
|  |         benchmark_score[benchmark_number]  = animsprites.benchmark(300) | ||||||
|  |         benchmark_number++ | ||||||
|  |  | ||||||
|  |         announce_benchmark("btree-struct-pointers") | ||||||
|  |         benchmark_score[benchmark_number]  = btree.benchmark(200) | ||||||
|  |         benchmark_number++ | ||||||
|  |  | ||||||
|  |         benchmark_names[benchmark_number] = 0 | ||||||
|  |         benchmark_score[benchmark_number] = 0 | ||||||
|  |  | ||||||
|  |         cx16.set_screen_mode(3) | ||||||
|  |         txt.uppercase() | ||||||
|  |         txt.color2(1, 6) | ||||||
|  |         uword total_score | ||||||
|  |         benchmark_number = 0 | ||||||
|  |         txt.print("\nscore benchmark (v12)\n\n") | ||||||
|  |         do { | ||||||
|  |             txt.spc() | ||||||
|  |             txt.print_uw(benchmark_score[benchmark_number]) | ||||||
|  |             txt.column(6) | ||||||
|  |             txt.print(benchmark_names[benchmark_number]) | ||||||
|  |             total_score += benchmark_score[benchmark_number] | ||||||
|  |             txt.nl() | ||||||
|  |             benchmark_number++ | ||||||
|  |         } until benchmark_names[benchmark_number]==0 | ||||||
|  |  | ||||||
|  |         txt.print("\n\ntotal score : ") | ||||||
|  |         txt.print_uw(total_score) | ||||||
|  |         txt.print(" (higher=better)\n") | ||||||
|  |  | ||||||
|  |         sub announce_benchmark(str name) { | ||||||
|  |             benchmark_names[benchmark_number] = name | ||||||
|  |             cx16.set_screen_mode(3) | ||||||
|  |             txt.uppercase() | ||||||
|  |             txt.color2(1, 6) | ||||||
|  |             txt.clear_screen() | ||||||
|  |             txt.plot(4, 6) | ||||||
|  |             txt.print(benchmark_names[benchmark_number]) | ||||||
|  |             txt.nl() | ||||||
|  |             sys.wait(60) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										38
									
								
								build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  | import org.jetbrains.kotlin.gradle.dsl.JvmTarget | ||||||
|  | import org.jetbrains.kotlin.gradle.dsl.JvmDefaultMode | ||||||
|  | import org.jetbrains.kotlin.gradle.internal.config.LanguageFeature | ||||||
|  | import org.jetbrains.kotlin.gradle.dsl.KotlinVersion | ||||||
|  |  | ||||||
|  |  | ||||||
|  | plugins { | ||||||
|  |     kotlin("jvm") version "2.2.20" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | allprojects { | ||||||
|  |     apply(plugin="kotlin") | ||||||
|  |  | ||||||
|  |     repositories { | ||||||
|  |         mavenLocal() | ||||||
|  |         mavenCentral() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     kotlin { | ||||||
|  |         compilerOptions { | ||||||
|  |             freeCompilerArgs = listOf("-Xwhen-guards") | ||||||
|  |             jvmTarget = JvmTarget.JVM_11 | ||||||
|  |             jvmDefault = JvmDefaultMode.NO_COMPATIBILITY | ||||||
|  |             // languageVersion.set(KotlinVersion.KOTLIN_2_3) | ||||||
|  |         } | ||||||
|  |         sourceSets.all { | ||||||
|  |             languageSettings { | ||||||
|  |                 // enable language features like so: | ||||||
|  |                 // enableLanguageFeature(LanguageFeature.WhenGuards.name) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     java { | ||||||
|  |         targetCompatibility = JavaVersion.VERSION_11 | ||||||
|  |         sourceCompatibility = JavaVersion.VERSION_11 | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								codeCore/build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								codeCore/build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | plugins { | ||||||
|  |     kotlin("jvm") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | dependencies { | ||||||
|  |     // should have no dependencies to other modules | ||||||
|  |     // implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") | ||||||
|  |     implementation("com.michael-bull.kotlin-result:kotlin-result-jvm:2.1.0") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | sourceSets { | ||||||
|  |     main { | ||||||
|  |         java { | ||||||
|  |             srcDir("${project.projectDir}/src") | ||||||
|  |         } | ||||||
|  |         resources { | ||||||
|  |             srcDir("${project.projectDir}/res") | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // note: there are no unit tests in this module! | ||||||
							
								
								
									
										14
									
								
								codeCore/codeCore.iml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								codeCore/codeCore.iml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <module type="JAVA_MODULE" version="4"> | ||||||
|  |   <component name="NewModuleRootManager" inherit-compiler-output="true"> | ||||||
|  |     <exclude-output /> | ||||||
|  |     <content url="file://$MODULE_DIR$"> | ||||||
|  |       <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> | ||||||
|  |       <excludeFolder url="file://$MODULE_DIR$/build" /> | ||||||
|  |     </content> | ||||||
|  |     <orderEntry type="inheritedJdk" /> | ||||||
|  |     <orderEntry type="sourceFolder" forTests="false" /> | ||||||
|  |     <orderEntry type="library" name="KotlinJavaRuntime" level="project" /> | ||||||
|  |     <orderEntry type="library" name="michael.bull.kotlin.result.jvm" level="project" /> | ||||||
|  |   </component> | ||||||
|  | </module> | ||||||
							
								
								
									
										32
									
								
								codeCore/src/prog8/code/Globals.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								codeCore/src/prog8/code/Globals.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | package prog8.code | ||||||
|  |  | ||||||
|  | import java.io.IOException | ||||||
|  | import java.nio.file.Path | ||||||
|  | import kotlin.io.path.absolute | ||||||
|  |  | ||||||
|  |  | ||||||
|  | const val INTERNED_STRINGS_MODULENAME = "prog8_interned_strings" | ||||||
|  |  | ||||||
|  | val PROG8_CONTAINER_MODULES = arrayOf(INTERNED_STRINGS_MODULENAME)      // option to add more if needed one day | ||||||
|  |  | ||||||
|  | // all automatically generated labels everywhere need to have the same label name prefix: | ||||||
|  | const val GENERATED_LABEL_PREFIX = "p8_label_gen_" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Returns the absolute path of the given path, | ||||||
|  |  * where links are replaced by the actual directories, | ||||||
|  |  * and containing no redundant path elements. | ||||||
|  |  * If the path doesn't refer to an existing directory or file on the file system, | ||||||
|  |  * it is returned unchanged. | ||||||
|  |  */ | ||||||
|  | fun Path.sanitize(): Path { | ||||||
|  |     return try { | ||||||
|  |         this.toRealPath().normalize() | ||||||
|  |     } catch (_: java.nio.file.NoSuchFileException) { | ||||||
|  |         this.absolute().normalize() | ||||||
|  |         //throw NoSuchFileException(this.toFile(), null, nx.reason).also { it.initCause(nx) } | ||||||
|  |     } catch (iox: IOException) { | ||||||
|  |         throw FileSystemException(this.toFile()).also { it.initCause(iox) } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										170
									
								
								codeCore/src/prog8/code/core/BuiltinFunctions.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								codeCore/src/prog8/code/core/BuiltinFunctions.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,170 @@ | |||||||
|  | package prog8.code.core | ||||||
|  |  | ||||||
|  | class ReturnConvention(val dt: BaseDataType?, val reg: RegisterOrPair?) | ||||||
|  | class ParamConvention(val dt: BaseDataType, val reg: RegisterOrPair?, val variable: Boolean) | ||||||
|  | class CallConvention(val params: List<ParamConvention>, val returns: ReturnConvention) { | ||||||
|  |     override fun toString(): String { | ||||||
|  |         val paramConvs =  params.mapIndexed { index, it -> | ||||||
|  |             when { | ||||||
|  |                 it.reg!=null -> "$index:${it.reg}" | ||||||
|  |                 it.variable -> "$index:variable" | ||||||
|  |                 else -> "$index:???" | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         val returnConv = | ||||||
|  |             when { | ||||||
|  |                 returns.reg == RegisterOrPair.FAC1 -> "floatFAC1" | ||||||
|  |                 returns.reg != null -> returns.reg.toString() | ||||||
|  |                 else -> "<no returnvalue>" | ||||||
|  |             } | ||||||
|  |         return "CallConvention[" + paramConvs.joinToString() + " ; returns: $returnConv]" | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class FParam(val name: String, vararg val possibleDatatypes: BaseDataType) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | private val IterableDatatypes = arrayOf(BaseDataType.STR, BaseDataType.ARRAY, BaseDataType.ARRAY_SPLITW) | ||||||
|  | private val IntegerDatatypes = arrayOf(BaseDataType.UBYTE, BaseDataType.BYTE, BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.LONG) | ||||||
|  | private val NumericDatatypes = arrayOf(BaseDataType.UBYTE, BaseDataType.BYTE, BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.LONG, BaseDataType.FLOAT) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class FSignature(val pure: Boolean,      // does it have side effects? | ||||||
|  |                  val returnType: BaseDataType?, | ||||||
|  |                  vararg val parameters: FParam) { | ||||||
|  |  | ||||||
|  |     fun callConvention(actualParamTypes: List<BaseDataType>): CallConvention { | ||||||
|  |         val returns: ReturnConvention = when (returnType) { | ||||||
|  |             BaseDataType.UBYTE, BaseDataType.BYTE -> ReturnConvention(returnType, RegisterOrPair.A) | ||||||
|  |             BaseDataType.UWORD, BaseDataType.WORD -> ReturnConvention(returnType, RegisterOrPair.AY) | ||||||
|  |             BaseDataType.LONG -> ReturnConvention(returnType, RegisterOrPair.R14R15_32) | ||||||
|  |             BaseDataType.FLOAT -> ReturnConvention(returnType, RegisterOrPair.FAC1) | ||||||
|  |             in IterableDatatypes -> ReturnConvention(returnType!!, RegisterOrPair.AY) | ||||||
|  |             null -> ReturnConvention(null, null) | ||||||
|  |             else -> { | ||||||
|  |                 // return type depends on arg type | ||||||
|  |                 when (val paramType = actualParamTypes.first()) { | ||||||
|  |                     BaseDataType.UBYTE, BaseDataType.BYTE -> ReturnConvention(paramType, RegisterOrPair.A) | ||||||
|  |                     BaseDataType.UWORD, BaseDataType.WORD -> ReturnConvention(paramType, RegisterOrPair.AY) | ||||||
|  |                     BaseDataType.LONG -> ReturnConvention(returnType, RegisterOrPair.R14R15_32) | ||||||
|  |                     BaseDataType.FLOAT -> ReturnConvention(paramType, RegisterOrPair.FAC1) | ||||||
|  |                     in IterableDatatypes -> ReturnConvention(paramType, RegisterOrPair.AY) | ||||||
|  |                     else -> ReturnConvention(paramType, null) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return when { | ||||||
|  |             actualParamTypes.isEmpty() -> CallConvention(emptyList(), returns) | ||||||
|  |             actualParamTypes.size==1 -> { | ||||||
|  |                 // One parameter goes via register/registerpair. | ||||||
|  |                 // this avoids repeated code for every caller to store the value in the subroutine's argument variable. | ||||||
|  |                 // (that store is still done, but only coded once at the start at the subroutine itself rather than at every call site). | ||||||
|  |                 val paramConv = when(val paramType = actualParamTypes[0]) { | ||||||
|  |                     BaseDataType.UBYTE, BaseDataType.BYTE -> ParamConvention(paramType, RegisterOrPair.A, false) | ||||||
|  |                     BaseDataType.UWORD, BaseDataType.WORD -> ParamConvention(paramType, RegisterOrPair.AY, false) | ||||||
|  |                     BaseDataType.LONG -> ParamConvention(paramType, RegisterOrPair.R14R15_32, false) | ||||||
|  |                     BaseDataType.FLOAT -> ParamConvention(paramType, RegisterOrPair.AY, false)      // NOTE: for builtin functions, floating point arguments are passed by reference (so you get a pointer in AY) | ||||||
|  |                     in IterableDatatypes -> ParamConvention(paramType, RegisterOrPair.AY, false) | ||||||
|  |                     else -> ParamConvention(paramType, null, false) | ||||||
|  |                 } | ||||||
|  |                 CallConvention(listOf(paramConv), returns) | ||||||
|  |             } | ||||||
|  |             actualParamTypes.size==2 && (actualParamTypes[0].isByte && actualParamTypes[1].isWord) -> { | ||||||
|  |                 TODO("opportunity to pass word+byte arguments in A,Y and X registers but not implemented yet") | ||||||
|  |             } | ||||||
|  |             actualParamTypes.size==2 && (actualParamTypes[0].isWord && actualParamTypes[1].isByte) -> { | ||||||
|  |                 TODO("opportunity to pass word+byte arguments in A,Y and X registers but not implemented yet") | ||||||
|  |             } | ||||||
|  |             actualParamTypes.size==3 && actualParamTypes.all { it.isByte } -> { | ||||||
|  |                 TODO("opportunity to pass 3 byte arguments in A,Y and X registers but not implemented yet") | ||||||
|  |             } | ||||||
|  |             else -> { | ||||||
|  |                 // multiple parameters go via variables | ||||||
|  |                 val paramConvs = actualParamTypes.map { ParamConvention(it, null, true) } | ||||||
|  |                 CallConvention(paramConvs, returns) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | val BuiltinFunctions: Map<String, FSignature> = mapOf( | ||||||
|  |     "setlsb"  to FSignature(false, null, FParam("variable", BaseDataType.WORD, BaseDataType.UWORD), FParam("value", BaseDataType.BYTE, BaseDataType.UBYTE)), | ||||||
|  |     "setmsb"  to FSignature(false, null, FParam("variable", BaseDataType.WORD, BaseDataType.UWORD), FParam("value", BaseDataType.BYTE, BaseDataType.UBYTE)), | ||||||
|  |     "rol"     to FSignature(false, null, FParam("item", BaseDataType.UBYTE, BaseDataType.UWORD, BaseDataType.LONG)), | ||||||
|  |     "ror"     to FSignature(false, null, FParam("item", BaseDataType.UBYTE, BaseDataType.UWORD, BaseDataType.LONG)), | ||||||
|  |     "rol2"    to FSignature(false, null, FParam("item", BaseDataType.UBYTE, BaseDataType.UWORD, BaseDataType.LONG)), | ||||||
|  |     "ror2"    to FSignature(false, null, FParam("item", BaseDataType.UBYTE, BaseDataType.UWORD, BaseDataType.LONG)), | ||||||
|  |     "cmp"     to FSignature(false, null, FParam("value1", *IntegerDatatypes), FParam("value2", *NumericDatatypes)),  // cmp returns result in the cpu status flags, but not asa proper return value | ||||||
|  |     "prog8_lib_stringcompare"     to FSignature(true, BaseDataType.BYTE, FParam("str1", BaseDataType.STR), FParam("str2", BaseDataType.STR)), | ||||||
|  |     "prog8_lib_square_byte"       to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.BYTE, BaseDataType.UBYTE)), | ||||||
|  |     "prog8_lib_square_word"       to FSignature(true, BaseDataType.UWORD, FParam("value", BaseDataType.WORD, BaseDataType.UWORD)), | ||||||
|  |     "prog8_lib_structalloc"       to FSignature(true, BaseDataType.UWORD), | ||||||
|  |     "abs"           to FSignature(true, null, FParam("value", *NumericDatatypes)), | ||||||
|  |     "abs__byte"     to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.BYTE)), | ||||||
|  |     "abs__word"     to FSignature(true, BaseDataType.UWORD, FParam("value", BaseDataType.WORD)), | ||||||
|  |     "abs__long"     to FSignature(true, BaseDataType.LONG, FParam("value", BaseDataType.LONG)), | ||||||
|  |     "abs__float"    to FSignature(true, BaseDataType.FLOAT, FParam("value", BaseDataType.FLOAT)), | ||||||
|  |     "len"           to FSignature(true, BaseDataType.UWORD, FParam("values", *IterableDatatypes)), | ||||||
|  |     "sizeof"        to FSignature(true, BaseDataType.UBYTE, FParam("object", *(BaseDataType.entries - BaseDataType.STRUCT_INSTANCE).toTypedArray())), | ||||||
|  |     "offsetof"      to FSignature(true, BaseDataType.UBYTE, FParam("field", BaseDataType.UBYTE)), | ||||||
|  |     "sgn"           to FSignature(true, BaseDataType.BYTE, FParam("value", *NumericDatatypes)), | ||||||
|  |     "sqrt"          to FSignature(true, null, FParam("value", *NumericDatatypes)), | ||||||
|  |     "sqrt__ubyte"   to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.UBYTE)), | ||||||
|  |     "sqrt__uword"   to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.UWORD)), | ||||||
|  |     "sqrt__float"   to FSignature(true, BaseDataType.FLOAT, FParam("value", BaseDataType.FLOAT)), | ||||||
|  |     "divmod"        to FSignature(false, null, FParam("dividend", BaseDataType.UBYTE, BaseDataType.UWORD), FParam("divisor", BaseDataType.UBYTE, BaseDataType.UWORD), FParam("quotient", BaseDataType.UBYTE, BaseDataType.UWORD), FParam("remainder", BaseDataType.UBYTE, BaseDataType.UWORD)), | ||||||
|  |     "divmod__ubyte" to FSignature(false, null, FParam("dividend", BaseDataType.UBYTE), FParam("divisor", BaseDataType.UBYTE), FParam("quotient", BaseDataType.UBYTE), FParam("remainder", BaseDataType.UBYTE)), | ||||||
|  |     "divmod__uword" to FSignature(false, null, FParam("dividend", BaseDataType.UWORD), FParam("divisor", BaseDataType.UWORD), FParam("quotient", BaseDataType.UWORD), FParam("remainder", BaseDataType.UWORD)), | ||||||
|  |     "lsb"           to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.LONG)), | ||||||
|  |     "lsb__long"     to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.LONG)), | ||||||
|  |     "msb"           to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.LONG)), | ||||||
|  |     "msb__long"     to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.LONG)), | ||||||
|  |     "lsw"           to FSignature(true, BaseDataType.UWORD, FParam("value", BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.LONG)), | ||||||
|  |     "msw"           to FSignature(true, BaseDataType.UWORD, FParam("value", BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.LONG)), | ||||||
|  |     "mkword"        to FSignature(true, BaseDataType.UWORD, FParam("msb", BaseDataType.UBYTE), FParam("lsb", BaseDataType.UBYTE)), | ||||||
|  |     "mklong"        to FSignature(true, BaseDataType.LONG, FParam("msb", BaseDataType.UBYTE), FParam("b2", BaseDataType.UBYTE), FParam("b1", BaseDataType.UBYTE), FParam("lsb", BaseDataType.UBYTE)), | ||||||
|  |     "mklong2"       to FSignature(true, BaseDataType.LONG, FParam("msw", BaseDataType.UWORD), FParam("lsw", BaseDataType.UWORD)), | ||||||
|  |     "clamp"         to FSignature(true, null, FParam("value", BaseDataType.BYTE), FParam("minimum", BaseDataType.BYTE), FParam("maximum", BaseDataType.BYTE)), | ||||||
|  |     "clamp__byte"   to FSignature(true, BaseDataType.BYTE, FParam("value", BaseDataType.BYTE), FParam("minimum", BaseDataType.BYTE), FParam("maximum", BaseDataType.BYTE)), | ||||||
|  |     "clamp__ubyte"  to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.UBYTE), FParam("minimum", BaseDataType.UBYTE), FParam("maximum", BaseDataType.UBYTE)), | ||||||
|  |     "clamp__word"   to FSignature(true, BaseDataType.WORD, FParam("value", BaseDataType.WORD), FParam("minimum", BaseDataType.WORD), FParam("maximum", BaseDataType.WORD)), | ||||||
|  |     "clamp__uword"  to FSignature(true, BaseDataType.UWORD, FParam("value", BaseDataType.UWORD), FParam("minimum", BaseDataType.UWORD), FParam("maximum", BaseDataType.UWORD)), | ||||||
|  |     "clamp__long"   to FSignature(true, BaseDataType.LONG, FParam("value", BaseDataType.LONG), FParam("minimum", BaseDataType.LONG), FParam("maximum", BaseDataType.LONG)), | ||||||
|  |     "min"           to FSignature(true, null, FParam("val1", BaseDataType.BYTE), FParam("val2", BaseDataType.BYTE)), | ||||||
|  |     "min__byte"     to FSignature(true, BaseDataType.BYTE, FParam("val1", BaseDataType.BYTE), FParam("val2", BaseDataType.BYTE)), | ||||||
|  |     "min__ubyte"    to FSignature(true, BaseDataType.UBYTE, FParam("val1", BaseDataType.UBYTE), FParam("val2", BaseDataType.UBYTE)), | ||||||
|  |     "min__word"     to FSignature(true, BaseDataType.WORD, FParam("val1", BaseDataType.WORD), FParam("val2", BaseDataType.WORD)), | ||||||
|  |     "min__uword"    to FSignature(true, BaseDataType.UWORD, FParam("val1", BaseDataType.UWORD), FParam("val2", BaseDataType.UWORD)), | ||||||
|  |     "min__long"     to FSignature(true, BaseDataType.LONG, FParam("val1", BaseDataType.LONG), FParam("val2", BaseDataType.LONG)), | ||||||
|  |     "max"           to FSignature(true, null, FParam("val1", BaseDataType.BYTE), FParam("val2", BaseDataType.BYTE)), | ||||||
|  |     "max__byte"     to FSignature(true, BaseDataType.BYTE, FParam("val1", BaseDataType.BYTE), FParam("val2", BaseDataType.BYTE)), | ||||||
|  |     "max__ubyte"    to FSignature(true, BaseDataType.UBYTE, FParam("val1", BaseDataType.UBYTE), FParam("val2", BaseDataType.UBYTE)), | ||||||
|  |     "max__word"     to FSignature(true, BaseDataType.WORD, FParam("val1", BaseDataType.WORD), FParam("val2", BaseDataType.WORD)), | ||||||
|  |     "max__uword"    to FSignature(true, BaseDataType.UWORD, FParam("val1", BaseDataType.UWORD), FParam("val2", BaseDataType.UWORD)), | ||||||
|  |     "max__long"     to FSignature(true, BaseDataType.LONG, FParam("val1", BaseDataType.LONG), FParam("val2", BaseDataType.LONG)), | ||||||
|  |     "peek"          to FSignature(true, BaseDataType.UBYTE, FParam("address", BaseDataType.UWORD)), | ||||||
|  |     "peekbool"      to FSignature(true, BaseDataType.BOOL, FParam("address", BaseDataType.UWORD)), | ||||||
|  |     "peekw"         to FSignature(true, BaseDataType.UWORD, FParam("address", BaseDataType.UWORD)), | ||||||
|  |     "peekl"         to FSignature(true, BaseDataType.LONG, FParam("address", BaseDataType.UWORD)), | ||||||
|  |     "peekf"         to FSignature(true, BaseDataType.FLOAT, FParam("address", BaseDataType.UWORD)), | ||||||
|  |     "poke"          to FSignature(false, null, FParam("address", BaseDataType.UWORD), FParam("value", BaseDataType.UBYTE, BaseDataType.BYTE)), | ||||||
|  |     "pokebool"      to FSignature(false, null, FParam("address", BaseDataType.UWORD), FParam("value", BaseDataType.BOOL)), | ||||||
|  |     "pokebowl"      to FSignature(false, null, FParam("address", BaseDataType.UWORD), FParam("value", BaseDataType.BOOL)), | ||||||
|  |     "pokew"         to FSignature(false, null, FParam("address", BaseDataType.UWORD), FParam("value", BaseDataType.UWORD, BaseDataType.WORD)), | ||||||
|  |     "pokel"         to FSignature(false, null, FParam("address", BaseDataType.UWORD), FParam("value", BaseDataType.LONG)), | ||||||
|  |     "pokef"         to FSignature(false, null, FParam("address", BaseDataType.UWORD), FParam("value", BaseDataType.FLOAT)), | ||||||
|  |     "pokemon"       to FSignature(false, BaseDataType.UBYTE, FParam("address", BaseDataType.UWORD), FParam("value", BaseDataType.UBYTE)), | ||||||
|  |     "rsave"         to FSignature(false, null), | ||||||
|  |     "rrestore"      to FSignature(false, null), | ||||||
|  |     "memory"        to FSignature(true, BaseDataType.UWORD, FParam("name", BaseDataType.STR), FParam("size", BaseDataType.UWORD), FParam("alignment", BaseDataType.UWORD)), | ||||||
|  |     "callfar"       to FSignature(false, BaseDataType.UWORD, FParam("bank", BaseDataType.UBYTE), FParam("address", BaseDataType.UWORD), FParam("arg", BaseDataType.UWORD)), | ||||||
|  |     "callfar2"      to FSignature(false, BaseDataType.UWORD, FParam("bank", BaseDataType.UBYTE), FParam("address", BaseDataType.UWORD), FParam("argA", BaseDataType.UBYTE), FParam("argX", BaseDataType.UBYTE), FParam("argY", BaseDataType.UBYTE), FParam("argC", BaseDataType.BOOL)), | ||||||
|  |     "call"          to FSignature(false, BaseDataType.UWORD, FParam("address", BaseDataType.UWORD)), | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | val InplaceModifyingBuiltinFunctions = setOf( | ||||||
|  |     "setlsb", "setmsb", | ||||||
|  |     "rol", "ror", "rol2", "ror2", | ||||||
|  |     "divmod", "divmod__ubyte", "divmod__uword" | ||||||
|  | ) | ||||||
							
								
								
									
										45
									
								
								codeCore/src/prog8/code/core/CompilationOptions.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								codeCore/src/prog8/code/core/CompilationOptions.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | |||||||
|  | package prog8.code.core | ||||||
|  |  | ||||||
|  | import java.nio.file.Path | ||||||
|  | import kotlin.io.path.Path | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class CompilationOptions(val output: OutputType, | ||||||
|  |                          val launcher: CbmPrgLauncherType, | ||||||
|  |                          val zeropage: ZeropageType, | ||||||
|  |                          val zpReserved: List<UIntRange>, | ||||||
|  |                          val zpAllowed: List<UIntRange>, | ||||||
|  |                          val floats: Boolean, | ||||||
|  |                          val noSysInit: Boolean, | ||||||
|  |                          val romable: Boolean, | ||||||
|  |                          val compTarget: ICompilationTarget, | ||||||
|  |                          val compilerVersion: String, | ||||||
|  |                          // these are set later, based on command line arguments or options in the source code: | ||||||
|  |                          var loadAddress: UInt, | ||||||
|  |                          var memtopAddress: UInt, | ||||||
|  |                          var warnSymbolShadowing: Boolean = false, | ||||||
|  |                          var optimize: Boolean = false, | ||||||
|  |                          var asmQuiet: Boolean = false, | ||||||
|  |                          var asmListfile: Boolean = false, | ||||||
|  |                          var includeSourcelines: Boolean = false, | ||||||
|  |                          var dumpVariables: Boolean = false, | ||||||
|  |                          var dumpSymbols: Boolean = false, | ||||||
|  |                          var experimentalCodegen: Boolean = false, | ||||||
|  |                          var varsHighBank: Int? = null, | ||||||
|  |                          var varsGolden: Boolean = false, | ||||||
|  |                          var slabsHighBank: Int? = null, | ||||||
|  |                          var slabsGolden: Boolean = false, | ||||||
|  |                          var breakpointCpuInstruction: String? = null, | ||||||
|  |                          var ignoreFootguns: Boolean = false, | ||||||
|  |                          var outputDir: Path = Path(""), | ||||||
|  |                          var quiet: Boolean = false, | ||||||
|  |                          var symbolDefs: Map<String, String> = emptyMap() | ||||||
|  | ) { | ||||||
|  |     init { | ||||||
|  |         compTarget.initializeMemoryAreas(this) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     companion object { | ||||||
|  |         val AllZeropageAllowed: List<UIntRange> = listOf(0u..255u) | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										97
									
								
								codeCore/src/prog8/code/core/Conversions.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								codeCore/src/prog8/code/core/Conversions.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | |||||||
|  | package prog8.code.core | ||||||
|  |  | ||||||
|  | import kotlin.math.abs | ||||||
|  | import kotlin.math.pow | ||||||
|  |  | ||||||
|  | val powersOfTwoFloat = (0..16).map { (2.0).pow(it) }.toTypedArray() | ||||||
|  | val negativePowersOfTwoFloat = powersOfTwoFloat.map { -it }.toTypedArray() | ||||||
|  | val powersOfTwoInt = (0..16).map { 2.0.pow(it).toInt() }.toTypedArray() | ||||||
|  |  | ||||||
|  | fun Number.toHex(): String { | ||||||
|  |     //  0..15 -> "0".."15" | ||||||
|  |     //  16..255 -> "$10".."$ff" | ||||||
|  |     //  256..65536 -> "$0100".."$ffff" | ||||||
|  |     //  larger -> "$12345678" | ||||||
|  |     // negative values are prefixed with '-'. | ||||||
|  |     val integer = this.toLong() | ||||||
|  |     if(integer<0) | ||||||
|  |         return '-' + abs(integer).toHex() | ||||||
|  |     return when (integer) { | ||||||
|  |         in 0 until 16 -> integer.toString() | ||||||
|  |         in 0 until 0x100 -> "$"+integer.toString(16).padStart(2,'0') | ||||||
|  |         in 0 until 0x10000 -> "$"+integer.toString(16).padStart(4,'0') | ||||||
|  |         else -> "$"+integer.toString(16).padStart(8,'0') | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fun UInt.toHex(): String { | ||||||
|  |     //  0..15 -> "0".."15" | ||||||
|  |     //  16..255 -> "$10".."$ff" | ||||||
|  |     //  256..65536 -> "$0100".."$ffff" | ||||||
|  |     //  larger -> "$12345678" | ||||||
|  |     return when (this) { | ||||||
|  |         in 0u until 16u -> this.toString() | ||||||
|  |         in 0u until 0x100u -> "$"+this.toString(16).padStart(2,'0') | ||||||
|  |         in 0u until 0x10000u -> "$"+this.toString(16).padStart(4,'0') | ||||||
|  |         else -> "$"+this.toString(16).padStart(8,'0') | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fun Char.escape(): Char = this.toString().escape()[0] | ||||||
|  |  | ||||||
|  | fun String.escape(): String { | ||||||
|  |     val es = this.map { | ||||||
|  |         when(it) { | ||||||
|  |             '\t' -> "\\t" | ||||||
|  |             '\n' -> "\\n" | ||||||
|  |             '\r' -> "\\r" | ||||||
|  |             '"' -> "\\\"" | ||||||
|  |             in '\u8000'..'\u80ff' -> "\\x" + (it.code - 0x8000).toString(16).padStart(2, '0')       // 'ugly' passthrough hack | ||||||
|  |             in '\u0000'..'\u00ff' -> it.toString() | ||||||
|  |             else -> "\\u" + it.code.toString(16).padStart(4, '0') | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return es.joinToString("") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fun String.unescape(): String { | ||||||
|  |     val result = mutableListOf<Char>() | ||||||
|  |     val iter = this.iterator() | ||||||
|  |     while(iter.hasNext()) { | ||||||
|  |         val c = iter.nextChar() | ||||||
|  |         if(c=='\\') { | ||||||
|  |             val ec = iter.nextChar() | ||||||
|  |             result.add(when(ec) { | ||||||
|  |                 '\\' -> '\\' | ||||||
|  |                 'n' -> '\n' | ||||||
|  |                 'r' -> '\r' | ||||||
|  |                 't' -> '\t' | ||||||
|  |                 '"' -> '"' | ||||||
|  |                 '\'' -> '\'' | ||||||
|  |                 'u' -> { | ||||||
|  |                     try { | ||||||
|  |                         "${iter.nextChar()}${iter.nextChar()}${iter.nextChar()}${iter.nextChar()}".toInt(16).toChar() | ||||||
|  |                     } catch (sb: StringIndexOutOfBoundsException) { | ||||||
|  |                         throw IllegalArgumentException("invalid \\u escape sequence") | ||||||
|  |                     } catch (nf: NumberFormatException) { | ||||||
|  |                         throw IllegalArgumentException("invalid \\u escape sequence") | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 'x' -> { | ||||||
|  |                     try { | ||||||
|  |                         val hex = ("" + iter.nextChar() + iter.nextChar()).toInt(16) | ||||||
|  |                         (0x8000 + hex).toChar()         // 'ugly' pass-through hack | ||||||
|  |                     } catch (sb: StringIndexOutOfBoundsException) { | ||||||
|  |                         throw IllegalArgumentException("invalid \\x escape sequence") | ||||||
|  |                     } catch (nf: NumberFormatException) { | ||||||
|  |                         throw IllegalArgumentException("invalid \\x escape sequence") | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 else -> throw IllegalArgumentException("invalid escape char in string: \\$ec") | ||||||
|  |             }) | ||||||
|  |         } else { | ||||||
|  |             result.add(c) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return result.joinToString("") | ||||||
|  | } | ||||||
							
								
								
									
										534
									
								
								codeCore/src/prog8/code/core/Enumerations.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										534
									
								
								codeCore/src/prog8/code/core/Enumerations.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,534 @@ | |||||||
|  | package prog8.code.core | ||||||
|  |  | ||||||
|  | import java.util.* | ||||||
|  |  | ||||||
|  | enum class BaseDataType { | ||||||
|  |     UBYTE,              // pass by value            8 bits unsigned | ||||||
|  |     BYTE,               // pass by value            8 bits signed | ||||||
|  |     UWORD,              // pass by value            16 bits unsigned | ||||||
|  |     WORD,               // pass by value            16 bits signed | ||||||
|  |     LONG,               // pass by value            32 bits signed | ||||||
|  |     FLOAT,              // pass by value            machine dependent | ||||||
|  |     BOOL,               // pass by value            bit 0 of an 8-bit byte | ||||||
|  |     STR,                // pass by reference | ||||||
|  |     ARRAY,              // pass by reference, subtype is the element type | ||||||
|  |     ARRAY_SPLITW,       // pass by reference, split word layout, subtype is the element type (restricted to word types) | ||||||
|  |     POINTER,            // typed pointer, subtype is whatever type is pointed to | ||||||
|  |     STRUCT_INSTANCE,    // the actual instance of a struct (not directly supported in the language yet, but we need its type) | ||||||
|  |     ARRAY_POINTER,      // array of pointers (uwords), subtype is whatever type each element points to | ||||||
|  |     UNDEFINED; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     fun largerSizeThan(other: BaseDataType) = | ||||||
|  |         when { | ||||||
|  |             this == other -> false | ||||||
|  |             this.isByteOrBool -> false | ||||||
|  |             this.isWord -> other.isByteOrBool | ||||||
|  |             this == LONG -> other.isByteOrBool || other.isWord | ||||||
|  |             this == STR && other == UWORD || this == UWORD && other == STR -> false | ||||||
|  |             this.isArray && other.isArray -> false | ||||||
|  |             this.isArray -> other != FLOAT | ||||||
|  |             this == STR -> other != FLOAT | ||||||
|  |             this.isPointer -> other.isByteOrBool | ||||||
|  |             else -> true | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     fun equalsSize(other: BaseDataType) = | ||||||
|  |         when { | ||||||
|  |             this == other -> true | ||||||
|  |             this.isArray && other.isArray -> true | ||||||
|  |             this.isByteOrBool -> other.isByteOrBool | ||||||
|  |             this.isWord -> other.isWord || other.isPointer | ||||||
|  |             this.isPointer -> other.isWord | ||||||
|  |             this == STR && other== UWORD || this== UWORD && other== STR -> true | ||||||
|  |             this == STR && other.isArray -> true | ||||||
|  |             this.isArray && other == STR -> true | ||||||
|  |             else -> false | ||||||
|  |         } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | val BaseDataType.isByte get() = this in arrayOf(BaseDataType.UBYTE, BaseDataType.BYTE) | ||||||
|  | val BaseDataType.isByteOrBool get() = this in arrayOf(BaseDataType.UBYTE, BaseDataType.BYTE, BaseDataType.BOOL) | ||||||
|  | val BaseDataType.isWord get() = this in arrayOf(BaseDataType.UWORD, BaseDataType.WORD) | ||||||
|  | val BaseDataType.isLong get() = this == BaseDataType.LONG | ||||||
|  | val BaseDataType.isInteger get() = this in arrayOf(BaseDataType.UBYTE, BaseDataType.BYTE, BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.LONG) | ||||||
|  | val BaseDataType.isIntegerOrBool get() = this in arrayOf(BaseDataType.UBYTE, BaseDataType.BYTE, BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.LONG, BaseDataType.BOOL) | ||||||
|  | val BaseDataType.isWordOrByteOrBool get() = this in arrayOf(BaseDataType.UBYTE, BaseDataType.BYTE, BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.BOOL) | ||||||
|  | val BaseDataType.isNumeric get() = this == BaseDataType.FLOAT || this.isInteger | ||||||
|  | val BaseDataType.isNumericOrBool get() = this == BaseDataType.BOOL || this.isNumeric | ||||||
|  | val BaseDataType.isSigned get() = this in arrayOf(BaseDataType.BYTE, BaseDataType.WORD, BaseDataType.LONG, BaseDataType.FLOAT) | ||||||
|  | val BaseDataType.isArray get() = this == BaseDataType.ARRAY || this == BaseDataType.ARRAY_SPLITW || this == BaseDataType.ARRAY_POINTER | ||||||
|  | val BaseDataType.isPointer get() = this == BaseDataType.POINTER | ||||||
|  | val BaseDataType.isStructInstance get() = this == BaseDataType.STRUCT_INSTANCE | ||||||
|  | val BaseDataType.isPointerArray get() = this == BaseDataType.ARRAY_POINTER | ||||||
|  | val BaseDataType.isSplitWordArray get() = this == BaseDataType.ARRAY_SPLITW || this == BaseDataType.ARRAY_POINTER       // pointer arrays are also always stored as split uwords | ||||||
|  | val BaseDataType.isIterable get() =  this in arrayOf(BaseDataType.STR, BaseDataType.ARRAY, BaseDataType.ARRAY_SPLITW, BaseDataType.ARRAY_POINTER) | ||||||
|  | val BaseDataType.isPassByRef get() = this.isIterable && !this.isPointer | ||||||
|  | val BaseDataType.isPassByValue get() = !this.isIterable || this.isPointer | ||||||
|  |  | ||||||
|  |  | ||||||
|  | interface ISubType { | ||||||
|  |     val scopedNameString: String | ||||||
|  |     fun memsize(sizer: IMemSizer): Int | ||||||
|  |     fun sameas(other: ISubType): Boolean | ||||||
|  |     fun getFieldType(name: String): DataType? | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class DataType private constructor(val base: BaseDataType, val sub: BaseDataType?, var subType: ISubType?, var subTypeFromAntlr: List<String>?=null) { | ||||||
|  |  | ||||||
|  |     init { | ||||||
|  |         when { | ||||||
|  |             base.isPointerArray -> { | ||||||
|  |                 require(sub!=null || subType!=null || subTypeFromAntlr!=null) | ||||||
|  |             } | ||||||
|  |             base.isArray -> { | ||||||
|  |                 require(sub != null && subType==null && subTypeFromAntlr==null) | ||||||
|  |                 if(base.isSplitWordArray) | ||||||
|  |                     require(sub == BaseDataType.UWORD || sub == BaseDataType.WORD) | ||||||
|  |             } | ||||||
|  |             base==BaseDataType.STR -> require(sub==BaseDataType.UBYTE) { "string subtype should be ubyte" } | ||||||
|  |             base!=BaseDataType.POINTER -> require(sub == null) { "only string, array and pointer base types can have a subtype"} | ||||||
|  |             else -> { | ||||||
|  |                 require(sub == null || (subType == null && subTypeFromAntlr == null)) { | ||||||
|  |                     "sub and subtype can't both be set" | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun equals(other: Any?): Boolean { | ||||||
|  |         if (this === other) return true | ||||||
|  |         if (other !is DataType) return false | ||||||
|  |         return base == other.base && sub == other.sub && (subType==other.subType || subType!!.sameas(other.subType!!)) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun hashCode(): Int = Objects.hash(base, sub, subType) | ||||||
|  |  | ||||||
|  |     fun setActualSubType(actualSubType: ISubType) { | ||||||
|  |         subType = actualSubType | ||||||
|  |         subTypeFromAntlr = null | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     companion object { | ||||||
|  |  | ||||||
|  |         val UBYTE = DataType(BaseDataType.UBYTE, null, null) | ||||||
|  |         val BYTE = DataType(BaseDataType.BYTE, null, null) | ||||||
|  |         val UWORD = DataType(BaseDataType.UWORD, null, null) | ||||||
|  |         val WORD = DataType(BaseDataType.WORD, null, null) | ||||||
|  |         val LONG = DataType(BaseDataType.LONG, null, null) | ||||||
|  |         val FLOAT = DataType(BaseDataType.FLOAT, null, null) | ||||||
|  |         val BOOL = DataType(BaseDataType.BOOL, null, null) | ||||||
|  |         val STR = DataType(BaseDataType.STR, BaseDataType.UBYTE, null) | ||||||
|  |         val UNDEFINED = DataType(BaseDataType.UNDEFINED, null, null) | ||||||
|  |  | ||||||
|  |         private val simpletypes = mapOf( | ||||||
|  |             BaseDataType.UBYTE to DataType(BaseDataType.UBYTE, null, null), | ||||||
|  |             BaseDataType.BYTE to DataType(BaseDataType.BYTE, null, null), | ||||||
|  |             BaseDataType.UWORD to DataType(BaseDataType.UWORD, null, null), | ||||||
|  |             BaseDataType.WORD to DataType(BaseDataType.WORD, null, null), | ||||||
|  |             BaseDataType.LONG to DataType(BaseDataType.LONG, null, null), | ||||||
|  |             BaseDataType.FLOAT to DataType(BaseDataType.FLOAT, null, null), | ||||||
|  |             BaseDataType.BOOL to DataType(BaseDataType.BOOL, null, null), | ||||||
|  |             BaseDataType.STR to DataType(BaseDataType.STR, BaseDataType.UBYTE, null), | ||||||
|  |             BaseDataType.UNDEFINED to DataType(BaseDataType.UNDEFINED, null, null) | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         fun forDt(dt: BaseDataType): DataType { | ||||||
|  |             if(dt.isStructInstance) | ||||||
|  |                 TODO("cannot use struct instance as a data type (yet) - use a pointer instead") | ||||||
|  |             return simpletypes.getValue(dt) | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         fun arrayFor(elementDt: BaseDataType, splitwordarray: Boolean=true): DataType { | ||||||
|  |             require(!elementDt.isPointer) { "use other array constructor for arrays of pointers" } | ||||||
|  |             val actualElementDt = if(elementDt==BaseDataType.STR) BaseDataType.UWORD else elementDt      // array of strings is actually just an array of UWORD pointers | ||||||
|  |             return if(splitwordarray && actualElementDt.isWord) | ||||||
|  |                 DataType(BaseDataType.ARRAY_SPLITW, actualElementDt, null) | ||||||
|  |             else { | ||||||
|  |                 if(actualElementDt.isNumericOrBool) | ||||||
|  |                     DataType(BaseDataType.ARRAY, actualElementDt, null) | ||||||
|  |                 else | ||||||
|  |                     throw NoSuchElementException("invalid basic element dt $elementDt") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         fun arrayOfPointersTo(sub: BaseDataType): DataType = DataType(BaseDataType.ARRAY_POINTER, sub, null) | ||||||
|  |         fun arrayOfPointersTo(structType: ISubType?): DataType = DataType(BaseDataType.ARRAY_POINTER, null, structType) | ||||||
|  |         fun arrayOfPointersFromAntlrTo(sub: BaseDataType?, identifier: List<String>?): DataType = | ||||||
|  |             DataType(BaseDataType.ARRAY_POINTER, sub, null, identifier) | ||||||
|  |  | ||||||
|  |         fun pointer(base: BaseDataType): DataType = DataType(BaseDataType.POINTER, base, null) | ||||||
|  |         fun pointer(dt: DataType): DataType = if(dt.isBasic) | ||||||
|  |                 DataType(BaseDataType.POINTER, dt.base, null) | ||||||
|  |             else | ||||||
|  |                 DataType(BaseDataType.POINTER, null, dt.subType, dt.subTypeFromAntlr) | ||||||
|  |         fun pointer(structType: ISubType): DataType = DataType(BaseDataType.POINTER, null, structType) | ||||||
|  |         fun pointerFromAntlr(identifier: List<String>): DataType = DataType(BaseDataType.POINTER, null, null, identifier) | ||||||
|  |         fun structInstance(type: ISubType?): DataType = DataType(BaseDataType.STRUCT_INSTANCE, sub=null, type) | ||||||
|  |         fun structInstanceFromAntlr(struct: List<String>): DataType = DataType(BaseDataType.STRUCT_INSTANCE, null, null, subTypeFromAntlr = struct) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     fun elementToArray(splitwords: Boolean = true): DataType { | ||||||
|  |         return if (base == BaseDataType.UWORD || base == BaseDataType.WORD || base == BaseDataType.STR) arrayFor(base, splitwords) | ||||||
|  |         else arrayFor(base, false) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun elementType(): DataType = | ||||||
|  |         when { | ||||||
|  |             isPointerArray -> DataType(BaseDataType.POINTER, sub, subType) | ||||||
|  |             base.isArray || base==BaseDataType.STR -> forDt(sub!!) | ||||||
|  |             else -> throw IllegalArgumentException("not an array") | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     fun typeForAddressOf(msb: Boolean): DataType { | ||||||
|  |         if (isUndefined) | ||||||
|  |             return if(msb) pointer(BaseDataType.UBYTE) else UWORD | ||||||
|  |         else { | ||||||
|  |             if (isBasic) | ||||||
|  |                 return pointer(base) | ||||||
|  |             if (isString) | ||||||
|  |                 return pointer(BaseDataType.UBYTE) | ||||||
|  |             if (isPointer) | ||||||
|  |                 return UWORD | ||||||
|  |             if (isArray) { | ||||||
|  |                 if (msb || isSplitWordArray) | ||||||
|  |                     return pointer(BaseDataType.UBYTE) | ||||||
|  |                 val elementDt = elementType() | ||||||
|  |                 require(elementDt.isBasic) | ||||||
|  |                 return pointer(elementDt) | ||||||
|  |             } | ||||||
|  |             if (subType != null) | ||||||
|  |                 return pointer(this) | ||||||
|  |             return UWORD | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun dereference(): DataType { | ||||||
|  |         require(isPointer || isUnsignedWord) | ||||||
|  |         return when { | ||||||
|  |             isUnsignedWord -> forDt(BaseDataType.UBYTE) | ||||||
|  |             sub!=null -> forDt(sub) | ||||||
|  |             subType!=null -> DataType(BaseDataType.STRUCT_INSTANCE, null, subType) | ||||||
|  |             subTypeFromAntlr!=null -> DataType(BaseDataType.STRUCT_INSTANCE, null, null, subTypeFromAntlr) | ||||||
|  |             else -> throw IllegalArgumentException("cannot dereference this pointer type") | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun toString(): String = when(base) { | ||||||
|  |         BaseDataType.ARRAY -> { | ||||||
|  |             when(sub) { | ||||||
|  |                 BaseDataType.BOOL -> "bool[]" | ||||||
|  |                 BaseDataType.FLOAT -> "float[]" | ||||||
|  |                 BaseDataType.BYTE -> "byte[]" | ||||||
|  |                 BaseDataType.WORD -> "word[]" | ||||||
|  |                 BaseDataType.UBYTE -> "ubyte[]" | ||||||
|  |                 BaseDataType.UWORD -> "uword[]" | ||||||
|  |                 BaseDataType.LONG -> "long[]" | ||||||
|  |                 else -> throw IllegalArgumentException("invalid sub type") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         BaseDataType.ARRAY_SPLITW -> { | ||||||
|  |             when(sub) { | ||||||
|  |                 BaseDataType.WORD -> "word[] (split)" | ||||||
|  |                 BaseDataType.UWORD -> "uword[] (split)" | ||||||
|  |                 else -> throw IllegalArgumentException("invalid sub type") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         BaseDataType.POINTER -> { | ||||||
|  |             if(sub!=null) "^^${sub.name.lowercase()}" else if(subType!=null) "^^${subType!!.scopedNameString}" else "^^${subTypeFromAntlr}" | ||||||
|  |         } | ||||||
|  |         BaseDataType.ARRAY_POINTER -> { | ||||||
|  |             if(sub!=null) "^^${sub.name.lowercase()}[] (split)" else if (subType!=null) "^^${subType!!.scopedNameString}[] (split)" else "^^${subTypeFromAntlr}[] (split)" | ||||||
|  |         } | ||||||
|  |         BaseDataType.STRUCT_INSTANCE -> { | ||||||
|  |             sub?.name?.lowercase() ?: if (subType!=null) subType!!.scopedNameString else "$subTypeFromAntlr" | ||||||
|  |         } | ||||||
|  |         else -> base.name.lowercase() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun sourceString(): String = when (base) { | ||||||
|  |         BaseDataType.BOOL -> "bool" | ||||||
|  |         BaseDataType.UBYTE -> "ubyte" | ||||||
|  |         BaseDataType.BYTE -> "byte" | ||||||
|  |         BaseDataType.UWORD -> "uword" | ||||||
|  |         BaseDataType.WORD -> "word" | ||||||
|  |         BaseDataType.LONG -> "long" | ||||||
|  |         BaseDataType.FLOAT -> "float" | ||||||
|  |         BaseDataType.STR -> "str" | ||||||
|  |         BaseDataType.POINTER -> { | ||||||
|  |             when { | ||||||
|  |                 sub!=null -> "^^${sub.name.lowercase()}" | ||||||
|  |                 subType!=null -> "^^${subType!!.scopedNameString}" | ||||||
|  |                 subTypeFromAntlr!=null -> "^^${subTypeFromAntlr!!.joinToString(".")}" | ||||||
|  |                 else -> "?????" | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         BaseDataType.STRUCT_INSTANCE -> { | ||||||
|  |             when { | ||||||
|  |                 sub!=null -> sub.name.lowercase() | ||||||
|  |                 subType!=null -> subType!!.scopedNameString | ||||||
|  |                 subTypeFromAntlr!=null -> subTypeFromAntlr!!.joinToString(".") | ||||||
|  |                 else -> "?????" | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         BaseDataType.ARRAY_POINTER -> { | ||||||
|  |             when { | ||||||
|  |                 sub!=null -> "^^${sub.name.lowercase()}[" | ||||||
|  |                 subType!=null -> "^^${subType!!.scopedNameString}[" | ||||||
|  |                 subTypeFromAntlr!=null -> "^^${subTypeFromAntlr!!.joinToString(".")}[" | ||||||
|  |                 else -> "????? [" | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         BaseDataType.ARRAY -> { | ||||||
|  |             when(sub) { | ||||||
|  |                 BaseDataType.UBYTE -> "ubyte[" | ||||||
|  |                 BaseDataType.UWORD -> "@nosplit uword[" | ||||||
|  |                 BaseDataType.BOOL -> "bool[" | ||||||
|  |                 BaseDataType.BYTE -> "byte[" | ||||||
|  |                 BaseDataType.WORD -> "@nosplit word[" | ||||||
|  |                 BaseDataType.LONG -> "long[" | ||||||
|  |                 BaseDataType.FLOAT -> "float[" | ||||||
|  |                 else -> throw IllegalArgumentException("invalid sub type") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         BaseDataType.ARRAY_SPLITW -> { | ||||||
|  |             when(sub) { | ||||||
|  |                 BaseDataType.UWORD -> "uword[" | ||||||
|  |                 BaseDataType.WORD -> "word[" | ||||||
|  |                 else -> throw IllegalArgumentException("invalid sub type") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         BaseDataType.UNDEFINED -> throw IllegalArgumentException("wrong dt") | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // is the type assignable to the given other type (perhaps via a typecast) without loss of precision? | ||||||
|  |     infix fun isAssignableTo(targetType: DataType) = | ||||||
|  |         when(base) { | ||||||
|  |             BaseDataType.BOOL -> targetType.base == BaseDataType.BOOL | ||||||
|  |             BaseDataType.UBYTE -> targetType.base in arrayOf(BaseDataType.UBYTE, BaseDataType.WORD, BaseDataType.UWORD, BaseDataType.LONG, BaseDataType.FLOAT) | ||||||
|  |             BaseDataType.BYTE -> targetType.base in arrayOf(BaseDataType.BYTE, BaseDataType.WORD, BaseDataType.LONG, BaseDataType.FLOAT) | ||||||
|  |             BaseDataType.UWORD -> targetType.base in arrayOf(BaseDataType.UWORD, BaseDataType.LONG, BaseDataType.FLOAT, BaseDataType.POINTER, BaseDataType.ARRAY_POINTER) | ||||||
|  |             BaseDataType.WORD -> targetType.base in arrayOf(BaseDataType.WORD, BaseDataType.LONG, BaseDataType.FLOAT) | ||||||
|  |             BaseDataType.LONG -> targetType.base in arrayOf(BaseDataType.LONG, BaseDataType.FLOAT) | ||||||
|  |             BaseDataType.FLOAT -> targetType.base in arrayOf(BaseDataType.FLOAT) | ||||||
|  |             BaseDataType.STR -> targetType.base in arrayOf(BaseDataType.STR, BaseDataType.UWORD) || (targetType.isPointer && targetType.sub==BaseDataType.UBYTE) | ||||||
|  |             BaseDataType.ARRAY, BaseDataType.ARRAY_SPLITW -> targetType.base in arrayOf(BaseDataType.ARRAY, BaseDataType.ARRAY_SPLITW) && targetType.sub == sub | ||||||
|  |             BaseDataType.POINTER -> { | ||||||
|  |                 when { | ||||||
|  |                     targetType.base == BaseDataType.UWORD || targetType.base == BaseDataType.LONG -> true | ||||||
|  |                     targetType.isPointer -> this.isUnsignedWord || this == targetType | ||||||
|  |                     else -> false | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             BaseDataType.STRUCT_INSTANCE -> false        // we cannot deal with actual struct instances yet in any shape or form (only getting fields from it) | ||||||
|  |             BaseDataType.ARRAY_POINTER -> false | ||||||
|  |             BaseDataType.UNDEFINED -> false | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     fun largerSizeThan(other: DataType): Boolean = base.largerSizeThan(other.base) | ||||||
|  |     fun equalsSize(other: DataType): Boolean = base.equalsSize(other.base) | ||||||
|  |  | ||||||
|  |     // note: for pointer types, size() doesn't return the size of the pointer itself but the size of the thing it points to | ||||||
|  |     fun size(memsizer: IMemSizer): Int = if(sub!=null) { | ||||||
|  |             memsizer.memorySize(sub) | ||||||
|  |         } else if(subType!=null) { | ||||||
|  |             subType!!.memsize(memsizer) | ||||||
|  |         } else { | ||||||
|  |             memsizer.memorySize(base) | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     val isBasic = sub==null && subType==null && subTypeFromAntlr==null | ||||||
|  |     val isUndefined = base == BaseDataType.UNDEFINED | ||||||
|  |     val isByte = base.isByte | ||||||
|  |     val isUnsignedByte = base == BaseDataType.UBYTE | ||||||
|  |     val isSignedByte = base == BaseDataType.BYTE | ||||||
|  |     val isByteOrBool = base.isByteOrBool | ||||||
|  |     val isWord = base.isWord | ||||||
|  |     val isUnsignedWord =  base == BaseDataType.UWORD | ||||||
|  |     val isSignedWord =  base == BaseDataType.WORD | ||||||
|  |     val isInteger = base.isInteger | ||||||
|  |     val isWordOrByteOrBool = base.isWordOrByteOrBool | ||||||
|  |     val isIntegerOrBool = base.isIntegerOrBool | ||||||
|  |     val isNumeric = base.isNumeric | ||||||
|  |     val isNumericOrBool = base.isNumericOrBool | ||||||
|  |     val isSigned = base.isSigned | ||||||
|  |     val isUnsigned = !base.isSigned | ||||||
|  |     val isArray = base.isArray | ||||||
|  |     val isPointer = base.isPointer | ||||||
|  |     val isPointerToByte = base.isPointer && sub?.isByteOrBool==true | ||||||
|  |     val isPointerToWord = base.isPointer && sub?.isWord==true | ||||||
|  |     val isStructInstance = base.isStructInstance | ||||||
|  |     val isPointerArray = base.isPointerArray | ||||||
|  |     val isBoolArray = base.isArray && !base.isPointerArray && sub == BaseDataType.BOOL | ||||||
|  |     val isByteArray = base.isArray && !base.isPointerArray && (sub == BaseDataType.UBYTE || sub == BaseDataType.BYTE) | ||||||
|  |     val isUnsignedByteArray = base.isArray && !base.isPointerArray && sub == BaseDataType.UBYTE | ||||||
|  |     val isSignedByteArray = base.isArray && !base.isPointerArray && sub == BaseDataType.BYTE | ||||||
|  |     val isWordArray = base.isArray && !base.isPointerArray && (sub == BaseDataType.UWORD || sub == BaseDataType.WORD) | ||||||
|  |     val isUnsignedWordArray = base.isArray && !base.isPointerArray && sub == BaseDataType.UWORD | ||||||
|  |     val isSignedWordArray = base.isArray && !base.isPointerArray && sub == BaseDataType.WORD | ||||||
|  |     val isLongArray = base.isArray && sub == BaseDataType.LONG | ||||||
|  |     val isFloatArray = base.isArray && !base.isPointerArray && sub == BaseDataType.FLOAT | ||||||
|  |     val isString = base == BaseDataType.STR | ||||||
|  |     val isBool = base == BaseDataType.BOOL | ||||||
|  |     val isFloat = base == BaseDataType.FLOAT | ||||||
|  |     val isLong = base == BaseDataType.LONG | ||||||
|  |     val isStringly = base == BaseDataType.STR || base == BaseDataType.UWORD || (base == BaseDataType.ARRAY && (sub == BaseDataType.UBYTE || sub == BaseDataType.BYTE)) | ||||||
|  |     val isSplitWordArray = base.isSplitWordArray | ||||||
|  |     val isSplitUnsignedWordArray = base.isSplitWordArray && !base.isPointerArray && sub == BaseDataType.UWORD | ||||||
|  |     val isSplitSignedWordArray = base.isSplitWordArray && !base.isPointerArray && sub == BaseDataType.WORD | ||||||
|  |     val isIterable =  base.isIterable | ||||||
|  |     val isPassByRef = base.isPassByRef | ||||||
|  |     val isPassByValue = base.isPassByValue | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | enum class CpuRegister { | ||||||
|  |     A, | ||||||
|  |     X, | ||||||
|  |     Y | ||||||
|  | } | ||||||
|  |  | ||||||
|  | enum class RegisterOrPair { | ||||||
|  |     A, | ||||||
|  |     X, | ||||||
|  |     Y, | ||||||
|  |     AX, | ||||||
|  |     AY, | ||||||
|  |     XY, | ||||||
|  |     FAC1, | ||||||
|  |     FAC2, | ||||||
|  |     // cx16 virtual registers: | ||||||
|  |     R0, R1, R2, R3, R4, R5, R6, R7, | ||||||
|  |     R8, R9, R10, R11, R12, R13, R14, R15, | ||||||
|  |     // combined virtual registers to store 32 bits longs: | ||||||
|  |     R0R1_32, R2R3_32, R4R5_32, R6R7_32, R8R9_32, R10R11_32, R12R13_32, R14R15_32; | ||||||
|  |  | ||||||
|  |     companion object { | ||||||
|  |         val names by lazy { entries.map { it.toString()} } | ||||||
|  |         fun fromCpuRegister(cpu: CpuRegister): RegisterOrPair { | ||||||
|  |             return when(cpu) { | ||||||
|  |                 CpuRegister.A -> A | ||||||
|  |                 CpuRegister.X -> X | ||||||
|  |                 CpuRegister.Y -> Y | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun startregname() = when(this) { | ||||||
|  |         R0R1_32 -> "r0" | ||||||
|  |         R2R3_32 -> "r2" | ||||||
|  |         R4R5_32 -> "r4" | ||||||
|  |         R6R7_32 -> "r6" | ||||||
|  |         R8R9_32 -> "r8" | ||||||
|  |         R10R11_32 -> "r10" | ||||||
|  |         R12R13_32 -> "r12" | ||||||
|  |         R14R15_32 -> "r14" | ||||||
|  |         else -> throw IllegalArgumentException("must be a combined virtual register $this") | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun asCpuRegister(): CpuRegister = when(this) { | ||||||
|  |         A -> CpuRegister.A | ||||||
|  |         X -> CpuRegister.X | ||||||
|  |         Y -> CpuRegister.Y | ||||||
|  |         else -> throw IllegalArgumentException("no cpu hardware register for $this") | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun asScopedNameVirtualReg(type: DataType?): List<String> { | ||||||
|  |         require(this in Cx16VirtualRegisters) | ||||||
|  |         val suffix = when(type?.base) { | ||||||
|  |             BaseDataType.UBYTE, BaseDataType.BOOL -> "L" | ||||||
|  |             BaseDataType.BYTE -> "sL" | ||||||
|  |             BaseDataType.WORD -> "s" | ||||||
|  |             BaseDataType.UWORD, BaseDataType.POINTER, null -> "" | ||||||
|  |             else -> throw IllegalArgumentException("invalid register param type for cx16 virtual reg") | ||||||
|  |         } | ||||||
|  |         return listOf("cx16", name.lowercase()+suffix) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun isWord() = this==AX || this == AY || this==XY || this in Cx16VirtualRegisters | ||||||
|  |     fun isLong() = this in combinedLongRegisters | ||||||
|  |  | ||||||
|  | }       // only used in parameter and return value specs in asm subroutines | ||||||
|  |  | ||||||
|  | enum class Statusflag { | ||||||
|  |     Pc, | ||||||
|  |     Pz,     // don't use | ||||||
|  |     Pv, | ||||||
|  |     Pn;     // don't use | ||||||
|  |  | ||||||
|  |     companion object { | ||||||
|  |         val names by lazy { entries.map { it.toString()} } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | enum class BranchCondition { | ||||||
|  |     CS, | ||||||
|  |     CC, | ||||||
|  |     EQ,     // EQ == Z | ||||||
|  |     Z, | ||||||
|  |     NE,     // NE == NZ | ||||||
|  |     NZ, | ||||||
|  |     MI,     // MI == NEG | ||||||
|  |     NEG, | ||||||
|  |     PL,     // PL == POS | ||||||
|  |     POS, | ||||||
|  |     VS, | ||||||
|  |     VC | ||||||
|  | } | ||||||
|  |  | ||||||
|  | val Cx16VirtualRegisters = arrayOf( | ||||||
|  |     RegisterOrPair.R0, RegisterOrPair.R1, RegisterOrPair.R2, RegisterOrPair.R3, | ||||||
|  |     RegisterOrPair.R4, RegisterOrPair.R5, RegisterOrPair.R6, RegisterOrPair.R7, | ||||||
|  |     RegisterOrPair.R8, RegisterOrPair.R9, RegisterOrPair.R10, RegisterOrPair.R11, | ||||||
|  |     RegisterOrPair.R12, RegisterOrPair.R13, RegisterOrPair.R14, RegisterOrPair.R15 | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | val combinedLongRegisters = arrayOf( | ||||||
|  |     RegisterOrPair.R0R1_32, | ||||||
|  |     RegisterOrPair.R2R3_32, | ||||||
|  |     RegisterOrPair.R4R5_32, | ||||||
|  |     RegisterOrPair.R6R7_32, | ||||||
|  |     RegisterOrPair.R8R9_32, | ||||||
|  |     RegisterOrPair.R10R11_32, | ||||||
|  |     RegisterOrPair.R12R13_32, | ||||||
|  |     RegisterOrPair.R14R15_32 | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | val CpuRegisters = arrayOf( | ||||||
|  |     RegisterOrPair.A, RegisterOrPair.X, RegisterOrPair.Y, | ||||||
|  |     RegisterOrPair.AX, RegisterOrPair.AY, RegisterOrPair.XY | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | enum class OutputType { | ||||||
|  |     RAW, | ||||||
|  |     PRG, | ||||||
|  |     XEX, | ||||||
|  |     LIBRARY | ||||||
|  | } | ||||||
|  |  | ||||||
|  | enum class CbmPrgLauncherType { | ||||||
|  |     BASIC, | ||||||
|  |     NONE | ||||||
|  | } | ||||||
|  |  | ||||||
|  | enum class ZeropageType { | ||||||
|  |     BASICSAFE, | ||||||
|  |     FLOATSAFE, | ||||||
|  |     KERNALSAFE, | ||||||
|  |     FULL, | ||||||
|  |     DONTUSE | ||||||
|  | } | ||||||
|  |  | ||||||
|  | enum class ZeropageWish { | ||||||
|  |     REQUIRE_ZEROPAGE, | ||||||
|  |     PREFER_ZEROPAGE, | ||||||
|  |     DONTCARE, | ||||||
|  |     NOT_IN_ZEROPAGE | ||||||
|  | } | ||||||
|  |  | ||||||
|  | enum class SplitWish { | ||||||
|  |     DONTCARE, | ||||||
|  |     NOSPLIT | ||||||
|  | } | ||||||
							
								
								
									
										7
									
								
								codeCore/src/prog8/code/core/Exceptions.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								codeCore/src/prog8/code/core/Exceptions.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | package prog8.code.core | ||||||
|  |  | ||||||
|  | class InternalCompilerException(message: String?) : Exception(message) | ||||||
|  |  | ||||||
|  | class AssemblyError(msg: String) : RuntimeException(msg) | ||||||
|  |  | ||||||
|  | class ErrorsReportedException(message: String?) : Exception(message) | ||||||
							
								
								
									
										44
									
								
								codeCore/src/prog8/code/core/ICompilationTarget.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								codeCore/src/prog8/code/core/ICompilationTarget.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | package prog8.code.core | ||||||
|  |  | ||||||
|  | import java.nio.file.Path | ||||||
|  |  | ||||||
|  | enum class CpuType { | ||||||
|  |     CPU6502, | ||||||
|  |     CPU65C02, | ||||||
|  |     VIRTUAL | ||||||
|  | } | ||||||
|  |  | ||||||
|  | interface ICompilationTarget: IStringEncoding, IMemSizer { | ||||||
|  |     val name: String | ||||||
|  |  | ||||||
|  |     val FLOAT_MAX_NEGATIVE: Double | ||||||
|  |     val FLOAT_MAX_POSITIVE: Double | ||||||
|  |     val FLOAT_MEM_SIZE: Int | ||||||
|  |     val STARTUP_CODE_RESERVED_SIZE: UInt        // this is here, so that certain compiler targets are able to tune this | ||||||
|  |     val PROGRAM_LOAD_ADDRESS : UInt | ||||||
|  |     val PROGRAM_MEMTOP_ADDRESS: UInt | ||||||
|  |     val BSSHIGHRAM_START: UInt | ||||||
|  |     val BSSHIGHRAM_END: UInt | ||||||
|  |     val BSSGOLDENRAM_START: UInt | ||||||
|  |     val BSSGOLDENRAM_END: UInt | ||||||
|  |  | ||||||
|  |     val cpu: CpuType | ||||||
|  |     var zeropage: Zeropage | ||||||
|  |     var golden: GoldenRam | ||||||
|  |     val libraryPath: Path? | ||||||
|  |     val customLauncher: List<String> | ||||||
|  |     val additionalAssemblerOptions: List<String> | ||||||
|  |     val defaultOutputType: OutputType | ||||||
|  |  | ||||||
|  |     fun initializeMemoryAreas(compilerOptions: CompilationOptions) | ||||||
|  |     fun getFloatAsmBytes(num: Number): String | ||||||
|  |  | ||||||
|  |     fun convertFloatToBytes(num: Double): List<UByte> | ||||||
|  |     fun convertBytesToFloat(bytes: List<UByte>): Double | ||||||
|  |  | ||||||
|  |     fun launchEmulator(selectedEmulator: Int, programNameWithPath: Path, quiet: Boolean) | ||||||
|  |     fun isIOAddress(address: UInt): Boolean | ||||||
|  |  | ||||||
|  |     override fun encodeString(str: String, encoding: Encoding): List<UByte> | ||||||
|  |     override fun decodeString(bytes: Iterable<UByte>, encoding: Encoding): String | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								codeCore/src/prog8/code/core/IErrorReporter.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								codeCore/src/prog8/code/core/IErrorReporter.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | package prog8.code.core | ||||||
|  |  | ||||||
|  | interface IErrorReporter { | ||||||
|  |     fun err(msg: String, position: Position) | ||||||
|  |     fun warn(msg: String, position: Position) | ||||||
|  |     fun info(msg: String, position: Position) | ||||||
|  |     fun undefined(symbol: List<String>, position: Position) | ||||||
|  |     fun noErrors(): Boolean | ||||||
|  |     fun report() | ||||||
|  |     fun finalizeNumErrors(numErrors: Int, numWarnings: Int, numInfos: Int) { | ||||||
|  |         if(numErrors>0) | ||||||
|  |             throw ErrorsReportedException("There are $numErrors errors, $numWarnings warnings, and $numInfos infos.") | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun noErrorForLine(position: Position): Boolean | ||||||
|  |  | ||||||
|  |     fun printSingleError(errormessage: String) | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								codeCore/src/prog8/code/core/IMemSizer.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								codeCore/src/prog8/code/core/IMemSizer.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | package prog8.code.core | ||||||
|  |  | ||||||
|  | interface IMemSizer { | ||||||
|  |     fun memorySize(dt: DataType, numElements: Int?): Int | ||||||
|  |  | ||||||
|  |     fun memorySize(dt: BaseDataType): Int { | ||||||
|  |         if(dt.isPassByRef) | ||||||
|  |             return memorySize(DataType.UWORD, null)      // a pointer size | ||||||
|  |         try { | ||||||
|  |             return memorySize(DataType.forDt(dt), null) | ||||||
|  |         } catch (x: NoSuchElementException) { | ||||||
|  |             throw IllegalArgumentException(x.message) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								codeCore/src/prog8/code/core/IStringEncoding.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								codeCore/src/prog8/code/core/IStringEncoding.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | package prog8.code.core | ||||||
|  |  | ||||||
|  | enum class Encoding(val prefix: String) { | ||||||
|  |     DEFAULT("default"),         // depends on compilation target | ||||||
|  |     PETSCII("petscii"),         // c64/c128/cx16 | ||||||
|  |     SCREENCODES("sc"),          // c64/c128/cx16 | ||||||
|  |     ATASCII("atascii"),         // atari | ||||||
|  |     ISO("iso"),                 // cx16  (iso-8859-15) | ||||||
|  |     ISO5("iso5"),               // cx16  (iso-8859-5, cyrillic) | ||||||
|  |     ISO16("iso16"),             // cx16  (iso-8859-16, eastern european) | ||||||
|  |     CP437("cp437"),             // cx16  (ibm pc, codepage 437) | ||||||
|  |     KATAKANA("kata"),           // cx16  (katakana) | ||||||
|  |     C64OS("c64os")              // c64 (C64 OS) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | interface IStringEncoding { | ||||||
|  |     val defaultEncoding: Encoding | ||||||
|  |  | ||||||
|  |     fun encodeString(str: String, encoding: Encoding): List<UByte> | ||||||
|  |     fun decodeString(bytes: Iterable<UByte>, encoding: Encoding): String | ||||||
|  | } | ||||||
							
								
								
									
										173
									
								
								codeCore/src/prog8/code/core/MemoryRegions.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								codeCore/src/prog8/code/core/MemoryRegions.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,173 @@ | |||||||
|  | package prog8.code.core | ||||||
|  |  | ||||||
|  | import com.github.michaelbull.result.Err | ||||||
|  | import com.github.michaelbull.result.Ok | ||||||
|  | import com.github.michaelbull.result.Result | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class MemAllocationError(message: String) : Exception(message) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | abstract class MemoryAllocator(protected val options: CompilationOptions) { | ||||||
|  |     data class VarAllocation(val address: UInt, val dt: DataType, val size: Int) | ||||||
|  |  | ||||||
|  |     abstract fun allocate(name: String, | ||||||
|  |                           datatype: DataType, | ||||||
|  |                           numElements: Int?, | ||||||
|  |                           position: Position?, | ||||||
|  |                           errors: IErrorReporter): Result<VarAllocation, MemAllocationError> | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | abstract class Zeropage(options: CompilationOptions): MemoryAllocator(options) { | ||||||
|  |  | ||||||
|  |     abstract val SCRATCH_B1 : UInt      // temp storage for a single byte | ||||||
|  |     abstract val SCRATCH_REG : UInt     // temp storage for a register byte, must be B1+1 | ||||||
|  |     abstract val SCRATCH_W1 : UInt      // temp storage 1 for a word | ||||||
|  |     abstract val SCRATCH_W2 : UInt      // temp storage 2 for a word | ||||||
|  |     abstract val SCRATCH_PTR : UInt     // temp storage for a pointer | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     // the variables allocated into Zeropage. | ||||||
|  |     // name (scoped) ==> pair of address to (Datatype + bytesize) | ||||||
|  |     val allocatedVariables = mutableMapOf<String, VarAllocation>() | ||||||
|  |  | ||||||
|  |     val free = mutableListOf<UInt>()     // subclasses must set this to the appropriate free locations. | ||||||
|  |  | ||||||
|  |     fun removeReservedFromFreePool() { | ||||||
|  |         synchronized(this) { | ||||||
|  |             for (reserved in options.zpReserved) | ||||||
|  |                 reserve(reserved) | ||||||
|  |  | ||||||
|  |             free.removeAll(arrayOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_W1, SCRATCH_W1 + 1u, SCRATCH_W2, SCRATCH_W2 + 1u, SCRATCH_PTR, SCRATCH_PTR+1u)) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun retainAllowed() { | ||||||
|  |         synchronized(this) { | ||||||
|  |             for(allowed in options.zpAllowed) | ||||||
|  |                 free.retainAll { it in allowed } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun availableBytes() = if(options.zeropage== ZeropageType.DONTUSE) 0 else free.size | ||||||
|  |     fun hasByteAvailable() = if(options.zeropage== ZeropageType.DONTUSE) false else free.isNotEmpty() | ||||||
|  |     fun hasWordAvailable(): Boolean { | ||||||
|  |         if(options.zeropage== ZeropageType.DONTUSE) | ||||||
|  |             return false | ||||||
|  |  | ||||||
|  |         return free.windowed(2).any { it[0] == it[1] - 1u } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun allocate(name: String, | ||||||
|  |                           datatype: DataType, | ||||||
|  |                           numElements: Int?, | ||||||
|  |                           position: Position?, | ||||||
|  |                           errors: IErrorReporter): Result<VarAllocation, MemAllocationError> { | ||||||
|  |  | ||||||
|  |         require(name.isEmpty() || name !in allocatedVariables) {"name can't be allocated twice"} | ||||||
|  |  | ||||||
|  |         if(options.zeropage== ZeropageType.DONTUSE) | ||||||
|  |             return Err(MemAllocationError("zero page usage has been disabled")) | ||||||
|  |  | ||||||
|  |         val size: Int = | ||||||
|  |                 when { | ||||||
|  |                     datatype.isIntegerOrBool -> options.compTarget.memorySize(datatype, null) | ||||||
|  |                     datatype.isPointer -> options.compTarget.memorySize(datatype, null) | ||||||
|  |                     datatype.isString || datatype.isArray -> { | ||||||
|  |                         val memsize = options.compTarget.memorySize(datatype, numElements!!) | ||||||
|  |                         if(position!=null) | ||||||
|  |                             errors.warn("allocating a large value in zeropage; str/array $memsize bytes", position) | ||||||
|  |                         else | ||||||
|  |                             errors.warn("$name: allocating a large value in zeropage; str/array $memsize bytes", Position.DUMMY) | ||||||
|  |                         memsize | ||||||
|  |                     } | ||||||
|  |                     datatype.isFloat -> { | ||||||
|  |                         if (options.floats) { | ||||||
|  |                             val memsize = options.compTarget.memorySize(DataType.FLOAT, null) | ||||||
|  |                             if(position!=null) | ||||||
|  |                                 errors.warn("allocating a large value in zeropage; float $memsize bytes", position) | ||||||
|  |                             else | ||||||
|  |                                 errors.warn("$name: allocating a large value in zeropage; float $memsize bytes", Position.DUMMY) | ||||||
|  |                             memsize | ||||||
|  |                         } else return Err(MemAllocationError("floating point option not enabled")) | ||||||
|  |                     } | ||||||
|  |                     else -> throw MemAllocationError("weird dt") | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |         synchronized(this) { | ||||||
|  |             if(free.isNotEmpty()) { | ||||||
|  |                 if(size==1) { | ||||||
|  |                     for(candidate in free.minOrNull()!! .. free.maxOrNull()!!+1u) { | ||||||
|  |                         if(oneSeparateByteFree(candidate)) | ||||||
|  |                             return Ok(VarAllocation(makeAllocation(candidate, 1, datatype, name), datatype,1)) | ||||||
|  |                     } | ||||||
|  |                     return Ok(VarAllocation(makeAllocation(free[0], 1, datatype, name), datatype,1)) | ||||||
|  |                 } | ||||||
|  |                 for(candidate in free.minOrNull()!! .. free.maxOrNull()!!+1u) { | ||||||
|  |                     if (sequentialFree(candidate, size)) | ||||||
|  |                         return Ok(VarAllocation(makeAllocation(candidate, size, datatype, name), datatype, size)) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return Err(MemAllocationError("no more free space in ZP to allocate $size sequential bytes")) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private fun reserve(range: UIntRange) = free.removeAll(range) | ||||||
|  |  | ||||||
|  |     private fun makeAllocation(address: UInt, size: Int, datatype: DataType, name: String): UInt { | ||||||
|  |         require(size>=0) | ||||||
|  |         free.removeAll(address until address+size.toUInt()) | ||||||
|  |         if(name.isNotEmpty()) { | ||||||
|  |             allocatedVariables[name] = when { | ||||||
|  |                 datatype.isNumericOrBool -> VarAllocation(address, datatype, size)        // numerical variables in zeropage never have an initial value here because they are set in separate initializer assignments | ||||||
|  |                 datatype.isString -> VarAllocation(address, datatype, size) | ||||||
|  |                 datatype.isArray -> VarAllocation(address, datatype, size) | ||||||
|  |                 datatype.isPointer -> VarAllocation(address, datatype, size) | ||||||
|  |                 else -> throw AssemblyError("invalid dt") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return address | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private fun oneSeparateByteFree(address: UInt) = address in free && address-1u !in free && address+1u !in free | ||||||
|  |     private fun sequentialFree(address: UInt, size: Int): Boolean { | ||||||
|  |         require(size>0) | ||||||
|  |         return free.containsAll((address until address+size.toUInt()).toList()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // TODO: this class is not yet used | ||||||
|  | class GoldenRam(options: CompilationOptions, val region: UIntRange): MemoryAllocator(options) { | ||||||
|  |     private var nextLocation: UInt = region.first | ||||||
|  |  | ||||||
|  |     override fun allocate( | ||||||
|  |         name: String, | ||||||
|  |         datatype: DataType, | ||||||
|  |         numElements: Int?, | ||||||
|  |         position: Position?, | ||||||
|  |         errors: IErrorReporter): Result<VarAllocation, MemAllocationError> { | ||||||
|  |  | ||||||
|  |         val size: Int = | ||||||
|  |             when { | ||||||
|  |                 datatype.isIntegerOrBool -> options.compTarget.memorySize(datatype, null) | ||||||
|  |                 datatype.isString -> numElements!! | ||||||
|  |                 datatype.isArray -> options.compTarget.memorySize(datatype, numElements!!) | ||||||
|  |                 datatype.isFloat -> { | ||||||
|  |                     if (options.floats) { | ||||||
|  |                         options.compTarget.memorySize(DataType.FLOAT, null) | ||||||
|  |                     } else return Err(MemAllocationError("floating point option not enabled")) | ||||||
|  |                 } | ||||||
|  |                 else -> throw MemAllocationError("weird dt") | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |         return if(nextLocation<=region.last && (region.last + 1u - nextLocation) >= size.toUInt()) { | ||||||
|  |             val result = Ok(VarAllocation(nextLocation, datatype, size)) | ||||||
|  |             nextLocation += size.toUInt() | ||||||
|  |             result | ||||||
|  |         } else | ||||||
|  |             Err(MemAllocationError("no more free space in Golden RAM to allocate $size sequential bytes")) | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								codeCore/src/prog8/code/core/Operators.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								codeCore/src/prog8/code/core/Operators.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | package prog8.code.core | ||||||
|  |  | ||||||
|  | val AssociativeOperators = arrayOf("+", "*", "&", "|", "^", "==", "!=", "xor")       // note: and,or are not associative because of Shortcircuit/McCarthy evaluation | ||||||
|  | val ComparisonOperators = arrayOf("==", "!=", "<", ">", "<=", ">=") | ||||||
|  | val LogicalOperators = arrayOf("and", "or", "xor", "not", "in") | ||||||
|  | val BitwiseOperators = arrayOf("&", "|", "^", "~") | ||||||
|  | val PrefixOperators = arrayOf("+", "-", "~", "not") | ||||||
|  |  | ||||||
|  | fun invertedComparisonOperator(operator: String) = | ||||||
|  |     when (operator) { | ||||||
|  |         "==" -> "!=" | ||||||
|  |         "!=" -> "==" | ||||||
|  |         "<" -> ">=" | ||||||
|  |         ">" -> "<=" | ||||||
|  |         "<=" -> ">" | ||||||
|  |         ">=" -> "<" | ||||||
|  |         else -> null | ||||||
|  |     } | ||||||
							
								
								
									
										27
									
								
								codeCore/src/prog8/code/core/Position.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								codeCore/src/prog8/code/core/Position.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | package prog8.code.core | ||||||
|  |  | ||||||
|  | import prog8.code.sanitize | ||||||
|  | import prog8.code.source.SourceCode | ||||||
|  | import java.nio.file.InvalidPathException | ||||||
|  | import kotlin.io.path.Path | ||||||
|  |  | ||||||
|  | data class Position(val file: String, val line: Int, val startCol: Int, val endCol: Int) { | ||||||
|  |     override fun toString(): String = "[$file: line $line col ${startCol+1}-${endCol+1}]" | ||||||
|  |     fun toClickableStr(): String { | ||||||
|  |         if(this===DUMMY) | ||||||
|  |             return "" | ||||||
|  |         if(SourceCode.isLibraryResource(file)) | ||||||
|  |             return "$file:$line:$startCol:" | ||||||
|  |         return try { | ||||||
|  |             val path = Path(file).sanitize().toString() | ||||||
|  |             "file://$path:$line:$startCol:" | ||||||
|  |         } catch(_: InvalidPathException) { | ||||||
|  |             // this can occur on Windows when the source origin contains "invalid" characters such as ':' | ||||||
|  |             "file://$file:$line:$startCol:" | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     companion object { | ||||||
|  |         val DUMMY = Position("~dummy~", 0, 0, 0) | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								codeCore/src/prog8/code/core/RegisterOrStatusflag.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								codeCore/src/prog8/code/core/RegisterOrStatusflag.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | package prog8.code.core | ||||||
|  |  | ||||||
|  | data class RegisterOrStatusflag(val registerOrPair: RegisterOrPair?, val statusflag: Statusflag?) | ||||||
							
								
								
									
										74
									
								
								codeCore/src/prog8/code/source/ImportFileSystem.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								codeCore/src/prog8/code/source/ImportFileSystem.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | |||||||
|  | package prog8.code.source | ||||||
|  |  | ||||||
|  | import prog8.code.core.Position | ||||||
|  | import prog8.code.sanitize | ||||||
|  | import java.nio.file.Path | ||||||
|  | import java.util.* | ||||||
|  | import kotlin.io.path.Path | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // Resource caching "filesystem". | ||||||
|  | // Note that it leaves the decision to load a resource or an actual disk file to the caller. | ||||||
|  |  | ||||||
|  | object ImportFileSystem { | ||||||
|  |  | ||||||
|  |     fun expandTilde(path: String): String = if (path.startsWith("~")) { | ||||||
|  |         val userHome = System.getProperty("user.home") | ||||||
|  |         userHome + path.drop(1) | ||||||
|  |     } else { | ||||||
|  |         path | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun expandTilde(path: Path): Path = Path(expandTilde(path.toString())) | ||||||
|  |  | ||||||
|  |     fun getFile(path: Path, isLibrary: Boolean=false): SourceCode { | ||||||
|  |         val normalized = path.sanitize() | ||||||
|  |         val cached = cache[normalized.toString()] | ||||||
|  |         if (cached != null) | ||||||
|  |             return cached | ||||||
|  |         val file = SourceCode.File(normalized, isLibrary) | ||||||
|  |         cache[normalized.toString()] = file | ||||||
|  |         return file | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun getResource(name: String): SourceCode { | ||||||
|  |         val cached = cache[name] | ||||||
|  |         if (cached != null) return cached | ||||||
|  |         val resource = SourceCode.Resource(name) | ||||||
|  |         cache[name] = resource | ||||||
|  |         return resource | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun retrieveSourceLine(position: Position): String { | ||||||
|  |         if(SourceCode.isLibraryResource(position.file)) { | ||||||
|  |             val cached = cache[SourceCode.withoutPrefix(position.file)] | ||||||
|  |             if(cached != null) | ||||||
|  |                 return getLine(cached, position.line) | ||||||
|  |         } | ||||||
|  |         val cached = cache[position.file] | ||||||
|  |         if(cached != null) | ||||||
|  |             return getLine(cached, position.line) | ||||||
|  |         val path = Path(position.file).sanitize() | ||||||
|  |         val cached2 = cache[path.toString()] | ||||||
|  |         if(cached2 != null) | ||||||
|  |             return getLine(cached2, position.line) | ||||||
|  |         throw NoSuchElementException("cannot get source line $position, with path $path") | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private fun getLine(code: SourceCode, lineIndex: Int): String { | ||||||
|  |         var spans = lineSpanCache[code] | ||||||
|  |         if(spans==null) { | ||||||
|  |             val lineSpans = Regex("^", RegexOption.MULTILINE).findAll(code.text).map { it.range.first } | ||||||
|  |             val ends = lineSpans.drop(1) + code.text.length | ||||||
|  |             spans = lineSpans.zip(ends).map { (start, end) -> LineSpan(start, end) }.toList().toTypedArray() | ||||||
|  |             lineSpanCache[code] = spans | ||||||
|  |         } | ||||||
|  |         val span = spans[lineIndex - 1] | ||||||
|  |         return code.text.substring(span.start, span.end).trim() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private class LineSpan(val start: Int, val end: Int) | ||||||
|  |  | ||||||
|  |     private val cache = TreeMap<String, SourceCode>(String.CASE_INSENSITIVE_ORDER) | ||||||
|  |     private val lineSpanCache = mutableMapOf<SourceCode, Array<LineSpan>>() | ||||||
|  | } | ||||||
							
								
								
									
										161
									
								
								codeCore/src/prog8/code/source/SourceCode.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								codeCore/src/prog8/code/source/SourceCode.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,161 @@ | |||||||
|  | package prog8.code.source | ||||||
|  |  | ||||||
|  | import prog8.code.sanitize | ||||||
|  | import java.io.IOException | ||||||
|  | import java.nio.file.Path | ||||||
|  | import java.text.Normalizer | ||||||
|  | import kotlin.io.path.Path | ||||||
|  | import kotlin.io.path.absolute | ||||||
|  | import kotlin.io.path.readText | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Encapsulates - and ties together - actual source code (=text) and its [origin]. | ||||||
|  |  */ | ||||||
|  | sealed class SourceCode { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Whether this [SourceCode] instance was created as a [Resource] | ||||||
|  |      */ | ||||||
|  |     abstract val isFromResources: Boolean | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Whether this [SourceCode] instance was created as a [File] | ||||||
|  |      */ | ||||||
|  |     abstract val isFromFilesystem: Boolean | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Whether this [SourceCode] instance was created from a library module file | ||||||
|  |      */ | ||||||
|  |     abstract val isFromLibrary: Boolean | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * The logical name of the source code unit. Usually the module's name. | ||||||
|  |      */ | ||||||
|  |     abstract val name: String | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Where this [SourceCode] instance came from. | ||||||
|  |      * This can be one of the following: | ||||||
|  |      * * a normal string representation of a [java.nio.file.Path], if it originates from a file (see [File]) | ||||||
|  |      * * `string:44c56085` if was created via [String] | ||||||
|  |      * * `library:/x/y/z.ext` if it is a library file that was loaded from resources (see [Resource]) | ||||||
|  |      */ | ||||||
|  |     abstract val origin: String | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * The source code as plain string. | ||||||
|  |      */ | ||||||
|  |     abstract val text: String | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Printable representation, deliberately does NOT return the actual text. | ||||||
|  |      */ | ||||||
|  |     final override fun toString() = "${this.javaClass.name}[${this.origin}]" | ||||||
|  |  | ||||||
|  |     companion object { | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * filename prefix to designate library files that will be retreived from internal resources rather than disk | ||||||
|  |          */ | ||||||
|  |         private const val LIBRARYFILEPREFIX = "library:" | ||||||
|  |         private const val STRINGSOURCEPREFIX = "string:" | ||||||
|  |         val curdir: Path = Path(".").absolute() | ||||||
|  |         fun relative(path: Path): Path = curdir.relativize(path.sanitize()) | ||||||
|  |         fun isRegularFilesystemPath(pathString: String) = !isLibraryResource(pathString) && !isStringResource(pathString) | ||||||
|  |         fun isLibraryResource(path: String) = path.startsWith(LIBRARYFILEPREFIX) | ||||||
|  |         fun isStringResource(path: String) = path.startsWith(STRINGSOURCEPREFIX) | ||||||
|  |         fun withoutPrefix(path: String): String { | ||||||
|  |             return if(isLibraryResource(path)) | ||||||
|  |                 path.removePrefix(LIBRARYFILEPREFIX) | ||||||
|  |             else if(isStringResource(path)) | ||||||
|  |                 path.removePrefix(STRINGSOURCEPREFIX) | ||||||
|  |             else | ||||||
|  |                 path | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Turn a plain String into a [SourceCode] object. | ||||||
|  |      * [origin] will be something like `string:44c56085`. | ||||||
|  |      */ | ||||||
|  |     class Text(origText: String): SourceCode() { | ||||||
|  |         override val text = origText.replace("\\R".toRegex(), "\n")      // normalize line endings | ||||||
|  |         override val isFromResources = false | ||||||
|  |         override val isFromFilesystem = false | ||||||
|  |         override val isFromLibrary = false | ||||||
|  |         override val origin = "$STRINGSOURCEPREFIX${System.identityHashCode(text).toString(16)}" | ||||||
|  |         override val name = "<unnamed-text>" | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Get [SourceCode] from the file represented by the specified Path. | ||||||
|  |      * This immediately reads the file fully into memory. | ||||||
|  |      * You can only get an instance of this via the ImportFileSystem object. | ||||||
|  |      * | ||||||
|  |      * [origin] will be the given path in absolute and normalized form. | ||||||
|  |      * @throws NoSuchFileException if the file does not exist | ||||||
|  |      * @throws FileSystemException if the file cannot be read | ||||||
|  |      */ | ||||||
|  |     internal class File(path: Path, override val isFromLibrary: Boolean): SourceCode() { | ||||||
|  |         override val text: String | ||||||
|  |         override val origin: String | ||||||
|  |         override val name: String | ||||||
|  |         override val isFromResources = false | ||||||
|  |         override val isFromFilesystem = true | ||||||
|  |  | ||||||
|  |         init { | ||||||
|  |             val normalized = path.normalize() | ||||||
|  |             origin = relative(normalized).toString() | ||||||
|  |             try { | ||||||
|  |                 val contents = Normalizer.normalize(normalized.readText(), Normalizer.Form.NFC) | ||||||
|  |                 text = contents.replace("\\R".toRegex(), "\n")      // normalize line endings | ||||||
|  |                 name = normalized.toFile().nameWithoutExtension | ||||||
|  |             } catch (nfx: java.nio.file.NoSuchFileException) { | ||||||
|  |                 throw NoSuchFileException(normalized.toFile()).also { it.initCause(nfx) } | ||||||
|  |             } catch (iox: IOException) { | ||||||
|  |                 throw FileSystemException(normalized.toFile()).also { it.initCause(iox) } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * [origin]: `library:/x/y/z.p8` for a given `pathString` of "x/y/z.p8" | ||||||
|  |      * You can only get an instance of this via the ImportFileSystem object. | ||||||
|  |      */ | ||||||
|  |     internal class Resource(pathString: String): SourceCode() { | ||||||
|  |         private val normalized = "/" + Path(pathString).normalize().toMutableList().joinToString("/") | ||||||
|  |  | ||||||
|  |         override val isFromResources = true | ||||||
|  |         override val isFromFilesystem = false | ||||||
|  |         override val isFromLibrary = true | ||||||
|  |         override val origin = "$LIBRARYFILEPREFIX$normalized" | ||||||
|  |         override val text: String | ||||||
|  |         override val name: String | ||||||
|  |  | ||||||
|  |         init { | ||||||
|  |             val rscURL = object {}.javaClass.getResource(normalized) | ||||||
|  |             if (rscURL == null) { | ||||||
|  |                 val rscRoot = object {}.javaClass.getResource("/") | ||||||
|  |                 throw NoSuchFileException( | ||||||
|  |                     java.io.File(normalized), | ||||||
|  |                     reason = "looked in resources rooted at $rscRoot" | ||||||
|  |                 ) | ||||||
|  |             } | ||||||
|  |             val stream = object {}.javaClass.getResourceAsStream(normalized) | ||||||
|  |             val contents = stream!!.reader().use { Normalizer.normalize(it.readText(), Normalizer.Form.NFC) } | ||||||
|  |             text = contents.replace("\\R".toRegex(), "\n")      // normalize line endings | ||||||
|  |             name = Path(pathString).toFile().nameWithoutExtension | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * SourceCode for internally generated nodes (usually Modules) | ||||||
|  |      */ | ||||||
|  |     class Generated(override val name: String) : SourceCode() { | ||||||
|  |         override val isFromResources: Boolean = false | ||||||
|  |         override val isFromFilesystem: Boolean = false | ||||||
|  |         override val isFromLibrary: Boolean = false | ||||||
|  |         override val origin: String = name | ||||||
|  |         override val text: String = "<generated code node, no text representation>" | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										81
									
								
								codeCore/src/prog8/code/target/C128Target.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								codeCore/src/prog8/code/target/C128Target.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | |||||||
|  | package prog8.code.target | ||||||
|  |  | ||||||
|  | import prog8.code.core.* | ||||||
|  | import prog8.code.target.encodings.Encoder | ||||||
|  | import prog8.code.target.zp.C128Zeropage | ||||||
|  | import java.nio.file.Path | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class C128Target: ICompilationTarget, | ||||||
|  |     IStringEncoding by Encoder(true), | ||||||
|  |     IMemSizer by NormalMemSizer(Mflpt5.FLOAT_MEM_SIZE) { | ||||||
|  |  | ||||||
|  |     override val name = NAME | ||||||
|  |     override val defaultEncoding = Encoding.PETSCII | ||||||
|  |     override val libraryPath = null | ||||||
|  |     override val customLauncher = emptyList<String>() | ||||||
|  |     override val additionalAssemblerOptions = emptyList<String>() | ||||||
|  |     override val defaultOutputType = OutputType.PRG | ||||||
|  |  | ||||||
|  |     companion object { | ||||||
|  |         const val NAME = "c128" | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     override val cpu = CpuType.CPU6502 | ||||||
|  |  | ||||||
|  |     override val FLOAT_MAX_POSITIVE = Mflpt5.FLOAT_MAX_POSITIVE | ||||||
|  |     override val FLOAT_MAX_NEGATIVE = Mflpt5.FLOAT_MAX_NEGATIVE | ||||||
|  |     override val FLOAT_MEM_SIZE = Mflpt5.FLOAT_MEM_SIZE | ||||||
|  |     override val STARTUP_CODE_RESERVED_SIZE = 20u | ||||||
|  |     override val PROGRAM_LOAD_ADDRESS = 0x1c01u | ||||||
|  |     override val PROGRAM_MEMTOP_ADDRESS = 0xc000u | ||||||
|  |  | ||||||
|  |     override val BSSHIGHRAM_START = 0u    // TODO address? | ||||||
|  |     override val BSSHIGHRAM_END = 0u      // TODO address? | ||||||
|  |     override val BSSGOLDENRAM_START = 0u  // TODO address? | ||||||
|  |     override val BSSGOLDENRAM_END = 0u    // TODO address? | ||||||
|  |  | ||||||
|  |     override lateinit var zeropage: Zeropage | ||||||
|  |     override lateinit var golden: GoldenRam | ||||||
|  |  | ||||||
|  |     override fun getFloatAsmBytes(num: Number) = Mflpt5.fromNumber(num).makeFloatFillAsm() | ||||||
|  |  | ||||||
|  |     override fun convertFloatToBytes(num: Double): List<UByte> { | ||||||
|  |         val m5 = Mflpt5.fromNumber(num) | ||||||
|  |         return listOf(m5.b0, m5.b1, m5.b2, m5.b3, m5.b4) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun convertBytesToFloat(bytes: List<UByte>): Double { | ||||||
|  |         require(bytes.size==5) { "need 5 bytes" } | ||||||
|  |         val m5 = Mflpt5(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]) | ||||||
|  |         return m5.toDouble() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun launchEmulator(selectedEmulator: Int, programNameWithPath: Path, quiet: Boolean) { | ||||||
|  |         if(selectedEmulator!=1) { | ||||||
|  |             System.err.println("The c128 target only supports the main emulator (Vice).") | ||||||
|  |             return | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!quiet) | ||||||
|  |             println("\nStarting C-128 emulator x128...") | ||||||
|  |  | ||||||
|  |         val viceMonlist = C64Target.viceMonListName(programNameWithPath.toString()) | ||||||
|  |         val cmdline = listOf("x128", "-silent", "-moncommands", viceMonlist, | ||||||
|  |             "-autostartprgmode", "1", "-autostart-warp", "-autostart", "${programNameWithPath}.prg") | ||||||
|  |         val processb = ProcessBuilder(cmdline) | ||||||
|  |         if(!quiet) | ||||||
|  |             processb.inheritIO() | ||||||
|  |         val process: Process = processb.start() | ||||||
|  |         process.waitFor() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun isIOAddress(address: UInt): Boolean = address==0u || address==1u || address in 0xd000u..0xdfffu | ||||||
|  |  | ||||||
|  |     override fun initializeMemoryAreas(compilerOptions: CompilationOptions) { | ||||||
|  |         zeropage = C128Zeropage(compilerOptions) | ||||||
|  |         golden = GoldenRam(compilerOptions, UIntRange.EMPTY)    // TODO does the c128 have some of this somewhere? | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										111
									
								
								codeCore/src/prog8/code/target/C64Target.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								codeCore/src/prog8/code/target/C64Target.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | |||||||
|  | package prog8.code.target | ||||||
|  |  | ||||||
|  | import prog8.code.core.* | ||||||
|  | import prog8.code.target.encodings.Encoder | ||||||
|  | import prog8.code.target.zp.C64Zeropage | ||||||
|  | import java.io.IOException | ||||||
|  | import java.nio.file.Path | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class C64Target: ICompilationTarget, | ||||||
|  |     IStringEncoding by Encoder(true), | ||||||
|  |     IMemSizer by NormalMemSizer(Mflpt5.FLOAT_MEM_SIZE) { | ||||||
|  |  | ||||||
|  |     override val name = NAME | ||||||
|  |     override val defaultEncoding = Encoding.PETSCII | ||||||
|  |     override val libraryPath = null | ||||||
|  |     override val customLauncher = emptyList<String>() | ||||||
|  |     override val additionalAssemblerOptions = emptyList<String>() | ||||||
|  |     override val defaultOutputType = OutputType.PRG | ||||||
|  |  | ||||||
|  |     companion object { | ||||||
|  |         const val NAME = "c64" | ||||||
|  |  | ||||||
|  |         fun viceMonListName(baseFilename: String) = "$baseFilename.vice-mon-list" | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     override val cpu = CpuType.CPU6502 | ||||||
|  |  | ||||||
|  |     override val FLOAT_MAX_POSITIVE = Mflpt5.FLOAT_MAX_POSITIVE | ||||||
|  |     override val FLOAT_MAX_NEGATIVE = Mflpt5.FLOAT_MAX_NEGATIVE | ||||||
|  |     override val FLOAT_MEM_SIZE = Mflpt5.FLOAT_MEM_SIZE | ||||||
|  |     override val STARTUP_CODE_RESERVED_SIZE = 20u | ||||||
|  |     override val PROGRAM_LOAD_ADDRESS = 0x0801u | ||||||
|  |     override val PROGRAM_MEMTOP_ADDRESS = 0xcfe0u      // $a000  if floats are used | ||||||
|  |     // note that at $cfe0-$cfff are the 16 'virtual registers' R0-R15 | ||||||
|  |  | ||||||
|  |     override val BSSHIGHRAM_START = 0xc000u | ||||||
|  |     override val BSSHIGHRAM_END = 0xcfdfu | ||||||
|  |     override val BSSGOLDENRAM_START = 0u        // no golden ram on C64 | ||||||
|  |     override val BSSGOLDENRAM_END = 0u | ||||||
|  |  | ||||||
|  |     override lateinit var zeropage: Zeropage | ||||||
|  |     override lateinit var golden: GoldenRam | ||||||
|  |  | ||||||
|  |     override fun getFloatAsmBytes(num: Number) = Mflpt5.fromNumber(num).makeFloatFillAsm() | ||||||
|  |  | ||||||
|  |     override fun convertFloatToBytes(num: Double): List<UByte> { | ||||||
|  |         val m5 = Mflpt5.fromNumber(num) | ||||||
|  |         return listOf(m5.b0, m5.b1, m5.b2, m5.b3, m5.b4) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun convertBytesToFloat(bytes: List<UByte>): Double { | ||||||
|  |         require(bytes.size==5) { "need 5 bytes" } | ||||||
|  |         val m5 = Mflpt5(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]) | ||||||
|  |         return m5.toDouble() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun launchEmulator(selectedEmulator: Int, programNameWithPath: Path, quiet: Boolean) { | ||||||
|  |         if(selectedEmulator!=1) { | ||||||
|  |             System.err.println("The c64 target only supports the main emulator (Vice).") | ||||||
|  |             return | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         for(emulator in listOf("x64sc", "x64")) { | ||||||
|  |             if(!quiet) | ||||||
|  |                 println("\nStarting C-64 emulator $emulator...") | ||||||
|  |  | ||||||
|  |             val viceMonlist = viceMonListName(programNameWithPath.toString()) | ||||||
|  |             val cmdline = listOf(emulator, "-silent", "-moncommands", viceMonlist, | ||||||
|  |                 "-autostartprgmode", "1", "-autostart-warp", "-autostart", "${programNameWithPath}.prg") | ||||||
|  |             val processb = ProcessBuilder(cmdline) | ||||||
|  |             if(!quiet) | ||||||
|  |                 processb.inheritIO() | ||||||
|  |             val process: Process | ||||||
|  |             try { | ||||||
|  |                 process=processb.start() | ||||||
|  |             } catch(_: IOException) { | ||||||
|  |                 continue  // try the next emulator executable | ||||||
|  |             } | ||||||
|  |             process.waitFor() | ||||||
|  |             break | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun isIOAddress(address: UInt): Boolean = address==0u || address==1u || address in 0xd000u..0xdfffu | ||||||
|  |  | ||||||
|  |     override fun initializeMemoryAreas(compilerOptions: CompilationOptions) { | ||||||
|  |         zeropage = C64Zeropage(compilerOptions) | ||||||
|  |         golden = GoldenRam(compilerOptions, UIntRange.EMPTY) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | val CompilationTargets = listOf( | ||||||
|  |     C64Target.NAME, | ||||||
|  |     C128Target.NAME, | ||||||
|  |     Cx16Target.NAME, | ||||||
|  |     PETTarget.NAME, | ||||||
|  |     VMTarget.NAME | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | fun getCompilationTargetByName(name: String) = when(name.lowercase()) { | ||||||
|  |     C64Target.NAME -> C64Target() | ||||||
|  |     C128Target.NAME -> C128Target() | ||||||
|  |     Cx16Target.NAME -> Cx16Target() | ||||||
|  |     PETTarget.NAME -> PETTarget() | ||||||
|  |     VMTarget.NAME -> VMTarget() | ||||||
|  |     else -> throw IllegalArgumentException("invalid compilation target") | ||||||
|  | } | ||||||
							
								
								
									
										173
									
								
								codeCore/src/prog8/code/target/ConfigFileTarget.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								codeCore/src/prog8/code/target/ConfigFileTarget.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,173 @@ | |||||||
|  | package prog8.code.target | ||||||
|  |  | ||||||
|  | import prog8.code.core.* | ||||||
|  | import prog8.code.source.ImportFileSystem.expandTilde | ||||||
|  | import prog8.code.target.encodings.Encoder | ||||||
|  | import prog8.code.target.zp.ConfigurableZeropage | ||||||
|  | import java.io.IOException | ||||||
|  | import java.nio.file.Path | ||||||
|  | import java.util.* | ||||||
|  | import kotlin.io.path.Path | ||||||
|  | import kotlin.io.path.inputStream | ||||||
|  | import kotlin.io.path.isDirectory | ||||||
|  | import kotlin.io.path.nameWithoutExtension | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ConfigFileTarget( | ||||||
|  |     override val name: String, | ||||||
|  |     override val defaultEncoding: Encoding, | ||||||
|  |     override val cpu: CpuType, | ||||||
|  |     override val PROGRAM_LOAD_ADDRESS: UInt, | ||||||
|  |     override val PROGRAM_MEMTOP_ADDRESS: UInt, | ||||||
|  |     override val STARTUP_CODE_RESERVED_SIZE: UInt, | ||||||
|  |     override val BSSHIGHRAM_START: UInt, | ||||||
|  |     override val BSSHIGHRAM_END: UInt, | ||||||
|  |     override val BSSGOLDENRAM_START: UInt, | ||||||
|  |     override val BSSGOLDENRAM_END: UInt, | ||||||
|  |     override val defaultOutputType: OutputType, | ||||||
|  |     override val libraryPath: Path, | ||||||
|  |     override val customLauncher: List<String>, | ||||||
|  |     override val additionalAssemblerOptions: List<String>, | ||||||
|  |     val ioAddresses: List<UIntRange>, | ||||||
|  |     val zpScratchB1: UInt, | ||||||
|  |     val zpScratchReg: UInt, | ||||||
|  |     val zpScratchW1: UInt, | ||||||
|  |     val zpScratchW2: UInt, | ||||||
|  |     val zpScratchPtr: UInt, | ||||||
|  |     val virtualregistersStart: UInt, | ||||||
|  |     val zpFullsafe: List<UIntRange>, | ||||||
|  |     val zpKernalsafe: List<UIntRange>, | ||||||
|  |     val zpBasicsafe: List<UIntRange> | ||||||
|  | ): ICompilationTarget, IStringEncoding by Encoder(true), IMemSizer by NormalMemSizer(8) { | ||||||
|  |  | ||||||
|  |     companion object { | ||||||
|  |  | ||||||
|  |         private fun Properties.getString(property: String): String { | ||||||
|  |             val value = this.getProperty(property, null) | ||||||
|  |             if(value!=null) | ||||||
|  |                 return value | ||||||
|  |             throw NoSuchElementException("string property '$property' not found in config file") | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private fun Properties.getInteger(property: String): UInt { | ||||||
|  |             val value = this.getProperty(property, null) | ||||||
|  |             if(value!=null) return parseInt(value) | ||||||
|  |             throw NoSuchElementException("integer property '$property' not found in config file") | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private fun parseInt(value: String): UInt { | ||||||
|  |             if(value.startsWith("0x")) | ||||||
|  |                 return value.drop(2).toUInt(16) | ||||||
|  |             if(value.startsWith("$")) | ||||||
|  |                 return value.drop(1).toUInt(16) | ||||||
|  |             if(value.startsWith("%")) | ||||||
|  |                 return value.drop(1).toUInt(2) | ||||||
|  |             return value.toUInt() | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private fun parseAddressRanges(key: String, props: Properties): List<UIntRange> { | ||||||
|  |             val rangesStr = props.getString(key) | ||||||
|  |             if(rangesStr.isBlank()) | ||||||
|  |                 return emptyList() | ||||||
|  |             val result = mutableListOf<UIntRange>() | ||||||
|  |             val ranges = rangesStr.split(",").map { it.trim() } | ||||||
|  |             for(r in ranges) { | ||||||
|  |                 if ('-' in r) { | ||||||
|  |                     val (fromStr, toStr) = r.split("-") | ||||||
|  |                     val from = parseInt(fromStr.trim()) | ||||||
|  |                     val to = parseInt(toStr.trim()) | ||||||
|  |                     result.add(from..to) | ||||||
|  |                 } else { | ||||||
|  |                     val address = parseInt(r) | ||||||
|  |                     result.add(address..address) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             return result | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         fun fromConfigFile(configfile: Path): ConfigFileTarget { | ||||||
|  |             val props = Properties() | ||||||
|  |             props.load(configfile.inputStream()) | ||||||
|  |  | ||||||
|  |             val cpuString = props.getString("cpu").uppercase() | ||||||
|  |             val cpuType = try { | ||||||
|  |                 CpuType.valueOf(cpuString) | ||||||
|  |             } catch (_: IllegalArgumentException) { | ||||||
|  |                 CpuType.valueOf("CPU$cpuString") | ||||||
|  |             } | ||||||
|  |             val ioAddresses = parseAddressRanges("io_regions", props) | ||||||
|  |             val zpFullsafe = parseAddressRanges("zp_fullsafe", props) | ||||||
|  |             val zpKernalsafe = parseAddressRanges("zp_kernalsafe", props) | ||||||
|  |             val zpBasicsafe = parseAddressRanges("zp_basicsafe", props) | ||||||
|  |  | ||||||
|  |             val libraryPath = expandTilde(Path(props.getString("library"))) | ||||||
|  |             if(!libraryPath.isDirectory()) | ||||||
|  |                 throw IOException("invalid library path: $libraryPath") | ||||||
|  |  | ||||||
|  |             val customLauncherStr = props.getProperty("custom_launcher_code", null) | ||||||
|  |             val customLauncher = | ||||||
|  |                 if(customLauncherStr?.isNotBlank()==true) | ||||||
|  |                     (customLauncherStr+"\n").lines().map { it.trimEnd() } | ||||||
|  |                 else emptyList() | ||||||
|  |             val assemblerOptionsStr = props.getProperty("assembler_options", "").trim() | ||||||
|  |             val outputTypeString = props.getProperty("output_type", "PRG") | ||||||
|  |             val defaultOutputType = OutputType.valueOf(outputTypeString.uppercase()) | ||||||
|  |  | ||||||
|  |             return ConfigFileTarget( | ||||||
|  |                 configfile.nameWithoutExtension, | ||||||
|  |                 Encoding.entries.first { it.prefix==props.getString("encoding") }, | ||||||
|  |                 cpuType, | ||||||
|  |                 props.getInteger("load_address"), | ||||||
|  |                 props.getInteger("memtop"), | ||||||
|  |                 0u,         // used only in a very specific error condition check in a certain scenario... | ||||||
|  |                 props.getInteger("bss_highram_start"), | ||||||
|  |                 props.getInteger("bss_highram_end"), | ||||||
|  |                 props.getInteger("bss_goldenram_start"), | ||||||
|  |                 props.getInteger("bss_goldenram_end"), | ||||||
|  |                 defaultOutputType, | ||||||
|  |                 libraryPath, | ||||||
|  |                 customLauncher, | ||||||
|  |                 if(assemblerOptionsStr=="") emptyList() else assemblerOptionsStr.split(" "), | ||||||
|  |                 ioAddresses, | ||||||
|  |                 props.getInteger("zp_scratch_b1"), | ||||||
|  |                 props.getInteger("zp_scratch_reg"), | ||||||
|  |                 props.getInteger("zp_scratch_w1"), | ||||||
|  |                 props.getInteger("zp_scratch_w2"), | ||||||
|  |                 props.getInteger("zp_scratch_ptr"), | ||||||
|  |                 props.getInteger("virtual_registers"), | ||||||
|  |                 zpFullsafe, | ||||||
|  |                 zpKernalsafe, | ||||||
|  |                 zpBasicsafe, | ||||||
|  |             ) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // TODO floats are not yet supported here, just enter some values | ||||||
|  |     override val FLOAT_MAX_POSITIVE = 9.999999999e97 | ||||||
|  |     override val FLOAT_MAX_NEGATIVE = -9.999999999e97 | ||||||
|  |     override val FLOAT_MEM_SIZE = 8 | ||||||
|  |  | ||||||
|  |     override lateinit var zeropage: Zeropage | ||||||
|  |     override lateinit var golden: GoldenRam     // TODO this is not yet used | ||||||
|  |  | ||||||
|  |     override fun getFloatAsmBytes(num: Number) = TODO("floats") | ||||||
|  |     override fun convertFloatToBytes(num: Double): List<UByte> = TODO("floats") | ||||||
|  |     override fun convertBytesToFloat(bytes: List<UByte>): Double = TODO("floats") | ||||||
|  |     override fun launchEmulator(selectedEmulator: Int, programNameWithPath: Path, quiet: Boolean) { | ||||||
|  |         throw IllegalArgumentException("Custom compiler target cannot automatically launch an emulator. Do this manually.") | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun isIOAddress(address: UInt): Boolean = ioAddresses.any { address in it } | ||||||
|  |  | ||||||
|  |     override fun initializeMemoryAreas(compilerOptions: CompilationOptions) { | ||||||
|  |         zeropage = ConfigurableZeropage( | ||||||
|  |             zpScratchB1, zpScratchReg, zpScratchW1, zpScratchW2, zpScratchPtr, | ||||||
|  |             virtualregistersStart, | ||||||
|  |             zpBasicsafe, | ||||||
|  |             zpKernalsafe, | ||||||
|  |             zpFullsafe, | ||||||
|  |             compilerOptions | ||||||
|  |         ) | ||||||
|  |         // note: there's no golden ram yet | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										94
									
								
								codeCore/src/prog8/code/target/Cx16Target.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								codeCore/src/prog8/code/target/Cx16Target.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | |||||||
|  | package prog8.code.target | ||||||
|  |  | ||||||
|  | import prog8.code.core.* | ||||||
|  | import prog8.code.target.encodings.Encoder | ||||||
|  | import prog8.code.target.zp.CX16Zeropage | ||||||
|  | import java.nio.file.Path | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Cx16Target: ICompilationTarget, | ||||||
|  |     IStringEncoding by Encoder(true), | ||||||
|  |     IMemSizer by NormalMemSizer(Mflpt5.FLOAT_MEM_SIZE) { | ||||||
|  |  | ||||||
|  |     override val name = NAME | ||||||
|  |     override val defaultEncoding = Encoding.PETSCII | ||||||
|  |     override val libraryPath = null | ||||||
|  |     override val customLauncher = emptyList<String>() | ||||||
|  |     override val additionalAssemblerOptions = emptyList<String>() | ||||||
|  |     override val defaultOutputType = OutputType.PRG | ||||||
|  |  | ||||||
|  |     companion object { | ||||||
|  |         const val NAME = "cx16" | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     override val cpu = CpuType.CPU65C02 | ||||||
|  |  | ||||||
|  |     override val FLOAT_MAX_POSITIVE = Mflpt5.FLOAT_MAX_POSITIVE | ||||||
|  |     override val FLOAT_MAX_NEGATIVE = Mflpt5.FLOAT_MAX_NEGATIVE | ||||||
|  |     override val FLOAT_MEM_SIZE = Mflpt5.FLOAT_MEM_SIZE | ||||||
|  |     override val STARTUP_CODE_RESERVED_SIZE = 20u | ||||||
|  |     override val PROGRAM_LOAD_ADDRESS = 0x0801u | ||||||
|  |     override val PROGRAM_MEMTOP_ADDRESS = 0x9f00u | ||||||
|  |  | ||||||
|  |     override val BSSHIGHRAM_START = 0xa000u     // hiram bank 1, 8Kb, assumed to be active | ||||||
|  |     override val BSSHIGHRAM_END = 0xbfffu       // Rom starts at $c000 | ||||||
|  |     override val BSSGOLDENRAM_START = 0x0400u | ||||||
|  |     override val BSSGOLDENRAM_END = 0x07ffu | ||||||
|  |  | ||||||
|  |     override lateinit var zeropage: Zeropage | ||||||
|  |     override lateinit var golden: GoldenRam | ||||||
|  |  | ||||||
|  |     override fun getFloatAsmBytes(num: Number) = Mflpt5.fromNumber(num).makeFloatFillAsm() | ||||||
|  |  | ||||||
|  |     override fun convertFloatToBytes(num: Double): List<UByte> { | ||||||
|  |         val m5 = Mflpt5.fromNumber(num) | ||||||
|  |         return listOf(m5.b0, m5.b1, m5.b2, m5.b3, m5.b4) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun convertBytesToFloat(bytes: List<UByte>): Double { | ||||||
|  |         require(bytes.size==5) { "need 5 bytes" } | ||||||
|  |         val m5 = Mflpt5(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]) | ||||||
|  |         return m5.toDouble() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun launchEmulator(selectedEmulator: Int, programNameWithPath: Path, quiet: Boolean) { | ||||||
|  |         val emulator: String | ||||||
|  |         val extraArgs: List<String> | ||||||
|  |  | ||||||
|  |         when(selectedEmulator) { | ||||||
|  |             1 -> { | ||||||
|  |                 emulator = "x16emu" | ||||||
|  |                 extraArgs = listOf("-debug") | ||||||
|  |             } | ||||||
|  |             2 -> { | ||||||
|  |                 emulator = "box16" | ||||||
|  |                 extraArgs = listOf("-sym", C64Target.viceMonListName(programNameWithPath.toString())) | ||||||
|  |             } | ||||||
|  |             else -> { | ||||||
|  |                 System.err.println("Cx16 target only supports x16emu and box16 emulators.") | ||||||
|  |                 return | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!quiet) | ||||||
|  |             println("\nStarting Commander X16 emulator $emulator...") | ||||||
|  |  | ||||||
|  |         val cmdline = listOf(emulator, "-scale", "2", "-rtc", "-run", "-prg", "${programNameWithPath}.prg") + extraArgs | ||||||
|  |         val processb = ProcessBuilder(cmdline) | ||||||
|  |         if(!quiet) | ||||||
|  |             processb.inheritIO() | ||||||
|  |         processb.environment()["PULSE_LATENCY_MSEC"] = "10" | ||||||
|  |         val process: Process = processb.start() | ||||||
|  |         process.waitFor() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun isIOAddress(address: UInt): Boolean = address==0u || address==1u || address in 0x9f00u..0x9fffu | ||||||
|  |  | ||||||
|  |     override fun initializeMemoryAreas(compilerOptions: CompilationOptions) { | ||||||
|  |         zeropage = CX16Zeropage(compilerOptions) | ||||||
|  |         golden = GoldenRam(compilerOptions, BSSGOLDENRAM_START..BSSGOLDENRAM_END) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										76
									
								
								codeCore/src/prog8/code/target/Mflpt5.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								codeCore/src/prog8/code/target/Mflpt5.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | |||||||
|  | package prog8.code.target | ||||||
|  |  | ||||||
|  | import prog8.code.core.InternalCompilerException | ||||||
|  | import kotlin.math.absoluteValue | ||||||
|  | import kotlin.math.pow | ||||||
|  |  | ||||||
|  | data class Mflpt5(val b0: UByte, val b1: UByte, val b2: UByte, val b3: UByte, val b4: UByte) { | ||||||
|  |  | ||||||
|  |     companion object { | ||||||
|  |         const val FLOAT_MAX_POSITIVE = 1.7014118345e+38         // bytes: 255,127,255,255,255 | ||||||
|  |         const val FLOAT_MAX_NEGATIVE = -1.7014118345e+38        // bytes: 255,255,255,255,255 | ||||||
|  |         const val FLOAT_MEM_SIZE = 5 | ||||||
|  |  | ||||||
|  |         val zero = Mflpt5(0u, 0u, 0u, 0u, 0u) | ||||||
|  |         fun fromNumber(num: Number): Mflpt5 { | ||||||
|  |             // see https://en.wikipedia.org/wiki/Microsoft_Binary_Format | ||||||
|  |             // and https://sourceforge.net/p/acme-crossass/code-0/62/tree/trunk/ACME_Lib/cbm/mflpt.a | ||||||
|  |             // and https://en.wikipedia.org/wiki/IEEE_754-1985 | ||||||
|  |  | ||||||
|  |             val flt = num.toDouble() | ||||||
|  |             if (flt !in FLOAT_MAX_NEGATIVE..FLOAT_MAX_POSITIVE) | ||||||
|  |                 throw InternalCompilerException("floating point number out of 5-byte mflpt range: $this") | ||||||
|  |             if (flt == 0.0) | ||||||
|  |                 return zero | ||||||
|  |  | ||||||
|  |             val sign = if (flt < 0.0) 0x80L else 0x00L | ||||||
|  |             var exponent = 128 + 32    // 128 is cbm's bias, 32 is this algo's bias | ||||||
|  |             var mantissa = flt.absoluteValue | ||||||
|  |  | ||||||
|  |             // if mantissa is too large, shift right and adjust exponent | ||||||
|  |             while (mantissa >= 0x100000000) { | ||||||
|  |                 mantissa /= 2.0 | ||||||
|  |                 exponent++ | ||||||
|  |             } | ||||||
|  |             // if mantissa is too small, shift left and adjust exponent | ||||||
|  |             while (mantissa < 0x80000000) { | ||||||
|  |                 mantissa *= 2.0 | ||||||
|  |                 exponent-- | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return when { | ||||||
|  |                 exponent < 0 -> zero  // underflow, use zero instead | ||||||
|  |                 exponent > 255 -> throw InternalCompilerException("floating point overflow: $this") | ||||||
|  |                 exponent == 0 -> zero | ||||||
|  |                 else -> { | ||||||
|  |                     val mantLong = mantissa.toLong() | ||||||
|  |                     Mflpt5( | ||||||
|  |                         exponent.toUByte(), | ||||||
|  |                         (mantLong.and(0x7f000000L) ushr 24).or(sign).toUByte(), | ||||||
|  |                         (mantLong.and(0x00ff0000L) ushr 16).toUByte(), | ||||||
|  |                         (mantLong.and(0x0000ff00L) ushr 8).toUByte(), | ||||||
|  |                         (mantLong.and(0x000000ffL)).toUByte() | ||||||
|  |                     ) | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun toDouble(): Double { | ||||||
|  |         if (this == zero) return 0.0 | ||||||
|  |         val exp = b0.toInt() - 128 | ||||||
|  |         val sign = (b1.toInt() and 0x80) > 0 | ||||||
|  |         val number = 0x80000000L.or(b1.toLong() shl 24).or(b2.toLong() shl 16).or(b3.toLong() shl 8).or(b4.toLong()) | ||||||
|  |         val result = number.toDouble() * (2.0).pow(exp) / 0x100000000 | ||||||
|  |         return if (sign) -result else result | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun makeFloatFillAsm(): String { | ||||||
|  |         val b0 = "$" + b0.toString(16).padStart(2, '0') | ||||||
|  |         val b1 = "$" + b1.toString(16).padStart(2, '0') | ||||||
|  |         val b2 = "$" + b2.toString(16).padStart(2, '0') | ||||||
|  |         val b3 = "$" + b3.toString(16).padStart(2, '0') | ||||||
|  |         val b4 = "$" + b4.toString(16).padStart(2, '0') | ||||||
|  |         return "$b0, $b1, $b2, $b3, $b4" | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										39
									
								
								codeCore/src/prog8/code/target/NormalMemSizer.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								codeCore/src/prog8/code/target/NormalMemSizer.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | package prog8.code.target | ||||||
|  |  | ||||||
|  | import prog8.code.core.BaseDataType | ||||||
|  | import prog8.code.core.DataType | ||||||
|  | import prog8.code.core.IMemSizer | ||||||
|  |  | ||||||
|  | internal class NormalMemSizer(val floatsize: Int): IMemSizer { | ||||||
|  |  | ||||||
|  |     override fun memorySize(dt: DataType, numElements: Int?): Int { | ||||||
|  |         if(dt.isPointerArray) | ||||||
|  |             return 2 * numElements!!        // array of pointers is just array of uwords | ||||||
|  |         else if(dt.isArray) { | ||||||
|  |             if(numElements==null) return 2      // treat it as a pointer size | ||||||
|  |             return when(dt.sub) { | ||||||
|  |                 BaseDataType.BOOL, BaseDataType.UBYTE, BaseDataType.BYTE -> numElements | ||||||
|  |                 BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.STR -> numElements * 2 | ||||||
|  |                 BaseDataType.LONG -> numElements * 4 | ||||||
|  |                 BaseDataType.FLOAT-> numElements * floatsize | ||||||
|  |                 BaseDataType.UNDEFINED -> throw IllegalArgumentException("undefined has no memory size") | ||||||
|  |                 else -> throw IllegalArgumentException("invalid sub type") | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         else if (dt.isString) { | ||||||
|  |             return numElements        // treat it as the size of the given string with the length | ||||||
|  |                 ?: 2    // treat it as the size to store a string pointer | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return when { | ||||||
|  |             dt.isByteOrBool -> 1 * (numElements ?: 1) | ||||||
|  |             dt.isFloat -> floatsize * (numElements ?: 1) | ||||||
|  |             dt.isLong -> 4 * (numElements ?: 1) | ||||||
|  |             dt.isPointer -> 2  // pointer is just a uword | ||||||
|  |             dt.isStructInstance -> dt.subType!!.memsize(this) | ||||||
|  |             dt.isUndefined -> throw IllegalArgumentException("undefined has no memory size") | ||||||
|  |             else -> 2 * (numElements ?: 1) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										80
									
								
								codeCore/src/prog8/code/target/PETTarget.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								codeCore/src/prog8/code/target/PETTarget.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | |||||||
|  | package prog8.code.target | ||||||
|  |  | ||||||
|  | import prog8.code.core.* | ||||||
|  | import prog8.code.target.encodings.Encoder | ||||||
|  | import prog8.code.target.zp.PETZeropage | ||||||
|  | import java.nio.file.Path | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class PETTarget: ICompilationTarget, | ||||||
|  |     IStringEncoding by Encoder(true), | ||||||
|  |     IMemSizer by NormalMemSizer(Mflpt5.FLOAT_MEM_SIZE) { | ||||||
|  |  | ||||||
|  |     override val name = NAME | ||||||
|  |     override val defaultEncoding = Encoding.PETSCII | ||||||
|  |     override val libraryPath = null | ||||||
|  |     override val customLauncher = emptyList<String>() | ||||||
|  |     override val additionalAssemblerOptions = emptyList<String>() | ||||||
|  |     override val defaultOutputType = OutputType.PRG | ||||||
|  |  | ||||||
|  |     companion object { | ||||||
|  |         const val NAME = "pet32" | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override val cpu = CpuType.CPU6502 | ||||||
|  |  | ||||||
|  |     override val FLOAT_MAX_POSITIVE = Mflpt5.FLOAT_MAX_POSITIVE | ||||||
|  |     override val FLOAT_MAX_NEGATIVE = Mflpt5.FLOAT_MAX_NEGATIVE | ||||||
|  |     override val FLOAT_MEM_SIZE = Mflpt5.FLOAT_MEM_SIZE | ||||||
|  |     override val STARTUP_CODE_RESERVED_SIZE = 20u | ||||||
|  |     override val PROGRAM_LOAD_ADDRESS = 0x0401u | ||||||
|  |     override val PROGRAM_MEMTOP_ADDRESS = 0x8000u | ||||||
|  |  | ||||||
|  |     override val BSSHIGHRAM_START = 0u | ||||||
|  |     override val BSSHIGHRAM_END = 0u | ||||||
|  |     override val BSSGOLDENRAM_START = 0u | ||||||
|  |     override val BSSGOLDENRAM_END = 0u | ||||||
|  |  | ||||||
|  |     override lateinit var zeropage: Zeropage | ||||||
|  |     override lateinit var golden: GoldenRam | ||||||
|  |  | ||||||
|  |     override fun getFloatAsmBytes(num: Number) = Mflpt5.fromNumber(num).makeFloatFillAsm() | ||||||
|  |  | ||||||
|  |     override fun convertFloatToBytes(num: Double): List<UByte> { | ||||||
|  |         val m5 = Mflpt5.fromNumber(num) | ||||||
|  |         return listOf(m5.b0, m5.b1, m5.b2, m5.b3, m5.b4) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun convertBytesToFloat(bytes: List<UByte>): Double { | ||||||
|  |         require(bytes.size==5) { "need 5 bytes" } | ||||||
|  |         val m5 = Mflpt5(bytes[0], bytes[1], bytes[2], bytes[3], bytes[4]) | ||||||
|  |         return m5.toDouble() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun launchEmulator(selectedEmulator: Int, programNameWithPath: Path, quiet: Boolean) { | ||||||
|  |         if(selectedEmulator!=1) { | ||||||
|  |             System.err.println("The pet target only supports the main emulator (Vice).") | ||||||
|  |             return | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!quiet) | ||||||
|  |             println("\nStarting PET emulator...") | ||||||
|  |  | ||||||
|  |         val viceMonlist = C64Target.viceMonListName(programNameWithPath.toString()) | ||||||
|  |         val cmdline = listOf("xpet", "-model", "4032", "-ramsize", "32", "-videosize", "40", "-silent", "-moncommands", viceMonlist, | ||||||
|  |             "-autostartprgmode", "1", "-autostart-warp", "-autostart", "${programNameWithPath}.prg") | ||||||
|  |         val processb = ProcessBuilder(cmdline) | ||||||
|  |         if(!quiet) | ||||||
|  |             processb.inheritIO() | ||||||
|  |         val process=processb.start() | ||||||
|  |         process.waitFor() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun isIOAddress(address: UInt): Boolean = address in 0xe800u..0xe8ffu | ||||||
|  |  | ||||||
|  |     override fun initializeMemoryAreas(compilerOptions: CompilationOptions) { | ||||||
|  |         zeropage = PETZeropage(compilerOptions) | ||||||
|  |         golden = GoldenRam(compilerOptions, UIntRange.EMPTY) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										109
									
								
								codeCore/src/prog8/code/target/VMTarget.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								codeCore/src/prog8/code/target/VMTarget.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,109 @@ | |||||||
|  | package prog8.code.target | ||||||
|  |  | ||||||
|  | import prog8.code.core.* | ||||||
|  | import prog8.code.target.encodings.Encoder | ||||||
|  | import java.nio.file.Path | ||||||
|  | import kotlin.io.path.extension | ||||||
|  | import kotlin.io.path.isReadable | ||||||
|  | import kotlin.io.path.name | ||||||
|  | import kotlin.io.path.readText | ||||||
|  |  | ||||||
|  | class VMTarget: ICompilationTarget, | ||||||
|  |     IStringEncoding by Encoder(false), | ||||||
|  |     IMemSizer by NormalMemSizer(FLOAT_MEM_SIZE) { | ||||||
|  |  | ||||||
|  |     override val name = NAME | ||||||
|  |     override val defaultEncoding = Encoding.ISO | ||||||
|  |     override val libraryPath = null | ||||||
|  |     override val customLauncher = emptyList<String>() | ||||||
|  |     override val additionalAssemblerOptions = emptyList<String>() | ||||||
|  |     override val defaultOutputType = OutputType.PRG | ||||||
|  |  | ||||||
|  |     companion object { | ||||||
|  |         const val NAME = "virtual" | ||||||
|  |         const val FLOAT_MEM_SIZE = 8             // 64-bits double | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override val cpu = CpuType.VIRTUAL | ||||||
|  |  | ||||||
|  |     override val FLOAT_MAX_POSITIVE = Double.MAX_VALUE | ||||||
|  |     override val FLOAT_MAX_NEGATIVE = -Double.MAX_VALUE | ||||||
|  |     override val FLOAT_MEM_SIZE = VMTarget.FLOAT_MEM_SIZE | ||||||
|  |     override val STARTUP_CODE_RESERVED_SIZE = 0u  // not actually used | ||||||
|  |     override val PROGRAM_LOAD_ADDRESS = 0u      // not actually used | ||||||
|  |     override val PROGRAM_MEMTOP_ADDRESS = 0xffffu  // not actually used | ||||||
|  |  | ||||||
|  |     override val BSSHIGHRAM_START = 0u          // not actually used | ||||||
|  |     override val BSSHIGHRAM_END = 0u            // not actually used | ||||||
|  |     override val BSSGOLDENRAM_START = 0u        // not actually used | ||||||
|  |     override val BSSGOLDENRAM_END = 0u          // not actually used | ||||||
|  |     override lateinit var zeropage: Zeropage    // not actually used | ||||||
|  |     override lateinit var golden: GoldenRam     // not actually used | ||||||
|  |  | ||||||
|  |     override fun getFloatAsmBytes(num: Number): String { | ||||||
|  |         // little endian binary representation | ||||||
|  |         val bits = num.toDouble().toBits().toULong() | ||||||
|  |         val hexStr = bits.toString(16).padStart(16, '0') | ||||||
|  |         val parts = hexStr.chunked(2).map { "$$it" } | ||||||
|  |         return parts.joinToString(", ") | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun convertFloatToBytes(num: Double): List<UByte> { | ||||||
|  |         val bits = num.toBits().toULong() | ||||||
|  |         val hexStr = bits.toString(16).padStart(16, '0') | ||||||
|  |         val parts = hexStr.chunked(2).map { it.toInt(16).toUByte() } | ||||||
|  |         return parts | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun convertBytesToFloat(bytes: List<UByte>): Double { | ||||||
|  |         require(bytes.size==8) { "need 8 bytes" } | ||||||
|  |         val b0 = bytes[0].toLong() shl (8*7) | ||||||
|  |         val b1 = bytes[1].toLong() shl (8*6) | ||||||
|  |         val b2 = bytes[2].toLong() shl (8*5) | ||||||
|  |         val b3 = bytes[3].toLong() shl (8*4) | ||||||
|  |         val b4 = bytes[4].toLong() shl (8*3) | ||||||
|  |         val b5 = bytes[5].toLong() shl (8*2) | ||||||
|  |         val b6 = bytes[6].toLong() shl (8*1) | ||||||
|  |         val b7 = bytes[7].toLong() shl (8*0) | ||||||
|  |         return Double.fromBits(b0 or b1 or b2 or b3 or b4 or b5 or b6 or b7) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun launchEmulator(selectedEmulator: Int, programNameWithPath: Path, quiet: Boolean) { | ||||||
|  |         if(!quiet) | ||||||
|  |             println("\nStarting Virtual Machine...") | ||||||
|  |  | ||||||
|  |         // to not have external module dependencies in our own module, we launch the virtual machine via reflection | ||||||
|  |         val vm = Class.forName("prog8.vm.VmRunner").getDeclaredConstructor().newInstance() as IVirtualMachineRunner | ||||||
|  |         val withExt = if(programNameWithPath.extension=="p8ir") programNameWithPath else programNameWithPath.resolveSibling("${programNameWithPath.name}.p8ir") | ||||||
|  |         if(withExt.isReadable()) | ||||||
|  |             vm.runProgram(withExt.readText(), quiet) | ||||||
|  |         else | ||||||
|  |             throw java.nio.file.NoSuchFileException(withExt.name, null, "not a .p8ir file") | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun isIOAddress(address: UInt): Boolean = false | ||||||
|  |  | ||||||
|  |     override fun initializeMemoryAreas(compilerOptions: CompilationOptions) { | ||||||
|  |         zeropage = VirtualZeropage(compilerOptions) | ||||||
|  |         golden = GoldenRam(compilerOptions, UIntRange.EMPTY) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | interface IVirtualMachineRunner { | ||||||
|  |     fun runProgram(irSource: String, quiet: Boolean) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | private class VirtualZeropage(options: CompilationOptions): Zeropage(options) { | ||||||
|  |     override val SCRATCH_B1: UInt | ||||||
|  |         get() = throw IllegalStateException("virtual shouldn't use this zeropage variable") | ||||||
|  |     override val SCRATCH_REG: UInt | ||||||
|  |         get() = throw IllegalStateException("virtual shouldn't use this zeropage variable") | ||||||
|  |     override val SCRATCH_W1: UInt | ||||||
|  |         get() = throw IllegalStateException("virtual shouldn't use this zeropage variable") | ||||||
|  |     override val SCRATCH_W2: UInt | ||||||
|  |         get() = throw IllegalStateException("virtual shouldn't use this zeropage variable") | ||||||
|  |     override val SCRATCH_PTR: UInt | ||||||
|  |         get() = throw IllegalStateException("virtual shouldn't use this zeropage variable") | ||||||
|  | } | ||||||
							
								
								
									
										215
									
								
								codeCore/src/prog8/code/target/encodings/AtasciiEncoding.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								codeCore/src/prog8/code/target/encodings/AtasciiEncoding.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,215 @@ | |||||||
|  | package prog8.code.target.encodings | ||||||
|  |  | ||||||
|  | import com.github.michaelbull.result.Ok | ||||||
|  | import com.github.michaelbull.result.Result | ||||||
|  | import java.io.CharConversionException | ||||||
|  |  | ||||||
|  | object AtasciiEncoding { | ||||||
|  |  | ||||||
|  |     private val decodeTable: CharArray = charArrayOf( | ||||||
|  |         // $00 | ||||||
|  |         '♥', | ||||||
|  |         '├', | ||||||
|  |         '\uf130',    //  🮇    0x02 -> RIGHT ONE QUARTER BLOCK (CUS) | ||||||
|  |         '┘', | ||||||
|  |         '┤', | ||||||
|  |         '┐', | ||||||
|  |         '╱', | ||||||
|  |         '╲', | ||||||
|  |         '◢', | ||||||
|  |         '▗', | ||||||
|  |         '◣', | ||||||
|  |         '▝', | ||||||
|  |         '▘', | ||||||
|  |         '\uf132',    //  🮂    0x1d -> UPPER ONE QUARTER BLOCK (CUS) | ||||||
|  |         '▂', | ||||||
|  |         '▖', | ||||||
|  |  | ||||||
|  |         // $10 | ||||||
|  |         '♣', | ||||||
|  |         '┌', | ||||||
|  |         '─', | ||||||
|  |         '┼', | ||||||
|  |         '•', | ||||||
|  |         '▄', | ||||||
|  |         '▎', | ||||||
|  |         '┬', | ||||||
|  |         '┴', | ||||||
|  |         '▌', | ||||||
|  |         '└', | ||||||
|  |         '\u001b',           // $1b = escape | ||||||
|  |         '\ufffe',           // UNDEFINED CHAR.   $1c = cursor up | ||||||
|  |         '\ufffe',           // UNDEFINED CHAR.   $1d = cursor down | ||||||
|  |         '\ufffe',           // UNDEFINED CHAR.   $1e = cursor left | ||||||
|  |         '\ufffe',           // UNDEFINED CHAR.   $1f = cursor right | ||||||
|  |  | ||||||
|  |         // $20 | ||||||
|  |         ' ', | ||||||
|  |         '!', | ||||||
|  |         '"', | ||||||
|  |         '#', | ||||||
|  |         '$', | ||||||
|  |         '%', | ||||||
|  |         '&', | ||||||
|  |         '\'', | ||||||
|  |         '(', | ||||||
|  |         ')', | ||||||
|  |         '*', | ||||||
|  |         '+', | ||||||
|  |         ',', | ||||||
|  |         '-', | ||||||
|  |         '.', | ||||||
|  |         '/', | ||||||
|  |  | ||||||
|  |         // $30 | ||||||
|  |         '0', | ||||||
|  |         '1', | ||||||
|  |         '2', | ||||||
|  |         '3', | ||||||
|  |         '4', | ||||||
|  |         '5', | ||||||
|  |         '6', | ||||||
|  |         '7', | ||||||
|  |         '8', | ||||||
|  |         '9', | ||||||
|  |         ':', | ||||||
|  |         ';', | ||||||
|  |         '<', | ||||||
|  |         '=', | ||||||
|  |         '>', | ||||||
|  |         '?', | ||||||
|  |  | ||||||
|  |         // $40 | ||||||
|  |         '@', | ||||||
|  |         'A', | ||||||
|  |         'B', | ||||||
|  |         'C', | ||||||
|  |         'D', | ||||||
|  |         'E', | ||||||
|  |         'F', | ||||||
|  |         'G', | ||||||
|  |         'H', | ||||||
|  |         'I', | ||||||
|  |         'J', | ||||||
|  |         'K', | ||||||
|  |         'L', | ||||||
|  |         'M', | ||||||
|  |         'N', | ||||||
|  |         'O', | ||||||
|  |  | ||||||
|  |         // $50 | ||||||
|  |         'P', | ||||||
|  |         'Q', | ||||||
|  |         'R', | ||||||
|  |         'S', | ||||||
|  |         'T', | ||||||
|  |         'U', | ||||||
|  |         'V', | ||||||
|  |         'W', | ||||||
|  |         'X', | ||||||
|  |         'Y', | ||||||
|  |         'Z', | ||||||
|  |         '[', | ||||||
|  |         '\\', | ||||||
|  |         ']', | ||||||
|  |         '^', | ||||||
|  |         '_', | ||||||
|  |  | ||||||
|  |         // $60 | ||||||
|  |         '♦', | ||||||
|  |         'a', | ||||||
|  |         'b', | ||||||
|  |         'c', | ||||||
|  |         'd', | ||||||
|  |         'e', | ||||||
|  |         'f', | ||||||
|  |         'g', | ||||||
|  |         'h', | ||||||
|  |         'i', | ||||||
|  |         'j', | ||||||
|  |         'k', | ||||||
|  |         'l', | ||||||
|  |         'm', | ||||||
|  |         'n', | ||||||
|  |         'o', | ||||||
|  |  | ||||||
|  |         // $70 | ||||||
|  |         'p', | ||||||
|  |         'q', | ||||||
|  |         'r', | ||||||
|  |         's', | ||||||
|  |         't', | ||||||
|  |         'u', | ||||||
|  |         'v', | ||||||
|  |         'w', | ||||||
|  |         'x', | ||||||
|  |         'y', | ||||||
|  |         'z', | ||||||
|  |         '♠', | ||||||
|  |         '|', | ||||||
|  |         '\u000c',    //       $7d -> FORM FEED (CLEAR SCREEN) | ||||||
|  |         '\u0008',    //       $7e -> BACKSPACE | ||||||
|  |         '\u0009',    //       $7f -> TAB | ||||||
|  |  | ||||||
|  |         // $80-$ff are reversed video characters + various special characters. | ||||||
|  |         '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', | ||||||
|  |         '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', | ||||||
|  |         // $90 | ||||||
|  |         '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', | ||||||
|  |         '\ufffe', | ||||||
|  |         '\ufffe', | ||||||
|  |         '\ufffe', | ||||||
|  |         '\n',               // $9b -> EOL/RETURN | ||||||
|  |         '\ufffe',           // UNDEFINED   $9c = DELETE LINE | ||||||
|  |         '\ufffe',           // UNDEFINED   $9d = INSERT LINE | ||||||
|  |         '\ufffe',           // UNDEFINED   $9e = CLEAR TAB STOP | ||||||
|  |         '\ufffe',           // UNDEFINED   $9f = SET TAB STOP | ||||||
|  |         // $a0 | ||||||
|  |         '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', | ||||||
|  |         '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', | ||||||
|  |         // $b0 | ||||||
|  |         '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', | ||||||
|  |         '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', | ||||||
|  |         // $c0 | ||||||
|  |         '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', | ||||||
|  |         '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', | ||||||
|  |         // $d0 | ||||||
|  |         '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', | ||||||
|  |         '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', | ||||||
|  |         // $e0 | ||||||
|  |         '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', | ||||||
|  |         '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', | ||||||
|  |         // $f0 | ||||||
|  |         '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', '\ufffe', | ||||||
|  |         '\ufffe', | ||||||
|  |         '\ufffe', | ||||||
|  |         '\ufffe', | ||||||
|  |         '\ufffe', | ||||||
|  |         '\ufffe', | ||||||
|  |         '\u0007',           // $fd = bell/beep | ||||||
|  |         '\u007f',           // $fe = DELETE | ||||||
|  |         '\ufffe'            // UNDEFINED     $ff = INSERT | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |     private val encodeTable = decodeTable.withIndex().associate{it.value to it.index} | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     fun encode(str: String): Result<List<UByte>, CharConversionException> { | ||||||
|  |         val mapped = str.map { chr -> | ||||||
|  |             when (chr) { | ||||||
|  |                 '\r' -> 0x9bu | ||||||
|  |                 '\u0000' -> 0u | ||||||
|  |                 in '\u8000'..'\u80ff' -> { | ||||||
|  |                     // special case: take the lower 8 bit hex value directly | ||||||
|  |                     (chr.code - 0x8000).toUByte() | ||||||
|  |                 } | ||||||
|  |                 else -> encodeTable.getValue(chr).toUByte() | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return Ok(mapped) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun decode(bytes: Iterable<UByte>): Result<String, CharConversionException> { | ||||||
|  |         return Ok(bytes.map { decodeTable[it.toInt()] }.joinToString("")) | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										327
									
								
								codeCore/src/prog8/code/target/encodings/C64osEncoding.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										327
									
								
								codeCore/src/prog8/code/target/encodings/C64osEncoding.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,327 @@ | |||||||
|  | package prog8.code.target.encodings | ||||||
|  |  | ||||||
|  | import com.github.michaelbull.result.Err | ||||||
|  | import com.github.michaelbull.result.Ok | ||||||
|  | import com.github.michaelbull.result.Result | ||||||
|  | import java.io.CharConversionException | ||||||
|  |  | ||||||
|  | object C64osEncoding { | ||||||
|  |  | ||||||
|  |     // decoding:  from C64 OS Screencodes (0-255) to unicode | ||||||
|  |     // character table from: | ||||||
|  |     // https://www.c64os.com/c64os/usersguide/appendices#charactersets | ||||||
|  |  | ||||||
|  |     private val decodingC64os = charArrayOf( | ||||||
|  |         '@'     ,    //  @    0x00 -> COMMERCIAL AT | ||||||
|  |         'a'     ,    //  a    0x01 -> LATIN SMALL LETTER A | ||||||
|  |         'b'     ,    //  b    0x02 -> LATIN SMALL LETTER B | ||||||
|  |         'c'     ,    //  c    0x03 -> LATIN SMALL LETTER C | ||||||
|  |         'd'     ,    //  d    0x04 -> LATIN SMALL LETTER D | ||||||
|  |         'e'     ,    //  e    0x05 -> LATIN SMALL LETTER E | ||||||
|  |         'f'     ,    //  f    0x06 -> LATIN SMALL LETTER F | ||||||
|  |         'g'     ,    //  g    0x07 -> LATIN SMALL LETTER G | ||||||
|  |         'h'     ,    //  h    0x08 -> LATIN SMALL LETTER H | ||||||
|  |         'i'     ,    //  i    0x09 -> LATIN SMALL LETTER I | ||||||
|  |         'j'     ,    //  j    0x0A -> LATIN SMALL LETTER J | ||||||
|  |         'k'     ,    //  k    0x0B -> LATIN SMALL LETTER K | ||||||
|  |         'l'     ,    //  l    0x0C -> LATIN SMALL LETTER L | ||||||
|  |         'm'     ,    //  m    0x0D -> LATIN SMALL LETTER M | ||||||
|  |         'n'     ,    //  n    0x0E -> LATIN SMALL LETTER N | ||||||
|  |         'o'     ,    //  o    0x0F -> LATIN SMALL LETTER O | ||||||
|  |         'p'     ,    //  p    0x10 -> LATIN SMALL LETTER P | ||||||
|  |         'q'     ,    //  q    0x11 -> LATIN SMALL LETTER Q | ||||||
|  |         'r'     ,    //  r    0x12 -> LATIN SMALL LETTER R | ||||||
|  |         's'     ,    //  s    0x13 -> LATIN SMALL LETTER S | ||||||
|  |         't'     ,    //  t    0x14 -> LATIN SMALL LETTER T | ||||||
|  |         'u'     ,    //  u    0x15 -> LATIN SMALL LETTER U | ||||||
|  |         'v'     ,    //  v    0x16 -> LATIN SMALL LETTER V | ||||||
|  |         'w'     ,    //  w    0x17 -> LATIN SMALL LETTER W | ||||||
|  |         'x'     ,    //  x    0x18 -> LATIN SMALL LETTER X | ||||||
|  |         'y'     ,    //  y    0x19 -> LATIN SMALL LETTER Y | ||||||
|  |         'z'     ,    //  z    0x1A -> LATIN SMALL LETTER Z | ||||||
|  |         '['     ,    //  [    0x1B -> LEFT SQUARE BRACKET | ||||||
|  |         '\\'    ,    //  \    0x1C -> REVERSE SOLIDUS | ||||||
|  |         ']'     ,    //  ]    0x1D -> RIGHT SQUARE BRACKET | ||||||
|  |         '^'     ,    //  ^    0x1E -> CIRCUMFLEX | ||||||
|  |         '_'     ,    //  _    0x1F -> UNDERSCORE | ||||||
|  |         ' '     ,    //       0x20 -> SPACE | ||||||
|  |         '!'     ,    //  !    0x21 -> EXCLAMATION MARK | ||||||
|  |         '"'     ,    //  "    0x22 -> QUOTATION MARK | ||||||
|  |         '#'     ,    //  #    0x23 -> NUMBER SIGN | ||||||
|  |         '$'     ,    //  $    0x24 -> DOLLAR SIGN | ||||||
|  |         '%'     ,    //  %    0x25 -> PERCENT SIGN | ||||||
|  |         '&'     ,    //  &    0x26 -> AMPERSAND | ||||||
|  |         '\''    ,    //  '    0x27 -> APOSTROPHE | ||||||
|  |         '('     ,    //  (    0x28 -> LEFT PARENTHESIS | ||||||
|  |         ')'     ,    //  )    0x29 -> RIGHT PARENTHESIS | ||||||
|  |         '*'     ,    //  *    0x2A -> ASTERISK | ||||||
|  |         '+'     ,    //  +    0x2B -> PLUS SIGN | ||||||
|  |         ','     ,    //  ,    0x2C -> COMMA | ||||||
|  |         '-'     ,    //  -    0x2D -> HYPHEN-MINUS | ||||||
|  |         '.'     ,    //  .    0x2E -> FULL STOP | ||||||
|  |         '/'     ,    //  /    0x2F -> SOLIDUS | ||||||
|  |         '0'     ,    //  0    0x30 -> DIGIT ZERO | ||||||
|  |         '1'     ,    //  1    0x31 -> DIGIT ONE | ||||||
|  |         '2'     ,    //  2    0x32 -> DIGIT TWO | ||||||
|  |         '3'     ,    //  3    0x33 -> DIGIT THREE | ||||||
|  |         '4'     ,    //  4    0x34 -> DIGIT FOUR | ||||||
|  |         '5'     ,    //  5    0x35 -> DIGIT FIVE | ||||||
|  |         '6'     ,    //  6    0x36 -> DIGIT SIX | ||||||
|  |         '7'     ,    //  7    0x37 -> DIGIT SEVEN | ||||||
|  |         '8'     ,    //  8    0x38 -> DIGIT EIGHT | ||||||
|  |         '9'     ,    //  9    0x39 -> DIGIT NINE | ||||||
|  |         ':'     ,    //  :    0x3A -> COLON | ||||||
|  |         ';'     ,    //  ;    0x3B -> SEMICOLON | ||||||
|  |         '<'     ,    //  <    0x3C -> LESS-THAN SIGN | ||||||
|  |         '='     ,    //  =    0x3D -> EQUALS SIGN | ||||||
|  |         '>'     ,    //  >    0x3E -> GREATER-THAN SIGN | ||||||
|  |         '?'     ,    //  ?    0x3F -> QUESTION MARK | ||||||
|  |         '`'     ,    //  `    0x40 -> GRAVE ACCENT | ||||||
|  |         'A'     ,    //  A    0x41 -> LATIN CAPITAL LETTER A | ||||||
|  |         'B'     ,    //  B    0x42 -> LATIN CAPITAL LETTER B | ||||||
|  |         'C'     ,    //  C    0x43 -> LATIN CAPITAL LETTER C | ||||||
|  |         'D'     ,    //  D    0x44 -> LATIN CAPITAL LETTER D | ||||||
|  |         'E'     ,    //  E    0x45 -> LATIN CAPITAL LETTER E | ||||||
|  |         'F'     ,    //  F    0x46 -> LATIN CAPITAL LETTER F | ||||||
|  |         'G'     ,    //  G    0x47 -> LATIN CAPITAL LETTER G | ||||||
|  |         'H'     ,    //  H    0x48 -> LATIN CAPITAL LETTER H | ||||||
|  |         'I'     ,    //  I    0x49 -> LATIN CAPITAL LETTER I | ||||||
|  |         'J'     ,    //  J    0x4A -> LATIN CAPITAL LETTER J | ||||||
|  |         'K'     ,    //  K    0x4B -> LATIN CAPITAL LETTER K | ||||||
|  |         'L'     ,    //  L    0x4C -> LATIN CAPITAL LETTER L | ||||||
|  |         'M'     ,    //  M    0x4D -> LATIN CAPITAL LETTER M | ||||||
|  |         'N'     ,    //  N    0x4E -> LATIN CAPITAL LETTER N | ||||||
|  |         'O'     ,    //  O    0x4F -> LATIN CAPITAL LETTER O | ||||||
|  |         'P'     ,    //  P    0x50 -> LATIN CAPITAL LETTER P | ||||||
|  |         'Q'     ,    //  Q    0x51 -> LATIN CAPITAL LETTER Q | ||||||
|  |         'R'     ,    //  R    0x52 -> LATIN CAPITAL LETTER R | ||||||
|  |         'S'     ,    //  S    0x53 -> LATIN CAPITAL LETTER S | ||||||
|  |         'T'     ,    //  T    0x54 -> LATIN CAPITAL LETTER T | ||||||
|  |         'U'     ,    //  U    0x55 -> LATIN CAPITAL LETTER U | ||||||
|  |         'V'     ,    //  V    0x56 -> LATIN CAPITAL LETTER V | ||||||
|  |         'W'     ,    //  W    0x57 -> LATIN CAPITAL LETTER W | ||||||
|  |         'X'     ,    //  X    0x58 -> LATIN CAPITAL LETTER X | ||||||
|  |         'Y'     ,    //  Y    0x59 -> LATIN CAPITAL LETTER Y | ||||||
|  |         'Z'     ,    //  Z    0x5A -> LATIN CAPITAL LETTER Z | ||||||
|  |         '{'     ,    //  {    0x5B -> LEFT BRACE | ||||||
|  |         '|'     ,    //  |    0x5C -> VERTICAL BAR | ||||||
|  |         '}'     ,    //  }    0x5D -> RIGHT BRACE | ||||||
|  |         '~'     ,    //  ~    0x5E -> TILDE | ||||||
|  |         '\ufffe',    //       0x5F -> RESERVED | ||||||
|  |         '\u00a0',    //       0x60 -> NO-BREAK SPACE (TRANSPARENT) | ||||||
|  |         '\ufffe',    //       0x61 -> COMMODORE SYMBOL | ||||||
|  |         '\u2191',    //  ↑    0x62 -> UP ARROW | ||||||
|  |         '\u2193',    //  ↓    0x63 -> DOWN ARROW | ||||||
|  |         '\u2190',    //  ←    0x64 -> LEFT ARROW | ||||||
|  |         '\u2192',    //  →    0x65 -> RIGHT ARROW | ||||||
|  |         '\u231A',    //  ⌚   0x66 -> WATCH (ANALOG CLOCKFACE) | ||||||
|  |         '\u21BB',    //  ↻    0x67 -> CYCLE ARROWS | ||||||
|  |         '\u2026',    //  …    0x68 -> ELLIPSIS | ||||||
|  |         '\u25a7',    //  ▧    0x69 -> DIAGNONAL STRIPES | ||||||
|  |         '\u2610',    //  ☐    0x6A -> CHECKBOX UNCHECKED | ||||||
|  |         '\u2611',    //  ☑    0x6B -> CHECKBOX CHECKED | ||||||
|  |         '\ufffe',    //       0x6C -> RADIO BUTTON UNSELECTED | ||||||
|  |         '\ufffe',    //       0x6D -> RADIO BUTTON SELECTED | ||||||
|  |         '\ufffe',    //       0x6E -> UTILITY CLOSE BUTTON | ||||||
|  |         '\ufffe',    //       0x6F -> UTILITY TITLE BAR | ||||||
|  |         '\u00a9',    //  ©    0x70 -> COPYRIGHT | ||||||
|  |         '\u2713',    //  ✓    0x71 -> CHECKMARK | ||||||
|  |         '\u2261',    //  ≡    0x72 -> THREE HORIZONTAL STRIPES | ||||||
|  |         '\ufffe',    //       0x73 -> TICK TRACK | ||||||
|  |         '\ufffe',    //       0x74 -> TICK TRACK NUB | ||||||
|  |         '\ufffe',    //       0x75 -> TAB CORNER | ||||||
|  |         '\u2980',    //  ⦀    0x76 -> THREE VERTICAL STRIPES | ||||||
|  |         '\ufffe',    //       0x77 -> CUSTOM 1 | ||||||
|  |         '\ufffe',    //       0x78 -> CUSTOM 2 | ||||||
|  |         '\ufffe',    //       0x79 -> CUSTOM 3 | ||||||
|  |         '\ufffe',    //       0x7A -> CUSTOM 4 | ||||||
|  |         '\ufffe',    //       0x7B -> CUSTOM 5 | ||||||
|  |         '\ufffe',    //       0x7C -> CUSTOM 6 | ||||||
|  |         '\ufffe',    //       0x7D -> CUSTOM 7 | ||||||
|  |         '\ufffe',    //       0x7E -> CUSTOM 8 | ||||||
|  |         '\ufffe',    //       0x7F -> CUSTOM 9 | ||||||
|  |         '\ufffe',    //       0x80 -> REVERSED COMMERCIAL AT | ||||||
|  |         '\ufffe',    //       0x81 -> REVERSED LATIN SMALL LETTER A | ||||||
|  |         '\ufffe',    //       0x82 -> REVERSED LATIN SMALL LETTER B | ||||||
|  |         '\ufffe',    //       0x83 -> REVERSED LATIN SMALL LETTER C | ||||||
|  |         '\ufffe',    //       0x84 -> REVERSED LATIN SMALL LETTER D | ||||||
|  |         '\ufffe',    //       0x85 -> REVERSED LATIN SMALL LETTER E | ||||||
|  |         '\ufffe',    //       0x86 -> REVERSED LATIN SMALL LETTER F | ||||||
|  |         '\ufffe',    //       0x87 -> REVERSED LATIN SMALL LETTER G | ||||||
|  |         '\ufffe',    //       0x88 -> REVERSED LATIN SMALL LETTER H | ||||||
|  |         '\ufffe',    //       0x89 -> REVERSED LATIN SMALL LETTER I | ||||||
|  |         '\ufffe',    //       0x8A -> REVERSED LATIN SMALL LETTER J | ||||||
|  |         '\ufffe',    //       0x8B -> REVERSED LATIN SMALL LETTER K | ||||||
|  |         '\ufffe',    //       0x8C -> REVERSED LATIN SMALL LETTER L | ||||||
|  |         '\ufffe',    //       0x8D -> REVERSED LATIN SMALL LETTER M | ||||||
|  |         '\ufffe',    //       0x8E -> REVERSED LATIN SMALL LETTER N | ||||||
|  |         '\ufffe',    //       0x8F -> REVERSED LATIN SMALL LETTER O | ||||||
|  |         '\ufffe',    //       0x90 -> REVERSED LATIN SMALL LETTER P | ||||||
|  |         '\ufffe',    //       0x91 -> REVERSED LATIN SMALL LETTER Q | ||||||
|  |         '\ufffe',    //       0x92 -> REVERSED LATIN SMALL LETTER R | ||||||
|  |         '\ufffe',    //       0x93 -> REVERSED LATIN SMALL LETTER S | ||||||
|  |         '\ufffe',    //       0x94 -> REVERSED LATIN SMALL LETTER T | ||||||
|  |         '\ufffe',    //       0x95 -> REVERSED LATIN SMALL LETTER U | ||||||
|  |         '\ufffe',    //       0x96 -> REVERSED LATIN SMALL LETTER V | ||||||
|  |         '\ufffe',    //       0x97 -> REVERSED LATIN SMALL LETTER W | ||||||
|  |         '\ufffe',    //       0x98 -> REVERSED LATIN SMALL LETTER X | ||||||
|  |         '\ufffe',    //       0x99 -> REVERSED LATIN SMALL LETTER Y | ||||||
|  |         '\ufffe',    //       0x9A -> REVERSED LATIN SMALL LETTER Z | ||||||
|  |         '\ufffe',    //       0x9B -> REVERSED LEFT SQUARE BRACKET | ||||||
|  |         '\ufffe',    //       0x9C -> REVERSED REVERSE SOLIDUS | ||||||
|  |         '\ufffe',    //       0x9D -> REVERSED RIGHT SQUARE BRACKET | ||||||
|  |         '\ufffe',    //       0x9E -> REVERSED CIRCUMFLEX | ||||||
|  |         '\ufffe',    //       0x9F -> REVERSED UNDERSCORE | ||||||
|  |         '\ufffe',    //       0xA0 -> REVERSED SPACE | ||||||
|  |         '\ufffe',    //       0xA1 -> REVERSED EXCLAMATION MARK | ||||||
|  |         '\ufffe',    //       0xA2 -> REVERSED QUOTATION MARK | ||||||
|  |         '\ufffe',    //       0xA3 -> REVERSED NUMBER SIGN | ||||||
|  |         '\ufffe',    //       0xA4 -> REVERSED DOLLAR SIGN | ||||||
|  |         '\ufffe',    //       0xA5 -> REVERSED PERCENT SIGN | ||||||
|  |         '\ufffe',    //       0xA6 -> REVERSED AMPERSAND | ||||||
|  |         '\ufffe',    //       0xA7 -> REVERSED APOSTROPHE | ||||||
|  |         '\ufffe',    //       0xA8 -> REVERSED LEFT PARENTHESIS | ||||||
|  |         '\ufffe',    //       0xA9 -> REVERSED RIGHT PARENTHESIS | ||||||
|  |         '\ufffe',    //       0xAA -> REVERSED ASTERISK | ||||||
|  |         '\ufffe',    //       0xAB -> REVERSED PLUS SIGN | ||||||
|  |         '\ufffe',    //       0xAC -> REVERSED COMMA | ||||||
|  |         '\ufffe',    //       0xAD -> REVERSED HYPHEN-MINUS | ||||||
|  |         '\ufffe',    //       0xAE -> REVERSED FULL STOP | ||||||
|  |         '\ufffe',    //       0xAF -> REVERSED SOLIDUS | ||||||
|  |         '\ufffe',    //       0xB0 -> REVERSED DIGIT ZERO | ||||||
|  |         '\ufffe',    //       0xB1 -> REVERSED DIGIT ONE | ||||||
|  |         '\ufffe',    //       0xB2 -> REVERSED DIGIT TWO | ||||||
|  |         '\ufffe',    //       0xB3 -> REVERSED DIGIT THREE | ||||||
|  |         '\ufffe',    //       0xB4 -> REVERSED DIGIT FOUR | ||||||
|  |         '\ufffe',    //       0xB5 -> REVERSED DIGIT FIVE | ||||||
|  |         '\ufffe',    //       0xB6 -> REVERSED DIGIT SIX | ||||||
|  |         '\ufffe',    //       0xB7 -> REVERSED DIGIT SEVEN | ||||||
|  |         '\ufffe',    //       0xB8 -> REVERSED DIGIT EIGHT | ||||||
|  |         '\ufffe',    //       0xB9 -> REVERSED DIGIT NINE | ||||||
|  |         '\ufffe',    //       0xBA -> REVERSED COLON | ||||||
|  |         '\ufffe',    //       0xBB -> REVERSED SEMICOLON | ||||||
|  |         '\ufffe',    //       0xBC -> REVERSED LESS-THAN SIGN | ||||||
|  |         '\ufffe',    //       0xBD -> REVERSED EQUALS SIGN | ||||||
|  |         '\ufffe',    //       0xBE -> REVERSED GREATER-THAN SIGN | ||||||
|  |         '\ufffe',    //       0xBF -> REVERSED QUESTION MARK | ||||||
|  |         '\ufffe',    //       0xC0 -> REVERSED GRAVE ACCENT | ||||||
|  |         '\ufffe',    //       0xC1 -> REVERSED LATIN CAPITAL LETTER A | ||||||
|  |         '\ufffe',    //       0xC2 -> REVERSED LATIN CAPITAL LETTER B | ||||||
|  |         '\ufffe',    //       0xC3 -> REVERSED LATIN CAPITAL LETTER C | ||||||
|  |         '\ufffe',    //       0xC4 -> REVERSED LATIN CAPITAL LETTER D | ||||||
|  |         '\ufffe',    //       0xC5 -> REVERSED LATIN CAPITAL LETTER E | ||||||
|  |         '\ufffe',    //       0xC6 -> REVERSED LATIN CAPITAL LETTER F | ||||||
|  |         '\ufffe',    //       0xC7 -> REVERSED LATIN CAPITAL LETTER G | ||||||
|  |         '\ufffe',    //       0xC8 -> REVERSED LATIN CAPITAL LETTER H | ||||||
|  |         '\ufffe',    //       0xC9 -> REVERSED LATIN CAPITAL LETTER I | ||||||
|  |         '\ufffe',    //       0xCA -> REVERSED LATIN CAPITAL LETTER J | ||||||
|  |         '\ufffe',    //       0xCB -> REVERSED LATIN CAPITAL LETTER K | ||||||
|  |         '\ufffe',    //       0xCC -> REVERSED LATIN CAPITAL LETTER L | ||||||
|  |         '\ufffe',    //       0xCD -> REVERSED LATIN CAPITAL LETTER M | ||||||
|  |         '\ufffe',    //       0xCE -> REVERSED LATIN CAPITAL LETTER N | ||||||
|  |         '\ufffe',    //       0xCF -> REVERSED LATIN CAPITAL LETTER O | ||||||
|  |         '\ufffe',    //       0xD0 -> REVERSED LATIN CAPITAL LETTER P | ||||||
|  |         '\ufffe',    //       0xD1 -> REVERSED LATIN CAPITAL LETTER Q | ||||||
|  |         '\ufffe',    //       0xD2 -> REVERSED LATIN CAPITAL LETTER R | ||||||
|  |         '\ufffe',    //       0xD3 -> REVERSED LATIN CAPITAL LETTER S | ||||||
|  |         '\ufffe',    //       0xD4 -> REVERSED LATIN CAPITAL LETTER T | ||||||
|  |         '\ufffe',    //       0xD5 -> REVERSED LATIN CAPITAL LETTER U | ||||||
|  |         '\ufffe',    //       0xD6 -> REVERSED LATIN CAPITAL LETTER V | ||||||
|  |         '\ufffe',    //       0xD7 -> REVERSED LATIN CAPITAL LETTER W | ||||||
|  |         '\ufffe',    //       0xD8 -> REVERSED LATIN CAPITAL LETTER X | ||||||
|  |         '\ufffe',    //       0xD9 -> REVERSED LATIN CAPITAL LETTER Y | ||||||
|  |         '\ufffe',    //       0xDA -> REVERSED LATIN CAPITAL LETTER Z | ||||||
|  |         '\ufffe',    //       0xDB -> REVERSED LEFT BRACE | ||||||
|  |         '\ufffe',    //       0xDC -> REVERSED VERTICAL BAR | ||||||
|  |         '\ufffe',    //       0xDD -> REVERSED RIGHT BRACE | ||||||
|  |         '\ufffe',    //       0xDE -> REVERSED TILDE | ||||||
|  |         '\ufffe',    //       0xDF -> RESERVED | ||||||
|  |         '\ufffe',    //       0xE0 -> RESERVED | ||||||
|  |         '\ufffe',    //       0xE1 -> REVERSED COMMODORE SYMBOL | ||||||
|  |         '\ufffe',    //       0xE2 -> REVERSED UP ARROW | ||||||
|  |         '\ufffe',    //       0xE3 -> REVERSED DOWN ARROW | ||||||
|  |         '\ufffe',    //       0xE4 -> REVERSED LEFT ARROW | ||||||
|  |         '\ufffe',    //       0xE5 -> REVERSED RIGHT ARROW | ||||||
|  |         '\ufffe',    //       0xE6 -> REVERSED ANALOG CLOCKFACE | ||||||
|  |         '\ufffe',    //       0xE7 -> REVERSED CYCLE ARROWS | ||||||
|  |         '\ufffe',    //       0xE8 -> REVERSED ELLIPSIS | ||||||
|  |         '\ufffe',    //       0xE9 -> REVERSED DIAGONAL STRIPES | ||||||
|  |         '\ufffe',    //       0xEA -> REVERSED CHECKBOX UNCHECKED | ||||||
|  |         '\ufffe',    //       0xEB -> REVERSED CHECKBOX CHECKED | ||||||
|  |         '\ufffe',    //       0xEC -> REVERSED RADIO BUTTON UNSELECTED | ||||||
|  |         '\ufffe',    //       0xED -> REVERSED RADIO BUTTON SELECTED | ||||||
|  |         '\ufffe',    //       0xEE -> MEMORY CHIP ICON | ||||||
|  |         '\u21e7',    //  ⇧    0xEF -> SHIFT SYMBOL | ||||||
|  |         '\ufffe',    //       0xF0 -> REVERSED COPYRIGHT SYMBOL | ||||||
|  |         '\ufffe',    //       0xF1 -> REVERSED CHECKMARK | ||||||
|  |         '\ufffe',    //       0xF2 -> REVERSED THREE HORIZONTAL STRIPES | ||||||
|  |         '\ufffe',    //       0xF3 -> REVERSED TICK TRACK | ||||||
|  |         '\ufffe',    //       0xF4 -> REVERSED TICK TRACK NUB | ||||||
|  |         '\ufffe',    //       0xF5 -> REVERSED TAB CORNER | ||||||
|  |         '\ufffe',    //       0xF6 -> REVERSED THREE VERTICAL STRIPES | ||||||
|  |         '\ufffe',    //       0xF7 -> CUSTOM 10 | ||||||
|  |         '\ufffe',    //       0xF8 -> CUSTOM 11 | ||||||
|  |         '\ufffe',    //       0xF9 -> CUSTOM 12 | ||||||
|  |         '\ufffe',    //       0xFA -> CUSTOM 13 | ||||||
|  |         '\ufffe',    //       0xFB -> CUSTOM 14 | ||||||
|  |         '\ufffe',    //       0xFC -> CUSTOM 15 | ||||||
|  |         '\ufffe',    //       0xFD -> CUSTOM 16 | ||||||
|  |         '\ufffe',    //       0xFE -> CUSTOM 17 | ||||||
|  |         '\ufffe'     //       0xFF -> CUSTOM 18 | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |     // encoding:  from unicode to C64 OS Screencodes (0-255) | ||||||
|  |     private val encodingC64os = decodingC64os.withIndex().associate{it.value to it.index} | ||||||
|  |  | ||||||
|  |     private fun replaceSpecial(chr: Char): Char = | ||||||
|  |         when(chr) { | ||||||
|  |             '\r' -> '\n'        // to make \r (carriage returrn) equivalent to \n (line feed): RETURN ($0d) | ||||||
|  |             else -> chr | ||||||
|  |         } | ||||||
|  |      | ||||||
|  |     fun encode(text: String, lowercase: Boolean = false): Result<List<UByte>, CharConversionException> { | ||||||
|  |         fun encodeChar(chr3: Char, lowercase: Boolean): UByte { | ||||||
|  |             val chr = replaceSpecial(chr3) | ||||||
|  |             val screencode = encodingC64os[chr] | ||||||
|  |             return screencode?.toUByte() ?: when (chr) { | ||||||
|  |                 '\u0000' -> 0u | ||||||
|  |                 '\n' -> 13u | ||||||
|  |                 in '\u8000'..'\u80ff' -> { | ||||||
|  |                     // special case: take the lower 8 bit hex value directly | ||||||
|  |                     (chr.code - 0x8000).toUByte() | ||||||
|  |                 } | ||||||
|  |                 else -> { | ||||||
|  |                     if(chr.isISOControl()) | ||||||
|  |                         throw CharConversionException("no c64os character for char #${chr.code}") | ||||||
|  |                     else | ||||||
|  |                         throw CharConversionException("no c64os character for char #${chr.code} '${chr}'") | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return try { | ||||||
|  |             Ok(text.map { | ||||||
|  |                 try { | ||||||
|  |                     encodeChar(it, lowercase) | ||||||
|  |                 } catch (x: CharConversionException) { | ||||||
|  |                     encodeChar(it, !lowercase) | ||||||
|  |                 } | ||||||
|  |             }) | ||||||
|  |         } catch(cx: CharConversionException) { | ||||||
|  |             Err(cx) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun decode(screencode: Iterable<UByte>, lowercase: Boolean = false): Result<String, CharConversionException> { | ||||||
|  |         return try { | ||||||
|  |             Ok(screencode.map { | ||||||
|  |                 val code = it.toInt() | ||||||
|  |                 if(code<0 || code>= decodingC64os.size) | ||||||
|  |                     throw CharConversionException("c64os $code out of range 0..${decodingC64os.size-1}") | ||||||
|  |                 decodingC64os[code] | ||||||
|  |             }.joinToString("")) | ||||||
|  |         } catch(ce: CharConversionException) { | ||||||
|  |             Err(ce) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										69
									
								
								codeCore/src/prog8/code/target/encodings/Cp437Encoding.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								codeCore/src/prog8/code/target/encodings/Cp437Encoding.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | |||||||
|  | package prog8.code.target.encodings | ||||||
|  |  | ||||||
|  | import com.github.michaelbull.result.Err | ||||||
|  | import com.github.michaelbull.result.Ok | ||||||
|  | import com.github.michaelbull.result.Result | ||||||
|  | import java.io.CharConversionException | ||||||
|  | import java.nio.charset.Charset | ||||||
|  |  | ||||||
|  | object Cp437Encoding { | ||||||
|  |     val charset: Charset = Charset.forName("IBM437") | ||||||
|  |  | ||||||
|  |     fun encode(str: String): Result<List<UByte>, CharConversionException> { | ||||||
|  |         return try { | ||||||
|  |             val mapped = str.map { chr -> | ||||||
|  |                 when (chr) { | ||||||
|  |                     '\u0000' -> 0u | ||||||
|  |                     '\u00a0' -> 255u | ||||||
|  |                     '☺' -> 1u | ||||||
|  |                     '☻' -> 2u | ||||||
|  |                     '♥' -> 3u | ||||||
|  |                     '♦' -> 4u | ||||||
|  |                     '♣' -> 5u | ||||||
|  |                     '♠' -> 6u | ||||||
|  |                     '•' -> 7u | ||||||
|  |                     '◘' -> 8u | ||||||
|  |                     '○' -> 9u | ||||||
|  |                     '◙' -> 10u | ||||||
|  |                     '♂' -> 11u | ||||||
|  |                     '♀' -> 12u | ||||||
|  |                     '♪' -> 13u | ||||||
|  |                     '♫' -> 14u | ||||||
|  |                     '☼' -> 15u | ||||||
|  |                     '►' -> 16u | ||||||
|  |                     '◄' -> 17u | ||||||
|  |                     '↕' -> 18u | ||||||
|  |                     '‼' -> 19u | ||||||
|  |                     '¶' -> 20u | ||||||
|  |                     '§' -> 21u | ||||||
|  |                     '▬' -> 22u | ||||||
|  |                     '↨' -> 23u | ||||||
|  |                     '↑' -> 24u | ||||||
|  |                     '↓' -> 25u | ||||||
|  |                     '→' -> 26u | ||||||
|  |                     '←' -> 27u | ||||||
|  |                     '∟' -> 28u | ||||||
|  |                     '↔' -> 29u | ||||||
|  |                     '▲' -> 30u | ||||||
|  |                     '▼' -> 31u | ||||||
|  |                     in '\u8000'..'\u80ff' -> { | ||||||
|  |                         // special case: take the lower 8 bit hex value directly | ||||||
|  |                         (chr.code - 0x8000).toUByte() | ||||||
|  |                     } | ||||||
|  |                     else -> charset.encode(chr.toString())[0].toUByte() | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             Ok(mapped) | ||||||
|  |         } catch (ce: CharConversionException) { | ||||||
|  |             Err(ce) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun decode(bytes: Iterable<UByte>): Result<String, CharConversionException> { | ||||||
|  |         return try { | ||||||
|  |             Ok(String(bytes.map { it.toByte() }.toByteArray(), charset)) | ||||||
|  |         } catch (ce: CharConversionException) { | ||||||
|  |             Err(ce) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										47
									
								
								codeCore/src/prog8/code/target/encodings/Encoder.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								codeCore/src/prog8/code/target/encodings/Encoder.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | |||||||
|  | package prog8.code.target.encodings | ||||||
|  |  | ||||||
|  | import com.github.michaelbull.result.fold | ||||||
|  | import prog8.code.core.Encoding | ||||||
|  | import prog8.code.core.IStringEncoding | ||||||
|  | import prog8.code.core.InternalCompilerException | ||||||
|  |  | ||||||
|  | class Encoder(val newlineToCarriageReturn: Boolean): IStringEncoding { | ||||||
|  |     override val defaultEncoding: Encoding = Encoding.ISO | ||||||
|  |  | ||||||
|  |     override fun encodeString(str: String, encoding: Encoding): List<UByte> { | ||||||
|  |         val coded = when(encoding) { | ||||||
|  |             Encoding.PETSCII -> PetsciiEncoding.encodePetscii(str, true) | ||||||
|  |             Encoding.SCREENCODES -> PetsciiEncoding.encodeScreencode(str, true) | ||||||
|  |             Encoding.ISO -> IsoEncoding.encode(str, newlineToCarriageReturn) | ||||||
|  |             Encoding.ISO5 -> IsoCyrillicEncoding.encode(str, newlineToCarriageReturn) | ||||||
|  |             Encoding.ISO16 -> IsoEasternEncoding.encode(str, newlineToCarriageReturn) | ||||||
|  |             Encoding.CP437 -> Cp437Encoding.encode(str) | ||||||
|  |             Encoding.KATAKANA -> KatakanaEncoding.encode(str, newlineToCarriageReturn) | ||||||
|  |             Encoding.ATASCII -> AtasciiEncoding.encode(str) | ||||||
|  |             Encoding.C64OS -> C64osEncoding.encode(str) | ||||||
|  |             else -> throw InternalCompilerException("unsupported encoding $encoding") | ||||||
|  |         } | ||||||
|  |         return coded.fold( | ||||||
|  |             failure = { throw it }, | ||||||
|  |             success = { it } | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  |     override fun decodeString(bytes: Iterable<UByte>, encoding: Encoding): String { | ||||||
|  |         val decoded = when(encoding) { | ||||||
|  |             Encoding.PETSCII -> PetsciiEncoding.decodePetscii(bytes, true) | ||||||
|  |             Encoding.SCREENCODES -> PetsciiEncoding.decodeScreencode(bytes, true) | ||||||
|  |             Encoding.ISO -> IsoEncoding.decode(bytes, newlineToCarriageReturn) | ||||||
|  |             Encoding.ISO5 -> IsoCyrillicEncoding.decode(bytes, newlineToCarriageReturn) | ||||||
|  |             Encoding.ISO16 -> IsoEasternEncoding.decode(bytes, newlineToCarriageReturn) | ||||||
|  |             Encoding.CP437 -> Cp437Encoding.decode(bytes) | ||||||
|  |             Encoding.KATAKANA -> KatakanaEncoding.decode(bytes, newlineToCarriageReturn) | ||||||
|  |             Encoding.ATASCII -> AtasciiEncoding.decode(bytes) | ||||||
|  |             Encoding.C64OS -> C64osEncoding.decode(bytes) | ||||||
|  |             else -> throw InternalCompilerException("unsupported encoding $encoding") | ||||||
|  |         } | ||||||
|  |         return decoded.fold( | ||||||
|  |             failure = { throw it }, | ||||||
|  |             success = { it } | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										49
									
								
								codeCore/src/prog8/code/target/encodings/IsoEncoding.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								codeCore/src/prog8/code/target/encodings/IsoEncoding.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | package prog8.code.target.encodings | ||||||
|  |  | ||||||
|  | import com.github.michaelbull.result.Err | ||||||
|  | import com.github.michaelbull.result.Ok | ||||||
|  | import com.github.michaelbull.result.Result | ||||||
|  | import java.io.CharConversionException | ||||||
|  | import java.nio.charset.Charset | ||||||
|  |  | ||||||
|  |  | ||||||
|  | open class IsoEncodingBase(charsetName: String) { | ||||||
|  |     val charset: Charset = Charset.forName(charsetName) | ||||||
|  |  | ||||||
|  |     fun encode(str: String, newlineToCarriageReturn: Boolean): Result<List<UByte>, CharConversionException> { | ||||||
|  |         return try { | ||||||
|  |             val mapped = str.map { chr -> | ||||||
|  |                 when (chr) { | ||||||
|  |                     '\u0000' -> 0u | ||||||
|  |                     '\n' -> if(newlineToCarriageReturn) 13u else 10u | ||||||
|  |                     in '\u8000'..'\u80ff' -> { | ||||||
|  |                         // special case: take the lower 8 bit hex value directly | ||||||
|  |                         (chr.code - 0x8000).toUByte() | ||||||
|  |                     } | ||||||
|  |                     else -> charset.encode(chr.toString())[0].toUByte() | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             Ok(mapped) | ||||||
|  |         } catch (ce: CharConversionException) { | ||||||
|  |             Err(ce) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun decode(bytes: Iterable<UByte>, newlineToCarriageReturn: Boolean): Result<String, CharConversionException> { | ||||||
|  |         return try { | ||||||
|  |             Ok(String(bytes.map { | ||||||
|  |                 when(it) { | ||||||
|  |                     13u.toUByte() -> if(newlineToCarriageReturn) 10 else 13 | ||||||
|  |                     else -> it.toByte() | ||||||
|  |                 } | ||||||
|  |             }.toByteArray(), charset)) | ||||||
|  |         } catch (ce: CharConversionException) { | ||||||
|  |             Err(ce) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | object IsoEncoding: IsoEncodingBase("ISO-8859-15") | ||||||
|  | object IsoCyrillicEncoding: IsoEncodingBase("ISO-8859-5") | ||||||
|  | object IsoEasternEncoding: IsoEncodingBase("ISO-8859-16") | ||||||
							
								
								
									
										128
									
								
								codeCore/src/prog8/code/target/encodings/KatakanaEncoding.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								codeCore/src/prog8/code/target/encodings/KatakanaEncoding.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | |||||||
|  | package prog8.code.target.encodings | ||||||
|  |  | ||||||
|  | import com.github.michaelbull.result.Err | ||||||
|  | import com.github.michaelbull.result.Ok | ||||||
|  | import com.github.michaelbull.result.Result | ||||||
|  | import java.io.CharConversionException | ||||||
|  | import java.nio.charset.Charset | ||||||
|  |  | ||||||
|  |  | ||||||
|  | object JapaneseCharacterConverter { | ||||||
|  |     // adapted from https://github.com/raminduw/Japanese-Character-Converter | ||||||
|  |  | ||||||
|  |     private val ZENKAKU_KATAKANA = charArrayOf( | ||||||
|  |         'ァ', 'ア', 'ィ', 'イ', 'ゥ', | ||||||
|  |         'ウ', 'ェ', 'エ', 'ォ', 'オ', 'カ', 'ガ', 'キ', 'ギ', 'ク', 'グ', 'ケ', 'ゲ', | ||||||
|  |         'コ', 'ゴ', 'サ', 'ザ', 'シ', 'ジ', 'ス', 'ズ', 'セ', 'ゼ', 'ソ', 'ゾ', 'タ', | ||||||
|  |         'ダ', 'チ', 'ヂ', 'ッ', 'ツ', 'ヅ', 'テ', 'デ', 'ト', 'ド', 'ナ', 'ニ', 'ヌ', | ||||||
|  |         'ネ', 'ノ', 'ハ', 'バ', 'パ', 'ヒ', 'ビ', 'ピ', 'フ', 'ブ', 'プ', 'ヘ', 'ベ', | ||||||
|  |         'ペ', 'ホ', 'ボ', 'ポ', 'マ', 'ミ', 'ム', 'メ', 'モ', 'ャ', 'ヤ', 'ュ', 'ユ', | ||||||
|  |         'ョ', 'ヨ', 'ラ', 'リ', 'ル', 'レ', 'ロ', 'ヮ', 'ワ', 'ヰ', 'ヱ', 'ヲ', 'ン', | ||||||
|  |         'ヴ', 'ヵ', 'ヶ' | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |     private val HANKAKU_HIRAGANA = charArrayOf( | ||||||
|  |         'ぁ', 'あ', 'ぃ', 'い', 'ぅ', 'う', 'ぇ', 'え', | ||||||
|  |         'ぉ', 'お', 'か', 'が', 'き', 'ぎ', 'く', 'ぐ', | ||||||
|  |         'け', 'げ', 'こ', 'ご', 'さ', 'ざ', 'し', 'じ', | ||||||
|  |         'す', 'ず', 'せ', 'ぜ', 'そ', 'ぞ', 'た', 'だ', | ||||||
|  |         'ち', 'ぢ', 'っ', 'つ', 'づ', 'て', 'で', 'と', | ||||||
|  |         'ど', 'な', 'に', 'ぬ', 'ね', 'の', 'は', 'ば', | ||||||
|  |         'ぱ', 'ひ', 'び', 'ぴ', 'ふ', 'ぶ', 'ぷ', 'へ', | ||||||
|  |         'べ', 'ぺ', 'ほ', 'ぼ', 'ぽ', 'ま', 'み', 'む', | ||||||
|  |         'め', 'も', 'ゃ', 'や', 'ゅ', 'ゆ', 'ょ', 'よ', | ||||||
|  |         'ら', 'り', 'る', 'れ', 'ろ', 'ゎ', 'わ', 'ゐ', | ||||||
|  |         'ゑ', 'を', 'ん', 'ゔ', 'ゕ', 'ゖ' | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |     private val HANKAKU_KATAKANA = arrayOf( | ||||||
|  |         "ァ", "ア", "ィ", "イ", "ゥ", | ||||||
|  |         "ウ", "ェ", "エ", "ォ", "オ", "カ", "ガ", "キ", "ギ", "ク", "グ", "ケ", | ||||||
|  |         "ゲ", "コ", "ゴ", "サ", "ザ", "シ", "ジ", "ス", "ズ", "セ", "ゼ", "ソ", | ||||||
|  |         "ゾ", "タ", "ダ", "チ", "ヂ", "ッ", "ツ", "ヅ", "テ", "デ", "ト", "ド", | ||||||
|  |         "ナ", "ニ", "ヌ", "ネ", "ノ", "ハ", "バ", "パ", "ヒ", "ビ", "ピ", "フ", | ||||||
|  |         "ブ", "プ", "ヘ", "ベ", "ペ", "ホ", "ボ", "ポ", "マ", "ミ", "ム", "メ", | ||||||
|  |         "モ", "ャ", "ヤ", "ュ", "ユ", "ョ", "ヨ", "ラ", "リ", "ル", "レ", "ロ", "ワ", | ||||||
|  |         "ワ", "イ", "エ", "ヲ", "ン", "ヴ", "カ", "ケ" | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |     private val ZENKAKU_KATAKANA_FIRST_CHAR_CODE = ZENKAKU_KATAKANA.first().code | ||||||
|  |     private val HANKAKU_HIRAGANA_FIRST_CHAR_CODE = HANKAKU_HIRAGANA.first().code | ||||||
|  |  | ||||||
|  |     private fun zenkakuKatakanaToHankakuKatakana(c: Char): String = if (c in ZENKAKU_KATAKANA) HANKAKU_KATAKANA[c.code - ZENKAKU_KATAKANA_FIRST_CHAR_CODE] else c.toString() | ||||||
|  |     private fun hankakuKatakanaToZenkakuKatakana(c: Char): Char = if (c in HANKAKU_HIRAGANA) ZENKAKU_KATAKANA[c.code - HANKAKU_HIRAGANA_FIRST_CHAR_CODE] else c | ||||||
|  |  | ||||||
|  |     fun zenkakuKatakanaToHankakuKatakana(s: String): String = buildString { | ||||||
|  |         for (element in s) { | ||||||
|  |             val converted = hankakuKatakanaToZenkakuKatakana(element) | ||||||
|  |             val convertedChar = zenkakuKatakanaToHankakuKatakana(converted) | ||||||
|  |             append(convertedChar) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | object KatakanaEncoding { | ||||||
|  |     val charset: Charset = Charset.forName("JIS_X0201") | ||||||
|  |  | ||||||
|  |     fun encode(str: String, newlineToCarriageReturn: Boolean): Result<List<UByte>, CharConversionException> { | ||||||
|  |         return try { | ||||||
|  |             val mapped = str.map { chr -> | ||||||
|  |                 when (chr) { | ||||||
|  |                     '\n' -> if(newlineToCarriageReturn) 13u else 10u | ||||||
|  |  | ||||||
|  |                     '\u0000' -> 0u | ||||||
|  |                     '\u00a0' -> 0xa0u // $a0 isn't technically a part of JIS X 0201 spec, and so we need to handle this ourselves | ||||||
|  |  | ||||||
|  |                     '♥' -> 0xe3u | ||||||
|  |                     '♦' -> 0xe4u | ||||||
|  |                     '♣' -> 0xe5u | ||||||
|  |                     '♠' -> 0xe6u | ||||||
|  |  | ||||||
|  |                     '大' -> 0xeau | ||||||
|  |                     '中' -> 0xebu | ||||||
|  |                     '小' -> 0xecu | ||||||
|  |                     '百' -> 0xedu | ||||||
|  |                     '千' -> 0xeeu | ||||||
|  |                     '万' -> 0xefu | ||||||
|  |                     '♪' -> 0xf0u | ||||||
|  |                     '土' -> 0xf1u | ||||||
|  |                     '金' -> 0xf2u | ||||||
|  |                     '木' -> 0xf3u | ||||||
|  |                     '水' -> 0xf4u | ||||||
|  |                     '火' -> 0xf5u | ||||||
|  |                     '月' -> 0xf6u | ||||||
|  |                     '日' -> 0xf7u | ||||||
|  |                     '時' -> 0xf8u | ||||||
|  |                     '分' -> 0xf9u | ||||||
|  |                     '秒' -> 0xfau | ||||||
|  |                     '年' -> 0xfbu | ||||||
|  |                     '円' -> 0xfcu | ||||||
|  |                     '人' -> 0xfdu | ||||||
|  |                     '生' -> 0xfeu | ||||||
|  |                     '〒' -> 0xffu | ||||||
|  |                     in '\u8000'..'\u80ff' -> { | ||||||
|  |                         // special case: take the lower 8 bit hex value directly | ||||||
|  |                         (chr.code - 0x8000).toUByte() | ||||||
|  |                     } | ||||||
|  |                     else -> charset.encode(chr.toString())[0].toUByte() | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             Ok(mapped) | ||||||
|  |         } catch (ce: CharConversionException) { | ||||||
|  |             Err(ce) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fun decode(bytes: Iterable<UByte>, newlineToCarriageReturn: Boolean): Result<String, CharConversionException> { | ||||||
|  |         return try { | ||||||
|  |             Ok(String(bytes.map { | ||||||
|  |                 when(it) { | ||||||
|  |                     13u.toUByte() -> if(newlineToCarriageReturn) 10 else 13 | ||||||
|  |                     else -> it.toByte() | ||||||
|  |                 } | ||||||
|  |             }.toByteArray(), charset)) | ||||||
|  |         } catch (ce: CharConversionException) { | ||||||
|  |             Err(ce) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										1195
									
								
								codeCore/src/prog8/code/target/encodings/PetsciiEncoding.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1195
									
								
								codeCore/src/prog8/code/target/encodings/PetsciiEncoding.kt
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										69
									
								
								codeCore/src/prog8/code/target/zp/C128Zeropage.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								codeCore/src/prog8/code/target/zp/C128Zeropage.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | |||||||
|  | package prog8.code.target.zp | ||||||
|  |  | ||||||
|  | import prog8.code.core.CompilationOptions | ||||||
|  | import prog8.code.core.InternalCompilerException | ||||||
|  | import prog8.code.core.Zeropage | ||||||
|  | import prog8.code.core.ZeropageType | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // reference: "Mapping the C128" zeropage chapter. | ||||||
|  |  | ||||||
|  | class C128Zeropage(options: CompilationOptions) : Zeropage(options) { | ||||||
|  |  | ||||||
|  |     override val SCRATCH_B1 = 0x74u      // temp storage for a single byte | ||||||
|  |     override val SCRATCH_REG = 0x75u     // temp storage for a register byte, must be B1+1 | ||||||
|  |     override val SCRATCH_W1 = 0xfbu      // temp storage 1 for a word  $fb+$fc | ||||||
|  |     override val SCRATCH_W2 = 0xfdu      // temp storage 2 for a word  $fd+$fe | ||||||
|  |     override val SCRATCH_PTR = 0x0bu     // temp storage for a pointer $0b+$0c | ||||||
|  |  | ||||||
|  |     init { | ||||||
|  |         if (options.floats && options.zeropage !in arrayOf( | ||||||
|  |                 ZeropageType.FLOATSAFE, | ||||||
|  |                 ZeropageType.BASICSAFE, | ||||||
|  |                 ZeropageType.DONTUSE | ||||||
|  |             )) | ||||||
|  |             throw InternalCompilerException("when floats are enabled, zero page type should be 'floatsafe' or 'basicsafe' or 'dontuse'") | ||||||
|  |  | ||||||
|  |         when (options.zeropage) { | ||||||
|  |             ZeropageType.FULL -> { | ||||||
|  |                 // $00/$01 are data port IO registers, // $02-$09 are storage locations for JSRFAR and such | ||||||
|  |                 free.addAll(0x0au..0xffu) | ||||||
|  |                 free.removeAll(arrayOf(0x90u, 0x91u, 0xa0u, 0xa1u, 0xa2u, 0xc0u, 0xccu, 0xcdu, 0xd0u, 0xd1u, 0xd2u, 0xd3u, 0xd4u, 0xd5u, 0xf7u))        // these are updated/used by IRQ | ||||||
|  |             } | ||||||
|  |             ZeropageType.KERNALSAFE -> { | ||||||
|  |                 free.addAll(0x0au..0x8fu)       // BASIC variables | ||||||
|  |                 free.addAll(arrayOf(0x92u, 0x96u, 0x9bu, 0x9cu, 0x9eu, 0x9fu, 0xa4u, 0xa7u, 0xa8u, 0xa9u, 0xaau, 0xabu, | ||||||
|  |                     0xb0u, 0xb1u, 0xb4u, 0xb5u, 0xb6u)) | ||||||
|  |             } | ||||||
|  |             ZeropageType.FLOATSAFE, | ||||||
|  |             ZeropageType.BASICSAFE -> { | ||||||
|  |                 free.addAll(arrayOf(0x0bu, 0x0cu, 0x0du, 0x0eu, 0x0fu, 0x10u, 0x11u, 0x12u, 0x16u, 0x17u, 0x18u, 0x19u, 0x1au)) | ||||||
|  |                 free.addAll(0x1bu..0x23u) | ||||||
|  |                 free.addAll(arrayOf(0x3fu, 0x40u, 0x41u, 0x42u, 0x43u, 0x44u, 0x47u, 0x48u, 0x49u, 0x4au, 0x4bu, 0x4cu, 0x4fu, | ||||||
|  |                     0x55u, 0x56u, 0x57u, 0x58u, | ||||||
|  |                     0x74u, 0x75u, 0x78u, 0x80u, 0x83u, 0x87u, 0x88u, 0x89u, 0x8au, 0x8bu, 0x8cu, 0x8du, 0x8eu, 0x8fu, | ||||||
|  |                     0x92u, 0x96u, 0x9bu, 0x9cu, 0x9eu, 0x9fu, 0xa4u, 0xa7u, 0xa8u, 0xa9u, 0xaau, 0xabu, | ||||||
|  |                     0xb0u, 0xb1u, 0xb4u, 0xb5u, 0xb6u | ||||||
|  |                 )) | ||||||
|  |  | ||||||
|  |                 // if(options.zeropage==ZeropageType.BASICSAFE) { | ||||||
|  |                     // can also clobber the FP locations (unconditionally, because the C128 target doesn't support floating point calculations in prog8 at this time0 | ||||||
|  |                     free.addAll(arrayOf(0x14u, 0x28u, 0x29u, 0x2au, 0x2bu, 0x2cu, | ||||||
|  |                         0x50u, 0x51u, 0x52u, 0x53u, 0x54u, 0x59u, 0x5au, 0x5bu, 0x5cu, 0x5du, 0x5eu, 0x5fu, 0x60u, 0x61u, 0x62u, | ||||||
|  |                         0x63u, 0x64u, 0x65u, 0x66u, 0x67u, 0x68u, | ||||||
|  |                         0x6au, 0x6bu, 0x6cu, 0x6du, 0x6eu, 0x6fu, 0x71u)) | ||||||
|  |                 // } | ||||||
|  |             } | ||||||
|  |             ZeropageType.DONTUSE -> { | ||||||
|  |                 free.clear()  // don't use zeropage at all | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         val distinctFree = free.distinct() | ||||||
|  |         free.clear() | ||||||
|  |         free.addAll(distinctFree) | ||||||
|  |  | ||||||
|  |         removeReservedFromFreePool() | ||||||
|  |         retainAllowed() | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										98
									
								
								codeCore/src/prog8/code/target/zp/C64Zeropage.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								codeCore/src/prog8/code/target/zp/C64Zeropage.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,98 @@ | |||||||
|  | package prog8.code.target.zp | ||||||
|  |  | ||||||
|  | import prog8.code.core.* | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class C64Zeropage(options: CompilationOptions) : Zeropage(options) { | ||||||
|  |  | ||||||
|  |     override val SCRATCH_B1 = 0x02u      // temp storage for a single byte | ||||||
|  |     override val SCRATCH_REG = 0x03u     // temp storage for a register byte, must be B1+1 | ||||||
|  |     override val SCRATCH_W1 = 0xfbu      // temp storage 1 for a word  $fb+$fc | ||||||
|  |     override val SCRATCH_W2 = 0xfdu      // temp storage 2 for a word  $fd+$fe | ||||||
|  |     override val SCRATCH_PTR = 0x9bu     // temp storage for a pointer $9b+$9c | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     init { | ||||||
|  |         if (options.floats && options.zeropage !in arrayOf( | ||||||
|  |                 ZeropageType.FLOATSAFE, | ||||||
|  |                 ZeropageType.BASICSAFE, | ||||||
|  |                 ZeropageType.DONTUSE | ||||||
|  |             )) | ||||||
|  |             throw InternalCompilerException("when floats are enabled, zero page type should be 'floatsafe' or 'basicsafe' or 'dontuse'") | ||||||
|  |  | ||||||
|  |         if (options.zeropage == ZeropageType.FULL) { | ||||||
|  |             free.addAll(0x02u..0xffu) | ||||||
|  |             free.removeAll(arrayOf(0xa0u, 0xa1u, 0xa2u, 0x91u, 0xc0u, 0xc5u, 0xcbu, 0xf5u, 0xf6u))        // these are updated by IRQ | ||||||
|  |         } else { | ||||||
|  |             if (options.zeropage == ZeropageType.KERNALSAFE || options.zeropage == ZeropageType.FLOATSAFE) { | ||||||
|  |                 free.addAll(arrayOf( | ||||||
|  |                         0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, | ||||||
|  |                         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, | ||||||
|  |                         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, | ||||||
|  |                         0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, | ||||||
|  |                         0x47, 0x48, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x51, 0x52, 0x53, | ||||||
|  |                         0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, | ||||||
|  |                         0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, | ||||||
|  |                         0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, | ||||||
|  |                         0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, | ||||||
|  |                         0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, | ||||||
|  |                         0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0xff | ||||||
|  |                         // 0x90-0xfa is 'kernal work storage area' | ||||||
|  |                 ).map{it.toUInt()}) | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (options.zeropage == ZeropageType.FLOATSAFE) { | ||||||
|  |                 // remove the zeropage locations used for floating point operations from the free list | ||||||
|  |                 free.removeAll(arrayOf( | ||||||
|  |                         0x03, 0x04, 0x05, 0x06, 0x10, 0x11, 0x12, | ||||||
|  |                         0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, | ||||||
|  |                         0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, | ||||||
|  |                         0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, | ||||||
|  |                         0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, | ||||||
|  |                         0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0xff | ||||||
|  |                 ).map{it.toUInt()}) | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if(options.zeropage != ZeropageType.DONTUSE) { | ||||||
|  |                 // add the free Zp addresses | ||||||
|  |                 // these are valid for the C-64 but allow BASIC to keep running fully *as long as you don't use tape I/O* | ||||||
|  |                 free.addAll(arrayOf(0x02, 0x03, 0x04, 0x05, 0x06, 0x0a, 0x0e, | ||||||
|  |                         0x92, 0x96, 0x9b, 0x9c, 0x9e, 0x9f, 0xa6, | ||||||
|  |                         0xb0, 0xb1, 0xbe, 0xbf, 0xf9).map{it.toUInt()}) | ||||||
|  |             } else { | ||||||
|  |                 // don't use the zeropage at all | ||||||
|  |                 free.clear() | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         val distinctFree = free.distinct() | ||||||
|  |         free.clear() | ||||||
|  |         free.addAll(distinctFree) | ||||||
|  |  | ||||||
|  |         removeReservedFromFreePool() | ||||||
|  |  | ||||||
|  |         if(options.zeropage==ZeropageType.FULL || options.zeropage==ZeropageType.KERNALSAFE) { | ||||||
|  |             // in these cases there is enough space on the zero page to stick the cx16 virtual registers in there as well. | ||||||
|  |             allocateCx16VirtualRegisters() | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         retainAllowed() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private fun allocateCx16VirtualRegisters() { | ||||||
|  |         // Note: the 16 virtual registers R0-R15 are not regular allocated variables, they're *memory mapped* elsewhere to fixed addresses. | ||||||
|  |         // However, to be able for the compiler to "see" them as zeropage variables, we have to register them here as well. | ||||||
|  |         // This is important because the compiler sometimes treats ZP variables more efficiently (for example if it's a pointer) | ||||||
|  |         // The base addres is $04.  Unfortunately it cannot be the same as on the Commander X16 ($02). | ||||||
|  |         for(reg in 0..15) { | ||||||
|  |             allocatedVariables["cx16.r${reg}"]   = VarAllocation((4+reg*2).toUInt(), DataType.UWORD, 2)       // cx16.r0 .. cx16.r15 | ||||||
|  |             allocatedVariables["cx16.r${reg}s"]  = VarAllocation((4+reg*2).toUInt(), DataType.WORD, 2)        // cx16.r0s .. cx16.r15s | ||||||
|  |             allocatedVariables["cx16.r${reg}L"]  = VarAllocation((4+reg*2).toUInt(), DataType.UBYTE, 1)       // cx16.r0L .. cx16.r15L | ||||||
|  |             allocatedVariables["cx16.r${reg}H"]  = VarAllocation((5+reg*2).toUInt(), DataType.UBYTE, 1)       // cx16.r0H .. cx16.r15H | ||||||
|  |             allocatedVariables["cx16.r${reg}sL"] = VarAllocation((4+reg*2).toUInt(), DataType.BYTE, 1)        // cx16.r0sL .. cx16.r15sL | ||||||
|  |             allocatedVariables["cx16.r${reg}sH"] = VarAllocation((5+reg*2).toUInt(), DataType.BYTE, 1)        // cx16.r0sH .. cx16.r15sH | ||||||
|  |             free.remove((4+reg*2).toUInt()) | ||||||
|  |             free.remove((5+reg*2).toUInt()) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										69
									
								
								codeCore/src/prog8/code/target/zp/CX16Zeropage.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								codeCore/src/prog8/code/target/zp/CX16Zeropage.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | |||||||
|  | package prog8.code.target.zp | ||||||
|  |  | ||||||
|  | import prog8.code.core.* | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class CX16Zeropage(options: CompilationOptions) : Zeropage(options) { | ||||||
|  |  | ||||||
|  |     override val SCRATCH_B1 = 0x7au      // temp storage for a single byte | ||||||
|  |     override val SCRATCH_REG = 0x7bu     // temp storage for a register byte, must be B1+1 | ||||||
|  |     override val SCRATCH_W1 = 0x7cu      // temp storage 1 for a word  $7c+$7d | ||||||
|  |     override val SCRATCH_W2 = 0x7eu      // temp storage 2 for a word  $7e+$7f | ||||||
|  |     override val SCRATCH_PTR = 0x22u     // temp storage for a pointer $22+$23 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     init { | ||||||
|  |         if (options.floats && options.zeropage !in arrayOf( | ||||||
|  |                 ZeropageType.FLOATSAFE, | ||||||
|  |                 ZeropageType.BASICSAFE, | ||||||
|  |                 ZeropageType.DONTUSE | ||||||
|  |             )) | ||||||
|  |             throw InternalCompilerException("when floats are enabled, zero page type should be 'floatsafe' or 'basicsafe' or 'dontuse'") | ||||||
|  |  | ||||||
|  |         // the addresses 0x02 to 0x21 (inclusive) are taken for sixteen virtual 16-bit api registers. | ||||||
|  |  | ||||||
|  |         synchronized(this) { | ||||||
|  |             when (options.zeropage) { | ||||||
|  |                 ZeropageType.FULL -> { | ||||||
|  |                     free.addAll(0x22u..0xffu) | ||||||
|  |                 } | ||||||
|  |                 ZeropageType.KERNALSAFE -> { | ||||||
|  |                     free.addAll(0x22u..0x7fu) | ||||||
|  |                     free.addAll(0xa9u..0xffu) | ||||||
|  |                 } | ||||||
|  |                 ZeropageType.FLOATSAFE -> { | ||||||
|  |                     free.addAll(0x22u..0x7fu) | ||||||
|  |                     free.addAll(0xd4u..0xffu) | ||||||
|  |                 } | ||||||
|  |                 ZeropageType.BASICSAFE -> { | ||||||
|  |                     free.addAll(0x22u..0x7fu) | ||||||
|  |                 } | ||||||
|  |                 ZeropageType.DONTUSE -> { | ||||||
|  |                     free.clear() // don't use zeropage at all | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             val distinctFree = free.distinct() | ||||||
|  |             free.clear() | ||||||
|  |             free.addAll(distinctFree) | ||||||
|  |  | ||||||
|  |             removeReservedFromFreePool() | ||||||
|  |             allocateCx16VirtualRegisters() | ||||||
|  |             retainAllowed() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private fun allocateCx16VirtualRegisters() { | ||||||
|  |         // Note: the 16 virtual registers R0-R15 are not regular allocated variables, they're *memory mapped* elsewhere to fixed addresses. | ||||||
|  |         // However, to be able for the compiler to "see" them as zeropage variables, we have to register them here as well. | ||||||
|  |         // This is important because the compiler sometimes treats ZP variables more efficiently (for example if it's a pointer) | ||||||
|  |         for(reg in 0..15) { | ||||||
|  |             allocatedVariables["cx16.r${reg}"]   = VarAllocation((2+reg*2).toUInt(), DataType.UWORD, 2)       // cx16.r0 .. cx16.r15 | ||||||
|  |             allocatedVariables["cx16.r${reg}s"]  = VarAllocation((2+reg*2).toUInt(), DataType.WORD, 2)        // cx16.r0s .. cx16.r15s | ||||||
|  |             allocatedVariables["cx16.r${reg}L"]  = VarAllocation((2+reg*2).toUInt(), DataType.UBYTE, 1)       // cx16.r0L .. cx16.r15L | ||||||
|  |             allocatedVariables["cx16.r${reg}H"]  = VarAllocation((3+reg*2).toUInt(), DataType.UBYTE, 1)       // cx16.r0H .. cx16.r15H | ||||||
|  |             allocatedVariables["cx16.r${reg}sL"] = VarAllocation((2+reg*2).toUInt(), DataType.BYTE, 1)        // cx16.r0sL .. cx16.r15sL | ||||||
|  |             allocatedVariables["cx16.r${reg}sH"] = VarAllocation((3+reg*2).toUInt(), DataType.BYTE, 1)        // cx16.r0sH .. cx16.r15sH | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										63
									
								
								codeCore/src/prog8/code/target/zp/ConfigurableZeropage.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								codeCore/src/prog8/code/target/zp/ConfigurableZeropage.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | |||||||
|  | package prog8.code.target.zp | ||||||
|  |  | ||||||
|  | import prog8.code.core.CompilationOptions | ||||||
|  | import prog8.code.core.DataType | ||||||
|  | import prog8.code.core.Zeropage | ||||||
|  | import prog8.code.core.ZeropageType | ||||||
|  |  | ||||||
|  | class ConfigurableZeropage( | ||||||
|  |     override val SCRATCH_B1: UInt,      // temp storage for a single byte | ||||||
|  |     override val SCRATCH_REG: UInt,     // temp storage for a register byte, must be B1+1 | ||||||
|  |     override val SCRATCH_W1: UInt,      // temp storage 1 for a word | ||||||
|  |     override val SCRATCH_W2: UInt,      // temp storage 2 for a word | ||||||
|  |     override val SCRATCH_PTR: UInt,     // temp storage for a pointer | ||||||
|  |  | ||||||
|  |     val virtualRegistersStart: UInt,        // location of 32 bytes for the r0-r15 virtual registers | ||||||
|  |     basicsafe: List<UIntRange>, | ||||||
|  |     kernalsafe: List<UIntRange>, | ||||||
|  |     fullsafe: List<UIntRange>, | ||||||
|  |     options: CompilationOptions | ||||||
|  | ) : Zeropage(options) { | ||||||
|  |  | ||||||
|  |     init { | ||||||
|  |         if (options.floats) { | ||||||
|  |             TODO("floats in configurable target zp") | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(SCRATCH_REG!=SCRATCH_B1+1u) | ||||||
|  |             throw IllegalArgumentException("Zero page scratch variable REG should be B1+1") | ||||||
|  |  | ||||||
|  |         when (options.zeropage) { | ||||||
|  |             ZeropageType.DONTUSE -> { /* don't use any zeropage at all */ } | ||||||
|  |             ZeropageType.FULL -> fullsafe.forEach { free.addAll(it) } | ||||||
|  |             ZeropageType.BASICSAFE -> basicsafe.forEach { free.addAll(it) } | ||||||
|  |             ZeropageType.KERNALSAFE -> kernalsafe.forEach { free.addAll(it) } | ||||||
|  |             ZeropageType.FLOATSAFE -> TODO("floatsafe in configurable target zp") | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         val distinctFree = free.distinct() | ||||||
|  |         free.clear() | ||||||
|  |         free.addAll(distinctFree) | ||||||
|  |  | ||||||
|  |         removeReservedFromFreePool() | ||||||
|  |         allocateCx16VirtualRegisters() | ||||||
|  |         retainAllowed() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private fun allocateCx16VirtualRegisters() { | ||||||
|  |         // Note: the 16 virtual registers R0-R15 are not regular allocated variables, they're *memory mapped* elsewhere to fixed addresses. | ||||||
|  |         // However, to be able for the compiler to "see" them as zeropage variables, we have to register them here as well. | ||||||
|  |         // This is important because the compiler sometimes treats ZP variables more efficiently (for example if it's a pointer) | ||||||
|  |         for(reg in 0..15) { | ||||||
|  |             val address = virtualRegistersStart + (2*reg).toUInt() | ||||||
|  |             if(address<=0xffu) { | ||||||
|  |                 allocatedVariables["cx16.r${reg}"]   = VarAllocation(address, DataType.UWORD, 2)       // cx16.r0 .. cx16.r15 | ||||||
|  |                 allocatedVariables["cx16.r${reg}s"]  = VarAllocation(address, DataType.WORD, 2)        // cx16.r0s .. cx16.r15s | ||||||
|  |                 allocatedVariables["cx16.r${reg}L"]  = VarAllocation(address, DataType.UBYTE, 1)       // cx16.r0L .. cx16.r15L | ||||||
|  |                 allocatedVariables["cx16.r${reg}H"]  = VarAllocation(address+1u, DataType.UBYTE, 1)    // cx16.r0H .. cx16.r15H | ||||||
|  |                 allocatedVariables["cx16.r${reg}sL"] = VarAllocation(address, DataType.BYTE, 1)        // cx16.r0sL .. cx16.r15sL | ||||||
|  |                 allocatedVariables["cx16.r${reg}sH"] = VarAllocation(address+1u, DataType.BYTE, 1)     // cx16.r0sH .. cx16.r15sH | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										52
									
								
								codeCore/src/prog8/code/target/zp/PETZeropage.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								codeCore/src/prog8/code/target/zp/PETZeropage.kt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | |||||||
|  | package prog8.code.target.zp | ||||||
|  |  | ||||||
|  | import prog8.code.core.CompilationOptions | ||||||
|  | import prog8.code.core.InternalCompilerException | ||||||
|  | import prog8.code.core.Zeropage | ||||||
|  | import prog8.code.core.ZeropageType | ||||||
|  |  | ||||||
|  |  | ||||||
|  | // reference: http://www.zimmers.net/cbmpics/cbm/PETx/petmem.txt | ||||||
|  |  | ||||||
|  | class PETZeropage(options: CompilationOptions) : Zeropage(options) { | ||||||
|  |  | ||||||
|  |     override val SCRATCH_B1 = 0xb3u      // temp storage for a single byte | ||||||
|  |     override val SCRATCH_REG = 0xb4u     // temp storage for a register byte, must be B1+1 | ||||||
|  |     override val SCRATCH_W1 = 0xb6u      // temp storage 1 for a word | ||||||
|  |     override val SCRATCH_W2 = 0xb8u      // temp storage 2 for a word | ||||||
|  |     override val SCRATCH_PTR = 0xb1u     // temp storage for a pointer $b1+$b2 | ||||||
|  |  | ||||||
|  |     init { | ||||||
|  |         if (options.floats && options.zeropage !in arrayOf( | ||||||
|  |                 ZeropageType.FLOATSAFE, | ||||||
|  |                 ZeropageType.BASICSAFE, | ||||||
|  |                 ZeropageType.DONTUSE | ||||||
|  |             )) | ||||||
|  |             throw InternalCompilerException("when floats are enabled, zero page type should be 'floatsafe' or 'basicsafe' or 'dontuse'") | ||||||
|  |  | ||||||
|  |         when (options.zeropage) { | ||||||
|  |             ZeropageType.FULL -> { | ||||||
|  |                 free.addAll(0x00u..0xffu) | ||||||
|  |                 free.removeAll(listOf(0x8du, 0x8eu, 0x8fu, 0x97u, 0x98u, 0x99u, 0x9au, 0x9bu, 0x9eu, 0xa7u, 0xa8u, 0xa9u, 0xaau))        // these are updated/used by IRQ | ||||||
|  |             } | ||||||
|  |             ZeropageType.KERNALSAFE -> { | ||||||
|  |                 free.addAll(0x00u..0xffu) | ||||||
|  |                 free.removeAll(listOf(0x8du, 0x8eu, 0x8fu, 0x97u, 0x98u, 0x99u, 0x9au, 0x9bu, 0x9eu, 0xa7u, 0xa8u, 0xa9u, 0xaau))        // these are updated/used by IRQ | ||||||
|  |             } | ||||||
|  |             ZeropageType.FLOATSAFE, | ||||||
|  |             ZeropageType.BASICSAFE -> { | ||||||
|  |                 free.addAll(0xb1u..0xbau)       // TODO more? | ||||||
|  |             } | ||||||
|  |             ZeropageType.DONTUSE -> { | ||||||
|  |                 free.clear()  // don't use zeropage at all | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         val distinctFree = free.distinct() | ||||||
|  |         free.clear() | ||||||
|  |         free.addAll(distinctFree) | ||||||
|  |  | ||||||
|  |         removeReservedFromFreePool() | ||||||
|  |         retainAllowed() | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										43
									
								
								codeGenCpu6502/build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								codeGenCpu6502/build.gradle.kts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | |||||||
|  | plugins { | ||||||
|  |     kotlin("jvm") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | dependencies { | ||||||
|  |     implementation(project(":codeCore")) | ||||||
|  |     implementation(project(":simpleAst")) | ||||||
|  |     // implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") | ||||||
|  |     // implementation "org.jetbrains.kotlin:kotlin-reflect" | ||||||
|  |     implementation("com.michael-bull.kotlin-result:kotlin-result-jvm:2.1.0") | ||||||
|  |  | ||||||
|  |     testImplementation("io.kotest:kotest-runner-junit5-jvm:5.9.1") | ||||||
|  |     testImplementation("io.kotest:kotest-framework-datatest:5.9.1") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | sourceSets { | ||||||
|  |     main { | ||||||
|  |         java { | ||||||
|  |             setSrcDirs(listOf("$projectDir/src")) | ||||||
|  |         } | ||||||
|  |         resources { | ||||||
|  |             setSrcDirs(listOf("$projectDir/res")) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     test { | ||||||
|  |         java { | ||||||
|  |             setSrcDirs(listOf("$projectDir/test")) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | tasks.test { | ||||||
|  |     // Enable JUnit 5 (Gradle 4.6+). | ||||||
|  |     useJUnitPlatform() | ||||||
|  |  | ||||||
|  |     // Always run tests, even when nothing changed. | ||||||
|  |     dependsOn("cleanTest") | ||||||
|  |  | ||||||
|  |     // Show test results. | ||||||
|  |     testLogging { | ||||||
|  |         events("skipped", "failed") | ||||||
|  |     } | ||||||
|  | } | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user