mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-26 03:17:38 +00:00 
			
		
		
		
	Compare commits
	
		
			602 Commits
		
	
	
		
			v1.80pr1.8
			...
			v1.96.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 1a52275dcb | ||
|   | 2fc2cf2e29 | ||
|   | 80c2fc68aa | ||
|   | 7c0664b9f2 | ||
|   | 4d1a950fbf | ||
|   | 135a3f56a5 | ||
|   | 1f117b7c47 | ||
|   | c820e051b3 | ||
|   | 01d7aaf062 | ||
|   | 1e75e4ff6e | ||
|   | f967a70121 | ||
|   | ac5150a664 | ||
|   | 0318e62524 | ||
|   | ca69d755e6 | ||
|   | 3ba7acc414 | ||
|   | 4c27eea73b | ||
|   | 225a64dd6b | ||
|   | 1831e81dd4 | ||
|   | a4dd6c24e5 | ||
|   | 936742895b | ||
|   | b5d1e618b9 | ||
|   | 10aa6c5297 | ||
|   | 010ebacd1a | ||
|   | 9e002beed7 | ||
|   | 6029defb20 | ||
|   | c16aa5f247 | ||
|   | 8d27bdca7b | ||
|   | 41aa8fa163 | ||
|   | e40fb67b50 | ||
|   | 96d46ffd2c | ||
|   | 652b7ebba6 | ||
|   | f0d7a1165d | ||
|   | 4a20eea852 | ||
|   | ccdd2bf477 | ||
|   | 8d8f41a50b | ||
|   | 72c78db28b | ||
|   | bf8a992273 | ||
|   | 9c214fcd8a | ||
|   | 082cc9d2d8 | ||
|   | bff2e81713 | ||
|   | 63aa3d8877 | ||
|   | 74c5d7e719 | ||
|   | 78a685c2cb | ||
|   | a475f55b9c | ||
|   | 9353ded2d5 | ||
|   | d197268e53 | ||
|   | 9648265056 | ||
|   | 264dbc570f | ||
|   | e4ad8bc117 | ||
|   | 1b31972092 | ||
|   | 6cd9fa9fb2 | ||
|   | d10f297ca0 | ||
|   | 9ae5636d41 | ||
|   | a60daf78cf | ||
|   | 76e0507c3b | ||
|   | d8e2fab2b1 | ||
|   | 5c5e510075 | ||
|   | 5a309258af | ||
|   | b0782ec38b | ||
|   | 46846a4fde | ||
|   | d955443b21 | ||
|   | 57e6c49844 | ||
|   | 66dbab7a6b | ||
|   | 558976e4ca | ||
|   | 3a7470a108 | ||
|   | cf2b332c3c | ||
|   | 8984ebcf80 | ||
|   | a28e7e2db3 | ||
|   | 3860e2466c | ||
|   | 5b31c2536a | ||
|   | 98dc7a6e58 | ||
|   | 5e0ceda7ce | ||
|   | 7fe3ac9222 | ||
|   | a65b8ed04c | ||
|   | 3e14b84c23 | ||
|   | 1710ad9861 | ||
|   | 9c48c99be7 | ||
|   | d10d1b45fe | ||
|   | 70a1cf5c5a | ||
|   | b546a10bd6 | ||
|   | 2f35bbb538 | ||
|   | 891dde43a9 | ||
|   | 094e0d4f33 | ||
|   | df40adce20 | ||
|   | e12ce95b2d | ||
|   | bcc0effd00 | ||
|   | 64f3aa2dba | ||
|   | 515ccfebd3 | ||
|   | 0b6dbe7778 | ||
|   | 19054684c6 | ||
|   | a72a5e6deb | ||
|   | eb2d9482a2 | ||
|   | 95794fdaf3 | ||
|   | af477a401a | ||
|   | 27531c161d | ||
|   | a8f208c394 | ||
|   | 148d9e9dda | ||
|   | 67fc21271b | ||
|   | ce28e2659a | ||
|   | 47e4826f2b | ||
|   | 9bde2d8d13 | ||
|   | 46acb6866e | ||
|   | c0506108f9 | ||
|   | 0dd7c3695f | ||
|   | 2a290be248 | ||
|   | c4a6c16330 | ||
|   | f8b3b544d1 | ||
|   | 53ae689468 | ||
|   | 73e460e533 | ||
|   | a4e68d637a | ||
|   | 1f1b20c81e | ||
|   | 20a9ff7a3f | ||
|   | 58cd5e3df7 | ||
|   | 5922d7548c | ||
|   | 386e01364e | ||
|   | 70eff6aa63 | ||
|   | 45ac601946 | ||
|   | d6c5a5bd27 | ||
|   | 02c7903cb7 | ||
|   | 37e856efdc | ||
|   | 8a38097887 | ||
|   | 884b417ec2 | ||
|   | 1d1d6227eb | ||
|   | d5eb82db60 | ||
|   | 3575654d02 | ||
|   | 79fcc7241b | ||
|   | b203d3aa0a | ||
|   | f1176af9d1 | ||
|   | 717686d855 | ||
|   | 92811ca0bc | ||
|   | f8a58dbcb1 | ||
|   | 98aabe2cfb | ||
|   | f938ed9779 | ||
|   | 03c9274b27 | ||
|   | 92c94ac039 | ||
|   | 5c6fd80b0c | ||
|   | f1ec59df15 | ||
|   | 624b23c7ac | ||
|   | 9b77a4aaee | ||
|   | d8b0037cfa | ||
|   | 91a9e7fdf7 | ||
|   | 2c3573719b | ||
|   | 46bc42d5a7 | ||
|   | 1b9e93a80f | ||
|   | 7b93f91ffa | ||
|   | 31a1027401 | ||
|   | e0fc994819 | ||
|   | 43408bf085 | ||
|   | d28f42e8b7 | ||
|   | ac452582c1 | ||
|   | 7e65c6b25c | ||
|   | 457a863842 | ||
|   | eef36e1358 | ||
|   | feda08b915 | ||
|   | 0240ce50ce | ||
|   | 592b83e784 | ||
|   | 5d91491ec7 | ||
|   | 7326d1110d | ||
|   | 0aa6ac05a0 | ||
|   | 27a2c063b9 | ||
|   | 89a195ec06 | ||
|   | 0e5fd4e8e0 | ||
|   | aa4ec53bb6 | ||
|   | 6b49327462 | ||
|   | 74ad934889 | ||
|   | 08b3dbbad5 | ||
|   | 54eac0a2f8 | ||
|   | 51ca5e620c | ||
|   | 076d572831 | ||
|   | 75f2b91fef | ||
|   | 79534e5630 | ||
|   | d483a91459 | ||
|   | 71d764f122 | ||
|   | 2e527eb11e | ||
|   | 19273b3696 | ||
|   | 4643641d51 | ||
|   | 63cd9c5bc7 | ||
|   | e9c11ff325 | ||
|   | 452464aa01 | ||
|   | 8885462175 | ||
|   | b8bd64913b | ||
|   | 00b458c39a | ||
|   | 88722d484f | ||
|   | 6d103e2114 | ||
|   | 42f23d56ae | ||
|   | 89d5211bd7 | ||
|   | 83e70377f7 | ||
|   | f6a26f75c3 | ||
|   | 664df62d5d | ||
|   | 1348ee0588 | ||
|   | 145dce7653 | ||
|   | 7f2651c23e | ||
|   | 05464107a8 | ||
|   | 86705787f0 | ||
|   | b34d8387d9 | ||
|   | 4d00969ef0 | ||
|   | 01d3d12992 | ||
|   | 5e31dcde83 | ||
|   | 5184883af1 | ||
|   | 0c45112262 | ||
|   | 0bf1672f45 | ||
|   | e1b8ac1f84 | ||
|   | deea552d99 | ||
|   | 54229c2ce1 | ||
|   | 1346a26179 | ||
|   | 14df44f09d | ||
|   | 1a21529499 | ||
|   | 2546990f41 | ||
|   | b39ca02464 | ||
|   | 628618105c | ||
|   | 075ba03f5d | ||
|   | 10bf84b631 | ||
|   | c346e22a45 | ||
|   | 418e1335b1 | ||
|   | d52372df31 | ||
|   | cc72e1c2bd | ||
|   | d28afcc6a9 | ||
|   | 220ed21e6e | ||
|   | 09d465774d | ||
|   | dfc8f48f12 | ||
|   | abe2ec4686 | ||
|   | 5333cda44e | ||
|   | dc88fbeb12 | ||
|   | c5eb7a9501 | ||
|   | bc969db2be | ||
|   | 50b7646178 | ||
|   | 3fa6b5bc9d | ||
|   | 33e65e39e3 | ||
|   | 0380e60590 | ||
|   | 2918892ee2 | ||
|   | e43dd9f7c6 | ||
|   | 244fd95034 | ||
|   | 14e98e2fcb | ||
|   | dcf5d59109 | ||
|   | b95083c77e | ||
|   | c54c8c3ea6 | ||
|   | f79c67e243 | ||
|   | 6ec7ebe439 | ||
|   | 76fe33760d | ||
|   | cb549d8f43 | ||
|   | 7b400fdcdd | ||
|   | ab70d918b5 | ||
|   | c64644b9ec | ||
|   | afb12eb342 | ||
|   | 64f5ca02b3 | ||
|   | 84bca21b0c | ||
|   | b6757c416f | ||
|   | dc9d3f2d15 | ||
|   | 807825d74e | ||
|   | 14c17676c6 | ||
|   | 324519575c | ||
|   | fbcf26bdc9 | ||
|   | 30ab6bd045 | ||
|   | 2ea816b78b | ||
|   | 56dcc57755 | ||
|   | a4830aff86 | ||
|   | 621bc526be | ||
|   | 605e1f6b9b | ||
|   | cb66ef7e30 | ||
|   | fd2f6a38c1 | ||
|   | 229821d398 | ||
|   | 1f2e0c444d | ||
|   | 429baa350c | ||
|   | 7fe62485fa | ||
|   | fe10c68099 | ||
|   | 06092cfddd | ||
|   | 9967dc5740 | ||
|   | b920e04c59 | ||
|   | baa1b5a5c9 | ||
|   | e84663a5c5 | ||
|   | 1c46220c42 | ||
|   | 889b445855 | ||
|   | 19553a981e | ||
|   | 15f4dbd061 | ||
|   | 98e12c7c3e | ||
|   | dfad319864 | ||
|   | 111b58f533 | ||
|   | 9345652808 | ||
|   | d40163b409 | ||
|   | 96400966d7 | ||
|   | db83bd4f64 | ||
|   | 579a38d366 | ||
|   | 0e6797c7da | ||
|   | c935577768 | ||
|   | c2b4077aa1 | ||
|   | ac020859f3 | ||
|   | 238be8955b | ||
|   | f997b02b8f | ||
|   | 799bb77847 | ||
|   | 2f66792a0d | ||
|   | 6cae8e211e | ||
|   | 48b1b2f01d | ||
|   | 8c45fd362a | ||
|   | 07b13dd2b4 | ||
|   | 45e84e1ede | ||
|   | b6715bd812 | ||
|   | 725dfa764f | ||
|   | c221502ec9 | ||
|   | 234f18c228 | ||
|   | 006ad109cb | ||
|   | 18aee02221 | ||
|   | 401bbf2e6a | ||
|   | 7467b7f88a | ||
|   | c82d8a7c2a | ||
|   | 6b81bcf334 | ||
|   | 3d67421d98 | ||
|   | acac70675d | ||
|   | 56434259c1 | ||
|   | da7e4b9016 | ||
|   | d4b8650d21 | ||
|   | 17645a79f0 | ||
|   | ce1f14a010 | ||
|   | 43050426de | ||
|   | b05f60c98b | ||
|   | c44c560f96 | ||
|   | e839ef54af | ||
|   | 0cb659d78c | ||
|   | 9048deeb95 | ||
|   | 5592ebae7d | ||
|   | b076c32fd1 | ||
|   | a48f1e310f | ||
|   | 19aca001d7 | ||
|   | 0db080154c | ||
|   | 114f913bf8 | ||
|   | 1c9810890a | ||
|   | b11beb508b | ||
|   | af8d4da594 | ||
|   | a81db2cda6 | ||
|   | 99bdff0f92 | ||
|   | bb138326df | ||
|   | 5b0ce7410d | ||
|   | d5ea22d1a0 | ||
|   | 210f3fa9e2 | ||
|   | d661cfa88b | ||
|   | 68bf3a71dc | ||
|   | 200311033f | ||
|   | 3192dc81ac | ||
|   | 3cdb12d293 | ||
|   | ad33acd7d1 | ||
|   | 0ec3884e98 | ||
|   | 7f2471d6b2 | ||
|   | b11d4bb209 | ||
|   | 2a716244e9 | ||
|   | 19b7ed538a | ||
|   | b0d9dc0b88 | ||
|   | e0660b1dab | ||
|   | 2182cfbeb7 | ||
|   | 8fafec4915 | ||
|   | b9fd690ecb | ||
|   | e6094a59fa | ||
|   | e8d7e6a562 | ||
|   | 536c2d9b2d | ||
|   | 2f2ada4416 | ||
|   | 9c951c58d9 | ||
|   | 4b4b47e231 | ||
|   | 2c027adb68 | ||
|   | f15a278f3b | ||
|   | 26b73c2ff3 | ||
|   | 4a25e7a178 | ||
|   | 55d54fec63 | ||
|   | 220e4bd660 | ||
|   | 978c28a686 | ||
|   | b867ada5e5 | ||
|   | 7071cc972b | ||
|   | 6898f932a0 | ||
|   | 2e0ef6385d | ||
|   | f93da7ea51 | ||
|   | 1210bb8a4d | ||
|   | 48a71e96eb | ||
|   | 3bf47b5290 | ||
|   | 9e9f199e55 | ||
|   | 5a8a111857 | ||
|   | 48ba247ab4 | ||
|   | c1e08fc3c7 | ||
|   | b9ec6f236d | ||
|   | b1fff97bff | ||
|   | c81bc70475 | ||
|   | 362dbd97ac | ||
|   | aa0e1883d1 | ||
|   | 9cdbcb4332 | ||
|   | 23ddd4feb5 | ||
|   | fcaa777c95 | ||
|   | b195cab6a7 | ||
|   | 63dc0daa09 | ||
|   | 34602ec4be | ||
|   | f3ce44042f | ||
|   | 4205f18f0c | ||
|   | 6be330ae8d | ||
|   | 4569af2130 | ||
|   | 765c31315a | ||
|   | 55a7ee4acf | ||
|   | 0e191e42a0 | ||
|   | ca34b2a1b8 | ||
|   | 7afc3e5260 | ||
|   | f9e13ca67a | ||
|   | 810258e9b8 | ||
|   | 5e462adc5c | ||
|   | 1fd0b40776 | ||
|   | 2965fb666f | ||
|   | 390575ab4d | ||
|   | e4ef92ca2d | ||
|   | 9bf586b018 | ||
|   | 173ea72001 | ||
|   | 1230cabcb0 | ||
|   | 6ed03e1fcd | ||
|   | c4b371b124 | ||
|   | a600213b00 | ||
|   | 7799b8d4cb | ||
|   | 245bf26480 | ||
|   | 5d05205d69 | ||
|   | 853e2622a1 | ||
|   | d0bf9e9cd7 | ||
|   | 7a7951ae68 | ||
|   | bd28955c8e | ||
|   | e46f09a939 | ||
|   | 71b1f8138d | ||
|   | 1d82a1c98c | ||
|   | b5f60f3f11 | ||
|   | 259665d9f1 | ||
|   | ba823bae13 | ||
|   | 1290a4402c | ||
|   | 379076a5e2 | ||
|   | d12bdf50d8 | ||
|   | cbfd5aeeee | ||
|   | 41429bdc0b | ||
|   | 54b9966feb | ||
|   | 105c66127c | ||
|   | 765ad0bd3f | ||
|   | dd05478483 | ||
|   | 5d028dea39 | ||
|   | 629c51d260 | ||
|   | 9ea57961af | ||
|   | 07b9b1c9c7 | ||
|   | 5b942ff9c1 | ||
|   | 7b5a918941 | ||
|   | 47721bf76b | ||
|   | 35ce0974cd | ||
|   | 52e1906d42 | ||
|   | eaf24a3ceb | ||
|   | 62760e371e | ||
|   | e154e11186 | ||
|   | 72d079ef61 | ||
|   | 0bfb7049b0 | ||
|   | f7cb526793 | ||
|   | e34e833d3d | ||
|   | a125a19728 | ||
|   | b3e6a53868 | ||
|   | 218f8e53bb | ||
|   | d02575528b | ||
|   | c78adb2cdc | ||
|   | 3e28f79ce9 | ||
|   | 67af7a698b | ||
|   | 06e76f9b15 | ||
|   | 6d383d005c | ||
|   | c373583723 | ||
|   | f1d10809d5 | ||
|   | 474f571798 | ||
|   | fb9c125ab8 | ||
|   | 162fb37421 | ||
|   | d953f031f0 | ||
|   | 7fde89ad95 | ||
|   | bd04a93ffb | ||
|   | e2bfaafe28 | ||
|   | 1fb3d16b89 | ||
|   | 35645b3d93 | ||
|   | a4cd1fe77d | ||
|   | 4145914024 | ||
|   | 6bd11a5e4a | ||
|   | 46fa798797 | ||
|   | 70a226207e | ||
|   | 257a35f3ed | ||
|   | af01b9514b | ||
|   | 070fd1f2ff | ||
|   | fb59da2b06 | ||
|   | 11e4d0de82 | ||
|   | e46ab1e267 | ||
|   | d6e0f368df | ||
|   | 9f2884bc0f | ||
|   | 18d468e887 | ||
|   | 63f6735bb8 | ||
|   | ab6f0ccd16 | ||
|   | ae0f093e73 | ||
|   | e5f988e3fe | ||
|   | 12e82afad2 | ||
|   | 6c2db93cbd | ||
|   | d5edbe700b | ||
|   | 86ad43c3ab | ||
|   | f450c0156b | ||
|   | 8abcfcb4ac | ||
|   | f3cace1d03 | ||
|   | e1e5e898ab | ||
|   | 3aa3852ff6 | ||
|   | 709a6329c7 | ||
|   | c9f05a2939 | ||
|   | e41377f862 | ||
|   | d173787a94 | ||
|   | d5aea26f3a | ||
|   | 2681e578c4 | ||
|   | 1f498dcc73 | ||
|   | 83b01d35eb | ||
|   | 8a7e651c99 | ||
|   | 80a5759bae | ||
|   | e8a4fbb4e3 | ||
|   | 0ce67afcc1 | ||
|   | a8dad23fa3 | ||
|   | 443e0f8f76 | ||
|   | a838595e1e | ||
|   | 61daab910e | ||
|   | 7fd19c43e9 | ||
|   | ce0685c31f | ||
|   | e33f852baa | ||
|   | 227d5e9e69 | ||
|   | 1c648850ab | ||
|   | 63691707fc | ||
|   | 5d97b9c8f3 | ||
|   | 77666d7399 | ||
|   | ed69495b03 | ||
|   | 66b61d4e9e | ||
|   | 8dd084ac5c | ||
|   | 932f8a44fc | ||
|   | 101b3500cc | ||
|   | a777801e15 | ||
|   | 0d6787641a | ||
|   | 744bba300e | ||
|   | 34d43d8273 | ||
|   | 7bc9745c7a | ||
|   | b414cba681 | ||
|   | 1c9110b927 | ||
|   | 325459e336 | ||
|   | ee3347afbd | ||
|   | 27aaec9a82 | ||
|   | 929f23fd2d | ||
|   | 8422a40c69 | ||
|   | ca334e7e5c | ||
|   | 54acf1d087 | ||
|   | 42d3901ee3 | ||
|   | f8b328a048 | ||
|   | 41a320e9a4 | ||
|   | 57fb77d7fe | ||
|   | b59dcbfc0e | ||
|   | 618c534d81 | ||
|   | 26ba61097b | ||
|   | 2c87e66db8 | ||
|   | f61f7df2d8 | ||
|   | 364d31465e | ||
|   | 4c7ac50dd8 | ||
|   | 37e25136ed | ||
|   | d9f03f3ec7 | ||
|   | 4d5c52bc63 | ||
|   | a1c4a9fb58 | ||
|   | 031f17c98e | ||
|   | 4ead319092 | ||
|   | dd6bab5413 | ||
|   | 5b48a0fa5f | ||
|   | 2032e7a83a | ||
|   | 72b9d3d802 | ||
|   | 70cb8ae16c | ||
|   | 05a97a4f12 | ||
|   | 8b86a954ee | ||
|   | 741ee447ca | ||
|   | 3537f49ced | ||
|   | c3e4a4de5e | ||
|   | 86569533e9 | ||
|   | e6850ab644 | ||
|   | 97c2421a22 | ||
|   | f765b6a487 | ||
|   | 3e6f6467af | ||
|   | 7e6eb62504 | ||
|   | 949b71d40c | ||
|   | afdfcb21b7 | ||
|   | 776a786e1b | ||
|   | 8ae65d1bdd | ||
|   | 0829506176 | ||
|   | 71ee692da0 | ||
|   | acd0092ed5 | ||
|   | 1160ffbf9e | ||
|   | 93cb6547bd | ||
|   | f9c91f288f | ||
|   | 62cf921cc6 | ||
|   | 4bd7381827 | ||
|   | 43459ec825 | ||
|   | 5fa01f8b96 | ||
|   | 67d5693d2a | ||
|   | c2a782afa4 | ||
|   | 14c9558ee6 | ||
|   | d53a73e7e7 | ||
|   | 7e334bd4a5 | ||
|   | 51e787f631 | ||
|   | 8080699030 | ||
|   | e555f9f7f0 | ||
|   | 822db6e9b5 | ||
|   | ac1f30ef43 | ||
|   | 0fc1b8c46b | ||
|   | e7c19bcf55 | ||
|   | 63ca8aca4c | ||
|   | 2caa9c57fc | ||
|   | 33fad2da15 | ||
|   | 518eefbe10 | ||
|   | 1ba73454c1 | ||
|   | ee4735c17c | ||
|   | b008edae90 | ||
|   | c6bd88f3ad | 
| @@ -5,9 +5,7 @@ indent_style = space | ||||
| indent_size = 4 | ||||
| end_of_line = lf | ||||
| charset = utf-8 | ||||
| # Sadly too many files have whitespace errors, so we leave this as is for | ||||
| # now and just make sure we don't introduce any more. | ||||
| # trim_trailing_whitespace = true | ||||
| trim_trailing_whitespace = true | ||||
| insert_final_newline = true | ||||
|  | ||||
| [*.md] | ||||
|   | ||||
							
								
								
									
										9
									
								
								.github/ISSUE_TEMPLATE/bug_report.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.github/ISSUE_TEMPLATE/bug_report.md
									
									
									
									
										vendored
									
									
								
							| @@ -1,16 +1,15 @@ | ||||
| --- | ||||
| name: Bug report | ||||
| about: Report some misbehaviour in the mod | ||||
|  | ||||
| labels: bug | ||||
| --- | ||||
|  | ||||
| <!-- | ||||
| ## Before reporting | ||||
|  - Search for the bug both here and [on the ComputerCraft issues page](https://github.com/dan200/ComputerCraft/issues?utf8=%E2%9C%93&q=is%3Aissue+) | ||||
|  - If possible, try to reproduce on vanilla ComputerCraft. If it still occurs, [report on the ComputerCraft repo](https://github.com/dan200/ComputerCraft/issues/new) instead. | ||||
|  - Search for the bug on the issue tracker. Make sure to look at closed issues too! | ||||
| --> | ||||
|  | ||||
| ## Useful information to include: | ||||
|  - Minecraft version | ||||
|  - CC: Tweaked version | ||||
|  - Detailed reproduction steps!** Sometimes I can spot a bug pretty easily, but often it's much more obscure. Anything you can give which will help reproduce it means it'll get fixed quicker. | ||||
|  - CC: Restitched version | ||||
|  - Detailed reproduction steps: sometimes I can spot a bug pretty easily, but often it's much more obscure. The more information I have to help reproduce it, the quicker it'll get fixed. | ||||
|   | ||||
							
								
								
									
										9
									
								
								.github/ISSUE_TEMPLATE/feature_request.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.github/ISSUE_TEMPLATE/feature_request.md
									
									
									
									
										vendored
									
									
								
							| @@ -1,15 +1,14 @@ | ||||
| --- | ||||
| name: Feature request | ||||
| about: Suggest an idea or improvement | ||||
|  | ||||
| labels: enhancement | ||||
| --- | ||||
|  | ||||
| <!-- | ||||
| ## Before reporting | ||||
|  - Search for the suggestion both here and [on the ComputerCraft issues page](https://github.com/dan200/ComputerCraft/issues?utf8=%E2%9C%93&q=is%3Aissue+). It's possible someone's suggested it before! | ||||
|  - Unless something is specific to CC:Tweaked, try to [suggest them on the ComputerCraft repo](https://github.com/dan200/ComputerCraft/issues/new). There's a lot more people watching it, so it allows the wider community to contribute. | ||||
|  - Search for the suggestion here. It's possible someone's suggested it before! | ||||
| --> | ||||
|  | ||||
| ## Useful information to include: | ||||
|  - Explanation of how the feature/change chould work. | ||||
|  - Some rationale/use case for a feature. I'd like to keep CC:T as minimal | ||||
|  - Explanation of how the feature/change should work. | ||||
|  - Some rationale/use case for a feature. My general approach to designing new features is to ask yourself "what issue are we trying to solve" and _then_ "is this the best way to solve this issue?". | ||||
|   | ||||
							
								
								
									
										12
									
								
								.github/ISSUE_TEMPLATE/peripheral_shoutout.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								.github/ISSUE_TEMPLATE/peripheral_shoutout.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| --- | ||||
| name: Peripheral Shoutout | ||||
| about: Made a Peripheral mod for CC:R? Let us know so we can give it a shoutout | ||||
| labels: peripheralShoutout | ||||
| --- | ||||
|  | ||||
| ## What to include? | ||||
|  - Link to the mod's Icon | ||||
|  - Link to the mod | ||||
|  - Mod Name | ||||
|  - Basic description of the mod | ||||
|  - Link to CC:R Peripheral Documentation for the mod | ||||
							
								
								
									
										12
									
								
								.github/pull_request_template.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.github/pull_request_template.md
									
									
									
									
										vendored
									
									
								
							| @@ -1,9 +1,3 @@ | ||||
| <!-- | ||||
| Unless this feature is specific to CC:Tweaked, try to [target the original ComputerCraft repo](https://github.com/dan200/ComputerCraft/) instead. There's a lot more people watching it, so it allows the wider community to contribute. | ||||
| --> | ||||
|  | ||||
| ## Useful information to include: | ||||
|  - Brief explanation of the changes you've made. | ||||
|  - Rationale of why this change has been made/reasoning behind it. | ||||
|  | ||||
| The more information you can provide, the easier it is to review something now _and_ to see why a change was made, when the code needs updating in the future. | ||||
| ## A quick checklist | ||||
|  - If there's a existing issue, please link to it. If not, provide fill out the same information you would in a normal issue - reproduction steps for bugs, rationale for use-case. | ||||
|  - If you're working on CraftOS, try to write a few test cases so we can ensure everything continues to work in the future. Tests live in `src/test/resources/test-rom/spec` and can be run with `./gradlew check`. | ||||
|   | ||||
							
								
								
									
										35
									
								
								.github/workflows/main-ci.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								.github/workflows/main-ci.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| name: Build | ||||
|  | ||||
| on: [push, pull_request] | ||||
|  | ||||
| jobs: | ||||
|     build: | ||||
|         name: Build | ||||
|         runs-on: ubuntu-latest | ||||
|  | ||||
|         steps: | ||||
|             - uses: actions/checkout@v2 | ||||
|             - name: Checkout submodules | ||||
|               run: git submodule update --init --recursive | ||||
|  | ||||
|             - name: Set up Java 8 | ||||
|               uses: actions/setup-java@v1 | ||||
|               with: | ||||
|                   java-version: 8 | ||||
|  | ||||
|             - name: Cache gradle dependencies | ||||
|               uses: actions/cache@v2 | ||||
|               with: | ||||
|                   path: ~/.gradle/caches | ||||
|                   key: ${{ runner.os }}-gradle-${{ hashFiles('gradle.properties') }} | ||||
|                   restore-keys: | | ||||
|                       ${{ runner.os }}-gradle- | ||||
|  | ||||
|             - name: Build with Gradle | ||||
|               run: ./gradlew build --no-daemon || ./gradlew build --no-daemon | ||||
|  | ||||
|             - name: Upload Jar | ||||
|               uses: actions/upload-artifact@v1 | ||||
|               with: | ||||
|                   name: cc-restiched | ||||
|                   path: build/libs | ||||
							
								
								
									
										23
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,12 +1,23 @@ | ||||
| build | ||||
| out | ||||
| run | ||||
| deploy | ||||
| # Build directories | ||||
| /classes | ||||
| /logs | ||||
| /build | ||||
| /out | ||||
|  | ||||
| # Runtime directories | ||||
| /run | ||||
| /run-* | ||||
| /test-files | ||||
|  | ||||
| # Autogenerated by IDE | ||||
| /bin | ||||
| /.settings | ||||
| .classpath | ||||
|  | ||||
| *.ipr | ||||
| *.iws | ||||
| *.iml | ||||
| .idea | ||||
| .gradle | ||||
| luaj-2.0.3/lib | ||||
| luaj-2.0.3/*.jar | ||||
| *.DS_Store | ||||
| .project | ||||
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| [submodule "src/main/resources/resourcepacks/overhaul"] | ||||
| 	path = src/main/resources/resourcepacks/overhaul | ||||
| 	url = https://github.com/3prm3/cc-pack | ||||
							
								
								
									
										34
									
								
								.luacheckrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								.luacheckrc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| std = "max" | ||||
|  | ||||
| ignore = { | ||||
|     -- Allow access to undefined globals or their fields. In the future we'll | ||||
|     -- define all of CC's globals within this file | ||||
|     '113', '143', | ||||
|  | ||||
|     -- FIXME: Ignore unused arguments and loop variables | ||||
|     '212', '213', | ||||
|  | ||||
|     -- Disable line is too long for now. It would be possible to clean | ||||
|     -- this up in the future. | ||||
|     '631', | ||||
| } | ||||
|  | ||||
| -- Only run the linter on ROM and bios for now, as the treasure disks | ||||
| -- are largely unsupported. | ||||
| include_files = { | ||||
|     'src/main/resources/assets/computercraft/lua/rom', | ||||
|     'src/main/resources/assets/computercraft/lua/bios.lua' | ||||
| } | ||||
|  | ||||
| files['src/main/resources/assets/computercraft/lua/bios.lua'] = { | ||||
|     -- Allow declaring and mutating globals | ||||
|     allow_defined_top = true, | ||||
|     ignore = { '112', '121', '122', '131', '142' }, | ||||
| } | ||||
|  | ||||
| files['src/main/resources/assets/computercraft/lua/rom/apis'] = { | ||||
|     -- APIs may define globals on the top level. We'll ignore unused globals, | ||||
|     -- as obviously they may be used outside that API. | ||||
|     allow_defined_top = true, | ||||
|     ignore = { '131' }, | ||||
| } | ||||
							
								
								
									
										14
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								.travis.yml
									
									
									
									
									
								
							| @@ -1,14 +0,0 @@ | ||||
| language: java | ||||
|  | ||||
| script: ./gradlew build --no-daemon | ||||
|  | ||||
| before_cache: | ||||
|   - rm -f  $HOME/.gradle/caches/modules-2/modules-2.lock | ||||
|   - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ | ||||
| cache: | ||||
|   directories: | ||||
|     - $HOME/.gradle/caches/ | ||||
|     - $HOME/.gradle/wrapper/s | ||||
|  | ||||
| jdk: | ||||
|     - oraclejdk8 | ||||
							
								
								
									
										3
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| { | ||||
| 	"java.configuration.updateBuildConfiguration": "automatic" | ||||
| } | ||||
							
								
								
									
										19
									
								
								LICENSE-luaj
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								LICENSE-luaj
									
									
									
									
									
								
							| @@ -1,19 +0,0 @@ | ||||
| Copyright (c) 2007 LuaJ. All rights reserved. | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
|  | ||||
| The above copyright notice and this permission notice shall be included in | ||||
| all copies or substantial portions of the Software. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| THE SOFTWARE. | ||||
							
								
								
									
										95
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										95
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,47 +1,68 @@ | ||||
| #  | ||||
| [](https://travis-ci.org/SquidDev-CC/CC-Tweaked) | ||||
| # CC:Restitched Patchwork | ||||
| # CC:R Version VS CC:T Version | ||||
| CC:R Strives to maintaim perfect pairity with CC:R, however in some cases this is not possible, or atleast, not yet, so just because you might be on CC:R 1.96.6, doesnt mean you are on CC:T 1.96.6.  | ||||
|  | ||||
| CC: Tweaked is a fork of ComputerCraft which aims to provide earlier access to the more experimental and in-development | ||||
| features of the mod. For a more stable experience, I recommend checking out the | ||||
| [original mod](https://github.com/dan200/ComputerCraft). | ||||
| <img src="logo.png" alt="CC: Restitched" width="100%"/> | ||||
|  | ||||
| *it works and runs-ish* | ||||
|  | ||||
| [](https://github.com/Merith-TK/cc-restitched/actions "Current build status") [](https://www.curseforge.com/minecraft/mc-mods/cc-restitched-updated "Download CC: Restitched on CurseForge") | ||||
|  | ||||
| ## What? | ||||
| CC: Tweaked (or CC:T for short) does not aim to create a competing fork of ComputerCraft, nor am I planning to take it | ||||
| in in a vastly different direction to the original mod. In fact, CC:T aims to be a nurturing ground for various | ||||
| features, with a pull request against the original mod being the end goal. | ||||
| This is an fork of [Zundrel/cc-tweaked-fabric](https://github.com/Zundrel/cc-tweaked-fabric) who's goal was to port [SquidDev-CC/CC-Tweaked](https://github.com/SquidDev-CC/CC-Tweaked) to the [Fabric](https://fabricmc.net/) modloader. I picked up maintaining the mod because the team working on Zundrel's fork, admitted they had gotten lethargic so I picked it up to make it equal with CC:T | ||||
|  | ||||
| CC:T also includes many pull requests from the community which have not yet been merged, offering a large number | ||||
| of additional bug fixes and features over the original mod. | ||||
| ## Resource Packs | ||||
| This mod includes textures that are more in-line with the style of Mojang's new texture-artist, Jappa. If you prefer the original textures, enable the "Classic" resource pack provided by the mod. | ||||
|  | ||||
| ## Features | ||||
| CC: Tweaked contains the all features of the latest alpha, as well as numerous fixes, performance improvements and | ||||
| several additional features. I'd recommend checking out [the releases page](https://github.com/SquidDev-CC/CC-Tweaked/releases) | ||||
| to see the full changes, but here's a couple of the more interesting changes: | ||||
|  | ||||
|  - Replace LuaJ with Cobalt. | ||||
|  - Allow running multiple computers at the same time. | ||||
|  - Websocket support in the HTTP library. | ||||
|  - Wired modems and cables act more like multiparts. | ||||
|  - Add map-like rendering for pocket computers and printed pages/books. | ||||
|  - Adds the `/computercraft` command, offering various diagnostic tools for server owners. This allows operators to | ||||
|    track which computers are hogging resources, turn on and shutdown multiple computers at once and interact with | ||||
|    computers remotely. | ||||
|  - Add full-block wired modems, allowing one to wrap non-solid peripherals (such as turtles, or chests if Plethora is | ||||
|    installed). | ||||
|  | ||||
| ## Relation to CCTweaks? | ||||
| This mod has nothing to do with CCTweaks, though there is no denying the name is a throwback to it. That being said, | ||||
| several features have been included, such as full block modems, the Cobalt runtime and map-like rendering for pocket | ||||
| computers. | ||||
| <img src="https://raw.githubusercontent.com/3prm3/cc-pack/main/pack.png" alt="CC: Restitched" width="16"  height="16"/> [3prm3/cc-pack](https://github.com/3prm3/cc-pack/) | ||||
| We also have a second resourcepack made by [3prm3](https://github.com/3prm3), it features a complete overhaul and can be enabled by enabling the `overhaul` resource pack, go check out his resource pack over here! | ||||
|  | ||||
| ## Major Tasks Planned | ||||
| * Rewrite the config system | ||||
|     * **Planned for 1.96.0 release** | ||||
| 	* it currently sets the values that would normally be read from `config/computercraft.json` to the default values, because it does not read the file at all | ||||
| * Fixing `/computercraft` commands, | ||||
|     * No clue why they broken, they just are | ||||
| 	 | ||||
| ## Contributing | ||||
| Any contribution is welcome, be that using the mod, reporting bugs or contributing code. If you do wish to contribute | ||||
| code, do consider submitting it to the ComputerCraft repository instead. | ||||
| Any contribution is welcome, be that using the mod, reporting bugs or contributing code. In order to start helping develop CC:R there are a few rules | ||||
| 1) Any updates that port commits from CC:T, ***MUST*** follow the format defined in [patchwork.md](patchwork.md) otherwise they will not be accepted, | ||||
| 	* Commit Message must be the same as it is in CC:T, | ||||
| 	* patchwork.md must be updated in the following format | ||||
| 	> Comments, optional but useful if you had to do something 	differently than in CC:T outside of [Fabric](https://fabricmc.net/)/[Forge](https://mcforge.readthedocs.io/en/1.16.x/) differences | ||||
| 	> | ||||
| 	> \`\`\` | ||||
| 	>  | ||||
| 	>commitID | ||||
| 	> | ||||
| 	> commit title | ||||
| 	> | ||||
| 	> commit desc | ||||
| 	> | ||||
| 	> \`\`\` | ||||
| 2) Follow the [Fabric](https://fabricmc.net/) programming guidelines as close as possible. This means you have to use [`loom`](https://fabricmc.net/wiki/tutorial:mappings) mappings,  | ||||
| 3) You cannot intentionally implement bugs and security vulnerabilities | ||||
| 4) Unless the commit is a ["patchwork"](https://github.com/Merith-TK/cc-restitched/blob/fabric/patchwork.md) compliant commit, (IE: taken from CC:T), the lua code is off limits | ||||
| ## Bleeding Edge Builds | ||||
| Bleeding edge builds can be found [here](https://github.com/Merith-TK/cc-restitched/actions) at Github Actions. | ||||
|  | ||||
| That being said, in order to start helping develop CC:T, you'll need to follow these steps: | ||||
| ## Community | ||||
| If you need help getting started with CC: Tweaked, want to show off your latest project, or just want to chat about ComputerCraft, here is the [Forum](https://forums.computercraft.cc/) and the [Discord](https://discord.gg/H2UyJXe)  | ||||
|  | ||||
|  - **Clone the repository:** `git clone https://github.com/SquidDev-CC/CC-Tweaked.git && cd CC-Tweaked` | ||||
|  - **Setup Forge:** `./gradlew setupDecompWorkspace` | ||||
|  - **Test your changes:** `./gradlew runClient` (or run the `GradleStart` class from your IDE). | ||||
| ## Known Issues | ||||
| Main Known issue | ||||
| * Mods that add blocks that can be used as peripherals for CC:T On forge, don't work with CC:R. | ||||
| 	* This is because of the differences between forge and fabric, and that mod devs, to my knowledge have not agreed upon a standard method in which to implement cross compatibility between mods, | ||||
| * [Fixed (d10f297c): please report if bug persists]</br> ~~Storage Peripherals throw a java "StackOverflowError" when using `pushItems()`,~~  | ||||
|     * ~~Work around, you are probably using `pushItems(chest, 1)` or similar. please use `pushItems(chest, 1, nil, 1)`.~~  | ||||
| * Computers will not run built in commands, saying "File not found" | ||||
|     * This is a know bug, dont know what causes it, but just restart the computer (`ctrl+r` for one second) and it will work again | ||||
|     * Occurs when server runs `/reload` or a datapack is updated | ||||
| 	 | ||||
| ## Perpherals | ||||
| Unfortunately, unlike the original CC:Tweaked project, CC:Restitched, does not have any actual peripheral mods, currently the only one we have is an example for mod devs to get started with making/adding the peripheral API to their mods! | ||||
|  | ||||
| If you want to run CC:T in a normal Minecraft instance, run `./gradlew build` and copy the `.jar` from `build/libs`. | ||||
| If your a mod dev made a mod with CC:R peripheral support, OR if your a player who found a mod with CC:R support, please open an [issue here](https://github.com/Merith-TK/cc-restitched/issues/new?assignees=&labels=peripheralShoutout&template=peripheral_shoutout.md) to let us know so we can add it to the list! | ||||
|  | ||||
| *  [CC Peripheral Test](https://github.com/Toad-Dev/cc-peripheral-test) | ||||
| 	* This is an example mod for how to make peripherals that work as a block, or as a turtle upgrade! | ||||
							
								
								
									
										242
									
								
								build.gradle
									
									
									
									
									
								
							
							
						
						
									
										242
									
								
								build.gradle
									
									
									
									
									
								
							| @@ -1,198 +1,120 @@ | ||||
|  | ||||
| // For those who want the bleeding edge | ||||
| buildscript { | ||||
|     repositories { | ||||
|         jcenter() | ||||
|         maven { | ||||
|             name = "forge" | ||||
|             url = "http://files.minecraftforge.net/maven" | ||||
|         } | ||||
|     } | ||||
|     dependencies { | ||||
|         classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT' | ||||
|         classpath 'org.ajoberstar:gradle-git:1.6.0' | ||||
|     } | ||||
| } | ||||
|  | ||||
| plugins { | ||||
|     id 'com.matthewprenger.cursegradle' version '1.0.10' | ||||
|     id 'fabric-loom' version '0.6-SNAPSHOT' | ||||
|     id 'maven-publish' | ||||
| } | ||||
|  | ||||
| apply plugin: 'net.minecraftforge.gradle.forge' | ||||
| apply plugin: 'org.ajoberstar.grgit' | ||||
| apply plugin: 'maven-publish' | ||||
| apply plugin: 'maven' | ||||
| sourceCompatibility = JavaVersion.VERSION_1_8 | ||||
| targetCompatibility = JavaVersion.VERSION_1_8 | ||||
|  | ||||
| version = "1.80pr1.8" | ||||
| group = "org.squiddev" | ||||
| archivesBaseName = "cc-tweaked" | ||||
| version = mod_version | ||||
|  | ||||
| minecraft { | ||||
|     version = "1.12.2-14.23.4.2749" | ||||
|     runDir = "run" | ||||
|     replace '${version}', project.version | ||||
|  | ||||
|     // the mappings can be changed at any time, and must be in the following format. | ||||
|     // snapshot_YYYYMMDD   snapshot are built nightly. | ||||
|     // stable_#            stables are built at the discretion of the MCP team. | ||||
|     // Use non-default mappings at your own risk. they may not allways work. | ||||
|     // simply re-run your setup task after changing the mappings to update your workspace. | ||||
|     mappings = "snapshot_20180724" | ||||
|     // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. | ||||
| } | ||||
| group = "dan200.computercraft" | ||||
| archivesBaseName = "cc-restiched" | ||||
|  | ||||
| repositories { | ||||
|     mavenCentral() | ||||
|     jcenter() | ||||
|     maven { | ||||
|         name = "JEI" | ||||
|         url  = "http://dvs1.progwml6.com/files/maven" | ||||
|         name "SquidDev" | ||||
|         url "https://squiddev.cc/maven" | ||||
|     } | ||||
|     maven { | ||||
|         name = "squiddev" | ||||
|         url = "https://dl.bintray.com/squiddev/maven" | ||||
|     } | ||||
|  | ||||
|     ivy { artifactPattern "https://asie.pl/files/mods/Charset/LibOnly/[module]-[revision](-[classifier]).[ext]" } | ||||
| } | ||||
|  | ||||
| configurations { | ||||
|     shade | ||||
|     compile.extendsFrom shade | ||||
|     deployerJars | ||||
| } | ||||
|  | ||||
| dependencies { | ||||
|     deobfProvided "mezz.jei:jei_1.12.2:4.8.5.159:api" | ||||
|     deobfProvided "pl.asie:Charset-Lib:0.5.4.6" | ||||
|     minecraft "com.mojang:minecraft:${mc_version}" | ||||
|     mappings "net.fabricmc:yarn:${mc_version}+build.${mappings_version}:v2" | ||||
|     modImplementation "net.fabricmc:fabric-loader:${fabric_loader_version}" | ||||
|     modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_api_version}" | ||||
|  | ||||
|     runtime "mezz.jei:jei_1.12.2:4.8.5.159" | ||||
|     compile 'com.electronwill.night-config:json:3.6.0' | ||||
|  | ||||
|     shade 'org.squiddev:Cobalt:0.3.2' | ||||
|     modImplementation "me.shedaniel.cloth:config-2:${cloth_config_version}" | ||||
|     modImplementation "io.github.prospector:modmenu:${modmenu_version}" | ||||
|  | ||||
|     testCompile 'junit:junit:4.11' | ||||
|     modApi "me.shedaniel.cloth.api:cloth-utils-v1:${project.cloth_api_version}" | ||||
|     include "me.shedaniel.cloth.api:cloth-utils-v1:${project.cloth_api_version}" | ||||
|  | ||||
|     deployerJars "org.apache.maven.wagon:wagon-ssh:3.0.0" | ||||
|     implementation "blue.endless:jankson:${jankson_version}" | ||||
|     implementation 'com.google.code.findbugs:jsr305:3.0.2' | ||||
|  | ||||
|     compileOnly 'com.google.auto.service:auto-service:1.0-rc7' | ||||
|     annotationProcessor 'com.google.auto.service:auto-service:1.0-rc7' | ||||
|  | ||||
|     include "me.shedaniel.cloth:config-2:${cloth_config_version}" | ||||
|     include "blue.endless:jankson:${jankson_version}" | ||||
|     include 'javax.vecmath:vecmath:1.5.2' | ||||
|  | ||||
|     compile 'javax.vecmath:vecmath:1.5.2' | ||||
|  | ||||
|     shade 'org.squiddev:Cobalt:0.5.2-SNAPSHOT' | ||||
|  | ||||
|     modRuntime "me.shedaniel:RoughlyEnoughItems-api:5.8.9" | ||||
|     modRuntime "me.shedaniel:RoughlyEnoughItems:5.8.9" | ||||
| } | ||||
|  | ||||
| javadoc { | ||||
|     include "dan200/computercraft/api/**/*.java" | ||||
| sourceSets { | ||||
|     main { | ||||
|         java { | ||||
|             exclude 'dan200/computercraft/shared/integration' | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| processResources { | ||||
|     inputs.property "version", project.version | ||||
|  | ||||
|     from(sourceSets.main.resources.srcDirs) { | ||||
|         include "fabric.mod.json" | ||||
|         expand "version": project.version | ||||
|     } | ||||
|  | ||||
|     from(sourceSets.main.resources.srcDirs) { | ||||
|         exclude "fabric.mod.json" | ||||
|     } | ||||
| } | ||||
|  | ||||
| // ensure that the encoding is set to UTF-8, no matter what the system default is | ||||
| // this fixes some edge cases with special characters not displaying correctly | ||||
| // see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html | ||||
| tasks.withType(JavaCompile) { | ||||
|     options.encoding = "UTF-8" | ||||
| } | ||||
|  | ||||
| // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task | ||||
| // if it is present. | ||||
| // If you remove this task, sources will not be generated. | ||||
| task sourcesJar(type: Jar, dependsOn: classes) { | ||||
|     classifier = "sources" | ||||
|     from sourceSets.main.allSource | ||||
| } | ||||
|  | ||||
| jar { | ||||
|     dependsOn javadoc | ||||
|  | ||||
|     manifest { | ||||
|         attributes('FMLAT': 'computercraft_at.cfg') | ||||
|     } | ||||
|  | ||||
|     into("docs", { from (javadoc.destinationDir) }) | ||||
|  | ||||
|     into("api", { from (sourceSets.main.allSource) { | ||||
|         include "dan200/computercraft/api/**/*.java" | ||||
|     }}) | ||||
|     from "LICENSE" | ||||
|  | ||||
|     from configurations.shade.collect { it.isDirectory() ? it : zipTree(it) } | ||||
| } | ||||
|  | ||||
| import org.ajoberstar.grgit.Grgit | ||||
|  | ||||
| processResources { | ||||
|     inputs.property "version", project.version | ||||
|     inputs.property "mcversion", project.minecraft.version | ||||
|  | ||||
|     def grgit = Grgit.open(dir: '.') | ||||
|     inputs.property "commithash", grgit.head().id | ||||
|  | ||||
|     def blacklist = ['GitHub', 'dan200', 'Daniel Ratcliffe'] | ||||
|     Set<String> contributors = [] | ||||
|  | ||||
|     grgit.log().each { | ||||
|         if (!blacklist.contains(it.author.name)) contributors.add(it.author.name) | ||||
|         if (!blacklist.contains(it.committer.name)) contributors.add(it.committer.name) | ||||
|     } | ||||
|  | ||||
|     from(sourceSets.main.resources.srcDirs) { | ||||
|         include 'mcmod.info' | ||||
|         include 'assets/computercraft/lua/rom/help/credits.txt' | ||||
|  | ||||
|         expand 'version':project.version, | ||||
|                'mcversion':project.minecraft.version, | ||||
|                'gitcontributors':contributors.sort(false, String.CASE_INSENSITIVE_ORDER).join('\n') | ||||
|     } | ||||
|  | ||||
|     from(sourceSets.main.resources.srcDirs) { | ||||
|         exclude 'mcmod.info' | ||||
|         exclude 'assets/computercraft/lua/rom/help/credits.txt' | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| curseforge { | ||||
|     apiKey = project.hasProperty('curseForgeApiKey') ? project.curseForgeApiKey : '' | ||||
|     project { | ||||
|         id = '282001' | ||||
|         releaseType = 'beta' | ||||
|         changelog = '' | ||||
|     } | ||||
| } | ||||
|  | ||||
| // configure the maven publication | ||||
| publishing { | ||||
|     publications { | ||||
|         mavenJava(MavenPublication) { | ||||
|             from components.java | ||||
|             artifact sourceJar | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| uploadArchives { | ||||
|     repositories { | ||||
|         if(project.hasProperty('mavenUploadUrl')) { | ||||
|             mavenDeployer { | ||||
|                 configuration = configurations.deployerJars | ||||
|  | ||||
|                 repository(url: project.property('mavenUploadUrl')) { | ||||
|                     authentication( | ||||
|                         userName: project.property('mavenUploadUser'), | ||||
|                         privateKey: project.property('mavenUploadKey')) | ||||
|                 } | ||||
|  | ||||
|                 pom.project { | ||||
|                     name 'CC: Tweaked' | ||||
|                     packaging 'jar' | ||||
|                     description 'A fork of ComputerCraft which aims to provide earlier access to the more experimental and in-development features of the mod.' | ||||
|                     url 'https://github.com/SquidDev-CC/CC-Tweaked' | ||||
|  | ||||
|                     scm { | ||||
|                         url 'https://github.com/dan200/ComputerCraft.git' | ||||
|                     } | ||||
|  | ||||
|                     issueManagement { | ||||
|                         system 'github' | ||||
|                         url 'https://github.com/dan200/ComputerCraft/issues' | ||||
|                     } | ||||
|  | ||||
|                     licenses { | ||||
|                         license { | ||||
|                             name 'ComputerCraft Public License, Version 1.0' | ||||
|                             url 'https://github.com/dan200/ComputerCraft/blob/master/LICENSE' | ||||
|                             distribution 'repo' | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 pom.whenConfigured { pom -> | ||||
|                     pom.dependencies.clear() | ||||
|                 } | ||||
|             // add all the jars that should be included when publishing to maven | ||||
|             artifact(remapJar) { | ||||
|                 builtBy remapJar | ||||
|             } | ||||
|             artifact(sourcesJar) { | ||||
|                 builtBy remapSourcesJar | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| gradle.projectsEvaluated { | ||||
|     tasks.withType(JavaCompile) { | ||||
|         options.compilerArgs << "-Xlint" | ||||
|     // select the repositories you want to publish to | ||||
|     repositories { | ||||
|         // uncomment to publish to the local maven | ||||
|         // mavenLocal() | ||||
|     } | ||||
| } | ||||
|  | ||||
| runClient.outputs.upToDateWhen { false } | ||||
| runServer.outputs.upToDateWhen { false } | ||||
|   | ||||
| @@ -1,12 +0,0 @@ | ||||
| #!/bin/sh | ||||
| cd luaj-2.0.3 | ||||
| echo "Building LuaJ..." | ||||
| ant clean | ||||
| ant | ||||
|  | ||||
| echo "Copying output to libs..." | ||||
| rm ../libs/luaj-jse-2.0.3.jar | ||||
| cp luaj-jse-2.0.3.jar ../libs | ||||
|  | ||||
| echo "Done." | ||||
| cd .. | ||||
							
								
								
									
										2491
									
								
								codeInspectionSettings.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2491
									
								
								codeInspectionSettings.xml
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										61
									
								
								codeStyleSettings.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								codeStyleSettings.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| <code_scheme name="Project" version="173"> | ||||
|   <JSON> | ||||
|     <option name="OBJECT_WRAPPING" value="1" /> | ||||
|     <option name="ARRAY_WRAPPING" value="1" /> | ||||
|   </JSON> | ||||
|   <JavaCodeStyleSettings> | ||||
|     <option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND"> | ||||
|       <value /> | ||||
|     </option> | ||||
|     <option name="JD_P_AT_EMPTY_LINES" value="false" /> | ||||
|     <option name="JD_PRESERVE_LINE_FEEDS" value="true" /> | ||||
|   </JavaCodeStyleSettings> | ||||
|   <codeStyleSettings language="JAVA"> | ||||
|     <option name="KEEP_FIRST_COLUMN_COMMENT" value="false" /> | ||||
|     <option name="BRACE_STYLE" value="2" /> | ||||
|     <option name="CLASS_BRACE_STYLE" value="2" /> | ||||
|     <option name="METHOD_BRACE_STYLE" value="2" /> | ||||
|     <option name="LAMBDA_BRACE_STYLE" value="5" /> | ||||
|     <option name="ELSE_ON_NEW_LINE" value="true" /> | ||||
|     <option name="CATCH_ON_NEW_LINE" value="true" /> | ||||
|     <option name="FINALLY_ON_NEW_LINE" value="true" /> | ||||
|     <option name="SPACE_WITHIN_METHOD_CALL_PARENTHESES" value="true" /> | ||||
|     <option name="SPACE_WITHIN_METHOD_PARENTHESES" value="true" /> | ||||
|     <option name="SPACE_WITHIN_IF_PARENTHESES" value="true" /> | ||||
|     <option name="SPACE_WITHIN_WHILE_PARENTHESES" value="true" /> | ||||
|     <option name="SPACE_WITHIN_FOR_PARENTHESES" value="true" /> | ||||
|     <option name="SPACE_WITHIN_TRY_PARENTHESES" value="true" /> | ||||
|     <option name="SPACE_WITHIN_CATCH_PARENTHESES" value="true" /> | ||||
|     <option name="SPACE_WITHIN_SWITCH_PARENTHESES" value="true" /> | ||||
|     <option name="SPACE_WITHIN_SYNCHRONIZED_PARENTHESES" value="true" /> | ||||
|     <option name="SPACE_WITHIN_ARRAY_INITIALIZER_BRACES" value="true" /> | ||||
|     <option name="SPACE_BEFORE_IF_PARENTHESES" value="false" /> | ||||
|     <option name="SPACE_BEFORE_WHILE_PARENTHESES" value="false" /> | ||||
|     <option name="SPACE_BEFORE_FOR_PARENTHESES" value="false" /> | ||||
|     <option name="SPACE_BEFORE_TRY_PARENTHESES" value="false" /> | ||||
|     <option name="SPACE_BEFORE_CATCH_PARENTHESES" value="false" /> | ||||
|     <option name="SPACE_BEFORE_SWITCH_PARENTHESES" value="false" /> | ||||
|     <option name="SPACE_BEFORE_SYNCHRONIZED_PARENTHESES" value="false" /> | ||||
|     <option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true" /> | ||||
|     <option name="KEEP_SIMPLE_METHODS_IN_ONE_LINE" value="true" /> | ||||
|     <option name="KEEP_SIMPLE_LAMBDAS_IN_ONE_LINE" value="true" /> | ||||
|     <option name="KEEP_SIMPLE_CLASSES_IN_ONE_LINE" value="true" /> | ||||
|     <option name="IF_BRACE_FORCE" value="1" /> | ||||
|     <option name="DOWHILE_BRACE_FORCE" value="1" /> | ||||
|     <option name="WHILE_BRACE_FORCE" value="1" /> | ||||
|     <option name="FOR_BRACE_FORCE" value="1" /> | ||||
|     <option name="SPACE_WITHIN_ANNOTATION_PARENTHESES" value="true" /> | ||||
|     <indentOptions> | ||||
|       <option name="CONTINUATION_INDENT_SIZE" value="4" /> | ||||
|     </indentOptions> | ||||
|   </codeStyleSettings> | ||||
|   <codeStyleSettings language="JSON"> | ||||
|     <option name="KEEP_BLANK_LINES_IN_CODE" value="1" /> | ||||
|     <option name="SPACE_WITHIN_BRACKETS" value="true" /> | ||||
|     <option name="SPACE_WITHIN_BRACES" value="true" /> | ||||
|     <indentOptions> | ||||
|       <option name="INDENT_SIZE" value="4" /> | ||||
|       <option name="CONTINUATION_INDENT_SIZE" value="4" /> | ||||
|     </indentOptions> | ||||
|   </codeStyleSettings> | ||||
| </code_scheme> | ||||
							
								
								
									
										10
									
								
								codesize.sh
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								codesize.sh
									
									
									
									
									
								
							| @@ -1,10 +0,0 @@ | ||||
| #!/bin/sh | ||||
| echo "Java code:" | ||||
| cat `find src | grep \\.java$` | wc | ||||
|  | ||||
| echo "Lua code:" | ||||
| cat `find src/main/resources/assets/computercraft/lua | grep \\.lua$` | wc | ||||
|  | ||||
| echo "JSON:" | ||||
| cat `find src/main/resources/assets/computercraft | grep \\.json$` | wc | ||||
|  | ||||
							
								
								
									
										21
									
								
								deploy.sh
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								deploy.sh
									
									
									
									
									
								
							| @@ -1,21 +0,0 @@ | ||||
| #!/bin/sh | ||||
|  | ||||
| echo "Building with gradle..." | ||||
| rm -rf build/libs | ||||
| rm -rf build/resources | ||||
| rm -rf build/classes | ||||
| chmod -R +rw src/main/resources | ||||
| chmod +x gradlew | ||||
| ./gradlew build | ||||
|  | ||||
| echo "Deleting old deployment..." | ||||
| rm -rf deploy | ||||
| mkdir deploy | ||||
|  | ||||
| echo "Making new deployment..." | ||||
| INPUTJAR=`ls -1 build/libs | grep -v sources` | ||||
| OUTPUTJAR=`ls -1 build/libs | grep -v sources | sed s/\-//g` | ||||
| FRIENDLYNAME=`ls -1 build/libs | grep -v sources | sed s/\-/\ /g | sed s/\.jar//g` | ||||
| cp build/libs/$INPUTJAR deploy/$OUTPUTJAR | ||||
|  | ||||
| echo "Done." | ||||
							
								
								
									
										17
									
								
								gradle.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								gradle.properties
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| # Done to increase the memory available to gradle. | ||||
| org.gradle.jvmargs=-Xmx1G | ||||
|  | ||||
| # Mod properties | ||||
| mod_version=1.96.0 | ||||
|  | ||||
| # Minecraft properties | ||||
| mc_version=1.16.5 | ||||
| mappings_version=9 | ||||
|  | ||||
| # Dependencies | ||||
| cloth_config_version=4.8.1 | ||||
| fabric_loader_version=0.11.3 | ||||
| fabric_api_version=0.32.0+1.16 | ||||
| jankson_version=1.2.0 | ||||
| modmenu_version=1.14.6+ | ||||
| cloth_api_version=1.4.5 | ||||
							
								
								
									
										
											BIN
										
									
								
								gradle/wrapper/gradle-wrapper.jar
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								gradle/wrapper/gradle-wrapper.jar
									
									
									
									
										vendored
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										5
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								gradle/wrapper/gradle-wrapper.properties
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,6 @@ | ||||
| #Tue Jul 07 13:15:43 EDT 2020 | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip | ||||
| distributionBase=GRADLE_USER_HOME | ||||
| distributionPath=wrapper/dists | ||||
| zipStoreBase=GRADLE_USER_HOME | ||||
| zipStorePath=wrapper/dists | ||||
| distributionUrl=https\://services.gradle.org/distributions/gradle-4.3-bin.zip | ||||
| zipStoreBase=GRADLE_USER_HOME | ||||
|   | ||||
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								logo.png
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								logo.png
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 5.2 KiB | 
| @@ -1,19 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <classpath> | ||||
| 	<classpathentry kind="src" path="src/core"/> | ||||
| 	<classpathentry excluding="org/luaj/vm2/luajc/antlr/|org/luaj/vm2/luajc/lst/|org/luaj/vm2/luajc/JavaCodeGenerator.java" kind="src" path="src/jse"/> | ||||
| 	<classpathentry kind="src" path="src/jme"/> | ||||
| 	<classpathentry kind="src" path="test/java"/> | ||||
| 	<classpathentry kind="src" path="test/junit"/> | ||||
| 	<classpathentry kind="src" path="test/lua"/> | ||||
| 	<classpathentry kind="src" path="examples/jse"/> | ||||
| 	<classpathentry kind="src" path="examples/jme"/> | ||||
| 	<classpathentry kind="src" path="examples/lua"/> | ||||
| 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> | ||||
| 	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/> | ||||
| 	<classpathentry kind="lib" path="lib/midpapi20.jar"/> | ||||
| 	<classpathentry kind="lib" path="lib/cldcapi11.jar"/> | ||||
| 	<classpathentry kind="lib" path="lib/bcel-5.2.jar"/> | ||||
| 	<classpathentry kind="var" path="JRE_LIB"/> | ||||
| 	<classpathentry kind="output" path="bin"/> | ||||
| </classpath> | ||||
| @@ -1,17 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <projectDescription> | ||||
| 	<name>luaj-vm</name> | ||||
| 	<comment></comment> | ||||
| 	<projects> | ||||
| 	</projects> | ||||
| 	<buildSpec> | ||||
| 		<buildCommand> | ||||
| 			<name>org.eclipse.jdt.core.javabuilder</name> | ||||
| 			<arguments> | ||||
| 			</arguments> | ||||
| 		</buildCommand> | ||||
| 	</buildSpec> | ||||
| 	<natures> | ||||
| 		<nature>org.eclipse.jdt.core.javanature</nature> | ||||
| 	</natures> | ||||
| </projectDescription> | ||||
| @@ -1,19 +0,0 @@ | ||||
| Copyright (c) 2007 LuaJ. All rights reserved. | ||||
|  | ||||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| of this software and associated documentation files (the "Software"), to deal | ||||
| in the Software without restriction, including without limitation the rights | ||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| copies of the Software, and to permit persons to whom the Software is | ||||
| furnished to do so, subject to the following conditions: | ||||
|  | ||||
| The above copyright notice and this permission notice shall be included in | ||||
| all copies or substantial portions of the Software. | ||||
|  | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| THE SOFTWARE. | ||||
| @@ -1,780 +0,0 @@ | ||||
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | ||||
| <html> | ||||
|  | ||||
| <head> | ||||
| <title>Getting Started with LuaJ</title> | ||||
| <link rel="stylesheet" type="text/css" href="http://www.lua.org/lua.css"> | ||||
| <META HTTP-EQUIV="content-type" CONTENT="text/html; charset=iso-8859-1"> | ||||
| </head> | ||||
|  | ||||
| <body> | ||||
|  | ||||
| <hr> | ||||
| <h1> | ||||
| <a href="README.html"><img src="http://sourceforge.net/dbimage.php?id=196139" alt="" border="0"></a> | ||||
|  | ||||
| Getting Started with LuaJ | ||||
|  | ||||
| </h1> | ||||
| James Roseborough, Ian Farmer, Version 2.0.3 | ||||
| <p> | ||||
| <small> | ||||
| Copyright © 2009-2012 Luaj.org. | ||||
| Freely available under the terms of the | ||||
| <a href="http://sourceforge.net/dbimage.php?id=196142">Luaj license</a>. | ||||
| </small> | ||||
| <hr> | ||||
| <p> | ||||
|  | ||||
| <a href="#1">introduction</a> | ||||
| · | ||||
| <a href="#2">examples</a> | ||||
| · | ||||
| <a href="#3">concepts</a> | ||||
| · | ||||
| <a href="#4">libraries</a> | ||||
| · | ||||
| <a href="#5">luaj api</a> | ||||
| · | ||||
| <a href="#6">parser</a> | ||||
| · | ||||
| <a href="#7">building</a> | ||||
| · | ||||
| <a href="#8">downloads</a> | ||||
| · | ||||
| <a href="#9">release notes</a> | ||||
|  | ||||
| <!-- ====================================================================== --> | ||||
| <p> | ||||
|  | ||||
| <h1>1 - <a name="1">Introduction</a></h1> | ||||
| <h2>Goals of Luaj</h2> | ||||
| Luaj is a lua interpreter based on the 5.1.x version of lua with the following goals in mind: | ||||
| <ul> | ||||
| <li>Java-centric implementation of lua vm built to leverage standard Java features. | ||||
| <li>Lightweight, high performance execution of lua.  | ||||
| <li>Multi-platform to be able to run on JME, JSE, or JEE environments.  | ||||
| <li>Complete set of libraries and tools for integration into real-world projects. | ||||
| <li>Dependable due to sufficient unit testing of vm and library features.  | ||||
| </ul> | ||||
|  | ||||
| <h2>Differences with 1.0</h2> | ||||
| In addition to the basic goals of luaj, version 2.0 is aimed  | ||||
| at improving on the 1.0 vm in the following aspects.  | ||||
| <ul> | ||||
| <li>Support for compiling lua source code into Java source code. | ||||
| <li>Support for compiling lua bytecode directly into Java bytecode. | ||||
| <li>Improved performance of of lua bytecode processing. | ||||
| <li>Stackless vm design centered around dynamically typed objects. | ||||
| <li>More alignment with C API (see <a href="names.csv">names.csv</a> for details) | ||||
| <li>Improved class and package naming conventions.  | ||||
| <li>Improved unit tests of core classes.  | ||||
| <li>Improved quality due to major redesign and rewrite of core elements.  | ||||
| <li>More complete implementation including weak keys and values, and all metatags.  | ||||
| </ul> | ||||
|  | ||||
| <h2>Performance</h2> | ||||
| Good performance is a major goal of luaj.   | ||||
| The following table provides measured execution times on a subset of benchmarks from  | ||||
| <a href="http://shootout.alioth.debian.org/">the computer language benchmarks game</a>   | ||||
| in comparison with the standard C distribution.  | ||||
| <table cellspacing="10"><tr><td><table> | ||||
| <tr valign="top"> | ||||
| 	<td><u>Project</td> | ||||
| 	<td><u>Version</td> | ||||
| 	<td><u>Mode</td> | ||||
| 	<td rowspan="9">  </td> | ||||
| 	<td colspan="4" align="center"><u>Benchmark execution time (sec)</td> | ||||
| 	<td rowspan="9">  </td> | ||||
| 	<td><u>Language</td> | ||||
| 	<td><u>Sample command</td> | ||||
| 	</tr> | ||||
| <tr valign="top"> | ||||
| 	<td colspan="2"></td> | ||||
| 	<td></td> | ||||
| 	<td><em>binarytrees 15</em></td> | ||||
| 	<td><em>fannkuch 10</em></td> | ||||
| 	<td><em>nbody 1e6</em></td> | ||||
| 	<td><em>nsieve 9</em></td> | ||||
| 	</tr> | ||||
| <tr valign="top"> | ||||
| 	<td>luaj</td> | ||||
| 	<td>2.0</td> | ||||
| 	<td>-b (luajc)</td> | ||||
| 	<td>2.980</td> | ||||
| 	<td>5.073</td> | ||||
| 	<td>16.794</td> | ||||
| 	<td>11.274</td> | ||||
| 	<td>Java</td> | ||||
| 	<td>java -cp luaj-jse-2.0.3.jar;bcel-5.2.jar lua <b>-b</b> fannkuch.lua 10</td></tr> | ||||
| <tr valign="top"> | ||||
| 	<td></td> | ||||
| 	<td></td> | ||||
| 	<td>-j (lua2java)</td> | ||||
| 	<td>4.463</td> | ||||
| 	<td>5.884</td> | ||||
| 	<td>16.701</td> | ||||
| 	<td>13.789</td> | ||||
| 	<td></td> | ||||
| 	<td>java -cp luaj-jse-2.0.3.jar lua <b>-j</b> fannkuch.lua 10</td></tr> | ||||
| <tr valign="top"> | ||||
| 	<td></td> | ||||
| 	<td></td> | ||||
| 	<td>-n (interpreted)</td> | ||||
| 	<td>12.838</td> | ||||
| 	<td>23.290</td> | ||||
| 	<td>36.894</td> | ||||
| 	<td>15.163</td> | ||||
| 	<td></td> | ||||
| 	<td>java -cp luaj-jse-2.0.3.jar lua -n fannkuch.lua 10</td></tr> | ||||
| <tr valign="top"> | ||||
| 	<td>lua</td> | ||||
| 	<td>5.1.4</td> | ||||
| 	<td></td> | ||||
| 	<td>17.637</td> | ||||
| 	<td>16.044</td> | ||||
| 	<td>15.201</td> | ||||
| 	<td>5.477</td> | ||||
| 	<td>C</td> | ||||
| 	<td>lua fannkuch.lua 10</td></tr> | ||||
| <tr valign="top"> | ||||
| 	<td>jill</td> | ||||
| 	<td>1.0.1</td> | ||||
| 	<td></td> | ||||
| 	<td>44.512</td> | ||||
| 	<td>54.630</td> | ||||
| 	<td>72.172</td> | ||||
| 	<td>20.779</td> | ||||
| 	<td>Java</td> | ||||
| 	<td></td></tr> | ||||
| <tr valign="top"> | ||||
| 	<td>kahlua</td> | ||||
| 	<td>1.0</td> | ||||
| 	<td>jse</td> | ||||
| 	<td>22.963</td> | ||||
| 	<td>63.277</td> | ||||
| 	<td>68.223</td> | ||||
| 	<td>21.529</td> | ||||
| 	<td>Java</td> | ||||
| 	<td></td></tr> | ||||
| <tr valign="top"> | ||||
| 	<td>mochalua</td> | ||||
| 	<td>1.0</td> | ||||
| 	<td></td> | ||||
| 	<td>50.457</td> | ||||
| 	<td>70.368</td> | ||||
| 	<td>82.868</td> | ||||
| 	<td>41.262</td> | ||||
| 	<td>Java</td> | ||||
| 	<td></td></tr> | ||||
| </table></td></tr></table> | ||||
|  | ||||
| Luaj in interpreted mode performs well for the benchmarks, and even better when source-to-source (lua2java)  | ||||
| or bytecode-to-bytecode (luajc) compilers are used,  | ||||
| and actually executes <em>faster</em> than C-based lua in some cases.   | ||||
| It is also faster than Java-lua implementations Jill, Kahlua, and Mochalua for all benchmarks tested.   | ||||
|  | ||||
| <h1>2 - <a name="2">Simple Examples</a></h1> | ||||
|  | ||||
| <h2>Run a lua script in Java SE</h2> | ||||
|  | ||||
| <p> | ||||
| From the main distribution directory line type: | ||||
|  | ||||
| <pre> | ||||
| 	java -cp lib/luaj-jse-2.0.3.jar lua examples/lua/hello.lua | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| You should see the following output: | ||||
| <pre> | ||||
| 	hello, world | ||||
| </pre> | ||||
|  | ||||
| To see how luaj can be used to acccess most Java API's including swing, try: | ||||
|  | ||||
| <pre> | ||||
| 	java -cp lib/luaj-jse-2.0.3.jar lua examples/lua/swingapp.lua | ||||
| </pre> | ||||
|  | ||||
| <h2>Compile lua source to lua bytecode</h2> | ||||
|  | ||||
| <p> | ||||
| From the main distribution directory line type: | ||||
|  | ||||
| <pre> | ||||
| 	java -cp lib/luaj-jse-2.0.3.jar luac examples/lua/hello.lua | ||||
| 	java -cp lib/luaj-jse-2.0.3.jar lua luac.out | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| The compiled output "luac.out" is lua bytecode and should run and produce the same result. | ||||
|  | ||||
| <h2>Compile lua source to java source</h2> | ||||
|  | ||||
| <p> | ||||
| Luaj can compile to lua source code to Java source code: | ||||
|  | ||||
| <pre> | ||||
| 	java -cp lib/luaj-jse-2.0.3.jar lua2java -s examples/lua -d . hello.lua | ||||
| 	javac -cp lib/luaj-jse-2.0.3.jar hello.java | ||||
| 	java -cp "lib/luaj-jse-2.0.3.jar;." lua -l hello | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| The output <em>hello.java</em> is Java source, that implements the logic in hello.lua directly. | ||||
| Once <em>hello.java</em> is compiled into <em>hello.class</em> it can be required and used in place of the original lua script, but with better performance.   | ||||
| There are no additional dependencies for compiling or running source-to-source compiled lua.  | ||||
|  | ||||
| <p> | ||||
| Lua scripts can also be run directly in this mode without precompiling using the <em>lua</em> command with the <b><em>-j</em></b> option when run in JDK 1.5 or higher: | ||||
| <pre> | ||||
| 	java -cp lib/luaj-jse-2.0.3.jar lua -j examples/lua/hello.lua | ||||
| </pre> | ||||
|  | ||||
| <h2>Compile lua bytecode to java bytecode</h2> | ||||
|  | ||||
| <p> | ||||
| Luaj can compile lua sources or binaries directly to java bytecode if the bcel library is on the class path. From the main distribution directory line type: | ||||
|  | ||||
| <pre> | ||||
| 	ant bcel-lib | ||||
| 	java -cp "lib/luaj-jse-2.0.3.jar;lib/bcel-5.2.jar" luajc -s examples/lua -d . hello.lua | ||||
| 	java -cp "lib/luaj-jse-2.0.3.jar;." lua -l hello | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| The output <em>hello.class</em> is Java bytecode, should run and produce the same result. | ||||
| There is no runtime dependency on the bcel library,  | ||||
| but the compiled classes must be in the class path at runtime, unless runtime jit-compiling via luajc and bcel are desired (see later sections). | ||||
|  | ||||
| <p> | ||||
| Lua scripts can also be run directly in this mode without precompiling using the <em>lua</em> command with the <b><em>-b</em></b> option and providing the <em>bcel</em> library in the class path: | ||||
| <pre> | ||||
| 	java -cp "lib/luaj-jse-2.0.3.jar;lib/bcel-5.2.jar" lua -b examples/lua/hello.lua | ||||
| </pre> | ||||
|  | ||||
|  | ||||
| <h2>Run a script in a Java Application</h2> | ||||
|  | ||||
| <p> | ||||
| The following pattern is used within Java SE | ||||
|  | ||||
| <pre> | ||||
| 	import org.luaj.vm2.*; | ||||
| 	import org.luaj.vm2.lib.jse.*; | ||||
|  | ||||
| 	String script = "examples/lua/hello.lua"; | ||||
| 	LuaValue _G = JsePlatform.standardGlobals(); | ||||
| 	_G.get("dofile").call( LuaValue.valueOf(script) ); | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| A simple example may be found in | ||||
| <pre> | ||||
| 	examples/jse/SampleJseMain.java | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| You must include the library <b>lib/luaj-jse-2.0.3.jar</b> in your class path. | ||||
|  | ||||
| <h2>Run a script in a MIDlet</h2> | ||||
|  | ||||
| <p> | ||||
| The for MIDlets the <em>JmePlatform</em> is used instead: | ||||
|  | ||||
| <pre> | ||||
| 	import org.luaj.vm2.*; | ||||
| 	import org.luaj.vm2.lib.jme.*; | ||||
|  | ||||
| 	String script = "examples/lua/hello.lua"; | ||||
| 	LuaValue _G = JmePlatform.standardGlobals(); | ||||
| 	_G.get("dofile").call( LuaValue.valueOf(script) ); | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| The file must be a resource within within the midlet jar for <em>dofile()</em> to find it. | ||||
| Any files included via <em>require()</em> must also be part of the midlet resources. | ||||
|  | ||||
| <p> | ||||
| A simple example may be found in | ||||
| <pre> | ||||
| 	examples/jme/SampleMIDlet.java | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| You must include the library <b>lib/luaj-jme-2.0.3.jar</b> in your midlet jar. | ||||
|  | ||||
| <p> | ||||
| An ant script to build and run the midlet is in | ||||
| <pre> | ||||
| 	build-midlet.xml | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| You must install the wireless toolkit and define <em>WTK_HOME</em> for this script to work.  | ||||
|  | ||||
| <h2>Run a script using JSR-223 Dynamic Scripting</h2> | ||||
|  | ||||
| <p> | ||||
| The standard use of JSR-223 scripting engines may be used: | ||||
|  | ||||
| <pre> | ||||
| 	ScriptEngineManager mgr = new ScriptEngineManager(); | ||||
| 	ScriptEngine e = mgr.getEngineByExtension(".lua"); | ||||
| 	e.put("x", 25); | ||||
| 	e.eval("y = math.sqrt(x)"); | ||||
| 	System.out.println( "y="+e.get("y") ); | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| All standard aspects of script engines including compiled statements should be supported. | ||||
|  | ||||
| <p> | ||||
| You must include the library <b>lib/luaj-jse-2.0.3.jar</b> in your class path. | ||||
|  | ||||
| <p> | ||||
| A working example may be found in | ||||
| <pre> | ||||
| 	examples/jse/ScriptEngineSample.java | ||||
| </pre> | ||||
|  | ||||
| To compile and run it using Java 1.6 or higher: | ||||
|  | ||||
| <pre> | ||||
| 	javac examples/jse/ScriptEngineSample.java | ||||
| 	java -cp "lib/luaj-jse-2.0.3.jar;examples/jse" ScriptEngineSample | ||||
| </pre> | ||||
|  | ||||
| <h2>Excluding the lua bytecode compiler</h2> | ||||
|  | ||||
| By default, the compiler is included whenever <em>standardGlobals()</em> or <em>debugGlobals()</em> are called.   | ||||
| Without a compiler, files can still be executed, but they must be compiled elsewhere beforehand. | ||||
| The "luac" utility is provided in the jse jar for this purpose, or a standard lua compiler can be used.   | ||||
|  | ||||
| <p> | ||||
| To exclude the lua-to-lua-bytecode compiler, do not call  | ||||
| <em>standardGlobals()</em> or <em>debugGlobals()</em>  | ||||
| but instead initialize globals with including only those libraries  | ||||
| that are needed and omitting the line: | ||||
| <pre> | ||||
| 	org.luaj.vm2.compiler.LuaC.install(); | ||||
| </pre> | ||||
|  | ||||
|  | ||||
| <h2>Including the Lua2Java lua-source-to-Java-source compiler</h2> | ||||
|  | ||||
| <p> | ||||
| To compile from lua sources to Java sources for all lua loaded at runtime,  | ||||
| install the Lua2Java compiler <em>after</em> globals have been created using: | ||||
|  | ||||
| <pre> | ||||
| 	org.luaj.vm2.jse.lua2java.Lua2Java.install(); | ||||
| </pre> | ||||
|  | ||||
| This uses the system Java compiler to compile from Java source to Java bytecode,  | ||||
| and cannot compile lua binary files containing lua bytecode at runtime.  | ||||
|  | ||||
| <h2>Including the LuaJC lua-bytecode-to-Java-bytecode compiler</h2> | ||||
|  | ||||
| <p> | ||||
| To compile from lua to Java bytecode for all lua loaded at runtime,  | ||||
| install the LuaJC compiler <em>after</em> globals have been created using: | ||||
|  | ||||
| <pre> | ||||
| 	org.luaj.vm2.jse.luajc.LuaJC.install(); | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| This will compile all lua bytecode into Java bytecode, regardless of if they are loaded as | ||||
| lua source or lua binary files. | ||||
|  | ||||
| <p> | ||||
| The requires <em>bcel</em> to be on the class path, and the ClassLoader of JSE or CDC.   | ||||
|  | ||||
| <h1>3 - <a name="3">Concepts</a></h1> | ||||
|  | ||||
| <h2>Globals</h2> | ||||
| The old notion of platform has been replaced with creation of globals.  | ||||
| Two classes are provided to encapsulate common combinations of libraries.   | ||||
|  | ||||
| <h3>JsePlatform</h3> | ||||
|  | ||||
| This class can be used as a factory for globals in a typical Java SE application.  | ||||
| All standard libraries are included, as well as the luajava library.  | ||||
| The default search path is the current directory, | ||||
| and the math operations include all those supported by Java SE. | ||||
|  | ||||
| <h3>JmePlatform</h3> | ||||
|  | ||||
| This class can be used to set up the basic environment for a Java ME application. | ||||
| The default search path is limited to the jar resources, | ||||
| and the math operations are limited to those supported by Java ME. | ||||
| All libraries are included except luajava, and the os, io, and math libraries are  | ||||
| limited to those functions that can be supported on that platform. | ||||
|  | ||||
|  | ||||
| <h1>4 - <a name="4">Libraries</a></h1> | ||||
|  | ||||
| <h2>Standard Libraries</h2> | ||||
|  | ||||
| Libraries are coded to closely match the behavior specified in  | ||||
| See <a href="http://www.lua.org/manual/5.1/">standard lua documentation</a> for details on the library API's | ||||
|  | ||||
| <p> | ||||
| The following libraries are loaded by both <em>JsePlatform.standardGlobals()</em> and <em>JmePlatform.standardGlobals()</em>: | ||||
| <pre>	base | ||||
| 	coroutine | ||||
| 	io | ||||
| 	math | ||||
| 	os | ||||
| 	package | ||||
| 	string | ||||
| 	table | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| The <em>JsePlatform.standardGlobals()</em> globals also include: | ||||
| <pre>	luajava  | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| The <em>JsePlatform.debugGlobals()</em> and <em>JsePlatform.debugGlobals()</em> functions produce globals that include: | ||||
| <pre>	debug | ||||
| </pre> | ||||
|  | ||||
| <h3>I/O Library</h3> | ||||
| The implementation of the <em>io</em> library differs by platform owing to platform limitations. | ||||
|  | ||||
| <p> | ||||
| The <em>JmePlatform.standardGlobals()</em> instantiated the io library <em>io</em> in  | ||||
| <pre> | ||||
| 	src/jme/org/luaj/vm2/lib/jme/JmeIoLib.java | ||||
| </pre> | ||||
|  | ||||
| The <em>JsePlatform.standardGlobals()</em> includes support for random access and is in  | ||||
| <pre> | ||||
| 	src/jse/org/luaj/vm2/lib/jse/JseIoLib.java | ||||
| </pre> | ||||
|  | ||||
| <h3>OS Library</h3> | ||||
| The implementation of the <em>os</em> library also differs per platform. | ||||
|  | ||||
| <p> | ||||
| The basic <em>os</em> library implementation us used by <em>JmePlatform</em> and is in: | ||||
| <pre> | ||||
| 	src/core/org/luaj/lib/OsLib.java | ||||
| </pre> | ||||
|  | ||||
| A richer version for use by <em>JsePlatform</em> is :  | ||||
| <pre> | ||||
| 	src/jse/org/luaj/vm2/lib/jse/JseOsLib.java | ||||
| </pre> | ||||
|  | ||||
| Time is a represented as number of milliseconds since the epoch,  | ||||
| and most time and date formatting, locales, and other features  | ||||
| are not implemented. | ||||
|  | ||||
| <h3>Coroutine Library</h3> | ||||
| The <em>coroutine</em> library is implemented using one JavaThread per coroutine.    | ||||
| This allows <em>coroutine.yield()</em> can be called from anywhere,  | ||||
| as with the yield-from-anywhere patch in C-based lua.  | ||||
|  | ||||
| <p> | ||||
| Luaj uses WeakReferences and the OrphanedThread error to ensure that coroutines that are no longer referenced  | ||||
| are properly garbage collected.  For thread safety, OrphanedThread should not be caught by Java code.   | ||||
| See <a href="http://luaj.sourceforge.net/api/2.0/org/luaj/vm2/LuaThread.html">LuaThread</a> | ||||
| and <a href="http://luaj.sourceforge.net/api/2.0/org/luaj/vm2/OrphanedThread.html">OrphanedThread</a> | ||||
| javadoc for details.  | ||||
|  | ||||
| <h3>Debug Library</h3> | ||||
| The <em>debug</em> library is not included by default by  | ||||
| <em>JmePlatform.standardGlobals()</em> or <em>JsePlatform.standardGlobsls()</em> . | ||||
|  | ||||
| The functions <em>JmePlatform.debugGlobals()</em> and <em>JsePlatform.debugGlobsls()</em>  | ||||
| create globals that contain the debug library in addition to the other standard libraries.  | ||||
|  | ||||
| To install dynamically from lua use java-class-based require:</em>: | ||||
| <pre> | ||||
| 	require 'org.luaj.vm2.lib.DebugLib' | ||||
| </pre> | ||||
|  | ||||
| The <em>lua</em> command line utility includes the <em>debug</em> library by default. | ||||
|  | ||||
|  | ||||
| <h3>The Luajava Library</h3> | ||||
| The <em>JsePlatform.standardGlobals()</em> includes the <em>luajava</em> library, which simplifies binding to Java classes and methods.   | ||||
| It is patterned after the original <a href="http://www.keplerproject.org/luajava/">luajava project</a>. | ||||
|  | ||||
| <p> | ||||
| The following lua script will open a swing frame on Java SE: | ||||
| <pre> | ||||
| 	jframe = luajava.bindClass( "javax.swing.JFrame" ) | ||||
| 	frame = luajava.newInstance( "javax.swing.JFrame", "Texts" ); | ||||
| 	frame:setDefaultCloseOperation(jframe.EXIT_ON_CLOSE) | ||||
| 	frame:setSize(300,400) | ||||
| 	frame:setVisible(true) | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| See a longer sample in <em>examples/lua/swingapp.lua</em> for details, including a simple animation loop, rendering graphics, mouse and key handling, and image loading.  | ||||
| Or try running it using:  | ||||
| <pre> | ||||
| 	java -cp lib/luaj-jse-2.0.3.jar lua examples/lua/swingapp.lua | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| The Java ME platform does not include this library, and it cannot be made to work because of the lack of a reflection API in Java ME.  | ||||
|  | ||||
| <p> | ||||
| The <em>lua</em> connand line tool includes <em>luajava</em>.  | ||||
|  | ||||
| <h1>5 - <a name="5">LuaJ API</a></h1> | ||||
|  | ||||
| <h2>API Javadoc</h2> | ||||
| The javadoc for the main classes in the LuaJ API are on line at | ||||
| <pre> | ||||
| 	 <a href="http://luaj.sourceforge.net/api/2.0/index.html">http://luaj.sourceforge.net/api/2.0</a> | ||||
| </pre> | ||||
|  | ||||
| You can also build a local version from sources using  | ||||
| <pre> | ||||
| 	 ant doc | ||||
| </pre> | ||||
|  | ||||
| <h2>LuaValue and Varargs</h2> | ||||
| All lua value manipulation is now organized around  | ||||
| <a href="http://luaj.sourceforge.net/api/2.0/org/luaj/vm2/LuaValue.html">LuaValue</a> | ||||
| which exposes the majority of interfaces used for lua computation.   | ||||
| <pre> | ||||
| 	 <a href="http://luaj.sourceforge.net/api/2.0/org/luaj/vm2/LuaValue.html">org.luaj.vm2.LuaValue</a> | ||||
| </pre> | ||||
|  | ||||
| <h3>Common Functions</h3> | ||||
| <em>LuaValue</em> exposes functions for each of the operations in LuaJ.   | ||||
| Some commonly used functions and constants include: | ||||
| <pre> | ||||
| 	call();               // invoke the function with no arguments | ||||
| 	call(LuaValue arg1);  // call the function with 1 argument | ||||
| 	invoke(Varargs arg);  // call the function with variable arguments, variable return values | ||||
| 	get(int index);       // get a table entry using an integer key | ||||
| 	get(LuaValue key);    // get a table entry using an arbitrary key, may be a LuaInteger | ||||
| 	rawget(int index);    // raw get without metatable calls | ||||
| 	valueOf(int i);       // return LuaValue corresponding to an integer | ||||
| 	valueOf(String s);    // return LuaValue corresponding to a String | ||||
| 	toint();              // return value as a Java int | ||||
| 	tojstring();          // return value as a Java String | ||||
| 	isnil();              // is the value nil | ||||
| 	NIL;                  // the value nil | ||||
| 	NONE;                 // a Varargs instance with no values	  | ||||
| </pre> | ||||
|  | ||||
| <h2>Varargs</h2> | ||||
| The interface <a href="http://luaj.sourceforge.net/api/2.0/org/luaj/vm2/Varargs.html">Varargs</a> provides an abstraction for  | ||||
| both a variable argument list and multiple return values.   | ||||
| For convenience, <em>LuaValue</em> implements <em>Varargs</em> so a single value can be supplied anywhere  | ||||
| variable arguments are expected.       | ||||
| <pre> | ||||
| 	 <a href="http://luaj.sourceforge.net/api/2.0/org/luaj/vm2/Varargs.html">org.luaj.vm2.Varargs</a> | ||||
| </pre> | ||||
|  | ||||
| <h3>Common Functions</h3> | ||||
| <em>Varargs</em> exposes functions for accessing elements, and coercing them to specific types: | ||||
| <pre> | ||||
| 	narg();                 // return number of arguments | ||||
| 	arg1();                 // return the first argument | ||||
| 	arg(int n);             // return the nth argument | ||||
| 	isnil(int n);           // true if the nth argument is nil | ||||
| 	checktable(int n);      // return table or throw error | ||||
| 	optlong(int n,long d);  // return n if a long, d if no argument, or error if not a long | ||||
| </pre> | ||||
|   | ||||
| See the <a href="http://luaj.sourceforge.net/api/2.0/org/luaj/vm2/Varargs.html">Varargs</a> API for a complete list. | ||||
|   | ||||
| <h2>LibFunction</h2> | ||||
| The simplest way to implement a function is to choose a base class based on the number of arguments to the function. | ||||
| LuaJ provides 5 base classes for this purpose, depending if the function has 0, 1, 2, 3 or variable arguments,  | ||||
| and if it provide multiple return values.    | ||||
| <pre> | ||||
| 	 <a href="http://luaj.sourceforge.net/api/2.0/org/luaj/vm2/lib/ZeroArgFunction.html">org.luaj.vm2.lib.ZeroArgFunction</a> | ||||
| 	 <a href="http://luaj.sourceforge.net/api/2.0/org/luaj/vm2/lib/OneArgFunction.html">org.luaj.vm2.lib.OneArgFunction</a> | ||||
| 	 <a href="http://luaj.sourceforge.net/api/2.0/org/luaj/vm2/lib/TwoArgFunction.html">org.luaj.vm2.lib.TwoArgFunction</a> | ||||
| 	 <a href="http://luaj.sourceforge.net/api/2.0/org/luaj/vm2/lib/ThreeArgFunction.html">org.luaj.vm2.lib.ThreeArgFunction</a> | ||||
| 	 <a href="http://luaj.sourceforge.net/api/2.0/org/luaj/vm2/lib/VarArgFunction.html">org.luaj.vm2.lib.VarArgFunction</a> | ||||
| </pre> | ||||
|  | ||||
| Each of these functions has an abstract method that must be implemented,  | ||||
| and argument fixup is done automatically by the classes as each Java function is invoked. | ||||
|  | ||||
| <p> | ||||
| For example, to implement a "hello, world" function, we could supply: | ||||
| <pre> | ||||
| 	pubic class hello extends ZeroArgFunction { | ||||
| 		public LuaValue call() { | ||||
| 			env.get("print").call(valueOf("hello, world")); | ||||
| 		} | ||||
| 	} | ||||
| </pre> | ||||
|  | ||||
| The value <em>env</em> is the environment of the function, and is normally supplied  | ||||
| by the instantiating object whenever default loading is used.  | ||||
|  | ||||
| <p> | ||||
| Calling this function from lua could be done by: | ||||
| <pre>  | ||||
| 	require( 'hello' )() | ||||
| </pre> | ||||
|  | ||||
| while calling this function from Java would look like: | ||||
| <pre>  | ||||
| 	new hello().call(); | ||||
| </pre> | ||||
|  | ||||
| Note that in both the lua and Java case, extra arguments will be ignored, and the function will be called.   | ||||
| Also, no virtual machine instance is necessary to call the function.  | ||||
| To allow for arguments, or return multiple values, extend one of the other base classes.  | ||||
|   | ||||
| <h2>Closures</h2> | ||||
| Closures still exist in this framework, but are optional, and are only used to implement lua bytecode execution.   | ||||
|  | ||||
| <h1>6 - <a name="6">Parser</a></h1> | ||||
|  | ||||
| <h2>Javacc Grammar</h2> | ||||
| A Javacc grammarwas developed to simplify the creation of Java-based parsers for the lua language. | ||||
| The grammar is specified for <a href="https://javacc.dev.java.net/">javacc version 5.0</a> because that tool generates standalone  | ||||
| parsers that do not require a separate runtime.      | ||||
|  | ||||
| <p> | ||||
| A plain undecorated grammer that can be used for validation is available in <a href="grammar/Lua51.jj">grammar/Lua51.jj</a> | ||||
| while a grammar that generates a typed parse tree is in  <a href="grammar/LuaParser.jj">grammar/LuaParser.jj</a> | ||||
|  | ||||
| <h2>Creating a Parse Tree from Lua Source</h2> | ||||
| The default lu compiler does a single-pass compile of lua source to lua bytecode, so no explicit parse tree is produced.   | ||||
|  | ||||
| <p> | ||||
| To simplify the creation of abstract syntax trees from lua sources, the LuaParser class is generated as part of the JME build.   | ||||
| To use it, provide an input stream, and invoke the root generator, which will return a Chunk if the file is valid,  | ||||
| or throw a ParseException if there is a syntax error. | ||||
|  | ||||
| <p> | ||||
| For example, to parse a file and print all variable names, use code like: | ||||
| <pre> | ||||
| 	try { | ||||
| 		String file = "main.lua"; | ||||
| 		LuaParser parser = new LuaParser(new FileInputStream(file)); | ||||
| 		Chunk chunk = parser.Chunk(); | ||||
| 		chunk.accept( new Visitor() { | ||||
| 			public void visit(Exp.NameExp exp) { | ||||
| 				System.out.println("Name in use: "+exp.name.name); | ||||
| 			} | ||||
| 		} ); | ||||
| 	} catch ( ParseException e ) { | ||||
| 		System.out.println("parse failed: " + e.getMessage() + "\n" | ||||
| 			+ "Token Image: '" + e.currentToken.image + "'\n" | ||||
| 			+ "Location: " + e.currentToken.beginLine + ":" + e.currentToken.beginColumn  | ||||
| 			         + "-" + e.currentToken.endLine + "," + e.currentToken.endColumn); | ||||
| 	} | ||||
| </pre>  | ||||
| In luaj 2.0.3 error reporting was turned on in the parser so line numbers are avaiable for most parse exceptions. | ||||
| This example may be found in | ||||
| <pre> | ||||
| 	examples/jse/SampleParser.java | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| See the <a href="http://luaj.sourceforge.net/api/2.0/org/luaj/vm2/ast/package-summary.html">org.luaj.vm2.ast package</a> javadoc for the API relating to the syntax tree that is produced.  | ||||
|  | ||||
| <h1>7 - <a name="7">Building and Testing</a></h1> | ||||
|  | ||||
| <h2>Building the jars</h2> | ||||
| An ant file is included in the root directory which builds the libraries by default. | ||||
|  | ||||
| <p> | ||||
| Other targets exist for creating distribution file an measuring code coverage of unit tests. | ||||
|  | ||||
| <h2>Unit tests</h2> | ||||
|  | ||||
| <p> | ||||
| The main luaj JUnit tests are organized into a JUnit 3 suite: | ||||
| <pre> | ||||
| 	test/junit/org/luaj/vm2/AllTests.lua | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| Unit test scripts can be found in these locations | ||||
| <pre> | ||||
| 	test/lua/*.lua | ||||
| 	test/junit/org/luaj/vm2/compiler/lua5.1-tests.zip | ||||
| 	test/junit/org/luaj/vm2/compiler/regressions.zip | ||||
| 	test/junit/org/luaj/vm2/vm1/luajvm1-tests.zip | ||||
| </pre> | ||||
|  | ||||
| <h2>Code coverage</h2> | ||||
|  | ||||
| <p> | ||||
| A build script for running unit tests and producing code coverage statistics is in  | ||||
| <pre> | ||||
| 	build-coverage.xml | ||||
| </pre> | ||||
|  | ||||
| It relies on the cobertura code coverage library. | ||||
|  | ||||
| <h1>8 - <a name="8">Downloads</a></h1> | ||||
|  | ||||
| <h2>Downloads and Project Pages</h2> | ||||
| Downloads for all version available on SourceForge or LuaForge.   | ||||
| Sources are hosted on SourceForge and available via sourceforge.net     | ||||
| <br/> | ||||
| <pre> | ||||
| 	<a href="http://luaj.sourceforge.net/">SourceForge Luaj Project Page</a> | ||||
| 	<a href="http://sourceforge.net/project/platformdownload.php?group_id=197627">SourceForge Luaj Download Area</a> | ||||
| </pre> | ||||
| <p/> | ||||
| and LuaForge: | ||||
| <pre> | ||||
| 	<a href="http://luaforge.net/projects/luaj/">LuaForge Luaj Project Page</a> | ||||
| 	<a href="http://luaforge.net/frs/?group_id=457">LuaForge Luaj Project Area</a> | ||||
| </pre> | ||||
|  | ||||
| <h1>9 - <a name="9">Release Notes</a></h1> | ||||
|  | ||||
| <h2>Main Changes by Version</h2> | ||||
| <table cellspacing="10"><tr><td><table cellspacing="4"> | ||||
| <tr valign="top"><td>  <b>2.0</b></td><td><ul> | ||||
| <li>Initial release of 2.0 version </li>   | ||||
| </ul></td></tr> | ||||
| <tr valign="top"><td>  <b>2.0.1</b></td><td><ul> | ||||
| <li>Improve correctness of singleton construction related to static initialization </li> | ||||
| <li>Fix nan-related error in constant folding logic that was failing on some JVMs </li> | ||||
| <li>JSR-223 fixes: add META-INF/services entry in jse jar, improve bindings implementation </li> | ||||
| </ul></td></tr> | ||||
| <tr valign="top"><td>  <b>2.0.2</b></td><td><ul> | ||||
| <li>JSR-223 bindings change: non Java-primitives will now be passed as LuaValue </li>  | ||||
| <li>JSR-223 enhancement: allow both ".lua" and "lua" as extensions in getScriptEngine() </li> | ||||
| <li>JSR-223 fix: use system class loader to support using luaj as JRE extension </li> | ||||
| <li>Improve selection logic when binding to overloaded functions using luajava</li> | ||||
| <li>Enhance javadoc, put it <a href="docs/api/index.html">in distribution</a> and <a href="http://luaj.sourceforge.net/api/2.0/index.html">on line</a></li> | ||||
| <li>Major refactor of luajava type coercion logic, improve method selection.</li>  | ||||
| <li>Add lib/luaj-sources-2.0.2.jar for easier integration into an IDE such as Netbeans </li> | ||||
| <tr valign="top"><td>  <b>2.0.3</b></td><td><ul> | ||||
| <li>Improve coroutine state logic including let unreferenced coroutines be garbage collected </li> | ||||
| <li>Fix lua command vararg values passed into main script to match what is in global arg table </li> | ||||
| <li>Add arithmetic metatag processing when left hand side is a number and right hand side has metatable </li> | ||||
| <li>Fix load(func) when mutiple string fragments are supplied by calls to func </li> | ||||
| <li>Allow access to public members of private inner classes where possible </li> | ||||
| <li>Turn on error reporting in LuaParser so line numbers ar available in ParseException </li> | ||||
| <li>Improve compatibility of table.remove() </li> | ||||
| <li>Disallow base library setfenv() calls on Java functions </li> | ||||
| </ul></td></tr> | ||||
| </table></td></tr></table> | ||||
|  | ||||
| <h2>Known Issues</h2> | ||||
| <ul> | ||||
| <li>debug code may not be completely removed by some obfuscators | ||||
| <li>tail calls are not tracked in debug information | ||||
| <li>using both version 1 and 2 libraries together in the same java vm has not been tested | ||||
| <li>module() and setfenv() only partially supported for lau2java or luajc compiled lua | ||||
| <li>values associated with weak keys may linger longer than expected | ||||
| <li>behavior of luaj when a SecurityManager is used has not been fully characterized | ||||
| </ul> | ||||
|  | ||||
| @@ -1,119 +0,0 @@ | ||||
| <project default="all" xmlns:artifact="antlib:org.apache.maven.artifact.ant"> | ||||
| 	<!--  | ||||
| 	Run code coverage for unit tests on the luaj vm and libraries. | ||||
| 	--> | ||||
|  | ||||
| 	<property name="classes.dir" value="build/classes-debug" /> | ||||
| 	<property name="instrumented.dir" value="build/instrumented" /> | ||||
| 	<property name="reports.xml.dir" value="build/reports-junit-xml" /> | ||||
| 	<property name="reports.html.dir" value="build/reports-junit-html" /> | ||||
| 	<property name="coverage.xml.dir" value="build/reports-coverage-xml" /> | ||||
| 	<property name="coverage.html.dir" value="build/reports-coverage-html" /> | ||||
| 	<property name="cobertura.serfile" value="cobertura.ser" /> | ||||
| 	<property name="cobertura.logfile" value="cobertura.log" /> | ||||
|  | ||||
| 	<artifact:dependencies filesetId="cobutura.fileset"> | ||||
| 		<dependency groupId="net.sourceforge.cobertura" artifactId="cobertura" version="1.9.4.1"/> | ||||
| 		<dependency groupId="junit" artifactId="junit" version="3.8.1"/> | ||||
| 	</artifact:dependencies> | ||||
| 	 | ||||
| 	<path id="cobertura.classpath"> | ||||
| 		<fileset refid="cobutura.fileset" /> | ||||
| 	</path> | ||||
| 	 | ||||
| 	<taskdef classpathref="cobertura.classpath" resource="tasks.properties" /> | ||||
| 	 | ||||
| 	<import file="wtk.xml"/> | ||||
| 	 | ||||
| 	<property environment="env"/> | ||||
|  | ||||
| 	<target name="clean" description="Remove all files created by the build/test process."> | ||||
| 		<delete dir="${classes.dir}" failonerror="yes"/> | ||||
| 		<delete dir="${instrumented.dir}" failonerror="yes"/> | ||||
| 		<delete file="${cobertura.logfile}" /> | ||||
| 		<delete file="${cobertura.serfile}" /> | ||||
| 	</target> | ||||
|  | ||||
| 	<target name="init"> | ||||
| 		<ant antfile="build.xml" target="bcel-lib"/> | ||||
| 		<ant antfile="build.xml" target="luaj1-lib"/> | ||||
| 		<mkdir dir="${classes.dir}" /> | ||||
| 		<mkdir dir="${instrumented.dir}" /> | ||||
| 		<mkdir dir="${reports.xml.dir}" /> | ||||
| 		<mkdir dir="${reports.html.dir}" /> | ||||
| 		<mkdir dir="${coverage.xml.dir}" /> | ||||
| 		<mkdir dir="${coverage.html.dir}" /> | ||||
| 	</target> | ||||
|  | ||||
| 	<target name="compile" depends="init,wtk-or-fail"> | ||||
| 		<javac destdir="${classes.dir}" debug="yes" target="1.5"> | ||||
| 			<classpath refid="cobertura.classpath" /> | ||||
| 		    <classpath refid="wtk-libs" /> | ||||
| 		    <classpath path="lib/bcel-5.2.jar" /> | ||||
| 		    <src path="src/core"/> | ||||
| 		    <src path="src/jme"/> | ||||
| 		    <src path="src/jse"/> | ||||
| 		    <src path="test/junit"/> | ||||
| 		</javac> | ||||
| 	</target> | ||||
|  | ||||
| 	<target name="instrument" depends="compile"> | ||||
| 		<delete file="${cobertura.serfile}"/> | ||||
| 		<delete dir="${instrumented.dir}" failonerror="no"/> | ||||
| 		<cobertura-instrument datafile="${cobertura.serfile}" todir="${instrumented.dir}"> | ||||
| 			<fileset dir="${classes.dir}"> | ||||
| 				<include name="org/luaj/vm2/*.class" /> | ||||
| 				<include name="org/luaj/vm2/lib/*.class" /> | ||||
| 				<include name="org/luaj/vm2/lib/jse/*.class" /> | ||||
| 				<include name="org/luaj/vm2/lib/jme/*.class" /> | ||||
| 				<include name="org/luaj/vm2/compiler/*.class" /> | ||||
| 				<include name="org/luaj/vm2/luajc/*.class" /> | ||||
| 				<include name="org/luaj/vm2/lua2java/*.class" /> | ||||
| 				<include name="org/luaj/vm2/parser/*.class" /> | ||||
| 				<include name="org/luaj/vm2/ast/*.class" /> | ||||
| 				<exclude name="**/*Test*.class" /> | ||||
| 			</fileset> | ||||
| 		</cobertura-instrument> | ||||
| 	</target> | ||||
|  | ||||
| 	<target name="test"> | ||||
| 		<junit fork="yes" dir="${basedir}" showoutput="yes"> | ||||
|      		<sysproperty key="net.sourceforge.cobertura.serfile"  | ||||
|      			file="${basedir}/${cobertura.serfile}" />		     | ||||
| 			<classpath location="${instrumented.dir}" /> | ||||
| 			<classpath location="${classes.dir}" /> | ||||
| 			<classpath refid="cobertura.classpath" /> | ||||
| 			<classpath location="test/lua" /> | ||||
| 			<classpath location="test/junit/org/luaj/vm2/compiler" /> | ||||
| 			<classpath location="test/junit/org/luaj/vm2/vm1" /> | ||||
| 		    <classpath path="lib/bcel-5.2.jar" /> | ||||
| 			<formatter type="xml" /> | ||||
| 			<batchtest todir="${reports.xml.dir}"> | ||||
| 				<fileset dir="test/junit"> | ||||
| 					<include name="org/luaj/vm2/AllTests.java" /> | ||||
| 				</fileset> | ||||
| 			</batchtest> | ||||
| 		</junit> | ||||
| 		 | ||||
| 		<junitreport todir="${reports.xml.dir}"> | ||||
| 			<fileset dir="${reports.xml.dir}"> | ||||
| 				<include name="TEST-*.xml" /> | ||||
| 			</fileset> | ||||
| 			<report format="frames" todir="${reports.html.dir}" /> | ||||
| 		</junitreport> | ||||
| 	</target> | ||||
|  | ||||
| 	<target name="report"> | ||||
| 		<cobertura-report datafile="${cobertura.serfile}" destdir="${coverage.xml.dir}" format="xml" />  | ||||
| 		<cobertura-report datafile="${cobertura.serfile}" destdir="${coverage.html.dir}"> | ||||
| 			<fileset dir="src/core"/> | ||||
| 			<fileset dir="src/jse"/> | ||||
| 			<fileset dir="src/jme"/> | ||||
| 		</cobertura-report> | ||||
| 	</target> | ||||
|  | ||||
| 	<target name="coverage" depends="clean,init,compile,instrument,test,report"/> | ||||
|  | ||||
| 	<target name="all" depends="coverage" /> | ||||
| 	 | ||||
| </project> | ||||
| @@ -1,56 +0,0 @@ | ||||
| <project default="all-libs"> | ||||
|  | ||||
| 	<available file="lib/midpapi20.jar" property="midpapi.lib.exists"/> | ||||
| 	<available file="lib/bcel-5.2.jar" property="bcel.lib.exists"/>			 | ||||
| 	<available file="lib/javacc.jar" property="javacc.lib.exists"/>			 | ||||
| 	<available file="lib/proguard.jar" property="proguard.lib.exists"/>			 | ||||
| 	<available file="lib/antenna-bin-1.2.0-beta.jar" property="antenna.lib.exists"/>			 | ||||
| 	<available file="lib/junit.jar" property="junit.lib.exists"/> | ||||
| 	<available file="lib/cobertura.jar" property="cobertura.lib.exists"/> | ||||
| 	<available file="lib/microemulator.jar" property="microemulator.lib.exists"/> | ||||
|  | ||||
| 	<macrodef name="download"> | ||||
| 		<attribute name="zipname"/> | ||||
| 		<attribute name="jars" default="**/*.jar"/> | ||||
| 		<sequential> | ||||
| 			<mkdir dir="lib"/> | ||||
| 			<get src="http://luaj.sourceforge.net/lib/@{zipname}.tar.gz"  | ||||
| 				dest="lib/@{zipname}.tar.gz"/> | ||||
| 			<gunzip src="lib/@{zipname}.tar.gz" dest="lib/@{zipname}.tar"/> | ||||
| 			<untar src="lib/@{zipname}.tar" dest="lib" overwrite="true"> | ||||
| 			    <patternset> | ||||
| 			        <include name="@{jars}"/> | ||||
| 			    </patternset> | ||||
| 			    <mapper type="flatten"/> | ||||
| 			</untar> | ||||
| 	   </sequential> | ||||
| 	</macrodef> | ||||
|  | ||||
| 	<target name="wtk-libs" unless="midpapi.lib.exists"> | ||||
| 		<download zipname="wtk-2.5.2-api"/> | ||||
| 	</target> | ||||
| 	<target name="bcel-lib" unless="bcel.lib.exists"> | ||||
| 		<download zipname="/bcel-5.2"/> | ||||
| 	</target> | ||||
| 	<target name="javacc-lib" unless="javacc.lib.exists"> | ||||
| 		<download zipname="javacc-5.0"/> | ||||
| 	</target> | ||||
| 	<target name="proguard-lib" unless="proguard.lib.exists"> | ||||
| 		<download zipname="proguard4.6"/> | ||||
| 	</target> | ||||
| 	<target name="antenna-lib" unless="antenna.lib.exists"> | ||||
| 		<download zipname="antenna-bin-1.2.0-beta"/> | ||||
| 	</target> | ||||
| 	<target name="junit-lib" unless="junit.lib.exists"> | ||||
| 		<download zipname="junit-3.8.2"/> | ||||
| 	</target> | ||||
| 	<target name="cobertura-lib" unless="cobertura.lib.exists"> | ||||
| 		<download zipname="cobertura-1.9.4.1-bin"/> | ||||
| 	</target> | ||||
| 	<target name="microemulator-lib" unless="microemulator.lib.exists"> | ||||
| 		<download zipname="microemulator-2.0.4" jars="**/microemulator.jar"/> | ||||
| 	</target> | ||||
|  | ||||
| 	<target name="all-libs" depends="wtk-libs,bcel-lib,javacc-lib,proguard-lib,antenna-lib,junit-lib,cobertura-lib"/> | ||||
| 	 | ||||
| </project> | ||||
| @@ -1,172 +0,0 @@ | ||||
| <project default="all"> | ||||
| 	<property file="version.properties"/> | ||||
| 		 | ||||
| 	<property name="jar.name.jme" value="luaj-jme-${version}.jar"/> | ||||
| 	<property name="jar.name.jse" value="luaj-jse-${version}.jar"/> | ||||
| 	<property name="jar.name.sources" value="luaj-sources-${version}.jar"/> | ||||
|  | ||||
| 	<target name="clean"> | ||||
| 		<delete dir="build"/> | ||||
| 		<delete> | ||||
| 		    <fileset dir="." includes="luaj-*.jar"/> | ||||
| 		</delete> | ||||
| 	</target> | ||||
|  | ||||
| 	<import file="build-libs.xml"/> | ||||
|  | ||||
| 	<target name="parser" depends="javacc-lib"> | ||||
| 		<java classname="javacc" classpath="lib/javacc.jar"> | ||||
| 			<arg line="grammar/LuaParser.jj"/> | ||||
| 		</java> | ||||
| 	</target> | ||||
| 		 | ||||
| 	<target name="compile" depends="wtk-libs,bcel-lib"> | ||||
| 		<delete dir="build/jme/src"/> | ||||
| 		<delete dir="build/jse/src"/> | ||||
| 		<mkdir dir="build/jme/src"/> | ||||
| 		<mkdir dir="build/jse/src"/> | ||||
| 		<mkdir dir="build/jme/classes"/> | ||||
| 		<mkdir dir="build/jse/classes"/> | ||||
| 		<copy todir="build/jme/src"> | ||||
| 			<fileset dir="src/core"/> | ||||
| 			<fileset dir="src/jme"/> | ||||
| 			<filterchain> | ||||
| 				<tokenfilter><replacestring from='"Luaj 0.0"' to='"Luaj-jme ${version}"'/></tokenfilter> | ||||
| 			</filterchain> | ||||
| 		</copy> | ||||
| 		<copy todir="build/jse/src"> | ||||
| 			<fileset dir="src/core"/> | ||||
| 			<filterchain> | ||||
| 				<tokenfilter><replacestring from='"Luaj 0.0"' to='"Luaj-jse ${version}"'/></tokenfilter> | ||||
| 			</filterchain> | ||||
| 		</copy> | ||||
| 		<copy todir="build/jse/src"> | ||||
| 			<fileset dir="src/jse"/> | ||||
| 			<filterchain> | ||||
| 				<tokenfilter><replacestring from='<String>' to=''/></tokenfilter> | ||||
| 				<tokenfilter><replacestring from='<Stat>' to=''/></tokenfilter> | ||||
| 				<tokenfilter><replacestring from='<Exp>' to=''/></tokenfilter> | ||||
| 				<tokenfilter><replacestring from='<Name>' to=''/></tokenfilter> | ||||
| 				<tokenfilter><replacestring from='<Block>' to=''/></tokenfilter> | ||||
| 				<tokenfilter><replacestring from='<TableField>' to=''/></tokenfilter> | ||||
| 				<tokenfilter><replacestring from='<VarExp>' to=''/></tokenfilter> | ||||
| 				<tokenfilter><replacestring from='<Exp.VarExp>' to=''/></tokenfilter> | ||||
| 				<tokenfilter><replacestring from='<Object,String>' to=''/></tokenfilter> | ||||
| 				<tokenfilter><replacestring from='<Double,String>' to=''/></tokenfilter> | ||||
| 				<tokenfilter><replacestring from='<Integer,Integer>' to=''/></tokenfilter> | ||||
| 				<tokenfilter><replacestring from='<Exp,Integer>' to=''/></tokenfilter> | ||||
| 				<tokenfilter><replacestring from='<String,byte[]>' to=''/></tokenfilter> | ||||
| 				<tokenfilter><replacestring from='<String,Variable>' to=''/></tokenfilter> | ||||
| 				<tokenfilter><replacestring from='<LuaValue,String>' to=''/></tokenfilter> | ||||
| 				<tokenfilter><replacestring from='<LuaString,String>' to=''/></tokenfilter> | ||||
| 			</filterchain> | ||||
| 		</copy> | ||||
| 		<path id="wtk-libs"> | ||||
| 			<pathelement path="lib/cldcapi11.jar"/> | ||||
| 			<pathelement path="lib/midpapi20.jar"/> | ||||
| 			<pathelement path="lib/mmapi.jar"/> | ||||
| 		</path> | ||||
| 		<javac destdir="build/jme/classes" encoding="utf-8" source="1.3" target="1.2" bootclasspathref="wtk-libs" | ||||
| 			srcdir="build/jme/src"/> | ||||
| 		<javac destdir="build/jse/classes" encoding="utf-8" source="1.3" target="1.3" | ||||
| 			classpath="lib/bcel-5.2.jar" | ||||
| 			srcdir="build/jse/src" | ||||
| 			excludes="**/script/*,**/Lua2Java*,lua*"/> | ||||
| 		<javac destdir="build/jse/classes" encoding="utf-8" source="1.5" target="1.5" | ||||
| 			classpath="build/jse/classes" | ||||
| 			srcdir="build/jse/src" | ||||
| 			includes="**/script/*,**/Lua2Java*"/> | ||||
| 		<javac destdir="build/jse/classes" encoding="utf-8" source="1.3" target="1.3" | ||||
| 			classpath="build/jse/classes" | ||||
| 			srcdir="build/jse/src" | ||||
| 			includes="lua*"/> | ||||
| 	</target> | ||||
| 	 | ||||
| 	<target name="jar-jme" depends="compile"> | ||||
| 		<jar destfile="${jar.name.jme}" basedir="build/jme/classes"/> | ||||
| 	</target> | ||||
| 	 | ||||
| 	<target name="jar-jse" depends="compile"> | ||||
| 		<jar destfile="${jar.name.jse}"> | ||||
| 		    <fileset dir="build/jse/classes"/> | ||||
| 		    <fileset dir="src/jse/"> | ||||
| 				<include name="META-INF/services/**"/> | ||||
| 		    </fileset> | ||||
| 		</jar> | ||||
| 	</target> | ||||
|  | ||||
| 	<target name="jar-jse-sources" depends="compile"> | ||||
| 		<jar destfile="${jar.name.sources}"> | ||||
| 		    <fileset dir="build/jme/src"/> | ||||
| 		    <fileset dir="build/jse/src"/> | ||||
| 		</jar> | ||||
| 	</target> | ||||
|  | ||||
| 	<target name="doc"> | ||||
| 		<delete dir="docs/api"/> | ||||
| 		<mkdir dir="docs/api"/> | ||||
| 		<javadoc defaultexcludes="yes" | ||||
| 				destdir="docs/api" | ||||
| 				author="true" | ||||
| 				version="true" | ||||
| 				use="true" | ||||
| 				windowtitle="Luaj API"> | ||||
| 		    <fileset dir="src/core" defaultexcludes="yes" includes="org/luaj/vm2/*.java,org/luaj/vm2/compiler/LuaC.java,org/luaj/vm2/lib/*.java"/> | ||||
| 		    <fileset dir="src/jse" defaultexcludes="yes" includes="org/luaj/vm2/lib/jse/*.java,org/luaj/vm2/luajc/LuaJC.java"/> | ||||
| 		    <fileset dir="src/jme" defaultexcludes="yes" includes="org/luaj/vm2/lib/jme/*.java"/> | ||||
| 			<doctitle><![CDATA[<h1>Luaj API</h1>]]></doctitle> | ||||
| 			<bottom><![CDATA[<i>Copyright © 2007-2008 Luaj.org. All Rights Reserved.</i>]]></bottom> | ||||
| 			<tag name="todo" scope="all" description="To do:"/> | ||||
| 			<group title="Core VM" packages="org.luaj.vm.*"/> | ||||
| 			<link offline="true" href="http://sourceforge.net/projects/luaj/" packagelistLoc="C:\tmp"/> | ||||
| 			<link href="http://sourceforge.net/projects/luaj/"/> | ||||
| 		</javadoc> | ||||
| 	</target> | ||||
| 	 | ||||
| 	<target name="dist" depends="all,doc"> | ||||
| 		<delete dir="build/luaj-${version}"/> | ||||
| 		<mkdir dir="build/luaj-${version}/src"/> | ||||
| 		<mkdir dir="build/luaj-${version}/lib"/> | ||||
| 		<copy todir="build/luaj-${version}/src"> | ||||
| 		    <fileset dir="src"> | ||||
| 				<exclude name="src/test/**"/> | ||||
| 				<exclude name="**/antlr/**"/> | ||||
| 				<exclude name="**/lst/**"/> | ||||
| 				<exclude name="**/JavaCodeGenerator.java"/> | ||||
| 				<exclude name="**/LuaJCompiler.java"/> | ||||
| 		    </fileset> | ||||
| 		</copy> | ||||
| 		<copy todir="build/luaj-${version}/test"> | ||||
| 		    <fileset dir="test"/> | ||||
| 		</copy> | ||||
| 		<copy todir="build/luaj-${version}/examples"> | ||||
| 		    <fileset dir="examples"/> | ||||
| 		</copy> | ||||
| 		<copy todir="build/luaj-${version}/lib"> | ||||
| 		    <fileset dir="."> | ||||
| 				<include name="*-${version}.jar"/> | ||||
| 		    </fileset>		 | ||||
| 		</copy> | ||||
| 		<copy todir="build/luaj-${version}"> | ||||
| 		    <fileset dir="."> | ||||
| 				<include name="build.xml"/> | ||||
| 				<include name="build-libs.xml"/> | ||||
| 				<include name="build-coverage.xml"/> | ||||
| 				<include name="version.properties"/> | ||||
| 				<include name="wtk.xml"/> | ||||
| 				<include name="README.html"/> | ||||
| 				<include name="names.csv"/> | ||||
| 				<include name=".classpath"/> | ||||
| 				<include name=".project"/> | ||||
| 		    </fileset>		 | ||||
| 		</copy> | ||||
| 		<copy todir="build/luaj-${version}/docs"> | ||||
| 			<fileset dir="docs"/> | ||||
| 		</copy> | ||||
| 		<zip destfile="luaj-${version}.zip"  | ||||
| 			basedir="build" includes="luaj-${version}/**"/> | ||||
| 	</target> | ||||
| 	 | ||||
| 	<target name="all" depends="clean,jar-jme,jar-jse,jar-jse-sources"/> | ||||
| 		 | ||||
| </project> | ||||
| @@ -1,89 +0,0 @@ | ||||
| LuaValue Consructors,,Return type,,,,,,,,,, | ||||
| ,valueOf(boolean),LuaBoolean,,,,,,,,,, | ||||
| ,valueOf(null),LuaNil,,,,,,,,,, | ||||
| ,valueOf(int) ,LuaInteger,,,,,,,,,, | ||||
| ,valueOf(double),LuaNumber,,,,,,,,,, | ||||
| ,valueOf(long),LuaNumber,,,,,,,,,, | ||||
| ,valueOf(String),LuaString,,,,,,,,,, | ||||
| ,tableOf(...),LuaTable,,,,,,,,,, | ||||
| ,listOf(LuaValue[]),LuaTable,,,,,,,,,, | ||||
| ,userdataOf(Object),LuaUserdata,,,,,,,,,, | ||||
| ,"uerdataOf(Object,Value)",LuaUserdata,,,,,,,,,, | ||||
| ,,,,,,,Arugment type,,,,, | ||||
| ,,,LuaBoolean,LuaClosure,LuaFunction,LuaDouble,LuaInteger,LuaNil,LuaString,LuaTable,LuaThread,LuaUserdata | ||||
| Type Check Functions,,,,,,,,,,,, | ||||
| ,isboolean,boolean,TRUE,f,f,f,f,f,f,f,f,f | ||||
| ,isclosure,boolean,f,TRUE,f,f,f,f,f,f,f,f | ||||
| ,isfunction,boolean,f,TRUE,TRUE,f,f,f,f,f,f,f | ||||
| ,isint,boolean,f,f,f,f,TRUE,f,true | f,f,f,f | ||||
| ,isinttype,boolean,f,f,f,f,TRUE,f,f,f,f,f | ||||
| ,isnumber,boolean,f,f,f,TRUE,TRUE,f,true | f,f,f,f | ||||
| ,islong,boolean,f,f,f,true | f,TRUE,f,true | f,f,f,f | ||||
| ,isnil,boolean,f,f,f,f,f,TRUE,f,f,f,f | ||||
| ,isstring,boolean,f,f,f,true | f,TRUE,f,TRUE,f,f,f | ||||
| ,istable,boolean,f,f,f,f,f,f,f,TRUE,f,f | ||||
| ,isthread,boolean,f,f,f,f,f,f,f,f,TRUE,f | ||||
| ,isuserdata,boolean,f,f,f,f,f,f,f,f,f,TRUE | ||||
| ,isuserdata(Class c),boolean,f,f,f,f,f,f,f,f,f,true | f | ||||
|  | ||||
|  | ||||
| Java Type Coercion Functions,,,,,,,,,,,, | ||||
| ,toboolean,boolean,this.v,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE | ||||
| ,tobyte,byte,0,0,0,0,this.v | 0,0,this.v | 0,0,0,0 | ||||
| ,tochar,char,0,0,0,0,this.v | 0,0,this.v | 0,0,0,0 | ||||
| ,todouble,double,0,0,0,this.v,this.v,0,this.v | 0,0,0,0 | ||||
| ,tofloat,float,0,0,0,this.v | 0,this.v,0,this.v | 0,0,0,0 | ||||
| ,toint,int,0,0,0,0,this.v,0,this.v | 0,0,0,0 | ||||
| ,tolong,long,0,0,0,0,this.v,0,this.v | 0,0,0,0 | ||||
| ,toshort,short,0,0,0,0,this.v | 0,0,this.v | 0,0,0,0 | ||||
| ,tojstring,String,"""true""|""false""","""closure: x""","""name""",(str) this.v,(str) this.v,"""nil""",this.v,"""table: x""","""thread: x""","""userdata: x""" | ||||
| ,touserdata,Object,null,null,null,null,null,null,null,null,this,this.instance | ||||
|  | ||||
| ,,,LuaBoolean,LuaClosure,LuaFunction,LuaDouble,LuaInteger,LuaNil,LuaString,LuaTable,LuaThread,LuaUserdata | ||||
| Optional Argument Conversion Functions,,,,,,,,,,,, | ||||
| ,optboolean,boolean,this,e,e,e,e,defval,e,e,e,e | ||||
| ,optclosure,LuaClosure,n,this,e,e,e,defval,e,e,e,e | ||||
| ,optdouble,double,e,e,e,this,this,defval,this | e,e,e,e | ||||
| ,optfunction,LuaFunction,n,this,this,e,e,defval,e,e,e,e | ||||
| ,optint,int,e,e,e,(int) this,this,defval,this | e,e,e,e | ||||
| ,optinteger,LuaInteger,e,e,e,(int) this,this,defval,this | e,e,e,e | ||||
| ,optlong,long,e,e,e,(long) this,this,defval,this | e,e,e,e | ||||
| ,optnumber,LuaNumber,e,e,e,this,this,defval,this | e,e,e,e | ||||
| ,optjstring,String,e,e,e,(str) this.v,(str) this.v,defval,this,e,e,e | ||||
| ,optstring,LuaString,e,e,e,(str) this.v,(str) this.v,defval,this,e,e,e | ||||
| ,opttable,LuaTable,e,e,e,e,e,defval,e,this,e,e | ||||
| ,optthread,LuaThread,e,e,e,e,e,defval,e,e,this,n | ||||
| ,optuserdata,Object,e,e,e,e,e,defval,e,e,e,instance | ||||
| ,optuserdata(Class c),Object,e,e,e,e,e,defval,e,e,e,instance | e | ||||
|  | ||||
| Required Argument Conversion Functions,,,,,,,,,,,, | ||||
| ,checkboolean,boolean,this,e,e,e,e,e,e,e,e,e | ||||
| ,checkclosure,LuaClosure,e,this,e,e,e,e,e,e,e,e | ||||
| ,checkdouble,double,e,e,e,this,this,e,e,e,e,e | ||||
| ,checkfunction,LuaFunction,e,this,this,e,e,e,e,e,e,e | ||||
| ,checkint,int,e,e,e,this | e,this,e,e,e,e,e | ||||
| ,checkinteger,LuaInteger,e,e,e,e,this,e,e,e,e,e | ||||
| ,checklong,LuaNumber,e,e,e,this | e,this,e,e,e,e,e | ||||
| ,checknumber,LuaNumber,e,e,e,this,this,e,e,e,e,e | ||||
| ,checkjstring,String,e,e,e,(str) this.v,(str) this.v,e,(str) this.v,e,e,e | ||||
| ,checkstring,LuaString,e,e,e,(str) this.v,(str) this.v,e,this,e,e,e | ||||
| ,checktable,LuaTable,e,e,e,e,e,e,e,this,e,e | ||||
| ,checkthread,LuaThread,e,e,e,e,e,e,e,e,this,e | ||||
| ,checkuserdata,Object,e,e,e,e,e,e,e,e,e,instance | ||||
| ,checkuserdata(Class c),Object,e,e,e,e,e,e,e,e,e,instance | e | ||||
| ,checkvalue,LuaValue,this,this,this,this,this,e,this,this,this,this | ||||
|  | ||||
| ,,,LuaBoolean,LuaClosure,LuaFunction,LuaDouble,LuaInteger,LuaNil,LuaString,LuaTable,LuaThread,LuaUserdata | ||||
| Lua Language Operations,,,,,,,,,,,, | ||||
| ,type,int,TBOOLEAN,TFUNCTION,TFUNCTION,TNUMBER,TNUMBER,TNIL,TSTRING,TTABLE,TTHREAD,TUSERDATA | ||||
| ,typename,string,"""boolean""","""function""","""function""","""number""","""number""","""nil""","""string""","""table""","""thread""","""userdata""" | ||||
| ,len,LuaInteger,e,e,e,e,e,e,#v,#v,e,e | ||||
| ,length,int,e,e,e,e,e,e,#v,#v,e,e | ||||
| ,getmetatable,LuaValue,static,static,static,static,static,static,static,instance,static ,instance | ||||
| ,setmetatable,LuaValue,e,e,e,e,e,e,e,instance,e,instance | ||||
| ,getfenv,LuaTable,e,instance,instance,e,e,e,e,e,instance,e | ||||
| ,setfenv,LuaFunction,e,instance,instance,e,e,e,e,e,instance,e | ||||
| ,call,LuaValue,__call,call,call,__call,__call,__call,__call,__call,__call,__call | ||||
| ,invoke,Varargs,__call,call,call,__call,__call,__call,__call,__call,__call,__call | ||||
| ,get,LuaValue,__index,__index,__index,__index,__index,__index,__index,get,__index,__index | ||||
| ,set,LuaValue,__newindex,__newindex,__newindex,__newindex,__newindex,__newindex,__newindex,set,__newindex,__newindex | ||||
| 
 | 
| @@ -1,260 +0,0 @@ | ||||
| /******************************************************************************* | ||||
|  * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * String buffer for use in string library methods, optimized for production  | ||||
|  * of StrValue instances. | ||||
|  * <p> | ||||
|  * The buffer can begin initially as a wrapped {@link LuaValue}  | ||||
|  * and only when concatenation actually occurs are the bytes first copied. | ||||
|  * <p>  | ||||
|  * To convert back to a {@link LuaValue} again,  | ||||
|  * the function {@link Buffer#value()} is used. | ||||
|  * @see LuaValue | ||||
|  * @see LuaValue#buffer() | ||||
|  * @see LuaString | ||||
|  */ | ||||
| public final class Buffer { | ||||
| 	 | ||||
| 	/** Default capacity for a buffer: 64 */ | ||||
| 	private static final int DEFAULT_CAPACITY = 64; | ||||
| 	 | ||||
| 	/** Shared static array with no bytes */ | ||||
| 	private static final byte[] NOBYTES = {}; | ||||
|  | ||||
| 	/** Bytes in this buffer */ | ||||
| 	private byte[] bytes; | ||||
| 	 | ||||
| 	/** Length of this buffer */ | ||||
| 	private int length; | ||||
| 	 | ||||
| 	/** Offset into the byte array */ | ||||
| 	private int offset; | ||||
| 	 | ||||
| 	/** Value of this buffer, when not represented in bytes */ | ||||
| 	private LuaValue value; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Create buffer with default capacity | ||||
| 	 * @see #DEFAULT_CAPACITY | ||||
| 	 */ | ||||
| 	public Buffer() { | ||||
| 		this(DEFAULT_CAPACITY); | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Create buffer with specified initial capacity | ||||
| 	 * @param initialCapacity the initial capacity | ||||
| 	 */ | ||||
| 	public Buffer( int initialCapacity ) { | ||||
| 		bytes = new byte[ initialCapacity ]; | ||||
| 		length = 0; | ||||
| 		offset = 0; | ||||
| 		value = null; | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Create buffer with specified initial value | ||||
| 	 * @param value the initial value | ||||
| 	 */ | ||||
| 	public Buffer(LuaValue value) { | ||||
| 		bytes = NOBYTES; | ||||
| 		length = offset = 0; | ||||
| 		this.value = value; | ||||
| 	} | ||||
|  | ||||
| 	/**  | ||||
| 	 * Get buffer contents as a {@link LuaValue} | ||||
| 	 * @return value as a {@link LuaValue}, converting as necessary | ||||
| 	 */ | ||||
| 	public LuaValue value() { | ||||
| 		return value != null? value: this.tostring(); | ||||
| 	} | ||||
|  | ||||
| 	/**  | ||||
| 	 * Set buffer contents as a {@link LuaValue} | ||||
| 	 * @param value value to set | ||||
| 	 */ | ||||
| 	public Buffer setvalue(LuaValue value) { | ||||
| 		bytes = NOBYTES; | ||||
| 		offset = length = 0; | ||||
| 		this.value = value; | ||||
| 		return this; | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Convert the buffer to a {@link LuaString} | ||||
| 	 * @return the value as a {@link LuaString} | ||||
| 	 */ | ||||
| 	public final LuaString tostring() { | ||||
| 		realloc( length, 0 ); | ||||
| 		return LuaString.valueOf( bytes, offset, length ); | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Convert the buffer to a Java String | ||||
| 	 * @return the value as a Java String | ||||
| 	 */ | ||||
| 	public String tojstring() { | ||||
| 		return value().tojstring(); | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Convert the buffer to a Java String | ||||
| 	 * @return the value as a Java String | ||||
| 	 */ | ||||
| 	public String toString() { | ||||
| 		return tojstring(); | ||||
| 	} | ||||
|  | ||||
| 	/**  | ||||
| 	 * Append a single byte to the buffer. | ||||
| 	 * @return {@code this} to allow call chaining | ||||
| 	 */ | ||||
| 	public final Buffer append( byte b ) { | ||||
| 		makeroom( 0, 1 ); | ||||
| 		bytes[ offset + length++ ] = b; | ||||
| 		return this; | ||||
| 	} | ||||
|  | ||||
| 	/**  | ||||
| 	 * Append a {@link LuaValue} to the buffer. | ||||
| 	 * @return {@code this} to allow call chaining | ||||
| 	 */ | ||||
| 	public final Buffer append( LuaValue val ) { | ||||
| 		append( val.strvalue() ); | ||||
| 		return this; | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Append a {@link LuaString} to the buffer. | ||||
| 	 * @return {@code this} to allow call chaining | ||||
| 	 */ | ||||
| 	public final Buffer append( LuaString str ) { | ||||
| 		final int n = str.m_length; | ||||
| 		makeroom( 0, n ); | ||||
| 		str.copyInto( 0, bytes, offset + length, n ); | ||||
| 		length += n; | ||||
| 		return this; | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Append a Java String to the buffer. | ||||
| 	 * The Java string will be converted to bytes using the UTF8 encoding.  | ||||
| 	 * @return {@code this} to allow call chaining | ||||
| 	 * @see LuaString#encodeToUtf8(char[], byte[], int) | ||||
| 	 */ | ||||
| 	public final Buffer append( String str ) { | ||||
| 		char[] chars = str.toCharArray(); | ||||
| 		/* DAN200 START */ | ||||
| 		/* | ||||
| 		final int n = LuaString.lengthAsUtf8( chars ); | ||||
| 		makeroom( 0, n ); | ||||
| 		LuaString.encodeToUtf8( chars, bytes, offset + length ); | ||||
| 		length += n; | ||||
| 		*/ | ||||
| 		makeroom( 0, chars.length ); | ||||
| 		for( int i=0; i<chars.length; ++i ) | ||||
| 		{ | ||||
| 			char ch = chars[i]; | ||||
| 			bytes[ offset + length + i ] = (ch < 256) ? (byte)ch : (byte)'?'; | ||||
| 		} | ||||
| 		length += chars.length; | ||||
| 		/* DAN200 END */ | ||||
| 		return this; | ||||
| 	} | ||||
|  | ||||
| 	/** Concatenate this buffer onto a {@link LuaValue} | ||||
| 	 * @param lhs the left-hand-side value onto which we are concatenating {@code this}  | ||||
| 	 * @return {@link Buffer} for use in call chaining. | ||||
| 	 */ | ||||
| 	public Buffer concatTo(LuaValue lhs) { | ||||
| 		return setvalue(lhs.concat(value())); | ||||
| 	} | ||||
|  | ||||
| 	/** Concatenate this buffer onto a {@link LuaString} | ||||
| 	 * @param lhs the left-hand-side value onto which we are concatenating {@code this}  | ||||
| 	 * @return {@link Buffer} for use in call chaining. | ||||
| 	 */ | ||||
| 	public Buffer concatTo(LuaString lhs) { | ||||
| 		return value!=null&&!value.isstring()? setvalue(lhs.concat(value)): prepend(lhs); | ||||
| 	} | ||||
|  | ||||
| 	/** Concatenate this buffer onto a {@link LuaNumber} | ||||
| 	 * <p> | ||||
| 	 * The {@link LuaNumber} will be converted to a string before concatenating.  | ||||
| 	 * @param lhs the left-hand-side value onto which we are concatenating {@code this}  | ||||
| 	 * @return {@link Buffer} for use in call chaining. | ||||
| 	 */ | ||||
| 	public Buffer concatTo(LuaNumber lhs) { | ||||
| 		return value!=null&&!value.isstring()? setvalue(lhs.concat(value)): prepend(lhs.strvalue()); | ||||
| 	} | ||||
|  | ||||
| 	/** Concatenate bytes from a {@link LuaString} onto the front of this buffer | ||||
| 	 * @param s the left-hand-side value which we will concatenate onto the front of {@code this}  | ||||
| 	 * @return {@link Buffer} for use in call chaining. | ||||
| 	 */ | ||||
| 	public Buffer prepend(LuaString s) { | ||||
| 		int n = s.m_length; | ||||
| 		makeroom( n, 0 ); | ||||
| 		System.arraycopy( s.m_bytes, s.m_offset, bytes, offset-n, n ); | ||||
| 		offset -= n; | ||||
| 		length += n; | ||||
| 		value = null; | ||||
| 		return this; | ||||
| 	} | ||||
|  | ||||
| 	/** Ensure there is enough room before and after the bytes. | ||||
| 	 * @param nbefore number of unused bytes which must precede the data after this completes  | ||||
| 	 * @param nafter number of unused bytes which must follow the data after this completes  | ||||
| 	 */ | ||||
| 	public final void makeroom( int nbefore, int nafter ) { | ||||
| 		if ( value != null ) { | ||||
| 			LuaString s = value.strvalue(); | ||||
| 			value = null; | ||||
| 			length = s.m_length; | ||||
| 			offset = nbefore; | ||||
| 			bytes = new byte[nbefore+length+nafter]; | ||||
| 			System.arraycopy(s.m_bytes, s.m_offset, bytes, offset, length); | ||||
| 		} else if ( offset+length+nafter > bytes.length || offset<nbefore ) { | ||||
| 			int n = nbefore+length+nafter; | ||||
| 			int m = n<32? 32: n<length*2? length*2: n; | ||||
| 			realloc( m, nbefore==0? 0: m-length-nafter ); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	/** Reallocate the internal storage for the buffer | ||||
| 	 * @param newSize the size of the buffer to use  | ||||
| 	 * @param newOffset the offset to use  | ||||
| 	 */ | ||||
| 	private final void realloc( int newSize, int newOffset ) { | ||||
| 		if ( newSize != bytes.length ) { | ||||
| 			byte[] newBytes = new byte[ newSize ]; | ||||
| 			System.arraycopy( bytes, offset, newBytes, newOffset, length ); | ||||
| 			bytes = newBytes; | ||||
| 			offset = newOffset; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -1,428 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
| import java.io.DataInputStream; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
|  | ||||
|  | ||||
| /** | ||||
| * Class to manage loading of {@link Prototype} instances. | ||||
| * <p> | ||||
| * The {@link LoadState} class exposes one main function,  | ||||
| * namely {@link #load(InputStream, String, LuaValue)},  | ||||
| * to be used to load code from a particular input stream.   | ||||
| * <p> | ||||
| * A simple pattern for loading and executing code is | ||||
| * <pre> {@code | ||||
| * LuaValue _G = JsePlatform.standardGlobals(); | ||||
| * LoadState.load( new FileInputStream("main.lua"), "main.lua", _G ).call(); | ||||
| * } </pre> | ||||
| * This should work regardless of which {@link LuaCompiler} | ||||
| * has been installed. | ||||
| * <p> | ||||
| *   | ||||
| * Prior to loading code, a compiler should be installed.  | ||||
| * <p> | ||||
| * By default, when using {@link JsePlatform} or {@JmePlatform} | ||||
| * to construct globals, the {@link LuaC} compiler is installed.  | ||||
| * <p> | ||||
| * To override the default compiler with, say, the {@link LuaJC} | ||||
| * lua-to-java bytecode compiler, install it before loading,  | ||||
| * for example: | ||||
| * <pre> {@code | ||||
| * LuaValue _G = JsePlatform.standardGlobals(); | ||||
| * LuaJC.install(); | ||||
| * LoadState.load( new FileInputStream("main.lua"), "main.lua", _G ).call(); | ||||
| * } </pre> | ||||
| *  | ||||
| * @see LuaCompiler | ||||
| * @see LuaClosure | ||||
| * @see LuaFunction | ||||
| * @see LoadState#compiler | ||||
| * @see LoadState#load(InputStream, String, LuaValue) | ||||
| * @see LuaC | ||||
| * @see LuaJC | ||||
| */ | ||||
| public class LoadState { | ||||
| 	 | ||||
| 	/** format corresponding to non-number-patched lua, all numbers are floats or doubles */ | ||||
| 	public static final int NUMBER_FORMAT_FLOATS_OR_DOUBLES    = 0; | ||||
|  | ||||
| 	/** format corresponding to non-number-patched lua, all numbers are ints */ | ||||
| 	public static final int NUMBER_FORMAT_INTS_ONLY            = 1; | ||||
| 	 | ||||
| 	/** format corresponding to number-patched lua, all numbers are 32-bit (4 byte) ints */ | ||||
| 	public static final int NUMBER_FORMAT_NUM_PATCH_INT32      = 4; | ||||
| 	 | ||||
| 	// type constants	 | ||||
| 	public static final int LUA_TINT            = (-2); | ||||
| 	public static final int LUA_TNONE			= (-1); | ||||
| 	public static final int LUA_TNIL			= 0; | ||||
| 	public static final int LUA_TBOOLEAN		= 1; | ||||
| 	public static final int LUA_TLIGHTUSERDATA	= 2; | ||||
| 	public static final int LUA_TNUMBER			= 3; | ||||
| 	public static final int LUA_TSTRING			= 4; | ||||
| 	public static final int LUA_TTABLE			= 5; | ||||
| 	public static final int LUA_TFUNCTION		= 6; | ||||
| 	public static final int LUA_TUSERDATA		= 7; | ||||
| 	public static final int LUA_TTHREAD			= 8; | ||||
| 	public static final int LUA_TVALUE          = 9; | ||||
| 	 | ||||
| 	/** Interface for the compiler, if it is installed.  | ||||
| 	 * <p> | ||||
| 	 * See the {@link LuaClosure} documentation for examples of how to use the compiler.  | ||||
| 	 * @see LuaClosure | ||||
| 	 * @see #load(InputStream, String, LuaValue) | ||||
| 	 * */ | ||||
| 	public interface LuaCompiler { | ||||
| 		 | ||||
| 		/** Load into a Closure or LuaFunction from a Stream and initializes the environment  | ||||
| 		 * @throws IOException */ | ||||
| 		public LuaFunction load(InputStream stream, String filename, LuaValue env) throws IOException; | ||||
| 	} | ||||
|  | ||||
| 	/** Compiler instance, if installed */ | ||||
| 	public static LuaCompiler compiler = null; | ||||
|  | ||||
| 	/** Signature byte indicating the file is a compiled binary chunk */ | ||||
| 	private static final byte[] LUA_SIGNATURE	= { '\033', 'L', 'u', 'a' }; | ||||
|  | ||||
| 	/** Name for compiled chunks */ | ||||
| 	public static final String SOURCE_BINARY_STRING = "binary string"; | ||||
|  | ||||
|  | ||||
| 	/** for header of binary files -- this is Lua 5.1 */ | ||||
| 	public static final int LUAC_VERSION		= 0x51; | ||||
|  | ||||
| 	/** for header of binary files -- this is the official format */ | ||||
| 	public static final int LUAC_FORMAT		= 0; | ||||
|  | ||||
| 	/** size of header of binary files */ | ||||
| 	public static final int LUAC_HEADERSIZE		= 12; | ||||
|  | ||||
| 	// values read from the header | ||||
| 	private int     luacVersion; | ||||
| 	private int     luacFormat; | ||||
| 	private boolean luacLittleEndian; | ||||
| 	private int     luacSizeofInt; | ||||
| 	private int     luacSizeofSizeT; | ||||
| 	private int     luacSizeofInstruction; | ||||
| 	private int     luacSizeofLuaNumber; | ||||
| 	private int 	luacNumberFormat; | ||||
|  | ||||
| 	/** input stream from which we are loading */ | ||||
| 	public final DataInputStream is; | ||||
|  | ||||
| 	/** Name of what is being loaded? */ | ||||
| 	String name; | ||||
|  | ||||
| 	private static final LuaValue[]     NOVALUES    = {}; | ||||
| 	private static final Prototype[] NOPROTOS    = {}; | ||||
| 	private static final LocVars[]   NOLOCVARS   = {}; | ||||
| 	private static final LuaString[]  NOSTRVALUES = {}; | ||||
| 	private static final int[]       NOINTS      = {}; | ||||
| 	 | ||||
| 	/** Read buffer */ | ||||
| 	private byte[] buf = new byte[512]; | ||||
| 	 | ||||
| 	 | ||||
| 	/** Load a 4-byte int value from the input stream | ||||
| 	 * @return the int value laoded.   | ||||
| 	 **/ | ||||
| 	int loadInt() throws IOException { | ||||
| 		is.readFully(buf,0,4); | ||||
| 		return luacLittleEndian?  | ||||
| 				(buf[3] << 24) | ((0xff & buf[2]) << 16) | ((0xff & buf[1]) << 8) | (0xff & buf[0]): | ||||
| 				(buf[0] << 24) | ((0xff & buf[1]) << 16) | ((0xff & buf[2]) << 8) | (0xff & buf[3]); | ||||
| 	} | ||||
| 	 | ||||
| 	/** Load an array of int values from the input stream | ||||
| 	 * @return the array of int values laoded.   | ||||
| 	 **/ | ||||
| 	int[] loadIntArray() throws IOException { | ||||
| 		int n = loadInt(); | ||||
| 		if ( n == 0 ) | ||||
| 			return NOINTS; | ||||
| 		 | ||||
| 		// read all data at once | ||||
| 		int m = n << 2; | ||||
| 		if ( buf.length < m ) | ||||
| 			buf = new byte[m]; | ||||
| 		is.readFully(buf,0,m); | ||||
| 		int[] array = new int[n]; | ||||
| 		for ( int i=0, j=0; i<n; ++i, j+=4 ) | ||||
| 			array[i] = luacLittleEndian?  | ||||
| 					(buf[j+3] << 24) | ((0xff & buf[j+2]) << 16) | ((0xff & buf[j+1]) << 8) | (0xff & buf[j+0]): | ||||
| 					(buf[j+0] << 24) | ((0xff & buf[j+1]) << 16) | ((0xff & buf[j+2]) << 8) | (0xff & buf[j+3]); | ||||
|  | ||||
| 		return array; | ||||
| 	} | ||||
| 	 | ||||
| 	/** Load a long  value from the input stream | ||||
| 	 * @return the long value laoded.   | ||||
| 	 **/ | ||||
| 	long loadInt64() throws IOException { | ||||
| 		int a,b; | ||||
| 		if ( this.luacLittleEndian ) { | ||||
| 			a = loadInt(); | ||||
| 			b = loadInt(); | ||||
| 		} else { | ||||
| 			b = loadInt(); | ||||
| 			a = loadInt(); | ||||
| 		} | ||||
| 		return (((long)b)<<32) | (((long)a)&0xffffffffL); | ||||
| 	} | ||||
|  | ||||
| 	/** Load a lua strin gvalue from the input stream | ||||
| 	 * @return the {@link LuaString} value laoded.   | ||||
| 	 **/ | ||||
| 	LuaString loadString() throws IOException { | ||||
| 		int size = this.luacSizeofSizeT == 8? (int) loadInt64(): loadInt(); | ||||
| 		if ( size == 0 ) | ||||
| 			return null; | ||||
| 		byte[] bytes = new byte[size]; | ||||
| 		is.readFully( bytes, 0, size ); | ||||
| 		return LuaString.valueOf( bytes, 0, bytes.length - 1 ); | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Convert bits in a long value to a {@link LuaValue}.  | ||||
| 	 * @param bits long value containing the bits | ||||
| 	 * @return {@link LuaInteger} or {@link LuaDouble} whose value corresponds to the bits provided. | ||||
| 	 */ | ||||
| 	public static LuaValue longBitsToLuaNumber( long bits ) { | ||||
| 		if ( ( bits & ( ( 1L << 63 ) - 1 ) ) == 0L ) { | ||||
| 			return LuaValue.ZERO; | ||||
| 		} | ||||
| 		 | ||||
| 		int e = (int)((bits >> 52) & 0x7ffL) - 1023; | ||||
| 		 | ||||
| 		if ( e >= 0 && e < 31 ) { | ||||
| 			long f = bits & 0xFFFFFFFFFFFFFL; | ||||
| 			int shift = 52 - e; | ||||
| 			long intPrecMask = ( 1L << shift ) - 1; | ||||
| 			if ( ( f & intPrecMask ) == 0 ) { | ||||
| 				int intValue = (int)( f >> shift ) | ( 1 << e ); | ||||
| 				return LuaInteger.valueOf( ( ( bits >> 63 ) != 0 ) ? -intValue : intValue ); | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		return LuaValue.valueOf( Double.longBitsToDouble(bits) ); | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Load a number from a binary chunk | ||||
| 	 * @return the {@link LuaValue} loaded | ||||
| 	 * @throws IOException if an i/o exception occurs | ||||
| 	 */ | ||||
| 	LuaValue loadNumber() throws IOException { | ||||
| 		if ( luacNumberFormat == NUMBER_FORMAT_INTS_ONLY ) { | ||||
| 			return LuaInteger.valueOf( loadInt() ); | ||||
| 		} else { | ||||
| 			return longBitsToLuaNumber( loadInt64() ); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Load a list of constants from a binary chunk | ||||
| 	 * @param f the function prototype | ||||
| 	 * @throws IOException if an i/o exception occurs | ||||
| 	 */ | ||||
| 	void loadConstants(Prototype f) throws IOException { | ||||
| 		int n = loadInt(); | ||||
| 		LuaValue[] values = n>0? new LuaValue[n]: NOVALUES; | ||||
| 		for ( int i=0; i<n; i++ ) { | ||||
| 			switch ( is.readByte() ) { | ||||
| 			case LUA_TNIL: | ||||
| 				values[i] = LuaValue.NIL; | ||||
| 				break; | ||||
| 			case LUA_TBOOLEAN: | ||||
| 				values[i] = (0 != is.readUnsignedByte()? LuaValue.TRUE: LuaValue.FALSE); | ||||
| 				break; | ||||
| 			case LUA_TINT: | ||||
| 				values[i] = LuaInteger.valueOf( loadInt() ); | ||||
| 				break; | ||||
| 			case LUA_TNUMBER: | ||||
| 				values[i] = loadNumber(); | ||||
| 				break; | ||||
| 			case LUA_TSTRING: | ||||
| 				values[i] = loadString(); | ||||
| 				break; | ||||
| 			default: | ||||
| 				throw new IllegalStateException("bad constant"); | ||||
| 			} | ||||
| 		} | ||||
| 		f.k = values; | ||||
| 		 | ||||
| 		n = loadInt(); | ||||
| 		Prototype[] protos = n>0? new Prototype[n]: NOPROTOS; | ||||
| 		for ( int i=0; i<n; i++ ) | ||||
| 			protos[i] = loadFunction(f.source); | ||||
| 		f.p = protos; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Load the debug infor for a function prototype | ||||
| 	 * @param f the function Prototype | ||||
| 	 * @throws IOException if there is an i/o exception | ||||
| 	 */ | ||||
| 	void loadDebug( Prototype f ) throws IOException { | ||||
| 		f.lineinfo = loadIntArray(); | ||||
| 		int n = loadInt(); | ||||
| 		f.locvars = n>0? new LocVars[n]: NOLOCVARS; | ||||
| 		for ( int i=0; i<n; i++ ) { | ||||
| 			LuaString varname = loadString(); | ||||
| 			int startpc = loadInt(); | ||||
| 			int endpc = loadInt(); | ||||
| 			f.locvars[i] = new LocVars(varname, startpc, endpc); | ||||
| 		} | ||||
| 		 | ||||
| 		n = loadInt(); | ||||
| 		f.upvalues = n>0? new LuaString[n]: NOSTRVALUES; | ||||
| 		for ( int i=0; i<n; i++ ) { | ||||
| 			f.upvalues[i] = loadString(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/**  | ||||
| 	 * Load a function prototype from the input stream | ||||
| 	 * @param p name of the source | ||||
| 	 * @return {@link Prototype} instance that was loaded | ||||
| 	 * @throws IOException | ||||
| 	 */ | ||||
| 	public Prototype loadFunction(LuaString p) throws IOException { | ||||
| 		Prototype f = new Prototype(); | ||||
| //		this.L.push(f); | ||||
| 		f.source = loadString(); | ||||
| 		if ( f.source == null ) | ||||
| 			f.source = p; | ||||
| 		f.linedefined = loadInt(); | ||||
| 		f.lastlinedefined = loadInt(); | ||||
| 		f.nups = is.readUnsignedByte(); | ||||
| 		f.numparams = is.readUnsignedByte(); | ||||
| 		f.is_vararg = is.readUnsignedByte(); | ||||
| 		f.maxstacksize = is.readUnsignedByte(); | ||||
| 		f.code = loadIntArray(); | ||||
| 		loadConstants(f); | ||||
| 		loadDebug(f); | ||||
| 		 | ||||
| 		// TODO: add check here, for debugging purposes, I believe | ||||
| 		// see ldebug.c | ||||
| //		 IF (!luaG_checkcode(f), "bad code"); | ||||
| 		 | ||||
| //		 this.L.pop(); | ||||
| 		 return f; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Load the lua chunk header values.  | ||||
| 	 * @throws IOException if an i/o exception occurs.  | ||||
| 	 */ | ||||
| 	public void loadHeader() throws IOException { | ||||
| 		luacVersion = is.readByte(); | ||||
| 		luacFormat = is.readByte(); | ||||
| 		luacLittleEndian = (0 != is.readByte()); | ||||
| 		luacSizeofInt = is.readByte(); | ||||
| 		luacSizeofSizeT = is.readByte(); | ||||
| 		luacSizeofInstruction = is.readByte(); | ||||
| 		luacSizeofLuaNumber = is.readByte(); | ||||
| 		luacNumberFormat = is.readByte(); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Load lua in either binary or text form from an input stream. | ||||
| 	 * @param firstByte the first byte of the input stream | ||||
| 	 * @param stream InputStream to read, after having read the first byte already | ||||
| 	 * @param name Name to apply to the loaded chunk | ||||
| 	 * @return {@link Prototype} that was loaded | ||||
| 	 * @throws IllegalArgumentException if the signature is bac | ||||
| 	 * @throws IOException if an IOException occurs | ||||
| 	 */ | ||||
| 	public static LuaFunction load( InputStream stream, String name, LuaValue env ) throws IOException { | ||||
| 		if ( compiler != null ) | ||||
| 			return compiler.load(stream, name, env); | ||||
| 		else { | ||||
| 			int firstByte = stream.read(); | ||||
| 			if ( firstByte != LUA_SIGNATURE[0] ) | ||||
| 				throw new LuaError("no compiler"); | ||||
| 			Prototype p = loadBinaryChunk( firstByte, stream, name ); | ||||
| 			return new LuaClosure( p, env ); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Load lua thought to be a binary chunk from its first byte from an input stream. | ||||
| 	 * @param firstByte the first byte of the input stream | ||||
| 	 * @param stream InputStream to read, after having read the first byte already | ||||
| 	 * @param name Name to apply to the loaded chunk | ||||
| 	 * @return {@link Prototype} that was loaded | ||||
| 	 * @throws IllegalArgumentException if the signature is bac | ||||
| 	 * @throws IOException if an IOException occurs | ||||
| 	 */ | ||||
| 	public static Prototype loadBinaryChunk( int firstByte, InputStream stream, String name ) throws IOException { | ||||
|  | ||||
| 		// check rest of signature | ||||
| 		if ( firstByte != LUA_SIGNATURE[0]  | ||||
| 		   || stream.read() != LUA_SIGNATURE[1] | ||||
| 	       || stream.read() != LUA_SIGNATURE[2] | ||||
| 		   || stream.read() != LUA_SIGNATURE[3] ) | ||||
| 			throw new IllegalArgumentException("bad signature"); | ||||
| 		 | ||||
| 		// load file as a compiled chunk | ||||
| 		String sname = getSourceName(name); | ||||
| 		LoadState s = new LoadState( stream, sname ); | ||||
| 		s.loadHeader(); | ||||
|  | ||||
| 		// check format | ||||
| 		switch ( s.luacNumberFormat ) { | ||||
| 		case NUMBER_FORMAT_FLOATS_OR_DOUBLES: | ||||
| 		case NUMBER_FORMAT_INTS_ONLY: | ||||
| 		case NUMBER_FORMAT_NUM_PATCH_INT32: | ||||
| 			break; | ||||
| 		default: | ||||
| 			throw new LuaError("unsupported int size"); | ||||
| 		} | ||||
| 		return s.loadFunction( LuaString.valueOf(sname) ); | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Construct a source name from a supplied chunk name | ||||
| 	 * @param name String name that appears in the chunk | ||||
| 	 * @return source file name | ||||
| 	 */ | ||||
|     public static String getSourceName(String name) { | ||||
|         String sname = name; | ||||
|         if ( name.startsWith("@") || name.startsWith("=") ) | ||||
| 			sname = name.substring(1); | ||||
| 		else if ( name.startsWith("\033") ) | ||||
| 			sname = SOURCE_BINARY_STRING; | ||||
|         return sname; | ||||
|     } | ||||
|  | ||||
| 	/** Private constructor for create a load state */ | ||||
| 	private LoadState( InputStream stream, String name ) { | ||||
| 		this.name = name; | ||||
| 		this.is = new DataInputStream( stream ); | ||||
| 	} | ||||
| } | ||||
| @@ -1,52 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
| /** | ||||
|  * Data class to hold debug information relatign to local variables for a {@link Prototype} | ||||
|  */ | ||||
| public class LocVars { | ||||
| 	/** The local variable name */ | ||||
| 	public LuaString varname; | ||||
| 	 | ||||
| 	/** The instruction offset when the variable comes into scope */  | ||||
| 	public int startpc; | ||||
| 	 | ||||
| 	/** The instruction offset when the variable goes out of scope */  | ||||
| 	public int endpc; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Construct a LocVars instance.  | ||||
| 	 * @param varname The local variable name | ||||
| 	 * @param startpc The instruction offset when the variable comes into scope | ||||
| 	 * @param endpc The instruction offset when the variable goes out of scope | ||||
| 	 */ | ||||
| 	public LocVars(LuaString varname, int startpc, int endpc) { | ||||
| 		this.varname = varname; | ||||
| 		this.startpc = startpc; | ||||
| 		this.endpc = endpc; | ||||
| 	} | ||||
| 	 | ||||
| 	public String tojstring() { | ||||
| 		return varname+" "+startpc+"-"+endpc; | ||||
| 	} | ||||
| } | ||||
| @@ -1,337 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Constants for lua limits and opcodes.  | ||||
|  * <p> | ||||
|  * This is a direct translation of C lua distribution header file constants | ||||
|  * for bytecode creation and processing.   | ||||
|  */ | ||||
| public class Lua { | ||||
| 	/** version is supplied by ant build task */ | ||||
| 	public static final String _VERSION = "Luaj 0.0"; | ||||
|  | ||||
| 	/** use return values from previous op */ | ||||
| 	public static final int LUA_MULTRET = -1; | ||||
|  | ||||
| 	/** masks for new-style vararg */ | ||||
| 	public static final int     VARARG_HASARG		= 1; | ||||
| 	public static final int     VARARG_ISVARARG	= 2; | ||||
| 	public static final int     VARARG_NEEDSARG	= 4; | ||||
| 	 | ||||
| 	// from lopcodes.h | ||||
|  | ||||
| 	/*=========================================================================== | ||||
| 	  We assume that instructions are unsigned numbers. | ||||
| 	  All instructions have an opcode in the first 6 bits. | ||||
| 	  Instructions can have the following fields: | ||||
| 		`A' : 8 bits | ||||
| 		`B' : 9 bits | ||||
| 		`C' : 9 bits | ||||
| 		`Bx' : 18 bits (`B' and `C' together) | ||||
| 		`sBx' : signed Bx | ||||
|  | ||||
| 	  A signed argument is represented in excess K; that is, the number | ||||
| 	  value is the unsigned value minus K. K is exactly the maximum value | ||||
| 	  for that argument (so that -max is represented by 0, and +max is | ||||
| 	  represented by 2*max), which is half the maximum for the corresponding | ||||
| 	  unsigned argument. | ||||
| 	===========================================================================*/ | ||||
|  | ||||
|  | ||||
| 	/* basic instruction format */ | ||||
| 	public static final int	iABC = 0; | ||||
| 	public static final int	iABx = 1; | ||||
| 	public static final int	iAsBx = 2; | ||||
|  | ||||
|  | ||||
| 	/* | ||||
| 	** size and position of opcode arguments. | ||||
| 	*/ | ||||
| 	public static final int SIZE_C		= 9; | ||||
| 	public static final int SIZE_B		= 9; | ||||
| 	public static final int SIZE_Bx		= (SIZE_C + SIZE_B); | ||||
| 	public static final int SIZE_A		= 8; | ||||
|  | ||||
| 	public static final int SIZE_OP		= 6; | ||||
|  | ||||
| 	public static final int POS_OP		= 0; | ||||
| 	public static final int POS_A		= (POS_OP + SIZE_OP); | ||||
| 	public static final int POS_C		= (POS_A + SIZE_A); | ||||
| 	public static final int POS_B		= (POS_C + SIZE_C); | ||||
| 	public static final int POS_Bx		= POS_C; | ||||
|  | ||||
|  | ||||
| 	public static final int MAX_OP          = ((1<<SIZE_OP)-1); | ||||
| 	public static final int MAXARG_A        = ((1<<SIZE_A)-1); | ||||
| 	public static final int MAXARG_B        = ((1<<SIZE_B)-1); | ||||
| 	public static final int MAXARG_C        = ((1<<SIZE_C)-1); | ||||
| 	public static final int MAXARG_Bx       = ((1<<SIZE_Bx)-1); | ||||
| 	public static final int MAXARG_sBx      = (MAXARG_Bx>>1);     	/* `sBx' is signed */ | ||||
|  | ||||
| 	public static final int MASK_OP = ((1<<SIZE_OP)-1)<<POS_OP;  | ||||
| 	public static final int MASK_A  = ((1<<SIZE_A)-1)<<POS_A;  | ||||
| 	public static final int MASK_B  = ((1<<SIZE_B)-1)<<POS_B;  | ||||
| 	public static final int MASK_C  = ((1<<SIZE_C)-1)<<POS_C;  | ||||
| 	public static final int MASK_Bx = ((1<<SIZE_Bx)-1)<<POS_Bx;  | ||||
|  | ||||
| 	public static final int MASK_NOT_OP = ~MASK_OP;  | ||||
| 	public static final int MASK_NOT_A  = ~MASK_A;  | ||||
| 	public static final int MASK_NOT_B  = ~MASK_B;  | ||||
| 	public static final int MASK_NOT_C  = ~MASK_C;  | ||||
| 	public static final int MASK_NOT_Bx = ~MASK_Bx;  | ||||
|  | ||||
| 	/* | ||||
| 	** the following macros help to manipulate instructions | ||||
| 	*/ | ||||
| 	public static int GET_OPCODE(int i) { | ||||
| 		return (i >> POS_OP) & MAX_OP; | ||||
| 	} | ||||
|  | ||||
| 	public static int GETARG_A(int i) { | ||||
| 		return (i >> POS_A) & MAXARG_A; | ||||
| 	} | ||||
|  | ||||
| 	public static int GETARG_B(int i) { | ||||
| 		return (i >> POS_B) & MAXARG_B; | ||||
| 	} | ||||
|  | ||||
| 	public static int GETARG_C(int i) { | ||||
| 		return (i >> POS_C) & MAXARG_C; | ||||
| 	} | ||||
|  | ||||
| 	public static int GETARG_Bx(int i) { | ||||
| 		return (i >> POS_Bx) & MAXARG_Bx; | ||||
| 	} | ||||
|  | ||||
| 	public static int GETARG_sBx(int i) { | ||||
| 		return ((i >> POS_Bx) & MAXARG_Bx) - MAXARG_sBx; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	/* | ||||
| 	** Macros to operate RK indices | ||||
| 	*/ | ||||
|  | ||||
| 	/** this bit 1 means constant (0 means register) */ | ||||
| 	public static final int BITRK		= (1 << (SIZE_B - 1)); | ||||
|  | ||||
| 	/** test whether value is a constant */ | ||||
| 	public static boolean ISK(int x) { | ||||
| 		return 0 != ((x) & BITRK); | ||||
| 	} | ||||
|  | ||||
| 	/** gets the index of the constant */ | ||||
| 	public static int INDEXK(int r) { | ||||
| 		return ((int)(r) & ~BITRK); | ||||
| 	} | ||||
|  | ||||
| 	public static final int MAXINDEXRK	= (BITRK - 1); | ||||
|  | ||||
| 	/** code a constant index as a RK value */ | ||||
| 	public static int RKASK(int x) { | ||||
| 		return ((x) | BITRK); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	/** | ||||
| 	** invalid register that fits in 8 bits | ||||
| 	*/ | ||||
| 	public static final int  NO_REG		= MAXARG_A; | ||||
|  | ||||
|  | ||||
| 	/* | ||||
| 	** R(x) - register | ||||
| 	** Kst(x) - constant (in constant table) | ||||
| 	** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x) | ||||
| 	*/ | ||||
|  | ||||
|  | ||||
| 	/* | ||||
| 	** grep "ORDER OP" if you change these enums | ||||
| 	*/ | ||||
|  | ||||
| 	/*---------------------------------------------------------------------- | ||||
| 	name		args	description | ||||
| 	------------------------------------------------------------------------*/ | ||||
| 	public static final int OP_MOVE = 0;/*	A B	R(A) := R(B)					*/ | ||||
| 	public static final int OP_LOADK = 1;/*	A Bx	R(A) := Kst(Bx)					*/ | ||||
| 	public static final int OP_LOADBOOL = 2;/*	A B C	R(A) := (Bool)B; if (C) pc++			*/ | ||||
| 	public static final int OP_LOADNIL = 3; /*	A B	R(A) := ... := R(B) := nil			*/ | ||||
| 	public static final int OP_GETUPVAL = 4; /*	A B	R(A) := UpValue[B]				*/ | ||||
|  | ||||
| 	public static final int OP_GETGLOBAL = 5; /*	A Bx	R(A) := Gbl[Kst(Bx)]				*/ | ||||
| 	public static final int OP_GETTABLE = 6; /*	A B C	R(A) := R(B)[RK(C)]				*/ | ||||
|  | ||||
| 	public static final int OP_SETGLOBAL = 7; /*	A Bx	Gbl[Kst(Bx)] := R(A)				*/ | ||||
| 	public static final int OP_SETUPVAL = 8; /*	A B	UpValue[B] := R(A)				*/ | ||||
| 	public static final int OP_SETTABLE = 9; /*	A B C	R(A)[RK(B)] := RK(C)				*/ | ||||
|  | ||||
| 	public static final int OP_NEWTABLE = 10; /*	A B C	R(A) := {} (size = B,C)				*/ | ||||
|  | ||||
| 	public static final int OP_SELF = 11; /*	A B C	R(A+1) := R(B); R(A) := R(B)[RK(C)]		*/ | ||||
|  | ||||
| 	public static final int OP_ADD = 12; /*	A B C	R(A) := RK(B) + RK(C)				*/ | ||||
| 	public static final int OP_SUB = 13; /*	A B C	R(A) := RK(B) - RK(C)				*/ | ||||
| 	public static final int OP_MUL = 14; /*	A B C	R(A) := RK(B) * RK(C)				*/ | ||||
| 	public static final int OP_DIV = 15; /*	A B C	R(A) := RK(B) / RK(C)				*/ | ||||
| 	public static final int OP_MOD = 16; /*	A B C	R(A) := RK(B) % RK(C)				*/ | ||||
| 	public static final int OP_POW = 17; /*	A B C	R(A) := RK(B) ^ RK(C)				*/ | ||||
| 	public static final int OP_UNM = 18; /*	A B	R(A) := -R(B)					*/ | ||||
| 	public static final int OP_NOT = 19; /*	A B	R(A) := not R(B)				*/ | ||||
| 	public static final int OP_LEN = 20; /*	A B	R(A) := length of R(B)				*/ | ||||
|  | ||||
| 	public static final int OP_CONCAT = 21; /*	A B C	R(A) := R(B).. ... ..R(C)			*/ | ||||
|  | ||||
| 	public static final int OP_JMP = 22; /*	sBx	pc+=sBx					*/ | ||||
|  | ||||
| 	public static final int OP_EQ = 23; /*	A B C	if ((RK(B) == RK(C)) ~= A) then pc++		*/ | ||||
| 	public static final int OP_LT = 24; /*	A B C	if ((RK(B) <  RK(C)) ~= A) then pc++  		*/ | ||||
| 	public static final int OP_LE = 25; /*	A B C	if ((RK(B) <= RK(C)) ~= A) then pc++  		*/ | ||||
|  | ||||
| 	public static final int OP_TEST = 26; /*	A C	if not (R(A) <=> C) then pc++			*/  | ||||
| 	public static final int OP_TESTSET = 27; /*	A B C	if (R(B) <=> C) then R(A) := R(B) else pc++	*/  | ||||
|  | ||||
| 	public static final int OP_CALL = 28; /*	A B C	R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ | ||||
| 	public static final int OP_TAILCALL = 29; /*	A B C	return R(A)(R(A+1), ... ,R(A+B-1))		*/ | ||||
| 	public static final int OP_RETURN = 30; /*	A B	return R(A), ... ,R(A+B-2)	(see note)	*/ | ||||
|  | ||||
| 	public static final int OP_FORLOOP = 31; /*	A sBx	R(A)+=R(A+2); | ||||
| 				if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/ | ||||
| 	public static final int OP_FORPREP = 32; /*	A sBx	R(A)-=R(A+2); pc+=sBx				*/ | ||||
|  | ||||
| 	public static final int OP_TFORLOOP = 33; /*	A C	R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));  | ||||
| 	                        if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++	*/  | ||||
| 	public static final int OP_SETLIST = 34; /*	A B C	R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B	*/ | ||||
|  | ||||
| 	public static final int OP_CLOSE = 35; /*	A 	close all variables in the stack up to (>=) R(A)*/ | ||||
| 	public static final int OP_CLOSURE = 36; /*	A Bx	R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))	*/ | ||||
| 	public static final int OP_VARARG = 37; /*	A B	R(A), R(A+1), ..., R(A+B-1) = vararg		*/ | ||||
| 	 | ||||
| 	public static final int NUM_OPCODES	= OP_VARARG + 1; | ||||
|  | ||||
| 	/* pseudo-opcodes used in parsing only.  */ | ||||
| 	public static final int OP_GT  = 63; // >  | ||||
| 	public static final int OP_GE  = 62; // >= | ||||
| 	public static final int OP_NEQ = 61; // ~=  | ||||
| 	public static final int OP_AND = 60; // and  | ||||
| 	public static final int OP_OR  = 59; // or  | ||||
| 	 | ||||
| 	/*=========================================================================== | ||||
| 	  Notes: | ||||
| 	  (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, | ||||
| 	      and can be 0: OP_CALL then sets `top' to last_result+1, so | ||||
| 	      next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. | ||||
|  | ||||
| 	  (*) In OP_VARARG, if (B == 0) then use actual number of varargs and | ||||
| 	      set top (like in OP_CALL with C == 0). | ||||
|  | ||||
| 	  (*) In OP_RETURN, if (B == 0) then return up to `top' | ||||
|  | ||||
| 	  (*) In OP_SETLIST, if (B == 0) then B = `top'; | ||||
| 	      if (C == 0) then next `instruction' is real C | ||||
|  | ||||
| 	  (*) For comparisons, A specifies what condition the test should accept | ||||
| 	      (true or false). | ||||
|  | ||||
| 	  (*) All `skips' (pc++) assume that next instruction is a jump | ||||
| 	===========================================================================*/ | ||||
|  | ||||
|  | ||||
| 	/* | ||||
| 	** masks for instruction properties. The format is: | ||||
| 	** bits 0-1: op mode | ||||
| 	** bits 2-3: C arg mode | ||||
| 	** bits 4-5: B arg mode | ||||
| 	** bit 6: instruction set register A | ||||
| 	** bit 7: operator is a test | ||||
| 	*/   | ||||
|  | ||||
| 	  public static final int OpArgN = 0;  /* argument is not used */ | ||||
| 	  public static final int OpArgU = 1;  /* argument is used */ | ||||
| 	  public static final int OpArgR = 2;  /* argument is a register or a jump offset */ | ||||
| 	  public static final int OpArgK = 3;  /* argument is a constant or register/constant */ | ||||
|  | ||||
| 	  public static final int[] luaP_opmodes = { | ||||
| 	  /*   T        A           B             C          mode		   opcode	*/ | ||||
| 		 (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC),		/* OP_MOVE */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgN<<2) | (iABx),		/* OP_LOADK */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC),		/* OP_LOADBOOL */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC),		/* OP_LOADNIL */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC),		/* OP_GETUPVAL */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgN<<2) | (iABx),		/* OP_GETGLOBAL */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgK<<2) | (iABC),		/* OP_GETTABLE */ | ||||
| 		 (0<<7) | (0<<6) | (OpArgK<<4) | (OpArgN<<2) | (iABx),		/* OP_SETGLOBAL */ | ||||
| 		 (0<<7) | (0<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC),		/* OP_SETUPVAL */ | ||||
| 		 (0<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC),		/* OP_SETTABLE */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC),		/* OP_NEWTABLE */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgK<<2) | (iABC),		/* OP_SELF */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC),		/* OP_ADD */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC),		/* OP_SUB */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC),		/* OP_MUL */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC),		/* OP_DIV */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC),		/* OP_MOD */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC),		/* OP_POW */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC),		/* OP_UNM */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC),		/* OP_NOT */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC),		/* OP_LEN */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgR<<2) | (iABC),		/* OP_CONCAT */ | ||||
| 		 (0<<7) | (0<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx),		/* OP_JMP */ | ||||
| 		 (1<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC),		/* OP_EQ */ | ||||
| 		 (1<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC),		/* OP_LT */ | ||||
| 		 (1<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC),		/* OP_LE */ | ||||
| 		 (1<<7) | (1<<6) | (OpArgR<<4) | (OpArgU<<2) | (iABC),		/* OP_TEST */ | ||||
| 		 (1<<7) | (1<<6) | (OpArgR<<4) | (OpArgU<<2) | (iABC),		/* OP_TESTSET */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC),		/* OP_CALL */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC),		/* OP_TAILCALL */ | ||||
| 		 (0<<7) | (0<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC),		/* OP_RETURN */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx),		/* OP_FORLOOP */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx),		/* OP_FORPREP */ | ||||
| 		 (1<<7) | (0<<6) | (OpArgN<<4) | (OpArgU<<2) | (iABC),		/* OP_TFORLOOP */ | ||||
| 		 (0<<7) | (0<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC),		/* OP_SETLIST */ | ||||
| 		 (0<<7) | (0<<6) | (OpArgN<<4) | (OpArgN<<2) | (iABC),		/* OP_CLOSE */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABx),		/* OP_CLOSURE */ | ||||
| 		 (0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC),		/* OP_VARARG */ | ||||
| 	  }; | ||||
|  | ||||
| 	public static int getOpMode(int m) { | ||||
| 		return luaP_opmodes[m] & 3; | ||||
| 	} | ||||
| 	public static int getBMode(int m) { | ||||
| 		return (luaP_opmodes[m] >> 4) & 3; | ||||
| 	} | ||||
| 	public static int getCMode(int m) { | ||||
| 		return (luaP_opmodes[m] >> 2) & 3; | ||||
| 	} | ||||
| 	public static boolean testAMode(int m) { | ||||
| 		return 0 != (luaP_opmodes[m] & (1 << 6)); | ||||
| 	} | ||||
| 	public static boolean testTMode(int m) { | ||||
| 		return 0 != (luaP_opmodes[m] & (1 << 7)); | ||||
| 	} | ||||
|  | ||||
| 	/* number of list items to accumulate before a SETLIST instruction */ | ||||
| 	public static final int LFIELDS_PER_FLUSH = 50; | ||||
| 	 | ||||
| } | ||||
| @@ -1,103 +0,0 @@ | ||||
| /******************************************************************************* | ||||
|  * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
| /** | ||||
|  * Extension of {@link LuaValue} which can hold a Java boolean as its value.  | ||||
|  * <p> | ||||
|  * These instance are not instantiated directly by clients.   | ||||
|  * Instead, there are exactly twon instances of this class,  | ||||
|  * {@link LuaValue#TRUE} and {@link LuaValue#FALSE}  | ||||
|  * representing the lua values {@code true} and {@link false}. | ||||
|  * The function {@link LuaValue#valueOf(boolean)} will always  | ||||
|  * return one of these two values.  | ||||
|  * <p> | ||||
|  * Any {@link LuaValue} can be converted to its equivalent  | ||||
|  * boolean representation using {@link LuaValue#toboolean()} | ||||
|  * <p> | ||||
|  * @see LuaValue | ||||
|  * @see LuaValue#valueOf(boolean) | ||||
|  * @see LuaValue#TRUE | ||||
|  * @see LuaValue#FALSE | ||||
|  */ | ||||
| public final class LuaBoolean extends LuaValue { | ||||
|  | ||||
| 	/** The singleton instance representing lua {@code true} */ | ||||
| 	static final LuaBoolean _TRUE = new LuaBoolean(true); | ||||
| 	 | ||||
| 	/** The singleton instance representing lua {@code false} */ | ||||
| 	static final LuaBoolean _FALSE = new LuaBoolean(false); | ||||
| 	 | ||||
| 	/** Shared static metatable for boolean values represented in lua. */ | ||||
| 	public static LuaValue s_metatable; | ||||
|  | ||||
| 	/** The value of the boolean */ | ||||
| 	public final boolean v; | ||||
|  | ||||
| 	LuaBoolean(boolean b) { | ||||
| 		this.v = b; | ||||
| 	} | ||||
|  | ||||
| 	public int type() { | ||||
| 		return LuaValue.TBOOLEAN; | ||||
| 	} | ||||
|  | ||||
| 	public String typename() { | ||||
| 		return "boolean"; | ||||
| 	} | ||||
|  | ||||
| 	public boolean isboolean() { | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue not() { | ||||
| 		return v ? FALSE : LuaValue.TRUE; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Return the boolean value for this boolean | ||||
| 	 * @return value as a Java boolean | ||||
| 	 */ | ||||
| 	public boolean booleanValue() { | ||||
| 		return v; | ||||
| 	} | ||||
|  | ||||
| 	public boolean toboolean() { | ||||
| 		return v; | ||||
| 	} | ||||
|  | ||||
| 	public String tojstring() { | ||||
| 		return v ? "true" : "false"; | ||||
| 	} | ||||
|  | ||||
| 	public boolean optboolean(boolean defval) { | ||||
| 		return this.v; | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean checkboolean() { | ||||
| 		return v; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue getmetatable() {  | ||||
| 		return s_metatable;  | ||||
| 	} | ||||
| } | ||||
| @@ -1,521 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
| import java.io.ByteArrayInputStream; | ||||
| import java.io.InputStream; | ||||
|  | ||||
| import org.luaj.vm2.LoadState.LuaCompiler; | ||||
| import org.luaj.vm2.compiler.LuaC; | ||||
| import org.luaj.vm2.lib.DebugLib; | ||||
|  | ||||
| /** | ||||
|  * Extension of {@link LuaFunction} which executes lua bytecode.  | ||||
|  * <p> | ||||
|  * A {@link LuaClosure} is a combination of a {@link Prototype}  | ||||
|  * and a {@link LuaValue} to use as an environment for execution.  | ||||
|  * <p> | ||||
|  * There are three main ways {@link LuaClosure} instances are created: | ||||
|  * <ul>  | ||||
|  * <li>Construct an instance using {@link #LuaClosure(Prototype, LuaValue)}</li> | ||||
|  * <li>Construct it indirectly by loading a chunk via {@link LuaCompiler#load(java.io.InputStream, String, LuaValue)} | ||||
|  * <li>Execute the lua bytecode {@link Lua#OP_CLOSURE} as part of bytecode processing | ||||
|  * </ul> | ||||
|  * <p> | ||||
|  * To construct it directly, the {@link Prototype} is typically created via a compiler such as {@link LuaC}: | ||||
|  * <pre> {@code | ||||
|  * InputStream is = new ByteArrayInputStream("print('hello,world').getBytes()); | ||||
|  * Prototype p = LuaC.instance.compile(is, "script"); | ||||
|  * LuaValue _G = JsePlatform.standardGlobals() | ||||
|  * LuaClosure f = new LuaClosure(p, _G); | ||||
|  * }</pre>  | ||||
|  * <p> | ||||
|  * To construct it indirectly, the {@link LuaC} compiler may be used,  | ||||
|  * which implements the {@link LuaCompiler} interface:  | ||||
|  * <pre> {@code | ||||
|  * LuaFunction f = LuaC.instance.load(is, "script", _G); | ||||
|  * }</pre> | ||||
|  * <p> | ||||
|  * Typically, a closure that has just been loaded needs to be initialized by executing it,  | ||||
|  * and its return value can be saved if needed: | ||||
|  * <pre> {@code | ||||
|  * LuaValue r = f.call(); | ||||
|  * _G.set( "mypkg", r )  | ||||
|  * }</pre> | ||||
|  * <p>  | ||||
|  * In the preceding, the loaded value is typed as {@link LuaFunction}  | ||||
|  * to allow for the possibility of other compilers such as {@link LuaJC} | ||||
|  * producing {@link LuaFunction} directly without  | ||||
|  * creating a {@link Prototype} or {@link LuaClosure}. | ||||
|  * <p>  | ||||
|  * Since a {@link LuaClosure} is a {@link LuaFunction} which is a {@link LuaValue},  | ||||
|  * all the value operations can be used directly such as: | ||||
|  * <ul> | ||||
|  * <li>{@link LuaValue#setfenv(LuaValue)}</li> | ||||
|  * <li>{@link LuaValue#call()}</li> | ||||
|  * <li>{@link LuaValue#call(LuaValue)}</li> | ||||
|  * <li>{@link LuaValue#invoke()}</li> | ||||
|  * <li>{@link LuaValue#invoke(Varargs)}</li> | ||||
|  * <li>{@link LuaValue#method(String)}</li> | ||||
|  * <li>{@link LuaValue#method(String,LuaValue)}</li> | ||||
|  * <li>{@link LuaValue#invokemethod(String)}</li> | ||||
|  * <li>{@link LuaValue#invokemethod(String,Varargs)}</li> | ||||
|  * <li> ...</li>  | ||||
|  * </ul> | ||||
|  * @see LuaValue | ||||
|  * @see LuaFunction | ||||
|  * @see LuaValue#isclosure() | ||||
|  * @see LuaValue#checkclosure() | ||||
|  * @see LuaValue#optclosure(LuaClosure) | ||||
|  * @see LoadState | ||||
|  * @see LoadState#compiler | ||||
|  */ | ||||
| public class LuaClosure extends LuaFunction { | ||||
| 	private static final UpValue[] NOUPVALUES = new UpValue[0]; | ||||
| 	 | ||||
| 	public final Prototype p; | ||||
| 	public final UpValue[] upValues; | ||||
| 	 | ||||
| 	LuaClosure() { | ||||
| 		p = null; | ||||
| 		upValues = null; | ||||
| 	} | ||||
| 	/** Supply the initial environment */ | ||||
| 	public LuaClosure(Prototype p, LuaValue env) { | ||||
| 		super( env ); | ||||
| 		this.p = p; | ||||
| 		this.upValues = p.nups>0? new UpValue[p.nups]: NOUPVALUES; | ||||
| 	} | ||||
| 	 | ||||
| 	protected LuaClosure(int nupvalues, LuaValue env) { | ||||
| 		super( env ); | ||||
| 		this.p = null; | ||||
| 		this.upValues = nupvalues>0? new UpValue[nupvalues]: NOUPVALUES; | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean isclosure() { | ||||
| 		return true; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaClosure optclosure(LuaClosure defval) { | ||||
| 		return this; | ||||
| 	} | ||||
|  | ||||
| 	public LuaClosure checkclosure() { | ||||
| 		return this; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue getmetatable() {  | ||||
| 		return s_metatable;  | ||||
| 	} | ||||
| 	 | ||||
| 	public final LuaValue call() { | ||||
| 		LuaValue[] stack = new LuaValue[p.maxstacksize]; | ||||
| 		System.arraycopy(NILS, 0, stack, 0, p.maxstacksize); | ||||
| 		return execute(stack,NONE).arg1(); | ||||
| 	} | ||||
|  | ||||
| 	public final LuaValue call(LuaValue arg) { | ||||
| 		LuaValue[] stack = new LuaValue[p.maxstacksize]; | ||||
| 		System.arraycopy(NILS, 0, stack, 0, p.maxstacksize); | ||||
| 		switch ( p.numparams ) { | ||||
| 		default: stack[0]=arg; return execute(stack,NONE).arg1(); | ||||
| 		case 0: return execute(stack,arg).arg1(); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	public final LuaValue call(LuaValue arg1, LuaValue arg2) { | ||||
| 		LuaValue[] stack = new LuaValue[p.maxstacksize]; | ||||
| 		System.arraycopy(NILS, 0, stack, 0, p.maxstacksize); | ||||
| 		switch ( p.numparams ) { | ||||
| 		default: stack[0]=arg1; stack[1]=arg2; return execute(stack,NONE).arg1(); | ||||
| 		case 1: stack[0]=arg1; return execute(stack,arg2).arg1(); | ||||
| 		case 0: return execute(stack,p.is_vararg!=0? varargsOf(arg1,arg2): NONE).arg1(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public final LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { | ||||
| 		LuaValue[] stack = new LuaValue[p.maxstacksize]; | ||||
| 		System.arraycopy(NILS, 0, stack, 0, p.maxstacksize); | ||||
| 		switch ( p.numparams ) { | ||||
| 		default: stack[0]=arg1; stack[1]=arg2; stack[2]=arg3; return execute(stack,NONE).arg1(); | ||||
| 		case 2: stack[0]=arg1; stack[1]=arg2; return execute(stack,arg3).arg1(); | ||||
| 		case 1: stack[0]=arg1; return execute(stack,p.is_vararg!=0? varargsOf(arg2,arg3): NONE).arg1(); | ||||
| 		case 0: return execute(stack,p.is_vararg!=0? varargsOf(arg1,arg2,arg3): NONE).arg1(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public final Varargs invoke(Varargs varargs) { | ||||
| 		return onInvoke( varargs ).eval(); | ||||
| 	} | ||||
| 	 | ||||
| 	public Varargs onInvoke(Varargs varargs) { | ||||
| 		LuaValue[] stack = new LuaValue[p.maxstacksize]; | ||||
| 		System.arraycopy(NILS, 0, stack, 0, p.maxstacksize); | ||||
| 		for ( int i=0; i<p.numparams; i++ ) | ||||
| 			stack[i] = varargs.arg(i+1);		 | ||||
| 		return execute(stack,p.is_vararg!=0? varargs.subargs(p.numparams+1): NONE); | ||||
| 	} | ||||
| 	 | ||||
| 	 | ||||
| 	protected Varargs execute( LuaValue[] stack, Varargs varargs ) { | ||||
| 		// loop through instructions | ||||
| 		int i,a,b,c,pc=0,top=0; | ||||
| 		LuaValue o; | ||||
| 		Varargs v = NONE; | ||||
| 		int[] code = p.code; | ||||
| 		LuaValue[] k = p.k; | ||||
| 		 | ||||
| 		// upvalues are only possible when closures create closures | ||||
| 		UpValue[] openups = p.p.length>0? new UpValue[stack.length]: null; | ||||
| 		 | ||||
| 		// create varargs "arg" table | ||||
| 		if ( p.is_vararg >= Lua.VARARG_NEEDSARG ) | ||||
| 			stack[p.numparams] = new LuaTable(varargs); | ||||
|  | ||||
| 		// debug wants args to this function | ||||
| 		if (DebugLib.DEBUG_ENABLED)  | ||||
| 			DebugLib.debugSetupCall(varargs, stack); | ||||
|  | ||||
| 		// process instructions | ||||
| 		LuaThread.CallStack cs = LuaThread.onCall( this );  | ||||
| 		try { | ||||
| 			while ( true ) { | ||||
| 				if (DebugLib.DEBUG_ENABLED)  | ||||
| 					DebugLib.debugBytecode(pc, v, top); | ||||
| 				 | ||||
| 				// pull out instruction | ||||
| 				i = code[pc++]; | ||||
| 				a = ((i>>6) & 0xff); | ||||
| 				 | ||||
| 				// process the op code | ||||
| 				switch ( i & 0x3f ) { | ||||
| 				 | ||||
| 				case Lua.OP_MOVE:/*	A B	R(A):= R(B)					*/ | ||||
| 					stack[a] = stack[i>>>23]; | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_LOADK:/*	A Bx	R(A):= Kst(Bx)					*/ | ||||
| 					stack[a] = k[i>>>14]; | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_LOADBOOL:/*	A B C	R(A):= (Bool)B: if (C) pc++			*/ | ||||
| 	                stack[a] = (i>>>23!=0)? LuaValue.TRUE: LuaValue.FALSE; | ||||
| 	                if ((i&(0x1ff<<14)) != 0) | ||||
| 	                    pc++; /* skip next instruction (if C) */ | ||||
| 	                continue; | ||||
| 	 | ||||
| 				case Lua.OP_LOADNIL: /*	A B	R(A):= ...:= R(B):= nil			*/ | ||||
| 					for ( b=i>>>23; a<=b; ) | ||||
| 						stack[a++] = LuaValue.NIL; | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_GETUPVAL: /*	A B	R(A):= UpValue[B]				*/ | ||||
| 	                stack[a] = upValues[i>>>23].getValue(); | ||||
| 	                continue; | ||||
| 					 | ||||
| 				case Lua.OP_GETGLOBAL: /*	A Bx	R(A):= Gbl[Kst(Bx)]				*/ | ||||
| 	                stack[a] = env.get(k[i>>>14]); | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_GETTABLE: /*	A B C	R(A):= R(B)[RK(C)]				*/ | ||||
| 	                stack[a] = stack[i>>>23].get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_SETGLOBAL: /*	A Bx	Gbl[Kst(Bx)]:= R(A)				*/ | ||||
| 	                env.set(k[i>>>14], stack[a]); | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_SETUPVAL: /*	A B	UpValue[B]:= R(A)				*/ | ||||
| 					upValues[i>>>23].setValue(stack[a]); | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_SETTABLE: /*	A B C	R(A)[RK(B)]:= RK(C)				*/ | ||||
| 					stack[a].set(((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]), (c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_NEWTABLE: /*	A B C	R(A):= {} (size = B,C)				*/ | ||||
| 					stack[a] = new LuaTable(i>>>23,(i>>14)&0x1ff); | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_SELF: /*	A B C	R(A+1):= R(B): R(A):= R(B)[RK(C)]		*/ | ||||
| 					stack[a+1] = (o = stack[i>>>23]); | ||||
| 					stack[a] = o.get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_ADD: /*	A B C	R(A):= RK(B) + RK(C)				*/ | ||||
| 					stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).add((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_SUB: /*	A B C	R(A):= RK(B) - RK(C)				*/ | ||||
| 					stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).sub((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_MUL: /*	A B C	R(A):= RK(B) * RK(C)				*/ | ||||
| 					stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).mul((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_DIV: /*	A B C	R(A):= RK(B) / RK(C)				*/ | ||||
| 					stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).div((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_MOD: /*	A B C	R(A):= RK(B) % RK(C)				*/ | ||||
| 					stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).mod((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_POW: /*	A B C	R(A):= RK(B) ^ RK(C)				*/ | ||||
| 					stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).pow((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]); | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_UNM: /*	A B	R(A):= -R(B)					*/ | ||||
| 					stack[a] = stack[i>>>23].neg(); | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_NOT: /*	A B	R(A):= not R(B)				*/ | ||||
| 					stack[a] = stack[i>>>23].not(); | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_LEN: /*	A B	R(A):= length of R(B)				*/ | ||||
| 					stack[a] = stack[i>>>23].len(); | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_CONCAT: /*	A B C	R(A):= R(B).. ... ..R(C)			*/ | ||||
| 					b = i>>>23; | ||||
| 					c = (i>>14)&0x1ff; | ||||
| 					{ | ||||
| 						if ( c > b+1 ) { | ||||
| 							Buffer sb = stack[c].buffer(); | ||||
| 							while ( --c>=b )  | ||||
| 								sb = stack[c].concat(sb); | ||||
| 							stack[a] = sb.value(); | ||||
| 						} else { | ||||
| 							stack[a] = stack[c-1].concat(stack[c]); | ||||
| 						} | ||||
| 					} | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_JMP: /*	sBx	pc+=sBx					*/ | ||||
| 					pc  += (i>>>14)-0x1ffff; | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_EQ: /*	A B C	if ((RK(B) == RK(C)) ~= A) then pc++		*/ | ||||
| 					if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).eq_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) )  | ||||
| 						++pc; | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_LT: /*	A B C	if ((RK(B) <  RK(C)) ~= A) then pc++  		*/ | ||||
| 					if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).lt_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) )  | ||||
| 						++pc; | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_LE: /*	A B C	if ((RK(B) <= RK(C)) ~= A) then pc++  		*/ | ||||
| 					if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).lteq_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) )  | ||||
| 						++pc; | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_TEST: /*	A C	if not (R(A) <=> C) then pc++			*/  | ||||
| 					if ( stack[a].toboolean() != ((i&(0x1ff<<14))!=0) )  | ||||
| 						++pc; | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_TESTSET: /*	A B C	if (R(B) <=> C) then R(A):= R(B) else pc++	*/ | ||||
| 					/* note: doc appears to be reversed */ | ||||
| 					if ( (o=stack[i>>>23]).toboolean() != ((i&(0x1ff<<14))!=0) )  | ||||
| 						++pc; | ||||
| 					else | ||||
| 						stack[a] = o; // TODO: should be sBx?  | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_CALL: /*	A B C	R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */ | ||||
| 					switch ( i & (Lua.MASK_B | Lua.MASK_C) ) { | ||||
| 					case (1<<Lua.POS_B) | (0<<Lua.POS_C): v=stack[a].invoke(NONE); top=a+v.narg(); continue; | ||||
| 					case (2<<Lua.POS_B) | (0<<Lua.POS_C): v=stack[a].invoke(stack[a+1]); top=a+v.narg(); continue; | ||||
| 					case (1<<Lua.POS_B) | (1<<Lua.POS_C): stack[a].call(); continue; | ||||
| 					case (2<<Lua.POS_B) | (1<<Lua.POS_C): stack[a].call(stack[a+1]); continue; | ||||
| 					case (3<<Lua.POS_B) | (1<<Lua.POS_C): stack[a].call(stack[a+1],stack[a+2]); continue; | ||||
| 					case (4<<Lua.POS_B) | (1<<Lua.POS_C): stack[a].call(stack[a+1],stack[a+2],stack[a+3]); continue; | ||||
| 					case (1<<Lua.POS_B) | (2<<Lua.POS_C): stack[a] = stack[a].call(); continue; | ||||
| 					case (2<<Lua.POS_B) | (2<<Lua.POS_C): stack[a] = stack[a].call(stack[a+1]); continue; | ||||
| 					case (3<<Lua.POS_B) | (2<<Lua.POS_C): stack[a] = stack[a].call(stack[a+1],stack[a+2]); continue; | ||||
| 					case (4<<Lua.POS_B) | (2<<Lua.POS_C): stack[a] = stack[a].call(stack[a+1],stack[a+2],stack[a+3]); continue; | ||||
| 					default: | ||||
| 						b = i>>>23; | ||||
| 						c = (i>>14)&0x1ff; | ||||
| 						v = b>0?  | ||||
| 							varargsOf(stack,a+1,b-1): // exact arg count | ||||
| 							varargsOf(stack, a+1, top-v.narg()-(a+1), v); // from prev top  | ||||
| 						v = stack[a].invoke(v); | ||||
| 						if ( c > 0 ) { | ||||
| 							while ( --c > 0 ) | ||||
| 								stack[a+c-1] = v.arg(c); | ||||
| 							v = NONE; // TODO: necessary? | ||||
| 						} else { | ||||
| 							top = a + v.narg(); | ||||
| 						} | ||||
| 						continue; | ||||
| 					} | ||||
| 					 | ||||
| 				case Lua.OP_TAILCALL: /*	A B C	return R(A)(R(A+1), ... ,R(A+B-1))		*/ | ||||
| 					switch ( i & Lua.MASK_B ) { | ||||
| 					case (1<<Lua.POS_B): return new TailcallVarargs(stack[a], NONE); | ||||
| 					case (2<<Lua.POS_B): return new TailcallVarargs(stack[a], stack[a+1]); | ||||
| 					case (3<<Lua.POS_B): return new TailcallVarargs(stack[a], varargsOf(stack[a+1],stack[a+2])); | ||||
| 					case (4<<Lua.POS_B): return new TailcallVarargs(stack[a], varargsOf(stack[a+1],stack[a+2],stack[a+3])); | ||||
| 					default: | ||||
| 						b = i>>>23; | ||||
| 						v = b>0?  | ||||
| 							varargsOf(stack,a+1,b-1): // exact arg count | ||||
| 							varargsOf(stack, a+1, top-v.narg()-(a+1), v); // from prev top  | ||||
| 						return new TailcallVarargs( stack[a], v ); | ||||
| 					} | ||||
| 					 | ||||
| 				case Lua.OP_RETURN: /*	A B	return R(A), ... ,R(A+B-2)	(see note)	*/ | ||||
| 					b = i>>>23; | ||||
| 					switch ( b ) { | ||||
| 					case 0: return varargsOf(stack, a, top-v.narg()-a, v);  | ||||
| 					case 1: return NONE; | ||||
| 					case 2: return stack[a];  | ||||
| 					default: | ||||
| 						return varargsOf(stack, a, b-1); | ||||
| 					} | ||||
| 					 | ||||
| 				case Lua.OP_FORLOOP: /*	A sBx	R(A)+=R(A+2): if R(A) <?= R(A+1) then { pc+=sBx: R(A+3)=R(A) }*/ | ||||
| 					{ | ||||
| 			            LuaValue limit = stack[a + 1]; | ||||
| 						LuaValue step  = stack[a + 2]; | ||||
| 						LuaValue idx   = step.add(stack[a]); | ||||
| 			            if (step.gt_b(0)? idx.lteq_b(limit): idx.gteq_b(limit)) { | ||||
| 		                    stack[a] = idx; | ||||
| 		                    stack[a + 3] = idx; | ||||
| 		                    pc += (i>>>14)-0x1ffff; | ||||
| 			            } | ||||
| 					} | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_FORPREP: /*	A sBx	R(A)-=R(A+2): pc+=sBx				*/ | ||||
| 					{ | ||||
| 						LuaValue init  = stack[a].checknumber("'for' initial value must be a number"); | ||||
| 						LuaValue limit = stack[a + 1].checknumber("'for' limit must be a number"); | ||||
| 						LuaValue step  = stack[a + 2].checknumber("'for' step must be a number"); | ||||
| 						stack[a] = init.sub(step); | ||||
| 						stack[a + 1] = limit; | ||||
| 						stack[a + 2] = step; | ||||
| 						pc += (i>>>14)-0x1ffff; | ||||
| 					} | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_TFORLOOP: /* | ||||
| 									 * A C R(A+3), ... ,R(A+2+C):= R(A)(R(A+1), | ||||
| 									 * R(A+2)): if R(A+3) ~= nil then R(A+2)=R(A+3) | ||||
| 									 * else pc++ | ||||
| 									 */ | ||||
| 					// TODO: stack call on for loop body, such as:   stack[a].call(ci); | ||||
| 					v = stack[a].invoke(varargsOf(stack[a+1],stack[a+2])); | ||||
| 					if ( (o=v.arg1()).isnil() ) | ||||
| 						++pc; | ||||
| 					else { | ||||
| 						stack[a+2] = stack[a+3] = o; | ||||
| 						for ( c=(i>>14)&0x1ff; c>1; --c ) | ||||
| 							stack[a+2+c] = v.arg(c); | ||||
| 						v = NONE; // todo: necessary?  | ||||
| 					} | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_SETLIST: /*	A B C	R(A)[(C-1)*FPF+i]:= R(A+i), 1 <= i <= B	*/ | ||||
| 					{ | ||||
| 		                if ( (c=(i>>14)&0x1ff) == 0 ) | ||||
| 		                    c = code[pc++]; | ||||
| 		                int offset = (c-1) * Lua.LFIELDS_PER_FLUSH; | ||||
| 		                o = stack[a]; | ||||
| 		                if ( (b=i>>>23) == 0 ) { | ||||
| 		                    b = top - a - 1; | ||||
| 		                    int m = b - v.narg();  | ||||
| 		                	int j=1; | ||||
| 		                	for ( ;j<=m; j++ ) | ||||
| 		                    	o.set(offset+j, stack[a + j]); | ||||
| 		                	for ( ;j<=b; j++ ) | ||||
| 		                    	o.set(offset+j, v.arg(j-m)); | ||||
| 		                } else { | ||||
| 		                    o.presize( offset + b ); | ||||
| 		                    for (int j=1; j<=b; j++) | ||||
| 		                    	o.set(offset+j, stack[a + j]); | ||||
| 		                } | ||||
| 					} | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_CLOSE: /*	A 	close all variables in the stack up to (>=) R(A)*/ | ||||
| 					for ( b=openups.length; --b>=a; ) | ||||
| 						if ( openups[b]!=null ) { | ||||
| 							openups[b].close(); | ||||
| 							openups[b] = null; | ||||
| 						} | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_CLOSURE: /*	A Bx	R(A):= closure(KPROTO[Bx], R(A), ... ,R(A+n))	*/ | ||||
| 					{ | ||||
| 						Prototype newp = p.p[i>>>14]; | ||||
| 						LuaClosure newcl = new LuaClosure(newp, env); | ||||
| 						for ( int j=0, nup=newp.nups; j<nup; ++j ) { | ||||
| 							i = code[pc++]; | ||||
| 							//b = B(i); | ||||
| 							b = i>>>23; | ||||
| 							newcl.upValues[j] = (i&4) != 0?  | ||||
| 									upValues[b]: | ||||
| 									openups[b]!=null? openups[b]: (openups[b]=new UpValue(stack,b)); | ||||
| 						} | ||||
| 						stack[a] = newcl; | ||||
| 					} | ||||
| 					continue; | ||||
| 					 | ||||
| 				case Lua.OP_VARARG: /*	A B	R(A), R(A+1), ..., R(A+B-1) = vararg		*/ | ||||
| 					b = i>>>23; | ||||
| 					if ( b == 0 ) { | ||||
| 						top = a + (b = varargs.narg()); | ||||
| 						v = varargs; | ||||
| 					} else {  | ||||
| 						for ( int j=1; j<b; ++j ) | ||||
| 							stack[a+j-1] = varargs.arg(j); | ||||
| 					} | ||||
| 					continue;				 | ||||
| 				} | ||||
| 			} | ||||
| 		} catch ( LuaError le ) { | ||||
| 			throw le; | ||||
| 		} catch ( Exception e ) { | ||||
| 			throw new LuaError(e); | ||||
| 		} finally { | ||||
| 			cs.onReturn(); | ||||
| 			if ( openups != null ) | ||||
| 				for ( int u=openups.length; --u>=0; ) | ||||
| 					if ( openups[u] != null ) | ||||
| 						openups[u].close(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	protected LuaValue getUpvalue(int i) { | ||||
| 		return upValues[i].getValue(); | ||||
| 	} | ||||
| 	 | ||||
| 	protected void setUpvalue(int i, LuaValue v) { | ||||
| 		upValues[i].setValue(v); | ||||
| 	} | ||||
| } | ||||
| @@ -1,288 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
| import org.luaj.vm2.lib.MathLib; | ||||
|  | ||||
| /** | ||||
|  * Extension of {@link LuaNumber} which can hold a Java double as its value.  | ||||
|  * <p> | ||||
|  * These instance are not instantiated directly by clients, but indirectly  | ||||
|  * via the static functions {@link LuaValue#valueOf(int)} or {@link LuaValue#valueOf(double)} | ||||
|  * functions.  This ensures that values which can be represented as int  | ||||
|  * are wrapped in {@link LuaInteger} instead of {@link LuaDouble}.   | ||||
|  * <p> | ||||
|  * Almost all API's implemented in LuaDouble are defined and documented in {@link LuaValue}. | ||||
|  * <p> | ||||
|  * However the constants {@link #NAN}, {@link #POSINF}, {@link #NEGINF}, | ||||
|  * {@link #JSTR_NAN}, {@link #JSTR_POSINF}, and {@link #JSTR_NEGINF} may be useful  | ||||
|  * when dealing with Nan or Infinite values.  | ||||
|  * <p> | ||||
|  * LuaDouble also defines functions for handling the unique math rules of lua devision and modulo in | ||||
|  * <ul> | ||||
|  * <li>{@link #ddiv(double, double)}</li> | ||||
|  * <li>{@link #ddiv_d(double, double)}</li> | ||||
|  * <li>{@link #dmod(double, double)}</li> | ||||
|  * <li>{@link #dmod_d(double, double)}</li> | ||||
|  * </ul>  | ||||
|  * <p> | ||||
|  * @see LuaValue | ||||
|  * @see LuaNumber | ||||
|  * @see LuaInteger | ||||
|  * @see LuaValue#valueOf(int) | ||||
|  * @see LuaValue#valueOf(double) | ||||
|  */ | ||||
| public class LuaDouble extends LuaNumber { | ||||
|  | ||||
| 	/** Constant LuaDouble representing NaN (not a number) */ | ||||
| 	public static final LuaDouble NAN    = new LuaDouble( Double.NaN ); | ||||
| 	 | ||||
| 	/** Constant LuaDouble representing positive infinity */ | ||||
| 	public static final LuaDouble POSINF = new LuaDouble( Double.POSITIVE_INFINITY ); | ||||
| 	 | ||||
| 	/** Constant LuaDouble representing negative infinity */ | ||||
| 	public static final LuaDouble NEGINF = new LuaDouble( Double.NEGATIVE_INFINITY ); | ||||
| 	 | ||||
| 	/** Constant String representation for NaN (not a number), "nan" */ | ||||
| 	public static final String JSTR_NAN    = "nan"; | ||||
| 	 | ||||
| 	/** Constant String representation for positive infinity, "inf" */ | ||||
| 	public static final String JSTR_POSINF = "inf"; | ||||
|  | ||||
| 	/** Constant String representation for negative infinity, "-inf" */ | ||||
| 	public static final String JSTR_NEGINF = "-inf"; | ||||
| 	 | ||||
| 	/** The value being held by this instance. */ | ||||
| 	final double v; | ||||
|  | ||||
| 	public static LuaNumber valueOf(double d) { | ||||
| 		int id = (int) d; | ||||
| 		return d==id? (LuaNumber) LuaInteger.valueOf(id): (LuaNumber) new LuaDouble(d); | ||||
| 	} | ||||
| 	 | ||||
| 	/** Don't allow ints to be boxed by DoubleValues  */ | ||||
| 	private LuaDouble(double d) { | ||||
| 		this.v = d; | ||||
| 	} | ||||
|  | ||||
| 	public int hashCode() { | ||||
| 		long l = Double.doubleToLongBits(v); | ||||
| 		return ((int)(l>>32)) | (int) l; | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean islong() { | ||||
| 		return v == (long) v;  | ||||
| 	} | ||||
| 	 | ||||
| 	public byte    tobyte()        { return (byte) (long) v; } | ||||
| 	public char    tochar()        { return (char) (long) v; } | ||||
| 	public double  todouble()      { return v; } | ||||
| 	public float   tofloat()       { return (float) v; } | ||||
| 	public int     toint()         { return (int) (long) v; } | ||||
| 	public long    tolong()        { return (long) v; } | ||||
| 	public short   toshort()       { return (short) (long) v; } | ||||
|  | ||||
| 	public double      optdouble(double defval)        { return v; } | ||||
| 	public int         optint(int defval)              { return (int) (long) v;  } | ||||
| 	public LuaInteger  optinteger(LuaInteger defval)   { return LuaInteger.valueOf((int) (long)v); } | ||||
| 	public long        optlong(long defval)            { return (long) v; } | ||||
| 	 | ||||
| 	public LuaInteger  checkinteger()                  { return LuaInteger.valueOf( (int) (long) v ); } | ||||
| 	 | ||||
| 	// unary operators | ||||
| 	public LuaValue neg() { return valueOf(-v); } | ||||
| 	 | ||||
| 	// object equality, used for key comparison | ||||
| 	public boolean equals(Object o) { return o instanceof LuaDouble? ((LuaDouble)o).v == v: false; } | ||||
| 	 | ||||
| 	// equality w/ metatable processing | ||||
| 	public LuaValue eq( LuaValue val )        { return val.raweq(v)? TRUE: FALSE; } | ||||
| 	public boolean eq_b( LuaValue val )       { return val.raweq(v); } | ||||
|  | ||||
| 	// equality w/o metatable processing | ||||
| 	public boolean raweq( LuaValue val )      { return val.raweq(v); } | ||||
| 	public boolean raweq( double val )        { return v == val; } | ||||
| 	public boolean raweq( int val )           { return v == val; } | ||||
| 	 | ||||
| 	// basic binary arithmetic | ||||
| 	public LuaValue   add( LuaValue rhs )        { return rhs.add(v); } | ||||
| 	public LuaValue   add( double lhs )     { return LuaDouble.valueOf(lhs + v); } | ||||
| 	public LuaValue   sub( LuaValue rhs )        { return rhs.subFrom(v); } | ||||
| 	public LuaValue   sub( double rhs )        { return LuaDouble.valueOf(v - rhs); } | ||||
| 	public LuaValue   sub( int rhs )        { return LuaDouble.valueOf(v - rhs); } | ||||
| 	public LuaValue   subFrom( double lhs )   { return LuaDouble.valueOf(lhs - v); } | ||||
| 	public LuaValue   mul( LuaValue rhs )        { return rhs.mul(v); } | ||||
| 	public LuaValue   mul( double lhs )   { return LuaDouble.valueOf(lhs * v); } | ||||
| 	public LuaValue   mul( int lhs )      { return LuaDouble.valueOf(lhs * v); } | ||||
| 	public LuaValue   pow( LuaValue rhs )        { return rhs.powWith(v); } | ||||
| 	public LuaValue   pow( double rhs )        { return MathLib.dpow(v,rhs); } | ||||
| 	public LuaValue   pow( int rhs )        { return MathLib.dpow(v,rhs); } | ||||
| 	public LuaValue   powWith( double lhs )   { return MathLib.dpow(lhs,v); } | ||||
| 	public LuaValue   powWith( int lhs )      { return MathLib.dpow(lhs,v); } | ||||
| 	public LuaValue   div( LuaValue rhs )        { return rhs.divInto(v); } | ||||
| 	public LuaValue   div( double rhs )        { return LuaDouble.ddiv(v,rhs); } | ||||
| 	public LuaValue   div( int rhs )        { return LuaDouble.ddiv(v,rhs); } | ||||
| 	public LuaValue   divInto( double lhs )   { return LuaDouble.ddiv(lhs,v); } | ||||
| 	public LuaValue   mod( LuaValue rhs )        { return rhs.modFrom(v); } | ||||
| 	public LuaValue   mod( double rhs )        { return LuaDouble.dmod(v,rhs); } | ||||
| 	public LuaValue   mod( int rhs )        { return LuaDouble.dmod(v,rhs); } | ||||
| 	public LuaValue   modFrom( double lhs )   { return LuaDouble.dmod(lhs,v); } | ||||
| 	 | ||||
| 	 | ||||
| 	/** Divide two double numbers according to lua math, and return a {@link LuaValue} result. | ||||
| 	 * @param lhs Left-hand-side of the division. | ||||
| 	 * @param rhs Right-hand-side of the division. | ||||
| 	 * @return {@link LuaValue} for the result of the division,  | ||||
| 	 * taking into account positive and negiative infinity, and Nan | ||||
| 	 * @see #ddiv_d(double, double)  | ||||
| 	 */ | ||||
| 	public static LuaValue ddiv(double lhs, double rhs) { | ||||
| 		return rhs!=0? valueOf( lhs / rhs ): lhs>0? POSINF: lhs==0? NAN: NEGINF;	 | ||||
| 	} | ||||
| 	 | ||||
| 	/** Divide two double numbers according to lua math, and return a double result. | ||||
| 	 * @param lhs Left-hand-side of the division. | ||||
| 	 * @param rhs Right-hand-side of the division. | ||||
| 	 * @return Value of the division, taking into account positive and negative infinity, and Nan | ||||
| 	 * @see #ddiv(double, double) | ||||
| 	 */ | ||||
| 	public static double ddiv_d(double lhs, double rhs) { | ||||
| 		return rhs!=0? lhs / rhs: lhs>0? Double.POSITIVE_INFINITY: lhs==0? Double.NaN: Double.NEGATIVE_INFINITY;	 | ||||
| 	} | ||||
| 	 | ||||
| 	/** Take modulo double numbers according to lua math, and return a {@link LuaValue} result. | ||||
| 	 * @param lhs Left-hand-side of the modulo. | ||||
| 	 * @param rhs Right-hand-side of the modulo. | ||||
| 	 * @return {@link LuaValue} for the result of the modulo,  | ||||
| 	 * using lua's rules for modulo | ||||
| 	 * @see #dmod_d(double, double)  | ||||
| 	 */ | ||||
| 	public static LuaValue dmod(double lhs, double rhs) { | ||||
| 		return rhs!=0? valueOf( lhs-rhs*Math.floor(lhs/rhs) ): NAN; | ||||
| 	} | ||||
|  | ||||
| 	/** Take modulo for double numbers according to lua math, and return a double result. | ||||
| 	 * @param lhs Left-hand-side of the modulo. | ||||
| 	 * @param rhs Right-hand-side of the modulo. | ||||
| 	 * @return double value for the result of the modulo,  | ||||
| 	 * using lua's rules for modulo | ||||
| 	 * @see #dmod(double, double) | ||||
| 	 */ | ||||
| 	public static double dmod_d(double lhs, double rhs) { | ||||
| 		return rhs!=0? lhs-rhs*Math.floor(lhs/rhs): Double.NaN; | ||||
| 	} | ||||
|  | ||||
| 	// relational operators | ||||
| 	public LuaValue   lt( LuaValue rhs )         { return rhs.gt_b(v)? LuaValue.TRUE: FALSE; } | ||||
| 	public LuaValue   lt( double rhs )      { return v < rhs? TRUE: FALSE; } | ||||
| 	public LuaValue   lt( int rhs )         { return v < rhs? TRUE: FALSE; } | ||||
| 	public boolean lt_b( LuaValue rhs )       { return rhs.gt_b(v); } | ||||
| 	public boolean lt_b( int rhs )         { return v < rhs; } | ||||
| 	public boolean lt_b( double rhs )      { return v < rhs; } | ||||
| 	public LuaValue   lteq( LuaValue rhs )       { return rhs.gteq_b(v)? LuaValue.TRUE: FALSE; } | ||||
| 	public LuaValue   lteq( double rhs )    { return v <= rhs? TRUE: FALSE; } | ||||
| 	public LuaValue   lteq( int rhs )       { return v <= rhs? TRUE: FALSE; } | ||||
| 	public boolean lteq_b( LuaValue rhs )     { return rhs.gteq_b(v); } | ||||
| 	public boolean lteq_b( int rhs )       { return v <= rhs; } | ||||
| 	public boolean lteq_b( double rhs )    { return v <= rhs; } | ||||
| 	public LuaValue   gt( LuaValue rhs )         { return rhs.lt_b(v)? LuaValue.TRUE: FALSE; } | ||||
| 	public LuaValue   gt( double rhs )      { return v > rhs? TRUE: FALSE; } | ||||
| 	public LuaValue   gt( int rhs )         { return v > rhs? TRUE: FALSE; } | ||||
| 	public boolean gt_b( LuaValue rhs )       { return rhs.lt_b(v); } | ||||
| 	public boolean gt_b( int rhs )         { return v > rhs; } | ||||
| 	public boolean gt_b( double rhs )      { return v > rhs; } | ||||
| 	public LuaValue   gteq( LuaValue rhs )       { return rhs.lteq_b(v)? LuaValue.TRUE: FALSE; } | ||||
| 	public LuaValue   gteq( double rhs )    { return v >= rhs? TRUE: FALSE; } | ||||
| 	public LuaValue   gteq( int rhs )       { return v >= rhs? TRUE: FALSE; } | ||||
| 	public boolean gteq_b( LuaValue rhs )     { return rhs.lteq_b(v); } | ||||
| 	public boolean gteq_b( int rhs )       { return v >= rhs; } | ||||
| 	public boolean gteq_b( double rhs )    { return v >= rhs; } | ||||
| 	 | ||||
| 	// string comparison | ||||
| 	public int strcmp( LuaString rhs )      { typerror("attempt to compare number with string"); return 0; } | ||||
| 			 | ||||
| 	public String tojstring() { | ||||
| 		/* | ||||
| 		if ( v == 0.0 ) { // never occurs in J2me  | ||||
| 			long bits = Double.doubleToLongBits( v ); | ||||
| 			return ( bits >> 63 == 0 ) ? "0" : "-0"; | ||||
| 		} | ||||
| 		*/ | ||||
| 		long l = (long) v; | ||||
| 		if ( l == v )  | ||||
| 			return Long.toString(l); | ||||
| 		if ( Double.isNaN(v) ) | ||||
| 			return JSTR_NAN; | ||||
| 		if ( Double.isInfinite(v) )  | ||||
| 			return (v<0? JSTR_NEGINF: JSTR_POSINF); | ||||
| 		return Float.toString((float)v); | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaString strvalue() { | ||||
| 		return LuaString.valueOf(tojstring()); | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaString optstring(LuaString defval) { | ||||
| 		return LuaString.valueOf(tojstring()); | ||||
| 	} | ||||
| 		 | ||||
| 	public LuaValue tostring() { | ||||
| 		return LuaString.valueOf(tojstring()); | ||||
| 	} | ||||
| 	 | ||||
| 	public String optjstring(String defval) { | ||||
| 		return tojstring(); | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaNumber optnumber(LuaNumber defval) { | ||||
| 		return this;  | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean isnumber() { | ||||
| 		return true;  | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean isstring() { | ||||
| 		return true; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue tonumber() { | ||||
| 		return this; | ||||
| 	} | ||||
| 	public int checkint()                { return (int) (long) v; } | ||||
| 	public long checklong()              { return (long) v; } | ||||
| 	public LuaNumber checknumber()       { return this; } | ||||
| 	public double checkdouble()          { return v; } | ||||
| 	 | ||||
| 	public String checkjstring() {  | ||||
| 		return tojstring(); | ||||
| 	} | ||||
| 	public LuaString checkstring() {  | ||||
| 		return LuaString.valueOf(tojstring()); | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue checkvalidkey() { | ||||
| 		if ( Double.isNaN(v) ) | ||||
| 			throw new LuaError("table index expected, got nan"); | ||||
| 		return this;  | ||||
| 	}	 | ||||
| } | ||||
| @@ -1,132 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
| import org.luaj.vm2.lib.DebugLib; | ||||
|  | ||||
| /** | ||||
|  * RuntimeException that is thrown and caught in response to a lua error.  | ||||
|  * <p> | ||||
|  * {@link LuaError} is used wherever a lua call to {@code error()}  | ||||
|  * would be used within a script. | ||||
|  * <p> | ||||
|  * Since it is an unchecked exception inheriting from {@link RuntimeException}, | ||||
|  * Java method signatures do notdeclare this exception, althoug it can  | ||||
|  * be thrown on almost any luaj Java operation. | ||||
|  * This is analagous to the fact that any lua script can throw a lua error at any time. | ||||
|  * <p>    | ||||
|  */ | ||||
| public class LuaError extends RuntimeException { | ||||
| 	private static final long serialVersionUID = 1L; | ||||
| 	 | ||||
| 	private String traceback; | ||||
|  | ||||
| 	/** | ||||
| 	 *  Run the error hook if there is one | ||||
| 	 *  @param msg the message to use in error hook processing.  | ||||
| 	 * */ | ||||
| 	private static String errorHook(String msg) { | ||||
| 		LuaThread thread = LuaThread.getRunning(); | ||||
| 		if ( thread.err != null ) {  | ||||
| 			LuaValue errfunc = thread.err; | ||||
| 			thread.err = null; | ||||
| 			try { | ||||
| 				return errfunc.call( LuaValue.valueOf(msg) ).tojstring(); | ||||
| 			} catch ( Throwable t ) { | ||||
| 				return "error in error handling"; | ||||
| 			} finally { | ||||
| 				thread.err = errfunc; | ||||
| 			} | ||||
| 		} | ||||
| 		return msg; | ||||
| 	} | ||||
| 	 | ||||
| 	private Throwable cause; | ||||
| 	 | ||||
| 	/** Construct LuaError when a program exception occurs.  | ||||
| 	 * <p>  | ||||
| 	 * All errors generated from lua code should throw LuaError(String) instead. | ||||
| 	 * @param cause the Throwable that caused the error, if known.   | ||||
| 	 */ | ||||
| 	public LuaError(Throwable cause) { | ||||
| 		super( errorHook( addFileLine( "vm error: "+cause ) ) ); | ||||
| 		this.cause = cause; | ||||
| 		this.traceback = DebugLib.traceback(1); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Construct a LuaError with a specific message.   | ||||
| 	 *   | ||||
| 	 * @param message message to supply | ||||
| 	 */ | ||||
| 	public LuaError(String message) { | ||||
| 		super( errorHook( addFileLine( message ) ) ); | ||||
| 		this.traceback = DebugLib.traceback(1); | ||||
| 	}		 | ||||
|  | ||||
| 	/** | ||||
| 	 * Construct a LuaError with a message, and level to draw line number information from. | ||||
| 	 * @param message message to supply | ||||
| 	 * @param level where to supply line info from in call stack | ||||
| 	 */ | ||||
| 	public LuaError(String message, int level) { | ||||
| 		super( errorHook( addFileLine( message, level ) ) ); | ||||
| 		this.traceback = DebugLib.traceback(1); | ||||
| 	}	 | ||||
|  | ||||
| 	/**  | ||||
| 	 * Add file and line info to a message at a particular level  | ||||
| 	 * @param message the String message to use | ||||
| 	 * @param level where to supply line info from in call stack | ||||
| 	 * */ | ||||
| 	private static String addFileLine( String message, int level ) { | ||||
| 		if ( message == null ) return null; | ||||
| 		if ( level == 0 ) return message; | ||||
| 		String fileline = DebugLib.fileline(level-1); | ||||
| 		return fileline!=null? fileline+": "+message: message;		 | ||||
| 	} | ||||
|  | ||||
| 	/** Add file and line info for the nearest enclosing closure | ||||
| 	 * @param message the String message to use | ||||
| 	 * */ | ||||
| 	private static String addFileLine( String message ) { | ||||
| 		if ( message == null ) return null; | ||||
| 		String fileline = DebugLib.fileline(); | ||||
| 		return fileline!=null? fileline+": "+message: message;		 | ||||
| 	} | ||||
| 	 | ||||
| 	/** Print the message and stack trace */ | ||||
| 	public void printStackTrace() { | ||||
| 		System.out.println( toString() ); | ||||
| 		if ( traceback != null ) | ||||
| 			System.out.println( traceback ); | ||||
| 	} | ||||
|  | ||||
| 	/**  | ||||
| 	 * Get the cause, if any. | ||||
| 	 */ | ||||
| 	public Throwable getCause() { | ||||
| 		return cause; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| } | ||||
| @@ -1,82 +0,0 @@ | ||||
| /******************************************************************************* | ||||
|  * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
| /**  | ||||
|  * Base class for functions implemented in Java.  | ||||
|  * <p> | ||||
|  * Direct subclass include {@link LibFunction} which is the base class for  | ||||
|  * all built-in library functions coded in Java,  | ||||
|  * and {@link LuaClosure}, which represents a lua closure  | ||||
|  * whose bytecode is interpreted when the function is invoked.     | ||||
|  * @see LuaValue | ||||
|  * @see LibFunction | ||||
|  * @see LuaClosure | ||||
|  */ | ||||
| abstract | ||||
| public class LuaFunction extends LuaValue { | ||||
| 	 | ||||
| 	/** Shared static metatable for all functions and closures. */ | ||||
| 	public static LuaValue s_metatable; | ||||
|  | ||||
| 	protected LuaValue env; | ||||
| 	 | ||||
| 	public LuaFunction() { | ||||
| 		this.env = NIL; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaFunction(LuaValue env) { | ||||
| 		this.env = env; | ||||
| 	} | ||||
|  | ||||
| 	public int type() { | ||||
| 		return TFUNCTION; | ||||
| 	} | ||||
| 	 | ||||
| 	public String typename() { | ||||
| 		return "function"; | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean isfunction() { | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue checkfunction()  { | ||||
| 		return this; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaFunction optfunction(LuaFunction defval) { | ||||
| 		return this;  | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue getmetatable() {  | ||||
| 		return s_metatable;  | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue getfenv() { | ||||
| 		return env; | ||||
| 	} | ||||
|  | ||||
| 	public void setfenv(LuaValue env) { | ||||
| 		this.env = env!=null? env: NIL; | ||||
| 	} | ||||
| } | ||||
| @@ -1,215 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
| import org.luaj.vm2.lib.MathLib; | ||||
|  | ||||
| /** | ||||
|  * Extension of {@link LuaNumber} which can hold a Java int as its value.  | ||||
|  * <p> | ||||
|  * These instance are not instantiated directly by clients, but indirectly  | ||||
|  * via the static functions {@link LuaValue#valueOf(int)} or {@link LuaValue#valueOf(double)} | ||||
|  * functions.  This ensures that policies regarding pooling of instances are  | ||||
|  * encapsulated.   | ||||
|  * <p> | ||||
|  * There are no API's specific to LuaInteger that are useful beyond what is already  | ||||
|  * exposed in {@link LuaValue}. | ||||
|  *  | ||||
|  * @see LuaValue | ||||
|  * @see LuaNumber | ||||
|  * @see LuaDouble | ||||
|  * @see LuaValue#valueOf(int) | ||||
|  * @see LuaValue#valueOf(double) | ||||
|  */ | ||||
| public class LuaInteger extends LuaNumber { | ||||
|  | ||||
| 	private static final LuaInteger[] intValues = new LuaInteger[512]; | ||||
| 	static { | ||||
| 		for ( int i=0; i<512; i++ ) | ||||
| 			intValues[i] = new LuaInteger(i-256); | ||||
| 	} | ||||
|  | ||||
| 	public static LuaInteger valueOf(int i) { | ||||
| 		return i<=255 && i>=-256? intValues[i+256]: new LuaInteger(i); | ||||
| 	}; | ||||
| 	 | ||||
| 	 // TODO consider moving this to LuaValue | ||||
| 	/** Return a LuaNumber that represents the value provided | ||||
| 	 * @param l long value to represent. | ||||
| 	 * @return LuaNumber that is eithe LuaInteger or LuaDouble representing l | ||||
| 	 * @see LuaValue#valueOf(int) | ||||
| 	 * @see LuaValue#valueOf(double) | ||||
| 	 */ | ||||
| 	public static LuaNumber valueOf(long l) { | ||||
| 		int i = (int) l; | ||||
| 		return l==i? (i<=255 && i>=-256? intValues[i+256]:  | ||||
| 			(LuaNumber) new LuaInteger(i)):  | ||||
| 			(LuaNumber) LuaDouble.valueOf(l); | ||||
| 	} | ||||
| 	 | ||||
| 	/** The value being held by this instance. */ | ||||
| 	public final int v; | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Package protected constructor.  | ||||
| 	 * @see LuaValue#valueOf(int) | ||||
| 	 **/ | ||||
| 	LuaInteger(int i) { | ||||
| 		this.v = i; | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean isint() {		return true;	} | ||||
| 	public boolean isinttype() {	return true;	} | ||||
| 	public boolean islong() {		return true;	} | ||||
| 	 | ||||
| 	public byte    tobyte()        { return (byte) v; } | ||||
| 	public char    tochar()        { return (char) v; } | ||||
| 	public double  todouble()      { return v; } | ||||
| 	public float   tofloat()       { return v; } | ||||
| 	public int     toint()         { return v; } | ||||
| 	public long    tolong()        { return v; } | ||||
| 	public short   toshort()       { return (short) v; } | ||||
|  | ||||
| 	public double      optdouble(double defval)            { return v; } | ||||
| 	public int         optint(int defval)                  { return v;  } | ||||
| 	public LuaInteger  optinteger(LuaInteger defval)       { return this; } | ||||
| 	public long        optlong(long defval)                { return v; } | ||||
|  | ||||
| 	public String tojstring() { | ||||
| 		return Integer.toString(v); | ||||
| 	} | ||||
|  | ||||
| 	public LuaString strvalue() { | ||||
| 		return LuaString.valueOf(Integer.toString(v)); | ||||
| 	} | ||||
| 		 | ||||
| 	public LuaString optstring(LuaString defval) { | ||||
| 		return LuaString.valueOf(Integer.toString(v));  | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue tostring() { | ||||
| 		return LuaString.valueOf(Integer.toString(v));  | ||||
| 	} | ||||
| 		 | ||||
| 	public String optjstring(String defval) {  | ||||
| 		return Integer.toString(v);  | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaInteger checkinteger() { | ||||
| 		return this; | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean isstring() { | ||||
| 		return true; | ||||
| 	} | ||||
| 	 | ||||
| 	public int hashCode() { | ||||
| 		return v; | ||||
| 	} | ||||
|  | ||||
| 	// unary operators | ||||
| 	public LuaValue neg() { return valueOf(-(long)v); } | ||||
| 	 | ||||
| 	// object equality, used for key comparison | ||||
| 	public boolean equals(Object o) { return o instanceof LuaInteger? ((LuaInteger)o).v == v: false; } | ||||
| 	 | ||||
| 	// equality w/ metatable processing | ||||
| 	public LuaValue eq( LuaValue val )    { return val.raweq(v)? TRUE: FALSE; } | ||||
| 	public boolean eq_b( LuaValue val )   { return val.raweq(v); } | ||||
| 	 | ||||
| 	// equality w/o metatable processing | ||||
| 	public boolean raweq( LuaValue val )  { return val.raweq(v); } | ||||
| 	public boolean raweq( double val )    { return v == val; } | ||||
| 	public boolean raweq( int val )       { return v == val; } | ||||
| 	 | ||||
| 	// arithmetic operators | ||||
| 	public LuaValue   add( LuaValue rhs )        { return rhs.add(v); } | ||||
| 	public LuaValue   add( double lhs )     { return LuaDouble.valueOf(lhs + v); } | ||||
| 	public LuaValue   add( int lhs )        { return LuaInteger.valueOf(lhs + (long)v); } | ||||
| 	public LuaValue   sub( LuaValue rhs )        { return rhs.subFrom(v); } | ||||
| 	public LuaValue   sub( double rhs )        { return LuaDouble.valueOf(v - rhs); } | ||||
| 	public LuaValue   sub( int rhs )        { return LuaDouble.valueOf(v - rhs); } | ||||
| 	public LuaValue   subFrom( double lhs )   { return LuaDouble.valueOf(lhs - v); } | ||||
| 	public LuaValue   subFrom( int lhs )      { return LuaInteger.valueOf(lhs - (long)v); } | ||||
| 	public LuaValue   mul( LuaValue rhs )        { return rhs.mul(v); } | ||||
| 	public LuaValue   mul( double lhs )   { return LuaDouble.valueOf(lhs * v); } | ||||
| 	public LuaValue   mul( int lhs )      { return LuaInteger.valueOf(lhs * (long)v); } | ||||
| 	public LuaValue   pow( LuaValue rhs )        { return rhs.powWith(v); } | ||||
| 	public LuaValue   pow( double rhs )        { return MathLib.dpow(v,rhs); } | ||||
| 	public LuaValue   pow( int rhs )        { return MathLib.dpow(v,rhs); } | ||||
| 	public LuaValue   powWith( double lhs )   { return MathLib.dpow(lhs,v); } | ||||
| 	public LuaValue   powWith( int lhs )      { return MathLib.dpow(lhs,v); } | ||||
| 	public LuaValue   div( LuaValue rhs )        { return rhs.divInto(v); } | ||||
| 	public LuaValue   div( double rhs )        { return LuaDouble.ddiv(v,rhs); } | ||||
| 	public LuaValue   div( int rhs )        { return LuaDouble.ddiv(v,rhs); } | ||||
| 	public LuaValue   divInto( double lhs )   { return LuaDouble.ddiv(lhs,v); } | ||||
| 	public LuaValue   mod( LuaValue rhs )        { return rhs.modFrom(v); } | ||||
| 	public LuaValue   mod( double rhs )        { return LuaDouble.dmod(v,rhs); } | ||||
| 	public LuaValue   mod( int rhs )        { return LuaDouble.dmod(v,rhs); } | ||||
| 	public LuaValue   modFrom( double lhs )   { return LuaDouble.dmod(lhs,v); } | ||||
| 	 | ||||
| 	// relational operators | ||||
| 	public LuaValue   lt( LuaValue rhs )         { return rhs.gt_b(v)? TRUE: FALSE; }	 | ||||
| 	public LuaValue   lt( double rhs )      { return v < rhs? TRUE: FALSE; } | ||||
| 	public LuaValue   lt( int rhs )         { return v < rhs? TRUE: FALSE; } | ||||
| 	public boolean lt_b( LuaValue rhs )       { return rhs.gt_b(v); } | ||||
| 	public boolean lt_b( int rhs )         { return v < rhs; } | ||||
| 	public boolean lt_b( double rhs )      { return v < rhs; } | ||||
| 	public LuaValue   lteq( LuaValue rhs )       { return rhs.gteq_b(v)? TRUE: FALSE; } | ||||
| 	public LuaValue   lteq( double rhs )    { return v <= rhs? TRUE: FALSE; } | ||||
| 	public LuaValue   lteq( int rhs )       { return v <= rhs? TRUE: FALSE; } | ||||
| 	public boolean lteq_b( LuaValue rhs )     { return rhs.gteq_b(v); } | ||||
| 	public boolean lteq_b( int rhs )       { return v <= rhs; } | ||||
| 	public boolean lteq_b( double rhs )    { return v <= rhs; } | ||||
| 	public LuaValue   gt( LuaValue rhs )         { return rhs.lt_b(v)? TRUE: FALSE; } | ||||
| 	public LuaValue   gt( double rhs )      { return v > rhs? TRUE: FALSE; } | ||||
| 	public LuaValue   gt( int rhs )         { return v > rhs? TRUE: FALSE; } | ||||
| 	public boolean gt_b( LuaValue rhs )       { return rhs.lt_b(v); } | ||||
| 	public boolean gt_b( int rhs )         { return v > rhs; } | ||||
| 	public boolean gt_b( double rhs )      { return v > rhs; } | ||||
| 	public LuaValue   gteq( LuaValue rhs )       { return rhs.lteq_b(v)? TRUE: FALSE; } | ||||
| 	public LuaValue   gteq( double rhs )    { return v >= rhs? TRUE: FALSE; } | ||||
| 	public LuaValue   gteq( int rhs )       { return v >= rhs? TRUE: FALSE; } | ||||
| 	public boolean gteq_b( LuaValue rhs )     { return rhs.lteq_b(v); } | ||||
| 	public boolean gteq_b( int rhs )       { return v >= rhs; } | ||||
| 	public boolean gteq_b( double rhs )    { return v >= rhs; } | ||||
| 	 | ||||
| 	// string comparison | ||||
| 	public int strcmp( LuaString rhs )      { typerror("attempt to compare number with string"); return 0; } | ||||
| 	 | ||||
| 	public int checkint() {  | ||||
| 		return v;  | ||||
| 	} | ||||
| 	public long checklong() { | ||||
| 		return v;  | ||||
| 	} | ||||
| 	public double checkdouble() { | ||||
| 		return v; | ||||
| 	} | ||||
| 	public String checkjstring() {  | ||||
| 		return String.valueOf(v);  | ||||
| 	} | ||||
| 	public LuaString checkstring() {  | ||||
| 		return valueOf( String.valueOf(v) );  | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -1,104 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
| /** | ||||
|  * Class to encapsulate behavior of the singleton instance {@code nil}  | ||||
|  * <p> | ||||
|  * There will be one instance of this class, {@link LuaValue#NIL},  | ||||
|  * per Java virtual machine.   | ||||
|  * However, the {@link Varargs} instance {@link LuaValue#NONE} | ||||
|  * which is the empty list,  | ||||
|  * is also considered treated as a nil value by default.   | ||||
|  * <p> | ||||
|  * Although it is possible to test for nil using Java == operator,  | ||||
|  * the recommended approach is to use the method {@link LuaValue#isnil()}  | ||||
|  * instead.  By using that any ambiguities between  | ||||
|  * {@link LuaValue#NIL} and {@link LuaValue#NONE} are avoided. | ||||
|  * @see LuaValue | ||||
|  * @see LuaValue#NIL | ||||
|  */ | ||||
| public class LuaNil extends LuaValue { | ||||
| 	 | ||||
| 	static final LuaNil _NIL = new LuaNil(); | ||||
| 	 | ||||
| 	public static LuaValue s_metatable; | ||||
| 	 | ||||
| 	LuaNil() {} | ||||
|  | ||||
| 	public int type() { | ||||
| 		return LuaValue.TNIL; | ||||
| 	} | ||||
| 	 | ||||
| 	public String typename() { | ||||
| 		return "nil"; | ||||
| 	} | ||||
| 	 | ||||
| 	public String tojstring() { | ||||
| 		return "nil"; | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue not()  {  | ||||
| 		return LuaValue.TRUE;   | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean toboolean() {  | ||||
| 		return false;  | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean isnil() { | ||||
| 		return true; | ||||
| 	} | ||||
| 		 | ||||
| 	public LuaValue getmetatable() {  | ||||
| 		return s_metatable;  | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean equals(Object o) { | ||||
| 		return o instanceof LuaNil; | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue checknotnil() {  | ||||
| 		return argerror("value"); | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue checkvalidkey() { | ||||
| 		return typerror("table index");  | ||||
| 	} | ||||
|  | ||||
| 	// optional argument conversions - nil alwas falls badk to default value | ||||
| 	public boolean     optboolean(boolean defval)          { return defval; } | ||||
| 	public LuaClosure  optclosure(LuaClosure defval)       { return defval; } | ||||
| 	public double      optdouble(double defval)               { return defval; } | ||||
| 	public LuaFunction optfunction(LuaFunction defval)     { return defval; } | ||||
| 	public int         optint(int defval)                  { return defval; } | ||||
| 	public LuaInteger  optinteger(LuaInteger defval)       { return defval; } | ||||
| 	public long        optlong(long defval)                { return defval; } | ||||
| 	public LuaNumber   optnumber(LuaNumber defval)         { return defval; } | ||||
| 	public LuaTable    opttable(LuaTable defval)           { return defval; } | ||||
| 	public LuaThread   optthread(LuaThread defval)         { return defval; } | ||||
| 	public String      optjstring(String defval)            { return defval; } | ||||
| 	public LuaString   optstring(LuaString defval)         { return defval; } | ||||
| 	public Object      optuserdata(Object defval)          { return defval; } | ||||
| 	public Object      optuserdata(Class c, Object defval) { return defval; } | ||||
| 	public LuaValue    optvalue(LuaValue defval)           { return defval; } | ||||
| } | ||||
| @@ -1,81 +0,0 @@ | ||||
| /******************************************************************************* | ||||
|  * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
| /**  | ||||
|  * Base class for representing numbers as lua values directly.  | ||||
|  * <p> | ||||
|  * The main subclasses are {@link LuaInteger} which holds values that fit in a java int,  | ||||
|  * and {@link LuaDouble} which holds all other number values. | ||||
|  * @see LuaInteger | ||||
|  * @see LuaDouble | ||||
|  * @see LuaValue | ||||
|  *  | ||||
|  */ | ||||
| abstract | ||||
| public class LuaNumber extends LuaValue { | ||||
|  | ||||
| 	/** Shared static metatable for all number values represented in lua. */ | ||||
| 	public static LuaValue s_metatable; | ||||
| 	 | ||||
| 	public int type() { | ||||
| 		return TNUMBER; | ||||
| 	} | ||||
| 	 | ||||
| 	public String typename() { | ||||
| 		return "number"; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaNumber checknumber() { | ||||
| 		return this;  | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaNumber checknumber(String errmsg) { | ||||
| 		return this;  | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaNumber optnumber(LuaNumber defval) { | ||||
| 		return this;  | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue tonumber() { | ||||
| 		return this; | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean isnumber() { | ||||
| 		return true; | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean isstring() { | ||||
| 		return true; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue getmetatable() {  | ||||
| 		return s_metatable;  | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue concat(LuaValue rhs)      { return rhs.concatTo(this); } | ||||
| 	public Buffer   concat(Buffer rhs)        { return rhs.concatTo(this); } | ||||
| 	public LuaValue concatTo(LuaNumber lhs)   { return strvalue().concatTo(lhs.strvalue()); } | ||||
| 	public LuaValue concatTo(LuaString lhs)   { return strvalue().concatTo(lhs); } | ||||
|  | ||||
| } | ||||
| @@ -1,749 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
|  | ||||
| import java.io.ByteArrayInputStream; | ||||
| import java.io.DataOutputStream; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.lang.String; | ||||
| import java.lang.ref.WeakReference; | ||||
| import java.util.Hashtable; | ||||
|  | ||||
| import org.luaj.vm2.lib.MathLib; | ||||
| import org.luaj.vm2.lib.StringLib; | ||||
|  | ||||
| /** | ||||
|  * Subclass of {@link LuaValue} for representing lua strings.  | ||||
|  * <p> | ||||
|  * Because lua string values are more nearly sequences of bytes than  | ||||
|  * sequences of characters or unicode code points, the {@link LuaString} | ||||
|  * implementation holds the string value in an internal byte array.   | ||||
|  * <p> | ||||
|  * {@link LuaString} values are generally not mutable once constructed,  | ||||
|  * so multiple {@link LuaString} values can chare a single byte array. | ||||
|  * <p> | ||||
|  * Currently {@link LuaString}s are pooled via a centrally managed weak table. | ||||
|  * To ensure that as many string values as possible take advantage of this,  | ||||
|  * Constructors are not exposed directly.  As with number, booleans, and nil,  | ||||
|  * instance construction should be via {@link LuaValue#valueOf(byte[])} or similar API. | ||||
|  * <p> | ||||
|  * When Java Strings are used to initialize {@link LuaString} data, the UTF8 encoding is assumed.  | ||||
|  * The functions  | ||||
|  * {@link LuaString#lengthAsUtf8(char[]), | ||||
|  * {@link LuaString#encodeToUtf8(char[], byte[], int)}, and  | ||||
|  * {@link LuaString#decodeAsUtf8(byte[], int, int)  | ||||
|  * are used to convert back and forth between UTF8 byte arrays and character arrays. | ||||
|  *  | ||||
|  * @see LuaValue | ||||
|  * @see LuaValue#valueOf(String) | ||||
|  * @see LuaValue#valueOf(byte[]) | ||||
|  */ | ||||
| public class LuaString extends LuaValue { | ||||
|  | ||||
| 	/** The singleton instance representing lua {@code true} */ | ||||
| 	public static LuaValue s_metatable; | ||||
|  | ||||
| 	/** The bytes for the string */ | ||||
| 	public final byte[] m_bytes; | ||||
| 	 | ||||
| 	/** The offset into the byte array, 0 means start at the first byte */ | ||||
| 	public final int    m_offset; | ||||
| 	 | ||||
| 	/** The number of bytes that comprise this string */ | ||||
| 	public final int    m_length; | ||||
|  | ||||
| 	private static final Hashtable index_java = new Hashtable(); | ||||
|  | ||||
| 	private final static LuaString index_get(Hashtable indextable, Object key) { | ||||
| 		WeakReference w = (WeakReference) indextable.get(key); | ||||
| 		return w!=null? (LuaString) w.get(): null; | ||||
| 	} | ||||
| 	 | ||||
| 	private final static void index_set(Hashtable indextable, Object key, LuaString value) { | ||||
| 		indextable.put(key, new WeakReference(value)); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Get a {@link LuaString} instance whose bytes match  | ||||
| 	 * the supplied Java String using the UTF8 encoding.  | ||||
| 	 * @param string Java String containing characters to encode as UTF8 | ||||
| 	 * @return {@link LuaString} with UTF8 bytes corresponding to the supplied String | ||||
| 	 */ | ||||
| 	public static LuaString valueOf(String string) { | ||||
| 		LuaString s = index_get( index_java, string ); | ||||
| 		if ( s != null ) return s; | ||||
| 		char[] c = string.toCharArray(); | ||||
|         /* DAN200 START */ | ||||
|         /* | ||||
| 		byte[] b = new byte[lengthAsUtf8(c)]; | ||||
| 		encodeToUtf8(c, b, 0); | ||||
| 		*/ | ||||
|         byte[] b = new byte[c.length]; | ||||
|         for( int i=0; i<b.length; ++i ) | ||||
|         { | ||||
|             char ch = c[i]; | ||||
|             b[i] = (ch < 256) ? (byte)ch : (byte)'?'; | ||||
|         } | ||||
|         /* DAN200 END */ | ||||
| 		s = valueOf(b, 0, b.length); | ||||
| 		index_set( index_java, string, s ); | ||||
| 		return s; | ||||
| 	} | ||||
|  | ||||
| 	// TODO: should this be deprecated or made private? | ||||
| 	/** Construct a {@link LuaString} around a byte array without copying the contents. | ||||
| 	 * <p> | ||||
| 	 * The array is used directly after this is called, so clients must not change contents. | ||||
| 	 * <p> | ||||
| 	 * @param bytes byte buffer | ||||
| 	 * @param off offset into the byte buffer | ||||
| 	 * @param len length of the byte buffer | ||||
| 	 * @return {@link LuaString} wrapping the byte buffer | ||||
| 	 */ | ||||
| 	public static LuaString valueOf(byte[] bytes, int off, int len) {  | ||||
| 		return new LuaString(bytes, off, len); | ||||
| 	} | ||||
| 	 | ||||
| 	/** Construct a {@link LuaString} using the supplied characters as byte values. | ||||
| 	 * <p> | ||||
| 	 * Only th elow-order 8-bits of each character are used, the remainder is ignored.  | ||||
| 	 * <p> | ||||
| 	 * This is most useful for constructing byte sequences that do not conform to UTF8.  | ||||
| 	 * @param bytes array of char, whose values are truncated at 8-bits each and put into a byte array.  | ||||
| 	 * @return {@link LuaString} wrapping a copy of the byte buffer  | ||||
| 	 */ | ||||
| 	public static LuaString valueOf(char[] bytes) { | ||||
| 		int n = bytes.length; | ||||
| 		byte[] b = new byte[n]; | ||||
| 		for ( int i=0; i<n; i++ ) | ||||
| 			b[i] = (byte) bytes[i]; | ||||
| 		return valueOf(b, 0, n); | ||||
| 	} | ||||
| 	 | ||||
| 	 | ||||
| 	/** Construct a {@link LuaString} around a byte array without copying the contents. | ||||
| 	 * <p> | ||||
| 	 * The array is used directly after this is called, so clients must not change contents. | ||||
| 	 * <p> | ||||
| 	 * @param bytes byte buffer | ||||
| 	 * @return {@link LuaString} wrapping the byte buffer | ||||
| 	 */ | ||||
| 	public static LuaString valueOf(byte[] bytes) { | ||||
| 		return valueOf(bytes, 0, bytes.length); | ||||
| 	} | ||||
| 	 | ||||
| 	/** Construct a {@link LuaString} around a byte array without copying the contents. | ||||
| 	 * <p> | ||||
| 	 * The array is used directly after this is called, so clients must not change contents. | ||||
| 	 * <p> | ||||
| 	 * @param bytes byte buffer | ||||
| 	 * @param offset offset into the byte buffer | ||||
| 	 * @param length length of the byte buffer | ||||
| 	 * @return {@link LuaString} wrapping the byte buffer | ||||
| 	 */ | ||||
| 	private LuaString(byte[] bytes, int offset, int length) { | ||||
| 		this.m_bytes = bytes; | ||||
| 		this.m_offset = offset; | ||||
| 		this.m_length = length; | ||||
| 	} | ||||
|  | ||||
| 	public boolean isstring() { | ||||
| 		return true;  | ||||
| 	} | ||||
| 		 | ||||
| 	public LuaValue getmetatable() {  | ||||
| 		return s_metatable;  | ||||
| 	} | ||||
| 	 | ||||
| 	public int type() { | ||||
| 		return LuaValue.TSTRING; | ||||
| 	} | ||||
|  | ||||
| 	public String typename() { | ||||
| 		return "string"; | ||||
| 	} | ||||
| 	 | ||||
| 	public String tojstring() { | ||||
|         /* DAN200 START */ | ||||
| 		/* | ||||
| 		return decodeAsUtf8(m_bytes, m_offset, m_length); | ||||
| 		*/ | ||||
|         char[] chars = new char[ m_length ]; | ||||
|         for( int i=0; i<chars.length; ++i ) | ||||
|         { | ||||
|             chars[i] = (char)(m_bytes[ m_offset + i ] & 255); | ||||
|         } | ||||
|         return new String( chars ); | ||||
|         /* DAN200 END */ | ||||
| 	} | ||||
|  | ||||
| 	// get is delegated to the string library | ||||
| 	public LuaValue get(LuaValue key) { | ||||
| 		return s_metatable!=null? gettable(this,key): StringLib.instance.get(key); | ||||
| 	} | ||||
|  | ||||
| 	// unary operators | ||||
| 	public LuaValue neg() { double d = scannumber(10); return Double.isNaN(d)? super.neg(): valueOf(-d); } | ||||
|  | ||||
| 	// basic binary arithmetic | ||||
| 	public LuaValue   add( LuaValue rhs )      { double d = scannumber(10); return Double.isNaN(d)? arithmt(ADD,rhs): rhs.add(d); } | ||||
| 	public LuaValue   add( double rhs )        { return valueOf( checkarith() + rhs ); } | ||||
| 	public LuaValue   add( int rhs )           { return valueOf( checkarith() + rhs ); } | ||||
| 	public LuaValue   sub( LuaValue rhs )      { double d = scannumber(10); return Double.isNaN(d)? arithmt(SUB,rhs): rhs.subFrom(d); } | ||||
| 	public LuaValue   sub( double rhs )        { return valueOf( checkarith() - rhs ); } | ||||
| 	public LuaValue   sub( int rhs )           { return valueOf( checkarith() - rhs ); } | ||||
| 	public LuaValue   subFrom( double lhs )    { return valueOf( lhs - checkarith() ); } | ||||
| 	public LuaValue   mul( LuaValue rhs )      { double d = scannumber(10); return Double.isNaN(d)? arithmt(MUL,rhs): rhs.mul(d); } | ||||
| 	public LuaValue   mul( double rhs )        { return valueOf( checkarith() * rhs ); } | ||||
| 	public LuaValue   mul( int rhs )           { return valueOf( checkarith() * rhs ); } | ||||
| 	public LuaValue   pow( LuaValue rhs )      { double d = scannumber(10); return Double.isNaN(d)? arithmt(POW,rhs): rhs.powWith(d); } | ||||
| 	public LuaValue   pow( double rhs )        { return MathLib.dpow(checkarith(),rhs); } | ||||
| 	public LuaValue   pow( int rhs )           { return MathLib.dpow(checkarith(),rhs); } | ||||
| 	public LuaValue   powWith( double lhs )    { return MathLib.dpow(lhs, checkarith()); } | ||||
| 	public LuaValue   powWith( int lhs )       { return MathLib.dpow(lhs, checkarith()); } | ||||
| 	public LuaValue   div( LuaValue rhs )      { double d = scannumber(10); return Double.isNaN(d)? arithmt(DIV,rhs): rhs.divInto(d); } | ||||
| 	public LuaValue   div( double rhs )        { return LuaDouble.ddiv(checkarith(),rhs); } | ||||
| 	public LuaValue   div( int rhs )           { return LuaDouble.ddiv(checkarith(),rhs); } | ||||
| 	public LuaValue   divInto( double lhs )    { return LuaDouble.ddiv(lhs, checkarith()); } | ||||
| 	public LuaValue   mod( LuaValue rhs )      { double d = scannumber(10); return Double.isNaN(d)? arithmt(MOD,rhs): rhs.modFrom(d); } | ||||
| 	public LuaValue   mod( double rhs )        { return LuaDouble.dmod(checkarith(), rhs); } | ||||
| 	public LuaValue   mod( int rhs )           { return LuaDouble.dmod(checkarith(), rhs); } | ||||
| 	public LuaValue   modFrom( double lhs )    { return LuaDouble.dmod(lhs, checkarith()); } | ||||
| 	 | ||||
| 	// relational operators, these only work with other strings | ||||
| 	public LuaValue   lt( LuaValue rhs )         { return rhs.strcmp(this)>0? LuaValue.TRUE: FALSE; } | ||||
| 	public boolean lt_b( LuaValue rhs )       { return rhs.strcmp(this)>0; } | ||||
| 	public boolean lt_b( int rhs )         { typerror("attempt to compare string with number"); return false; } | ||||
| 	public boolean lt_b( double rhs )      { typerror("attempt to compare string with number"); return false; } | ||||
| 	public LuaValue   lteq( LuaValue rhs )       { return rhs.strcmp(this)>=0? LuaValue.TRUE: FALSE; } | ||||
| 	public boolean lteq_b( LuaValue rhs )     { return rhs.strcmp(this)>=0; } | ||||
| 	public boolean lteq_b( int rhs )       { typerror("attempt to compare string with number"); return false; } | ||||
| 	public boolean lteq_b( double rhs )    { typerror("attempt to compare string with number"); return false; } | ||||
| 	public LuaValue   gt( LuaValue rhs )         { return rhs.strcmp(this)<0? LuaValue.TRUE: FALSE; } | ||||
| 	public boolean gt_b( LuaValue rhs )       { return rhs.strcmp(this)<0; } | ||||
| 	public boolean gt_b( int rhs )         { typerror("attempt to compare string with number"); return false; } | ||||
| 	public boolean gt_b( double rhs )      { typerror("attempt to compare string with number"); return false; } | ||||
| 	public LuaValue   gteq( LuaValue rhs )       { return rhs.strcmp(this)<=0? LuaValue.TRUE: FALSE; } | ||||
| 	public boolean gteq_b( LuaValue rhs )     { return rhs.strcmp(this)<=0; } | ||||
| 	public boolean gteq_b( int rhs )       { typerror("attempt to compare string with number"); return false; } | ||||
| 	public boolean gteq_b( double rhs )    { typerror("attempt to compare string with number"); return false; } | ||||
|  | ||||
| 	// concatenation | ||||
| 	public LuaValue concat(LuaValue rhs)      { return rhs.concatTo(this); } | ||||
| 	public Buffer   concat(Buffer rhs)        { return rhs.concatTo(this); } | ||||
| 	public LuaValue concatTo(LuaNumber lhs)   { return concatTo(lhs.strvalue()); } | ||||
| 	public LuaValue concatTo(LuaString lhs)   {  | ||||
| 		byte[] b = new byte[lhs.m_length+this.m_length]; | ||||
| 		System.arraycopy(lhs.m_bytes, lhs.m_offset, b, 0, lhs.m_length); | ||||
| 		System.arraycopy(this.m_bytes, this.m_offset, b, lhs.m_length, this.m_length); | ||||
| 		return new LuaString(b, 0, b.length); | ||||
| 	} | ||||
|  | ||||
| 	// string comparison  | ||||
| 	public int strcmp(LuaValue lhs)           { return -lhs.strcmp(this); } | ||||
| 	public int strcmp(LuaString rhs) { | ||||
| 		for ( int i=0, j=0; i<m_length && j<rhs.m_length; ++i, ++j ) { | ||||
| 			if ( m_bytes[m_offset+i] != rhs.m_bytes[rhs.m_offset+j] ) { | ||||
| 				return ((int)m_bytes[m_offset+i]) - ((int) rhs.m_bytes[rhs.m_offset+j]); | ||||
| 			} | ||||
| 		} | ||||
| 		return m_length - rhs.m_length; | ||||
| 	} | ||||
| 	 | ||||
| 	/** Check for number in arithmetic, or throw aritherror */ | ||||
| 	private double checkarith() {  | ||||
| 		double d = scannumber(10); | ||||
| 		if ( Double.isNaN(d) )  | ||||
| 			aritherror(); | ||||
| 		return d; | ||||
| 	} | ||||
| 	 | ||||
| 	public int checkint() { | ||||
| 		return (int) (long) checkdouble(); | ||||
| 	} | ||||
| 	public LuaInteger checkinteger() { | ||||
| 		return valueOf(checkint()); | ||||
| 	} | ||||
| 	public long checklong() { | ||||
| 		return (long) checkdouble(); | ||||
| 	} | ||||
| 	public double checkdouble() { | ||||
| 		double d = scannumber(10); | ||||
| 		if ( Double.isNaN(d) ) | ||||
| 			argerror("number"); | ||||
| 		return d; | ||||
| 	} | ||||
| 	public LuaNumber checknumber() { | ||||
| 		return valueOf(checkdouble()); | ||||
| 	} | ||||
| 	public LuaNumber checknumber(String msg) { | ||||
| 		double d = scannumber(10); | ||||
| 		if ( Double.isNaN(d) ) | ||||
| 			error(msg); | ||||
| 		return valueOf(d); | ||||
| 	} | ||||
| 	public LuaValue tonumber() { | ||||
| 		return tonumber(10); | ||||
| 	} | ||||
|  | ||||
| 	public boolean isnumber() { | ||||
| 		double d = scannumber(10); | ||||
| 		return ! Double.isNaN(d); | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean isint() { | ||||
| 		double d = scannumber(10); | ||||
| 		if ( Double.isNaN(d) )  | ||||
| 			return false; | ||||
| 		int i = (int) d; | ||||
| 		return i == d; | ||||
| 	} | ||||
|  | ||||
| 	public boolean islong() {  | ||||
| 		double d = scannumber(10); | ||||
| 		if ( Double.isNaN(d) )  | ||||
| 			return false; | ||||
| 		long l = (long) d; | ||||
| 		return l == d; | ||||
| 	} | ||||
| 	 | ||||
| 	public byte    tobyte()        { return (byte) toint(); } | ||||
| 	public char    tochar()        { return (char) toint(); } | ||||
| 	public double  todouble()      { double d=scannumber(10); return Double.isNaN(d)? 0: d; } | ||||
| 	public float   tofloat()       { return (float) todouble(); } | ||||
| 	public int     toint()         { return (int) tolong(); } | ||||
| 	public long    tolong()        { return (long) todouble(); } | ||||
| 	public short   toshort()       { return (short) toint(); } | ||||
|  | ||||
| 	public double optdouble(double defval) { | ||||
| 		return checknumber().checkdouble(); | ||||
| 	} | ||||
| 	 | ||||
| 	public int optint(int defval) { | ||||
| 		return checknumber().checkint(); | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaInteger optinteger(LuaInteger defval) {  | ||||
| 		return checknumber().checkinteger(); | ||||
| 	} | ||||
| 	 | ||||
| 	public long optlong(long defval) { | ||||
| 		return checknumber().checklong(); | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaNumber optnumber(LuaNumber defval) { | ||||
| 		return checknumber().checknumber(); | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaString optstring(LuaString defval) { | ||||
| 		return this;  | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue tostring() { | ||||
| 		return this; | ||||
| 	} | ||||
|  | ||||
| 	public String optjstring(String defval) {  | ||||
| 		return tojstring();  | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaString strvalue() { | ||||
| 		return this; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaString substring( int beginIndex, int endIndex ) { | ||||
| 		return new LuaString( m_bytes, m_offset + beginIndex, endIndex - beginIndex ); | ||||
| 	} | ||||
| 	 | ||||
| 	public int hashCode() { | ||||
| 		int h = m_length;  /* seed */ | ||||
| 		int step = (m_length>>5)+1;  /* if string is too long, don't hash all its chars */ | ||||
| 		for (int l1=m_length; l1>=step; l1-=step)  /* compute hash */ | ||||
| 		    h = h ^ ((h<<5)+(h>>2)+(((int) m_bytes[m_offset+l1-1] ) & 0x0FF )); | ||||
| 		return h; | ||||
| 	} | ||||
| 	 | ||||
| 	// object comparison, used in key comparison | ||||
| 	public boolean equals( Object o ) { | ||||
| 		if ( o instanceof LuaString ) { | ||||
| 			return raweq( (LuaString) o ); | ||||
| 		} | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	// equality w/ metatable processing | ||||
| 	public LuaValue eq( LuaValue val )    { return val.raweq(this)? TRUE: FALSE; } | ||||
| 	public boolean eq_b( LuaValue val )   { return val.raweq(this); } | ||||
| 	 | ||||
| 	// equality w/o metatable processing | ||||
| 	public boolean raweq( LuaValue val ) { | ||||
| 		return val.raweq(this); | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean raweq( LuaString s ) {  | ||||
| 		if ( this == s ) | ||||
| 			return true; | ||||
| 		if ( s.m_length != m_length ) | ||||
| 			return false; | ||||
| 		if ( s.m_bytes == m_bytes && s.m_offset == m_offset ) | ||||
| 			return true; | ||||
| 		if ( s.hashCode() != hashCode() ) | ||||
| 			return false; | ||||
| 		for ( int i=0; i<m_length; i++ ) | ||||
| 			if ( s.m_bytes[s.m_offset+i] != m_bytes[m_offset+i] ) | ||||
| 				return false; | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	public static boolean equals( LuaString a, int i, LuaString b, int j, int n ) { | ||||
| 		return equals( a.m_bytes, a.m_offset + i, b.m_bytes, b.m_offset + j, n ); | ||||
| 	} | ||||
| 	 | ||||
| 	public static boolean equals( byte[] a, int i, byte[] b, int j, int n ) { | ||||
| 		if ( a.length < i + n || b.length < j + n ) | ||||
| 			return false; | ||||
| 		while ( --n>=0 )  | ||||
| 			if ( a[i++]!=b[j++] ) | ||||
| 				return false; | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	public void write(DataOutputStream writer, int i, int len) throws IOException { | ||||
| 		writer.write(m_bytes,m_offset+i,len); | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue len() { | ||||
| 		return LuaInteger.valueOf(m_length); | ||||
| 	} | ||||
|  | ||||
| 	public int length() { | ||||
| 		return m_length; | ||||
| 	} | ||||
|  | ||||
| 	public int luaByte(int index) { | ||||
| 		return m_bytes[m_offset + index] & 0x0FF; | ||||
| 	} | ||||
|  | ||||
| 	public int charAt( int index ) { | ||||
| 		if ( index < 0 || index >= m_length ) | ||||
| 			throw new IndexOutOfBoundsException(); | ||||
| 		return luaByte( index ); | ||||
| 	} | ||||
| 	 | ||||
| 	public String checkjstring() {  | ||||
| 		return tojstring();  | ||||
| 	} | ||||
|  | ||||
| 	public LuaString checkstring() { | ||||
| 		return this; | ||||
| 	} | ||||
| 	 | ||||
| 	/** Convert value to an input stream. | ||||
| 	 *  | ||||
| 	 * @return {@link InputStream} whose data matches the bytes in this {@link LuaString} | ||||
| 	 */ | ||||
| 	public InputStream toInputStream() { | ||||
| 		return new ByteArrayInputStream(m_bytes, m_offset, m_length); | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Copy the bytes of the string into the given byte array.  | ||||
| 	 * @param strOffset offset from which to copy | ||||
| 	 * @param bytes destination byte array | ||||
| 	 * @param arrayOffset offset in destination | ||||
| 	 * @param len number of bytes to copy | ||||
| 	 */ | ||||
| 	public void copyInto( int strOffset, byte[] bytes, int arrayOffset, int len ) { | ||||
| 		System.arraycopy( m_bytes, m_offset+strOffset, bytes, arrayOffset, len ); | ||||
| 	} | ||||
| 	 | ||||
| 	/** Java version of strpbrk - find index of any byte that in an accept string. | ||||
| 	 * @param accept {@link LuaString} containing characters to look for. | ||||
| 	 * @return index of first match in the {@code accept} string, or -1 if not found. | ||||
| 	 */ | ||||
| 	public int indexOfAny( LuaString accept ) { | ||||
| 		final int ilimit = m_offset + m_length; | ||||
| 		final int jlimit = accept.m_offset + accept.m_length; | ||||
| 		for ( int i = m_offset; i < ilimit; ++i ) { | ||||
| 			for ( int j = accept.m_offset; j < jlimit; ++j ) { | ||||
| 				if ( m_bytes[i] == accept.m_bytes[j] ) { | ||||
| 					return i - m_offset; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return -1; | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Find the index of a byte starting at a point in this string | ||||
| 	 * @param b the byte to look for | ||||
| 	 * @param start the first index in the string | ||||
| 	 * @return index of first match found, or -1 if not found. | ||||
| 	 */ | ||||
| 	public int indexOf( byte b, int start ) { | ||||
| 		for ( int i=0, j=m_offset+start; i < m_length; ++i ) { | ||||
| 			if ( m_bytes[j++] == b ) | ||||
| 				return i; | ||||
| 		} | ||||
| 		return -1; | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Find the index of a string starting at a point in this string | ||||
| 	 * @param s the string to search for | ||||
| 	 * @param start the first index in the string | ||||
| 	 * @return index of first match found, or -1 if not found. | ||||
| 	 */ | ||||
| 	public int indexOf( LuaString s, int start ) { | ||||
| 		final int slen = s.length(); | ||||
| 		final int limit = m_offset + m_length - slen; | ||||
| 		for ( int i = m_offset + start; i <= limit; ++i ) { | ||||
| 			if ( equals( m_bytes, i, s.m_bytes, s.m_offset, slen ) ) { | ||||
| 				/* DAN200 START */ | ||||
| 				//return i; | ||||
| 				return i - m_offset; | ||||
| 				/* DAN200 END */ | ||||
| 			} | ||||
| 		} | ||||
| 		return -1; | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Find the last index of a string in this string | ||||
| 	 * @param s the string to search for | ||||
| 	 * @return index of last match found, or -1 if not found. | ||||
| 	 */ | ||||
| 	public int lastIndexOf( LuaString s ) { | ||||
| 		final int slen = s.length(); | ||||
| 		final int limit = m_offset + m_length - slen; | ||||
| 		for ( int i = limit; i >= m_offset; --i ) { | ||||
| 			if ( equals( m_bytes, i, s.m_bytes, s.m_offset, slen ) ) { | ||||
| 				/* DAN200 START */ | ||||
| 				//return i; | ||||
| 				return i - m_offset; | ||||
| 				/* DAN200 END */ | ||||
| 			} | ||||
| 		} | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	/** | ||||
| 	 * Convert to Java String interpreting as utf8 characters.  | ||||
| 	 *  | ||||
| 	 * @param bytes byte array in UTF8 encoding to convert | ||||
| 	 * @param offset starting index in byte array | ||||
| 	 * @param length number of bytes to convert | ||||
| 	 * @return Java String corresponding to the value of bytes interpreted using UTF8  | ||||
| 	 * @see #lengthAsUtf8(char[]) | ||||
| 	 * @see #encodeToUtf8(char[], byte[], int) | ||||
| 	 * @see #isValidUtf8() | ||||
| 	 */ | ||||
| 	/* DAN200 START */ | ||||
| 	//public static String decodeAsUtf8(byte[] bytes, int offset, int length) { | ||||
| 	private static String decodeAsUtf8(byte[] bytes, int offset, int length) { | ||||
| 	/* DAN200 END */ | ||||
| 		int i,j,n,b; | ||||
| 		for ( i=offset,j=offset+length,n=0; i<j; ++n ) { | ||||
| 			switch ( 0xE0 & bytes[i++] ) { | ||||
| 			case 0xE0: ++i; | ||||
| 			case 0xC0: ++i; | ||||
| 			} | ||||
| 		} | ||||
| 		char[] chars=new char[n]; | ||||
| 		for ( i=offset,j=offset+length,n=0; i<j; ) { | ||||
| 			chars[n++] = (char) ( | ||||
| 				((b=bytes[i++])>=0||i>=j)? b: | ||||
| 				(b<-32||i+1>=j)? (((b&0x3f) << 6) | (bytes[i++]&0x3f)): | ||||
| 					(((b&0xf) << 12) | ((bytes[i++]&0x3f)<<6) | (bytes[i++]&0x3f))); | ||||
| 		} | ||||
| 		return new String(chars); | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Count the number of bytes required to encode the string as UTF-8. | ||||
| 	 * @param chars Array of unicode characters to be encoded as UTF-8 | ||||
| 	 * @return count of bytes needed to encode using UTF-8 | ||||
| 	 * @see #encodeToUtf8(char[], byte[], int) | ||||
| 	 * @see #decodeAsUtf8(byte[], int, int) | ||||
| 	 * @see #isValidUtf8() | ||||
| 	 */ | ||||
| 	/* DAN200 START */ | ||||
| 	//public static int lengthAsUtf8(char[] chars) {		 | ||||
| 	private static int lengthAsUtf8(char[] chars) {		 | ||||
| 	/* DAN200 END */ | ||||
| 		int i,b; | ||||
| 		char c; | ||||
| 		for ( i=b=chars.length; --i>=0; ) | ||||
| 			if ( (c=chars[i]) >=0x80 ) | ||||
| 				b += (c>=0x800)? 2: 1; | ||||
| 		return b; | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Encode the given Java string as UTF-8 bytes, writing the result to bytes | ||||
| 	 * starting at offset.  | ||||
| 	 * <p> | ||||
| 	 * The string should be measured first with lengthAsUtf8 | ||||
| 	 * to make sure the given byte array is large enough. | ||||
| 	 * @param chars Array of unicode characters to be encoded as UTF-8 | ||||
| 	 * @param bytes byte array to hold the result | ||||
| 	 * @param off offset into the byte array to start writing | ||||
| 	 * @see #lengthAsUtf8(char[]) | ||||
| 	 * @see #decodeAsUtf8(byte[], int, int) | ||||
| 	 * @see #isValidUtf8() | ||||
| 	 */ | ||||
| 	/* DAN200 START */ | ||||
| 	//public static void encodeToUtf8(char[] chars, byte[] bytes, int off) { | ||||
| 	private static void encodeToUtf8(char[] chars, byte[] bytes, int off) { | ||||
| 	/* DAN200 END */ | ||||
| 		final int n = chars.length; | ||||
| 		char c; | ||||
| 		for ( int i=0, j=off; i<n; i++ ) { | ||||
| 			if ( (c = chars[i]) < 0x80 ) { | ||||
| 				bytes[j++] = (byte) c; | ||||
| 			} else if ( c < 0x800 ) { | ||||
| 				bytes[j++] = (byte) (0xC0 | ((c>>6)  & 0x1f)); | ||||
| 				bytes[j++] = (byte) (0x80 | ( c      & 0x3f));				 | ||||
| 			} else { | ||||
| 				bytes[j++] = (byte) (0xE0 | ((c>>12) & 0x0f)); | ||||
| 				bytes[j++] = (byte) (0x80 | ((c>>6)  & 0x3f)); | ||||
| 				bytes[j++] = (byte) (0x80 | ( c      & 0x3f));				 | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** Check that a byte sequence is valid UTF-8 | ||||
| 	 * @return true if it is valid UTF-8, otherwise false | ||||
| 	 * @see #lengthAsUtf8(char[]) | ||||
| 	 * @see #encodeToUtf8(char[], byte[], int) | ||||
| 	 * @see #decodeAsUtf8(byte[], int, int) | ||||
| 	 */ | ||||
| 	public boolean isValidUtf8() { | ||||
| 		int i,j,n,b,e=0; | ||||
| 		for ( i=m_offset,j=m_offset+m_length,n=0; i<j; ++n ) { | ||||
| 			int c = m_bytes[i++]; | ||||
| 			if ( c >= 0 ) continue; | ||||
| 			if ( ((c & 0xE0) == 0xC0)  | ||||
| 					&& i<j  | ||||
| 					&& (m_bytes[i++] & 0xC0) == 0x80) continue; | ||||
| 			if ( ((c & 0xF0) == 0xE0)  | ||||
| 					&& i+1<j  | ||||
| 					&& (m_bytes[i++] & 0xC0) == 0x80  | ||||
| 					&& (m_bytes[i++] & 0xC0) == 0x80) continue; | ||||
| 			return false; | ||||
| 		} | ||||
| 		return true; | ||||
| 	} | ||||
| 	 | ||||
| 	// --------------------- number conversion ----------------------- | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * convert to a number using a supplied base, or NIL if it can't be converted | ||||
| 	 * @param base the base to use, such as 10 | ||||
| 	 * @return IntValue, DoubleValue, or NIL depending on the content of the string. | ||||
| 	 * @see LuaValue#tonumber()  | ||||
| 	 */ | ||||
| 	public LuaValue tonumber( int base ) { | ||||
| 		double d = scannumber( base ); | ||||
| 		return Double.isNaN(d)? NIL: valueOf(d); | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Convert to a number in a base, or return Double.NaN if not a number. | ||||
| 	 * @param base the base to use, such as 10 | ||||
| 	 * @return double value if conversion is valid, or Double.NaN if not  | ||||
| 	 */ | ||||
| 	public double scannumber( int base ) { | ||||
| 		if ( base >= 2 && base <= 36 ) { | ||||
| 			int i=m_offset,j=m_offset+m_length; | ||||
| 			while ( i<j && m_bytes[i]==' ' ) ++i; | ||||
| 			while ( i<j && m_bytes[j-1]==' ' ) --j; | ||||
| 			if ( i>=j ) | ||||
| 				return Double.NaN; | ||||
| 			if ( ( base == 10 || base == 16 ) && ( m_bytes[i]=='0' && i+1<j && (m_bytes[i+1]=='x'||m_bytes[i+1]=='X') ) ) { | ||||
| 				base = 16; | ||||
| 				i+=2; | ||||
| 			} | ||||
| 			double l = scanlong( base, i, j ); | ||||
| 			return Double.isNaN(l) && base==10? scandouble(i,j): l; | ||||
| 		} | ||||
| 		 | ||||
| 		return Double.NaN; | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Scan and convert a long value, or return Double.NaN if not found. | ||||
| 	 * @param base the base to use, such as 10 | ||||
| 	 * @param start the index to start searching from | ||||
| 	 * @param end the first index beyond the search range | ||||
| 	 * @return double value if conversion is valid,  | ||||
| 	 * or Double.NaN if not | ||||
| 	 */ | ||||
| 	private double scanlong( int base, int start, int end ) { | ||||
| 		long x = 0; | ||||
| 		boolean neg = (m_bytes[start] == '-'); | ||||
| 		for ( int i=(neg?start+1:start); i<end; i++ ) { | ||||
| 			int digit = m_bytes[i] - (base<=10||(m_bytes[i]>='0'&&m_bytes[i]<='9')? '0': | ||||
| 					m_bytes[i]>='A'&&m_bytes[i]<='Z'? ('A'-10): ('a'-10)); | ||||
| 			if ( digit < 0 || digit >= base ) | ||||
| 				return Double.NaN;		 | ||||
| 			x = x * base + digit; | ||||
| 		} | ||||
| 		return neg? -x: x; | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Scan and convert a double value, or return Double.NaN if not a double. | ||||
| 	 * @param start the index to start searching from | ||||
| 	 * @param end the first index beyond the search range | ||||
| 	 * @return double value if conversion is valid,  | ||||
| 	 * or Double.NaN if not | ||||
| 	 */ | ||||
| 	private double scandouble(int start, int end) { | ||||
| 		if ( end>start+64 ) end=start+64; | ||||
| 		for ( int i=start; i<end; i++ ) { | ||||
| 			switch ( m_bytes[i] ) { | ||||
| 			case '-': | ||||
| 			case '+': | ||||
| 			case '.': | ||||
| 			case 'e': case 'E': | ||||
| 			case '0': case '1': case '2': case '3': case '4': | ||||
| 			case '5': case '6': case '7': case '8': case '9': | ||||
| 				break; | ||||
| 			default: | ||||
| 				return Double.NaN; | ||||
| 			} | ||||
| 		} | ||||
| 		char [] c = new char[end-start]; | ||||
| 		for ( int i=start; i<end; i++ ) | ||||
| 			c[i-start] = (char) m_bytes[i]; | ||||
| 		try { | ||||
| 			return Double.parseDouble(new String(c)); | ||||
| 		} catch ( Exception e ) {			 | ||||
| 			return Double.NaN; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -1,718 +0,0 @@ | ||||
| /******************************************************************************* | ||||
|  * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
| import java.util.Vector; | ||||
|  | ||||
| /** | ||||
|  * Subclass of {@link LuaValue} for representing lua tables.  | ||||
|  * <p> | ||||
|  * Almost all API's implemented in {@link LuaTable} are defined and documented in {@link LuaValue}. | ||||
|  * <p> | ||||
|  * If a table is needed, the one of the type-checking functions can be used such as | ||||
|  * {@link #istable()},  | ||||
|  * {@link #checktable()}, or | ||||
|  * {@link #opttable(LuaTable)}  | ||||
|  * <p> | ||||
|  * The main table operations are defined on {@link LuaValue}  | ||||
|  * for getting and setting values with and without metatag processing: | ||||
|  * <ul> | ||||
|  * <li>{@link #get(LuaValue)}</li>   | ||||
|  * <li>{@link #set(LuaValue,LuaValue)}</li>   | ||||
|  * <li>{@link #rawget(LuaValue)}</li>   | ||||
|  * <li>{@link #rawset(LuaValue,LuaValue)}</li> | ||||
|  * <li>plus overloads such as {@link #get(String)}, {@link #get(int)}, and so on</li>   | ||||
|  * </ul> | ||||
|  * <p> | ||||
|  * To iterate over key-value pairs from Java, use | ||||
|  * <pre> {@code | ||||
|  * LuaValue k = LuaValue.NIL; | ||||
|  * while ( true ) { | ||||
|  *    Varargs n = table.next(k); | ||||
|  *    if ( (k = n.arg1()).isnil() ) | ||||
|  *       break; | ||||
|  *    LuaValue v = n.arg(2) | ||||
|  *    process( k, v ) | ||||
|  * }}</pre> | ||||
|  *  | ||||
|  * <p> | ||||
|  * As with other types, {@link LuaTable} instances should be constructed via one of the table constructor  | ||||
|  * methods on {@link LuaValue}: | ||||
|  * <ul> | ||||
|  * <li>{@link LuaValue#tableOf()} empty table</li> | ||||
|  * <li>{@link LuaValue#tableOf(int, int)} table with capacity</li> | ||||
|  * <li>{@link LuaValue#listOf(LuaValue[])} initialize array part</li> | ||||
|  * <li>{@link LuaValue#listOf(LuaValue[], Varargs)} initialize array part</li> | ||||
|  * <li>{@link LuaValue#tableOf(LuaValue[])} initialize named hash part</li> | ||||
|  * <li>{@link LuaValue#tableOf(Varargs, int)} initialize named hash part</li> | ||||
|  * <li>{@link LuaValue#tableOf(LuaValue[], LuaValue[])} initialize array and named parts</li> | ||||
|  * <li>{@link LuaValue#tableOf(LuaValue[], LuaValue[], Varargs)} initialize array and named parts</li> | ||||
|  * </ul> | ||||
|  * @see LuaValue | ||||
|  */ | ||||
| public class LuaTable extends LuaValue { | ||||
| 	private static final int      MIN_HASH_CAPACITY = 2; | ||||
| 	private static final LuaString N = valueOf("n"); | ||||
| 	 | ||||
| 	/** the array values */ | ||||
| 	protected LuaValue[] array; | ||||
| 	 | ||||
| 	/** the hash keys */ | ||||
| 	protected LuaValue[] hashKeys; | ||||
| 	 | ||||
| 	/** the hash values */ | ||||
| 	protected LuaValue[] hashValues; | ||||
| 	 | ||||
| 	/** the number of hash entries */ | ||||
| 	protected int hashEntries; | ||||
| 	 | ||||
| 	/** metatable for this table, or null */ | ||||
| 	protected LuaValue m_metatable; | ||||
| 	 | ||||
| 	/** Construct empty table */ | ||||
| 	public LuaTable() { | ||||
| 		array = NOVALS; | ||||
| 		hashKeys = NOVALS; | ||||
| 		hashValues = NOVALS; | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Construct table with preset capacity. | ||||
| 	 * @param narray capacity of array part | ||||
| 	 * @param nhash capacity of hash part | ||||
| 	 */ | ||||
| 	public LuaTable(int narray, int nhash) { | ||||
| 		presize(narray, nhash); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Construct table with named and unnamed parts.  | ||||
| 	 * @param named Named elements in order {@code key-a, value-a, key-b, value-b, ... } | ||||
| 	 * @param unnamed Unnamed elements in order {@code value-1, value-2, ... }  | ||||
| 	 * @param lastarg Additional unnamed values beyond {@code unnamed.length} | ||||
| 	 */ | ||||
| 	public LuaTable(LuaValue[] named, LuaValue[] unnamed, Varargs lastarg) { | ||||
| 		int nn = (named!=null? named.length: 0); | ||||
| 		int nu = (unnamed!=null? unnamed.length: 0); | ||||
| 		int nl = (lastarg!=null? lastarg.narg(): 0); | ||||
| 		presize(nu+nl, nn-(nn>>1)); | ||||
| 		for ( int i=0; i<nu; i++ ) | ||||
| 			rawset(i+1,unnamed[i]); | ||||
| 		if ( lastarg != null ) | ||||
| 			for ( int i=1,n=lastarg.narg(); i<=n; ++i ) | ||||
| 				rawset(nu+i,lastarg.arg(i)); | ||||
| 		for ( int i=0; i<nn; i+=2 ) | ||||
| 			if (!named[i+1].isnil()) | ||||
| 				rawset(named[i], named[i+1]); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Construct table of unnamed elements.  | ||||
| 	 * @param varargs Unnamed elements in order {@code value-1, value-2, ... }  | ||||
| 	 */ | ||||
| 	public LuaTable(Varargs varargs) { | ||||
| 		this(varargs,1); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Construct table of unnamed elements.  | ||||
| 	 * @param varargs Unnamed elements in order {@code value-1, value-2, ... } | ||||
| 	 * @param firstarg the index in varargs of the first argument to include in the table  | ||||
| 	 */ | ||||
| 	public LuaTable(Varargs varargs, int firstarg) { | ||||
| 		int nskip = firstarg-1; | ||||
| 		int n = Math.max(varargs.narg()-nskip,0); | ||||
| 		presize( n, 1 ); | ||||
| 		set(N, valueOf(n)); | ||||
| 		for ( int i=1; i<=n; i++ ) | ||||
| 			set(i, varargs.arg(i+nskip)); | ||||
| 	} | ||||
| 	 | ||||
| 	public int type() { | ||||
| 		return LuaValue.TTABLE; | ||||
| 	} | ||||
|  | ||||
| 	public String typename() { | ||||
| 		return "table"; | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean istable() {  | ||||
| 		return true;  | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaTable checktable()     {  | ||||
| 		return this; | ||||
| 	} | ||||
|  | ||||
| 	public LuaTable opttable(LuaTable defval)  { | ||||
| 		return this; | ||||
| 	} | ||||
| 	 | ||||
| 	public void presize( int narray ) { | ||||
| 		if ( narray > array.length ) | ||||
| 			array = resize( array, narray ); | ||||
| 	} | ||||
|  | ||||
| 	public void presize(int narray, int nhash) { | ||||
| 		if ( nhash > 0 && nhash < MIN_HASH_CAPACITY ) | ||||
| 			nhash = MIN_HASH_CAPACITY; | ||||
| 		array = (narray>0? new LuaValue[narray]: NOVALS); | ||||
| 		hashKeys = (nhash>0? new LuaValue[nhash]: NOVALS); | ||||
| 		hashValues = (nhash>0? new LuaValue[nhash]: NOVALS); | ||||
| 		hashEntries = 0; | ||||
| 	} | ||||
|  | ||||
| 	/** Resize the table */ | ||||
| 	private static LuaValue[] resize( LuaValue[] old, int n ) { | ||||
| 		LuaValue[] v = new LuaValue[n]; | ||||
| 		System.arraycopy(old, 0, v, 0, old.length); | ||||
| 		return v; | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Get the length of the array part of the table.  | ||||
| 	 * @return length of the array part, does not relate to count of objects in the table.  | ||||
| 	 */ | ||||
| 	protected int getArrayLength() { | ||||
| 		return array.length; | ||||
| 	} | ||||
|  | ||||
| 	/**  | ||||
| 	 * Get the length of the hash part of the table.  | ||||
| 	 * @return length of the hash part, does not relate to count of objects in the table.  | ||||
| 	 */ | ||||
| 	protected int getHashLength() { | ||||
| 		return hashValues.length; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue getmetatable() { | ||||
| 		return m_metatable; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue setmetatable(LuaValue metatable) { | ||||
| 		m_metatable = metatable; | ||||
| 		LuaValue mode; | ||||
| 		if ( m_metatable!=null && (mode=m_metatable.rawget(MODE)).isstring() ) { | ||||
| 			String m = mode.tojstring(); | ||||
| 			boolean k = m.indexOf('k')>=0; | ||||
| 			boolean v = m.indexOf('v')>=0; | ||||
| 			return changemode(k,v); | ||||
| 		} | ||||
| 		return this; | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Change the mode of a table | ||||
| 	 * @param weakkeys true to make the table have weak keys going forward | ||||
| 	 * @param weakvalues true to make the table have weak values going forward | ||||
| 	 * @return {@code this} or a new {@link WeakTable} if the mode change requires copying. | ||||
| 	 */ | ||||
| 	protected LuaTable changemode(boolean weakkeys, boolean weakvalues) { | ||||
| 		if ( weakkeys || weakvalues ) | ||||
| 			return new WeakTable(weakkeys, weakvalues, this); | ||||
| 		return this; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue get( int key ) { | ||||
| 		LuaValue v = rawget(key); | ||||
| 		return v.isnil() && m_metatable!=null? gettable(this,valueOf(key)): v; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue get( LuaValue key ) { | ||||
| 		LuaValue v = rawget(key); | ||||
| 		return v.isnil() && m_metatable!=null? gettable(this,key): v; | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue rawget( int key ) { | ||||
| 		if ( key>0 && key<=array.length )  | ||||
| 			return array[key-1]!=null? array[key-1]: NIL; | ||||
| 		return hashget( LuaInteger.valueOf(key) ); | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue rawget( LuaValue key ) { | ||||
| 		if ( key.isinttype() ) { | ||||
| 			int ikey = key.toint(); | ||||
| 			if ( ikey>0 && ikey<=array.length )  | ||||
| 				return array[ikey-1]!=null? array[ikey-1]: NIL; | ||||
| 		} | ||||
| 		return hashget( key ); | ||||
| 	} | ||||
| 		 | ||||
| 	protected LuaValue hashget(LuaValue key) { | ||||
| 		if ( hashEntries > 0 ) { | ||||
| 			LuaValue v = hashValues[hashFindSlot(key)]; | ||||
| 			return v!=null? v: NIL; | ||||
| 		} | ||||
| 		return NIL; | ||||
| 	} | ||||
|  | ||||
| 	public void set( int key, LuaValue value ) { | ||||
| 		if ( m_metatable==null || ! rawget(key).isnil() || ! settable(this,LuaInteger.valueOf(key),value) ) | ||||
| 			rawset(key, value); | ||||
| 	} | ||||
|  | ||||
| 	/** caller must ensure key is not nil */ | ||||
| 	public void set( LuaValue key, LuaValue value ) { | ||||
| 		key.checkvalidkey(); | ||||
| 		if ( m_metatable==null || ! rawget(key).isnil() ||  ! settable(this,key,value) ) | ||||
| 			rawset(key, value); | ||||
| 	} | ||||
|  | ||||
| 	public void rawset( int key, LuaValue value ) { | ||||
| 		if ( ! arrayset(key, value) ) | ||||
| 			hashset( LuaInteger.valueOf(key), value ); | ||||
| 	} | ||||
|  | ||||
| 	/** caller must ensure key is not nil */ | ||||
| 	public void rawset( LuaValue key, LuaValue value ) { | ||||
| 		if ( !key.isinttype() || !arrayset(key.toint(), value) ) | ||||
| 			hashset( key, value ); | ||||
| 	} | ||||
|  | ||||
| 	/** Set an array element */ | ||||
| 	private boolean arrayset( int key, LuaValue value ) { | ||||
| 		if ( key>0 && key<=array.length ) { | ||||
| 			array[key-1] = (value.isnil()? null: value); | ||||
| 			return true; | ||||
| 		} else if ( key==array.length+1 && !value.isnil() ) { | ||||
| 			expandarray(); | ||||
| 			array[key-1] = value; | ||||
| 			return true; | ||||
| 		} | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	/** Expand the array part */ | ||||
| 	private void expandarray() { | ||||
| 		int n = array.length; | ||||
| 		int m = Math.max(2,n*2); | ||||
| 		array = resize(array, m); | ||||
| 		for ( int i=n; i<m; i++ ) { | ||||
| 			LuaValue k = LuaInteger.valueOf(i+1); | ||||
| 			LuaValue v = hashget(k); | ||||
| 			if ( !v.isnil() ) { | ||||
| 				hashset(k, NIL); | ||||
| 				array[i] = v; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** Remove the element at a position in a list-table | ||||
| 	 *   | ||||
| 	 * @param pos the position to remove | ||||
| 	 * @return The removed item, or {@link #NONE} if not removed | ||||
| 	 */ | ||||
| 	public LuaValue remove(int pos) { | ||||
| 		int n = length(); | ||||
| 		if ( pos == 0 ) | ||||
| 			pos = n; | ||||
| 		else if (pos > n) | ||||
| 			return NONE; | ||||
| 		LuaValue v = rawget(pos); | ||||
| 		for ( LuaValue r=v; !r.isnil(); ) { | ||||
| 			r = rawget(pos+1); | ||||
| 			rawset(pos++, r); | ||||
| 		} | ||||
| 		return v.isnil()? NONE: v; | ||||
| 	 | ||||
| 	} | ||||
|  | ||||
| 	/** Insert an element at a position in a list-table | ||||
| 	 *   | ||||
| 	 * @param pos the position to remove | ||||
| 	 * @param value The value to insert | ||||
| 	 */ | ||||
| 	public void insert(int pos, LuaValue value) { | ||||
| 		if ( pos == 0 ) | ||||
| 			pos = length()+1; | ||||
| 		while ( ! value.isnil() ) { | ||||
| 			LuaValue v = rawget( pos ); | ||||
| 			rawset(pos++, value); | ||||
| 			value = v; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** Concatenate the contents of a table efficiently, using {@link Buffer} | ||||
| 	 *  | ||||
| 	 * @param sep {@link LuaString} separater to apply between elements | ||||
| 	 * @param i the first element index | ||||
| 	 * @param j the last element index, inclusive | ||||
| 	 * @return {@link LuaString} value of the concatenation | ||||
| 	 */ | ||||
| 	public LuaValue concat(LuaString sep, int i, int j) { | ||||
| 		Buffer  sb = new Buffer (); | ||||
| 		if ( i<=j ) { | ||||
| 			sb.append( get(i).checkstring() ); | ||||
| 			while ( ++i<=j ) { | ||||
| 				sb.append( sep ); | ||||
| 				sb.append( get(i).checkstring() ); | ||||
| 			} | ||||
| 		} | ||||
| 		return sb.tostring(); | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue getn() {  | ||||
| 		for ( int n=getArrayLength(); n>0; --n ) | ||||
| 			if ( !rawget(n).isnil() ) | ||||
| 				return LuaInteger.valueOf(n); | ||||
| 		return ZERO; | ||||
| 	} | ||||
|  | ||||
| 	public int length() { | ||||
| 		int a = getArrayLength(); | ||||
| 		int n = a+1,m=0; | ||||
| 		while ( !rawget(n).isnil() ) { | ||||
| 			m = n; | ||||
| 			n += a+getHashLength()+1; | ||||
| 		} | ||||
| 		while ( n > m+1 ) { | ||||
| 			int k = (n+m) / 2; | ||||
| 			if ( !rawget(k).isnil() ) | ||||
| 				m = k; | ||||
| 			else | ||||
| 				n = k; | ||||
| 		} | ||||
| 		return m; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue len()  {  | ||||
| 		return LuaInteger.valueOf(length()); | ||||
| 	} | ||||
| 	 | ||||
| 	/** Return table.maxn() as defined by lua 5.0. | ||||
| 	 * <p> | ||||
| 	 * Provided for compatibility, not a scalable operation.  | ||||
| 	 * @return value for maxn | ||||
| 	 */ | ||||
| 	public int maxn() { | ||||
| 		int n = 0; | ||||
| 		for ( int i=0; i<array.length; i++ ) | ||||
| 			if ( array[i] != null ) | ||||
| 				n = i+1; | ||||
| 		for ( int i=0; i<hashKeys.length; i++ ) { | ||||
| 			LuaValue v = hashKeys[i]; | ||||
| 			if ( v!=null && v.isinttype() ) { | ||||
| 				int key = v.toint(); | ||||
| 				if ( key > n ) | ||||
| 					n = key; | ||||
| 			} | ||||
| 		} | ||||
| 		return n; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Get the next element after a particular key in the table  | ||||
| 	 * @return key,value or nil | ||||
| 	 */ | ||||
| 	public Varargs next( LuaValue key ) { | ||||
| 		int i = 0; | ||||
| 		do { | ||||
| 			// find current key index | ||||
| 			if ( ! key.isnil() ) { | ||||
| 				if ( key.isinttype() ) {  | ||||
| 					i = key.toint(); | ||||
| 					if ( i>0 && i<=array.length ) { | ||||
| 						if ( array[i-1] == null ) | ||||
| 							error( "invalid key to 'next'" ); | ||||
| 						break; | ||||
| 					} | ||||
| 				} | ||||
| 				if ( hashKeys.length == 0 ) | ||||
| 					error( "invalid key to 'next'" ); | ||||
| 				i = hashFindSlot(key); | ||||
| 				if ( hashKeys[i] == null ) | ||||
| 					error( "invalid key to 'next'" ); | ||||
| 				i += 1+array.length; | ||||
| 			} | ||||
| 		} while ( false ); | ||||
| 		 | ||||
| 		// check array part | ||||
| 		for ( ; i<array.length; ++i ) | ||||
| 			if ( array[i] != null ) | ||||
| 				return varargsOf(LuaInteger.valueOf(i+1),array[i]); | ||||
|  | ||||
| 		// check hash part | ||||
| 		for ( i-=array.length; i<hashKeys.length; ++i ) | ||||
| 			if ( hashKeys[i] != null ) | ||||
| 				return varargsOf(hashKeys[i],hashValues[i]); | ||||
| 		 | ||||
| 		// nothing found, push nil, return nil. | ||||
| 		return NIL; | ||||
| 	} | ||||
| 		 | ||||
| 	/** | ||||
| 	 * Get the next element after a particular key in the  | ||||
| 	 * contiguous array part of a table  | ||||
| 	 * @return key,value or none | ||||
| 	 */ | ||||
| 	public Varargs inext(LuaValue key) { | ||||
| 		int k = key.checkint() + 1; | ||||
| 		LuaValue v = rawget(k); | ||||
| 		return v.isnil()? NONE: varargsOf(LuaInteger.valueOf(k),v); | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Call the supplied function once for each key-value pair | ||||
| 	 *  | ||||
| 	 * @param func function to call | ||||
| 	 */ | ||||
| 	public LuaValue foreach(LuaValue func) { | ||||
| 		Varargs n; | ||||
| 		LuaValue k = NIL; | ||||
| 		LuaValue v; | ||||
| 		while ( !(k = ((n = next(k)).arg1())).isnil() ) | ||||
| 			if ( ! (v = func.call(k, n.arg(2))).isnil() ) | ||||
| 				return v; | ||||
| 		return NIL; | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Call the supplied function once for each key-value pair  | ||||
| 	 * in the contiguous array part | ||||
| 	 *  | ||||
| 	 * @param func | ||||
| 	 */ | ||||
| 	public LuaValue foreachi(LuaValue func) { | ||||
| 		LuaValue v,r; | ||||
| 		for ( int k=0; !(v = rawget(++k)).isnil(); ) | ||||
| 			if ( ! (r = func.call(valueOf(k), v)).isnil() ) | ||||
| 				return r; | ||||
| 		return NIL; | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	/** | ||||
| 	 * Set a hashtable value | ||||
| 	 * @param key key to set | ||||
| 	 * @param value value to set | ||||
| 	 */ | ||||
| 	public void hashset(LuaValue key, LuaValue value) { | ||||
| 		if ( value.isnil() ) | ||||
| 			hashRemove(key); | ||||
| 		else { | ||||
| 			if ( hashKeys.length == 0 ) { | ||||
| 				hashKeys = new LuaValue[ MIN_HASH_CAPACITY ]; | ||||
| 				hashValues = new LuaValue[ MIN_HASH_CAPACITY ]; | ||||
| 			} | ||||
| 			int slot = hashFindSlot( key ); | ||||
| 			if ( hashFillSlot( slot, value ) ) | ||||
| 				return; | ||||
| 			hashKeys[slot] = key; | ||||
| 			hashValues[slot] = value; | ||||
| 			if ( checkLoadFactor() ) | ||||
| 				rehash(); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Find the hashtable slot to use | ||||
| 	 * @param key key to look for | ||||
| 	 * @return slot to use | ||||
| 	 */ | ||||
| 	public int hashFindSlot(LuaValue key) {		 | ||||
| 		int i = ( key.hashCode() & 0x7FFFFFFF ) % hashKeys.length; | ||||
| 		 | ||||
| 		// This loop is guaranteed to terminate as long as we never allow the | ||||
| 		// table to get 100% full. | ||||
| 		LuaValue k; | ||||
| 		while ( ( k = hashKeys[i] ) != null && !k.raweq(key) ) { | ||||
| 			i = ( i + 1 ) % hashKeys.length; | ||||
| 		} | ||||
| 		return i; | ||||
| 	} | ||||
|  | ||||
| 	private boolean hashFillSlot( int slot, LuaValue value ) { | ||||
| 		hashValues[ slot ] = value; | ||||
| 		if ( hashKeys[ slot ] != null ) { | ||||
| 			return true; | ||||
| 		} else { | ||||
| 			++hashEntries; | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	private void hashRemove( LuaValue key ) { | ||||
| 		if ( hashKeys.length > 0 ) { | ||||
| 			int slot = hashFindSlot( key ); | ||||
| 			hashClearSlot( slot ); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Clear a particular slot in the table | ||||
| 	 * @param i slot to clear. | ||||
| 	 */ | ||||
| 	protected void hashClearSlot( int i ) { | ||||
| 		if ( hashKeys[ i ] != null ) { | ||||
| 			 | ||||
| 			int j = i; | ||||
| 			int n = hashKeys.length;  | ||||
| 			while ( hashKeys[ j = ( ( j + 1 ) % n ) ] != null ) { | ||||
| 				final int k = ( ( hashKeys[ j ].hashCode() )& 0x7FFFFFFF ) % n; | ||||
| 				if ( ( j > i && ( k <= i || k > j ) ) || | ||||
| 					 ( j < i && ( k <= i && k > j ) ) ) { | ||||
| 					hashKeys[ i ] = hashKeys[ j ]; | ||||
| 					hashValues[ i ] = hashValues[ j ]; | ||||
| 					i = j; | ||||
| 				} | ||||
| 			} | ||||
| 			 | ||||
| 			--hashEntries; | ||||
| 			hashKeys[ i ] = null; | ||||
| 			hashValues[ i ] = null; | ||||
| 			 | ||||
| 			if ( hashEntries == 0 ) { | ||||
| 				hashKeys = NOVALS; | ||||
| 				hashValues = NOVALS; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	private boolean checkLoadFactor() { | ||||
| 		// Using a load factor of (n+1) >= 7/8 because that is easy to compute without | ||||
| 		// overflow or division. | ||||
| 		final int hashCapacity = hashKeys.length; | ||||
| 		return hashEntries >= (hashCapacity - (hashCapacity>>3)); | ||||
| 	} | ||||
|  | ||||
| 	private void rehash() { | ||||
| 		final int oldCapacity = hashKeys.length; | ||||
| 		final int newCapacity = oldCapacity+(oldCapacity>>2)+MIN_HASH_CAPACITY; | ||||
| 		 | ||||
| 		final LuaValue[] oldKeys = hashKeys; | ||||
| 		final LuaValue[] oldValues = hashValues; | ||||
| 		 | ||||
| 		hashKeys = new LuaValue[ newCapacity ]; | ||||
| 		hashValues = new LuaValue[ newCapacity ]; | ||||
| 		 | ||||
| 		for ( int i = 0; i < oldCapacity; ++i ) { | ||||
| 			final LuaValue k = oldKeys[i]; | ||||
| 			if ( k != null ) { | ||||
| 				final LuaValue v = oldValues[i]; | ||||
| 				final int slot = hashFindSlot( k ); | ||||
| 				hashKeys[slot] = k; | ||||
| 				hashValues[slot] = v; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	// ----------------- sort support ----------------------------- | ||||
| 	// | ||||
| 	// implemented heap sort from wikipedia | ||||
| 	// | ||||
| 	// Only sorts the contiguous array part.  | ||||
| 	// | ||||
| 	/** Sort the table using a comparator. | ||||
| 	 * @param comparator {@link LuaValue} to be called to compare elements. | ||||
| 	 */ | ||||
| 	public void sort(LuaValue comparator) { | ||||
| 		int n = array.length; | ||||
| 		while ( n > 0 && array[n-1] == null ) | ||||
| 			--n; | ||||
| 		if ( n > 1 )  | ||||
| 			heapSort(n, comparator); | ||||
| 	} | ||||
|  | ||||
| 	private void heapSort(int count, LuaValue cmpfunc) { | ||||
| 		heapify(count, cmpfunc); | ||||
| 		for ( int end=count-1; end>0; ) { | ||||
| 			swap(end, 0); | ||||
| 			siftDown(0, --end, cmpfunc); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	private void heapify(int count, LuaValue cmpfunc) { | ||||
| 		for ( int start=count/2-1; start>=0; --start ) | ||||
| 			siftDown(start, count - 1, cmpfunc); | ||||
| 	} | ||||
|  | ||||
| 	private void siftDown(int start, int end, LuaValue cmpfunc) { | ||||
| 		for ( int root=start; root*2+1 <= end; ) {  | ||||
| 			int child = root*2+1;  | ||||
| 			if (child < end && compare(child, child + 1, cmpfunc)) | ||||
| 				++child;  | ||||
| 			if (compare(root, child, cmpfunc)) { | ||||
| 				swap(root, child); | ||||
| 				root = child; | ||||
| 			} else | ||||
| 				return; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	private boolean compare(int i, int j, LuaValue cmpfunc) { | ||||
| 		LuaValue a = array[i]; | ||||
| 		LuaValue b = array[j]; | ||||
| 		if ( a == null || b == null ) | ||||
| 			return false; | ||||
| 		if ( ! cmpfunc.isnil() ) { | ||||
| 			return cmpfunc.call(a,b).toboolean(); | ||||
| 		} else { | ||||
| 			return a.lt_b(b); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	private void swap(int i, int j) { | ||||
| 		LuaValue a = array[i]; | ||||
| 		array[i] = array[j]; | ||||
| 		array[j] = a; | ||||
| 	} | ||||
| 	 | ||||
| 	/** This may be deprecated in a future release.   | ||||
| 	 * It is recommended to count via iteration over next() instead | ||||
| 	 * @return count of keys in the table  | ||||
| 	 * */ | ||||
| 	public int keyCount() { | ||||
| 		LuaValue k = LuaValue.NIL; | ||||
| 		for ( int i=0; true; i++ ) { | ||||
| 			Varargs n = next(k); | ||||
| 			if ( (k = n.arg1()).isnil() ) | ||||
| 				return i; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	/** This may be deprecated in a future release.   | ||||
| 	 * It is recommended to use next() instead  | ||||
| 	 * @return array of keys in the table  | ||||
| 	 * */ | ||||
| 	public LuaValue[] keys() { | ||||
| 		Vector l = new Vector(); | ||||
| 		LuaValue k = LuaValue.NIL; | ||||
| 		while ( true ) { | ||||
| 			Varargs n = next(k); | ||||
| 			if ( (k = n.arg1()).isnil() ) | ||||
| 				break; | ||||
| 			l.addElement( k ); | ||||
| 		} | ||||
| 		LuaValue[] a = new LuaValue[l.size()]; | ||||
| 		l.copyInto(a); | ||||
| 		return a; | ||||
| 	} | ||||
| 	 | ||||
| 	// equality w/ metatable processing | ||||
| 	public LuaValue eq( LuaValue val ) {  return eq_b(val)? TRUE: FALSE; } | ||||
| 	public boolean eq_b( LuaValue val )  { | ||||
| 		if ( this == val ) return true; | ||||
| 		if ( m_metatable == null || !val.istable() ) return false; | ||||
| 		LuaValue valmt = val.getmetatable(); | ||||
| 		return valmt!=null && LuaValue.eqmtcall(this, m_metatable, val, valmt);  | ||||
| 	} | ||||
| } | ||||
| @@ -1,433 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2007-2012 LuaJ. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
|  | ||||
| /* DAN200 START */ | ||||
| import java.lang.ref.WeakReference; | ||||
| import java.util.Enumeration; | ||||
| import java.util.Vector; | ||||
| /* DAN200 END */ | ||||
|  | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.lib.DebugLib; | ||||
|  | ||||
| /**  | ||||
|  * Subclass of {@link LuaValue} that implements  | ||||
|  * a lua coroutine thread using Java Threads. | ||||
|  * <p> | ||||
|  * A LuaThread is typically created in response to a scripted call to  | ||||
|  * {@code coroutine.create()} | ||||
|  * <p> | ||||
|  * The threads must be initialized with the globals, so that  | ||||
|  * the global environment may be passed along according to rules of lua.  | ||||
|  * This is done via a call to {@link #setGlobals(LuaValue)}  | ||||
|  * at some point during globals initialization. | ||||
|  * See {@link BaseLib} for additional documentation and example code.   | ||||
|  * <p>  | ||||
|  * The utility classes {@link JsePlatform} and {@link JmePlatform}  | ||||
|  * see to it that this initialization is done properly.   | ||||
|  * For this reason it is highly recommended to use one of these classes | ||||
|  * when initializing globals.  | ||||
|  * <p> | ||||
|  * The behavior of coroutine threads matches closely the behavior  | ||||
|  * of C coroutine library.  However, because of the use of Java threads  | ||||
|  * to manage call state, it is possible to yield from anywhere in luaj.  | ||||
|  * <p> | ||||
|  * Each Java thread wakes up at regular intervals and checks a weak reference | ||||
|  * to determine if it can ever be resumed.  If not, it throws  | ||||
|  * {@link OrphanedThread} which is an {@link java.lang.Error}.  | ||||
|  * Applications should not catch {@link OrphanedThread}, because it can break | ||||
|  * the thread safety of luaj. | ||||
|  *    | ||||
|  * @see LuaValue | ||||
|  * @see JsePlatform | ||||
|  * @see JmePlatform | ||||
|  * @see CoroutineLib | ||||
|  */ | ||||
| public class LuaThread extends LuaValue { | ||||
| 	 | ||||
| 	public static LuaValue s_metatable; | ||||
|  | ||||
| 	public static int coroutine_count = 0; | ||||
|  | ||||
| 	/** Interval at which to check for lua threads that are no longer referenced.  | ||||
| 	 * This can be changed by Java startup code if desired. | ||||
| 	 */ | ||||
| 	static long thread_orphan_check_interval = 30000; | ||||
| 	 | ||||
| 	private static final int STATUS_INITIAL       = 0; | ||||
| 	private static final int STATUS_SUSPENDED     = 1; | ||||
| 	private static final int STATUS_RUNNING       = 2; | ||||
| 	private static final int STATUS_NORMAL        = 3; | ||||
| 	private static final int STATUS_DEAD          = 4; | ||||
| 	private static final String[] STATUS_NAMES = {  | ||||
| 		"suspended",  | ||||
| 		"suspended",  | ||||
| 		"running",  | ||||
| 		"normal",  | ||||
| 		"dead",}; | ||||
| 	 | ||||
| 	private LuaValue env; | ||||
| 	private final State state; | ||||
|  | ||||
| 	/** Field to hold state of error condition during debug hook function calls. */ | ||||
| 	public LuaValue err; | ||||
| 	 | ||||
| 	final CallStack callstack = new CallStack(); | ||||
| 	 | ||||
| 	public static final int        MAX_CALLSTACK = 256; | ||||
| 	 | ||||
| 	private static final LuaThread main_thread = new LuaThread(); | ||||
| 	 | ||||
| 	// state of running thread including call stack | ||||
| 	private static LuaThread       running_thread    = main_thread; | ||||
|  | ||||
| 	/** Interval to check for LuaThread dereferencing.  */ | ||||
| 	public static int GC_INTERVAL = 30000; | ||||
|  | ||||
| 	/** Thread-local used by DebugLib to store debugging state.  */ | ||||
| 	public Object debugState; | ||||
|  | ||||
| 	/* DAN200 START */ | ||||
|     private Vector children = new Vector(); | ||||
|     /* DAN200 END */ | ||||
|  | ||||
| 	/** Private constructor for main thread only */ | ||||
| 	private LuaThread() { | ||||
| 		state = new State(this, null); | ||||
| 		state.status = STATUS_RUNNING; | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Create a LuaThread around a function and environment | ||||
| 	 * @param func The function to execute | ||||
| 	 * @param env The environment to apply to the thread | ||||
| 	 */ | ||||
| 	public LuaThread(LuaValue func, LuaValue env) {	 | ||||
| 		LuaValue.assert_(func != null, "function cannot be null"); | ||||
| 		this.env = env; | ||||
| 		state = new State(this, func); | ||||
| 	} | ||||
| 	 | ||||
| 	public int type() { | ||||
| 		return LuaValue.TTHREAD; | ||||
| 	} | ||||
| 	 | ||||
| 	public String typename() { | ||||
| 		return "thread"; | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean isthread() { | ||||
| 		return true; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaThread optthread(LuaThread defval) { | ||||
| 		return this; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaThread checkthread() { | ||||
| 		return this; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue getmetatable() {  | ||||
| 		return s_metatable;  | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue getfenv() { | ||||
| 		return env; | ||||
| 	} | ||||
| 	 | ||||
| 	public void setfenv(LuaValue env) { | ||||
| 		this.env = env; | ||||
| 	} | ||||
|  | ||||
| 	public String getStatus() { | ||||
| 		return STATUS_NAMES[state.status]; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Get the currently running thread.  | ||||
| 	 * @return {@link LuaThread} that is currenly running | ||||
| 	 */ | ||||
| 	public static LuaThread getRunning() { | ||||
| 		return running_thread; | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Test if this is the main thread  | ||||
| 	 * @return true if this is the main thread | ||||
| 	 */ | ||||
| 	public static boolean isMainThread(LuaThread r) {		 | ||||
| 		return r == main_thread; | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Set the globals of the current thread. | ||||
| 	 * <p> | ||||
| 	 * This must be done once before any other code executes. | ||||
| 	 * @param globals The global variables for the main ghread.  | ||||
| 	 */ | ||||
| 	public static void setGlobals(LuaValue globals) { | ||||
| 		running_thread.env = globals; | ||||
| 	} | ||||
| 	 | ||||
| 	/** Get the current thread's environment  | ||||
| 	 * @return {@link LuaValue} containing the global variables of the current thread. | ||||
| 	 */ | ||||
| 	public static LuaValue getGlobals() { | ||||
| 		LuaValue e = running_thread.env; | ||||
| 		return e!=null? e: LuaValue.error("LuaThread.setGlobals() not initialized"); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Callback used at the beginning of a call to prepare for possible getfenv/setfenv calls | ||||
| 	 * @param function Function being called | ||||
| 	 * @return CallStack which is used to signal the return or a tail-call recursion | ||||
| 	 * @see DebugLib | ||||
| 	 */ | ||||
| 	public static final CallStack onCall(LuaFunction function) { | ||||
| 		CallStack cs = running_thread.callstack; | ||||
| 		cs.onCall(function); | ||||
| 		return cs; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Get the function called as a specific location on the stack. | ||||
| 	 * @param level 1 for the function calling this one, 2 for the next one. | ||||
| 	 * @return LuaFunction on the call stack, or null if outside of range of active stack | ||||
| 	 */ | ||||
| 	public static final LuaFunction getCallstackFunction(int level) { | ||||
| 		return running_thread.callstack.getFunction(level); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Replace the error function of the currently running thread. | ||||
| 	 * @param errfunc the new error function to use. | ||||
| 	 * @return the previous error function. | ||||
| 	 */ | ||||
| 	public static LuaValue setErrorFunc(LuaValue errfunc) { | ||||
| 		LuaValue prev = running_thread.err; | ||||
| 		running_thread.err = errfunc; | ||||
| 		return prev; | ||||
| 	} | ||||
|  | ||||
| 	/** Yield the current thread with arguments  | ||||
| 	 *  | ||||
| 	 * @param args The arguments to send as return values to {@link #resume(Varargs)} | ||||
| 	 * @return {@link Varargs} provided as arguments to {@link #resume(Varargs)} | ||||
| 	 */ | ||||
| 	public static Varargs yield(Varargs args) { | ||||
| 		State s = running_thread.state; | ||||
| 		if (s.function == null) | ||||
| 			throw new LuaError("cannot yield main thread"); | ||||
| 		return s.lua_yield(args); | ||||
| 	} | ||||
| 	 | ||||
| 	/** Start or resume this thread  | ||||
| 	 *  | ||||
| 	 * @param args The arguments to send as return values to {@link #yield(Varargs)} | ||||
| 	 * @return {@link Varargs} provided as arguments to {@link #yield(Varargs)} | ||||
| 	 */ | ||||
| 	public Varargs resume(Varargs args) { | ||||
| 		if (this.state.status > STATUS_SUSPENDED) | ||||
| 			return LuaValue.varargsOf(LuaValue.FALSE,  | ||||
| 					LuaValue.valueOf("cannot resume "+LuaThread.STATUS_NAMES[this.state.status]+" coroutine")); | ||||
| 		return state.lua_resume(this, args); | ||||
| 	} | ||||
|  | ||||
| 	/* DAN200 START */ | ||||
|     public void addChild( LuaThread thread ) { | ||||
|         this.children.addElement( new WeakReference( thread ) ); | ||||
|     } | ||||
|  | ||||
|     public Varargs abandon() { | ||||
|         if( this.state.status > STATUS_SUSPENDED ) { | ||||
|             return LuaValue.varargsOf( LuaValue.FALSE, LuaValue.valueOf( "cannot abandon " + STATUS_NAMES[this.state.status] + " coroutine" ) ); | ||||
|         } else { | ||||
|             this.state.lua_abandon( this ); | ||||
|  | ||||
|             Enumeration it = this.children.elements(); | ||||
|             while( it.hasMoreElements() ) { | ||||
|                 WeakReference ref = (WeakReference)it.nextElement(); | ||||
|                 LuaThread thread = (LuaThread)ref.get(); | ||||
|                 if(thread != null && !thread.getStatus().equals("dead")) { | ||||
|                     thread.abandon(); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             this.children.removeAllElements(); | ||||
|             return LuaValue.varargsOf( new LuaValue[] { LuaValue.TRUE } ); | ||||
|         } | ||||
|     } | ||||
|     /* DAN200 END */ | ||||
|  | ||||
| 	static class State implements Runnable { | ||||
| 		final WeakReference lua_thread; | ||||
| 		final LuaValue function; | ||||
| 		Varargs args = LuaValue.NONE; | ||||
| 		Varargs result = LuaValue.NONE; | ||||
| 		String error = null; | ||||
| 		int status = LuaThread.STATUS_INITIAL; | ||||
|         /* DAN200 START */ | ||||
|         boolean abandoned = false; | ||||
|         /* DAN200 END */ | ||||
|  | ||||
| 		State(LuaThread lua_thread, LuaValue function) { | ||||
| 			this.lua_thread = new WeakReference(lua_thread); | ||||
| 			this.function = function; | ||||
| 		} | ||||
| 		 | ||||
| 		public synchronized void run() { | ||||
| 			try { | ||||
| 				Varargs a = this.args; | ||||
| 				this.args = LuaValue.NONE; | ||||
| 				this.result = function.invoke(a); | ||||
| 			} catch (Throwable t) { | ||||
| 				this.error = t.getMessage(); | ||||
| 			} finally { | ||||
| 				this.status = LuaThread.STATUS_DEAD; | ||||
| 				this.notify(); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		synchronized Varargs lua_resume(LuaThread new_thread, Varargs args) { | ||||
| 			LuaThread previous_thread = LuaThread.running_thread; | ||||
| 			try { | ||||
| 				LuaThread.running_thread = new_thread; | ||||
| 				this.args = args; | ||||
| 				if (this.status == STATUS_INITIAL) { | ||||
| 					this.status = STATUS_RUNNING;  | ||||
| 					new Thread(this, "Coroutine-"+(++coroutine_count)).start(); | ||||
| 				} else { | ||||
| 					this.notify(); | ||||
| 				} | ||||
| 				previous_thread.state.status = STATUS_NORMAL; | ||||
| 				this.status = STATUS_RUNNING; | ||||
| 				this.wait(); | ||||
| 				return (this.error != null?  | ||||
| 					LuaValue.varargsOf(LuaValue.FALSE, LuaValue.valueOf(this.error)): | ||||
| 					LuaValue.varargsOf(LuaValue.TRUE, this.result)); | ||||
| 			} catch (InterruptedException ie) { | ||||
| 				throw new OrphanedThread(); | ||||
| 			} finally { | ||||
| 				running_thread = previous_thread; | ||||
| 				running_thread.state.status =STATUS_RUNNING; | ||||
| 				this.args = LuaValue.NONE; | ||||
| 				this.result = LuaValue.NONE; | ||||
| 				this.error = null; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		synchronized Varargs lua_yield(Varargs args) { | ||||
| 			try { | ||||
| 				this.result = args; | ||||
| 				this.status = STATUS_SUSPENDED; | ||||
| 				this.notify(); | ||||
| 				do { | ||||
| 					this.wait(thread_orphan_check_interval); | ||||
|                     /* DAN200 START */ | ||||
| 					//if (this.lua_thread.get() == null) { | ||||
|                     if( this.abandoned || this.lua_thread.get() == null ) { | ||||
|                     /* DAN200 END */ | ||||
| 						this.status = STATUS_DEAD; | ||||
| 						throw new OrphanedThread(); | ||||
| 					} | ||||
| 				} while (this.status == STATUS_SUSPENDED); | ||||
| 				return this.args; | ||||
| 			} catch (InterruptedException ie) { | ||||
| 				this.status = STATUS_DEAD; | ||||
| 				throw new OrphanedThread(); | ||||
| 			} finally { | ||||
| 				this.args = LuaValue.NONE; | ||||
| 				this.result = LuaValue.NONE; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		/* DAN200 START */ | ||||
|         synchronized void lua_abandon(LuaThread thread) { | ||||
|             LuaThread current = LuaThread.running_thread; | ||||
|  | ||||
|             try { | ||||
|                 current.state.status = STATUS_NORMAL; | ||||
|                 this.abandoned = true; | ||||
|                 if(this.status == STATUS_INITIAL) { | ||||
|                     this.status = STATUS_DEAD; | ||||
|                 } else { | ||||
|                     this.notify(); | ||||
|                     this.wait(); | ||||
|                 } | ||||
|             } catch (InterruptedException var7) { | ||||
|                 this.status = STATUS_DEAD; | ||||
|             } finally { | ||||
|                 current.state.status = STATUS_RUNNING; | ||||
|                 this.args = LuaValue.NONE; | ||||
|                 this.result = LuaValue.NONE; | ||||
|                 this.error = null; | ||||
|             } | ||||
|         } | ||||
|         /* DAN200 END */ | ||||
| 	} | ||||
|  | ||||
| 	public static class CallStack { | ||||
| 		final LuaFunction[]     functions     = new LuaFunction[MAX_CALLSTACK]; | ||||
| 		int                     calls         = 0; | ||||
|  | ||||
| 		/** | ||||
| 		 * Method to indicate the start of a call | ||||
| 		 * @see DebugLib | ||||
| 		 */ | ||||
| 		final void onCall(LuaFunction function) { | ||||
| 			functions[calls++] = function; | ||||
| 			if (DebugLib.DEBUG_ENABLED)  | ||||
| 				DebugLib.debugOnCall(running_thread, calls, function); | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Method to signal the end of a call | ||||
| 		 * @see DebugLib | ||||
| 		 */ | ||||
| 		public final void onReturn() { | ||||
| 			functions[--calls] = null; | ||||
| 			if (DebugLib.DEBUG_ENABLED)  | ||||
| 				DebugLib.debugOnReturn(running_thread, calls); | ||||
| 		} | ||||
| 		 | ||||
| 		/** | ||||
| 		 * Get number of calls in stack | ||||
| 		 * @return number of calls in current call stack | ||||
| 		 * @see DebugLib | ||||
| 		 */ | ||||
| 		public final int getCallstackDepth() { | ||||
| 			return calls; | ||||
| 		} | ||||
|  | ||||
| 		/**  | ||||
| 		 * Get the function at a particular level of the stack. | ||||
| 		 * @param level # of levels back from the top of the stack. | ||||
| 		 * @return LuaFunction, or null if beyond the stack limits. | ||||
| 		 */ | ||||
| 		LuaFunction getFunction(int level) { | ||||
| 			return level>0 && level<=calls? functions[calls-level]: null; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,126 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
|  | ||||
| public class LuaUserdata extends LuaValue { | ||||
| 	 | ||||
| 	public final Object m_instance; | ||||
| 	public LuaValue m_metatable; | ||||
| 	 | ||||
| 	public LuaUserdata(Object obj) { | ||||
| 		m_instance = obj; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaUserdata(Object obj, LuaValue metatable) { | ||||
| 		m_instance = obj; | ||||
| 		m_metatable = metatable; | ||||
| 	} | ||||
|  | ||||
| 	public String tojstring() { | ||||
| 		return String.valueOf(m_instance); | ||||
| 	} | ||||
| 	 | ||||
| 	public int type() { | ||||
| 		return LuaValue.TUSERDATA; | ||||
| 	} | ||||
| 	 | ||||
| 	public String typename() { | ||||
| 		return "userdata"; | ||||
| 	} | ||||
|  | ||||
| 	public int hashCode() { | ||||
| 		return m_instance.hashCode(); | ||||
| 	} | ||||
| 	 | ||||
| 	public Object userdata() { | ||||
| 		return m_instance; | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean isuserdata()                        { return true; } | ||||
| 	public boolean isuserdata(Class c)                 { return c.isAssignableFrom(m_instance.getClass()); } | ||||
| 	public Object  touserdata()                        { return m_instance; } | ||||
| 	public Object  touserdata(Class c)                 { return c.isAssignableFrom(m_instance.getClass())? m_instance: null; } | ||||
| 	public Object  optuserdata(Object defval)          { return m_instance; } | ||||
| 	public Object optuserdata(Class c, Object defval) { | ||||
| 		if (!c.isAssignableFrom(m_instance.getClass())) | ||||
| 			typerror(c.getName()); | ||||
| 		return m_instance; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue getmetatable() { | ||||
| 		return m_metatable; | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue setmetatable(LuaValue metatable) { | ||||
| 		this.m_metatable = metatable; | ||||
| 		return this; | ||||
| 	} | ||||
|  | ||||
| 	public Object checkuserdata() { | ||||
| 		return m_instance; | ||||
| 	} | ||||
| 	 | ||||
| 	public Object checkuserdata(Class c) {  | ||||
| 		if ( c.isAssignableFrom(m_instance.getClass()) ) | ||||
| 			return m_instance;		 | ||||
| 		return typerror(c.getName()); | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue get( LuaValue key ) { | ||||
| 		return m_metatable!=null? gettable(this,key): NIL; | ||||
| 	} | ||||
| 	 | ||||
| 	public void set( LuaValue key, LuaValue value ) { | ||||
| 		if ( m_metatable==null || ! settable(this,key,value) ) | ||||
| 			error( "cannot set "+key+" for userdata" ); | ||||
| 	} | ||||
|  | ||||
| 	public boolean equals( Object val ) { | ||||
| 		if ( this == val ) | ||||
| 			return true; | ||||
| 		if ( ! (val instanceof LuaUserdata) ) | ||||
| 			return false; | ||||
| 		LuaUserdata u = (LuaUserdata) val; | ||||
| 		return m_instance.equals(u.m_instance); | ||||
| 	} | ||||
|  | ||||
| 	// equality w/ metatable processing | ||||
| 	public LuaValue eq( LuaValue val )     { return eq_b(val)? TRUE: FALSE; }  | ||||
| 	public boolean eq_b( LuaValue val ) {  | ||||
| 		if ( val.raweq(this) ) return true; | ||||
| 		if ( m_metatable == null || !val.isuserdata() ) return false; | ||||
| 		LuaValue valmt = val.getmetatable(); | ||||
| 		return valmt!=null && LuaValue.eqmtcall(this, m_metatable, val, valmt);  | ||||
| 	} | ||||
| 	 | ||||
| 	// equality w/o metatable processing | ||||
| 	public boolean raweq( LuaValue val )      { return val.raweq(this); } | ||||
| 	public boolean raweq( LuaUserdata val )   { | ||||
| 		return this == val || (m_metatable == val.m_metatable && m_instance.equals(val.m_instance));  | ||||
| 	} | ||||
| 	 | ||||
| 	// __eq metatag processing | ||||
| 	public boolean eqmt( LuaValue val )    {  | ||||
| 		return m_metatable!=null && val.isuserdata()? LuaValue.eqmtcall(this, m_metatable, val, val.getmetatable()): false;  | ||||
| 	} | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,44 +0,0 @@ | ||||
| /******************************************************************************* | ||||
|  * Copyright (c) 2012 Luaj.org. All rights reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
| /** | ||||
|  * {@link java.lang.Error} sublcass that indicates a lua thread that is no | ||||
|  * longer referenced has been detected. | ||||
|  * <p> | ||||
|  * The java thread in which this is thrown should correspond to a | ||||
|  * {@link LuaThread} being used as a coroutine that could not possibly be | ||||
|  * resumed again because there are no more references to the LuaThread with | ||||
|  * which it is associated. Rather than locking up resources forever, this error | ||||
|  * is thrown, and should fall through all the way to the thread's {@link Thread.run}() method. | ||||
|  * <p> | ||||
|  * Java code mixed with the luaj vm should not catch this error because it may | ||||
|  * occur when the coroutine is not running, so any processing done during error | ||||
|  * handling could break the thread-safety of the application because other lua | ||||
|  * processing could be going on in a different thread. | ||||
|  */ | ||||
| public class OrphanedThread extends Error { | ||||
|  | ||||
| 	public OrphanedThread() { | ||||
| 		super("orphaned thread"); | ||||
| 	} | ||||
| } | ||||
| @@ -1,417 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
| import java.io.ByteArrayOutputStream; | ||||
| import java.io.PrintStream; | ||||
|  | ||||
| /** | ||||
|  * Debug helper class to pretty-print lua bytecodes.  | ||||
|  * @see Prototype | ||||
|  * @see LuaClosure  | ||||
|  */ | ||||
| public class Print extends Lua { | ||||
|  | ||||
| 	/** opcode names */ | ||||
| 	private static final String STRING_FOR_NULL = "null"; | ||||
| 	public static PrintStream ps = System.out; | ||||
|  | ||||
| 	public static final String[] OPNAMES = { | ||||
| 		  "MOVE", | ||||
| 		  "LOADK", | ||||
| 		  "LOADBOOL", | ||||
| 		  "LOADNIL", | ||||
| 		  "GETUPVAL", | ||||
| 		  "GETGLOBAL", | ||||
| 		  "GETTABLE", | ||||
| 		  "SETGLOBAL", | ||||
| 		  "SETUPVAL", | ||||
| 		  "SETTABLE", | ||||
| 		  "NEWTABLE", | ||||
| 		  "SELF", | ||||
| 		  "ADD", | ||||
| 		  "SUB", | ||||
| 		  "MUL", | ||||
| 		  "DIV", | ||||
| 		  "MOD", | ||||
| 		  "POW", | ||||
| 		  "UNM", | ||||
| 		  "NOT", | ||||
| 		  "LEN", | ||||
| 		  "CONCAT", | ||||
| 		  "JMP", | ||||
| 		  "EQ", | ||||
| 		  "LT", | ||||
| 		  "LE", | ||||
| 		  "TEST", | ||||
| 		  "TESTSET", | ||||
| 		  "CALL", | ||||
| 		  "TAILCALL", | ||||
| 		  "RETURN", | ||||
| 		  "FORLOOP", | ||||
| 		  "FORPREP", | ||||
| 		  "TFORLOOP", | ||||
| 		  "SETLIST", | ||||
| 		  "CLOSE", | ||||
| 		  "CLOSURE", | ||||
| 		  "VARARG", | ||||
| 		  null, | ||||
| 	}; | ||||
|  | ||||
|  | ||||
| 	static void printString(PrintStream ps, final LuaString s) { | ||||
| 		 | ||||
| 		ps.print('"'); | ||||
| 		for (int i = 0, n = s.m_length; i < n; i++) { | ||||
| 			int c = s.m_bytes[s.m_offset+i]; | ||||
| 			if ( c >= ' ' && c <= '~' && c != '\"' && c != '\\' ) | ||||
| 				ps.print((char) c); | ||||
| 			else { | ||||
| 				switch (c) { | ||||
| 					case '"': | ||||
| 						ps.print("\\\""); | ||||
| 						break; | ||||
| 					case '\\': | ||||
| 						ps.print("\\\\"); | ||||
| 						break; | ||||
| 					case 0x0007: /* bell */ | ||||
| 						ps.print("\\a"); | ||||
| 						break; | ||||
| 					case '\b': /* backspace */ | ||||
| 						ps.print("\\b"); | ||||
| 						break; | ||||
| 					case '\f':  /* form feed */ | ||||
| 						ps.print("\\f"); | ||||
| 						break; | ||||
| 					case '\t':  /* tab */ | ||||
| 						ps.print("\\t"); | ||||
| 						break; | ||||
| 					case '\r': /* carriage return */ | ||||
| 						ps.print("\\r"); | ||||
| 						break; | ||||
| 					case '\n': /* newline */ | ||||
| 						ps.print("\\n"); | ||||
| 						break; | ||||
| 					case 0x000B: /* vertical tab */ | ||||
| 						ps.print("\\v"); | ||||
| 						break; | ||||
| 					default: | ||||
| 						ps.print('\\'); | ||||
| 						ps.print(Integer.toString(1000 + 0xff&c).substring(1)); | ||||
| 						break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		ps.print('"'); | ||||
| 	} | ||||
|  | ||||
| 	static void printValue( PrintStream ps, LuaValue v ) { | ||||
| 		switch ( v.type() ) { | ||||
| 		case LuaValue.TSTRING: printString( ps, (LuaString) v ); break; | ||||
| 		default: ps.print( v.tojstring() ); | ||||
| 		 | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	static void printConstant(PrintStream ps, Prototype f, int i) { | ||||
| 		printValue( ps, f.k[i] ); | ||||
| 	} | ||||
|  | ||||
| 	/**  | ||||
| 	 * Print the code in a prototype | ||||
| 	 * @param f the {@link Prototype} | ||||
| 	 */ | ||||
| 	public static void printCode(Prototype f) { | ||||
| 		int[] code = f.code; | ||||
| 		int pc, n = code.length; | ||||
| 		for (pc = 0; pc < n; pc++) { | ||||
| 			printOpCode(f, pc); | ||||
| 			ps.println(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/**  | ||||
| 	 * Print an opcode in a prototype | ||||
| 	 * @param f the {@link Prototype} | ||||
| 	 * @param pc the program counter to look up and print | ||||
| 	 */ | ||||
| 	public static void printOpCode(Prototype f, int pc) { | ||||
| 		printOpCode(ps,f,pc); | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Print an opcode in a prototype | ||||
| 	 * @param ps the {@link PrintStream} to print to | ||||
| 	 * @param f the {@link Prototype} | ||||
| 	 * @param pc the program counter to look up and print | ||||
| 	 */ | ||||
| 	public static void printOpCode(PrintStream ps, Prototype f, int pc) { | ||||
| 		int[] code = f.code; | ||||
| 		int i = code[pc]; | ||||
| 		int o = GET_OPCODE(i); | ||||
| 		int a = GETARG_A(i); | ||||
| 		int b = GETARG_B(i); | ||||
| 		int c = GETARG_C(i); | ||||
| 		int bx = GETARG_Bx(i); | ||||
| 		int sbx = GETARG_sBx(i); | ||||
| 		int line = getline(f, pc); | ||||
| 		ps.print("  " + (pc + 1) + "  "); | ||||
| 		if (line > 0) | ||||
| 			ps.print("[" + line + "]  "); | ||||
| 		else | ||||
| 			ps.print("[-]  "); | ||||
| 		ps.print(OPNAMES[o] + "  "); | ||||
| 		switch (getOpMode(o)) { | ||||
| 		case iABC: | ||||
| 			ps.print( a ); | ||||
| 			if (getBMode(o) != OpArgN) | ||||
| 				ps.print(" "+(ISK(b) ? (-1 - INDEXK(b)) : b)); | ||||
| 			if (getCMode(o) != OpArgN) | ||||
| 				ps.print(" "+(ISK(c) ? (-1 - INDEXK(c)) : c)); | ||||
| 			break; | ||||
| 		case iABx: | ||||
| 			if (getBMode(o) == OpArgK) { | ||||
| 				ps.print(a + " " + (-1 - bx)); | ||||
| 			} else { | ||||
| 				ps.print(a + " " + (bx)); | ||||
| 			} | ||||
| 			break; | ||||
| 		case iAsBx: | ||||
| 			if (o == OP_JMP) | ||||
| 				ps.print( sbx ); | ||||
| 			else | ||||
| 				ps.print(a + " " + sbx); | ||||
| 			break; | ||||
| 		} | ||||
| 		switch (o) { | ||||
| 		case OP_LOADK: | ||||
| 			ps.print("  ; "); | ||||
| 			printConstant(ps, f, bx); | ||||
| 			break; | ||||
| 		case OP_GETUPVAL: | ||||
| 		case OP_SETUPVAL: | ||||
| 			ps.print("  ; "); | ||||
| 			if ( f.upvalues.length > b ) | ||||
| 				printValue(ps, f.upvalues[b]); | ||||
| 			else | ||||
| 				ps.print( "-" ); | ||||
| 			break; | ||||
| 		case OP_GETGLOBAL: | ||||
| 		case OP_SETGLOBAL: | ||||
| 			ps.print("  ; "); | ||||
| 			printConstant( ps, f, bx ); | ||||
| 			break; | ||||
| 		case OP_GETTABLE: | ||||
| 		case OP_SELF: | ||||
| 			if (ISK(c)) { | ||||
| 				ps.print("  ; "); | ||||
| 				printConstant(ps, f, INDEXK(c)); | ||||
| 			} | ||||
| 			break; | ||||
| 		case OP_SETTABLE: | ||||
| 		case OP_ADD: | ||||
| 		case OP_SUB: | ||||
| 		case OP_MUL: | ||||
| 		case OP_DIV: | ||||
| 		case OP_POW: | ||||
| 		case OP_EQ: | ||||
| 		case OP_LT: | ||||
| 		case OP_LE: | ||||
| 			if (ISK(b) || ISK(c)) { | ||||
| 				ps.print("  ; "); | ||||
| 				if (ISK(b)) | ||||
| 					printConstant(ps, f, INDEXK(b)); | ||||
| 				else | ||||
| 					ps.print("-"); | ||||
| 				ps.print(" "); | ||||
| 				if (ISK(c)) | ||||
| 					printConstant(ps, f, INDEXK(c)); | ||||
| 				else | ||||
| 					ps.print("-"); | ||||
| 			} | ||||
| 			break; | ||||
| 		case OP_JMP: | ||||
| 		case OP_FORLOOP: | ||||
| 		case OP_FORPREP: | ||||
| 			ps.print("  ; to " + (sbx + pc + 2)); | ||||
| 			break; | ||||
| 		case OP_CLOSURE: | ||||
| 			ps.print("  ; " + f.p[bx].getClass().getName()); | ||||
| 			break; | ||||
| 		case OP_SETLIST: | ||||
| 			if (c == 0) | ||||
| 				ps.print("  ; " + ((int) code[++pc])); | ||||
| 			else | ||||
| 				ps.print("  ; " + ((int) c)); | ||||
| 			break; | ||||
| 		case OP_VARARG: | ||||
| 			ps.print( "  ; is_vararg="+ f.is_vararg ); | ||||
| 			break;			 | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	private static int getline(Prototype f, int pc) { | ||||
| 		return pc>0 && f.lineinfo!=null && pc<f.lineinfo.length? f.lineinfo[pc]: -1; | ||||
| 	} | ||||
|  | ||||
| 	static void printHeader(Prototype f) { | ||||
| 		String s = String.valueOf(f.source); | ||||
| 		if (s.startsWith("@") || s.startsWith("=")) | ||||
| 			s = s.substring(1); | ||||
| 		else if ("\033Lua".equals(s)) | ||||
| 			s = "(bstring)"; | ||||
| 		else | ||||
| 			s = "(string)"; | ||||
| 		String a = (f.linedefined == 0) ? "main" : "function"; | ||||
| 		ps.print("\n%" + a + " <" + s + ":" + f.linedefined + "," | ||||
| 				+ f.lastlinedefined + "> (" + f.code.length + " instructions, " | ||||
| 				+ f.code.length * 4 + " bytes at " + id(f) + ")\n"); | ||||
| 		ps.print(f.numparams + " param, " + f.maxstacksize + " slot, " | ||||
| 				+ f.upvalues.length + " upvalue, "); | ||||
| 		ps.print(f.locvars.length + " local, " + f.k.length | ||||
| 				+ " constant, " + f.p.length + " function\n"); | ||||
| 	} | ||||
|  | ||||
| 	static void printConstants(Prototype f) { | ||||
| 		int i, n = f.k.length; | ||||
| 		ps.print("constants (" + n + ") for " + id(f) + ":\n"); | ||||
| 		for (i = 0; i < n; i++) { | ||||
| 			ps.print("  " + (i + 1) + "  "); | ||||
| 			printValue( ps, f.k[i] ); | ||||
| 			ps.print( "\n"); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	static void printLocals(Prototype f) { | ||||
| 		int i, n = f.locvars.length; | ||||
| 		ps.print("locals (" + n + ") for " + id(f) + ":\n"); | ||||
| 		for (i = 0; i < n; i++) { | ||||
| 			ps.println("  "+i+"  "+f.locvars[i].varname+" "+(f.locvars[i].startpc+1)+" "+(f.locvars[i].endpc+1)); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	static void printUpValues(Prototype f) { | ||||
| 		int i, n = f.upvalues.length; | ||||
| 		ps.print("upvalues (" + n + ") for " + id(f) + ":\n"); | ||||
| 		for (i = 0; i < n; i++) { | ||||
| 			ps.print("  " + i + "  " + f.upvalues[i] + "\n"); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public static void print(Prototype p) { | ||||
| 		printFunction(p, true); | ||||
| 	} | ||||
| 	 | ||||
| 	public static void printFunction(Prototype f, boolean full) { | ||||
| 		int i, n = f.p.length; | ||||
| 		printHeader(f); | ||||
| 		printCode(f); | ||||
| 		if (full) { | ||||
| 			printConstants(f); | ||||
| 			printLocals(f); | ||||
| 			printUpValues(f); | ||||
| 		} | ||||
| 		for (i = 0; i < n; i++) | ||||
| 			printFunction(f.p[i], full); | ||||
| 	} | ||||
|  | ||||
| 	private static void format( String s, int maxcols ) { | ||||
| 		int n = s.length(); | ||||
| 		if ( n > maxcols ) | ||||
| 			ps.print( s.substring(0,maxcols) ); | ||||
| 		else { | ||||
| 			ps.print( s ); | ||||
| 			for ( int i=maxcols-n; --i>=0; ) | ||||
| 				ps.print( ' ' ); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	private static String id(Prototype f) { | ||||
| 		return "Proto"; | ||||
| 	} | ||||
| 	private void _assert(boolean b) { | ||||
| 		if ( !b )  | ||||
| 			throw new NullPointerException("_assert failed"); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Print the state of a {@link LuaClosure} that is being executed | ||||
| 	 * @param cl the {@link LuaClosure}  | ||||
| 	 * @param pc the program counter | ||||
| 	 * @param stack the stack of {@link LuaValue} | ||||
| 	 * @param top the top of the stack | ||||
| 	 * @param varargs any {@link Varargs} value that may apply | ||||
| 	 */ | ||||
| 	public static void printState(LuaClosure cl, int pc, LuaValue[] stack, int top, Varargs varargs) { | ||||
| 		// print opcode into buffer | ||||
| 		PrintStream previous = ps; | ||||
| 		ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||||
| 		ps = new PrintStream( baos ); | ||||
| 		printOpCode( cl.p, pc ); | ||||
| 		ps.flush(); | ||||
| 		ps.close(); | ||||
| 		ps = previous; | ||||
| 		format( baos.toString(), 50 ); | ||||
|  | ||||
| 		// print stack | ||||
| 		ps.print('['); | ||||
| 		for ( int i=0; i<stack.length; i++ ) { | ||||
| 			LuaValue v = stack[i]; | ||||
| 			if ( v == null )  | ||||
| 				ps.print(STRING_FOR_NULL); | ||||
| 			else switch ( v.type() ) { | ||||
| 			case LuaValue.TSTRING:  | ||||
| 				LuaString s = v.checkstring(); | ||||
| 				ps.print( s.length() < 48? | ||||
| 						s.tojstring(): | ||||
| 						s.substring(0, 32).tojstring()+"...+"+(s.length()-32)+"b");					 | ||||
| 				break; | ||||
| 			case LuaValue.TFUNCTION: | ||||
| 				ps.print( ( v instanceof LuaClosure )? | ||||
| 					((LuaClosure)v).p.toString(): v.tojstring() ); | ||||
| 				break; | ||||
| 			case LuaValue.TUSERDATA: | ||||
| 				Object o = v.touserdata(); | ||||
| 				if ( o != null ) { | ||||
| 					String n = o.getClass().getName(); | ||||
| 					n = n.substring(n.lastIndexOf('.')+1); | ||||
| 					ps.print( n+": "+Integer.toHexString(o.hashCode()) ); | ||||
| 				} else { | ||||
| 					ps.print( v.toString() ); | ||||
| 				} | ||||
| 				break; | ||||
| 			default: | ||||
| 				ps.print(v.tojstring()); | ||||
| 			} | ||||
| 			if ( i+1 == top ) | ||||
| 				ps.print(']'); | ||||
| 			ps.print( " | " ); | ||||
| 		} | ||||
| 		ps.print(varargs); | ||||
| 		ps.println(); | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
|  | ||||
| } | ||||
| @@ -1,77 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
| /** | ||||
|  * Prototype representing compiled lua code.  | ||||
|  * <p> | ||||
|  * This is both a straight translation of the corresponding C type,  | ||||
|  * and the main data structure for execution of compiled lua bytecode.  | ||||
|  * <p> | ||||
|  * See documentatation on {@link LuaClosure} for information on how to load  | ||||
|  * and execute a {@link Prototype}. | ||||
|  * @see LuaClosure | ||||
|  */ | ||||
|  | ||||
| public class Prototype { | ||||
| 	/* constants used by the function */ | ||||
| 	public LuaValue[] k;  | ||||
| 	public int[] code; | ||||
| 	/* functions defined inside the function */ | ||||
| 	public Prototype[] p; | ||||
| 	/* map from opcodes to source lines */ | ||||
| 	public int[] lineinfo; | ||||
| 	/* information about local variables */ | ||||
| 	public LocVars[] locvars; | ||||
| 	/* upvalue names */ | ||||
| 	public LuaString[] upvalues; | ||||
| 	public LuaString  source; | ||||
| 	public int nups; | ||||
| 	public int linedefined; | ||||
| 	public int lastlinedefined; | ||||
| 	public int numparams; | ||||
| 	public int is_vararg; | ||||
| 	public int maxstacksize; | ||||
|  | ||||
| 	 | ||||
| 	public String toString() { | ||||
| 		return source + ":" + linedefined+"-"+lastlinedefined; | ||||
| 	} | ||||
| 	 | ||||
| 	/** Get the name of a local variable. | ||||
| 	 *  | ||||
| 	 * @param number the local variable number to look up | ||||
| 	 * @param pc the program counter | ||||
| 	 * @return the name, or null if not found | ||||
| 	 */ | ||||
| 	public LuaString getlocalname(int number, int pc) { | ||||
| 	  int i; | ||||
| 	  for (i = 0; i<locvars.length && locvars[i].startpc <= pc; i++) { | ||||
| 	    if (pc < locvars[i].endpc) {  /* is variable active? */ | ||||
| 	    	number--; | ||||
| 	      if (number == 0) | ||||
| 	        return locvars[i].varname; | ||||
| 	    } | ||||
| 	  } | ||||
| 	  return null;  /* not found */ | ||||
| 	} | ||||
| } | ||||
| @@ -1,97 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2010-2011 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
| /** | ||||
|  * Subclass of {@link Varargs} that represents a lua tail call  | ||||
|  * in a Java library function execution environment.  | ||||
|  * <p> | ||||
|  * Since Java doesn't have direct support for tail calls,  | ||||
|  * any lua function whose {@link Prototype} contains the  | ||||
|  * {@link Lua#OP_TAILCALL} bytecode needs a mechanism  | ||||
|  * for tail calls when converting lua-bytecode to java-bytecode. | ||||
|  * <p> | ||||
|  * The tail call holds the next function and arguments,  | ||||
|  * and the client a call to {@link #eval()} executes the function | ||||
|  * repeatedly until the tail calls are completed.  | ||||
|  * <p> | ||||
|  * Normally, users of luaj need not concern themselves with the  | ||||
|  * details of this mechanism, as it is built into the core  | ||||
|  * execution framework.  | ||||
|  * @see Prototype  | ||||
|  * @see LuaJC | ||||
|  */ | ||||
| public class TailcallVarargs extends Varargs { | ||||
|  | ||||
| 	private LuaValue func; | ||||
| 	private Varargs args; | ||||
| 	private Varargs result; | ||||
| 	 | ||||
| 	public TailcallVarargs(LuaValue f, Varargs args) { | ||||
| 		this.func = f; | ||||
| 		this.args = args; | ||||
| 	} | ||||
| 	 | ||||
| 	public TailcallVarargs(LuaValue object, LuaValue methodname, Varargs args) { | ||||
| 		this.func = object.get(methodname); | ||||
| 		this.args = LuaValue.varargsOf(object, args); | ||||
| 	} | ||||
| 	 | ||||
| 	public boolean isTailcall() { | ||||
| 		return true; | ||||
| 	} | ||||
| 	 | ||||
| 	public Varargs eval() { | ||||
| 		while ( result == null ) { | ||||
| 			Varargs r = func.onInvoke(args); | ||||
| 			if (r.isTailcall()) { | ||||
| 				TailcallVarargs t = (TailcallVarargs) r; | ||||
| 				func = t.func; | ||||
| 				args = t.args; | ||||
| 			} | ||||
| 			else { | ||||
| 				result = r;			 | ||||
| 				func = null; | ||||
| 				args = null; | ||||
| 			} | ||||
| 		} | ||||
| 		return result; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue arg( int i ) { | ||||
| 		if ( result == null ) | ||||
| 			eval(); | ||||
| 		return result.arg(i); | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue arg1() { | ||||
| 		if (result == null) | ||||
| 			eval(); | ||||
| 		return result.arg1(); | ||||
| 	} | ||||
| 	 | ||||
| 	public int narg() { | ||||
| 		if (result == null) | ||||
| 			eval(); | ||||
| 		return result.narg(); | ||||
| 	} | ||||
| } | ||||
| @@ -1,77 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
|  | ||||
| /** Upvalue used with Closure formulation | ||||
|  * <p> | ||||
|  * @see LuaClosure | ||||
|  * @see Prototype | ||||
|  */ | ||||
| public final class UpValue { | ||||
|  | ||||
| 	LuaValue[] array; // initially the stack, becomes a holder  | ||||
| 	int index; | ||||
|  | ||||
| 	/** | ||||
| 	 *  Create an upvalue relative to a stack | ||||
| 	 * @param stack the stack | ||||
| 	 * @param index the index on the stack for the upvalue | ||||
| 	 */ | ||||
| 	public UpValue( LuaValue[] stack, int index) { | ||||
| 		this.array = stack; | ||||
| 		this.index = index; | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Convert this upvalue to a Java String | ||||
| 	 * @return the Java String for this upvalue. | ||||
| 	 * @see LuaValue#tojstring() | ||||
| 	 */ | ||||
| 	public String tojstring() { | ||||
| 		return array[index].tojstring(); | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Get the value of the upvalue | ||||
| 	 * @return the {@link LuaValue} for this upvalue | ||||
| 	 */ | ||||
| 	public final LuaValue getValue() { | ||||
| 		return array[index]; | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Set the value of the upvalue | ||||
| 	 * @param the {@link LuaValue} to set it to | ||||
| 	 */ | ||||
| 	public final void setValue( LuaValue value ) { | ||||
| 		array[index] = value; | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Close this upvalue so it is no longer on the stack | ||||
| 	 */ | ||||
| 	public final void close() { | ||||
| 		array = new LuaValue[] { array[index] }; | ||||
| 		index = 0; | ||||
| 	} | ||||
| } | ||||
| @@ -1,537 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
| /** | ||||
|  * Class to encapsulate varargs values, either as part of a variable argument list, or multiple return values. | ||||
|  * <p> | ||||
|  * To construct varargs, use one of the static methods such as  | ||||
|  * {@code LuaValue.varargsOf(LuaValue,LuaValue)} | ||||
|  * <p> | ||||
|  * <p> | ||||
|  * Any LuaValue can be used as a stand-in for Varargs, for both calls and return values.  | ||||
|  * When doing so, nargs() will return 1 and arg1() or arg(1) will return this.   | ||||
|  * This simplifies the case when calling or implementing varargs functions with only  | ||||
|  * 1 argument or 1 return value.   | ||||
|  * <p> | ||||
|  * Varargs can also be derived from other varargs by appending to the front with a call  | ||||
|  * such as  {@code LuaValue.varargsOf(LuaValue,Varargs)} | ||||
|  * or by taking a portion of the args using {@code Varargs.subargs(int start)} | ||||
|  * <p> | ||||
|  * @see LuaValue#varargsOf(LuaValue[]) | ||||
|  * @see LuaValue#varargsOf(LuaValue, Varargs) | ||||
|  * @see LuaValue#varargsOf(LuaValue[], Varargs) | ||||
|  * @see LuaValue#varargsOf(LuaValue, LuaValue, Varargs) | ||||
|  * @see LuaValue#varargsOf(LuaValue[], int, int) | ||||
|  * @see LuaValue#varargsOf(LuaValue[], int, int, Varargs) | ||||
|  * @see LuaValue#subargs(int) | ||||
|  */ | ||||
| public abstract class Varargs { | ||||
|  | ||||
| 	/** | ||||
| 	 * Get the n-th argument value (1-based). | ||||
| 	 * @param i the index of the argument to get, 1 is the first argument | ||||
| 	 * @return Value at position i, or LuaValue.NIL if there is none. | ||||
| 	 * @see Varargs#arg1() | ||||
| 	 * @see LuaValue#NIL | ||||
| 	 */ | ||||
| 	abstract public LuaValue arg( int i ); | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Get the number of arguments, or 0 if there are none.  | ||||
| 	 * @return number of arguments.  | ||||
| 	 */ | ||||
| 	abstract public int narg(); | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Get the first argument in the list.  | ||||
| 	 * @return LuaValue which is first in the list, or LuaValue.NIL if there are no values. | ||||
| 	 * @see Varargs#arg(int) | ||||
| 	 * @see LuaValue#NIL | ||||
| 	 */ | ||||
| 	abstract public LuaValue arg1(); | ||||
|  | ||||
| 	/**  | ||||
| 	 * Evaluate any pending tail call and return result. | ||||
| 	 * @return the evaluated tail call result  | ||||
| 	 */ | ||||
| 	public Varargs eval() { return this; } | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Return true if this is a TailcallVarargs | ||||
| 	 * @return true if a tail call, false otherwise | ||||
| 	 */ | ||||
| 	public boolean isTailcall() { | ||||
| 		return false; | ||||
| 	} | ||||
| 	 | ||||
| 	// ----------------------------------------------------------------------- | ||||
| 	// utilities to get specific arguments and type-check them. | ||||
| 	// ----------------------------------------------------------------------- | ||||
| 	 | ||||
| 	/** Gets the type of argument {@code i}  | ||||
| 	 * @param i the index of the argument to convert, 1 is the first argument | ||||
| 	 * @return int value corresponding to one of the LuaValue integer type values | ||||
| 	 * @see LuaValue.TNIL | ||||
| 	 * @see LuaValue.TBOOLEAN | ||||
| 	 * @see LuaValue.TNUMBER | ||||
| 	 * @see LuaValue.TSTRING | ||||
| 	 * @see LuaValue.TTABLE | ||||
| 	 * @see LuaValue.TFUNCTION | ||||
| 	 * @see LuaValue.TUSERDATA | ||||
| 	 * @see LuaValue.TTHREAD | ||||
| 	 * */ | ||||
| 	public int type(int i)             { return arg(i).type(); } | ||||
| 	 | ||||
| 	/** Tests if argument i is nil. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return true if the argument is nil or does not exist, false otherwise | ||||
| 	 * @see LuaValue.TNIL | ||||
| 	 * */ | ||||
| 	public boolean isnil(int i)        { return arg(i).isnil(); } | ||||
|  | ||||
| 	/** Tests if argument i is a function. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return true if the argument exists and is a function or closure, false otherwise | ||||
| 	 * @see LuaValue.TFUNCTION | ||||
| 	 * */ | ||||
| 	public boolean isfunction(int i)   { return arg(i).isfunction(); } | ||||
|  | ||||
| 	/** Tests if argument i is a number. | ||||
| 	 * Since anywhere a number is required, a string can be used that  | ||||
| 	 * is a number, this will return true for both numbers and  | ||||
| 	 * strings that can be interpreted as numbers.   | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return true if the argument exists and is a number or  | ||||
| 	 * string that can be interpreted as a number, false otherwise | ||||
| 	 * @see LuaValue.TNUMBER | ||||
| 	 * @see LuaValue.TSTRING | ||||
| 	 * */ | ||||
| 	public boolean isnumber(int i)     { return arg(i).isnumber(); } | ||||
|  | ||||
| 	/** Tests if argument i is a string.   | ||||
| 	 * Since all lua numbers can be used where strings are used,  | ||||
| 	 * this will return true for both strings and numbers.   | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return true if the argument exists and is a string or number, false otherwise | ||||
| 	 * @see LuaValue.TNUMBER | ||||
| 	 * @see LuaValue.TSTRING | ||||
| 	 * */ | ||||
| 	public boolean isstring(int i)     { return arg(i).isstring(); } | ||||
|  | ||||
| 	/** Tests if argument i is a table. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return true if the argument exists and is a lua table, false otherwise | ||||
| 	 * @see LuaValue.TTABLE | ||||
| 	 * */ | ||||
| 	public boolean istable(int i)      { return arg(i).istable(); } | ||||
|  | ||||
| 	/** Tests if argument i is a thread. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return true if the argument exists and is a lua thread, false otherwise | ||||
| 	 * @see LuaValue.TTHREAD | ||||
| 	 * */ | ||||
| 	public boolean isthread(int i)     { return arg(i).isthread(); } | ||||
|  | ||||
| 	/** Tests if argument i is a userdata. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return true if the argument exists and is a userdata, false otherwise | ||||
| 	 * @see LuaValue.TUSERDATA | ||||
| 	 * */ | ||||
| 	public boolean isuserdata(int i)   { return arg(i).isuserdata(); } | ||||
|  | ||||
| 	/** Tests if a value exists at argument i. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return true if the argument exists, false otherwise | ||||
| 	 * */ | ||||
| 	public boolean isvalue(int i)      { return i>0 && i<=narg(); } | ||||
| 	 | ||||
| 	/** Return argument i as a boolean value, {@code defval} if nil, or throw a LuaError if any other type. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return true if argument i is boolean true, false if it is false, or defval if not supplied or nil  | ||||
| 	 * @exception LuaError if the argument is not a lua boolean | ||||
| 	 * */ | ||||
| 	public boolean      optboolean(int i, boolean defval)          { return arg(i).optboolean(defval); } | ||||
|  | ||||
| 	/** Return argument i as a closure, {@code defval} if nil, or throw a LuaError if any other type. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return LuaClosure if argument i is a closure, or defval if not supplied or nil | ||||
| 	 * @exception LuaError if the argument is not a lua closure | ||||
| 	 * */ | ||||
| 	public LuaClosure   optclosure(int i, LuaClosure defval)       { return arg(i).optclosure(defval); } | ||||
|  | ||||
| 	/** Return argument i as a double, {@code defval} if nil, or throw a LuaError if it cannot be converted to one. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return java double value if argument i is a number or string that converts to a number, or defval if not supplied or nil | ||||
| 	 * @exception LuaError if the argument is not a number | ||||
| 	 * */ | ||||
| 	public double       optdouble(int i, double defval)            { return arg(i).optdouble(defval); } | ||||
|  | ||||
| 	/** Return argument i as a function, {@code defval} if nil, or throw a LuaError  if an incompatible type. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return LuaValue that can be called if argument i is lua function or closure, or defval if not supplied or nil | ||||
| 	 * @exception LuaError if the argument is not a lua function or closure | ||||
| 	 * */ | ||||
| 	public LuaFunction  optfunction(int i, LuaFunction defval)     { return arg(i).optfunction(defval); } | ||||
|  | ||||
| 	/** Return argument i as a java int value, discarding any fractional part, {@code defval} if nil, or throw a LuaError  if not a number. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return int value with fraction discarded and truncated if necessary if argument i is number, or defval if not supplied or nil | ||||
| 	 * @exception LuaError if the argument is not a number | ||||
| 	 * */ | ||||
| 	public int          optint(int i, int defval)                  { return arg(i).optint(defval); } | ||||
|  | ||||
| 	/** Return argument i as a java int value, {@code defval} if nil, or throw a LuaError  if not a number or is not representable by a java int. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return LuaInteger value that fits in a java int without rounding, or defval if not supplied or nil | ||||
| 	 * @exception LuaError if the argument cannot be represented by a java int value | ||||
| 	 * */ | ||||
| 	public LuaInteger   optinteger(int i, LuaInteger defval)       { return arg(i).optinteger(defval); } | ||||
|  | ||||
| 	/** Return argument i as a java long value, discarding any fractional part, {@code defval} if nil, or throw a LuaError  if not a number. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return long value with fraction discarded and truncated if necessary if argument i is number, or defval if not supplied or nil | ||||
| 	 * @exception LuaError if the argument is not a number | ||||
| 	 * */ | ||||
| 	public long         optlong(int i, long defval)                { return arg(i).optlong(defval); } | ||||
|  | ||||
| 	/** Return argument i as a LuaNumber, {@code defval} if nil, or throw a LuaError  if not a number or string that can be converted to a number. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument, or defval if not supplied or nil | ||||
| 	 * @return LuaNumber if argument i is number or can be converted to a number | ||||
| 	 * @exception LuaError if the argument is not a number | ||||
| 	 * */ | ||||
| 	public LuaNumber    optnumber(int i, LuaNumber defval)         { return arg(i).optnumber(defval); } | ||||
|  | ||||
| 	/** Return argument i as a java String if a string or number, {@code defval} if nil, or throw a LuaError  if any other type | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return String value if argument i is a string or number, or defval if not supplied or nil | ||||
| 	 * @exception LuaError if the argument is not a string or number | ||||
| 	 * */ | ||||
| 	public String       optjstring(int i, String defval)           { return arg(i).optjstring(defval); } | ||||
|  | ||||
| 	/** Return argument i as a LuaString if a string or number, {@code defval} if nil, or throw a LuaError  if any other type | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return LuaString value if argument i is a string or number, or defval if not supplied or nil | ||||
| 	 * @exception LuaError if the argument is not a string or number | ||||
| 	 * */ | ||||
| 	public LuaString    optstring(int i, LuaString defval)         { return arg(i).optstring(defval); } | ||||
|  | ||||
| 	/** Return argument i as a LuaTable if a lua table, {@code defval} if nil, or throw a LuaError  if any other type. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return LuaTable value if a table, or defval if not supplied or nil | ||||
| 	 * @exception LuaError if the argument is not a lua table | ||||
| 	 * */ | ||||
| 	public LuaTable     opttable(int i, LuaTable defval)           { return arg(i).opttable(defval); } | ||||
|  | ||||
| 	/** Return argument i as a LuaThread if a lua thread, {@code defval} if nil, or throw a LuaError  if any other type. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return LuaThread value if a thread, or defval if not supplied or nil | ||||
| 	 * @exception LuaError if the argument is not a lua thread | ||||
| 	 * */ | ||||
| 	public LuaThread    optthread(int i, LuaThread defval)         { return arg(i).optthread(defval); } | ||||
|  | ||||
| 	/** Return argument i as a java Object if a userdata, {@code defval} if nil, or throw a LuaError  if any other type. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return java Object value if argument i is a userdata, or defval if not supplied or nil | ||||
| 	 * @exception LuaError if the argument is not a userdata | ||||
| 	 * */ | ||||
| 	public Object       optuserdata(int i, Object defval)          { return arg(i).optuserdata(defval); } | ||||
|  | ||||
| 	/** Return argument i as a java Object if it is a userdata whose instance Class c or a subclass,  | ||||
| 	 * {@code defval} if nil, or throw a LuaError  if any other type. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @param c the class to which the userdata instance must be assignable | ||||
| 	 * @return java Object value if argument i is a userdata whose instance Class c or a subclass, or defval if not supplied or nil | ||||
| 	 * @exception LuaError if the argument is not a userdata or from whose instance c is not assignable | ||||
| 	 * */ | ||||
| 	public Object       optuserdata(int i, Class c, Object defval) { return arg(i).optuserdata(c,defval); } | ||||
|  | ||||
| 	/** Return argument i as a LuaValue if it exists, or {@code defval}. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return LuaValue value if the argument exists, defval if not | ||||
| 	 * @exception LuaError if the argument does not exist. | ||||
| 	 * */ | ||||
| 	public LuaValue     optvalue(int i, LuaValue defval)           { return i>0 && i<=narg()? arg(i): defval; } | ||||
|  | ||||
| 	/** Return argument i as a boolean value, or throw an error if any other type. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return true if argument i is boolean true, false if it is false | ||||
| 	 * @exception LuaError if the argument is not a lua boolean | ||||
| 	 * */ | ||||
| 	public boolean      checkboolean(int i)          { return arg(i).checkboolean(); } | ||||
|  | ||||
| 	/** Return argument i as a closure, or throw an error if any other type. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return LuaClosure if argument i is a closure. | ||||
| 	 * @exception LuaError if the argument is not a lua closure | ||||
| 	 * */ | ||||
| 	public LuaClosure   checkclosure(int i)          { return arg(i).checkclosure(); } | ||||
|  | ||||
| 	/** Return argument i as a double, or throw an error if it cannot be converted to one. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return java double value if argument i is a number or string that converts to a number | ||||
| 	 * @exception LuaError if the argument is not a number | ||||
| 	 * */ | ||||
| 	public double       checkdouble(int i)           { return arg(i).checknumber().todouble(); } | ||||
|  | ||||
| 	/** Return argument i as a function, or throw an error if an incompatible type. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return LuaValue that can be called if argument i is lua function or closure | ||||
| 	 * @exception LuaError if the argument is not a lua function or closure | ||||
| 	 * */ | ||||
| 	public LuaValue     checkfunction(int i)         { return arg(i).checkfunction(); } | ||||
|  | ||||
| 	/** Return argument i as a java int value, discarding any fractional part, or throw an error if not a number. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return int value with fraction discarded and truncated if necessary if argument i is number | ||||
| 	 * @exception LuaError if the argument is not a number | ||||
| 	 * */ | ||||
| 	public int          checkint(int i)              { return arg(i).checknumber().toint(); } | ||||
|  | ||||
| 	/** Return argument i as a java int value, or throw an error if not a number or is not representable by a java int. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return LuaInteger value that fits in a java int without rounding | ||||
| 	 * @exception LuaError if the argument cannot be represented by a java int value | ||||
| 	 * */ | ||||
| 	public LuaInteger   checkinteger(int i)          { return arg(i).checkinteger(); } | ||||
|  | ||||
| 	/** Return argument i as a java long value, discarding any fractional part, or throw an error if not a number. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return long value with fraction discarded and truncated if necessary if argument i is number | ||||
| 	 * @exception LuaError if the argument is not a number | ||||
| 	 * */ | ||||
| 	public long         checklong(int i)             { return arg(i).checknumber().tolong(); } | ||||
|  | ||||
| 	/** Return argument i as a LuaNumber, or throw an error if not a number or string that can be converted to a number. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return LuaNumber if argument i is number or can be converted to a number | ||||
| 	 * @exception LuaError if the argument is not a number | ||||
| 	 * */ | ||||
| 	public LuaNumber    checknumber(int i)           { return arg(i).checknumber(); } | ||||
|  | ||||
| 	/** Return argument i as a java String if a string or number, or throw an error if any other type | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return String value if argument i is a string or number | ||||
| 	 * @exception LuaError if the argument is not a string or number | ||||
| 	 * */ | ||||
| 	public String       checkjstring(int i)          { return arg(i).checkjstring(); } | ||||
|  | ||||
| 	/** Return argument i as a LuaString if a string or number, or throw an error if any other type | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return LuaString value if argument i is a string or number | ||||
| 	 * @exception LuaError if the argument is not a string or number | ||||
| 	 * */ | ||||
| 	public LuaString    checkstring(int i)           { return arg(i).checkstring(); } | ||||
|  | ||||
| 	/** Return argument i as a LuaTable if a lua table, or throw an error if any other type. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return LuaTable value if a table | ||||
| 	 * @exception LuaError if the argument is not a lua table | ||||
| 	 * */ | ||||
| 	public LuaTable     checktable(int i)            { return arg(i).checktable(); } | ||||
|  | ||||
| 	/** Return argument i as a LuaThread if a lua thread, or throw an error if any other type. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return LuaThread value if a thread | ||||
| 	 * @exception LuaError if the argument is not a lua thread | ||||
| 	 * */ | ||||
| 	public LuaThread    checkthread(int i)           { return arg(i).checkthread(); } | ||||
|  | ||||
| 	/** Return argument i as a java Object if a userdata, or throw an error if any other type. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return java Object value if argument i is a userdata | ||||
| 	 * @exception LuaError if the argument is not a userdata | ||||
| 	 * */ | ||||
| 	public Object       checkuserdata(int i)         { return arg(i).checkuserdata(); } | ||||
|  | ||||
| 	/** Return argument i as a java Object if it is a userdata whose instance Class c or a subclass,  | ||||
| 	 * or throw an error if any other type. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @param c the class to which the userdata instance must be assignable | ||||
| 	 * @return java Object value if argument i is a userdata whose instance Class c or a subclass | ||||
| 	 * @exception LuaError if the argument is not a userdata or from whose instance c is not assignable | ||||
| 	 * */ | ||||
| 	public Object       checkuserdata(int i,Class c) { return arg(i).checkuserdata(c); } | ||||
|  | ||||
| 	/** Return argument i as a LuaValue if it exists, or throw an error. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return LuaValue value if the argument exists | ||||
| 	 * @exception LuaError if the argument does not exist. | ||||
| 	 * */ | ||||
| 	public LuaValue     checkvalue(int i)            { return i<=narg()? arg(i): LuaValue.argerror(i,"value expected"); } | ||||
|  | ||||
| 	/** Return argument i as a LuaValue if it is not nil, or throw an error if it is nil. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return LuaValue value if the argument is not nil | ||||
| 	 * @exception LuaError if the argument doesn't exist or evaluates to nil. | ||||
| 	 * */ | ||||
| 	public LuaValue     checknotnil(int i)           { return arg(i).checknotnil(); } | ||||
| 	 | ||||
| 	/** Return argument i as a LuaValue when a user-supplied assertion passes, or throw an error. | ||||
| 	 * @param test user supplied assertion to test against | ||||
| 	 * @param i the index to report in any error message | ||||
| 	 * @param msg the error message to use when the test fails | ||||
| 	 * @return LuaValue value if the value of {@code test} is {@code true} | ||||
| 	 * @exception LuaError if the the value of {@code test} is {@code false} | ||||
| 	 * */ | ||||
| 	public void         argcheck(boolean test, int i, String msg) { if (!test) LuaValue.argerror(i,msg); } | ||||
| 	 | ||||
| 	/** Return true if there is no argument or nil at argument i. | ||||
| 	 * @param i the index of the argument to test, 1 is the first argument | ||||
| 	 * @return true if argument i contains either no argument or nil | ||||
| 	 * */ | ||||
| 	public boolean isnoneornil(int i) { | ||||
| 		return i>narg() || arg(i).isnil(); | ||||
| 	} | ||||
| 	 | ||||
| 	/** Convert argument {@code i} to java boolean based on lua rules for boolean evaluation.  | ||||
| 	 * @param i the index of the argument to convert, 1 is the first argument | ||||
| 	 * @return {@code false} if argument i is nil or false, otherwise {@code true} | ||||
| 	 * */ | ||||
| 	public boolean toboolean(int i)           { return arg(i).toboolean(); } | ||||
|  | ||||
| 	/** Return argument i as a java byte value, discarding any fractional part and truncating,  | ||||
| 	 * or 0 if not a number. | ||||
| 	 * @param i the index of the argument to convert, 1 is the first argument | ||||
| 	 * @return byte value with fraction discarded and truncated if necessary if argument i is number, otherwise 0 | ||||
| 	 * */ | ||||
| 	public byte    tobyte(int i)              { return arg(i).tobyte(); } | ||||
| 	 | ||||
| 	/** Return argument i as a java char value, discarding any fractional part and truncating,  | ||||
| 	 * or 0 if not a number. | ||||
| 	 * @param i the index of the argument to convert, 1 is the first argument | ||||
| 	 * @return char value with fraction discarded and truncated if necessary if argument i is number, otherwise 0 | ||||
| 	 * */ | ||||
| 	public char    tochar(int i)              { return arg(i).tochar(); } | ||||
|  | ||||
| 	/** Return argument i as a java double value or 0 if not a number. | ||||
| 	 * @param i the index of the argument to convert, 1 is the first argument | ||||
| 	 * @return double value if argument i is number, otherwise 0 | ||||
| 	 * */ | ||||
| 	public double  todouble(int i)            { return arg(i).todouble(); } | ||||
|  | ||||
| 	/** Return argument i as a java float value, discarding excess fractional part and truncating,  | ||||
| 	 * or 0 if not a number. | ||||
| 	 * @param i the index of the argument to convert, 1 is the first argument | ||||
| 	 * @return float value with excess fraction discarded and truncated if necessary if argument i is number, otherwise 0 | ||||
| 	 * */ | ||||
| 	public float   tofloat(int i)             { return arg(i).tofloat(); } | ||||
| 	 | ||||
| 	/** Return argument i as a java int value, discarding any fractional part and truncating,  | ||||
| 	 * or 0 if not a number. | ||||
| 	 * @param i the index of the argument to convert, 1 is the first argument | ||||
| 	 * @return int value with fraction discarded and truncated if necessary if argument i is number, otherwise 0 | ||||
| 	 * */ | ||||
| 	public int     toint(int i)               { return arg(i).toint(); } | ||||
|  | ||||
| 	/** Return argument i as a java long value, discarding any fractional part and truncating,  | ||||
| 	 * or 0 if not a number. | ||||
| 	 * @param i the index of the argument to convert, 1 is the first argument | ||||
| 	 * @return long value with fraction discarded and truncated if necessary if argument i is number, otherwise 0 | ||||
| 	 * */ | ||||
| 	public long    tolong(int i)              { return arg(i).tolong(); } | ||||
|  | ||||
| 	/** Return argument i as a java String based on the type of the argument. | ||||
| 	 * @param i the index of the argument to convert, 1 is the first argument | ||||
| 	 * @return String value representing the type | ||||
| 	 * */ | ||||
| 	public String  tojstring(int i)           { return arg(i).tojstring(); } | ||||
| 	 | ||||
| 	/** Return argument i as a java short value, discarding any fractional part and truncating,  | ||||
| 	 * or 0 if not a number. | ||||
| 	 * @param i the index of the argument to convert, 1 is the first argument | ||||
| 	 * @return short value with fraction discarded and truncated if necessary if argument i is number, otherwise 0 | ||||
| 	 * */ | ||||
| 	public short   toshort(int i)             { return arg(i).toshort(); } | ||||
|  | ||||
| 	/** Return argument i as a java Object if a userdata, or null. | ||||
| 	 * @param i the index of the argument to convert, 1 is the first argument | ||||
| 	 * @return java Object value if argument i is a userdata, otherwise null | ||||
| 	 * */ | ||||
| 	public Object  touserdata(int i)          { return arg(i).touserdata(); } | ||||
|  | ||||
| 	/** Return argument i as a java Object if it is a userdata whose instance Class c or a subclass, or null. | ||||
| 	 * @param i the index of the argument to convert, 1 is the first argument | ||||
| 	 * @param c the class to which the userdata instance must be assignable | ||||
| 	 * @return java Object value if argument i is a userdata whose instance Class c or a subclass, otherwise null | ||||
| 	 * */ | ||||
| 	public Object  touserdata(int i,Class c)  { return arg(i).touserdata(c); } | ||||
| 	 | ||||
| 	/** Convert the list of varargs values to a human readable java String.  | ||||
| 	 * @return String value in human readable form such as {1,2}.  | ||||
| 	 */ | ||||
| 	public String tojstring() { | ||||
| 		Buffer sb = new Buffer(); | ||||
| 		sb.append( "(" ); | ||||
| 		for ( int i=1,n=narg(); i<=n; i++ ) { | ||||
| 			if (i>1) sb.append( "," ); | ||||
| 			sb.append( arg(i).tojstring() ); | ||||
| 		} | ||||
| 		sb.append( ")" ); | ||||
| 		return sb.tojstring(); | ||||
| 	} | ||||
| 	 | ||||
| 	/** Convert the value or values to a java String using Varargs.tojstring()  | ||||
| 	 * @return String value in human readable form.  | ||||
| 	 * @see Varargs#tojstring() | ||||
| 	 */ | ||||
| 	public String toString() { return tojstring(); } | ||||
|  | ||||
| 	/** | ||||
| 	 * Create a {@code Varargs} instance containing arguments starting at index {@code start} | ||||
| 	 * @param start the index from which to include arguments, where 1 is the first argument. | ||||
| 	 * @return Varargs containing argument { start, start+1,  ... , narg-start-1 } | ||||
| 	 */ | ||||
| 	public Varargs subargs(final int start) { | ||||
| 		int end = narg(); | ||||
| 		switch ( end-start ) { | ||||
| 		case 0: return arg(start); | ||||
| 		case 1: return new LuaValue.PairVarargs(arg(start),arg(end)); | ||||
| 		} | ||||
| 		return end<start? (Varargs) LuaValue.NONE: new SubVarargs(this,start,end);  | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Implementation of Varargs for use in the Varargs.subargs() function. | ||||
| 	 * @see Varargs#subargs(int) | ||||
| 	 */ | ||||
| 	private static class SubVarargs extends Varargs { | ||||
| 		private final Varargs v; | ||||
| 		private final int start; | ||||
| 		private final int end; | ||||
| 		public SubVarargs(Varargs varargs, int start, int end) { | ||||
| 			this.v = varargs; | ||||
| 			this.start = start; | ||||
| 			this.end = end; | ||||
| 		} | ||||
| 		public LuaValue arg(int i) { | ||||
| 			i += start-1; | ||||
| 			return i>=start && i<=end? v.arg(i): LuaValue.NIL; | ||||
| 		} | ||||
| 		public LuaValue arg1() { | ||||
| 			return v.arg(start); | ||||
| 		} | ||||
| 		public int narg() { | ||||
| 			return end+1-start; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,349 +0,0 @@ | ||||
| /******************************************************************************* | ||||
|  * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  ******************************************************************************/ | ||||
| package org.luaj.vm2; | ||||
|  | ||||
| import java.lang.ref.WeakReference; | ||||
|  | ||||
| import org.luaj.vm2.lib.TwoArgFunction; | ||||
|  | ||||
| /** | ||||
|  * Subclass of {@link LuaTable} that provides weak key and weak value semantics.  | ||||
|  * <p>  | ||||
|  * Normally these are not created directly, but indirectly when changing the mode  | ||||
|  * of a {@link LuaTable} as lua script executes.   | ||||
|  * <p> | ||||
|  * However, calling the constructors directly when weak tables are required from  | ||||
|  * Java will reduce overhead.   | ||||
|  */ | ||||
| public class WeakTable extends LuaTable { | ||||
| 	private boolean weakkeys,weakvalues; | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Construct a table with weak keys, weak values, or both | ||||
| 	 * @param weakkeys true to let the table have weak keys | ||||
| 	 * @param weakvalues true to let the table have weak values | ||||
| 	 */ | ||||
| 	public WeakTable(boolean weakkeys, boolean weakvalues) { | ||||
| 		this(weakkeys, weakvalues, 0, 0); | ||||
| 	} | ||||
|  | ||||
| 	/**  | ||||
| 	 * Construct a table with weak keys, weak values, or both, and an initial capacity | ||||
| 	 * @param weakkeys true to let the table have weak keys | ||||
| 	 * @param weakvalues true to let the table have weak values | ||||
| 	 * @param narray capacity of array part | ||||
| 	 * @param nhash capacity of hash part | ||||
| 	 */ | ||||
| 	protected WeakTable(boolean weakkeys, boolean weakvalues, int narray, int nhash) { | ||||
| 		super(narray, nhash); | ||||
| 		this.weakkeys = weakkeys; | ||||
| 		this.weakvalues = weakvalues; | ||||
| 	} | ||||
|  | ||||
| 	/**  | ||||
| 	 * Construct a table with weak keys, weak values, or both, and a source of initial data | ||||
| 	 * @param weakkeys true to let the table have weak keys | ||||
| 	 * @param weakvalues true to let the table have weak values | ||||
| 	 * @param source {@link LuaTable} containing the initial elements | ||||
| 	 */ | ||||
| 	protected WeakTable(boolean weakkeys, boolean weakvalues, LuaTable source) { | ||||
| 		this(weakkeys, weakvalues, source.getArrayLength(), source.getHashLength()); | ||||
| 		Varargs n; | ||||
| 		LuaValue k = NIL; | ||||
| 		while ( !(k = ((n = source.next(k)).arg1())).isnil() ) | ||||
| 			rawset(k, n.arg(2)); | ||||
| 		m_metatable = source.m_metatable; | ||||
| 	} | ||||
| 	 | ||||
| 	public void presize( int narray ) { | ||||
| 		super.presize(narray); | ||||
| 	} | ||||
|  | ||||
| 	/**  | ||||
| 	 * Presize capacity of both array and hash parts. | ||||
| 	 * @param narray capacity of array part | ||||
| 	 * @param nhash capacity of hash part | ||||
| 	 */ | ||||
| 	public void presize(int narray, int nhash) { | ||||
| 		super.presize(narray, nhash); | ||||
| 	} | ||||
| 	 | ||||
| 	protected int getArrayLength() { | ||||
| 		return super.getArrayLength(); | ||||
| 	} | ||||
|  | ||||
| 	protected int getHashLength() { | ||||
| 		return super.getHashLength(); | ||||
| 	} | ||||
| 	 | ||||
| 	protected LuaTable changemode(boolean weakkeys, boolean weakvalues) { | ||||
| 		this.weakkeys = weakkeys; | ||||
| 		this.weakvalues = weakvalues; | ||||
| 		return this; | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Self-sent message to convert a value to its weak counterpart | ||||
| 	 * @param value value to convert | ||||
| 	 * @return {@link LuaValue} that is a strong or weak reference, depending on type of {@code value} | ||||
| 	 */ | ||||
| 	LuaValue weaken( LuaValue value ) { | ||||
| 		switch ( value.type() ) { | ||||
| 			case LuaValue.TFUNCTION: | ||||
| 			case LuaValue.TTHREAD: | ||||
| 			case LuaValue.TTABLE: | ||||
| 				return new WeakValue(value); | ||||
| 			case LuaValue.TUSERDATA: | ||||
| 				return new WeakUserdata(value); | ||||
| 			default: | ||||
| 				return value; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	public void rawset( int key, LuaValue value ) { | ||||
| 		if ( weakvalues ) | ||||
| 			value = weaken( value ); | ||||
| 		super.rawset(key, value); | ||||
| 	} | ||||
| 	 | ||||
| 	public void rawset( LuaValue key, LuaValue value ) { | ||||
| 		if ( weakvalues ) | ||||
| 			value = weaken( value ); | ||||
| 		if ( weakkeys ) { | ||||
| 			switch ( key.type() ) { | ||||
| 				case LuaValue.TFUNCTION: | ||||
| 				case LuaValue.TTHREAD: | ||||
| 				case LuaValue.TTABLE: | ||||
| 				case LuaValue.TUSERDATA: | ||||
| 					key = value = new WeakEntry(this, key, value); | ||||
| 					break; | ||||
| 				default: | ||||
| 					break; | ||||
| 			} | ||||
| 		} | ||||
| 		super.rawset(key, value); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	public LuaValue rawget( int key ) { | ||||
| 		return super.rawget(key).strongvalue(); | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue rawget( LuaValue key ) { | ||||
| 		return super.rawget(key).strongvalue(); | ||||
| 	} | ||||
|  | ||||
| 	/** Get the hash value for a key  | ||||
| 	 * key the key to look up  | ||||
| 	 * */ | ||||
| 	protected LuaValue hashget(LuaValue key) { | ||||
| 		if ( hashEntries > 0 ) { | ||||
| 			int i = hashFindSlot(key); | ||||
| 			if ( hashEntries == 0 ) | ||||
| 				return NIL; | ||||
| 			LuaValue v = hashValues[i]; | ||||
| 			return v!=null? v: NIL; | ||||
| 		} | ||||
| 		return NIL; | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
| 	// override to remove values for weak keys as we search | ||||
| 	public int hashFindSlot(LuaValue key) {		 | ||||
| 		int i = ( key.hashCode() & 0x7FFFFFFF ) % hashKeys.length; | ||||
| 		LuaValue k; | ||||
| 		while ( ( k = hashKeys[i] ) != null ) { | ||||
| 			if ( k.isweaknil() ) { | ||||
| 				hashClearSlot(i); | ||||
| 				if ( hashEntries == 0 ) | ||||
| 					return 0; | ||||
| 			} | ||||
| 			else { | ||||
| 				if ( k.raweq(key.strongkey()) ) | ||||
| 					return i; | ||||
| 				i = ( i + 1 ) % hashKeys.length; | ||||
| 			} | ||||
| 		} | ||||
| 		return i; | ||||
| 	} | ||||
| 	 | ||||
| 	public int maxn() { | ||||
| 		return super.maxn(); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	/** | ||||
| 	 * Get the next element after a particular key in the table  | ||||
| 	 * @return key,value or nil | ||||
| 	 */ | ||||
| 	public Varargs next( LuaValue key ) { | ||||
| 		while ( true ) { | ||||
| 			Varargs n = super.next(key); | ||||
| 			LuaValue k = n.arg1(); | ||||
| 			if ( k.isnil() ) | ||||
| 				return NIL; | ||||
| 			LuaValue ks = k.strongkey(); | ||||
| 			LuaValue vs = n.arg(2).strongvalue(); | ||||
| 			if ( ks.isnil() || vs.isnil() ) { | ||||
| 				super.rawset(k, NIL); | ||||
| 			} else { | ||||
| 				return varargsOf(ks,vs); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	// ----------------- sort support ----------------------------- | ||||
| 	public void sort(final LuaValue comparator) { | ||||
| 		super.sort( new TwoArgFunction() { | ||||
| 			public LuaValue call(LuaValue arg1, LuaValue arg2) { | ||||
| 				return comparator.call( arg1.strongvalue(), arg2.strongvalue() ); | ||||
| 			} | ||||
| 		} ); | ||||
| 	} | ||||
|  | ||||
| 	/** Internal class to implement weak values.  | ||||
| 	 * @see WeakTable | ||||
| 	 */ | ||||
| 	static class WeakValue extends LuaValue { | ||||
| 		final WeakReference ref; | ||||
|  | ||||
| 		protected WeakValue(LuaValue value) { | ||||
| 			ref = new WeakReference(value); | ||||
| 		} | ||||
|  | ||||
| 		public int type() { | ||||
| 			illegal("type","weak value"); | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		public String typename() { | ||||
| 			illegal("typename","weak value"); | ||||
| 			return null; | ||||
| 		} | ||||
| 		 | ||||
| 		public String toString() { | ||||
| 			return "weak<"+ref.get()+">"; | ||||
| 		} | ||||
| 		 | ||||
| 		public LuaValue strongvalue() { | ||||
| 			Object o = ref.get(); | ||||
| 			return o!=null? (LuaValue)o: NIL; | ||||
| 		} | ||||
| 		 | ||||
| 		public boolean raweq(LuaValue rhs) { | ||||
| 			Object o = ref.get(); | ||||
| 			return o!=null && rhs.raweq((LuaValue)o); | ||||
| 		} | ||||
| 		 | ||||
| 		public boolean isweaknil() { | ||||
| 			return ref.get() == null; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	/** Internal class to implement weak userdata values.  | ||||
| 	 * @see WeakTable | ||||
| 	 */ | ||||
| 	static final class WeakUserdata extends WeakValue { | ||||
| 		private final WeakReference ob; | ||||
| 		private final LuaValue mt; | ||||
|  | ||||
| 		private WeakUserdata(LuaValue value) { | ||||
| 			super(value); | ||||
| 			ob = new WeakReference(value.touserdata()); | ||||
| 			mt = value.getmetatable(); | ||||
| 		} | ||||
| 		 | ||||
| 		public LuaValue strongvalue() { | ||||
| 			Object u = ref.get(); | ||||
| 			if ( u != null ) | ||||
| 				return (LuaValue) u; | ||||
| 			Object o = ob.get(); | ||||
| 			return o!=null? userdataOf(o,mt): NIL; | ||||
| 		} | ||||
| 		 | ||||
| 		public boolean raweq(LuaValue rhs) { | ||||
| 			if ( ! rhs.isuserdata() ) | ||||
| 				return false; | ||||
| 			LuaValue v = (LuaValue) ref.get(); | ||||
| 			if ( v != null && v.raweq(rhs) ) | ||||
| 				return true; | ||||
| 			return rhs.touserdata() == ob.get(); | ||||
| 		} | ||||
| 		 | ||||
| 		public boolean isweaknil() { | ||||
| 			return ob.get() == null || ref.get() == null; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** Internal class to implement weak table entries.  | ||||
| 	 * @see WeakTable | ||||
| 	 */ | ||||
| 	static final class WeakEntry extends LuaValue { | ||||
| 		final LuaValue weakkey; | ||||
| 		LuaValue weakvalue; | ||||
| 		final int keyhash; | ||||
|  | ||||
| 		private WeakEntry(WeakTable table, LuaValue key, LuaValue weakvalue) { | ||||
| 			this.weakkey = table.weaken(key); | ||||
| 			this.keyhash = key.hashCode(); | ||||
| 			this.weakvalue = weakvalue; | ||||
| 		} | ||||
|  | ||||
| 		public LuaValue strongkey() { | ||||
| 			return weakkey.strongvalue(); | ||||
| 		} | ||||
|  | ||||
| 		// when looking up the value, look in the keys metatable | ||||
| 		public LuaValue strongvalue() { | ||||
| 			LuaValue key = weakkey.strongvalue(); | ||||
| 			if ( key.isnil() ) | ||||
| 				return weakvalue = NIL; | ||||
| 			return weakvalue.strongvalue(); | ||||
| 		} | ||||
|  | ||||
| 		public int type() { | ||||
| 			return TNONE; | ||||
| 		} | ||||
|  | ||||
| 		public String typename() { | ||||
| 			illegal("typename","weak entry"); | ||||
| 			return null; | ||||
| 		} | ||||
| 		 | ||||
| 		public String toString() { | ||||
| 			return "weak<"+weakkey.strongvalue()+","+strongvalue()+">"; | ||||
| 		} | ||||
| 		 | ||||
| 		public int hashCode() { | ||||
| 			return keyhash; | ||||
| 		} | ||||
| 		 | ||||
| 		public boolean raweq(LuaValue rhs) { | ||||
| 			//return rhs.raweq(weakkey.strongvalue()); | ||||
| 			return weakkey.raweq(rhs); | ||||
| 		} | ||||
| 		 | ||||
| 		public boolean isweaknil() { | ||||
| 			return weakkey.isweaknil() || weakvalue.isweaknil(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,267 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.compiler; | ||||
|  | ||||
| import java.io.DataOutputStream; | ||||
| import java.io.IOException; | ||||
| import java.io.OutputStream; | ||||
|  | ||||
| import org.luaj.vm2.LocVars; | ||||
| import org.luaj.vm2.Prototype; | ||||
| import org.luaj.vm2.LuaString; | ||||
| import org.luaj.vm2.LuaValue; | ||||
|  | ||||
|  | ||||
| public class DumpState { | ||||
|  | ||||
| 	/** mark for precompiled code (`<esc>Lua') */ | ||||
| 	public static final String LUA_SIGNATURE	= "\033Lua"; | ||||
|  | ||||
| 	/** for header of binary files -- this is Lua 5.1 */ | ||||
| 	public static final int LUAC_VERSION		= 0x51; | ||||
|  | ||||
| 	/** for header of binary files -- this is the official format */ | ||||
| 	public static final int LUAC_FORMAT		= 0; | ||||
|  | ||||
| 	/** size of header of binary files */ | ||||
| 	public static final int LUAC_HEADERSIZE		= 12; | ||||
|  | ||||
| 	/** expected lua header bytes */ | ||||
| 	private static final byte[] LUAC_HEADER_SIGNATURE = { '\033', 'L', 'u', 'a' }; | ||||
|  | ||||
| 	/** set true to allow integer compilation */ | ||||
| 	public static boolean ALLOW_INTEGER_CASTING = false; | ||||
| 	 | ||||
| 	/** format corresponding to non-number-patched lua, all numbers are floats or doubles */ | ||||
| 	public static final int NUMBER_FORMAT_FLOATS_OR_DOUBLES    = 0; | ||||
|  | ||||
| 	/** format corresponding to non-number-patched lua, all numbers are ints */ | ||||
| 	public static final int NUMBER_FORMAT_INTS_ONLY            = 1; | ||||
| 	 | ||||
| 	/** format corresponding to number-patched lua, all numbers are 32-bit (4 byte) ints */ | ||||
| 	public static final int NUMBER_FORMAT_NUM_PATCH_INT32      = 4; | ||||
| 	 | ||||
| 	/** default number format */ | ||||
| 	public static final int NUMBER_FORMAT_DEFAULT = NUMBER_FORMAT_FLOATS_OR_DOUBLES; | ||||
|  | ||||
| 	// header fields | ||||
| 	private boolean IS_LITTLE_ENDIAN = false; | ||||
| 	private int NUMBER_FORMAT = NUMBER_FORMAT_DEFAULT; | ||||
| 	private int SIZEOF_LUA_NUMBER = 8; | ||||
| 	private static final int SIZEOF_INT = 4; | ||||
| 	private static final int SIZEOF_SIZET = 4; | ||||
| 	private static final int SIZEOF_INSTRUCTION = 4; | ||||
|  | ||||
| 	DataOutputStream writer; | ||||
| 	boolean strip; | ||||
| 	int status; | ||||
|  | ||||
| 	public DumpState(OutputStream w, boolean strip) { | ||||
| 		this.writer = new DataOutputStream( w ); | ||||
| 		this.strip = strip; | ||||
| 		this.status = 0; | ||||
| 	} | ||||
|  | ||||
| 	void dumpBlock(final byte[] b, int size) throws IOException { | ||||
| 		writer.write(b, 0, size); | ||||
| 	} | ||||
|  | ||||
| 	void dumpChar(int b) throws IOException { | ||||
| 		writer.write( b ); | ||||
| 	} | ||||
|  | ||||
| 	void dumpInt(int x) throws IOException { | ||||
| 		if ( IS_LITTLE_ENDIAN ) { | ||||
| 			writer.writeByte(x&0xff); | ||||
| 			writer.writeByte((x>>8)&0xff); | ||||
| 			writer.writeByte((x>>16)&0xff); | ||||
| 			writer.writeByte((x>>24)&0xff); | ||||
| 		} else { | ||||
| 			writer.writeInt(x); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	void dumpString(LuaString s) throws IOException { | ||||
| 		final int len = s.len().toint(); | ||||
| 		dumpInt( len+1 ); | ||||
| 		s.write( writer, 0, len ); | ||||
| 		writer.write( 0 ); | ||||
| 	} | ||||
| 	 | ||||
| 	void dumpDouble(double d) throws IOException { | ||||
| 		long l = Double.doubleToLongBits(d); | ||||
| 		if ( IS_LITTLE_ENDIAN ) { | ||||
| 			dumpInt( (int) l ); | ||||
| 			dumpInt( (int) (l>>32) ); | ||||
| 		} else { | ||||
| 			writer.writeLong(l); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	void dumpCode( final Prototype f ) throws IOException { | ||||
| 		final int[] code = f.code; | ||||
| 		int n = code.length; | ||||
| 		dumpInt( n ); | ||||
| 		for ( int i=0; i<n; i++ ) | ||||
| 			dumpInt( code[i] ); | ||||
| 	} | ||||
| 	 | ||||
| 	void dumpConstants(final Prototype f) throws IOException { | ||||
| 		final LuaValue[] k = f.k; | ||||
| 		int i, n = k.length; | ||||
| 		dumpInt(n); | ||||
| 		for (i = 0; i < n; i++) { | ||||
| 			final LuaValue o = k[i]; | ||||
| 			switch ( o.type() ) { | ||||
| 			case LuaValue.TNIL: | ||||
| 				writer.write(LuaValue.TNIL); | ||||
| 				break; | ||||
| 			case LuaValue.TBOOLEAN: | ||||
| 				writer.write(LuaValue.TBOOLEAN); | ||||
| 				dumpChar(o.toboolean() ? 1 : 0); | ||||
| 				break; | ||||
| 			case LuaValue.TNUMBER: | ||||
| 				switch (NUMBER_FORMAT) { | ||||
| 				case NUMBER_FORMAT_FLOATS_OR_DOUBLES: | ||||
| 					writer.write(LuaValue.TNUMBER); | ||||
| 					dumpDouble(o.todouble()); | ||||
| 					break; | ||||
| 				case NUMBER_FORMAT_INTS_ONLY: | ||||
| 					if ( ! ALLOW_INTEGER_CASTING && ! o.isint() ) | ||||
| 						throw new java.lang.IllegalArgumentException("not an integer: "+o); | ||||
| 					writer.write(LuaValue.TNUMBER); | ||||
| 					dumpInt(o.toint()); | ||||
| 					break; | ||||
| 				case NUMBER_FORMAT_NUM_PATCH_INT32: | ||||
| 					if ( o.isint() ) { | ||||
| 						writer.write(LuaValue.TINT); | ||||
| 						dumpInt(o.toint()); | ||||
| 					} else { | ||||
| 						writer.write(LuaValue.TNUMBER); | ||||
| 						dumpDouble(o.todouble()); | ||||
| 					} | ||||
| 					break; | ||||
| 				default: | ||||
| 					throw new IllegalArgumentException("number format not supported: "+NUMBER_FORMAT); | ||||
| 				} | ||||
| 				break; | ||||
| 			case LuaValue.TSTRING: | ||||
| 				writer.write(LuaValue.TSTRING); | ||||
| 				dumpString((LuaString)o); | ||||
| 				break; | ||||
| 			default: | ||||
| 				throw new IllegalArgumentException("bad type for " + o);			 | ||||
| 			} | ||||
| 		} | ||||
| 		n = f.p.length; | ||||
| 		dumpInt(n); | ||||
| 		for (i = 0; i < n; i++) | ||||
| 			dumpFunction(f.p[i], f.source); | ||||
| 	} | ||||
| 	 | ||||
| 	void dumpDebug(final Prototype f) throws IOException { | ||||
| 		int i, n; | ||||
| 		n = (strip) ? 0 : f.lineinfo.length; | ||||
| 		dumpInt(n); | ||||
| 		for (i = 0; i < n; i++) | ||||
| 			dumpInt(f.lineinfo[i]); | ||||
| 		n = (strip) ? 0 : f.locvars.length; | ||||
| 		dumpInt(n); | ||||
| 		for (i = 0; i < n; i++) { | ||||
| 			LocVars lvi = f.locvars[i]; | ||||
| 			dumpString(lvi.varname); | ||||
| 			dumpInt(lvi.startpc); | ||||
| 			dumpInt(lvi.endpc); | ||||
| 		} | ||||
| 		n = (strip) ? 0 : f.upvalues.length; | ||||
| 		dumpInt(n); | ||||
| 		for (i = 0; i < n; i++) | ||||
| 			dumpString(f.upvalues[i]); | ||||
| 	} | ||||
| 	 | ||||
| 	void dumpFunction(final Prototype f, final LuaString string) throws IOException { | ||||
| 		if ( f.source == null || f.source.equals(string) || strip ) | ||||
| 			dumpInt(0); | ||||
| 		else | ||||
| 			dumpString(f.source); | ||||
| 		dumpInt(f.linedefined); | ||||
| 		dumpInt(f.lastlinedefined); | ||||
| 		dumpChar(f.nups); | ||||
| 		dumpChar(f.numparams); | ||||
| 		dumpChar(f.is_vararg); | ||||
| 		dumpChar(f.maxstacksize); | ||||
| 		dumpCode(f); | ||||
| 		dumpConstants(f); | ||||
| 		dumpDebug(f); | ||||
| 	} | ||||
|  | ||||
| 	void dumpHeader() throws IOException { | ||||
| 		writer.write( LUAC_HEADER_SIGNATURE ); | ||||
| 		writer.write( LUAC_VERSION ); | ||||
| 		writer.write( LUAC_FORMAT ); | ||||
| 		writer.write( IS_LITTLE_ENDIAN? 1: 0 ); | ||||
| 		writer.write( SIZEOF_INT ); | ||||
| 		writer.write( SIZEOF_SIZET ); | ||||
| 		writer.write( SIZEOF_INSTRUCTION ); | ||||
| 		writer.write( SIZEOF_LUA_NUMBER ); | ||||
| 		writer.write( NUMBER_FORMAT ); | ||||
| 	} | ||||
|  | ||||
| 	/* | ||||
| 	** dump Lua function as precompiled chunk | ||||
| 	*/ | ||||
| 	public static int dump( Prototype f, OutputStream w, boolean strip ) throws IOException { | ||||
| 		DumpState D = new DumpState(w,strip); | ||||
| 		D.dumpHeader(); | ||||
| 		D.dumpFunction(f,null); | ||||
| 		return D.status; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 *  | ||||
| 	 * @param f the function to dump | ||||
| 	 * @param w the output stream to dump to | ||||
| 	 * @param stripDebug true to strip debugging info, false otherwise | ||||
| 	 * @param numberFormat one of NUMBER_FORMAT_FLOATS_OR_DOUBLES, NUMBER_FORMAT_INTS_ONLY, NUMBER_FORMAT_NUM_PATCH_INT32 | ||||
| 	 * @param littleendian true to use little endian for numbers, false for big endian | ||||
| 	 * @return 0 if dump succeeds | ||||
| 	 * @throws IOException | ||||
| 	 * @throws IllegalArgumentException if the number format it not supported | ||||
| 	 */ | ||||
| 	public static int dump(Prototype f, OutputStream w, boolean stripDebug, int numberFormat, boolean littleendian) throws IOException { | ||||
| 		switch ( numberFormat ) { | ||||
| 		case NUMBER_FORMAT_FLOATS_OR_DOUBLES: | ||||
| 		case NUMBER_FORMAT_INTS_ONLY: | ||||
| 		case NUMBER_FORMAT_NUM_PATCH_INT32: | ||||
| 			break; | ||||
| 		default: | ||||
| 			throw new IllegalArgumentException("number format not supported: "+numberFormat); | ||||
| 		} | ||||
| 		DumpState D = new DumpState(w,stripDebug); | ||||
| 		D.IS_LITTLE_ENDIAN = littleendian; | ||||
| 		D.NUMBER_FORMAT = numberFormat; | ||||
| 		D.SIZEOF_LUA_NUMBER = (numberFormat==NUMBER_FORMAT_INTS_ONLY? 4: 8); | ||||
| 		D.dumpHeader(); | ||||
| 		D.dumpFunction(f,null); | ||||
| 		return D.status; | ||||
| 	} | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,37 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.compiler; | ||||
|  | ||||
| class InstructionPtr { | ||||
| 	final int[] code; | ||||
| 	final int idx; | ||||
| 	InstructionPtr(int[] code, int idx ) { | ||||
| 		this.code = code; | ||||
| 		this.idx = idx; | ||||
| 	} | ||||
| 	int get() { | ||||
| 		return code[idx]; | ||||
| 	} | ||||
| 	void set(int value) { | ||||
| 		code[idx] = value; | ||||
| 	} | ||||
| } | ||||
| @@ -1,31 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.compiler; | ||||
|  | ||||
| public class IntPtr { | ||||
| 	int i; | ||||
| 	IntPtr() { | ||||
| 	} | ||||
| 	IntPtr(int value) { | ||||
| 		this.i = value; | ||||
| 	} | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,251 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.compiler; | ||||
|  | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.util.Hashtable; | ||||
|  | ||||
| import org.luaj.vm2.LoadState; | ||||
| import org.luaj.vm2.LocVars; | ||||
| import org.luaj.vm2.Lua; | ||||
| import org.luaj.vm2.LuaClosure; | ||||
| import org.luaj.vm2.LuaError; | ||||
| import org.luaj.vm2.LuaFunction; | ||||
| import org.luaj.vm2.LuaString; | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.Prototype; | ||||
| import org.luaj.vm2.LoadState.LuaCompiler; | ||||
|  | ||||
| /** | ||||
|  * Compiler for Lua. | ||||
|  * <p> | ||||
|  * Compiles lua source files into lua bytecode within a {@link Prototype},  | ||||
|  * loads lua binary files directly into a{@link Prototype},  | ||||
|  * and optionaly instantiates a {@link LuaClosure} around the result  | ||||
|  * using a user-supplied environment.   | ||||
|  * <p> | ||||
|  * Implements the {@link LuaCompiler} interface for loading  | ||||
|  * initialized chunks, which is an interface common to  | ||||
|  * lua bytecode compiling and java bytecode compiling.  | ||||
|  * <p>  | ||||
|  * Teh {@link LuaC} compiler is installed by default by both the  | ||||
|  * {@link JsePlatform} and {@link JmePlatform} classes,  | ||||
|  * so in the following example, the default {@link LuaC} compiler  | ||||
|  * will be used: | ||||
|  * <pre> {@code | ||||
|  * LuaValue _G = JsePlatform.standardGlobals(); | ||||
|  * LoadState.load( new ByteArrayInputStream("print 'hello'".getBytes()), "main.lua", _G ).call(); | ||||
|  * } </pre> | ||||
|  * @see LuaCompiler | ||||
|  * @see LuaJC | ||||
|  * @see JsePlatform | ||||
|  * @see JmePlatform | ||||
|  * @see BaseLib | ||||
|  * @see LuaValue | ||||
|  * @see LuaCompiler | ||||
|  * @see Prototype | ||||
|  */ | ||||
| public class LuaC extends Lua implements LuaCompiler { | ||||
|  | ||||
| 	public static final LuaC instance = new LuaC(); | ||||
| 	 | ||||
| 	/** Install the compiler so that LoadState will first  | ||||
| 	 * try to use it when handed bytes that are  | ||||
| 	 * not already a compiled lua chunk. | ||||
| 	 */ | ||||
| 	public static void install() { | ||||
| 		org.luaj.vm2.LoadState.compiler = instance; | ||||
| 	} | ||||
|  | ||||
| 	protected static void _assert(boolean b) {		 | ||||
| 		if (!b) | ||||
| 			throw new LuaError("compiler assert failed"); | ||||
| 	} | ||||
| 	 | ||||
| 	public static final int MAXSTACK = 250; | ||||
| 	static final int LUAI_MAXUPVALUES = 60; | ||||
| 	static final int LUAI_MAXVARS = 200; | ||||
| 	static final int NO_REG		 = MAXARG_A; | ||||
| 	 | ||||
|  | ||||
| 	/* OpMode - basic instruction format */ | ||||
| 	static final int  | ||||
| 		iABC = 0, | ||||
| 		iABx = 1, | ||||
| 		iAsBx = 2; | ||||
|  | ||||
| 	/* OpArgMask */ | ||||
| 	static final int  | ||||
| 	  OpArgN = 0,  /* argument is not used */ | ||||
| 	  OpArgU = 1,  /* argument is used */ | ||||
| 	  OpArgR = 2,  /* argument is a register or a jump offset */ | ||||
| 	  OpArgK = 3;   /* argument is a constant or register/constant */ | ||||
|  | ||||
|  | ||||
| 	static void SET_OPCODE(InstructionPtr i,int o) { | ||||
| 		i.set( ( i.get() & (MASK_NOT_OP)) | ((o << POS_OP) & MASK_OP) ); | ||||
| 	} | ||||
| 	 | ||||
| 	static void SETARG_A(InstructionPtr i,int u) { | ||||
| 		i.set( ( i.get() & (MASK_NOT_A)) | ((u << POS_A) & MASK_A) ); | ||||
| 	} | ||||
|  | ||||
| 	static void SETARG_B(InstructionPtr i,int u) { | ||||
| 		i.set( ( i.get() & (MASK_NOT_B)) | ((u << POS_B) & MASK_B) ); | ||||
| 	} | ||||
|  | ||||
| 	static void SETARG_C(InstructionPtr i,int u) { | ||||
| 		i.set( ( i.get() & (MASK_NOT_C)) | ((u << POS_C) & MASK_C) ); | ||||
| 	} | ||||
| 	 | ||||
| 	static void SETARG_Bx(InstructionPtr i,int u) { | ||||
| 		i.set( ( i.get() & (MASK_NOT_Bx)) | ((u << POS_Bx) & MASK_Bx) ); | ||||
| 	} | ||||
| 	 | ||||
| 	static void SETARG_sBx(InstructionPtr i,int u) { | ||||
| 		SETARG_Bx( i, u + MAXARG_sBx ); | ||||
| 	} | ||||
|  | ||||
| 	static int CREATE_ABC(int o, int a, int b, int c) { | ||||
| 		return ((o << POS_OP) & MASK_OP) | | ||||
| 				((a << POS_A) & MASK_A) | | ||||
| 				((b << POS_B) & MASK_B) | | ||||
| 				((c << POS_C) & MASK_C) ; | ||||
| 	} | ||||
| 	 | ||||
| 	static int CREATE_ABx(int o, int a, int bc) { | ||||
| 		return ((o << POS_OP) & MASK_OP) | | ||||
| 				((a << POS_A) & MASK_A) | | ||||
| 				((bc << POS_Bx) & MASK_Bx) ; | ||||
|  	} | ||||
|  | ||||
| 	// vector reallocation | ||||
| 	 | ||||
| 	static LuaValue[] realloc(LuaValue[] v, int n) { | ||||
| 		LuaValue[] a = new LuaValue[n]; | ||||
| 		if ( v != null ) | ||||
| 			System.arraycopy(v, 0, a, 0, Math.min(v.length,n)); | ||||
| 		return a; | ||||
| 	} | ||||
|  | ||||
| 	static Prototype[] realloc(Prototype[] v, int n) { | ||||
| 		Prototype[] a = new Prototype[n]; | ||||
| 		if ( v != null ) | ||||
| 			System.arraycopy(v, 0, a, 0, Math.min(v.length,n)); | ||||
| 		return a; | ||||
| 	} | ||||
|  | ||||
| 	static LuaString[] realloc(LuaString[] v, int n) { | ||||
| 		LuaString[] a = new LuaString[n]; | ||||
| 		if ( v != null ) | ||||
| 			System.arraycopy(v, 0, a, 0, Math.min(v.length,n)); | ||||
| 		return a; | ||||
| 	} | ||||
|  | ||||
| 	static LocVars[] realloc(LocVars[] v, int n) { | ||||
| 		LocVars[] a = new LocVars[n]; | ||||
| 		if ( v != null ) | ||||
| 			System.arraycopy(v, 0, a, 0, Math.min(v.length,n)); | ||||
| 		return a; | ||||
| 	} | ||||
|  | ||||
| 	static int[] realloc(int[] v, int n) { | ||||
| 		int[] a = new int[n]; | ||||
| 		if ( v != null ) | ||||
| 			System.arraycopy(v, 0, a, 0, Math.min(v.length,n)); | ||||
| 		return a; | ||||
| 	} | ||||
|  | ||||
| 	static byte[] realloc(byte[] v, int n) { | ||||
| 		byte[] a = new byte[n]; | ||||
| 		if ( v != null ) | ||||
| 			System.arraycopy(v, 0, a, 0, Math.min(v.length,n)); | ||||
| 		return a; | ||||
| 	} | ||||
|  | ||||
| 	public int nCcalls; | ||||
| 	Hashtable strings; | ||||
|  | ||||
| 	protected LuaC() {} | ||||
| 	 | ||||
| 	private LuaC(Hashtable strings) { | ||||
| 		 this.strings = strings; | ||||
| 	} | ||||
| 	 | ||||
| 	/** Load into a Closure or LuaFunction, with the supplied initial environment */ | ||||
| 	public LuaFunction load(InputStream stream, String name, LuaValue env) throws IOException { | ||||
| 		Prototype p = compile( stream, name ); | ||||
| 		return new LuaClosure( p, env ); | ||||
| 	} | ||||
|  | ||||
| 	/** Compile a prototype or load as a binary chunk */ | ||||
| 	public static Prototype compile(InputStream stream, String name) throws IOException { | ||||
| 		int firstByte = stream.read(); | ||||
| 		return ( firstByte == '\033' )? | ||||
| 			LoadState.loadBinaryChunk(firstByte, stream, name): | ||||
| 			(new LuaC(new Hashtable())).luaY_parser(firstByte, stream, name); | ||||
| 	} | ||||
|  | ||||
| 	/** Parse the input */ | ||||
| 	private Prototype luaY_parser(int firstByte, InputStream z, String name) { | ||||
| 		LexState lexstate = new LexState(this, z); | ||||
| 		FuncState funcstate = new FuncState(); | ||||
| 		// lexstate.buff = buff; | ||||
| 		lexstate.setinput( this, firstByte, z, (LuaString) LuaValue.valueOf(name) ); | ||||
| 		lexstate.open_func(funcstate); | ||||
| 		/* main func. is always vararg */ | ||||
| 		funcstate.f.is_vararg = LuaC.VARARG_ISVARARG; | ||||
| 		funcstate.f.source = (LuaString) LuaValue.valueOf(name); | ||||
| 		lexstate.next(); /* read first token */ | ||||
| 		lexstate.chunk(); | ||||
| 		lexstate.check(LexState.TK_EOS); | ||||
| 		lexstate.close_func(); | ||||
| 		LuaC._assert (funcstate.prev == null); | ||||
| 		LuaC._assert (funcstate.f.nups == 0); | ||||
| 		LuaC._assert (lexstate.fs == null); | ||||
| 		return funcstate.f; | ||||
| 	} | ||||
|  | ||||
| 	// look up and keep at most one copy of each string | ||||
| 	public LuaString newTString(byte[] bytes, int offset, int len) { | ||||
| 		LuaString tmp = LuaString.valueOf(bytes, offset, len); | ||||
| 		LuaString v = (LuaString) strings.get(tmp); | ||||
| 		if ( v == null ) { | ||||
| 			// must copy bytes, since bytes could be from reusable buffer | ||||
| 			byte[] copy = new byte[len]; | ||||
| 			System.arraycopy(bytes, offset, copy, 0, len); | ||||
| 			v = LuaString.valueOf(copy); | ||||
| 			strings.put(v, v); | ||||
| 		} | ||||
| 		return v; | ||||
| 	} | ||||
|  | ||||
| 	public String pushfstring(String string) { | ||||
| 		return string; | ||||
| 	} | ||||
|  | ||||
| 	public LuaFunction load(Prototype p, String filename, LuaValue env) { | ||||
| 		return new LuaClosure( p, env ); | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -1,430 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.lib; | ||||
|  | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.io.PrintStream; | ||||
|  | ||||
| import org.luaj.vm2.LoadState; | ||||
| import org.luaj.vm2.Lua; | ||||
| import org.luaj.vm2.LuaError; | ||||
| import org.luaj.vm2.LuaString; | ||||
| import org.luaj.vm2.LuaTable; | ||||
| import org.luaj.vm2.LuaThread; | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.Varargs; | ||||
|  | ||||
| /**  | ||||
|  * Subclass of {@link LibFunction} which implements the lua basic library functions.  | ||||
|  * <p> | ||||
|  * This contains all library functions listed as "basic functions" in the lua documentation for JME.  | ||||
|  * The functions dofile and loadfile use the  | ||||
|  * {@link #FINDER} instance to find resource files. | ||||
|  * Since JME has no file system by default, {@link BaseLib} implements  | ||||
|  * {@link ResourceFinder} using {@link Class#getResource(String)},  | ||||
|  * which is the closest equivalent on JME.      | ||||
|  * The default loader chain in {@link PackageLib} will use these as well. | ||||
|  * <p>   | ||||
|  * To use basic library functions that include a {@link ResourceFinder} based on  | ||||
|  * directory lookup, use {@link JseBaseLib} instead.  | ||||
|  * <p> | ||||
|  * Typically, this library is included as part of a call to either  | ||||
|  * {@link JmePlatform#standardGlobals()} | ||||
|  * <p> | ||||
|  * To instantiate and use it directly,  | ||||
|  * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: | ||||
|  * <pre> {@code | ||||
|  * LuaTable _G = new LuaTable(); | ||||
|  * LuaThread.setGlobals(_G); | ||||
|  * _G.load(new BaseLib()); | ||||
|  * _G.get("print").call(LuaValue.valueOf("hello, world")); | ||||
|  * } </pre> | ||||
|  * Doing so will ensure the library is properly initialized  | ||||
|  * and loaded into the globals table.  | ||||
|  * <p> | ||||
|  * This is a direct port of the corresponding library in C. | ||||
|  * @see JseBaseLib | ||||
|  * @see ResourceFinder | ||||
|  * @see #FINDER | ||||
|  * @see LibFunction | ||||
|  * @see JsePlatform | ||||
|  * @see JmePlatform | ||||
|  * @see <a href="http://www.lua.org/manual/5.1/manual.html#5.1">http://www.lua.org/manual/5.1/manual.html#5.1</a> | ||||
|  */ | ||||
| public class BaseLib extends OneArgFunction implements ResourceFinder { | ||||
| 	 | ||||
| 	public static BaseLib instance; | ||||
| 	 | ||||
| 	public InputStream STDIN  = null; | ||||
| 	public PrintStream STDOUT = System.out; | ||||
| 	public PrintStream STDERR = System.err; | ||||
|  | ||||
| 	/**  | ||||
| 	 * Singleton file opener for this Java ClassLoader realm. | ||||
| 	 *  | ||||
| 	 * Unless set or changed elsewhere, will be set by the BaseLib that is created. | ||||
| 	 */ | ||||
| 	public static ResourceFinder FINDER; | ||||
| 	 | ||||
| 	private LuaValue next; | ||||
| 	private LuaValue inext; | ||||
| 	 | ||||
| 	private static final String[] LIB2_KEYS = { | ||||
| 		"collectgarbage", // ( opt [,arg] ) -> value | ||||
| 		"error", // ( message [,level] ) -> ERR | ||||
| 		"setfenv", // (f, table) -> void | ||||
| 	}; | ||||
| 	private static final String[] LIBV_KEYS = { | ||||
| 		"assert", // ( v [,message] ) -> v, message | ERR | ||||
| 		"dofile", // ( filename ) -> result1, ... | ||||
| 		"getfenv", // ( [f] ) -> env | ||||
| 		"getmetatable", // ( object ) -> table  | ||||
| 		"load", // ( func [,chunkname] ) -> chunk | nil, msg | ||||
| 		"loadfile", // ( [filename] ) -> chunk | nil, msg | ||||
| 		"loadstring", // ( string [,chunkname] ) -> chunk | nil, msg | ||||
| 		"pcall", // (f, arg1, ...) -> status, result1, ... | ||||
| 		"xpcall", // (f, err) -> result1, ... | ||||
| 		"print", // (...) -> void | ||||
| 		"select", // (f, ...) -> value1, ... | ||||
| 		"unpack", // (list [,i [,j]]) -> result1, ... | ||||
| 		"type",  // (v) -> value | ||||
| 		"rawequal", // (v1, v2) -> boolean | ||||
| 		"rawget", // (table, index) -> value | ||||
| 		"rawset", // (table, index, value) -> table | ||||
| 		"setmetatable", // (table, metatable) -> table | ||||
| 		"tostring", // (e) -> value | ||||
| 		"tonumber", // (e [,base]) -> value | ||||
| 		"pairs", // "pairs" (t) -> iter-func, t, nil | ||||
| 		"ipairs", // "ipairs", // (t) -> iter-func, t, 0 | ||||
| 		"next", // "next"  ( table, [index] ) -> next-index, next-value | ||||
| 		"__inext", // "inext" ( table, [int-index] ) -> next-index, next-value | ||||
| 	}; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Construct a base libarary instance. | ||||
| 	 */ | ||||
| 	public BaseLib() { | ||||
| 		instance = this; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue call(LuaValue arg) { | ||||
| 		env.set( "_G", env ); | ||||
| 		env.set( "_VERSION", Lua._VERSION ); | ||||
| 		bind( env, BaseLib2.class, LIB2_KEYS ); | ||||
| 		bind( env, BaseLibV.class, LIBV_KEYS );  | ||||
| 		 | ||||
| 		// remember next, and inext for use in pairs and ipairs | ||||
| 		next = env.get("next"); | ||||
| 		inext = env.get("__inext"); | ||||
| 		 | ||||
| 		// inject base lib int vararg instances | ||||
| 		for ( int i=0; i<LIBV_KEYS.length; i++ )  | ||||
| 			((BaseLibV) env.get(LIBV_KEYS[i])).baselib = this; | ||||
| 		 | ||||
| 		// set the default resource finder if not set already | ||||
| 		if ( FINDER == null ) | ||||
| 			FINDER = this; | ||||
| 		return env; | ||||
| 	} | ||||
|  | ||||
| 	/** ResourceFinder implementation  | ||||
| 	 *  | ||||
| 	 * Tries to open the file as a resource, which can work for .  | ||||
| 	 */ | ||||
| 	public InputStream findResource(String filename) { | ||||
| 		Class c = getClass(); | ||||
| 		return c.getResourceAsStream(filename.startsWith("/")? filename: "/"+filename); | ||||
| 	} | ||||
|  | ||||
| 	static final class BaseLib2 extends TwoArgFunction { | ||||
| 		public LuaValue call(LuaValue arg1, LuaValue arg2) { | ||||
| 			switch ( opcode ) { | ||||
| 			case 0: // "collectgarbage", // ( opt [,arg] ) -> value | ||||
| 				String s = arg1.checkjstring(); | ||||
| 				int result = 0; | ||||
| 				if ( "collect".equals(s) ) { | ||||
| 					System.gc(); | ||||
| 					return ZERO; | ||||
| 				} else if ( "count".equals(s) ) { | ||||
| 					Runtime rt = Runtime.getRuntime(); | ||||
| 					long used = rt.totalMemory() - rt.freeMemory(); | ||||
| 					return valueOf(used/1024.); | ||||
| 				} else if ( "step".equals(s) ) { | ||||
| 					System.gc(); | ||||
| 					return LuaValue.TRUE; | ||||
| 				} else { | ||||
| 					this.argerror(1, "gc op"); | ||||
| 				} | ||||
| 				return NIL; | ||||
| 			case 1: // "error", // ( message [,level] ) -> ERR | ||||
| 				throw new LuaError( arg1.isnil()? null: arg1.tojstring(), arg2.optint(1) ); | ||||
| 			case 2: { // "setfenv", // (f, table) -> void | ||||
| 				LuaTable t = arg2.checktable(); | ||||
| 				LuaValue f = getfenvobj(arg1); | ||||
| 				if ( ! f.isthread() && ! f.isclosure()  ) | ||||
| 					error("'setfenv' cannot change environment of given object"); | ||||
| 			    f.setfenv(t); | ||||
| 			    return f.isthread()? NONE: f; | ||||
| 			} | ||||
| 			} | ||||
| 			return NIL; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	private static LuaValue getfenvobj(LuaValue arg) { | ||||
| 		if ( arg.isfunction() ) | ||||
| 			return arg; | ||||
| 		int level = arg.optint(1); | ||||
| 	    arg.argcheck(level>=0, 1, "level must be non-negative"); | ||||
| 		if ( level == 0 ) | ||||
| 			return LuaThread.getRunning(); | ||||
| 		LuaValue f = LuaThread.getCallstackFunction(level); | ||||
| 	    arg.argcheck(f != null, 1, "invalid level"); | ||||
| 	    return f; | ||||
| 	} | ||||
|  | ||||
| 	static final class BaseLibV extends VarArgFunction { | ||||
| 		public BaseLib baselib; | ||||
| 		public Varargs invoke(Varargs args) { | ||||
| 			switch ( opcode ) { | ||||
| 			case 0: // "assert", // ( v [,message] ) -> v, message | ERR | ||||
| 				if ( !args.arg1().toboolean() )  | ||||
| 					error( args.narg()>1? args.optjstring(2,"assertion failed!"): "assertion failed!" ); | ||||
| 				return args; | ||||
| 			case 1: // "dofile", // ( filename ) -> result1, ... | ||||
| 			{ | ||||
| 				Varargs v = args.isnil(1)?  | ||||
| 						BaseLib.loadStream( baselib.STDIN, "=stdin" ): | ||||
| 						BaseLib.loadFile( args.checkjstring(1) ); | ||||
| 				return v.isnil(1)? error(v.tojstring(2)): v.arg1().invoke(); | ||||
| 			} | ||||
| 			case 2: // "getfenv", // ( [f] ) -> env | ||||
| 			{ | ||||
| 				LuaValue f = getfenvobj(args.arg1()); | ||||
| 			    LuaValue e = f.getfenv(); | ||||
| 				return e!=null? e: NIL; | ||||
| 			} | ||||
| 			case 3: // "getmetatable", // ( object ) -> table | ||||
| 			{ | ||||
| 				LuaValue mt = args.checkvalue(1).getmetatable(); | ||||
| 				return mt!=null? mt.rawget(METATABLE).optvalue(mt): NIL; | ||||
| 			} | ||||
| 			case 4: // "load", // ( func [,chunkname] ) -> chunk | nil, msg | ||||
| 			{ | ||||
| 				LuaValue func = args.checkfunction(1); | ||||
| 				String chunkname = args.optjstring(2, "function"); | ||||
| 				return BaseLib.loadStream(new StringInputStream(func), chunkname); | ||||
| 			} | ||||
| 			case 5: // "loadfile", // ( [filename] ) -> chunk | nil, msg | ||||
| 			{ | ||||
| 				return args.isnil(1)?  | ||||
| 					BaseLib.loadStream( baselib.STDIN, "stdin" ): | ||||
| 					BaseLib.loadFile( args.checkjstring(1) ); | ||||
| 			} | ||||
| 			case 6: // "loadstring", // ( string [,chunkname] ) -> chunk | nil, msg | ||||
| 			{ | ||||
| 				LuaString script = args.checkstring(1); | ||||
| 				String chunkname = args.optjstring(2, "string"); | ||||
| 				return BaseLib.loadStream(script.toInputStream(),chunkname); | ||||
| 			} | ||||
| 			case 7: // "pcall", // (f, arg1, ...) -> status, result1, ... | ||||
| 			{ | ||||
| 				LuaValue func = args.checkvalue(1); | ||||
| 				LuaThread.CallStack cs = LuaThread.onCall(this); | ||||
| 				try { | ||||
| 					return pcall(func,args.subargs(2),null); | ||||
| 				} finally { | ||||
| 					cs.onReturn(); | ||||
| 				} | ||||
| 			} | ||||
| 			case 8: // "xpcall", // (f, err) -> result1, ...				 | ||||
| 			{ | ||||
| 				LuaThread.CallStack cs = LuaThread.onCall(this); | ||||
| 				try { | ||||
| 					return pcall(args.arg1(),NONE,args.checkvalue(2)); | ||||
| 				} finally { | ||||
| 					cs.onReturn(); | ||||
| 				} | ||||
| 			} | ||||
| 			case 9: // "print", // (...) -> void | ||||
| 			{ | ||||
| 				LuaValue tostring = LuaThread.getGlobals().get("tostring");  | ||||
| 				for ( int i=1, n=args.narg(); i<=n; i++ ) { | ||||
| 					if ( i>1 ) baselib.STDOUT.write( '\t' ); | ||||
| 					LuaString s = tostring.call( args.arg(i) ).strvalue(); | ||||
| 					int z = s.indexOf((byte)0, 0); | ||||
| 					baselib.STDOUT.write( s.m_bytes, s.m_offset, z>=0? z: s.m_length ); | ||||
| 				} | ||||
| 				baselib.STDOUT.println(); | ||||
| 				return NONE; | ||||
| 			} | ||||
| 			case 10: // "select", // (f, ...) -> value1, ... | ||||
| 			{ | ||||
| 				int n = args.narg()-1; 				 | ||||
| 				if ( args.arg1().equals(valueOf("#")) ) | ||||
| 					return valueOf(n); | ||||
| 				int i = args.checkint(1); | ||||
| 				if ( i == 0 || i < -n ) | ||||
| 					argerror(1,"index out of range"); | ||||
| 				return args.subargs(i<0? n+i+2: i+1); | ||||
| 			} | ||||
| 			case 11: // "unpack", // (list [,i [,j]]) -> result1, ... | ||||
| 			{ | ||||
| 				int na = args.narg(); | ||||
| 				LuaTable t = args.checktable(1); | ||||
| 				int n = t.length(); | ||||
| 				int i = na>=2? args.checkint(2): 1; | ||||
| 				int j = na>=3? args.checkint(3): n; | ||||
| 				n = j-i+1; | ||||
| 				if ( n<0 ) return NONE; | ||||
| 				if ( n==1 ) return t.get(i); | ||||
| 				if ( n==2 ) return varargsOf(t.get(i),t.get(j)); | ||||
| 				LuaValue[] v = new LuaValue[n]; | ||||
| 				for ( int k=0; k<n; k++ ) | ||||
| 					v[k] = t.get(i+k); | ||||
| 				return varargsOf(v); | ||||
| 			} | ||||
| 			case 12: // "type",  // (v) -> value | ||||
| 				return valueOf(args.checkvalue(1).typename()); | ||||
| 			case 13: // "rawequal", // (v1, v2) -> boolean | ||||
| 				return valueOf(args.checkvalue(1) == args.checkvalue(2)); | ||||
| 			case 14: // "rawget", // (table, index) -> value | ||||
| 				return args.checktable(1).rawget(args.checkvalue(2)); | ||||
| 			case 15: { // "rawset", // (table, index, value) -> table | ||||
| 				LuaTable t = args.checktable(1); | ||||
| 				t.rawset(args.checknotnil(2), args.checkvalue(3)); | ||||
| 				return t; | ||||
| 			} | ||||
| 			case 16: { // "setmetatable", // (table, metatable) -> table | ||||
| 				final LuaValue t = args.arg1(); | ||||
| 				final LuaValue mt0 = t.getmetatable(); | ||||
| 				if ( mt0!=null && !mt0.rawget(METATABLE).isnil() ) | ||||
| 					error("cannot change a protected metatable"); | ||||
| 				final LuaValue mt = args.checkvalue(2); | ||||
| 				return t.setmetatable(mt.isnil()? null: mt.checktable()); | ||||
| 			} | ||||
| 			case 17: { // "tostring", // (e) -> value | ||||
| 				LuaValue arg = args.checkvalue(1); | ||||
| 				LuaValue h = arg.metatag(TOSTRING); | ||||
| 				if ( ! h.isnil() )  | ||||
| 					return h.call(arg); | ||||
| 				LuaValue v = arg.tostring(); | ||||
| 				if ( ! v.isnil() )  | ||||
| 					return v; | ||||
| 				return valueOf(arg.tojstring()); | ||||
| 			} | ||||
| 			case 18: { // "tonumber", // (e [,base]) -> value | ||||
| 				LuaValue arg1 = args.checkvalue(1); | ||||
| 				final int base = args.optint(2,10); | ||||
| 				if (base == 10) {  /* standard conversion */ | ||||
| 					return arg1.tonumber(); | ||||
| 				} else { | ||||
| 					if ( base < 2 || base > 36 ) | ||||
| 						argerror(2, "base out of range"); | ||||
| 					return arg1.checkstring().tonumber(base); | ||||
| 				} | ||||
| 			} | ||||
| 			case 19: // "pairs" (t) -> iter-func, t, nil | ||||
| 				return varargsOf( baselib.next, args.checktable(1), NIL ); | ||||
| 			case 20: // "ipairs", // (t) -> iter-func, t, 0 | ||||
| 				return varargsOf( baselib.inext, args.checktable(1), ZERO ); | ||||
| 			case 21: // "next"  ( table, [index] ) -> next-index, next-value | ||||
| 				return args.checktable(1).next(args.arg(2)); | ||||
| 			case 22: // "inext" ( table, [int-index] ) -> next-index, next-value | ||||
| 				return args.checktable(1).inext(args.arg(2)); | ||||
| 			} | ||||
| 			return NONE; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public static Varargs pcall(LuaValue func, Varargs args, LuaValue errfunc) { | ||||
| 		LuaValue olderr = LuaThread.setErrorFunc(errfunc); | ||||
| 		try { | ||||
| 			Varargs result =  varargsOf(LuaValue.TRUE, func.invoke(args)); | ||||
| 			LuaThread.setErrorFunc(olderr); | ||||
| 			return result; | ||||
| 		} catch ( LuaError le ) { | ||||
| 			LuaThread.setErrorFunc(olderr); | ||||
| 			String m = le.getMessage(); | ||||
| 			return varargsOf(FALSE, m!=null? valueOf(m): NIL); | ||||
| 		} catch ( Exception e ) { | ||||
| 			LuaThread.setErrorFunc(olderr); | ||||
| 			String m = e.getMessage(); | ||||
| 			return varargsOf(FALSE, valueOf(m!=null? m: e.toString())); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Load from a named file, returning the chunk or nil,error of can't load | ||||
| 	 * @return Varargs containing chunk, or NIL,error-text on error | ||||
| 	 */ | ||||
| 	public static Varargs loadFile(String filename) { | ||||
| 		InputStream is = FINDER.findResource(filename); | ||||
| 		if ( is == null ) | ||||
| 			return varargsOf(NIL, valueOf("cannot open "+filename+": No such file or directory")); | ||||
| 		try { | ||||
| 			return loadStream(is, "@"+filename); | ||||
| 		} finally { | ||||
| 			try { | ||||
| 				is.close(); | ||||
| 			} catch ( Exception e ) { | ||||
| 				e.printStackTrace(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public static Varargs loadStream(InputStream is, String chunkname) { | ||||
| 		try { | ||||
| 			if ( is == null ) | ||||
| 				return varargsOf(NIL, valueOf("not found: "+chunkname)); | ||||
| 			return LoadState.load(is, chunkname, LuaThread.getGlobals()); | ||||
| 		} catch (Exception e) { | ||||
| 			return varargsOf(NIL, valueOf(e.getMessage())); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	 | ||||
| 	private static class StringInputStream extends InputStream { | ||||
| 		final LuaValue func; | ||||
| 		byte[] bytes;  | ||||
| 		int offset, remaining = 0; | ||||
| 		StringInputStream(LuaValue func) { | ||||
| 			this.func = func; | ||||
| 		} | ||||
| 		public int read() throws IOException { | ||||
| 			if ( remaining <= 0 ) { | ||||
| 				LuaValue s = func.call(); | ||||
| 				if ( s.isnil() ) | ||||
| 					return -1; | ||||
| 				LuaString ls = s.strvalue(); | ||||
| 				bytes = ls.m_bytes; | ||||
| 				offset = ls.m_offset; | ||||
| 				remaining = ls.m_length; | ||||
| 				if (remaining <= 0) | ||||
| 					return -1; | ||||
| 			} | ||||
| 			--remaining; | ||||
| 			return bytes[offset++]; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,181 +0,0 @@ | ||||
| /******************************************************************************* | ||||
|  * Copyright (c) 2012 Luaj.org. All rights reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  ******************************************************************************/ | ||||
| package org.luaj.vm2.lib; | ||||
|  | ||||
| import org.luaj.vm2.LuaInteger; | ||||
| import org.luaj.vm2.LuaTable; | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.Varargs; | ||||
|  | ||||
| /** | ||||
|  * Subclass of LibFunction that implements the Lua standard {@code bit32} library. | ||||
|  */ | ||||
| public class Bit32Lib extends ZeroArgFunction | ||||
| { | ||||
|     public LuaValue call( ) | ||||
|     { | ||||
|         LuaTable t = new LuaTable(); | ||||
|         bind( t, Bit32LibV.class, new String[] { | ||||
|             "band", "bnot", "bor", "btest", "bxor", "extract", "replace" | ||||
|         } ); | ||||
|         bind( t, Bit32Lib2.class, new String[] { | ||||
|             "arshift", "lrotate", "lshift", "rrotate", "rshift" | ||||
|         } ); | ||||
|         env.set( "bit32", t ); | ||||
|         return t; | ||||
|     } | ||||
|  | ||||
|     public static final class Bit32LibV extends VarArgFunction | ||||
|     { | ||||
|         public Varargs invoke( Varargs args ) | ||||
|         { | ||||
|             switch( opcode ) | ||||
|             { | ||||
|                 case 0: // band | ||||
|                 { | ||||
|                     int result = -1; | ||||
|                     for( int i = 1; i <= args.narg(); i++ ) | ||||
|                     { | ||||
|                         result &= args.checkint( i ); | ||||
|                     } | ||||
|                     return bitsToValue( result ); | ||||
|                 } | ||||
|                 case 1: // bnot | ||||
|                     return bitsToValue( ~args.checkint( 1 ) ); | ||||
|                 case 2: // bot | ||||
|                 { | ||||
|                     int result = 0; | ||||
|                     for( int i = 1; i <= args.narg(); i++ ) | ||||
|                     { | ||||
|                         result |= args.checkint( i ); | ||||
|                     } | ||||
|                     return bitsToValue( result ); | ||||
|                 } | ||||
|                 case 3: // btest | ||||
|                 { | ||||
|                     int bits = -1; | ||||
|                     for( int i = 1; i <= args.narg(); i++ ) | ||||
|                     { | ||||
|                         bits &= args.checkint( i ); | ||||
|                     } | ||||
|                     return valueOf( bits != 0 ); | ||||
|                 } | ||||
|                 case 4: // bxor | ||||
|                 { | ||||
|                     int result = 0; | ||||
|                     for( int i = 1; i <= args.narg(); i++ ) | ||||
|                     { | ||||
|                         result ^= args.checkint( i ); | ||||
|                     } | ||||
|                     return bitsToValue( result ); | ||||
|                 } | ||||
|                 case 5: // extract | ||||
|                 { | ||||
|                     int field = args.checkint( 2 ); | ||||
|                     int width = args.optint( 3, 1 ); | ||||
|  | ||||
|                     if( field < 0 ) argerror( 2, "field cannot be negative" ); | ||||
|                     if( width <= 0 ) argerror( 3, "width must be postive" ); | ||||
|                     if( field + width > 32 ) error( "trying to access non-existent bits" ); | ||||
|  | ||||
|                     return bitsToValue( (args.checkint( 1 ) >>> field) & (-1 >>> (32 - width)) ); | ||||
|                 } | ||||
|                 case 6: // replace | ||||
|                 { | ||||
|                     int n = args.checkint( 1 ); | ||||
|                     int v = args.checkint( 2 ); | ||||
|                     int field = args.checkint( 3 ); | ||||
|                     int width = args.optint( 4, 1 ); | ||||
|  | ||||
|                     if( field < 0 ) argerror( 3, "field cannot be negative" ); | ||||
|                     if( width <= 0 ) argerror( 4, "width must be postive" ); | ||||
|                     if( field + width > 32 ) error( "trying to access non-existent bits" ); | ||||
|  | ||||
|                     int mask = (-1 >>> (32 - width)) << field; | ||||
|                     n = (n & ~mask) | ((v << field) & mask); | ||||
|                     return bitsToValue( n ); | ||||
|                 } | ||||
|             } | ||||
|             return NIL; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static final class Bit32Lib2 extends TwoArgFunction | ||||
|     { | ||||
|         public LuaValue call( LuaValue arg1, LuaValue arg2 ) | ||||
|         { | ||||
|             switch( opcode ) | ||||
|             { | ||||
|                 case 0: // arshift | ||||
|                 { | ||||
|                     int x = arg1.checkint(); | ||||
|                     int disp = arg2.checkint(); | ||||
|                     return disp >= 0 ? bitsToValue( x >> disp ) : bitsToValue( x << -disp ); | ||||
|                 } | ||||
|                 case 1: // lrotate | ||||
|                     return rotate( arg1.checkint(), arg2.checkint() ); | ||||
|                 case 2: // lshift | ||||
|                     return shift( arg1.checkint(), arg2.checkint() ); | ||||
|                 case 3: // rrotate | ||||
|                     return rotate( arg1.checkint(), -arg2.checkint() ); | ||||
|                 case 4: // rshift | ||||
|                     return shift( arg1.checkint(), -arg2.checkint() ); | ||||
|             } | ||||
|             return NIL; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static LuaValue rotate( int x, int disp ) | ||||
|     { | ||||
|         if( disp < 0 ) | ||||
|         { | ||||
|             disp = -disp & 31; | ||||
|             return bitsToValue( (x >>> disp) | (x << (32 - disp)) ); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             disp = disp & 31; | ||||
|             return bitsToValue( (x << disp) | (x >>> (32 - disp)) ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static LuaValue shift( int x, int disp ) | ||||
|     { | ||||
|         if( disp >= 32 || disp <= -32 ) | ||||
|         { | ||||
|             return ZERO; | ||||
|         } | ||||
|         else if( disp >= 0 ) | ||||
|         { | ||||
|             return bitsToValue( x << disp ); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return bitsToValue( x >>> -disp ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private static LuaValue bitsToValue( int x ) | ||||
|     { | ||||
|         return x < 0 ? LuaValue.valueOf( (long) x & 0xFFFFFFFFL ) : LuaInteger.valueOf( x ); | ||||
|     } | ||||
| } | ||||
| @@ -1,134 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2007-2011 LuaJ. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.lib; | ||||
|  | ||||
| import org.luaj.vm2.LuaTable; | ||||
| import org.luaj.vm2.LuaThread; | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.Varargs; | ||||
|  | ||||
| /**  | ||||
|  * Subclass of {@link LibFunction} which implements the lua standard {@code coroutine}  | ||||
|  * library.  | ||||
|  * <p>  | ||||
|  * The coroutine library in luaj has the same behavior as the | ||||
|  * coroutine library in C, but is implemented using Java Threads to maintain  | ||||
|  * the call state between invocations.  Therefore it can be yielded from anywhere,  | ||||
|  * similar to the "Coco" yield-from-anywhere patch available for C-based lua. | ||||
|  * However, coroutines that are yielded but never resumed to complete their execution | ||||
|  * may not be collected by the garbage collector.  | ||||
|  * <p>  | ||||
|  * Typically, this library is included as part of a call to either  | ||||
|  * {@link JsePlatform#standardGlobals()} or {@link JmePlatform#standardGlobals()} | ||||
|  * <p> | ||||
|  * To instantiate and use it directly,  | ||||
|  * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: | ||||
|  * <pre> {@code | ||||
|  * LuaTable _G = new LuaTable(); | ||||
|  * _G.load(new CoroutineLib()); | ||||
|  * } </pre> | ||||
|  * Doing so will ensure the library is properly initialized  | ||||
|  * and loaded into the globals table.  | ||||
|  * <p> | ||||
|  * @see LibFunction | ||||
|  * @see JsePlatform | ||||
|  * @see JmePlatform | ||||
|  * @see <a href="http://www.lua.org/manual/5.1/manual.html#5.2">http://www.lua.org/manual/5.1/manual.html#5.2</a> | ||||
|  */ | ||||
| public class CoroutineLib extends VarArgFunction { | ||||
| 	 | ||||
| 	private static final int INIT    = 0; | ||||
| 	private static final int CREATE  = 1; | ||||
| 	private static final int RESUME  = 2; | ||||
| 	private static final int RUNNING = 3; | ||||
| 	private static final int STATUS  = 4; | ||||
| 	private static final int YIELD   = 5; | ||||
| 	private static final int WRAP    = 6; | ||||
| 	private static final int WRAPPED = 7; | ||||
| 	 | ||||
| 	public CoroutineLib() { | ||||
| 	} | ||||
|  | ||||
| 	private LuaTable init() { | ||||
| 		LuaTable t = new LuaTable(); | ||||
| 		bind(t, CoroutineLib.class, new  String[] { | ||||
| 			"create", "resume", "running", "status", "yield", "wrap" }, | ||||
| 			CREATE); | ||||
| 		env.set("coroutine", t); | ||||
| 		PackageLib.instance.LOADED.set("coroutine", t); | ||||
| 		return t; | ||||
| 	} | ||||
| 	 | ||||
| 	public Varargs invoke(Varargs args) { | ||||
| 		switch ( opcode ) { | ||||
| 			case INIT: { | ||||
| 				return init(); | ||||
| 			} | ||||
| 			case CREATE: { | ||||
| 				final LuaValue func = args.checkfunction(1); | ||||
|                 /* DAN200 START */ | ||||
| 				//return new LuaThread(func, LuaThread.getGlobals() ); | ||||
|                 final LuaThread thread = new LuaThread( func, LuaThread.getGlobals() ); | ||||
|                 LuaThread.getRunning().addChild( thread ); | ||||
|                 return thread; | ||||
|                 /* DAN200 END */ | ||||
| 			} | ||||
| 			case RESUME: { | ||||
| 				final LuaThread t = args.checkthread(1); | ||||
| 				return t.resume( args.subargs(2) ); | ||||
| 			} | ||||
| 			case RUNNING: { | ||||
| 				final LuaThread r = LuaThread.getRunning(); | ||||
| 				return LuaThread.isMainThread(r)? NIL: r; | ||||
| 			} | ||||
| 			case STATUS: { | ||||
| 				return valueOf( args.checkthread(1).getStatus() ); | ||||
| 			} | ||||
| 			case YIELD: { | ||||
| 				return LuaThread.yield( args ); | ||||
| 			} | ||||
| 			case WRAP: { | ||||
| 				final LuaValue func = args.checkfunction(1); | ||||
| 				final LuaThread thread = new LuaThread(func, func.getfenv()); | ||||
|                 /* DAN200 START */ | ||||
|                 LuaThread.getRunning().addChild( thread ); | ||||
|                 /* DAN200 END */ | ||||
| 				CoroutineLib cl = new CoroutineLib(); | ||||
| 				cl.setfenv(thread); | ||||
| 				cl.name = "wrapped"; | ||||
| 				cl.opcode = WRAPPED; | ||||
| 				return cl; | ||||
| 			} | ||||
| 			case WRAPPED: { | ||||
| 				final LuaThread t = (LuaThread) env; | ||||
| 				final Varargs result = t.resume( args ); | ||||
| 				if ( result.arg1().toboolean() ) { | ||||
| 					return result.subargs(2); | ||||
| 				} else { | ||||
| 					error( result.arg(2).tojstring() ); | ||||
| 				} | ||||
| 			} | ||||
| 			default: | ||||
| 				return NONE; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,977 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.lib; | ||||
|  | ||||
| import java.lang.ref.WeakReference; | ||||
|  | ||||
| import org.luaj.vm2.Lua; | ||||
| import org.luaj.vm2.LuaBoolean; | ||||
| import org.luaj.vm2.LuaClosure; | ||||
| import org.luaj.vm2.LuaError; | ||||
| import org.luaj.vm2.LuaFunction; | ||||
| import org.luaj.vm2.LuaNil; | ||||
| import org.luaj.vm2.LuaNumber; | ||||
| import org.luaj.vm2.LuaString; | ||||
| import org.luaj.vm2.LuaTable; | ||||
| import org.luaj.vm2.LuaThread; | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.Print; | ||||
| import org.luaj.vm2.Prototype; | ||||
| import org.luaj.vm2.Varargs; | ||||
|  | ||||
| /**  | ||||
|  * Subclass of {@link LibFunction} which implements the lua standard {@code debug}  | ||||
|  * library.  | ||||
|  * <p>  | ||||
|  * The debug library in luaj tries to emulate the behavior of the corresponding C-based lua library. | ||||
|  * To do this, it must maintain a separate stack of calls to {@link LuaClosure} and {@link LibFunction}  | ||||
|  * instances.   | ||||
|  * Especially when lua-to-java bytecode compiling is being used | ||||
|  * via a {@link LuaCompiler} such as {@link LuaJC},  | ||||
|  * this cannot be done in all cases.   | ||||
|  * <p>  | ||||
|  * Typically, this library is included as part of a call to either  | ||||
|  * {@link JsePlatform#debugGlobals()} or {@link JmePlatform#debugGlobals()} | ||||
|  * <p> | ||||
|  * To instantiate and use it directly,  | ||||
|  * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: | ||||
|  * <pre> {@code | ||||
|  * LuaTable _G = new LuaTable(); | ||||
|  * _G.load(new DebugLib()); | ||||
|  * } </pre> | ||||
|  * Doing so will ensure the library is properly initialized  | ||||
|  * and loaded into the globals table.  | ||||
|  * <p> | ||||
|  * @see LibFunction | ||||
|  * @see JsePlatform | ||||
|  * @see JmePlatform | ||||
|  * @see <a href="http://www.lua.org/manual/5.1/manual.html#5.9">http://www.lua.org/manual/5.1/manual.html#5.9</a> | ||||
|  */ | ||||
| public class DebugLib extends VarArgFunction { | ||||
| 	public static final boolean CALLS = (null != System.getProperty("CALLS")); | ||||
| 	public static final boolean TRACE = (null != System.getProperty("TRACE")); | ||||
|  | ||||
| 	// leave this unset to allow obfuscators to  | ||||
| 	// remove it in production builds | ||||
| 	public static boolean DEBUG_ENABLED; | ||||
|  | ||||
| 	static final String[] NAMES = { | ||||
| 		"debug", | ||||
| 		"getfenv", | ||||
| 		"gethook", | ||||
| 		"getinfo", | ||||
| 		"getlocal", | ||||
| 		"getmetatable", | ||||
| 		"getregistry", | ||||
| 		"getupvalue", | ||||
| 		"setfenv", | ||||
| 		"sethook", | ||||
| 		"setlocal", | ||||
| 		"setmetatable", | ||||
| 		"setupvalue", | ||||
| 		"traceback", | ||||
| 	}; | ||||
| 	 | ||||
| 	private static final int INIT        	= 0; | ||||
| 	private static final int DEBUG        	= 1; | ||||
| 	private static final int GETFENV        = 2; | ||||
| 	private static final int GETHOOK        = 3; | ||||
| 	private static final int GETINFO        = 4; | ||||
| 	private static final int GETLOCAL       = 5; | ||||
| 	private static final int GETMETATABLE 	= 6; | ||||
| 	private static final int GETREGISTRY    = 7; | ||||
| 	private static final int GETUPVALUE    	= 8; | ||||
| 	private static final int SETFENV        = 9; | ||||
| 	private static final int SETHOOK        = 10; | ||||
| 	private static final int SETLOCAL 		= 11; | ||||
| 	private static final int SETMETATABLE   = 12; | ||||
| 	private static final int SETUPVALUE    	= 13; | ||||
| 	private static final int TRACEBACK    	= 14; | ||||
|  | ||||
| 	/* maximum stack for a Lua function */ | ||||
| 	private static final int MAXSTACK = 250; | ||||
| 	 | ||||
| 	private static final LuaString LUA        = valueOf("Lua");   | ||||
| 	private static final LuaString JAVA       = valueOf("Java");   | ||||
| 	private static final LuaString QMARK      = valueOf("?");   | ||||
| 	private static final LuaString GLOBAL     = valueOf("global");   | ||||
| 	private static final LuaString LOCAL      = valueOf("local");   | ||||
| 	private static final LuaString METHOD     = valueOf("method");   | ||||
| 	private static final LuaString UPVALUE    = valueOf("upvalue");   | ||||
| 	private static final LuaString FIELD      = valueOf("field"); | ||||
| 	private static final LuaString CALL       = valueOf("call");   | ||||
| 	private static final LuaString LINE       = valueOf("line");   | ||||
| 	private static final LuaString COUNT      = valueOf("count");   | ||||
| 	private static final LuaString RETURN     = valueOf("return");   | ||||
| 	private static final LuaString TAILRETURN = valueOf("tail return"); | ||||
| 	 | ||||
| 	private static final LuaString FUNC            = valueOf("func");   | ||||
| 	private static final LuaString NUPS            = valueOf("nups");   | ||||
| 	private static final LuaString NAME            = valueOf("name");   | ||||
| 	private static final LuaString NAMEWHAT        = valueOf("namewhat");   | ||||
| 	private static final LuaString WHAT            = valueOf("what");   | ||||
| 	private static final LuaString SOURCE          = valueOf("source");   | ||||
| 	private static final LuaString SHORT_SRC       = valueOf("short_src");   | ||||
| 	private static final LuaString LINEDEFINED     = valueOf("linedefined");   | ||||
| 	private static final LuaString LASTLINEDEFINED = valueOf("lastlinedefined");   | ||||
| 	private static final LuaString CURRENTLINE     = valueOf("currentline");   | ||||
| 	private static final LuaString ACTIVELINES     = valueOf("activelines");   | ||||
|  | ||||
| 	public DebugLib() { | ||||
| 	} | ||||
| 	 | ||||
| 	private LuaTable init() { | ||||
| 		DEBUG_ENABLED = true; | ||||
| 		LuaTable t = new LuaTable(); | ||||
| 		bind(t, DebugLib.class, NAMES, DEBUG); | ||||
| 		env.set("debug", t); | ||||
| 		PackageLib.instance.LOADED.set("debug", t); | ||||
| 		return t; | ||||
| 	} | ||||
| 	 | ||||
| 	public Varargs invoke(Varargs args) { | ||||
| 		switch ( opcode ) { | ||||
| 		case INIT:         return init(); | ||||
| 		case DEBUG:        return _debug(args); | ||||
| 		case GETFENV:      return _getfenv(args); | ||||
| 		case GETHOOK:      return _gethook(args); | ||||
| 		case GETINFO:      return _getinfo(args,this); | ||||
| 		case GETLOCAL:     return _getlocal(args); | ||||
| 		case GETMETATABLE: return _getmetatable(args); | ||||
| 		case GETREGISTRY:  return _getregistry(args); | ||||
| 		case GETUPVALUE:   return _getupvalue(args); | ||||
| 		case SETFENV:      return _setfenv(args); | ||||
| 		case SETHOOK:      return _sethook(args); | ||||
| 		case SETLOCAL:     return _setlocal(args); | ||||
| 		case SETMETATABLE: return _setmetatable(args); | ||||
| 		case SETUPVALUE:   return _setupvalue(args); | ||||
| 		case TRACEBACK:    return _traceback(args); | ||||
| 		default:           return NONE; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// ------------------------ Debug Info management -------------------------- | ||||
| 	//  | ||||
| 	// when DEBUG_ENABLED is set to true, these functions will be called  | ||||
| 	// by Closure instances as they process bytecodes. | ||||
| 	// | ||||
| 	// Each thread will get a DebugState attached to it by the debug library | ||||
| 	// which will track function calls, hook functions, etc. | ||||
| 	//  | ||||
| 	static class DebugInfo { | ||||
| 		LuaValue func; | ||||
| 		LuaClosure closure; | ||||
| 		LuaValue[] stack; | ||||
| 		Varargs varargs, extras; | ||||
| 		int pc, top; | ||||
| 		 | ||||
| 		private DebugInfo() {			 | ||||
| 			func = NIL; | ||||
| 		} | ||||
| 		private DebugInfo(LuaValue func) { | ||||
| 			pc = -1; | ||||
| 			setfunction( func ); | ||||
| 		} | ||||
| 		void setargs(Varargs varargs, LuaValue[] stack) { | ||||
| 			this.varargs = varargs; | ||||
| 			this.stack = stack; | ||||
| 		} | ||||
| 		void setfunction( LuaValue func ) { | ||||
| 			this.func = func; | ||||
| 			this.closure = (func instanceof LuaClosure? (LuaClosure) func: null); | ||||
| 		} | ||||
| 		void clear() { | ||||
| 			func = NIL; | ||||
| 			closure = null; | ||||
| 			stack = null; | ||||
| 			varargs = extras = null; | ||||
| 			pc = top = 0; | ||||
| 		} | ||||
| 		public void bytecode(int pc, Varargs extras, int top) { | ||||
| 			this.pc = pc; | ||||
| 			this.top = top; | ||||
| 			this.extras = extras; | ||||
| 		} | ||||
| 		public int currentline() { | ||||
| 			if ( closure == null ) return -1; | ||||
| 			int[] li = closure.p.lineinfo; | ||||
| 			return li==null || pc<0 || pc>=li.length? -1: li[pc];  | ||||
| 		} | ||||
| 		public LuaString[] getfunckind() { | ||||
| 			if ( closure == null || pc<0 ) return null; | ||||
| 			int stackpos = (closure.p.code[pc] >> 6) & 0xff;  | ||||
| 			return getobjname(this, stackpos); | ||||
| 		} | ||||
| 		public String sourceline() { | ||||
| 			if ( closure == null ) return func.tojstring(); | ||||
| 			String s = closure.p.source.tojstring(); | ||||
| 			int line = currentline(); | ||||
| 			return (s.startsWith("@")||s.startsWith("=")? s.substring(1): s) + ":" + line; | ||||
| 		} | ||||
| 		public String tracename() { | ||||
| 			// if ( func != null ) | ||||
| 			// 	return func.tojstring(); | ||||
| 			LuaString[] kind = getfunckind(); | ||||
| 			if ( kind == null ) | ||||
| 				return "function ?"; | ||||
| 			return "function "+kind[0].tojstring(); | ||||
| 		} | ||||
| 		public LuaString getlocalname(int index) { | ||||
| 			if ( closure == null ) return null; | ||||
| 			return closure.p.getlocalname(index, pc); | ||||
| 		} | ||||
| 		public String tojstring() { | ||||
| 			return tracename()+" "+sourceline(); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	/** DebugState is associated with a Thread */ | ||||
| 	static class DebugState { | ||||
| 		private final WeakReference thread_ref; | ||||
| 		private int debugCalls = 0; | ||||
| 		private DebugInfo[] debugInfo = new DebugInfo[LuaThread.MAX_CALLSTACK+1]; | ||||
| 		private LuaValue hookfunc; | ||||
| 		private boolean hookcall,hookline,hookrtrn,inhook; | ||||
| 		private int hookcount,hookcodes; | ||||
| 		private int line; | ||||
| 		DebugState(LuaThread thread) { | ||||
| 			this.thread_ref = new WeakReference(thread); | ||||
| 		} | ||||
| 		public DebugInfo nextInfo() { | ||||
| 			DebugInfo di = debugInfo[debugCalls]; | ||||
| 			if ( di == null )  | ||||
| 				debugInfo[debugCalls] = di = new DebugInfo(); | ||||
| 			return di; | ||||
| 		} | ||||
| 		public DebugInfo pushInfo( int calls ) { | ||||
| 			while ( debugCalls < calls ) { | ||||
| 				nextInfo(); | ||||
| 				++debugCalls; | ||||
| 			} | ||||
| 			return debugInfo[debugCalls-1]; | ||||
| 		} | ||||
| 		public void popInfo(int calls) { | ||||
| 			while ( debugCalls > calls ) | ||||
| 				debugInfo[--debugCalls].clear(); | ||||
| 		} | ||||
| 		void callHookFunc(DebugState ds, LuaString type, LuaValue arg) { | ||||
| 			if ( inhook || hookfunc == null ) | ||||
| 				return; | ||||
| 			inhook = true; | ||||
| 			try { | ||||
| 				int n = debugCalls; | ||||
| 				ds.nextInfo().setargs( arg, null ); | ||||
| 				ds.pushInfo(n+1).setfunction(hookfunc); | ||||
| 				try { | ||||
| 					hookfunc.call(type,arg); | ||||
| 				} finally { | ||||
| 					ds.popInfo(n); | ||||
| 				} | ||||
| 			} catch ( Exception e ) { | ||||
| 				e.printStackTrace(); | ||||
| 			} finally { | ||||
| 				inhook = false; | ||||
| 			} | ||||
| 		} | ||||
| 		public void sethook(LuaValue func, boolean call, boolean line, boolean rtrn, int count) { | ||||
| 			this.hookcount = count; | ||||
| 			this.hookcall = call; | ||||
| 			this.hookline = line; | ||||
| 			this.hookrtrn = rtrn; | ||||
| 			this.hookfunc = func; | ||||
| 		} | ||||
| 		DebugInfo getDebugInfo() { | ||||
| 			try { | ||||
| 				return debugInfo[debugCalls-1]; | ||||
| 			} catch ( Exception e ) { | ||||
| 				if ( debugCalls <= 0 ) | ||||
| 					return debugInfo[debugCalls++] = new DebugInfo(); | ||||
| 				return null; | ||||
| 			} | ||||
| 		} | ||||
| 		DebugInfo getDebugInfo(int level) { | ||||
| 			return level < 0 || level >= debugCalls? null: debugInfo[debugCalls-level-1]; | ||||
| 		} | ||||
| 		public DebugInfo findDebugInfo(LuaValue func) {			 | ||||
| 			for ( int i=debugCalls; --i>=0; ) { | ||||
| 				if ( debugInfo[i].func == func ) { | ||||
| 					return debugInfo[i]; | ||||
| 				} | ||||
| 			} | ||||
| 			return new DebugInfo(func); | ||||
| 		} | ||||
| 		public String tojstring() { | ||||
| 			LuaThread thread = (LuaThread) thread_ref.get(); | ||||
| 			return thread != null? DebugLib.traceback(thread, 0): "orphaned thread"; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	static DebugState getDebugState( LuaThread thread ) { | ||||
| 		if ( thread.debugState == null ) | ||||
| 			thread.debugState = new DebugState(thread); | ||||
| 		return (DebugState) thread.debugState; | ||||
| 	} | ||||
| 	 | ||||
| 	static DebugState getDebugState() { | ||||
| 		return getDebugState( LuaThread.getRunning() ); | ||||
| 	} | ||||
| 	 | ||||
| 	/** Called by Closures to set up stack and arguments to next call */ | ||||
| 	public static void debugSetupCall(Varargs args, LuaValue[] stack) { | ||||
| 		DebugState ds = getDebugState(); | ||||
| 		if ( ds.inhook ) | ||||
| 			return; | ||||
| 		ds.nextInfo().setargs( args, stack ); | ||||
| 	} | ||||
| 	 | ||||
| 	/** Called by Closures and recursing java functions on entry | ||||
| 	 * @param thread the thread for the call  | ||||
| 	 * @param calls the number of calls in the call stack | ||||
| 	 * @param func the function called | ||||
| 	 */ | ||||
| 	public static void debugOnCall(LuaThread thread, int calls, LuaFunction func) { | ||||
| 		DebugState ds = getDebugState(); | ||||
| 		if ( ds.inhook ) | ||||
| 			return; | ||||
| 		DebugInfo di = ds.pushInfo(calls); | ||||
| 		di.setfunction( func ); | ||||
| 		if(CALLS)System.out.println("calling "+func);		 | ||||
| 		if ( ds.hookcall ) | ||||
| 			ds.callHookFunc( ds, CALL, LuaValue.NIL ); | ||||
| 	} | ||||
| 	 | ||||
| 	/** Called by Closures and recursing java functions on return  | ||||
| 	 * @param thread the thread for the call  | ||||
| 	 * @param calls the number of calls in the call stack | ||||
| 	 */ | ||||
| 	public static void debugOnReturn(LuaThread thread, int calls) { | ||||
| 		DebugState ds = getDebugState(thread); | ||||
| 		if ( ds.inhook ) | ||||
| 			return; | ||||
| 		if(CALLS)System.out.println("returning");		 | ||||
| 		try { | ||||
| 			if ( ds.hookrtrn ) | ||||
| 				ds.callHookFunc( ds, RETURN, LuaValue.NIL ); | ||||
| 		} finally { | ||||
| 			getDebugState().popInfo(calls); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	/** Called by Closures on bytecode execution */ | ||||
| 	public static void debugBytecode( int pc, Varargs extras, int top ) { | ||||
| 		DebugState ds = getDebugState(); | ||||
| 		if ( ds.inhook ) | ||||
| 			return; | ||||
| 		DebugInfo di = ds.getDebugInfo(); | ||||
| 		if(TRACE)Print.printState(di.closure, pc, di.stack, top, di.varargs);		 | ||||
| 		di.bytecode( pc, extras, top ); | ||||
| 		if ( ds.hookcount > 0 ) { | ||||
| 			if ( ++ds.hookcodes >= ds.hookcount ) { | ||||
| 				ds.hookcodes = 0; | ||||
| 				ds.callHookFunc( ds, COUNT, LuaValue.NIL ); | ||||
| 			} | ||||
| 		} | ||||
| 		if ( ds.hookline ) { | ||||
| 			int newline = di.currentline(); | ||||
| 			if ( newline != ds.line ) { | ||||
| 				int c = di.closure.p.code[pc]; | ||||
| 				if ( (c&0x3f) != Lua.OP_JMP || ((c>>>14)-0x1ffff) >= 0 ) { | ||||
| 					ds.line = newline; | ||||
| 					ds.callHookFunc( ds, LINE, LuaValue.valueOf(newline) ); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// ------------------- library function implementations ----------------- | ||||
| 	 | ||||
| 	// j2se subclass may wish to override and provide actual console here.  | ||||
| 	// j2me platform has not System.in to provide console. | ||||
| 	static Varargs _debug(Varargs args) { | ||||
| 		return NONE; | ||||
| 	} | ||||
| 	 | ||||
| 	static Varargs _gethook(Varargs args) { | ||||
| 		int a=1; | ||||
| 		LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning();  | ||||
| 		DebugState ds = getDebugState(thread); | ||||
| 		return varargsOf( | ||||
| 				ds.hookfunc, | ||||
| 				valueOf((ds.hookcall?"c":"")+(ds.hookline?"l":"")+(ds.hookrtrn?"r":"")), | ||||
| 				valueOf(ds.hookcount)); | ||||
| 	} | ||||
|  | ||||
| 	static Varargs _sethook(Varargs args) { | ||||
| 		int a=1; | ||||
| 		LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning();  | ||||
| 		LuaValue func    = args.optfunction(a++, null); | ||||
| 		String str       = args.optjstring(a++,""); | ||||
| 		int count        = args.optint(a++,0); | ||||
| 		boolean call=false,line=false,rtrn=false; | ||||
| 		for ( int i=0; i<str.length(); i++ ) | ||||
| 			switch ( str.charAt(i) ) { | ||||
| 				case 'c': call=true; break; | ||||
| 				case 'l': line=true; break; | ||||
| 				case 'r': rtrn=true; break; | ||||
| 			} | ||||
| 		getDebugState(thread).sethook(func, call, line, rtrn, count); | ||||
| 		return NONE; | ||||
| 	} | ||||
|  | ||||
| 	static Varargs _getfenv(Varargs args) { | ||||
| 		LuaValue object = args.arg1(); | ||||
| 		LuaValue env = object.getfenv(); | ||||
| 		return env!=null? env: LuaValue.NIL; | ||||
| 	} | ||||
|  | ||||
| 	static Varargs _setfenv(Varargs args) { | ||||
| 		LuaValue object = args.arg1(); | ||||
| 		LuaTable table = args.checktable(2); | ||||
| 		object.setfenv(table); | ||||
| 		return object; | ||||
| 	} | ||||
| 	 | ||||
| 	protected static Varargs _getinfo(Varargs args, LuaValue level0func) { | ||||
| 		int a=1; | ||||
| 		LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning();  | ||||
| 		LuaValue func = args.arg(a++); | ||||
| 		String what = args.optjstring(a++, "nSluf"); | ||||
| 		 | ||||
| 		// find the stack info | ||||
| 		DebugState ds = getDebugState( thread ); | ||||
| 		DebugInfo di = null; | ||||
| 		if ( func.isnumber() ) { | ||||
| 			int level = func.checkint(); | ||||
| 			di = level>0?  | ||||
| 				ds.getDebugInfo(level-1): | ||||
| 				new DebugInfo( level0func ); | ||||
| 		} else {			 | ||||
| 			di = ds.findDebugInfo( func.checkfunction() ); | ||||
| 		} | ||||
| 		if ( di == null ) | ||||
| 			return NIL; | ||||
|  | ||||
| 		// start a table | ||||
| 		LuaTable info = new LuaTable(); | ||||
| 		LuaClosure c = di.closure; | ||||
| 		for (int i = 0, j = what.length(); i < j; i++) { | ||||
| 			switch (what.charAt(i)) { | ||||
| 				case 'S': { | ||||
| 					if ( c != null ) { | ||||
| 						Prototype p = c.p; | ||||
| 						info.set(WHAT, LUA); | ||||
| 						info.set(SOURCE, p.source); | ||||
| 						info.set(SHORT_SRC, valueOf(sourceshort(p))); | ||||
| 						info.set(LINEDEFINED, valueOf(p.linedefined)); | ||||
| 						info.set(LASTLINEDEFINED, valueOf(p.lastlinedefined)); | ||||
| 					} else { | ||||
| 						String shortName = di.func.tojstring(); | ||||
| 						LuaString name = LuaString.valueOf("[Java] "+shortName); | ||||
| 						info.set(WHAT, JAVA); | ||||
| 						info.set(SOURCE, name); | ||||
| 						info.set(SHORT_SRC, valueOf(shortName)); | ||||
| 						info.set(LINEDEFINED, LuaValue.MINUSONE); | ||||
| 						info.set(LASTLINEDEFINED, LuaValue.MINUSONE); | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
| 				case 'l': { | ||||
| 					int line = di.currentline(); | ||||
| 					info.set( CURRENTLINE, valueOf(line) ); | ||||
| 					break; | ||||
| 				} | ||||
| 				case 'u': { | ||||
| 					info.set(NUPS, valueOf(c!=null? c.p.nups: 0)); | ||||
| 					break; | ||||
| 				} | ||||
| 				case 'n': { | ||||
| 					LuaString[] kind = di.getfunckind(); | ||||
| 					info.set(NAME, kind!=null? kind[0]: QMARK); | ||||
| 					info.set(NAMEWHAT, kind!=null? kind[1]: EMPTYSTRING); | ||||
| 					break; | ||||
| 				} | ||||
| 				case 'f': { | ||||
| 					info.set( FUNC, di.func ); | ||||
| 					break; | ||||
| 				} | ||||
| 				case 'L': { | ||||
| 					LuaTable lines = new LuaTable(); | ||||
| 					info.set(ACTIVELINES, lines); | ||||
| //					if ( di.luainfo != null ) { | ||||
| //						int line = di.luainfo.currentline(); | ||||
| //						if ( line >= 0 ) | ||||
| //							lines.set(1, IntValue.valueOf(line)); | ||||
| //					} | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return info; | ||||
| 	} | ||||
|  | ||||
| 	public static String sourceshort(Prototype p) { | ||||
| 		String name = p.source.tojstring(); | ||||
|         if ( name.startsWith("@") || name.startsWith("=") ) | ||||
| 			name = name.substring(1); | ||||
| 		else if ( name.startsWith("\033") ) | ||||
| 			name = "binary string"; | ||||
|         return name; | ||||
| 	} | ||||
| 	 | ||||
| 	static Varargs _getlocal(Varargs args) { | ||||
| 		int a=1; | ||||
| 		LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning();  | ||||
| 		int level = args.checkint(a++); | ||||
| 		int local = args.checkint(a++); | ||||
| 		 | ||||
| 		DebugState ds = getDebugState(thread);  | ||||
| 		DebugInfo di = ds.getDebugInfo(level-1); | ||||
| 		LuaString name = (di!=null? di.getlocalname(local): null); | ||||
| 		if ( name != null ) { | ||||
| 			LuaValue value = di.stack[local-1]; | ||||
| 			return varargsOf( name, value ); | ||||
| 		} else { | ||||
| 			return NIL; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	static Varargs _setlocal(Varargs args) { | ||||
| 		int a=1; | ||||
| 		LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning();  | ||||
| 		int level = args.checkint(a++); | ||||
| 		int local = args.checkint(a++); | ||||
| 		LuaValue value = args.arg(a++); | ||||
| 		 | ||||
| 		DebugState ds = getDebugState(thread);  | ||||
| 		DebugInfo di = ds.getDebugInfo(level-1); | ||||
| 		LuaString name = (di!=null? di.getlocalname(local): null); | ||||
| 		if ( name != null ) { | ||||
| 			di.stack[local-1] = value; | ||||
| 			return name; | ||||
| 		} else { | ||||
| 			return NIL; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	static LuaValue _getmetatable(Varargs args) { | ||||
| 		LuaValue object = args.arg(1); | ||||
| 		LuaValue mt = object.getmetatable(); | ||||
| 		return mt!=null? mt: NIL; | ||||
| 	} | ||||
|  | ||||
| 	static Varargs _setmetatable(Varargs args) { | ||||
| 		LuaValue object = args.arg(1); | ||||
| 		try { | ||||
| 			LuaValue mt = args.opttable(2, null); | ||||
| 			switch ( object.type() ) { | ||||
| 				case TNIL:      LuaNil.s_metatable      = mt; break; | ||||
| 				case TNUMBER:   LuaNumber.s_metatable   = mt; break; | ||||
| 				case TBOOLEAN:  LuaBoolean.s_metatable  = mt; break; | ||||
| 				case TSTRING:   LuaString.s_metatable   = mt; break; | ||||
| 				case TFUNCTION: LuaFunction.s_metatable = mt; break; | ||||
| 				case TTHREAD:   LuaThread.s_metatable   = mt; break; | ||||
| 				default: object.setmetatable( mt ); | ||||
| 			} | ||||
| 			return LuaValue.TRUE; | ||||
| 		} catch ( LuaError e ) { | ||||
| 			return varargsOf(FALSE, valueOf(e.toString())); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	static Varargs _getregistry(Varargs args) { | ||||
| 		return new LuaTable(); | ||||
| 	} | ||||
|  | ||||
| 	static LuaString findupvalue(LuaClosure c, int up) { | ||||
| 		if ( c.upValues != null && up > 0 && up <= c.upValues.length ) { | ||||
| 			if ( c.p.upvalues != null && up <= c.p.upvalues.length ) | ||||
| 				return c.p.upvalues[up-1]; | ||||
| 			else | ||||
| 				return LuaString.valueOf( "."+up ); | ||||
| 		} | ||||
| 		return null; | ||||
| 	} | ||||
|  | ||||
| 	static Varargs _getupvalue(Varargs args) { | ||||
| 		LuaValue func = args.checkfunction(1); | ||||
| 		int up = args.checkint(2); | ||||
| 		if ( func instanceof LuaClosure ) { | ||||
| 			LuaClosure c = (LuaClosure) func; | ||||
| 			LuaString name = findupvalue(c, up); | ||||
| 			if ( name != null ) { | ||||
| 				return varargsOf(name, c.upValues[up-1].getValue() ); | ||||
| 			} | ||||
| 		} | ||||
| 		return NIL; | ||||
| 	} | ||||
|  | ||||
| 	static LuaValue _setupvalue(Varargs args) { | ||||
| 		LuaValue func = args.checkfunction(1); | ||||
| 		int up = args.checkint(2); | ||||
| 		LuaValue value = args.arg(3); | ||||
| 		if ( func instanceof LuaClosure ) { | ||||
| 			LuaClosure c = (LuaClosure) func; | ||||
| 			LuaString name = findupvalue(c, up); | ||||
| 			if ( name != null ) { | ||||
| 				c.upValues[up-1].setValue(value); | ||||
| 				return name; | ||||
| 			} | ||||
| 		} | ||||
| 		return NIL; | ||||
| 	} | ||||
|  | ||||
| 	static LuaValue _traceback(Varargs args) { | ||||
| 		int a=1; | ||||
| 		LuaThread thread = args.isthread(a)? args.checkthread(a++): LuaThread.getRunning();  | ||||
| 		String message = args.optjstring(a++, null); | ||||
| 		int level = args.optint(a++,1); | ||||
| 		String tb = DebugLib.traceback(thread, level-1); | ||||
| 		return valueOf(message!=null? message+"\n"+tb: tb); | ||||
| 	} | ||||
| 	 | ||||
| 	// =================== public utilities ==================== | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Get a traceback as a string for the current thread  | ||||
| 	 */ | ||||
| 	public static String traceback(int level) { | ||||
| 		return traceback(LuaThread.getRunning(), level); | ||||
| 	} | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Get a traceback for a particular thread. | ||||
| 	 * @param thread LuaThread to provide stack trace for | ||||
| 	 * @param level 0-based level to start reporting on | ||||
| 	 * @return String containing the stack trace. | ||||
| 	 */ | ||||
| 	public static String traceback(LuaThread thread, int level) { | ||||
| 		StringBuffer sb = new StringBuffer(); | ||||
| 		DebugState ds = getDebugState(thread); | ||||
| 		sb.append( "stack traceback:" ); | ||||
| 		DebugInfo di = ds.getDebugInfo(level); | ||||
| 		if ( di != null ) { | ||||
| 			sb.append( "\n\t" ); | ||||
| 			sb.append( di.sourceline() ); | ||||
| 			sb.append( " in " ); | ||||
| 			while ( (di = ds.getDebugInfo(++level)) != null ) { | ||||
| 				sb.append( di.tracename() ); | ||||
| 				sb.append( "\n\t" ); | ||||
| 				sb.append( di.sourceline() ); | ||||
| 				sb.append( " in " ); | ||||
| 			} | ||||
| 			sb.append( "main chunk" ); | ||||
| 		} | ||||
| 		return sb.toString(); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	/** | ||||
| 	 * Get file and line for the nearest calling closure. | ||||
| 	 * @return String identifying the file and line of the nearest lua closure, | ||||
| 	 * or the function name of the Java call if no closure is being called. | ||||
| 	 */ | ||||
| 	public static String fileline() { | ||||
| 		DebugState ds = getDebugState(LuaThread.getRunning()); | ||||
| 		DebugInfo di; | ||||
| 		for ( int i=0, n=ds.debugCalls; i<n; i++ ) { | ||||
| 			di = ds.getDebugInfo(i); | ||||
| 			if ( di != null && di.func.isclosure() ) | ||||
| 				return di.sourceline(); | ||||
| 		} | ||||
| 		return fileline(0); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Get file and line for a particular level, even if it is a java function. | ||||
| 	 *  | ||||
| 	 * @param level 0-based index of level to get | ||||
| 	 * @return String containing file and line info if available | ||||
| 	 */ | ||||
| 	public static String fileline(int level) { | ||||
| 		DebugState ds = getDebugState(LuaThread.getRunning()); | ||||
| 		DebugInfo di = ds.getDebugInfo(level); | ||||
| 		return di!=null? di.sourceline(): null; | ||||
| 	} | ||||
|  | ||||
| 	// ======================================================= | ||||
| 	 | ||||
| 	static void lua_assert(boolean x) { | ||||
| 		if (!x) throw new RuntimeException("lua_assert failed"); | ||||
| 	}	 | ||||
|  | ||||
| 	 | ||||
| 	// return StrValue[] { name, namewhat } if found, null if not | ||||
| 	static LuaString[] getobjname(DebugInfo di, int stackpos) { | ||||
| 		LuaString name; | ||||
| 		if (di.closure != null) { /* a Lua function? */ | ||||
| 			Prototype p = di.closure.p; | ||||
| 			int pc = di.pc; // currentpc(L, ci); | ||||
| 			int i;// Instruction i; | ||||
| 			name = p.getlocalname(stackpos + 1, pc); | ||||
| 			if (name != null) /* is a local? */ | ||||
| 				return new LuaString[] { name, LOCAL }; | ||||
| 			i = symbexec(p, pc, stackpos); /* try symbolic execution */ | ||||
| 			lua_assert(pc != -1); | ||||
| 			switch (Lua.GET_OPCODE(i)) { | ||||
| 			case Lua.OP_GETGLOBAL: { | ||||
| 				int g = Lua.GETARG_Bx(i); /* global index */ | ||||
| 				// lua_assert(p.k[g].isString()); | ||||
| 				return new LuaString[] { p.k[g].strvalue(), GLOBAL }; | ||||
| 			} | ||||
| 			case Lua.OP_MOVE: { | ||||
| 				int a = Lua.GETARG_A(i); | ||||
| 				int b = Lua.GETARG_B(i); /* move from `b' to `a' */ | ||||
| 				if (b < a) | ||||
| 					return getobjname(di, b); /* get name for `b' */ | ||||
| 				break; | ||||
| 			} | ||||
| 			case Lua.OP_GETTABLE: { | ||||
| 				int k = Lua.GETARG_C(i); /* key index */ | ||||
| 				name = kname(p, k); | ||||
| 				return new LuaString[] { name, FIELD }; | ||||
| 			} | ||||
| 			case Lua.OP_GETUPVAL: { | ||||
| 				int u = Lua.GETARG_B(i); /* upvalue index */ | ||||
| 				name = u < p.upvalues.length ? p.upvalues[u] : QMARK; | ||||
| 				return new LuaString[] { name, UPVALUE }; | ||||
| 			} | ||||
| 			case Lua.OP_SELF: { | ||||
| 				int k = Lua.GETARG_C(i); /* key index */ | ||||
| 				name = kname(p, k); | ||||
| 				return new LuaString[] { name, METHOD }; | ||||
| 			} | ||||
| 			default: | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		return null; /* no useful name found */ | ||||
| 	} | ||||
|  | ||||
| 	static LuaString kname(Prototype p, int c) { | ||||
| 		if (Lua.ISK(c) && p.k[Lua.INDEXK(c)].isstring()) | ||||
| 			return p.k[Lua.INDEXK(c)].strvalue(); | ||||
| 		else | ||||
| 			return QMARK; | ||||
| 	} | ||||
|  | ||||
| 	static boolean checkreg(Prototype pt,int reg)	{ | ||||
| 		return (reg < pt.maxstacksize); | ||||
| 	} | ||||
|  | ||||
| 	static boolean precheck(Prototype pt) { | ||||
| 		if (!(pt.maxstacksize <= MAXSTACK)) return false; | ||||
| 		lua_assert(pt.numparams + (pt.is_vararg & Lua.VARARG_HASARG) <= pt.maxstacksize); | ||||
| 		lua_assert((pt.is_vararg & Lua.VARARG_NEEDSARG) == 0 | ||||
| 				|| (pt.is_vararg & Lua.VARARG_HASARG) != 0); | ||||
| 		if (!(pt.upvalues.length <= pt.nups)) return false; | ||||
| 		if (!(pt.lineinfo.length == pt.code.length || pt.lineinfo.length == 0)) return false; | ||||
| 		if (!(Lua.GET_OPCODE(pt.code[pt.code.length - 1]) == Lua.OP_RETURN)) return false; | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	static boolean checkopenop(Prototype pt,int pc) { | ||||
| 		int i = pt.code[(pc)+1]; | ||||
| 		switch (Lua.GET_OPCODE(i)) { | ||||
| 		case Lua.OP_CALL: | ||||
| 		case Lua.OP_TAILCALL: | ||||
| 		case Lua.OP_RETURN: | ||||
| 		case Lua.OP_SETLIST: { | ||||
| 			if (!(Lua.GETARG_B(i) == 0)) return false; | ||||
| 			return true; | ||||
| 		} | ||||
| 		default: | ||||
| 			return false; /* invalid instruction after an open call */ | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	//static int checkArgMode (Prototype pt, int r, enum OpArgMask mode) { | ||||
| 	static boolean checkArgMode (Prototype pt, int r, int mode) { | ||||
| 		switch (mode) { | ||||
| 			case Lua.OpArgN: if (!(r == 0)) return false; break; | ||||
| 			case Lua.OpArgU: break; | ||||
| 			case Lua.OpArgR: checkreg(pt, r); break; | ||||
| 			case Lua.OpArgK: | ||||
| 				if (!(Lua.ISK(r) ? Lua.INDEXK(r) < pt.k.length : r < pt.maxstacksize)) return false; | ||||
| 				break; | ||||
| 		} | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	// return last instruction, or 0 if error | ||||
| 	static int symbexec(Prototype pt, int lastpc, int reg) { | ||||
| 		int pc; | ||||
| 		int last; /* stores position of last instruction that changed `reg' */ | ||||
| 		last = pt.code.length - 1; /* | ||||
| 									 * points to final return (a `neutral' | ||||
| 									 * instruction) | ||||
| 									 */ | ||||
| 		if (!(precheck(pt))) return 0; | ||||
| 		for (pc = 0; pc < lastpc; pc++) { | ||||
| 			int i = pt.code[pc]; | ||||
| 			int op = Lua.GET_OPCODE(i); | ||||
| 			int a = Lua.GETARG_A(i); | ||||
| 			int b = 0; | ||||
| 			int c = 0; | ||||
| 			if (!(op < Lua.NUM_OPCODES)) return 0; | ||||
| 			if (!checkreg(pt, a)) return 0; | ||||
| 			switch (Lua.getOpMode(op)) { | ||||
| 			case Lua.iABC: { | ||||
| 				b = Lua.GETARG_B(i); | ||||
| 				c = Lua.GETARG_C(i); | ||||
| 				if (!(checkArgMode(pt, b, Lua.getBMode(op)))) return 0; | ||||
| 				if (!(checkArgMode(pt, c, Lua.getCMode(op)))) return 0; | ||||
| 				break; | ||||
| 			} | ||||
| 			case Lua.iABx: { | ||||
| 				b = Lua.GETARG_Bx(i); | ||||
| 				if (Lua.getBMode(op) == Lua.OpArgK) | ||||
| 					if (!(b < pt.k.length)) return 0; | ||||
| 				break; | ||||
| 			} | ||||
| 			case Lua.iAsBx: { | ||||
| 				b = Lua.GETARG_sBx(i); | ||||
| 				if (Lua.getBMode(op) == Lua.OpArgR) { | ||||
| 					int dest = pc + 1 + b; | ||||
| 					if (!(0 <= dest && dest < pt.code.length)) return 0; | ||||
| 					if (dest > 0) { | ||||
| 						/* cannot jump to a setlist count */ | ||||
| 						int d = pt.code[dest - 1]; | ||||
| 						if ((Lua.GET_OPCODE(d) == Lua.OP_SETLIST && Lua.GETARG_C(d) == 0)) return 0; | ||||
| 					} | ||||
| 				} | ||||
| 				break; | ||||
| 			} | ||||
| 			} | ||||
| 			if (Lua.testAMode(op)) { | ||||
| 				if (a == reg) | ||||
| 					last = pc; /* change register `a' */ | ||||
| 			} | ||||
| 			if (Lua.testTMode(op)) { | ||||
| 				if (!(pc + 2 < pt.code.length)) return 0; /* check skip */ | ||||
| 				if (!(Lua.GET_OPCODE(pt.code[pc + 1]) == Lua.OP_JMP)) return 0; | ||||
| 			} | ||||
| 			switch (op) { | ||||
| 			case Lua.OP_LOADBOOL: { | ||||
| 				if (!(c == 0 || pc + 2 < pt.code.length)) return 0; /* check its jump */ | ||||
| 				break; | ||||
| 			} | ||||
| 			case Lua.OP_LOADNIL: { | ||||
| 				if (a <= reg && reg <= b) | ||||
| 					last = pc; /* set registers from `a' to `b' */ | ||||
| 				break; | ||||
| 			} | ||||
| 			case Lua.OP_GETUPVAL: | ||||
| 			case Lua.OP_SETUPVAL: { | ||||
| 				if (!(b < pt.nups)) return 0; | ||||
| 				break; | ||||
| 			} | ||||
| 			case Lua.OP_GETGLOBAL: | ||||
| 			case Lua.OP_SETGLOBAL: { | ||||
| 				if (!(pt.k[b].isstring())) return 0; | ||||
| 				break; | ||||
| 			} | ||||
| 			case Lua.OP_SELF: { | ||||
| 				if (!checkreg(pt, a + 1)) return 0; | ||||
| 				if (reg == a + 1) | ||||
| 					last = pc; | ||||
| 				break; | ||||
| 			} | ||||
| 			case Lua.OP_CONCAT: { | ||||
| 				if (!(b < c)) return 0; /* at least two operands */ | ||||
| 				break; | ||||
| 			} | ||||
| 			case Lua.OP_TFORLOOP: { | ||||
| 				if (!(c >= 1)) return 0; /* at least one result (control variable) */ | ||||
| 				if (!checkreg(pt, a + 2 + c)) return 0; /* space for results */ | ||||
| 				if (reg >= a + 2) | ||||
| 					last = pc; /* affect all regs above its base */ | ||||
| 				break; | ||||
| 			} | ||||
| 			case Lua.OP_FORLOOP: | ||||
| 			case Lua.OP_FORPREP: | ||||
| 				if (!checkreg(pt, a + 3)) return 0; | ||||
| 				/* go through */ | ||||
| 			case Lua.OP_JMP: { | ||||
| 				int dest = pc + 1 + b; | ||||
| 				/* not full check and jump is forward and do not skip `lastpc'? */ | ||||
| 				if (reg != Lua.NO_REG && pc < dest && dest <= lastpc) | ||||
| 					pc += b; /* do the jump */ | ||||
| 				break; | ||||
| 			} | ||||
| 			case Lua.OP_CALL: | ||||
| 			case Lua.OP_TAILCALL: { | ||||
| 				if (b != 0) { | ||||
| 					if (!checkreg(pt, a + b - 1)) return 0; | ||||
| 				} | ||||
| 				c--; /* c = num. returns */ | ||||
| 				if (c == Lua.LUA_MULTRET) { | ||||
| 					if (!(checkopenop(pt, pc))) return 0; | ||||
| 				} else if (c != 0) | ||||
| 					if (!checkreg(pt, a + c - 1)) return 0; | ||||
| 				if (reg >= a) | ||||
| 					last = pc; /* affect all registers above base */ | ||||
| 				break; | ||||
| 			} | ||||
| 			case Lua.OP_RETURN: { | ||||
| 				b--; /* b = num. returns */ | ||||
| 				if (b > 0) | ||||
| 					if (!checkreg(pt, a + b - 1)) return 0; | ||||
| 				break; | ||||
| 			} | ||||
| 			case Lua.OP_SETLIST: { | ||||
| 				if (b > 0) | ||||
| 					if (!checkreg(pt, a + b)) return 0; | ||||
| 				if (c == 0) | ||||
| 					pc++; | ||||
| 				break; | ||||
| 			} | ||||
| 			case Lua.OP_CLOSURE: { | ||||
| 				int nup, j; | ||||
| 				if (!(b < pt.p.length)) return 0; | ||||
| 				nup = pt.p[b].nups; | ||||
| 				if (!(pc + nup < pt.code.length)) return 0; | ||||
| 				for (j = 1; j <= nup; j++) { | ||||
| 					int op1 = Lua.GET_OPCODE(pt.code[pc + j]); | ||||
| 					if (!(op1 == Lua.OP_GETUPVAL || op1 == Lua.OP_MOVE)) return 0; | ||||
| 				} | ||||
| 				if (reg != Lua.NO_REG) /* tracing? */ | ||||
| 					pc += nup; /* do not 'execute' these pseudo-instructions */ | ||||
| 				break; | ||||
| 			} | ||||
| 			case Lua.OP_VARARG: { | ||||
| 				if (!((pt.is_vararg & Lua.VARARG_ISVARARG) != 0 | ||||
| 						&& (pt.is_vararg & Lua.VARARG_NEEDSARG) == 0)) return 0; | ||||
| 				b--; | ||||
| 				if (b == Lua.LUA_MULTRET) | ||||
| 					if (!(checkopenop(pt, pc))) return 0; | ||||
| 				if (!checkreg(pt, a + b - 1)) return 0; | ||||
| 				break; | ||||
| 			} | ||||
| 			default: | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		return pt.code[last]; | ||||
| 	} | ||||
| 	 | ||||
| } | ||||
| @@ -1,607 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.lib; | ||||
|  | ||||
| import java.io.ByteArrayOutputStream; | ||||
| import java.io.EOFException; | ||||
| import java.io.IOException; | ||||
|  | ||||
| import org.luaj.vm2.LuaString; | ||||
| import org.luaj.vm2.LuaTable; | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.Varargs; | ||||
|  | ||||
| /**  | ||||
|  * Abstract base class extending {@link LibFunction} which implements the  | ||||
|  * core of the lua standard {@code io} library.    | ||||
|  * <p>  | ||||
|  * It contains the implementation of the io library support that is common to | ||||
|  * the JSE and JME platforms.  | ||||
|  * In practice on of the concrete IOLib subclasses is chosen:   | ||||
|  * {@link org.luaj.vm2.lib.jse.JseIoLib} for the JSE platform, and  | ||||
|  * {@link org.luaj.vm2.lib.jme.JmeIoLib} for the JME platform. | ||||
|  * <p> | ||||
|  * The JSE implementation conforms almost completely to the C-based lua library,  | ||||
|  * while the JME implementation follows closely except in the area of random-access files,  | ||||
|  * which are difficult to support properly on JME.  | ||||
|  * <p>  | ||||
|  * Typically, this library is included as part of a call to either  | ||||
|  * {@link JsePlatform#standardGlobals()} or {@link JmePlatform#standardGlobals()} | ||||
|  * <p> | ||||
|  * To instantiate and use it directly,  | ||||
|  * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: | ||||
|  * <pre> {@code | ||||
|  * LuaTable _G = new LuaTable(); | ||||
|  * _G.load(new JseIoLib()); | ||||
|  * LuaThread.setGlobals(_G); | ||||
|  * _G.load(new JseBaseLib()); | ||||
|  * _G.load(new PackageLib()); | ||||
|  * _G.load(new JseIoLib()); | ||||
|  * _G.get("io").get("write").call(LuaValue.valueOf("hello, world\n")); | ||||
|  * } </pre> | ||||
|  * Doing so will ensure the library is properly initialized  | ||||
|  * and loaded into the globals table.  | ||||
|  * <p> | ||||
|  * This has been implemented to match as closely as possible the behavior in the corresponding library in C. | ||||
|  * @see LibFunction | ||||
|  * @see JsePlatform | ||||
|  * @see JmePlatform | ||||
|  * @see JseIoLib | ||||
|  * @see JmeIoLib | ||||
|  * @see <a href="http://www.lua.org/manual/5.1/manual.html#5.7">http://www.lua.org/manual/5.1/manual.html#5.7</a> | ||||
|  */ | ||||
| abstract  | ||||
| public class IoLib extends OneArgFunction { | ||||
|  | ||||
| 	abstract  | ||||
| 	protected class File extends LuaValue{ | ||||
| 		abstract public void write( LuaString string ) throws IOException; | ||||
| 		abstract public void flush() throws IOException; | ||||
| 		abstract public boolean isstdfile(); | ||||
| 		abstract public void close() throws IOException; | ||||
| 		abstract public boolean isclosed(); | ||||
| 		// returns new position | ||||
| 		abstract public int seek(String option, int bytecount) throws IOException; | ||||
| 		abstract public void setvbuf(String mode, int size);		 | ||||
| 		// get length remaining to read | ||||
| 		abstract public int remaining() throws IOException;		 | ||||
| 		// peek ahead one character | ||||
| 		abstract public int peek() throws IOException, EOFException;		 | ||||
| 		// return char if read, -1 if eof, throw IOException on other exception  | ||||
| 		abstract public int read() throws IOException, EOFException; | ||||
| 		// return number of bytes read if positive, false if eof, throw IOException on other exception | ||||
| 		abstract public int read(byte[] bytes, int offset, int length) throws IOException; | ||||
| 		 | ||||
| 		// delegate method access to file methods table | ||||
| 		public LuaValue get( LuaValue key ) { | ||||
| 			return filemethods.get(key); | ||||
| 		} | ||||
|  | ||||
| 		// essentially a userdata instance | ||||
| 		public int type() { | ||||
| 			return LuaValue.TUSERDATA; | ||||
| 		} | ||||
| 		public String typename() { | ||||
| 			return "userdata"; | ||||
| 		} | ||||
| 		 | ||||
| 		// displays as "file" type | ||||
| 		public String tojstring() { | ||||
| 			return "file: " + Integer.toHexString(hashCode()); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	/**  | ||||
| 	 * Wrap the standard input.  | ||||
| 	 * @return File  | ||||
| 	 * @throws IOException | ||||
| 	 */ | ||||
| 	abstract protected File wrapStdin() throws IOException; | ||||
|  | ||||
| 	/**  | ||||
| 	 * Wrap the standard output.  | ||||
| 	 * @return File  | ||||
| 	 * @throws IOException | ||||
| 	 */ | ||||
| 	abstract protected File wrapStdout() throws IOException; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Open a file in a particular mode.  | ||||
| 	 * @param filename | ||||
| 	 * @param readMode true if opening in read mode | ||||
| 	 * @param appendMode true if opening in append mode | ||||
| 	 * @param updateMode true if opening in update mode | ||||
| 	 * @param binaryMode true if opening in binary mode | ||||
| 	 * @return File object if successful | ||||
| 	 * @throws IOException if could not be opened | ||||
| 	 */ | ||||
| 	abstract protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException; | ||||
|  | ||||
| 	/** | ||||
| 	 * Open a temporary file.  | ||||
| 	 * @return File object if successful | ||||
| 	 * @throws IOException if could not be opened | ||||
| 	 */ | ||||
| 	abstract protected File tmpFile() throws IOException; | ||||
|  | ||||
| 	/** | ||||
| 	 * Start a new process and return a file for input or output | ||||
| 	 * @param prog the program to execute | ||||
| 	 * @param mode "r" to read, "w" to write | ||||
| 	 * @return File to read to or write from  | ||||
| 	 * @throws IOException if an i/o exception occurs | ||||
| 	 */ | ||||
| 	abstract protected File openProgram(String prog, String mode) throws IOException; | ||||
|  | ||||
| 	private File infile  = null; | ||||
| 	private File outfile = null; | ||||
| 	private File errfile = null; | ||||
|  | ||||
| 	private static final LuaValue STDIN       = valueOf("stdin"); | ||||
| 	private static final LuaValue STDOUT      = valueOf("stdout"); | ||||
| 	private static final LuaValue STDERR      = valueOf("stderr");		 | ||||
| 	private static final LuaValue FILE        = valueOf("file"); | ||||
| 	private static final LuaValue CLOSED_FILE = valueOf("closed file"); | ||||
| 	 | ||||
| 	private static final int IO_CLOSE      = 0; | ||||
| 	private static final int IO_FLUSH      = 1; | ||||
| 	private static final int IO_INPUT      = 2; | ||||
| 	private static final int IO_LINES      = 3; | ||||
| 	private static final int IO_OPEN       = 4; | ||||
| 	private static final int IO_OUTPUT     = 5; | ||||
| 	private static final int IO_POPEN      = 6; | ||||
| 	private static final int IO_READ       = 7; | ||||
| 	private static final int IO_TMPFILE    = 8; | ||||
| 	private static final int IO_TYPE       = 9; | ||||
| 	private static final int IO_WRITE      = 10; | ||||
|  | ||||
| 	private static final int FILE_CLOSE    = 11; | ||||
| 	private static final int FILE_FLUSH    = 12; | ||||
| 	private static final int FILE_LINES    = 13; | ||||
| 	private static final int FILE_READ     = 14; | ||||
| 	private static final int FILE_SEEK     = 15; | ||||
| 	private static final int FILE_SETVBUF  = 16; | ||||
| 	private static final int FILE_WRITE    = 17; | ||||
| 	 | ||||
| 	private static final int IO_INDEX      = 18; | ||||
| 	private static final int LINES_ITER    = 19; | ||||
|  | ||||
| 	public static final String[] IO_NAMES = { | ||||
| 		"close", | ||||
| 		"flush", | ||||
| 		"input", | ||||
| 		"lines", | ||||
| 		"open", | ||||
| 		"output", | ||||
| 		"popen", | ||||
| 		"read", | ||||
| 		"tmpfile", | ||||
| 		"type", | ||||
| 		"write", | ||||
| 	}; | ||||
| 	 | ||||
| 	public static final String[] FILE_NAMES = { | ||||
| 		"close", | ||||
| 		"flush", | ||||
| 		"lines", | ||||
| 		"read", | ||||
| 		"seek", | ||||
| 		"setvbuf", | ||||
| 		"write", | ||||
| 	}; | ||||
|  | ||||
| 	LuaTable filemethods; | ||||
| 	 | ||||
| 	public IoLib() { | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue call(LuaValue arg) { | ||||
| 		 | ||||
| 		// io lib functions | ||||
| 		LuaTable t = new LuaTable(); | ||||
| 		bind(t, IoLibV.class, IO_NAMES ); | ||||
| 		 | ||||
| 		// create file methods table | ||||
| 		filemethods = new LuaTable(); | ||||
| 		bind(filemethods, IoLibV.class, FILE_NAMES, FILE_CLOSE ); | ||||
|  | ||||
| 		// set up file metatable | ||||
| 		LuaTable mt = new LuaTable(); | ||||
| 		bind(mt, IoLibV.class, new String[] { "__index" }, IO_INDEX ); | ||||
| 		t.setmetatable( mt ); | ||||
| 		 | ||||
| 		// all functions link to library instance | ||||
| 		setLibInstance( t ); | ||||
| 		setLibInstance( filemethods ); | ||||
| 		setLibInstance( mt ); | ||||
| 		 | ||||
| 		// return the table | ||||
| 		env.set("io", t); | ||||
| 		PackageLib.instance.LOADED.set("io", t); | ||||
| 		return t; | ||||
| 	} | ||||
|  | ||||
| 	private void setLibInstance(LuaTable t) { | ||||
| 		LuaValue[] k = t.keys(); | ||||
| 		for ( int i=0, n=k.length; i<n; i++ ) | ||||
| 			((IoLibV) t.get(k[i])).iolib = this; | ||||
| 	} | ||||
| 	 | ||||
| 	static final class IoLibV extends VarArgFunction { | ||||
| 		public IoLib iolib; | ||||
| 		public IoLibV() { | ||||
| 		} | ||||
| 		public IoLibV(LuaValue env, String name, int opcode, IoLib iolib) { | ||||
| 			super(); | ||||
| 			this.env = env; | ||||
| 			this.name = name; | ||||
| 			this.opcode = opcode; | ||||
| 			this.iolib = iolib; | ||||
| 		} | ||||
|  | ||||
| 		public Varargs invoke(Varargs args) { | ||||
| 			try { | ||||
| 				switch ( opcode ) { | ||||
| 				case IO_FLUSH:		return iolib._io_flush(); | ||||
| 				case IO_TMPFILE:	return iolib._io_tmpfile(); | ||||
| 				case IO_CLOSE:		return iolib._io_close(args.arg1()); | ||||
| 				case IO_INPUT:		return iolib._io_input(args.arg1()); | ||||
| 				case IO_OUTPUT:		return iolib._io_output(args.arg1()); | ||||
| 				case IO_TYPE:		return iolib._io_type(args.arg1()); | ||||
| 				case IO_POPEN:		return iolib._io_popen(args.checkjstring(1),args.optjstring(2,"r")); | ||||
| 				case IO_OPEN:		return iolib._io_open(args.checkjstring(1), args.optjstring(2,"r")); | ||||
| 				case IO_LINES:		return iolib._io_lines(args.isvalue(1)? args.checkjstring(1): null); | ||||
| 				case IO_READ:		return iolib._io_read(args); | ||||
| 				case IO_WRITE:		return iolib._io_write(args); | ||||
| 					 | ||||
| 				case FILE_CLOSE:	return iolib._file_close(args.arg1()); | ||||
| 				case FILE_FLUSH:	return iolib._file_flush(args.arg1()); | ||||
| 				case FILE_SETVBUF:	return iolib._file_setvbuf(args.arg1(),args.checkjstring(2),args.optint(3,1024)); | ||||
| 				case FILE_LINES:	return iolib._file_lines(args.arg1()); | ||||
| 				case FILE_READ:		return iolib._file_read(args.arg1(),args.subargs(2)); | ||||
| 				case FILE_SEEK:		return iolib._file_seek(args.arg1(),args.optjstring(2,"cur"),args.optint(3,0)); | ||||
| 				case FILE_WRITE:	return iolib._file_write(args.arg1(),args.subargs(2)); | ||||
|  | ||||
| 				case IO_INDEX:		return iolib._io_index(args.arg(2)); | ||||
| 				case LINES_ITER:	return iolib._lines_iter(env); | ||||
| 				} | ||||
| 			} catch ( IOException ioe ) { | ||||
| 				return errorresult(ioe); | ||||
| 			} | ||||
| 			return NONE; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	private File input() { | ||||
| 		return infile!=null? infile: (infile=ioopenfile("-","r")); | ||||
| 	} | ||||
| 	 | ||||
| 	//	io.flush() -> bool  | ||||
| 	public Varargs _io_flush() throws IOException { | ||||
| 		checkopen(output()); | ||||
| 		outfile.flush(); | ||||
| 		return LuaValue.TRUE; | ||||
| 	} | ||||
|  | ||||
| 	//	io.tmpfile() -> file | ||||
| 	public Varargs _io_tmpfile() throws IOException { | ||||
| 		return tmpFile(); | ||||
| 	} | ||||
|  | ||||
| 	//	io.close([file]) -> void | ||||
| 	public Varargs _io_close(LuaValue file) throws IOException { | ||||
| 		File f = file.isnil()? output(): checkfile(file); | ||||
| 		checkopen(f); | ||||
| 		return ioclose(f); | ||||
| 	} | ||||
|  | ||||
| 	//	io.input([file]) -> file | ||||
| 	public Varargs _io_input(LuaValue file) { | ||||
| 		infile = file.isnil()? input():  | ||||
| 				file.isstring()? ioopenfile(file.checkjstring(),"r"): | ||||
| 				checkfile(file); | ||||
| 		return infile; | ||||
| 	} | ||||
|  | ||||
| 	// io.output(filename) -> file | ||||
| 	public Varargs _io_output(LuaValue filename) { | ||||
| 		outfile = filename.isnil()? output():  | ||||
| 				  filename.isstring()? ioopenfile(filename.checkjstring(),"w"): | ||||
| 				  checkfile(filename); | ||||
| 		return outfile; | ||||
| 	} | ||||
|  | ||||
| 	//	io.type(obj) -> "file" | "closed file" | nil | ||||
| 	public Varargs _io_type(LuaValue obj) { | ||||
| 		File f = optfile(obj); | ||||
| 		return f!=null? | ||||
| 			f.isclosed()? CLOSED_FILE: FILE: | ||||
| 			NIL; | ||||
| 	} | ||||
|  | ||||
| 	// io.popen(prog, [mode]) -> file | ||||
| 	public Varargs _io_popen(String prog, String mode) throws IOException { | ||||
| 		return openProgram(prog, mode); | ||||
| 	} | ||||
|  | ||||
| 	//	io.open(filename, [mode]) -> file | nil,err | ||||
| 	public Varargs _io_open(String filename, String mode) throws IOException { | ||||
| 		return rawopenfile(filename, mode); | ||||
| 	} | ||||
|  | ||||
| 	//	io.lines(filename) -> iterator | ||||
| 	public Varargs _io_lines(String filename) { | ||||
| 		infile = filename==null? input(): ioopenfile(filename,"r"); | ||||
| 		checkopen(infile); | ||||
| 		return lines(infile); | ||||
| 	} | ||||
|  | ||||
| 	//	io.read(...) -> (...) | ||||
| 	public Varargs _io_read(Varargs args) throws IOException { | ||||
| 		checkopen(input()); | ||||
| 		return ioread(infile,args); | ||||
| 	} | ||||
|  | ||||
| 	//	io.write(...) -> void | ||||
| 	public Varargs _io_write(Varargs args) throws IOException { | ||||
| 		checkopen(output()); | ||||
| 		return iowrite(outfile,args); | ||||
| 	} | ||||
|  | ||||
| 	// file:close() -> void | ||||
| 	public Varargs _file_close(LuaValue file) throws IOException { | ||||
| 		return ioclose(checkfile(file)); | ||||
| 	} | ||||
|  | ||||
| 	// file:flush() -> void | ||||
| 	public Varargs _file_flush(LuaValue file) throws IOException { | ||||
| 		checkfile(file).flush(); | ||||
| 		return LuaValue.TRUE; | ||||
| 	} | ||||
|  | ||||
| 	// file:setvbuf(mode,[size]) -> void | ||||
| 	public Varargs _file_setvbuf(LuaValue file, String mode, int size) { | ||||
| 		checkfile(file).setvbuf(mode,size); | ||||
| 		return LuaValue.TRUE; | ||||
| 	} | ||||
|  | ||||
| 	// file:lines() -> iterator | ||||
| 	public Varargs _file_lines(LuaValue file) { | ||||
| 		return lines(checkfile(file)); | ||||
| 	} | ||||
|  | ||||
| 	//	file:read(...) -> (...) | ||||
| 	public Varargs _file_read(LuaValue file, Varargs subargs) throws IOException { | ||||
| 		return ioread(checkfile(file),subargs); | ||||
| 	} | ||||
|  | ||||
| 	//  file:seek([whence][,offset]) -> pos | nil,error | ||||
| 	public Varargs _file_seek(LuaValue file, String whence, int offset) throws IOException { | ||||
| 		return valueOf( checkfile(file).seek(whence,offset) ); | ||||
| 	} | ||||
|  | ||||
| 	//	file:write(...) -> void		 | ||||
| 	public Varargs _file_write(LuaValue file, Varargs subargs) throws IOException { | ||||
| 		return iowrite(checkfile(file),subargs); | ||||
| 	} | ||||
|  | ||||
| 	// __index, returns a field | ||||
| 	public Varargs _io_index(LuaValue v) { | ||||
| 		return v.equals(STDOUT)?output(): | ||||
| 			   v.equals(STDIN)?  input(): | ||||
| 			   v.equals(STDERR)? errput(): NIL; | ||||
| 	} | ||||
|  | ||||
| 	//	lines iterator(s,var) -> var' | ||||
| 	public Varargs _lines_iter(LuaValue file) throws IOException { | ||||
| 		return freadline(checkfile(file)); | ||||
| 	} | ||||
|  | ||||
| 	private File output() { | ||||
| 		return outfile!=null? outfile: (outfile=ioopenfile("-","w")); | ||||
| 	} | ||||
| 	 | ||||
| 	private File errput() { | ||||
| 		return errfile!=null? errfile: (errfile=ioopenfile("-","w")); | ||||
| 	} | ||||
| 	 | ||||
| 	private File ioopenfile(String filename, String mode) { | ||||
| 		try { | ||||
| 			return rawopenfile(filename, mode); | ||||
| 		} catch ( Exception e ) { | ||||
| 			error("io error: "+e.getMessage()); | ||||
| 			return null; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	private static Varargs ioclose(File f) throws IOException { | ||||
| 		if ( f.isstdfile() ) | ||||
| 			return errorresult("cannot close standard file"); | ||||
| 		else { | ||||
| 			f.close(); | ||||
| 			return successresult(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	private static Varargs successresult() { | ||||
| 		return LuaValue.TRUE; | ||||
| 	} | ||||
|  | ||||
| 	private static Varargs errorresult(Exception ioe) { | ||||
| 		String s = ioe.getMessage();		 | ||||
| 		return errorresult("io error: "+(s!=null? s: ioe.toString())); | ||||
| 	} | ||||
| 	 | ||||
| 	private static Varargs errorresult(String errortext) { | ||||
| 		return varargsOf(NIL, valueOf(errortext)); | ||||
| 	} | ||||
|  | ||||
| 	private Varargs lines(final File f) { | ||||
| 		try { | ||||
| 			return new IoLibV(f,"lnext",LINES_ITER,this); | ||||
| 		} catch ( Exception e ) { | ||||
| 			return error("lines: "+e); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	private static Varargs iowrite(File f, Varargs args) throws IOException { | ||||
| 		for ( int i=1, n=args.narg(); i<=n; i++ ) | ||||
| 			f.write( args.checkstring(i) ); | ||||
| 		return LuaValue.TRUE; | ||||
| 	} | ||||
|  | ||||
| 	private Varargs ioread(File f, Varargs args) throws IOException { | ||||
| 		int i,n=args.narg(); | ||||
| 		LuaValue[] v = new LuaValue[n]; | ||||
| 		LuaValue ai,vi; | ||||
| 		LuaString fmt; | ||||
| 		for ( i=0; i<n; ) { | ||||
| 			item: switch ( (ai = args.arg(i+1)).type() ) { | ||||
| 				case LuaValue.TNUMBER: | ||||
| 					vi = freadbytes(f,ai.toint()); | ||||
| 					break item; | ||||
| 				case LuaValue.TSTRING: | ||||
| 					fmt = ai.checkstring(); | ||||
| 					if ( fmt.m_length == 2 && fmt.m_bytes[fmt.m_offset] == '*' ) { | ||||
| 						switch ( fmt.m_bytes[fmt.m_offset+1] ) { | ||||
| 						case 'n': vi = freadnumber(f); break item; | ||||
| 						case 'l': vi = freadline(f); break item; | ||||
| 						case 'a': vi = freadall(f); break item; | ||||
| 						} | ||||
| 					} | ||||
| 				default:  | ||||
| 					return argerror( i+1, "(invalid format)" );  | ||||
| 			} | ||||
| 			if ( (v[i++] = vi).isnil() ) | ||||
| 				break; | ||||
| 		} | ||||
| 		return i==0? NIL: varargsOf(v, 0, i); | ||||
| 	} | ||||
|  | ||||
| 	private static File checkfile(LuaValue val) { | ||||
| 		File f = optfile(val); | ||||
| 		if ( f == null ) | ||||
| 			argerror(1,"file"); | ||||
| 		checkopen( f ); | ||||
| 		return f; | ||||
| 	} | ||||
| 	 | ||||
| 	private static File optfile(LuaValue val) { | ||||
| 		return (val instanceof File)? (File) val: null; | ||||
| 	} | ||||
| 	 | ||||
| 	private static File checkopen(File file) { | ||||
| 		if ( file.isclosed() ) | ||||
| 			error("attempt to use a closed file"); | ||||
| 		return file; | ||||
| 	} | ||||
| 	 | ||||
| 	private File rawopenfile(String filename, String mode) throws IOException { | ||||
| 		boolean isstdfile = "-".equals(filename); | ||||
| 		boolean isreadmode = mode.startsWith("r"); | ||||
| 		if ( isstdfile ) { | ||||
| 			return isreadmode?  | ||||
| 				wrapStdin(): | ||||
| 				wrapStdout(); | ||||
| 		} | ||||
| 		boolean isappend = mode.startsWith("a"); | ||||
| 		boolean isupdate = mode.indexOf("+") > 0; | ||||
| 		boolean isbinary = mode.endsWith("b"); | ||||
| 		return openFile( filename, isreadmode, isappend, isupdate, isbinary ); | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	// ------------- file reading utilitied ------------------ | ||||
| 	 | ||||
| 	public static LuaValue freadbytes(File f, int count) throws IOException { | ||||
| 		byte[] b = new byte[count]; | ||||
| 		int r; | ||||
| 		if ( ( r = f.read(b,0,b.length) ) < 0 ) | ||||
| 			return NIL; | ||||
| 		return LuaString.valueOf(b, 0, r); | ||||
| 	} | ||||
| 	public static LuaValue freaduntil(File f,boolean lineonly) throws IOException { | ||||
| 		ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||||
| 		int c; | ||||
| 		try { | ||||
| 			if ( lineonly ) { | ||||
| 				loop: while ( (c = f.read()) > 0 ) {  | ||||
| 					switch ( c ) { | ||||
| 					case '\r': break; | ||||
| 					case '\n': break loop; | ||||
| 					default: baos.write(c); break; | ||||
| 					} | ||||
| 				} | ||||
| 			} else { | ||||
| 				while ( (c = f.read()) > 0 )  | ||||
| 					baos.write(c); | ||||
| 			} | ||||
| 		} catch ( EOFException e ) { | ||||
| 			c = -1; | ||||
| 		} | ||||
| 		return ( c < 0 && baos.size() == 0 )?  | ||||
| 			(LuaValue) NIL: | ||||
| 			(LuaValue) LuaString.valueOf(baos.toByteArray()); | ||||
| 	} | ||||
| 	public static LuaValue freadline(File f) throws IOException { | ||||
| 		return freaduntil(f,true); | ||||
| 	} | ||||
| 	public static LuaValue freadall(File f) throws IOException { | ||||
| 		int n = f.remaining(); | ||||
| 		if ( n >= 0 ) { | ||||
| 			return freadbytes(f, n); | ||||
| 		} else { | ||||
| 			return freaduntil(f,false); | ||||
| 		} | ||||
| 	} | ||||
| 	public static LuaValue freadnumber(File f) throws IOException { | ||||
| 		ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||||
| 		freadchars(f," \t\r\n",null); | ||||
| 		freadchars(f,"-+",baos); | ||||
| 		//freadchars(f,"0",baos); | ||||
| 		//freadchars(f,"xX",baos); | ||||
| 		freadchars(f,"0123456789",baos); | ||||
| 		freadchars(f,".",baos); | ||||
| 		freadchars(f,"0123456789",baos); | ||||
| 		//freadchars(f,"eEfFgG",baos); | ||||
| 		// freadchars(f,"+-",baos); | ||||
| 		//freadchars(f,"0123456789",baos); | ||||
| 		String s = baos.toString(); | ||||
| 		return s.length()>0? valueOf( Double.parseDouble(s) ): NIL; | ||||
| 	} | ||||
| 	private static void freadchars(File f, String chars, ByteArrayOutputStream baos) throws IOException { | ||||
| 		int c; | ||||
| 		while ( true ) { | ||||
| 			c = f.peek(); | ||||
| 			if ( chars.indexOf(c) < 0 ) { | ||||
| 				return; | ||||
| 			} | ||||
| 			f.read(); | ||||
| 			if ( baos != null ) | ||||
| 				baos.write( c ); | ||||
| 		} | ||||
| 	}		 | ||||
| 	 | ||||
| 	 | ||||
| 	 | ||||
| } | ||||
| @@ -1,200 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.lib; | ||||
|  | ||||
| import org.luaj.vm2.LuaError; | ||||
| import org.luaj.vm2.LuaFunction; | ||||
| import org.luaj.vm2.LuaValue; | ||||
|  | ||||
| /** | ||||
|  * Subclass of {@link LuaFunction} common to Java functions exposed to lua.  | ||||
|  * <p> | ||||
|  * To provide for common implementations in JME and JSE,  | ||||
|  * library functions are typically grouped on one or more library classes | ||||
|  * and an opcode per library function is defined and used to key the switch | ||||
|  * to the correct function within the library.   | ||||
|  * <p> | ||||
|  * Since lua functions can be called with too few or too many arguments,  | ||||
|  * and there are overloaded {@link LuaValue#call()} functions with varying  | ||||
|  * number of arguments, a Java function exposed in lua needs to handle  the | ||||
|  * argument fixup when a function is called with a number of arguments  | ||||
|  * differs from that expected.   | ||||
|  * <p> | ||||
|  * To simplify the creation of library functions,  | ||||
|  * there are 5 direct subclasses to handle common cases based on number of  | ||||
|  * argument values and number of return return values. | ||||
|  * <ul> | ||||
|  * <li>{@link ZeroArgFunction}</li> | ||||
|  * <li>{@link OneArgFunction}</li> | ||||
|  * <li>{@link TwoArgFunction}</li> | ||||
|  * <li>{@link ThreeArgFunction}</li> | ||||
|  * <li>{@link VarArgFunction}</li> | ||||
|  * </ul> | ||||
|  * <p> | ||||
|  * To be a Java library that can be loaded via {@code require}, it should have  | ||||
|  * a public constructor that returns a {@link LuaValue} that, when executed,  | ||||
|  * initializes the library.  | ||||
|  * <p>  | ||||
|  * For example, the following code will implement a library called "hyperbolic"  | ||||
|  * with two functions, "sinh", and "cosh": | ||||
|  <pre> {@code  | ||||
|  * import org.luaj.vm2.LuaValue; | ||||
|  * import org.luaj.vm2.lib.OneArgFunction; | ||||
|  *  | ||||
|  * public class hyperbolic extends OneArgFunction { | ||||
|  * | ||||
|  *	public hyperbolic() {} | ||||
|  * | ||||
|  *	public LuaValue call(LuaValue libname) { | ||||
|  *		LuaValue library = tableOf(); | ||||
|  *		library.set( "sinh", new sinh() ); | ||||
|  *		library.set( "cosh", new cosh() ); | ||||
|  *		env.set( "hyperbolic", library ); | ||||
|  *		return library; | ||||
|  *	} | ||||
|  * | ||||
|  *	static class sinh extends OneArgFunction { | ||||
|  *		public LuaValue call(LuaValue x) { | ||||
|  *			return LuaValue.valueOf(Math.sinh(x.checkdouble())); | ||||
|  *		} | ||||
|  *	} | ||||
|  *	 | ||||
|  *	static class cosh extends OneArgFunction { | ||||
|  *		public LuaValue call(LuaValue x) { | ||||
|  *			return LuaValue.valueOf(Math.cosh(x.checkdouble())); | ||||
|  *		} | ||||
|  *	} | ||||
|  *} | ||||
|  *}</pre> | ||||
|  * The default constructor is used to instantiate the library  | ||||
|  * in response to {@code require 'hyperbolic'} statement, | ||||
|  * provided it is on Javas class path.  | ||||
|  * This instance is then invoked with the name supplied to require()  | ||||
|  * as the only argument, and library should initialized whatever global | ||||
|  * data it needs to and place it into the environment if needed. | ||||
|  * In this case, it creates two function, 'sinh', and 'cosh', and puts  | ||||
|  * them into a global table called 'hyperbolic.' | ||||
|  * It placed the library table into the globals via the {@link #env}  | ||||
|  * local variable which corresponds to the globals that apply when the | ||||
|  * library is loaded. | ||||
|  * <p> | ||||
|  * To test it, a script such as this can be used: | ||||
|  * <pre> {@code | ||||
|  * local t = require('hyperbolic') | ||||
|  * print( 't', t ) | ||||
|  * print( 'hyperbolic', hyperbolic ) | ||||
|  * for k,v in pairs(t) do | ||||
|  * 	print( 'k,v', k,v ) | ||||
|  * end | ||||
|  * print( 'sinh(.5)', hyperbolic.sinh(.5) ) | ||||
|  * print( 'cosh(.5)', hyperbolic.cosh(.5) ) | ||||
|  * }</pre>  | ||||
|  * <p> | ||||
|  * It should produce something like: | ||||
|  * <pre> {@code | ||||
|  * t	table: 3dbbd23f | ||||
|  * hyperbolic	table: 3dbbd23f | ||||
|  * k,v	cosh	function: 3dbbd128 | ||||
|  * k,v	sinh	function: 3dbbd242 | ||||
|  * sinh(.5)	0.5210953 | ||||
|  * cosh(.5)	1.127626 | ||||
|  * }</pre>  | ||||
|  * <p>  | ||||
|  * See the source code in any of the library functions  | ||||
|  * such as {@link BaseLib} or {@link TableLib} for other examples.   | ||||
|  */ | ||||
| abstract public class LibFunction extends LuaFunction { | ||||
| 	 | ||||
| 	/** User-defined opcode to differentiate between instances of the library function class.  | ||||
| 	 * <p> | ||||
| 	 * Subclass will typicall switch on this value to provide the specific behavior for each function.  | ||||
| 	 */ | ||||
| 	protected int opcode; | ||||
| 	 | ||||
| 	/** The common name for this function, useful for debugging. | ||||
| 	 * <p> | ||||
| 	 * Binding functions initialize this to the name to which it is bound. | ||||
| 	 */ | ||||
| 	protected String name; | ||||
| 	 | ||||
| 	/** Default constructor for use by subclasses */ | ||||
| 	protected LibFunction() {		 | ||||
| 	} | ||||
| 	 | ||||
| 	public String tojstring() { | ||||
| 		return name != null? name: super.tojstring(); | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Bind a set of library functions.   | ||||
| 	 * <p> | ||||
| 	 * An array of names is provided, and the first name is bound  | ||||
| 	 * with opcode = 0, second with 1, etc.  | ||||
| 	 * @param env The environment to apply to each bound function  | ||||
| 	 * @param factory the Class to instantiate for each bound function | ||||
| 	 * @param names array of String names, one for each function. | ||||
| 	 * @see #bind(LuaValue, Class, String[], int)   | ||||
| 	 */ | ||||
| 	protected void bind(LuaValue env, Class factory,  String[] names ) { | ||||
| 		bind( env, factory, names, 0 ); | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Bind a set of library functions, with an offset   | ||||
| 	 * <p> | ||||
| 	 * An array of names is provided, and the first name is bound  | ||||
| 	 * with opcode = {@code firstopcode}, second with {@code firstopcode+1}, etc.  | ||||
| 	 * @param env The environment to apply to each bound function  | ||||
| 	 * @param factory the Class to instantiate for each bound function | ||||
| 	 * @param names array of String names, one for each function. | ||||
| 	 * @param firstopcode the first opcode to use   | ||||
| 	 * @see #bind(LuaValue, Class, String[])   | ||||
| 	 */ | ||||
| 	protected void bind(LuaValue env, Class factory,  String[] names, int firstopcode ) { | ||||
| 		try { | ||||
| 			for ( int i=0, n=names.length; i<n; i++ ) { | ||||
| 				LibFunction f = (LibFunction) factory.newInstance(); | ||||
| 				f.opcode = firstopcode + i; | ||||
| 				f.name = names[i]; | ||||
| 				f.env = env; | ||||
| 				env.set(f.name, f); | ||||
| 			} | ||||
| 		} catch ( Exception e ) { | ||||
| 			throw new LuaError( "bind failed: "+e ); | ||||
| 		} | ||||
| 	}	 | ||||
|  | ||||
| 	/** Java code generation utility to allocate storage for upvalue, leave it empty */ | ||||
| 	protected static LuaValue[] newupe() { | ||||
| 		return new LuaValue[1]; | ||||
| 	} | ||||
|  | ||||
| 	/** Java code generation utility to allocate storage for upvalue, initialize with nil */ | ||||
| 	protected static LuaValue[] newupn() { | ||||
| 		return new LuaValue[] { NIL }; | ||||
| 	} | ||||
| 	 | ||||
| 	/** Java code generation utility to allocate storage for upvalue, initialize with value */ | ||||
| 	protected static LuaValue[] newupl(LuaValue v) { | ||||
| 		return new LuaValue[] { v }; | ||||
| 	} | ||||
| }  | ||||
| @@ -1,251 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.lib; | ||||
|  | ||||
| import java.util.Random; | ||||
|  | ||||
| import org.luaj.vm2.LuaDouble; | ||||
| import org.luaj.vm2.LuaTable; | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.Varargs; | ||||
|  | ||||
| /**  | ||||
|  * Subclass of {@link LibFunction} which implements the lua standard {@code math}  | ||||
|  * library.  | ||||
|  * <p>  | ||||
|  * It contains only the math library support that is possible on JME.   | ||||
|  * For a more complete implementation based on math functions specific to JSE  | ||||
|  * use {@link org.luaj.vm2.lib.jse.JseMathLib}.  | ||||
|  * In Particular the following math functions are <b>not</b> implemented by this library: | ||||
|  * <ul> | ||||
|  * <li>acos</li> | ||||
|  * <li>asin</li> | ||||
|  * <li>atan</li> | ||||
|  * <li>cosh</li> | ||||
|  * <li>log</li> | ||||
|  * <li>log10</li> | ||||
|  * <li>sinh</li> | ||||
|  * <li>tanh</li> | ||||
|  * <li>atan2</li> | ||||
|  * </ul> | ||||
|  * <p> | ||||
|  * The implementations of {@code exp()} and {@code pow()} are constructed by  | ||||
|  * hand for JME, so will be slower and less accurate than when executed on the JSE platform. | ||||
|  * <p>  | ||||
|  * Typically, this library is included as part of a call to either  | ||||
|  * {@link JmePlatform#standardGlobals()} | ||||
|  * <p> | ||||
|  * To instantiate and use it directly,  | ||||
|  * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: | ||||
|  * <pre> {@code | ||||
|  * LuaTable _G = new LuaTable(); | ||||
|  * LuaThread.setGlobals(_G); | ||||
|  * _G.load(new BaseLib()); | ||||
|  * _G.load(new PackageLib()); | ||||
|  * _G.load(new MathLib()); | ||||
|  * System.out.println( _G.get("math").get("sqrt").call( LuaValue.valueOf(2) ) ); | ||||
|  * } </pre> | ||||
|  * Doing so will ensure the library is properly initialized  | ||||
|  * and loaded into the globals table.  | ||||
|  * <p> | ||||
|  * This has been implemented to match as closely as possible the behavior in the corresponding library in C. | ||||
|  * @see LibFunction | ||||
|  * @see JsePlatform | ||||
|  * @see JmePlatform | ||||
|  * @see JseMathLib | ||||
|  * @see <a href="http://www.lua.org/manual/5.1/manual.html#5.6">http://www.lua.org/manual/5.1/manual.html#5.6</a> | ||||
|  */ | ||||
| public class MathLib extends OneArgFunction { | ||||
| 	 | ||||
| 	public static MathLib MATHLIB = null; | ||||
|  | ||||
| 	private Random random; | ||||
| 	 | ||||
| 	public MathLib() { | ||||
| 		MATHLIB = this; | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue call(LuaValue arg) { | ||||
| 		LuaTable t = new LuaTable(0,30); | ||||
| 		t.set( "pi", Math.PI ); | ||||
| 		t.set( "huge", LuaDouble.POSINF ); | ||||
| 		bind( t, MathLib1.class, new String[] { | ||||
| 			"abs", "ceil", "cos", "deg",  | ||||
| 			"exp", "floor", "rad", "sin",  | ||||
| 			"sqrt", "tan" } ); | ||||
| 		bind( t, MathLib2.class, new String[] { | ||||
| 			"fmod", "ldexp", "pow", } ); | ||||
| 		bind( t, MathLibV.class, new String[] { | ||||
| 			"frexp", "max", "min", "modf",  | ||||
| 			"randomseed", "random", } ); | ||||
| 		((MathLibV) t.get("randomseed")).mathlib = this; | ||||
| 		((MathLibV) t.get("random"    )).mathlib = this; | ||||
| 		env.set("math", t); | ||||
| 		PackageLib.instance.LOADED.set("math", t); | ||||
| 		return t; | ||||
| 	} | ||||
|  | ||||
| 	static final class MathLib1 extends OneArgFunction { | ||||
| 		public LuaValue call(LuaValue arg) { | ||||
| 			switch ( opcode ) { | ||||
| 			case 0: return valueOf(Math.abs(arg.checkdouble()));  | ||||
| 			case 1: return valueOf(Math.ceil(arg.checkdouble()));  | ||||
| 			case 2: return valueOf(Math.cos(arg.checkdouble()));  | ||||
| 			case 3: return valueOf(Math.toDegrees(arg.checkdouble()));  | ||||
| 			case 4: return dpow(Math.E,arg.checkdouble()); | ||||
| 			case 5: return valueOf(Math.floor(arg.checkdouble())); | ||||
| 			case 6: return valueOf(Math.toRadians(arg.checkdouble()));  | ||||
| 			case 7: return valueOf(Math.sin(arg.checkdouble()));  | ||||
| 			case 8: return valueOf(Math.sqrt(arg.checkdouble()));  | ||||
| 			case 9: return valueOf(Math.tan(arg.checkdouble()));  | ||||
| 			} | ||||
| 			return NIL; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	static final class MathLib2 extends TwoArgFunction { | ||||
| 		protected MathLib mathlib; | ||||
| 		public LuaValue call(LuaValue arg1, LuaValue arg2) { | ||||
| 			switch ( opcode ) { | ||||
| 			case 0: { // fmod | ||||
| 				double x = arg1.checkdouble(); | ||||
| 				double y = arg2.checkdouble(); | ||||
| 				double q = x/y; | ||||
| 				double f = x - y * (q>=0? Math.floor(q): Math.ceil(q)); | ||||
| 				return valueOf( f ); | ||||
| 			} | ||||
| 			case 1: { // ldexp | ||||
| 				double x = arg1.checkdouble(); | ||||
| 				double y = arg2.checkdouble()+1023.5; | ||||
| 				long e = (long) ((0!=(1&((int)y)))? Math.floor(y): Math.ceil(y-1)); | ||||
| 				return valueOf(x * Double.longBitsToDouble(e << 52)); | ||||
| 			} | ||||
| 			case 2: { // pow | ||||
| 				return dpow(arg1.checkdouble(), arg2.checkdouble()); | ||||
| 			} | ||||
| 			} | ||||
| 			return NIL; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** compute power using installed math library, or default if there is no math library installed */ | ||||
| 	public static LuaValue dpow(double a, double b) { | ||||
| 		return LuaDouble.valueOf(  | ||||
| 				MATHLIB!=null? | ||||
| 				MATHLIB.dpow_lib(a,b): | ||||
| 				dpow_default(a,b) ); | ||||
| 	} | ||||
| 	public static double dpow_d(double a, double b) { | ||||
| 		return MATHLIB!=null?  | ||||
| 				MATHLIB.dpow_lib(a,b):  | ||||
| 				dpow_default(a,b); | ||||
| 	} | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Hook to override default dpow behavior with faster implementation.   | ||||
| 	 */ | ||||
| 	public double dpow_lib(double a, double b) { | ||||
| 		return dpow_default(a,b); | ||||
| 	} | ||||
|  | ||||
| 	/**  | ||||
| 	 * Default JME version computes using longhand heuristics.  | ||||
| 	 */ | ||||
| 	protected static double dpow_default(double a, double b) { | ||||
| 		if ( b < 0 ) | ||||
| 			return 1 / dpow_default( a, -b ); | ||||
| 		double p = 1; | ||||
| 		int whole = (int) b; | ||||
| 		for ( double v=a; whole > 0; whole>>=1, v*=v ) | ||||
| 			if ( (whole & 1) != 0 ) | ||||
| 				p *= v; | ||||
| 		if ( (b -= whole) > 0 ) { | ||||
| 			int frac = (int) (0x10000 * b); | ||||
| 			for ( ; (frac&0xffff)!=0; frac<<=1 ) { | ||||
| 				a = Math.sqrt(a); | ||||
| 				if ( (frac & 0x8000) != 0 ) | ||||
| 					p *= a; | ||||
| 			} | ||||
| 		} | ||||
| 		return p; | ||||
| 	} | ||||
|  | ||||
| 	static final class MathLibV extends VarArgFunction { | ||||
| 		protected MathLib mathlib; | ||||
| 		public Varargs invoke(Varargs args) { | ||||
| 			switch ( opcode ) { | ||||
| 			case 0: { // frexp | ||||
| 				double x = args.checkdouble(1); | ||||
| 				if ( x == 0 ) return varargsOf(ZERO,ZERO); | ||||
| 				long bits = Double.doubleToLongBits( x ); | ||||
| 				double m = ((bits & (~(-1L<<52))) + (1L<<52)) * ((bits >= 0)? (.5 / (1L<<52)): (-.5 / (1L<<52))); | ||||
| 				double e = (((int) (bits >> 52)) & 0x7ff) - 1022; | ||||
| 				return varargsOf( valueOf(m), valueOf(e) ); | ||||
| 			} | ||||
| 			case 1: { // max | ||||
| 				double m = args.checkdouble(1); | ||||
| 				for ( int i=2,n=args.narg(); i<=n; ++i ) | ||||
| 					m = Math.max(m,args.checkdouble(i)); | ||||
| 				return valueOf(m); | ||||
| 			} | ||||
| 			case 2: { // min | ||||
| 				double m = args.checkdouble(1); | ||||
| 				for ( int i=2,n=args.narg(); i<=n; ++i ) | ||||
| 					m = Math.min(m,args.checkdouble(i)); | ||||
| 				return valueOf(m); | ||||
| 			} | ||||
| 			case 3: { // modf | ||||
| 				double x = args.checkdouble(1); | ||||
| 				double intPart = ( x > 0 ) ? Math.floor( x ) : Math.ceil( x ); | ||||
| 				double fracPart = x - intPart; | ||||
| 				return varargsOf( valueOf(intPart), valueOf(fracPart) ); | ||||
| 			} | ||||
| 			case 4: { // randomseed  | ||||
| 				long seed = args.checklong(1); | ||||
| 				mathlib.random = new Random(seed); | ||||
| 				return NONE; | ||||
| 			} | ||||
| 			case 5: { // random | ||||
| 				if ( mathlib.random == null ) | ||||
| 					mathlib.random = new Random(); | ||||
| 				 | ||||
| 				switch ( args.narg() ) { | ||||
| 				case 0: | ||||
| 					return valueOf( mathlib.random.nextDouble() ); | ||||
| 				case 1: { | ||||
| 					int m = args.checkint(1); | ||||
| 					if (m<1) argerror(1, "interval is empty"); | ||||
| 					return valueOf( 1 + mathlib.random.nextInt(m) ); | ||||
| 				} | ||||
| 				default: { | ||||
| 					int m = args.checkint(1); | ||||
| 					int n = args.checkint(2); | ||||
| 					if (n<m) argerror(2, "interval is empty"); | ||||
| 					return valueOf( m + mathlib.random.nextInt(n+1-m) ); | ||||
| 				} | ||||
| 				} | ||||
| 			} | ||||
| 			} | ||||
| 			return NONE; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,79 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.lib; | ||||
|  | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.Varargs; | ||||
|  | ||||
| /** Abstract base class for Java function implementations that take one argument and  | ||||
|  * return one value.  | ||||
|  * <p> | ||||
|  * Subclasses need only implement {@link LuaValue#call(LuaValue)} to complete this class,  | ||||
|  * simplifying development.   | ||||
|  * All other uses of {@link #call()}, {@link #invoke(Varargs)},etc,  | ||||
|  * are routed through this method by this class,  | ||||
|  * dropping or extending arguments with {@code nil} values as required. | ||||
|  * <p> | ||||
|  * If more than one argument are required, or no arguments are required,  | ||||
|  * or variable argument or variable return values,  | ||||
|  * then use one of the related function | ||||
|  * {@link ZeroArgFunction}, {@link TwoArgFunction}, {@link ThreeArgFunction}, or {@link VarArgFunction}. | ||||
|  * <p> | ||||
|  * See {@link LibFunction} for more information on implementation libraries and library functions. | ||||
|  * @see #call(LuaValue) | ||||
|  * @see LibFunction | ||||
|  * @see ZeroArgFunction | ||||
|  * @see TwoArgFunction | ||||
|  * @see ThreeArgFunction | ||||
|  * @see VarArgFunction | ||||
|  */ | ||||
| abstract public class OneArgFunction extends LibFunction { | ||||
|  | ||||
| 	abstract public LuaValue call(LuaValue arg); | ||||
| 	 | ||||
| 	/** Default constructor */ | ||||
| 	public OneArgFunction() { | ||||
| 	} | ||||
| 	 | ||||
| 	/** Constructor with specific environment | ||||
| 	 * @param env The environment to apply during constructon. | ||||
| 	 */ | ||||
| 	public OneArgFunction( LuaValue env ) { | ||||
| 		this.env = env; | ||||
| 	} | ||||
| 	 | ||||
| 	public final LuaValue call() { | ||||
| 		return call(NIL); | ||||
| 	} | ||||
|  | ||||
| 	public final LuaValue call(LuaValue arg1, LuaValue arg2) { | ||||
| 		return call(arg1); | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { | ||||
| 		return call(arg1); | ||||
| 	} | ||||
|  | ||||
| 	public Varargs invoke(Varargs varargs) { | ||||
| 		return call(varargs.arg1()); | ||||
| 	} | ||||
| }  | ||||
| @@ -1,323 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.lib; | ||||
|  | ||||
| import java.io.IOException; | ||||
|  | ||||
| import org.luaj.vm2.LuaTable; | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.Varargs; | ||||
|  | ||||
| /** | ||||
|  * Subclass of {@link LibFunction} which implements the standard lua {@code os} library. | ||||
|  * <p> | ||||
|  * It is a usable base with simplified stub functions | ||||
|  * for library functions that cannot be implemented uniformly  | ||||
|  * on Jse and Jme.    | ||||
|  * <p> | ||||
|  * This can be installed as-is on either platform, or extended  | ||||
|  * and refined to be used in a complete Jse implementation. | ||||
|  * <p> | ||||
|  * Because the nature of the {@code os} library is to encapsulate  | ||||
|  * os-specific features, the behavior of these functions varies considerably  | ||||
|  * from their counterparts in the C platform.   | ||||
|  * <p> | ||||
|  * The following functions have limited implementations of features  | ||||
|  * that are not supported well on Jme: | ||||
|  * <ul> | ||||
|  * <li>{@code execute()}</li> | ||||
|  * <li>{@code remove()}</li> | ||||
|  * <li>{@code rename()}</li> | ||||
|  * <li>{@code tmpname()}</li> | ||||
|  * </ul> | ||||
|  * <p> | ||||
|  * Typically, this library is included as part of a call to either  | ||||
|  * {@link JmePlatform#standardGlobals()} | ||||
|  * <p> | ||||
|  * To instantiate and use it directly,  | ||||
|  * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: | ||||
|  * <pre> {@code | ||||
|  * LuaTable _G = new LuaTable(); | ||||
|  * LuaThread.setGlobals(_G); | ||||
|  * _G.load(new BaseLib()); | ||||
|  * _G.load(new PackageLib()); | ||||
|  * _G.load(new OsLib()); | ||||
|  * System.out.println( _G.get("os").get("time").call() ); | ||||
|  * } </pre> | ||||
|  * Doing so will ensure the library is properly initialized  | ||||
|  * and loaded into the globals table.  | ||||
|  * <p> | ||||
|   * @see LibFunction | ||||
|  * @see JseOsLib | ||||
|  * @see JsePlatform | ||||
|  * @see JmePlatform | ||||
|  * @see <a href="http://www.lua.org/manual/5.1/manual.html#5.8">http://www.lua.org/manual/5.1/manual.html#5.8</a> | ||||
|  */ | ||||
| public class OsLib extends VarArgFunction { | ||||
| 	public static String TMP_PREFIX    = ".luaj"; | ||||
| 	public static String TMP_SUFFIX    = "tmp"; | ||||
|  | ||||
| 	private static final int INIT      = 0; | ||||
| 	private static final int CLOCK     = 1; | ||||
| 	private static final int DATE      = 2; | ||||
| 	private static final int DIFFTIME  = 3; | ||||
| 	private static final int EXECUTE   = 4; | ||||
| 	private static final int EXIT      = 5; | ||||
| 	private static final int GETENV    = 6; | ||||
| 	private static final int REMOVE    = 7; | ||||
| 	private static final int RENAME    = 8; | ||||
| 	private static final int SETLOCALE = 9; | ||||
| 	private static final int TIME      = 10; | ||||
| 	private static final int TMPNAME   = 11; | ||||
|  | ||||
| 	private static final String[] NAMES = { | ||||
| 		"clock", | ||||
| 		"date", | ||||
| 		"difftime", | ||||
| 		"execute", | ||||
| 		"exit", | ||||
| 		"getenv", | ||||
| 		"remove", | ||||
| 		"rename", | ||||
| 		"setlocale", | ||||
| 		"time", | ||||
| 		"tmpname", | ||||
| 	}; | ||||
| 	 | ||||
| 	private static final long t0 = System.currentTimeMillis(); | ||||
| 	private static long tmpnames = t0; | ||||
|  | ||||
| 	/**  | ||||
| 	 * Create and OsLib instance.    | ||||
| 	 */ | ||||
| 	public OsLib() { | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue init() { | ||||
| 		LuaTable t = new LuaTable(); | ||||
| 		bind(t, this.getClass(), NAMES, CLOCK); | ||||
| 		env.set("os", t); | ||||
| 		PackageLib.instance.LOADED.set("os", t); | ||||
| 		return t; | ||||
| 	} | ||||
|  | ||||
| 	public Varargs invoke(Varargs args) { | ||||
| 		try { | ||||
| 			switch ( opcode ) { | ||||
| 			case INIT:  | ||||
| 				return init(); | ||||
| 			case CLOCK: | ||||
| 				return valueOf(clock()); | ||||
| 			case DATE: { | ||||
| 				String s = args.optjstring(1, null); | ||||
| 				double t = args.optdouble(2,-1); | ||||
| 				return valueOf( date(s, t==-1? System.currentTimeMillis()/1000.: t) ); | ||||
| 			} | ||||
| 			case DIFFTIME: | ||||
| 				return valueOf(difftime(args.checkdouble(1),args.checkdouble(2))); | ||||
| 			case EXECUTE: | ||||
| 				return valueOf(execute(args.optjstring(1, null))); | ||||
| 			case EXIT: | ||||
| 				exit(args.optint(1, 0)); | ||||
| 				return NONE; | ||||
| 			case GETENV: { | ||||
| 				final String val = getenv(args.checkjstring(1)); | ||||
| 				return val!=null? valueOf(val): NIL; | ||||
| 			} | ||||
| 			case REMOVE: | ||||
| 				remove(args.checkjstring(1)); | ||||
| 				return LuaValue.TRUE; | ||||
| 			case RENAME: | ||||
| 				rename(args.checkjstring(1), args.checkjstring(2)); | ||||
| 				return LuaValue.TRUE; | ||||
| 			case SETLOCALE: { | ||||
| 				String s = setlocale(args.optjstring(1,null), args.optjstring(2, "all")); | ||||
| 				return s!=null? valueOf(s): NIL; | ||||
| 			} | ||||
| 			case TIME: | ||||
| 				return valueOf(time(args.arg1().isnil()? null: args.checktable(1))); | ||||
| 			case TMPNAME: | ||||
| 				return valueOf(tmpname()); | ||||
| 			} | ||||
| 			return NONE; | ||||
| 		} catch ( IOException e ) { | ||||
| 			return varargsOf(NIL, valueOf(e.getMessage())); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return an approximation of the amount in seconds of CPU time used by  | ||||
| 	 * the program. | ||||
| 	 */ | ||||
| 	protected double clock() { | ||||
| 		return (System.currentTimeMillis()-t0) / 1000.; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Returns the number of seconds from time t1 to time t2.  | ||||
| 	 * In POSIX, Windows, and some other systems, this value is exactly t2-t1. | ||||
| 	 * @param t2 | ||||
| 	 * @param t1 | ||||
| 	 * @return diffeence in time values, in seconds | ||||
| 	 */ | ||||
| 	protected double difftime(double t2, double t1) { | ||||
| 		return t2 - t1; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * If the time argument is present, this is the time to be formatted  | ||||
| 	 * (see the os.time function for a description of this value).  | ||||
| 	 * Otherwise, date formats the current time. | ||||
| 	 *  | ||||
| 	 * If format starts with '!', then the date is formatted in Coordinated  | ||||
| 	 * Universal Time. After this optional character, if format is the string  | ||||
| 	 * "*t", then date returns a table with the following fields: year  | ||||
| 	 * (four digits), month (1--12), day (1--31), hour (0--23), min (0--59),  | ||||
| 	 * sec (0--61), wday (weekday, Sunday is 1), yday (day of the year),  | ||||
| 	 * and isdst (daylight saving flag, a boolean). | ||||
| 	 *  | ||||
| 	 * If format is not "*t", then date returns the date as a string,  | ||||
| 	 * formatted according to the same rules as the C function strftime. | ||||
| 	 *  | ||||
| 	 * When called without arguments, date returns a reasonable date and  | ||||
| 	 * time representation that depends on the host system and on the  | ||||
| 	 * current locale (that is, os.date() is equivalent to os.date("%c")). | ||||
| 	 *   | ||||
| 	 * @param format  | ||||
| 	 * @param time time since epoch, or -1 if not supplied | ||||
| 	 * @return a LString or a LTable containing date and time,  | ||||
| 	 * formatted according to the given string format. | ||||
| 	 */ | ||||
| 	protected String date(String format, double time) { | ||||
| 		return new java.util.Date((long)(time*1000)).toString(); | ||||
| 	} | ||||
|  | ||||
| 	/**  | ||||
| 	 * This function is equivalent to the C function system.  | ||||
| 	 * It passes command to be executed by an operating system shell.  | ||||
| 	 * It returns a status code, which is system-dependent.  | ||||
| 	 * If command is absent, then it returns nonzero if a shell  | ||||
| 	 * is available and zero otherwise. | ||||
| 	 * @param command command to pass to the system | ||||
| 	 */  | ||||
| 	protected int execute(String command) { | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Calls the C function exit, with an optional code, to terminate the host program.  | ||||
| 	 * @param code | ||||
| 	 */ | ||||
| 	protected void exit(int code) { | ||||
| 		/* DAN200 START */ | ||||
| 		//System.exit(code); | ||||
| 		/* DAN200 END */ | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Returns the value of the process environment variable varname,  | ||||
| 	 * or null if the variable is not defined.  | ||||
| 	 * @param varname | ||||
| 	 * @return String value, or null if not defined | ||||
| 	 */ | ||||
| 	protected String getenv(String varname) { | ||||
| 		return System.getProperty(varname); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Deletes the file or directory with the given name.  | ||||
| 	 * Directories must be empty to be removed.  | ||||
| 	 * If this function fails, it throws and IOException | ||||
| 	 *   | ||||
| 	 * @param filename | ||||
| 	 * @throws IOException if it fails | ||||
| 	 */ | ||||
| 	protected void remove(String filename) throws IOException { | ||||
| 		throw new IOException( "not implemented" ); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Renames file or directory named oldname to newname.  | ||||
| 	 * If this function fails,it throws and IOException | ||||
| 	 *   | ||||
| 	 * @param oldname old file name | ||||
| 	 * @param newname new file name | ||||
| 	 * @throws IOException if it fails | ||||
| 	 */ | ||||
| 	protected void rename(String oldname, String newname) throws IOException { | ||||
| 		throw new IOException( "not implemented" ); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Sets the current locale of the program. locale is a string specifying  | ||||
| 	 * a locale; category is an optional string describing which category to change:  | ||||
| 	 * "all", "collate", "ctype", "monetary", "numeric", or "time"; the default category  | ||||
| 	 * is "all".  | ||||
| 	 *  | ||||
| 	 * If locale is the empty string, the current locale is set to an implementation- | ||||
| 	 * defined native locale. If locale is the string "C", the current locale is set  | ||||
| 	 * to the standard C locale. | ||||
| 	 *  | ||||
| 	 * When called with null as the first argument, this function only returns the  | ||||
| 	 * name of the current locale for the given category. | ||||
| 	 *   | ||||
| 	 * @param locale | ||||
| 	 * @param category | ||||
| 	 * @return the name of the new locale, or null if the request  | ||||
| 	 * cannot be honored. | ||||
| 	 */ | ||||
| 	protected String setlocale(String locale, String category) { | ||||
| 		return "C"; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Returns the current time when called without arguments,  | ||||
| 	 * or a time representing the date and time specified by the given table.  | ||||
| 	 * This table must have fields year, month, and day,  | ||||
| 	 * and may have fields hour, min, sec, and isdst  | ||||
| 	 * (for a description of these fields, see the os.date function). | ||||
| 	 * @param table | ||||
| 	 * @return long value for the time | ||||
| 	 */ | ||||
| 	protected long time(LuaTable table) { | ||||
| 		return System.currentTimeMillis(); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Returns a string with a file name that can be used for a temporary file.  | ||||
| 	 * The file must be explicitly opened before its use and explicitly removed  | ||||
| 	 * when no longer needed. | ||||
| 	 *  | ||||
| 	 * On some systems (POSIX), this function also creates a file with that name,  | ||||
| 	 * to avoid security risks. (Someone else might create the file with wrong  | ||||
| 	 * permissions in the time between getting the name and creating the file.)  | ||||
| 	 * You still have to open the file to use it and to remove it (even if you  | ||||
| 	 * do not use it).  | ||||
| 	 *  | ||||
| 	 * @return String filename to use | ||||
| 	 */ | ||||
| 	protected String tmpname() { | ||||
| 		synchronized ( OsLib.class ) { | ||||
| 			return TMP_PREFIX+(tmpnames++)+TMP_SUFFIX; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,466 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2010-2011 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.lib; | ||||
|  | ||||
| import java.io.InputStream; | ||||
| import java.io.PrintStream; | ||||
|  | ||||
| import org.luaj.vm2.LuaFunction; | ||||
| import org.luaj.vm2.LuaString; | ||||
| import org.luaj.vm2.LuaTable; | ||||
| import org.luaj.vm2.LuaThread; | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.Varargs; | ||||
|  | ||||
| /**  | ||||
|  * Subclass of {@link LibFunction} which implements the lua standard package and module  | ||||
|  * library functions.  | ||||
|  *  | ||||
|  * <p> | ||||
|  * Typically, this library is included as part of a call to either  | ||||
|  * {@link JsePlatform#standardGlobals()} or {@link JmePlatform#standardGlobals()} | ||||
|  * <p> | ||||
|  * To instantiate and use it directly,  | ||||
|  * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: | ||||
|  * <pre> {@code | ||||
|  * LuaTable _G = new LuaTable(); | ||||
|  * LuaThread.setGlobals(_G); | ||||
|  * _G.load(new BaseLib()); | ||||
|  * _G.load(new PackageLib()); | ||||
|  * System.out.println( _G.get("require").call(LuaValue.valueOf("hyperbolic")) ); | ||||
|  * } </pre> | ||||
|  * In practice, the first 4 lines of the above are minimal requirements to get  | ||||
|  * and initialize a globals table capable of basic reqire, print, and other functions,  | ||||
|  * so it is much more convenient to use the {@link JsePlatform} and {@link JmePlatform}  | ||||
|  * utility classes instead.   | ||||
|  * <p> | ||||
|  * This has been implemented to match as closely as possible the behavior in the corresponding library in C. | ||||
|  * However, the default filesystem search semantics are different and delegated to the bas library  | ||||
|  * as outlined in the {@link BaseLib} and {@link JseBaseLib} documetnation.  | ||||
|  * @see LibFunction | ||||
|  * @see BaseLib | ||||
|  * @see JseBaseLib | ||||
|  * @see JsePlatform | ||||
|  * @see JmePlatform | ||||
|  * @see <a href="http://www.lua.org/manual/5.1/manual.html#5.3">http://www.lua.org/manual/5.1/manual.html#5.3</a> | ||||
|  */ | ||||
| public class PackageLib extends OneArgFunction { | ||||
|  | ||||
| 	public static String DEFAULT_LUA_PATH = "?.lua"; | ||||
|  | ||||
| 	public InputStream    STDIN   = null; | ||||
| 	public PrintStream    STDOUT  = System.out; | ||||
| 	public LuaTable       LOADED; | ||||
| 	public LuaTable       PACKAGE; | ||||
|  | ||||
| 	/** Most recent instance of PackageLib */ | ||||
| 	public static PackageLib instance; | ||||
| 	 | ||||
| 	/** Loader that loads from preload table if found there */ | ||||
| 	public LuaValue preload_loader; | ||||
| 	 | ||||
| 	/** Loader that loads as a lua script using the LUA_PATH */ | ||||
| 	public LuaValue lua_loader; | ||||
| 	 | ||||
| 	/** Loader that loads as a Java class.  Class must have public constructor and be a LuaValue */ | ||||
| 	public LuaValue java_loader; | ||||
| 	 | ||||
| 	private static final LuaString _M         = valueOf("_M"); | ||||
| 	private static final LuaString _NAME      = valueOf("_NAME");	 | ||||
| 	private static final LuaString _PACKAGE   = valueOf("_PACKAGE");	 | ||||
| 	private static final LuaString _DOT       = valueOf("."); | ||||
| 	private static final LuaString _LOADERS   = valueOf("loaders"); | ||||
| 	private static final LuaString _LOADED    = valueOf("loaded"); | ||||
| 	private static final LuaString _LOADLIB   = valueOf("loadlib"); | ||||
| 	private static final LuaString _PRELOAD   = valueOf("preload"); | ||||
| 	private static final LuaString _PATH      = valueOf("path"); | ||||
| 	private static final LuaString _SEEALL    = valueOf("seeall"); | ||||
| 	private static final LuaString _SENTINEL  = valueOf("\u0001"); | ||||
| 	 | ||||
| 	private static final int OP_MODULE         = 0; | ||||
| 	private static final int OP_REQUIRE        = 1; | ||||
| 	private static final int OP_LOADLIB        = 2; | ||||
| 	private static final int OP_SEEALL         = 3; | ||||
| 	private static final int OP_PRELOAD_LOADER = 4; | ||||
| 	private static final int OP_LUA_LOADER     = 5; | ||||
| 	private static final int OP_JAVA_LOADER    = 6; | ||||
| 	 | ||||
| 	public PackageLib() { | ||||
| 		instance = this; | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue call(LuaValue arg) { | ||||
| 		env.set("require", new PkgLib1(env,"require",OP_REQUIRE,this)); | ||||
| 		env.set("module",  new PkgLibV(env,"module",OP_MODULE,this)); | ||||
| 		env.set( "package", PACKAGE=tableOf( new LuaValue[] { | ||||
| 				_LOADED,  LOADED=tableOf(), | ||||
| 				_PRELOAD, tableOf(), | ||||
| 				_PATH,    valueOf(DEFAULT_LUA_PATH), | ||||
| 				_LOADLIB, new PkgLibV(env,"loadlib",OP_LOADLIB,this), | ||||
| 				_SEEALL,  new PkgLib1(env,"seeall",OP_SEEALL,this), | ||||
| 				_LOADERS, listOf(new LuaValue[] { | ||||
| 						preload_loader = new PkgLibV(env,"preload_loader", OP_PRELOAD_LOADER,this), | ||||
| 						lua_loader     = new PkgLibV(env,"lua_loader", OP_LUA_LOADER,this), | ||||
| 						java_loader    = new PkgLibV(env,"java_loader", OP_JAVA_LOADER,this), | ||||
| 				}) }) ); | ||||
| 		LOADED.set("package", PACKAGE); | ||||
| 		return env; | ||||
| 	} | ||||
|  | ||||
| 	static final class PkgLib1 extends OneArgFunction { | ||||
| 		PackageLib lib; | ||||
| 		public PkgLib1(LuaValue env,String name, int opcode, PackageLib lib) { | ||||
| 			this.env = env; | ||||
| 			this.name = name; | ||||
| 			this.opcode = opcode; | ||||
| 			this.lib = lib; | ||||
| 		} | ||||
| 		public LuaValue call(LuaValue arg) { | ||||
| 			switch ( opcode ) { | ||||
| 			case OP_REQUIRE:  | ||||
| 				return lib.require(arg); | ||||
| 			case OP_SEEALL: {  | ||||
| 				LuaTable t = arg.checktable(); | ||||
| 				LuaValue m = t.getmetatable(); | ||||
| 				if ( m == null ) | ||||
| 					t.setmetatable(m=tableOf()); | ||||
| 				m.set( INDEX, LuaThread.getGlobals() ); | ||||
| 				return NONE; | ||||
| 			} | ||||
| 			} | ||||
| 			return NIL; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	static final class PkgLibV extends VarArgFunction { | ||||
| 		PackageLib lib; | ||||
| 		public PkgLibV(LuaValue env,String name, int opcode, PackageLib lib) { | ||||
| 			this.env = env; | ||||
| 			this.name = name; | ||||
| 			this.opcode = opcode; | ||||
| 			this.lib = lib; | ||||
| 		} | ||||
| 		public Varargs invoke(Varargs args) { | ||||
| 			switch ( opcode ) { | ||||
| 			case OP_MODULE:  | ||||
| 				return lib.module(args); | ||||
| 			case OP_LOADLIB:  | ||||
| 				return loadlib(args); | ||||
| 			case OP_PRELOAD_LOADER: { | ||||
| 				return lib.loader_preload(args); | ||||
| 			} | ||||
| 			case OP_LUA_LOADER: { | ||||
| 				return lib.loader_Lua(args); | ||||
| 			} | ||||
| 			case OP_JAVA_LOADER: { | ||||
| 				return lib.loader_Java(args); | ||||
| 			} | ||||
| 			} | ||||
| 			return NONE; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	/** Allow packages to mark themselves as loaded */ | ||||
| 	public void setIsLoaded(String name, LuaTable value) { | ||||
| 		LOADED.set(name, value); | ||||
| 	} | ||||
|  | ||||
| 	public void setLuaPath( String newLuaPath ) { | ||||
| 		PACKAGE.set( _PATH, valueOf(newLuaPath) ); | ||||
| 	} | ||||
| 	 | ||||
| 	public String tojstring() { | ||||
| 		return "package"; | ||||
| 	} | ||||
| 	 | ||||
| 	 | ||||
| 	// ======================== Module, Package loading ============================= | ||||
| 	/** | ||||
| 	 * module (name [, ...]) | ||||
| 	 *  | ||||
| 	 * Creates a module. If there is a table in package.loaded[name], this table | ||||
| 	 * is the module. Otherwise, if there is a global table t with the given | ||||
| 	 * name, this table is the module. Otherwise creates a new table t and sets | ||||
| 	 * it as the value of the global name and the value of package.loaded[name]. | ||||
| 	 * This function also initializes t._NAME with the given name, t._M with the | ||||
| 	 * module (t itself), and t._PACKAGE with the package name (the full module | ||||
| 	 * name minus last component; see below). Finally, module sets t as the new | ||||
| 	 * environment of the current function and the new value of | ||||
| 	 * package.loaded[name], so that require returns t. | ||||
| 	 *  | ||||
| 	 * If name is a compound name (that is, one with components separated by | ||||
| 	 * dots), module creates (or reuses, if they already exist) tables for each | ||||
| 	 * component. For instance, if name is a.b.c, then module stores the module | ||||
| 	 * table in field c of field b of global a. | ||||
| 	 *  | ||||
| 	 * This function may receive optional options after the module name, where | ||||
| 	 * each option is a function to be applied over the module. | ||||
| 	 */ | ||||
| 	public Varargs module(Varargs args) { | ||||
| 		LuaString modname = args.checkstring(1); | ||||
| 		int n = args.narg(); | ||||
| 		LuaValue value = LOADED.get(modname); | ||||
| 		LuaValue module; | ||||
| 		if ( ! value.istable() ) { /* not found? */ | ||||
| 			 | ||||
| 		    /* try global variable (and create one if it does not exist) */ | ||||
| 			LuaValue globals = LuaThread.getGlobals(); | ||||
| 			module = findtable( globals, modname ); | ||||
| 			if ( module == null ) | ||||
| 				error( "name conflict for module '"+modname+"'" ); | ||||
| 			LOADED.set(modname, module); | ||||
| 		} else { | ||||
| 			module = (LuaTable) value; | ||||
| 		} | ||||
| 		 | ||||
| 		 | ||||
| 		/* check whether table already has a _NAME field */ | ||||
| 		LuaValue name = module.get(_NAME); | ||||
| 		if ( name.isnil() ) { | ||||
| 			modinit( module, modname ); | ||||
| 		} | ||||
| 		 | ||||
| 		// set the environment of the current function | ||||
| 		LuaFunction f = LuaThread.getCallstackFunction(1); | ||||
| 		if ( f == null ) | ||||
| 			error("no calling function"); | ||||
| 		if ( ! f.isclosure() ) | ||||
| 			error("'module' not called from a Lua function"); | ||||
| 		f.setfenv(module); | ||||
| 		 | ||||
| 		// apply the functions | ||||
| 		for ( int i=2; i<=n; i++ ) | ||||
| 			args.arg(i).call( module ); | ||||
| 		 | ||||
| 		// returns no results | ||||
| 		return NONE; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 *  | ||||
| 	 * @param table the table at which to start the search | ||||
| 	 * @param fname the name to look up or create, such as "abc.def.ghi" | ||||
| 	 * @return the table for that name, possible a new one, or null if a non-table has that name already.  | ||||
| 	 */ | ||||
| 	private static final LuaValue findtable(LuaValue table, LuaString fname) { | ||||
| 		int b, e=(-1); | ||||
| 		do { | ||||
| 			e = fname.indexOf(_DOT, b=e+1 ); | ||||
| 			if ( e < 0 ) | ||||
| 				e = fname.m_length; | ||||
| 			LuaString key = fname.substring(b, e); | ||||
| 			LuaValue val = table.rawget(key); | ||||
| 			if ( val.isnil() ) { /* no such field? */ | ||||
| 				LuaTable field = new LuaTable(); /* new table for field */ | ||||
| 				table.set(key, field); | ||||
| 				table = field; | ||||
| 			} else if ( ! val.istable() ) {  /* field has a non-table value? */ | ||||
| 				return null; | ||||
| 			} else { | ||||
| 				table = val; | ||||
| 			} | ||||
| 		} while ( e < fname.m_length ); | ||||
| 		return table; | ||||
| 	} | ||||
|  | ||||
| 	private static final void modinit(LuaValue module, LuaString modname) { | ||||
| 		/* module._M = module */ | ||||
| 		module.set(_M, module); | ||||
| 		int e = modname.lastIndexOf(_DOT); | ||||
| 		module.set(_NAME, modname ); | ||||
| 		module.set(_PACKAGE, (e<0? EMPTYSTRING: modname.substring(0,e+1)) ); | ||||
| 	} | ||||
|  | ||||
| 	/**  | ||||
| 	 * require (modname) | ||||
| 	 *  | ||||
| 	 * Loads the given module. The function starts by looking into the package.loaded table to  | ||||
| 	 * determine whether modname is already loaded. If it is, then require returns the value  | ||||
| 	 * stored at package.loaded[modname]. Otherwise, it tries to find a loader for the module. | ||||
| 	 *  | ||||
| 	 * To find a loader, require is guided by the package.loaders array. By changing this array,  | ||||
| 	 * we can change how require looks for a module. The following explanation is based on the  | ||||
| 	 * default configuration for package.loaders. | ||||
| 	 *   | ||||
| 	 * First require queries package.preload[modname]. If it has a value, this value  | ||||
| 	 * (which should be a function) is the loader. Otherwise require searches for a Lua loader  | ||||
| 	 * using the path stored in package.path. If that also fails, it searches for a C loader  | ||||
| 	 * using the path stored in package.cpath. If that also fails, it tries an all-in-one loader  | ||||
| 	 * (see package.loaders). | ||||
| 	 *  | ||||
| 	 * Once a loader is found, require calls the loader with a single argument, modname.  | ||||
| 	 * If the loader returns any value, require assigns the returned value to package.loaded[modname].  | ||||
| 	 * If the loader returns no value and has not assigned any value to package.loaded[modname],  | ||||
| 	 * then require assigns true to this entry. In any case, require returns the final value of  | ||||
| 	 * package.loaded[modname].  | ||||
| 	 *  | ||||
| 	 * If there is any error loading or running the module, or if it cannot find any loader for  | ||||
| 	 * the module, then require signals an error. | ||||
| 	 */	 | ||||
| 	public LuaValue require( LuaValue arg ) { | ||||
| 		LuaString name = arg.checkstring(); | ||||
| 		LuaValue loaded = LOADED.get(name); | ||||
| 		if ( loaded.toboolean() ) { | ||||
| 			if ( loaded == _SENTINEL ) | ||||
| 				error("loop or previous error loading module '"+name+"'"); | ||||
| 			return loaded; | ||||
| 		} | ||||
|  | ||||
| 		/* else must load it; iterate over available loaders */ | ||||
| 		LuaTable tbl = PACKAGE.get(_LOADERS).checktable(); | ||||
| 		StringBuffer sb = new StringBuffer(); | ||||
| 		LuaValue chunk = null; | ||||
| 		for ( int i=1; true; i++ ) { | ||||
| 			LuaValue loader = tbl.get(i); | ||||
| 			if ( loader.isnil() ) { | ||||
| 				error( "module '"+name+"' not found: "+name+sb );				 | ||||
| 		    } | ||||
| 						 | ||||
| 		    /* call loader with module name as argument */ | ||||
| 			chunk = loader.call(name); | ||||
| 			if ( chunk.isfunction() ) | ||||
| 				break; | ||||
| 			if ( chunk.isstring() ) | ||||
| 				sb.append( chunk.tojstring() ); | ||||
| 		} | ||||
|  | ||||
| 		// load the module using the loader | ||||
| 		LOADED.set(name, _SENTINEL); | ||||
| 		LuaValue result = chunk.call(name); | ||||
| 		if ( ! result.isnil() ) | ||||
| 			LOADED.set( name, result ); | ||||
| 		else if ( (result = LOADED.get(name)) == _SENTINEL )  | ||||
| 			LOADED.set( name, result = LuaValue.TRUE ); | ||||
| 		return result; | ||||
| 	} | ||||
|  | ||||
| 	public static Varargs loadlib( Varargs args ) { | ||||
| 		args.checkstring(1); | ||||
| 		return varargsOf(NIL, valueOf("dynamic libraries not enabled"), valueOf("absent")); | ||||
| 	} | ||||
|  | ||||
| 	LuaValue loader_preload( Varargs args ) { | ||||
| 		LuaString name = args.checkstring(1); | ||||
| 		LuaValue preload = PACKAGE.get(_PRELOAD).checktable(); | ||||
| 		LuaValue val = preload.get(name); | ||||
| 		return val.isnil()?  | ||||
| 			valueOf("\n\tno field package.preload['"+name+"']"): | ||||
| 			val; | ||||
| 	} | ||||
|  | ||||
| 	LuaValue loader_Lua( Varargs args ) { | ||||
| 		String name = args.checkjstring(1); | ||||
| 		InputStream is = null; | ||||
| 		 | ||||
| 		 | ||||
| 		// get package path | ||||
| 		LuaValue pp = PACKAGE.get(_PATH); | ||||
| 		if ( ! pp.isstring() )  | ||||
| 			return valueOf("package.path is not a string"); | ||||
| 		String path = pp.tojstring(); | ||||
| 		 | ||||
| 		// check the path elements | ||||
| 		int e = -1; | ||||
| 		int n = path.length(); | ||||
| 		StringBuffer sb = null; | ||||
| 		name = name.replace('.','/'); | ||||
| 		while ( e < n ) { | ||||
| 			 | ||||
| 			// find next template | ||||
| 			int b = e+1; | ||||
| 			e = path.indexOf(';',b); | ||||
| 			if ( e < 0 ) | ||||
| 				e = path.length(); | ||||
| 			String template = path.substring(b,e); | ||||
|  | ||||
| 			// create filename | ||||
| 			int q = template.indexOf('?'); | ||||
| 			String filename = template; | ||||
| 			if ( q >= 0 ) { | ||||
| 				filename = template.substring(0,q) + name + template.substring(q+1); | ||||
| 			} | ||||
| 			 | ||||
| 			// try loading the file | ||||
| 			Varargs v = BaseLib.loadFile(filename);  | ||||
| 			if ( v.arg1().isfunction() ) | ||||
| 				return v.arg1(); | ||||
| 			 | ||||
| 			// report error | ||||
| 			if ( sb == null ) | ||||
| 				sb = new StringBuffer(); | ||||
| 			sb.append( "\n\t'"+filename+"': "+v.arg(2) ); | ||||
| 		} | ||||
| 		return valueOf(sb.toString()); | ||||
| 	} | ||||
| 	 | ||||
| 	LuaValue loader_Java( Varargs args ) { | ||||
| 		String name = args.checkjstring(1); | ||||
| 		String classname = toClassname( name ); | ||||
| 		Class c = null; | ||||
| 		LuaValue v = null; | ||||
| 		try { | ||||
| 			c = Class.forName(classname); | ||||
| 			v = (LuaValue) c.newInstance(); | ||||
| 			v.setfenv(env); | ||||
| 			return v; | ||||
| 		} catch ( ClassNotFoundException  cnfe ) { | ||||
| 			return valueOf("\n\tno class '"+classname+"'" ); | ||||
| 		} catch ( Exception e ) { | ||||
| 			return valueOf("\n\tjava load failed on '"+classname+"', "+e ); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	/** Convert lua filename to valid class name */ | ||||
| 	public static final String toClassname( String filename ) { | ||||
| 		int n=filename.length(); | ||||
| 		int j=n; | ||||
| 		if ( filename.endsWith(".lua") ) | ||||
| 			j -= 4; | ||||
| 		for ( int k=0; k<j; k++ ) { | ||||
| 			char c = filename.charAt(k); | ||||
| 			if ( (!isClassnamePart(c)) || (c=='/') || (c=='\\') ) { | ||||
| 				StringBuffer sb = new StringBuffer(j); | ||||
| 				for ( int i=0; i<j; i++ ) { | ||||
| 					c = filename.charAt(i); | ||||
| 					sb.append(  | ||||
| 							 (isClassnamePart(c))? c: | ||||
| 							 ((c=='/') || (c=='\\'))? '.': '_' );  | ||||
| 				} | ||||
| 				return sb.toString(); | ||||
| 			} | ||||
| 		} | ||||
| 		return n==j? filename: filename.substring(0,j); | ||||
| 	} | ||||
| 	 | ||||
| 	private static final boolean isClassnamePart(char c) { | ||||
| 		if ( (c>='a'&&c<='z') || (c>='A'&&c<='Z') || (c>='0'&&c<='9') ) | ||||
| 			return true; | ||||
| 		switch ( c ) { | ||||
| 		case '.': | ||||
| 		case '$': | ||||
| 		case '_': | ||||
| 			return true; | ||||
| 		default: | ||||
| 			return false; | ||||
| 		} | ||||
| 	}	 | ||||
| } | ||||
| @@ -1,57 +0,0 @@ | ||||
| /******************************************************************************* | ||||
|  * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  ******************************************************************************/ | ||||
| package org.luaj.vm2.lib; | ||||
|  | ||||
| import java.io.InputStream; | ||||
|  | ||||
| /**  | ||||
|  * Interface for opening application resource files such as scripts sources.   | ||||
|  * <p> | ||||
|  * This is used by required to load files that are part of  | ||||
|  * the application, and implemented by BaseLib | ||||
|  * for both the Jme and Jse platforms.  | ||||
|  * <p> | ||||
|  * The Jme version of base lib {@link BaseLib}  | ||||
|  * implements {@link BaseLib#FINDER} via {@link Class#getResourceAsStream(String)},  | ||||
|  * while the Jse version {@link JseBaseLib} implements it using {@link java.io.File#File(String)}. | ||||
|  * <p> | ||||
|  * The io library does not use this API for file manipulation. | ||||
|  * <p> | ||||
|  * @see BaseLib | ||||
|  * @see BaseLib#FINDER | ||||
|  * @see JseBaseLib | ||||
|  * @see JmePlatform | ||||
|  * @see JsePlatform  | ||||
|  */ | ||||
| public interface ResourceFinder { | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Try to open a file, or return null if not found. | ||||
| 	 *  | ||||
| 	 * @see org.luaj.vm2.lib.BaseLib | ||||
| 	 * @see org.luaj.vm2.lib.jse.JseBaseLib | ||||
| 	 *  | ||||
| 	 * @param filename | ||||
| 	 * @return InputStream, or null if not found.  | ||||
| 	 */ | ||||
| 	public InputStream findResource( String filename ); | ||||
| } | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,124 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.lib; | ||||
|  | ||||
| import org.luaj.vm2.LuaTable; | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.Varargs; | ||||
|  | ||||
| /**  | ||||
|  * Subclass of {@link LibFunction} which implements the lua standard {@code table}  | ||||
|  * library.  | ||||
|  *  | ||||
|  * <p> | ||||
|  * Typically, this library is included as part of a call to either  | ||||
|  * {@link JsePlatform#standardGlobals()} or {@link JmePlatform#standardGlobals()} | ||||
|  * <p> | ||||
|  * To instantiate and use it directly,  | ||||
|  * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: | ||||
|  * <pre> {@code | ||||
|  * LuaTable _G = new LuaTable(); | ||||
|  * LuaThread.setGlobals(_G); | ||||
|  * _G.load(new BaseLib()); | ||||
|  * _G.load(new PackageLib()); | ||||
|  * _G.load(new TableLib()); | ||||
|  * LuaValue tbl = LuaValue.listOf( new LuaValue[] { | ||||
|  * 		LuaValue.valueOf( "abc" ), | ||||
|  * 		LuaValue.valueOf( "def" ) } ); | ||||
|  * LuaValue sep = LuaValue.valueOf( "-" ); | ||||
|  * System.out.println( _G.get("table").get("concat").call( tbl, sep ) ); | ||||
|  * } </pre> | ||||
|  * Doing so will ensure the library is properly initialized  | ||||
|  * and loaded into the globals table.  | ||||
|  * <p> | ||||
|  * This has been implemented to match as closely as possible the behavior in the corresponding library in C. | ||||
|  * @see LibFunction | ||||
|  * @see JsePlatform | ||||
|  * @see JmePlatform | ||||
|  * @see <a href="http://www.lua.org/manual/5.1/manual.html#5.5">http://www.lua.org/manual/5.1/manual.html#5.5</a> | ||||
|  */ | ||||
| public class TableLib extends OneArgFunction { | ||||
|  | ||||
| 	public TableLib() { | ||||
| 	} | ||||
|  | ||||
| 	private LuaTable init() { | ||||
| 		LuaTable t = new LuaTable(); | ||||
| 		bind(t, TableLib.class, new String[] { "getn", "maxn", }, 1 ); | ||||
| 		bind(t, TableLibV.class, new String[] { | ||||
| 			"remove", "concat", "insert", "sort", "foreach", "foreachi", } ); | ||||
| 		env.set("table", t); | ||||
| 		PackageLib.instance.LOADED.set("table", t); | ||||
| 		return t; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue call(LuaValue arg) { | ||||
| 		switch ( opcode ) { | ||||
| 		case 0: // init library | ||||
| 			return init(); | ||||
| 		case 1:  // "getn" (table) -> number | ||||
| 			return arg.checktable().getn(); | ||||
| 		case 2: // "maxn"  (table) -> number  | ||||
| 			return valueOf( arg.checktable().maxn()); | ||||
| 		} | ||||
| 		return NIL; | ||||
| 	} | ||||
|  | ||||
| 	static final class TableLibV extends VarArgFunction { | ||||
| 		public Varargs invoke(Varargs args) { | ||||
| 			switch ( opcode ) { | ||||
| 			case 0: { // "remove" (table [, pos]) -> removed-ele | ||||
| 				LuaTable table = args.checktable(1); | ||||
| 				int pos = args.narg()>1? args.checkint(2): 0; | ||||
| 				return table.remove(pos); | ||||
| 			} | ||||
| 			case 1: { // "concat" (table [, sep [, i [, j]]]) -> string | ||||
| 				LuaTable table = args.checktable(1); | ||||
| 				return table.concat( | ||||
| 						args.optstring(2,LuaValue.EMPTYSTRING), | ||||
| 						args.optint(3,1), | ||||
| 						args.isvalue(4)? args.checkint(4): table.length() ); | ||||
| 			} | ||||
| 			case 2: { // "insert" (table, [pos,] value) -> prev-ele | ||||
| 				final LuaTable table = args.checktable(1); | ||||
| 				final int pos = args.narg()>2? args.checkint(2): 0; | ||||
| 				final LuaValue value = args.arg( args.narg()>2? 3: 2 ); | ||||
| 				table.insert( pos, value ); | ||||
| 				return NONE; | ||||
| 			} | ||||
| 			case 3: { // "sort" (table [, comp]) -> void | ||||
| 				LuaTable table = args.checktable(1); | ||||
| 				LuaValue compare = (args.isnoneornil(2)? NIL: args.checkfunction(2)); | ||||
| 				table.sort( compare ); | ||||
| 				return NONE; | ||||
| 			} | ||||
| 			case 4: { // (table, func) -> void | ||||
| 				return args.checktable(1).foreach( args.checkfunction(2) ); | ||||
| 			} | ||||
| 			case 5: { // "foreachi" (table, func) -> void | ||||
| 				return args.checktable(1).foreachi( args.checkfunction(2) ); | ||||
| 			} | ||||
| 			} | ||||
| 			return NONE; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,80 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.lib; | ||||
|  | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.Varargs; | ||||
|  | ||||
| /** Abstract base class for Java function implementations that take two arguments and  | ||||
|  * return one value.  | ||||
|  * <p> | ||||
|  * Subclasses need only implement {@link LuaValue#call(LuaValue,LuaValue,LuaValue)} to complete this class,  | ||||
|  * simplifying development.   | ||||
|  * All other uses of {@link #call()}, {@link #invoke(Varargs)},etc,  | ||||
|  * are routed through this method by this class,  | ||||
|  * dropping or extending arguments with {@code nil} values as required. | ||||
|  * <p> | ||||
|  * If more or less than three arguments are required,   | ||||
|  * or variable argument or variable return values,  | ||||
|  * then use one of the related function | ||||
|  * {@link ZeroArgFunction}, {@link OneArgFunction}, {@link TwoArgFunction}, or {@link VarArgFunction}. | ||||
|  * <p> | ||||
|  * See {@link LibFunction} for more information on implementation libraries and library functions. | ||||
|  * @see #call(LuaValue,LuaValue,LuaValue) | ||||
|  * @see LibFunction | ||||
|  * @see ZeroArgFunction | ||||
|  * @see OneArgFunction | ||||
|  * @see TwoArgFunction | ||||
|  * @see VarArgFunction | ||||
|  */ | ||||
| abstract public class ThreeArgFunction extends LibFunction { | ||||
|  | ||||
| 	abstract public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3); | ||||
| 	 | ||||
| 	/** Default constructor */ | ||||
| 	public ThreeArgFunction() { | ||||
| 	} | ||||
| 	 | ||||
| 	/** Constructor with specific environment | ||||
| 	 * @param env The environment to apply during constructon. | ||||
| 	 */ | ||||
| 	public ThreeArgFunction( LuaValue env ) { | ||||
| 		this.env = env; | ||||
| 	} | ||||
| 	 | ||||
| 	public final LuaValue call() { | ||||
| 		return call(NIL, NIL, NIL); | ||||
| 	} | ||||
|  | ||||
| 	public final LuaValue call(LuaValue arg) { | ||||
| 		return call(arg, NIL, NIL); | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue call(LuaValue arg1, LuaValue arg2) { | ||||
| 		return call(arg1, arg2, NIL); | ||||
| 	} | ||||
| 	 | ||||
| 	public Varargs invoke(Varargs varargs) { | ||||
| 		return call(varargs.arg1(),varargs.arg(2),varargs.arg(3)); | ||||
| 	} | ||||
| 	 | ||||
| }  | ||||
| @@ -1,80 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.lib; | ||||
|  | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.Varargs; | ||||
|  | ||||
| /** Abstract base class for Java function implementations that take two arguments and  | ||||
|  * return one value.  | ||||
|  * <p> | ||||
|  * Subclasses need only implement {@link LuaValue#call(LuaValue,LuaValue)} to complete this class,  | ||||
|  * simplifying development.   | ||||
|  * All other uses of {@link #call()}, {@link #invoke(Varargs)},etc,  | ||||
|  * are routed through this method by this class,  | ||||
|  * dropping or extending arguments with {@code nil} values as required. | ||||
|  * <p> | ||||
|  * If more or less than two arguments are required,   | ||||
|  * or variable argument or variable return values,  | ||||
|  * then use one of the related function | ||||
|  * {@link ZeroArgFunction}, {@link OneArgFunction}, {@link ThreeArgFunction}, or {@link VarArgFunction}. | ||||
|  * <p> | ||||
|  * See {@link LibFunction} for more information on implementation libraries and library functions. | ||||
|  * @see #call(LuaValue,LuaValue) | ||||
|  * @see LibFunction | ||||
|  * @see ZeroArgFunction | ||||
|  * @see OneArgFunction | ||||
|  * @see ThreeArgFunction | ||||
|  * @see VarArgFunction | ||||
|  */ | ||||
| abstract public class TwoArgFunction extends LibFunction { | ||||
|  | ||||
| 	abstract public LuaValue call(LuaValue arg1, LuaValue arg2); | ||||
| 	 | ||||
| 	/** Default constructor */ | ||||
| 	public TwoArgFunction() { | ||||
| 	} | ||||
| 	 | ||||
| 	/** Constructor with specific environment | ||||
| 	 * @param env The environment to apply during constructon. | ||||
| 	 */ | ||||
| 	public TwoArgFunction( LuaValue env ) { | ||||
| 		this.env = env; | ||||
| 	} | ||||
| 	 | ||||
| 	public final LuaValue call() { | ||||
| 		return call(NIL, NIL); | ||||
| 	} | ||||
|  | ||||
| 	public final LuaValue call(LuaValue arg) { | ||||
| 		return call(arg, NIL); | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { | ||||
| 		return call(arg1, arg2); | ||||
| 	} | ||||
| 	 | ||||
| 	public Varargs invoke(Varargs varargs) { | ||||
| 		return call(varargs.arg1(),varargs.arg(2)); | ||||
| 	} | ||||
| 	 | ||||
| }  | ||||
| @@ -1,100 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.lib; | ||||
|  | ||||
| import org.luaj.vm2.LuaThread; | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.Varargs; | ||||
|  | ||||
| /** Abstract base class for Java function implementations that takes varaiable arguments and  | ||||
|  * returns multiple return values.  | ||||
|  * <p> | ||||
|  * Subclasses need only implement {@link LuaValue#invoke(Varargs)} to complete this class,  | ||||
|  * simplifying development.   | ||||
|  * All other uses of {@link #call(LuaValue)}, {@link #invoke()},etc,  | ||||
|  * are routed through this method by this class, | ||||
|  * converting arguments to {@linnk Varargs} and   | ||||
|  * dropping or extending return values with {@code nil} values as required. | ||||
|  * <p> | ||||
|  * If between one and three arguments are required, and only one return value is returned,    | ||||
|  * {@link ZeroArgFunction}, {@link OneArgFunction}, {@link TwoArgFunction}, or {@link ThreeArgFunction}. | ||||
|  * <p> | ||||
|  * See {@link LibFunction} for more information on implementation libraries and library functions. | ||||
|  * @see #invoke(Varargs) | ||||
|  * @see LibFunction | ||||
|  * @see ZeroArgFunction | ||||
|  * @see OneArgFunction | ||||
|  * @see TwoArgFunction | ||||
|  * @see ThreeArgFunction | ||||
|  */ | ||||
| abstract public class VarArgFunction extends LibFunction { | ||||
| 	public VarArgFunction() { | ||||
| 	} | ||||
| 	 | ||||
| 	public VarArgFunction( LuaValue env ) { | ||||
| 		this.env = env; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue call() { | ||||
| 		return invoke(NONE).arg1(); | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue call(LuaValue arg) { | ||||
| 		return invoke(arg).arg1(); | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue call(LuaValue arg1, LuaValue arg2) { | ||||
| 		return invoke(varargsOf(arg1,arg2)).arg1(); | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { | ||||
| 		return invoke(varargsOf(arg1,arg2,arg3)).arg1(); | ||||
| 	} | ||||
|  | ||||
| 	/**  | ||||
| 	 * Override and implement for the best performance.  | ||||
| 	 * May not have expected behavior for tail calls.  | ||||
| 	 * Should not be used if either: | ||||
| 	 * - function needs to be used as a module | ||||
| 	 * - function has a possibility of returning a TailcallVarargs | ||||
| 	 * @param args the arguments to the function call. | ||||
| 	 */ | ||||
| 	public Varargs invoke(Varargs args) { | ||||
| 		LuaThread.CallStack cs = LuaThread.onCall(this); | ||||
| 		try { | ||||
| 			return this.onInvoke(args).eval(); | ||||
| 		} finally { | ||||
| 			cs.onReturn(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Override to provide a call implementation that runs in an environment | ||||
| 	 * that can participate in setfenv, and behaves as expected  | ||||
| 	 * when returning TailcallVarargs.  | ||||
| 	 * @param args the arguments to the function call. | ||||
| 	 */ | ||||
| 	public Varargs onInvoke(Varargs args) { | ||||
| 		return invoke(args); | ||||
| 	} | ||||
| 	 | ||||
| }  | ||||
| @@ -1,77 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.lib; | ||||
|  | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.Varargs; | ||||
|  | ||||
| /** Abstract base class for Java function implementations that take no arguments and  | ||||
|  * return one value.  | ||||
|  * <p> | ||||
|  * Subclasses need only implement {@link LuaValue#call()} to complete this class,  | ||||
|  * simplifying development.   | ||||
|  * All other uses of {@link #call(LuaValue)}, {@link #invoke(Varargs)},etc,  | ||||
|  * are routed through this method by this class. | ||||
|  * <p> | ||||
|  * If one or more arguments are required, or variable argument or variable return values,  | ||||
|  * then use one of the related function | ||||
|  * {@link OneArgFunction}, {@link TwoArgFunction}, {@link ThreeArgFunction}, or {@link VarArgFunction}. | ||||
|  * <p> | ||||
|  * See {@link LibFunction} for more information on implementation libraries and library functions. | ||||
|  * @see #call() | ||||
|  * @see LibFunction | ||||
|  * @see OneArgFunction | ||||
|  * @see TwoArgFunction | ||||
|  * @see ThreeArgFunction | ||||
|  * @see VarArgFunction | ||||
|  */ | ||||
| abstract public class ZeroArgFunction extends LibFunction { | ||||
|  | ||||
| 	abstract public LuaValue call(); | ||||
|  | ||||
| 	/** Default constructor */ | ||||
| 	public ZeroArgFunction() { | ||||
| 	} | ||||
| 	 | ||||
| 	/** Constructor with specific environment | ||||
| 	 * @param env The environment to apply during constructon. | ||||
| 	 */ | ||||
| 	public ZeroArgFunction( LuaValue env ) { | ||||
| 		this.env = env; | ||||
| 	} | ||||
| 	 | ||||
| 	public LuaValue call(LuaValue arg) { | ||||
| 		return call(); | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue call(LuaValue arg1, LuaValue arg2) { | ||||
| 		return call(); | ||||
| 	} | ||||
|  | ||||
| 	public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { | ||||
| 		return call(); | ||||
| 	} | ||||
|  | ||||
| 	public Varargs invoke(Varargs varargs) { | ||||
| 		return call(); | ||||
| 	} | ||||
| }  | ||||
| @@ -1,227 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009-2011 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.lib.jme; | ||||
|  | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.io.OutputStream; | ||||
|  | ||||
| import javax.microedition.io.Connector; | ||||
| import javax.microedition.io.StreamConnection; | ||||
|  | ||||
| import org.luaj.vm2.LuaString; | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.lib.BaseLib; | ||||
| import org.luaj.vm2.lib.IoLib; | ||||
| import org.luaj.vm2.lib.LibFunction; | ||||
|  | ||||
| /**  | ||||
|  * Subclass of {@link IoLib} and therefore {@link LibFunction} which implements the lua standard {@code io}  | ||||
|  * library for the JSE platform.  | ||||
|  * <p>  | ||||
|  * The implementation of the is based on CLDC 1.0 and StreamConnection. | ||||
|  * However, seek is not supported.  | ||||
|  * <p> | ||||
|  * Typically, this library is included as part of a call to  | ||||
|  * {@link JmePlatform#standardGlobals()} | ||||
|  * <p> | ||||
|  * To instantiate and use it directly,  | ||||
|  * link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as: | ||||
|  * <pre> {@code | ||||
|  * LuaTable _G = new LuaTable(); | ||||
|  * LuaThread.setGlobals(_G); | ||||
|  * _G.load(new BaseLib()); | ||||
|  * _G.load(new PackageLib()); | ||||
|  * _G.load(new JmeIoLib()); | ||||
|  * _G.get("io").get("write").call(LuaValue.valueOf("hello, world\n")); | ||||
|  * } </pre> | ||||
|  * Doing so will ensure the library is properly initialized  | ||||
|  * and loaded into the globals table.  | ||||
|  * <p> | ||||
|  * This has been implemented to match as closely as possible the behavior in the corresponding library in C. | ||||
|  * @see LibFunction | ||||
|  * @see JsePlatform | ||||
|  * @see JmePlatform | ||||
|  * @see IoLib | ||||
|  * @see JseIoLib | ||||
|  * @see <a href="http://www.lua.org/manual/5.1/manual.html#5.6">http://www.lua.org/manual/5.1/manual.html#5.6</a> | ||||
|  */ | ||||
| public class JmeIoLib extends IoLib { | ||||
| 	 | ||||
| 	public JmeIoLib() { | ||||
| 		super(); | ||||
| 	} | ||||
|  | ||||
| 	protected File wrapStdin() throws IOException { | ||||
| 		return new FileImpl(BaseLib.instance.STDIN); | ||||
| 	} | ||||
| 	 | ||||
| 	protected File wrapStdout() throws IOException { | ||||
| 		return new FileImpl(BaseLib.instance.STDOUT); | ||||
| 	} | ||||
| 	 | ||||
| 	protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException { | ||||
| 		String url = "file:///" + filename; | ||||
| 		int mode  = readMode? Connector.READ: Connector.READ_WRITE; | ||||
| 		StreamConnection conn = (StreamConnection) Connector.open( url, mode ); | ||||
| 		File f = readMode?  | ||||
| 				new FileImpl(conn, conn.openInputStream(), null): | ||||
| 				new FileImpl(conn, conn.openInputStream(), conn.openOutputStream()); | ||||
| 		/* | ||||
| 		if ( appendMode ) { | ||||
| 			f.seek("end",0); | ||||
| 		} else { | ||||
| 			if ( ! readMode ) | ||||
| 				conn.truncate(0); | ||||
| 		} | ||||
| 		*/ | ||||
| 		return f; | ||||
| 	} | ||||
| 	 | ||||
| 	private static void notimplemented() throws IOException { | ||||
| 		throw new IOException("not implemented"); | ||||
| 	} | ||||
| 	 | ||||
| 	protected File openProgram(String prog, String mode) throws IOException { | ||||
| 		notimplemented(); | ||||
| 		return null; | ||||
| 	} | ||||
|  | ||||
| 	protected File tmpFile() throws IOException { | ||||
| 		notimplemented(); | ||||
| 		return null; | ||||
| 	} | ||||
| 	 | ||||
| 	private final class FileImpl extends File { | ||||
| 		private final StreamConnection conn; | ||||
| 		private final InputStream is; | ||||
| 		private final OutputStream os; | ||||
| 		private boolean closed = false; | ||||
| 		private boolean nobuffer = false; | ||||
| 		private int lookahead = -1; | ||||
| 		private FileImpl( StreamConnection conn, InputStream is, OutputStream os ) { | ||||
| 			this.conn = conn; | ||||
| 			this.is = is; | ||||
| 			this.os = os; | ||||
| 		} | ||||
| 		private FileImpl( InputStream i ) { | ||||
| 			this( null, i, null ); | ||||
| 		} | ||||
| 		private FileImpl( OutputStream o ) { | ||||
| 			this( null, null, o ); | ||||
| 		} | ||||
| 		public String tojstring() { | ||||
| 			return "file ("+this.hashCode()+")"; | ||||
| 		} | ||||
| 		public boolean isstdfile() { | ||||
| 			return conn == null; | ||||
| 		} | ||||
| 		public void close() throws IOException  { | ||||
| 			closed = true; | ||||
| 			if ( conn != null ) { | ||||
| 				conn.close(); | ||||
| 			} | ||||
| 		} | ||||
| 		public void flush() throws IOException { | ||||
| 			if ( os != null ) | ||||
| 				os.flush(); | ||||
| 		} | ||||
| 		public void write(LuaString s) throws IOException { | ||||
| 			if ( os != null ) | ||||
| 				os.write( s.m_bytes, s.m_offset, s.m_length ); | ||||
| 			else | ||||
| 				notimplemented(); | ||||
| 			if ( nobuffer ) | ||||
| 				flush(); | ||||
| 		} | ||||
| 		public boolean isclosed() { | ||||
| 			return closed; | ||||
| 		} | ||||
| 		public int seek(String option, int pos) throws IOException { | ||||
| 			/* | ||||
| 			if ( conn != null ) { | ||||
| 				if ( "set".equals(option) ) { | ||||
| 					conn.seek(pos); | ||||
| 					return (int) conn.getFilePointer(); | ||||
| 				} else if ( "end".equals(option) ) { | ||||
| 					conn.seek(conn.length()+1+pos); | ||||
| 					return (int) conn.length()+1; | ||||
| 				} else { | ||||
| 					conn.seek(conn.getFilePointer()+pos); | ||||
| 					return (int) conn.getFilePointer(); | ||||
| 				} | ||||
| 			} | ||||
| 			*/ | ||||
| 			notimplemented(); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		public void setvbuf(String mode, int size) { | ||||
| 			nobuffer = "no".equals(mode); | ||||
| 		} | ||||
|  | ||||
| 		// get length remaining to read | ||||
| 		public int remaining() throws IOException { | ||||
| 			return -1; | ||||
| 		} | ||||
| 		 | ||||
| 		// peek ahead one character | ||||
| 		public int peek() throws IOException { | ||||
| 			if ( lookahead < 0 ) | ||||
| 				lookahead = is.read(); | ||||
| 			return lookahead; | ||||
| 		}		 | ||||
| 		 | ||||
| 		// return char if read, -1 if eof, throw IOException on other exception  | ||||
| 		public int read() throws IOException { | ||||
| 			if ( lookahead >= 0 ) { | ||||
| 				int c = lookahead; | ||||
| 				lookahead = -1; | ||||
| 				return c; | ||||
| 			} | ||||
| 			if ( is != null )  | ||||
| 				return is.read(); | ||||
| 			notimplemented(); | ||||
| 			return 0; | ||||
| 		} | ||||
|  | ||||
| 		// return number of bytes read if positive, -1 if eof, throws IOException | ||||
| 		public int read(byte[] bytes, int offset, int length) throws IOException { | ||||
| 			int n,i=0; | ||||
| 			if (is!=null) { | ||||
| 				if ( length > 0 && lookahead >= 0 ) { | ||||
| 					bytes[offset] = (byte) lookahead; | ||||
| 					lookahead = -1; | ||||
| 					i += 1; | ||||
| 				} | ||||
| 				for ( ; i<length; ) { | ||||
| 					n = is.read(bytes, offset+i, length-i); | ||||
| 					if ( n < 0 ) | ||||
| 						return ( i > 0 ? i : -1 ); | ||||
| 					i += n; | ||||
| 				} | ||||
| 			} else { | ||||
| 				notimplemented(); | ||||
| 			} | ||||
| 			return length; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,130 +0,0 @@ | ||||
| /******************************************************************************* | ||||
|  * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  *  | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  ******************************************************************************/ | ||||
| package org.luaj.vm2.lib.jme; | ||||
|  | ||||
| import org.luaj.vm2.compiler.LuaC; | ||||
| import org.luaj.vm2.LoadState; | ||||
| import org.luaj.vm2.LuaTable; | ||||
| import org.luaj.vm2.LuaThread; | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.lib.BaseLib; | ||||
| import org.luaj.vm2.lib.CoroutineLib; | ||||
| import org.luaj.vm2.lib.DebugLib; | ||||
| import org.luaj.vm2.lib.MathLib; | ||||
| import org.luaj.vm2.lib.OsLib; | ||||
| import org.luaj.vm2.lib.PackageLib; | ||||
| import org.luaj.vm2.lib.StringLib; | ||||
| import org.luaj.vm2.lib.TableLib; | ||||
|  | ||||
| /** The {@link JmePlatform} class is a convenience class to standardize  | ||||
|  * how globals tables are initialized for the JME platform.  | ||||
|  * <p> | ||||
|  * The JME platform, being limited, cannot implement all libraries in all aspects.  The main limitations are | ||||
|  * <ul> | ||||
|  * <li>Some math functions are not implemented, see {@link MathLib} for details</li> | ||||
|  * <li>Scripts are loaded via Class.getResourceAsStream(), see {@link BaseLib} for details</li> | ||||
|  * <li>OS functions execute(), remove(), rename(), and tmpname() vary, see {@link OsLib} for details</li> | ||||
|  * <li>I/O seek is not implemented, see {@link JmeIoLib} for details</li> | ||||
|  * <li>luajava is not available, see {@link LuajavaLib} for details</li> | ||||
|  * </ul> | ||||
|  * <p> | ||||
|  * It is used to allocate either a set of standard globals using  | ||||
|  * {@link #standardGlobals()} or debug globals using {@link #debugGlobals()} | ||||
|  * <p> | ||||
|  * A simple example of initializing globals and using them from Java is: | ||||
|  * <pre> {@code | ||||
|  * LuaValue _G = JmePlatform.standardGlobals(); | ||||
|  * _G.get("print").call(LuaValue.valueOf("hello, world")); | ||||
|  * } </pre> | ||||
|  * <p> | ||||
|  * Once globals are created, a simple way to load and run a script is: | ||||
|  * <pre> {@code | ||||
|  * LoadState.load( getClass().getResourceAsStream("main.lua"), "main.lua", _G ).call(); | ||||
|  * } </pre> | ||||
|  * <p> | ||||
|  * although {@code require} could also be used:  | ||||
|  * <pre> {@code | ||||
|  * _G.get("require").call(LuaValue.valueOf("main")); | ||||
|  * } </pre> | ||||
|  * For this to succeed, the file "main.lua" must be a resource in the class path. | ||||
|  * See {@link BaseLib} for details on finding scripts using {@link ResourceFinder}. | ||||
|  * <p> | ||||
|  * The standard globals will contain all standard libraries in their JME flavors: | ||||
|  * <ul> | ||||
|  * <li>{@link BaseLib}</li> | ||||
|  * <li>{@link PackageLib}</li> | ||||
|  * <li>{@link TableLib}</li> | ||||
|  * <li>{@link StringLib}</li> | ||||
|  * <li>{@link CoroutineLib}</li> | ||||
|  * <li>{@link MathLib}</li> | ||||
|  * <li>{@link JmeIoLib}</li> | ||||
|  * <li>{@link OsLib}</li> | ||||
|  * </ul> | ||||
|  * In addition, the {@link LuaC} compiler is installed so lua files may be loaded in their source form.  | ||||
|  * <p>  | ||||
|  * The debug globals are simply the standard globals plus the {@code debug} library {@link DebugLib}. | ||||
|  * <p> | ||||
|  * <p> | ||||
|  * The class ensures that initialization is done in the correct order,  | ||||
|  * and that linkage is made  to {@link LuaThread#setGlobals(LuaValue)}.  | ||||
|  * @see JsePlatform | ||||
|  * @see LoadState | ||||
|  */ | ||||
| public class JmePlatform { | ||||
|  | ||||
| 	/** | ||||
| 	 * Create a standard set of globals for JME including all the libraries. | ||||
| 	 *  | ||||
| 	 * @return Table of globals initialized with the standard JME libraries | ||||
| 	 * @see #debugGlobals() | ||||
| 	 * @see JsePlatform | ||||
| 	 * @see JmePlatform | ||||
| 	 */ | ||||
| 	public static LuaTable standardGlobals() { | ||||
| 		LuaTable _G = new LuaTable(); | ||||
| 		_G.load(new BaseLib()); | ||||
| 		_G.load(new PackageLib()); | ||||
| 		_G.load(new OsLib()); | ||||
| 		_G.load(new MathLib()); | ||||
| 		_G.load(new TableLib()); | ||||
| 		_G.load(new StringLib()); | ||||
| 		_G.load(new CoroutineLib()); | ||||
| 		_G.load(new JmeIoLib()); | ||||
| 		LuaThread.setGlobals(_G); | ||||
| 		LuaC.install(); | ||||
| 		return _G;		 | ||||
| 	} | ||||
| 	 | ||||
| 	/** Create standard globals including the {@link debug} library. | ||||
| 	 *  | ||||
| 	 * @return Table of globals initialized with the standard JSE and debug libraries | ||||
| 	 * @see #standarsGlobals() | ||||
| 	 * @see JsePlatform | ||||
| 	 * @see JmePlatform | ||||
| 	 * @see DebugLib | ||||
| 	 */ | ||||
| 	public static LuaTable debugGlobals() { | ||||
| 		LuaTable _G = standardGlobals(); | ||||
| 		_G.load(new DebugLib()); | ||||
| 		return _G; | ||||
| 	} | ||||
| } | ||||
| @@ -1 +0,0 @@ | ||||
| org.luaj.vm2.script.LuaScriptEngineFactory | ||||
| @@ -1,223 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
|  | ||||
| import java.io.BufferedReader; | ||||
| import java.io.ByteArrayInputStream; | ||||
| import java.io.FileInputStream; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.io.InputStreamReader; | ||||
| import java.util.Vector; | ||||
|  | ||||
| import org.luaj.vm2.LoadState; | ||||
| import org.luaj.vm2.Lua; | ||||
| import org.luaj.vm2.LuaFunction; | ||||
| import org.luaj.vm2.LuaTable; | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.Varargs; | ||||
| import org.luaj.vm2.lib.jse.JsePlatform; | ||||
| import org.luaj.vm2.lua2java.Lua2Java; | ||||
| import org.luaj.vm2.luajc.LuaJC; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * lua command for use in java se environments. | ||||
|  */ | ||||
| public class lua { | ||||
| 	private static final String version = Lua._VERSION + "Copyright (c) 2009 Luaj.org.org"; | ||||
|  | ||||
| 	private static final String usage =  | ||||
| 		"usage: java -cp luaj-jse.jar lua [options] [script [args]].\n" + | ||||
| 		"Available options are:\n" + | ||||
| 		"  -e stat  execute string 'stat'\n" + | ||||
| 		"  -l name  require library 'name'\n" + | ||||
| 		"  -i       enter interactive mode after executing 'script'\n" + | ||||
| 		"  -v       show version information\n" + | ||||
| 		"  -j      	use lua2java source-to-source compiler\n" + | ||||
| 		"  -b      	use luajc bytecode-to-bytecode compiler (requires bcel on class path)\n" + | ||||
| 		"  -n      	nodebug - do not load debug library by default\n" + | ||||
| 		"  --       stop handling options\n" + | ||||
| 		"  -        execute stdin and stop handling options"; | ||||
|  | ||||
| 	private static void usageExit() { | ||||
| 		System.out.println(usage); | ||||
| 		System.exit(-1);		 | ||||
| 	} | ||||
|  | ||||
| 	private static LuaValue _G; | ||||
| 	 | ||||
| 	public static void main( String[] args ) throws IOException { | ||||
|  | ||||
| 		// process args | ||||
| 		boolean interactive = (args.length == 0); | ||||
| 		boolean versioninfo = false; | ||||
| 		boolean processing = true; | ||||
| 		boolean nodebug = false; | ||||
| 		boolean luajc = false; | ||||
| 		boolean lua2java = false; | ||||
| 		Vector libs = null; | ||||
| 		try { | ||||
| 			// stateful argument processing | ||||
| 			for ( int i=0; i<args.length; i++ ) { | ||||
| 				if ( ! processing || ! args[i].startsWith("-") ) { | ||||
| 					// input file - defer to last stage | ||||
| 					break; | ||||
| 				} else if ( args[i].length() <= 1 ) { | ||||
| 					// input file - defer to last stage | ||||
| 					break; | ||||
| 				} else { | ||||
| 					switch ( args[i].charAt(1) ) { | ||||
| 					case 'e': | ||||
| 						if ( ++i >= args.length ) | ||||
| 							usageExit(); | ||||
| 						// input script - defer to last stage | ||||
| 						break; | ||||
| 					case 'b': | ||||
| 						luajc = true; | ||||
| 						break; | ||||
| 					case 'j': | ||||
| 						lua2java = true; | ||||
| 						break; | ||||
| 					case 'l': | ||||
| 						if ( ++i >= args.length ) | ||||
| 							usageExit(); | ||||
| 						libs = libs!=null? libs: new Vector(); | ||||
| 						libs.addElement( args[i] ); | ||||
| 						break; | ||||
| 					case 'i': | ||||
| 						interactive = true; | ||||
| 						break; | ||||
| 					case 'v': | ||||
| 						versioninfo = true; | ||||
| 						break; | ||||
| 					case 'n': | ||||
| 						nodebug = true; | ||||
| 						break; | ||||
| 					case '-': | ||||
| 						if ( args[i].length() > 2 ) | ||||
| 							usageExit(); | ||||
| 						processing = false; | ||||
| 						break; | ||||
| 					default: | ||||
| 						usageExit(); | ||||
| 						break; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// echo version | ||||
| 			if ( versioninfo ) | ||||
| 				System.out.println(version); | ||||
| 			 | ||||
| 			// new lua state | ||||
| 			_G = nodebug? JsePlatform.standardGlobals(): JsePlatform.debugGlobals(); | ||||
| 			if ( luajc ) LuaJC.install(); | ||||
| 			if ( lua2java) Lua2Java.install(); | ||||
| 			for ( int i=0, n=libs!=null? libs.size(): 0; i<n; i++ ) | ||||
| 				loadLibrary( (String) libs.elementAt(i) ); | ||||
| 			 | ||||
| 			// input script processing | ||||
| 			processing = true; | ||||
| 			for ( int i=0; i<args.length; i++ ) { | ||||
| 				if ( ! processing || ! args[i].startsWith("-") ) { | ||||
| 					processScript( new FileInputStream(args[i]), args[i], args, i ); | ||||
| 					break; | ||||
| 				} else if ( "-".equals( args[i] ) ) { | ||||
| 					processScript( System.in, "=stdin", args, i ); | ||||
| 					break; | ||||
| 				} else { | ||||
| 					switch ( args[i].charAt(1) ) { | ||||
| 					case 'l': | ||||
| 						++i; | ||||
| 						break; | ||||
| 					case 'e': | ||||
| 						++i; | ||||
| 						processScript( new ByteArrayInputStream(args[i].getBytes()), "string", args, i ); | ||||
| 						break; | ||||
| 					case '-': | ||||
| 						processing = false; | ||||
| 						break; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			 | ||||
| 			if ( interactive ) | ||||
| 				interactiveMode(); | ||||
| 			 | ||||
| 		} catch ( IOException ioe ) { | ||||
| 			System.err.println( ioe.toString() ); | ||||
| 			System.exit(-2); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	private static void loadLibrary( String libname ) throws IOException { | ||||
| 		LuaValue slibname =LuaValue.valueOf(libname);  | ||||
| 		try { | ||||
| 			// load via plain require | ||||
| 			_G.get("require").call(slibname); | ||||
| 		} catch ( Exception e ) { | ||||
| 			try { | ||||
| 				// load as java class | ||||
| 				LuaValue v = (LuaValue) Class.forName(libname).newInstance();  | ||||
| 				v.setfenv(_G); | ||||
| 				v.call(slibname, _G); | ||||
| 			} catch ( Exception f ) { | ||||
| 				throw new IOException("loadLibrary("+libname+") failed: "+e+","+f ); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	private static void processScript( InputStream script, String chunkname, String[] args, int firstarg ) throws IOException { | ||||
| 		try { | ||||
| 			LuaFunction c; | ||||
| 			try { | ||||
| 				c = LoadState.load(script, chunkname, _G); | ||||
| 			} finally { | ||||
| 				script.close(); | ||||
| 			} | ||||
| 			Varargs scriptargs = (args!=null? setGlobalArg(args, firstarg): LuaValue.NONE); | ||||
| 			c.invoke( scriptargs ); | ||||
| 		} catch ( Exception e ) { | ||||
| 			e.printStackTrace( System.err ); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	private static Varargs setGlobalArg(String[] args, int i) { | ||||
| 		LuaTable arg = LuaValue.tableOf(); | ||||
| 		for ( int j=0; j<args.length; j++ ) | ||||
| 			arg.set( j-i, LuaValue.valueOf(args[j]) ); | ||||
| 		_G.set( "arg", arg ); | ||||
| 		return _G.get("unpack").invoke(arg); | ||||
| 	} | ||||
|  | ||||
| 	private static void interactiveMode( ) throws IOException { | ||||
| 		BufferedReader reader = new BufferedReader( new InputStreamReader( System.in ) ); | ||||
| 		while ( true ) { | ||||
| 			System.out.print("> "); | ||||
| 			System.out.flush(); | ||||
| 			String line = reader.readLine(); | ||||
| 			if ( line == null ) | ||||
| 				return; | ||||
| 			processScript( new ByteArrayInputStream(line.getBytes()), "=stdin", null, 0 ); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,213 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2010 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
|  | ||||
| import java.io.File; | ||||
| import java.io.FileInputStream; | ||||
| import java.io.FileOutputStream; | ||||
| import java.io.IOException; | ||||
| import java.io.PrintWriter; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.luaj.vm2.Lua; | ||||
| import org.luaj.vm2.ast.Chunk; | ||||
| import org.luaj.vm2.lib.jse.JsePlatform; | ||||
| import org.luaj.vm2.lua2java.JavaCodeGen; | ||||
| import org.luaj.vm2.parser.LuaParser; | ||||
|  | ||||
| /** | ||||
|  * Compile lua sources into java sources.  | ||||
|  */ | ||||
| public class lua2java { | ||||
| 	private static final String version = Lua._VERSION + "Copyright (C) 2010 luaj.org"; | ||||
|  | ||||
| 	private static final String usage =  | ||||
| 		"usage: java -cp luaj-jse.jar lua2java [options] fileordir [, fileordir ...]\n" + | ||||
| 		"Available options are:\n" + | ||||
| 		"  -		process stdin\n" + | ||||
| 		"  -s src	source directory\n" + | ||||
| 		"  -d dir	destination directory\n" + | ||||
| 		"  -p pkg	package prefix to apply to all classes\n" + | ||||
| 		"  -e enc	override default character encoding\n" + | ||||
| 		"  -r		recursively compile all\n" + | ||||
| 		"  -v   	verbose\n"; | ||||
| 	 | ||||
| 	private static void usageExit() { | ||||
| 		System.out.println(usage); | ||||
| 		System.exit(-1);		 | ||||
| 	} | ||||
|  | ||||
| 	private String srcdir = null; | ||||
| 	private String destdir = null; | ||||
| 	private String pkgprefix = null; | ||||
| 	private String encoding = "ISO8859-1"; | ||||
| 	private boolean recurse = false; | ||||
| 	private boolean verbose = false; | ||||
| 	private List files = new ArrayList(); | ||||
|  | ||||
| 	public static void main( String[] args ) throws IOException { | ||||
| 		new lua2java( args ); | ||||
| 	} | ||||
|  | ||||
| 	private lua2java( String[] args ) throws IOException { | ||||
| 		 | ||||
| 		// process args | ||||
| 		try { | ||||
| 			List seeds = new ArrayList (); | ||||
| 			 | ||||
| 			// get stateful args | ||||
| 			for ( int i=0; i<args.length; i++ ) { | ||||
| 				if ( ! args[i].startsWith("-") ) { | ||||
| 					seeds.add(args[i]); | ||||
| 				} else { | ||||
| 					switch ( args[i].charAt(1) ) { | ||||
| 					case 's': | ||||
| 						if ( ++i >= args.length ) | ||||
| 							usageExit(); | ||||
| 						srcdir = args[i]; | ||||
| 						break; | ||||
| 					case 'd': | ||||
| 						if ( ++i >= args.length ) | ||||
| 							usageExit(); | ||||
| 						destdir = args[i]; | ||||
| 						break; | ||||
| 					case 'p': | ||||
| 						if ( ++i >= args.length ) | ||||
| 							usageExit(); | ||||
| 						pkgprefix = args[i]; | ||||
| 						break; | ||||
| 					case 'e': | ||||
| 						if ( ++i >= args.length ) | ||||
| 							usageExit(); | ||||
| 						encoding = args[i]; | ||||
| 						break; | ||||
| 					case 'r': | ||||
| 						recurse = true; | ||||
| 						break; | ||||
| 					case 'v': | ||||
| 						verbose = true; | ||||
| 						break; | ||||
| 					default: | ||||
| 						usageExit(); | ||||
| 						break; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			 | ||||
| 			// echo version | ||||
| 			if ( verbose ) { | ||||
| 				System.out.println(version); | ||||
| 				System.out.println("srcdir: "+srcdir); | ||||
| 				System.out.println("destdir: "+destdir); | ||||
| 				System.out.println("files: "+seeds); | ||||
| 				System.out.println("encoding: "+encoding); | ||||
| 				System.out.println("recurse: "+recurse); | ||||
| 			} | ||||
| 			 | ||||
| 			// need at least one seed | ||||
| 			if ( seeds.size() <= 0 ) { | ||||
| 				System.err.println(usage); | ||||
| 				System.exit(-1); | ||||
| 			} | ||||
|  | ||||
| 			// collect up files to process | ||||
| 			for ( int i=0; i<seeds.size(); i++ ) | ||||
| 				collectFiles( srcdir+"/"+seeds.get(i) ); | ||||
| 			 | ||||
| 			// check for at least one file | ||||
| 			if ( files.size() <= 0 ) { | ||||
| 				System.err.println("no files found in "+seeds); | ||||
| 				System.exit(-1); | ||||
| 			} | ||||
| 			 | ||||
| 			// process input files | ||||
| 			JsePlatform.standardGlobals(); | ||||
| 			for ( int i=0,n=files.size(); i<n; i++ ) | ||||
| 				processFile( (InputFile) files.get(i) ); | ||||
| 			 | ||||
| 		} catch ( Exception ioe ) { | ||||
| 			System.err.println( ioe.toString() ); | ||||
| 			System.exit(-2); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	private void collectFiles(String path) { | ||||
| 		File f = new File(path); | ||||
| 		if ( f.isDirectory() && recurse ) | ||||
| 			scandir(f,pkgprefix); | ||||
| 		else if ( f.isFile() ) { | ||||
| 			File dir = f.getAbsoluteFile().getParentFile(); | ||||
| 			if ( dir != null ) | ||||
| 				scanfile( dir, f, pkgprefix ); | ||||
| 		} | ||||
| 	} | ||||
| 	private void scandir(File dir, String javapackage) { | ||||
| 		File[] f = dir.listFiles(); | ||||
| 		for ( int i=0; i<f.length; i++ )  | ||||
| 			scanfile( dir, f[i], javapackage ); | ||||
| 	} | ||||
|  | ||||
| 	private void scanfile(File dir, File f, String javapackage) { | ||||
| 		if ( f.exists() ) { | ||||
| 			if ( f.isDirectory() && recurse ) | ||||
| 				scandir( f, (javapackage!=null? javapackage+"."+f.getName(): f.getName()) ); | ||||
| 			else if ( f.isFile() && f.getName().endsWith(".lua") ) | ||||
| 				files.add( new InputFile(dir,f,javapackage) ); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	class InputFile { | ||||
| 		public File infile; | ||||
| 		public File outdir; | ||||
| 		public File outfile; | ||||
| 		public String javapackage; | ||||
| 		public String javaclassname; | ||||
| 		public InputFile(File dir, File f, String javapackage) { | ||||
| 			String outdirpath = javapackage!=null? destdir+"/"+javapackage.replace('.', '/'): destdir; | ||||
| 			this.javaclassname = f.getName().substring(0,f.getName().lastIndexOf('.')); | ||||
| 			this.javapackage = javapackage; | ||||
| 			this.infile = f; | ||||
| 			this.outdir = new File(outdirpath); | ||||
| 			this.outfile = new File(outdirpath+"/"+this.javaclassname+".java"); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	private void processFile( InputFile inf ) { | ||||
| 		inf.outdir.mkdirs(); | ||||
| 		try { | ||||
| 			if ( verbose )  | ||||
| 				System.out.println( | ||||
| 					"pkg="+inf.javapackage+" file="+inf.javaclassname+".java dest="+inf.outfile+" src="+inf.infile); | ||||
| 			FileInputStream in = new FileInputStream(inf.infile); | ||||
| 			FileOutputStream out = new FileOutputStream(inf.outfile); | ||||
| 			PrintWriter pw = new PrintWriter(out); | ||||
| 		    LuaParser parser = new LuaParser(in,encoding); | ||||
| 		    Chunk chunk = parser.Chunk(); | ||||
| 			new JavaCodeGen(chunk,pw,inf.javapackage,inf.javaclassname); | ||||
| 			pw.close(); | ||||
| 			out.close(); | ||||
| 			in.close(); | ||||
| 		} catch ( Exception e ) { | ||||
| 			e.printStackTrace( System.err ); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,181 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
|  | ||||
| import java.io.FileInputStream; | ||||
| import java.io.FileOutputStream; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStream; | ||||
| import java.io.OutputStream; | ||||
|  | ||||
| import org.luaj.vm2.Lua; | ||||
| import org.luaj.vm2.Print; | ||||
| import org.luaj.vm2.Prototype; | ||||
| import org.luaj.vm2.compiler.DumpState; | ||||
| import org.luaj.vm2.compiler.LuaC; | ||||
| import org.luaj.vm2.lib.jse.JsePlatform; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Compiler for lua files to lua bytecode.  | ||||
|  */ | ||||
| public class luac { | ||||
| 	private static final String version = Lua._VERSION + "Copyright (C) 2009 luaj.org"; | ||||
|  | ||||
| 	private static final String usage =  | ||||
| 		"usage: java -cp luaj-jse.jar luac [options] [filenames].\n" + | ||||
| 		"Available options are:\n" + | ||||
| 		"  -        process stdin\n" + | ||||
| 		"  -l       list\n" + | ||||
| 		"  -o name  output to file 'name' (default is \"luac.out\")\n" + | ||||
| 		"  -p       parse only\n" + | ||||
| 		"  -s       strip debug information\n" + | ||||
| 		"  -e       little endian format for numbers\n" + | ||||
| 		"  -i<n>    number format 'n', (n=0,1 or 4, default="+DumpState.NUMBER_FORMAT_DEFAULT+")\n" + | ||||
| 		"  -v       show version information\n" + | ||||
| 		"  --       stop handling options\n"; | ||||
| 	 | ||||
| 	private static void usageExit() { | ||||
| 		System.out.println(usage); | ||||
| 		System.exit(-1);		 | ||||
| 	} | ||||
|  | ||||
| 	private boolean list = false; | ||||
| 	private String output = "luac.out"; | ||||
| 	private boolean parseonly = false; | ||||
| 	private boolean stripdebug = false; | ||||
| 	private boolean littleendian = false; | ||||
| 	private int numberformat = DumpState.NUMBER_FORMAT_DEFAULT; | ||||
| 	private boolean versioninfo = false; | ||||
| 	private boolean processing = true; | ||||
|  | ||||
| 	public static void main( String[] args ) throws IOException { | ||||
| 		new luac( args ); | ||||
| 	} | ||||
|  | ||||
| 	private luac( String[] args ) throws IOException { | ||||
| 		 | ||||
| 		// process args | ||||
| 		try { | ||||
| 			// get stateful args | ||||
| 			for ( int i=0; i<args.length; i++ ) { | ||||
| 				if ( ! processing || ! args[i].startsWith("-") ) { | ||||
| 					// input file - defer to next stage | ||||
| 				} else if ( args[i].length() <= 1 ) { | ||||
| 					// input file - defer to next stage | ||||
| 				} else { | ||||
| 					switch ( args[i].charAt(1) ) { | ||||
| 					case 'l': | ||||
| 						list = true; | ||||
| 						break; | ||||
| 					case 'o': | ||||
| 						if ( ++i >= args.length ) | ||||
| 							usageExit(); | ||||
| 						output = args[i]; | ||||
| 						break; | ||||
| 					case 'p': | ||||
| 						parseonly = true; | ||||
| 						break; | ||||
| 					case 's': | ||||
| 						stripdebug = true; | ||||
| 						break; | ||||
| 					case 'e': | ||||
| 						littleendian = true; | ||||
| 						break; | ||||
| 					case 'i': | ||||
| 						if ( args[i].length() <= 2 ) | ||||
| 							usageExit(); | ||||
| 						numberformat = Integer.parseInt(args[i].substring(2)); | ||||
| 						break; | ||||
| 					case 'v': | ||||
| 						versioninfo = true; | ||||
| 						break; | ||||
| 					case '-': | ||||
| 						if ( args[i].length() > 2 ) | ||||
| 							usageExit(); | ||||
| 						processing = false; | ||||
| 						break; | ||||
| 					default: | ||||
| 						usageExit(); | ||||
| 						break; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			 | ||||
| 			// echo version | ||||
| 			if ( versioninfo ) | ||||
| 				System.out.println(version); | ||||
|  | ||||
| 			// open output file | ||||
| 			OutputStream fos = new FileOutputStream( output ); | ||||
| 			 | ||||
| 			// process input files | ||||
| 			try { | ||||
| 				JsePlatform.standardGlobals(); | ||||
| 				processing = true; | ||||
| 				for ( int i=0; i<args.length; i++ ) { | ||||
| 					if ( ! processing || ! args[i].startsWith("-") ) { | ||||
| 						String chunkname = args[i].substring(0,args[i].length()-4); | ||||
| 						processScript( new FileInputStream(args[i]), chunkname, fos ); | ||||
| 					} else if ( args[i].length() <= 1 ) { | ||||
| 						processScript( System.in, "=stdin", fos ); | ||||
| 					} else { | ||||
| 						switch ( args[i].charAt(1) ) { | ||||
| 						case 'o': | ||||
| 							++i; | ||||
| 							break; | ||||
| 						case '-': | ||||
| 							processing = false; | ||||
| 							break; | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} finally { | ||||
| 				fos.close(); | ||||
| 			} | ||||
| 			 | ||||
| 		} catch ( IOException ioe ) { | ||||
| 			System.err.println( ioe.toString() ); | ||||
| 			System.exit(-2); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	private void processScript( InputStream script, String chunkname, OutputStream out ) throws IOException { | ||||
| 		try { | ||||
| 	        // create the chunk | ||||
| 	        Prototype chunk = LuaC.instance.compile(script, chunkname); | ||||
|  | ||||
| 	        // list the chunk | ||||
| 	        if (list) | ||||
| 	            Print.printCode(chunk); | ||||
|  | ||||
| 	        // write out the chunk | ||||
| 	        if (!parseonly) { | ||||
| 	            DumpState.dump(chunk, out, stripdebug, numberformat, littleendian); | ||||
| 	        } | ||||
| 	         | ||||
| 		} catch ( Exception e ) { | ||||
| 			e.printStackTrace( System.err ); | ||||
| 		} finally { | ||||
| 			script.close(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,245 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2009 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
|  | ||||
| import java.io.File; | ||||
| import java.io.FileInputStream; | ||||
| import java.io.FileOutputStream; | ||||
| import java.io.IOException; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Enumeration; | ||||
| import java.util.Hashtable; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.luaj.vm2.Lua; | ||||
| import org.luaj.vm2.lib.jse.JsePlatform; | ||||
| import org.luaj.vm2.luajc.LuaJC; | ||||
|  | ||||
| /** | ||||
|  * Compiler for lua files to compile lua sources or lua binaries into java classes.  | ||||
|  */ | ||||
| public class luajc { | ||||
| 	private static final String version = Lua._VERSION + "Copyright (C) 2009 luaj.org"; | ||||
|  | ||||
| 	private static final String usage =  | ||||
| 		"usage: java -cp luaj-jse.jar,bcel-5.2.jar luajc [options] fileordir [, fileordir ...]\n" + | ||||
| 		"Available options are:\n" + | ||||
| 		"  -        process stdin\n" + | ||||
| 		"  -s src	source directory\n" + | ||||
| 		"  -d dir	destination directory\n" + | ||||
| 		"  -p pkg	package prefix to apply to all classes\n" + | ||||
| 		"  -r		recursively compile all\n" + | ||||
| 		"  -l		load classes to verify generated bytecode\n" + | ||||
| 		"  -v   	verbose\n"; | ||||
| 	 | ||||
| 	private static void usageExit() { | ||||
| 		System.out.println(usage); | ||||
| 		System.exit(-1);		 | ||||
| 	} | ||||
|  | ||||
| 	private String srcdir = null; | ||||
| 	private String destdir = null; | ||||
| 	private boolean recurse = false; | ||||
| 	private boolean verbose = false; | ||||
| 	private boolean loadclasses = false; | ||||
| 	private String pkgprefix = null; | ||||
| 	private List files = new ArrayList(); | ||||
|  | ||||
| 	public static void main( String[] args ) throws IOException { | ||||
| 		new luajc( args ); | ||||
| 	} | ||||
|  | ||||
| 	private luajc( String[] args ) throws IOException { | ||||
| 		 | ||||
| 		// process args | ||||
| 		List seeds = new ArrayList (); | ||||
| 		 | ||||
| 		// get stateful args | ||||
| 		for ( int i=0; i<args.length; i++ ) { | ||||
| 			if ( ! args[i].startsWith("-") ) { | ||||
| 				seeds.add(args[i]); | ||||
| 			} else { | ||||
| 				switch ( args[i].charAt(1) ) { | ||||
| 				case 's': | ||||
| 					if ( ++i >= args.length ) | ||||
| 						usageExit(); | ||||
| 					srcdir = args[i]; | ||||
| 					break; | ||||
| 				case 'd': | ||||
| 					if ( ++i >= args.length ) | ||||
| 						usageExit(); | ||||
| 					destdir = args[i]; | ||||
| 					break; | ||||
| 				case 'l': | ||||
| 					loadclasses = true; | ||||
| 					break; | ||||
| 				case 'p': | ||||
| 					if ( ++i >= args.length ) | ||||
| 						usageExit(); | ||||
| 					pkgprefix = args[i]; | ||||
| 					break; | ||||
| 				case 'r': | ||||
| 					recurse = true; | ||||
| 					break; | ||||
| 				case 'v': | ||||
| 					verbose = true; | ||||
| 					break; | ||||
| 				default: | ||||
| 					usageExit(); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		// echo version | ||||
| 		if ( verbose ) { | ||||
| 			System.out.println(version); | ||||
| 			System.out.println("srcdir: "+srcdir); | ||||
| 			System.out.println("destdir: "+srcdir); | ||||
| 			System.out.println("files: "+seeds); | ||||
| 			System.out.println("recurse: "+recurse); | ||||
| 		} | ||||
|  | ||||
| 		// need at least one seed | ||||
| 		if ( seeds.size() <= 0 ) { | ||||
| 			System.err.println(usage); | ||||
| 			System.exit(-1); | ||||
| 		} | ||||
|  | ||||
| 		// collect up files to process | ||||
| 		for ( int i=0; i<seeds.size(); i++ ) | ||||
| 			collectFiles( srcdir+"/"+seeds.get(i) ); | ||||
| 		 | ||||
| 		// check for at least one file | ||||
| 		if ( files.size() <= 0 ) { | ||||
| 			System.err.println("no files found in "+seeds); | ||||
| 			System.exit(-1); | ||||
| 		} | ||||
| 		 | ||||
| 		// process input files | ||||
| 		JsePlatform.standardGlobals(); | ||||
| 		for ( int i=0,n=files.size(); i<n; i++ ) | ||||
| 			processFile( (InputFile) files.get(i) ); | ||||
| 	} | ||||
| 	 | ||||
| 	private void collectFiles(String path) { | ||||
| 		File f = new File(path); | ||||
| 		if ( f.isDirectory() && recurse ) | ||||
| 			scandir(f,pkgprefix); | ||||
| 		else if ( f.isFile() ) { | ||||
| 			File dir = f.getAbsoluteFile().getParentFile(); | ||||
| 			if ( dir != null ) | ||||
| 				scanfile( dir, f, pkgprefix ); | ||||
| 		} | ||||
| 	} | ||||
| 	private void scandir(File dir, String javapackage) { | ||||
| 		File[] f = dir.listFiles(); | ||||
| 		for ( int i=0; i<f.length; i++ )  | ||||
| 			scanfile( dir, f[i], javapackage ); | ||||
| 	} | ||||
|  | ||||
| 	private void scanfile(File dir, File f, String javapackage) { | ||||
| 		if ( f.exists() ) { | ||||
| 			if ( f.isDirectory() && recurse ) | ||||
| 				scandir( f, (javapackage!=null? javapackage+"."+f.getName(): f.getName()) ); | ||||
| 			else if ( f.isFile() && f.getName().endsWith(".lua") ) | ||||
| 				files.add( new InputFile(dir,f,javapackage) ); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	class InputFile { | ||||
| 		public String luachunkname; | ||||
| 		public String srcfilename; | ||||
| 		public File infile; | ||||
| 		public File outdir; | ||||
| 		public String javapackage; | ||||
| 		 | ||||
| 		public InputFile(File dir, File f, String javapackage) { | ||||
| 			this.infile = f; | ||||
| 			String subdir = javapackage!=null? javapackage.replace('.', '/'): null; | ||||
| 			String outdirpath = subdir!=null? destdir+"/"+subdir: destdir; | ||||
| 			this.javapackage = javapackage; | ||||
| 			this.srcfilename = (subdir!=null? subdir+"/": "")+infile.getName(); | ||||
| 			this.luachunkname = (subdir!=null? subdir+"/": "")+infile.getName().substring( 0, infile.getName().lastIndexOf('.') ); | ||||
| 			this.infile = f; | ||||
| 			this.outdir = new File(outdirpath); | ||||
| 		} | ||||
| 	} | ||||
| 		 | ||||
| 	private void processFile( InputFile inf ) { | ||||
| 		inf.outdir.mkdirs(); | ||||
| 		try { | ||||
| 			if ( verbose )  | ||||
| 				System.out.println("chunk="+inf.luachunkname+" srcfile="+inf.srcfilename); | ||||
|  | ||||
| 	        // create the chunk | ||||
| 			FileInputStream fis = new FileInputStream( inf.infile ); | ||||
| 			final Hashtable t = LuaJC.getInstance().compileAll(fis, inf.luachunkname, inf.srcfilename); | ||||
| 			fis.close(); | ||||
| 			 | ||||
| 	        // write out the chunk | ||||
|         	for ( Enumeration e = t.keys(); e.hasMoreElements(); ) { | ||||
|         		String key = (String) e.nextElement(); | ||||
|         		byte[] bytes = (byte[]) t.get(key); | ||||
|         		if ( key.indexOf('/')>=0 ) { | ||||
|         			String d = (destdir!=null? destdir+"/": "")+key.substring(0,key.lastIndexOf('/')); | ||||
|         			new File(d).mkdirs(); | ||||
|         		} | ||||
|         		String destpath = (destdir!=null? destdir+"/": "") + key + ".class"; | ||||
|     			if ( verbose ) | ||||
|     				System.out.println( "  "+destpath +" ("+bytes.length+" bytes)"); | ||||
| 	        	FileOutputStream fos = new FileOutputStream( destpath ); | ||||
| 	        	fos.write( bytes ); | ||||
| 	        	fos.close(); | ||||
| 	        } | ||||
|  | ||||
|         	// try to load the files | ||||
|         	if ( loadclasses ) { | ||||
| 				ClassLoader loader = new ClassLoader() { | ||||
| 			         public Class findClass(String classname) throws ClassNotFoundException { | ||||
| 			        	 byte[] bytes = (byte[]) t.get(classname); | ||||
| 			        	 if ( bytes != null ) | ||||
| 			        		 return defineClass(classname, bytes, 0, bytes.length); | ||||
| 			        	 return super.findClass(classname); | ||||
| 			         } | ||||
| 				}; | ||||
|             	for ( Enumeration e = t.keys(); e.hasMoreElements(); ) { | ||||
|                 	String classname = (String) e.nextElement(); | ||||
| 	        		try { | ||||
|                 		Class c = loader.loadClass(classname); | ||||
|                 		Object o = c.newInstance(); | ||||
|                 		if ( verbose ) | ||||
|     	        			System.out.println("    loaded "+classname+" as "+o ); | ||||
| 	        		} catch ( Exception ex ) { | ||||
| 	        			System.out.flush(); | ||||
| 	        			System.err.println("    failed to load "+classname+": "+ex ); | ||||
| 	        			System.err.flush(); | ||||
| 	        		} | ||||
|             	} | ||||
|         	} | ||||
|         	 | ||||
| 		} catch ( Exception e ) { | ||||
| 			System.err.println("    failed to load "+inf.srcfilename+": "+e ); | ||||
| 			e.printStackTrace( System.err ); | ||||
| 			System.err.flush(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,41 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2010 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.ast; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| public class Block extends Stat { | ||||
| 	 | ||||
| 	public List<Stat> stats = new ArrayList<Stat>(); | ||||
| 	public NameScope scope; | ||||
| 	 | ||||
| 	public void add(Stat s) { | ||||
| 		if ( s == null ) | ||||
| 			return; | ||||
| 		stats.add(s); | ||||
| 	} | ||||
|  | ||||
| 	public void accept(Visitor visitor) { | ||||
| 		visitor.visit(this); | ||||
| 	} | ||||
| } | ||||
| @@ -1,34 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2010 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.ast; | ||||
|  | ||||
| public class Chunk { | ||||
| 	public final Block block; | ||||
| 	 | ||||
| 	public Chunk(Block b) { | ||||
| 		this.block = b; | ||||
| 	} | ||||
| 	 | ||||
| 	public void accept( Visitor visitor ) { | ||||
| 		visitor.visit( this ); | ||||
| 	} | ||||
| } | ||||
| @@ -1,313 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2010 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.ast; | ||||
|  | ||||
| import org.luaj.vm2.Lua; | ||||
| import org.luaj.vm2.LuaValue; | ||||
|  | ||||
| abstract | ||||
| public class Exp { | ||||
| 	abstract public void accept(Visitor visitor); | ||||
|  | ||||
| 	public static Exp constant(LuaValue value) { | ||||
| 		return new Constant(value); | ||||
| 	} | ||||
|  | ||||
| 	public static Exp numberconstant(String token) {		 | ||||
| 		return new Constant( LuaValue.valueOf(token).tonumber() ); | ||||
| 	} | ||||
|  | ||||
| 	public static Exp varargs() { | ||||
| 		return new VarargsExp(); | ||||
| 	} | ||||
|  | ||||
| 	public static Exp tableconstructor(TableConstructor tc) { | ||||
| 		return tc; | ||||
| 	} | ||||
|  | ||||
| 	public static Exp unaryexp(int op, Exp rhs) { | ||||
| 		if ( rhs instanceof BinopExp ) { | ||||
| 			BinopExp b = (BinopExp) rhs; | ||||
| 			if ( precedence(op) > precedence(b.op)  ) | ||||
| 				return binaryexp( unaryexp(op, b.lhs), b.op, b.rhs ); | ||||
| 		} | ||||
| 		return new UnopExp(op, rhs); | ||||
| 	} | ||||
|  | ||||
| 	public static Exp binaryexp(Exp lhs, int op, Exp rhs) { | ||||
| 		if ( lhs instanceof UnopExp ) { | ||||
| 			UnopExp u = (UnopExp) lhs; | ||||
| 			if ( precedence(op) > precedence(u.op) ) | ||||
| 				return unaryexp( u.op, binaryexp( u.rhs, op, rhs ) ); | ||||
| 		} | ||||
| 		// TODO: cumulate string concatenations together | ||||
| 		// TODO: constant folding | ||||
| 		if ( lhs instanceof BinopExp ) { | ||||
| 			BinopExp b = (BinopExp) lhs; | ||||
| 			if ( (precedence(op) > precedence(b.op)) || | ||||
| 				 ((precedence(op) == precedence(b.op)) && isrightassoc(op)) ) | ||||
| 				return binaryexp( b.lhs, b.op, binaryexp( b.rhs, op, rhs ) ); | ||||
| 		} | ||||
| 		if ( rhs instanceof BinopExp ) { | ||||
| 			BinopExp b = (BinopExp) rhs; | ||||
| 			if ( (precedence(op) > precedence(b.op)) || | ||||
| 				 ((precedence(op) == precedence(b.op)) && ! isrightassoc(op)) ) | ||||
| 				return binaryexp( binaryexp( lhs, op, b.lhs ), b.op, b.rhs ); | ||||
| 		} | ||||
| 		return new BinopExp(lhs, op, rhs); | ||||
| 	} | ||||
|  | ||||
| 	static boolean isrightassoc(int op) { | ||||
| 		switch ( op ) { | ||||
| 		case Lua.OP_CONCAT: | ||||
| 		case Lua.OP_POW: return true; | ||||
| 		default: return false; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	static int precedence(int op) { | ||||
| 		switch ( op ) { | ||||
| 		case Lua.OP_OR: return 0; | ||||
| 		case Lua.OP_AND: return 1; | ||||
| 		case Lua.OP_LT: case Lua.OP_GT: case Lua.OP_LE: case Lua.OP_GE: case Lua.OP_NEQ: case Lua.OP_EQ: return 2; | ||||
| 		case Lua.OP_CONCAT: return 3; | ||||
| 		case Lua.OP_ADD: case Lua.OP_SUB: return 4; | ||||
| 		case Lua.OP_MUL: case Lua.OP_DIV: case Lua.OP_MOD: return 5; | ||||
| 		case Lua.OP_NOT: case Lua.OP_UNM: case Lua.OP_LEN: return 6; | ||||
| 		case Lua.OP_POW: return 7; | ||||
| 		default: throw new IllegalStateException("precedence of bad op "+op); | ||||
| 		} | ||||
| 	}	 | ||||
| 	 | ||||
| 	public static Exp anonymousfunction(FuncBody funcbody) { | ||||
| 		return new AnonFuncDef(funcbody); | ||||
| 	} | ||||
|  | ||||
| 	/** foo */ | ||||
| 	public static NameExp nameprefix(String name) { | ||||
| 		return new NameExp(name); | ||||
| 	} | ||||
|  | ||||
| 	/** ( foo.bar ) */ | ||||
| 	public static ParensExp parensprefix(Exp exp) { | ||||
| 		return new ParensExp(exp); | ||||
| 	} | ||||
|  | ||||
| 	/** foo[exp] */ | ||||
| 	public static IndexExp indexop(PrimaryExp lhs, Exp exp) { | ||||
| 		return new IndexExp(lhs, exp); | ||||
| 	} | ||||
|  | ||||
| 	/** foo.bar */ | ||||
| 	public static FieldExp fieldop(PrimaryExp lhs, String name) { | ||||
| 		return new FieldExp(lhs, name); | ||||
| 	} | ||||
|  | ||||
| 	/** foo(2,3) */ | ||||
| 	public static FuncCall functionop(PrimaryExp lhs, FuncArgs args) { | ||||
| 		return new FuncCall(lhs, args); | ||||
| 	} | ||||
|  | ||||
| 	/** foo:bar(4,5) */ | ||||
| 	public static MethodCall methodop(PrimaryExp lhs, String name, FuncArgs args) { | ||||
| 		return new MethodCall(lhs, name, args); | ||||
| 	} | ||||
|  | ||||
| 	public boolean isvarexp() { | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	public boolean isfunccall() { | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	public boolean isvarargexp() { | ||||
| 		return false; | ||||
| 	} | ||||
| 	 | ||||
| 	abstract public static class PrimaryExp extends Exp { | ||||
| 		public boolean isvarexp() { | ||||
| 			return false; | ||||
| 		} | ||||
| 		public boolean isfunccall() { | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	abstract public static class VarExp extends PrimaryExp { | ||||
| 		public boolean isvarexp() { | ||||
| 			return true; | ||||
| 		} | ||||
| 		public void markHasAssignment() { | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	public static class NameExp extends VarExp { | ||||
| 		public final Name name; | ||||
| 		public NameExp(String name) { | ||||
| 			this.name = new Name(name); | ||||
| 		} | ||||
| 		public void markHasAssignment() { | ||||
| 			name.variable.hasassignments = true; | ||||
| 		} | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit(this); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	public static class ParensExp extends PrimaryExp { | ||||
| 		public final Exp exp; | ||||
| 		public ParensExp(Exp exp) { | ||||
| 			this.exp = exp; | ||||
| 		} | ||||
| 		 | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit(this); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	public static class FieldExp extends VarExp { | ||||
| 		public final PrimaryExp lhs; | ||||
| 		public final Name name; | ||||
| 		public FieldExp(PrimaryExp lhs, String name) { | ||||
| 			this.lhs = lhs; | ||||
| 			this.name = new Name(name); | ||||
| 		} | ||||
| 		 | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit(this); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	public static class IndexExp extends VarExp { | ||||
| 		public final PrimaryExp lhs; | ||||
| 		public final Exp exp; | ||||
| 		public IndexExp(PrimaryExp lhs, Exp exp) { | ||||
| 			this.lhs = lhs; | ||||
| 			this.exp = exp; | ||||
| 		} | ||||
| 		 | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit(this); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	public static class FuncCall extends PrimaryExp { | ||||
| 		public final PrimaryExp lhs; | ||||
| 		public final FuncArgs args; | ||||
| 		 | ||||
| 		public FuncCall(PrimaryExp lhs, FuncArgs args) { | ||||
| 			this.lhs = lhs; | ||||
| 			this.args = args; | ||||
| 		} | ||||
|  | ||||
| 		public boolean isfunccall() { | ||||
| 			return true; | ||||
| 		} | ||||
| 		 | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit(this); | ||||
| 		} | ||||
| 		 | ||||
| 		public boolean isvarargexp() { | ||||
| 			return true; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	public static class MethodCall extends FuncCall { | ||||
| 		public final String name; | ||||
| 		 | ||||
| 		public MethodCall(PrimaryExp lhs, String name, FuncArgs args) { | ||||
| 			super(lhs, args); | ||||
| 			this.name = new String(name); | ||||
| 		} | ||||
|  | ||||
| 		public boolean isfunccall() { | ||||
| 			return true; | ||||
| 		} | ||||
| 		 | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit(this); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public static class Constant extends Exp { | ||||
| 		public final LuaValue value; | ||||
| 		public Constant(LuaValue value) { | ||||
| 			this.value = value; | ||||
| 		} | ||||
|  | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit(this); | ||||
| 		}		 | ||||
| 	} | ||||
|  | ||||
| 	public static class VarargsExp extends Exp { | ||||
| 		 | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit(this); | ||||
| 		} | ||||
| 		 | ||||
| 		public boolean isvarargexp() { | ||||
| 			return true; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	public static class UnopExp extends Exp { | ||||
| 		public final int op; | ||||
| 		public final Exp rhs; | ||||
| 		public UnopExp(int op, Exp rhs) { | ||||
| 			this.op = op; | ||||
| 			this.rhs = rhs; | ||||
| 		} | ||||
|  | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit(this); | ||||
| 		}		 | ||||
| 	} | ||||
| 	 | ||||
| 	public static class BinopExp extends Exp { | ||||
| 		public final Exp lhs,rhs; | ||||
| 		public final int op; | ||||
| 		public BinopExp(Exp lhs, int op, Exp rhs) { | ||||
| 			this.lhs = lhs; | ||||
| 			this.op = op; | ||||
| 			this.rhs = rhs; | ||||
| 		} | ||||
|  | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit(this); | ||||
| 		}		 | ||||
| 	} | ||||
| 	 | ||||
| 	public static class AnonFuncDef extends Exp { | ||||
| 		public final FuncBody body; | ||||
| 		public AnonFuncDef(FuncBody funcbody) { | ||||
| 			this.body = funcbody; | ||||
| 		} | ||||
|  | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit(this); | ||||
| 		}		 | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -1,66 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2010 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.ast; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.luaj.vm2.LuaString; | ||||
|  | ||||
| public class FuncArgs { | ||||
|  | ||||
| 	public final List<Exp> exps; | ||||
| 	 | ||||
| 	/** exp1,exp2... */ | ||||
| 	public static FuncArgs explist(List<Exp> explist) { | ||||
| 		return new FuncArgs(explist); | ||||
| 	} | ||||
|  | ||||
| 	/** {...} */ | ||||
| 	public static FuncArgs tableconstructor(TableConstructor table) { | ||||
| 		return new FuncArgs(table); | ||||
| 	} | ||||
|  | ||||
| 	/** "mylib" */ | ||||
| 	public static FuncArgs string(LuaString string) { | ||||
| 		return new FuncArgs(string); | ||||
| 	} | ||||
|  | ||||
| 	public FuncArgs(List<Exp> exps) { | ||||
| 		this.exps = exps; | ||||
| 	} | ||||
|  | ||||
| 	public FuncArgs(LuaString string) { | ||||
| 		this.exps = new ArrayList<Exp>(); | ||||
| 		this.exps.add( Exp.constant(string) ); | ||||
| 	} | ||||
|  | ||||
| 	public FuncArgs(TableConstructor table) { | ||||
| 		this.exps = new ArrayList<Exp>(); | ||||
| 		this.exps.add( table ); | ||||
| 	} | ||||
|  | ||||
| 	public void accept(Visitor visitor) { | ||||
| 		visitor.visit(this); | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -1,36 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2010 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.ast; | ||||
|  | ||||
| public class FuncBody { | ||||
| 	public ParList parlist; | ||||
| 	public Block block; | ||||
| 	public NameScope scope; | ||||
|  | ||||
| 	public FuncBody(ParList parlist, Block block) { | ||||
| 		this.parlist = parlist!=null? parlist: ParList.EMPTY_PARLIST; | ||||
| 		this.block = block; | ||||
| 	} | ||||
| 	public void accept(Visitor visitor) { | ||||
| 		visitor.visit(this); | ||||
| 	} | ||||
| } | ||||
| @@ -1,49 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2010 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.ast; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| public class FuncName { | ||||
| 	// example: a.b.c.d:e | ||||
| 	 | ||||
| 	// initial base name: "a" | ||||
| 	public final Name name; | ||||
| 	 | ||||
| 	// intermediate field accesses: "b", "c", "d" | ||||
| 	public List<String> dots; | ||||
| 	 | ||||
| 	// optional final method name: "e" | ||||
| 	public String method; | ||||
| 	 | ||||
| 	public FuncName( String name ) { | ||||
| 		this.name = new Name(name); | ||||
| 	} | ||||
| 	 | ||||
| 	public void adddot(String dot) { | ||||
| 		if ( dots == null ) | ||||
| 			dots = new ArrayList<String>(); | ||||
| 		dots.add(dot); | ||||
| 	} | ||||
| 	 | ||||
| } | ||||
| @@ -1,31 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2010 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.ast; | ||||
|  | ||||
|  | ||||
| public class Name { | ||||
| 	public final String name; | ||||
| 	public Variable variable; | ||||
| 	public Name(String name) { | ||||
| 		this.name = name; | ||||
| 	} | ||||
| } | ||||
| @@ -1,127 +0,0 @@ | ||||
| package org.luaj.vm2.ast; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import org.luaj.vm2.LuaValue; | ||||
| import org.luaj.vm2.ast.Exp.Constant; | ||||
| import org.luaj.vm2.ast.Exp.NameExp; | ||||
| import org.luaj.vm2.ast.Exp.VarExp; | ||||
| import org.luaj.vm2.ast.Stat.Assign; | ||||
| import org.luaj.vm2.ast.Stat.FuncDef; | ||||
| import org.luaj.vm2.ast.Stat.GenericFor; | ||||
| import org.luaj.vm2.ast.Stat.LocalAssign; | ||||
| import org.luaj.vm2.ast.Stat.LocalFuncDef; | ||||
| import org.luaj.vm2.ast.Stat.NumericFor; | ||||
|  | ||||
| /**  | ||||
|  * Visitor that resolves names to scopes. | ||||
|  * Each Name is resolved to a NamedVarible, possibly in a NameScope  | ||||
|  * if it is a local, or in no named scope if it is a global.  | ||||
|  */ | ||||
| public class NameResolver extends Visitor { | ||||
|  | ||||
| 	private NameScope scope = null; | ||||
|  | ||||
| 	private void pushScope() { | ||||
| 		scope = new NameScope(scope); | ||||
| 	} | ||||
| 	private void popScope() { | ||||
| 		scope = scope.outerScope; | ||||
| 	} | ||||
| 	 | ||||
| 	public void visit(NameScope scope) { | ||||
| 	}	 | ||||
|  | ||||
| 	public void visit(Block block) { | ||||
| 		pushScope(); | ||||
| 		block.scope = scope; | ||||
| 		super.visit(block); | ||||
| 		popScope(); | ||||
| 	} | ||||
| 	 | ||||
| 	public void visit(FuncBody body) { | ||||
| 		pushScope(); | ||||
| 		scope.functionNestingCount++; | ||||
| 		body.scope = scope; | ||||
| 		super.visit(body); | ||||
| 		popScope(); | ||||
| 	} | ||||
| 	 | ||||
| 	public void visit(LocalFuncDef stat) { | ||||
| 		defineLocalVar(stat.name); | ||||
| 		super.visit(stat); | ||||
| 	} | ||||
|  | ||||
| 	public void visit(NumericFor stat) { | ||||
| 		pushScope(); | ||||
| 		stat.scope = scope; | ||||
| 		defineLocalVar(stat.name); | ||||
| 		super.visit(stat); | ||||
| 		popScope(); | ||||
| 	} | ||||
|  | ||||
| 	public void visit(GenericFor stat) { | ||||
| 		pushScope(); | ||||
| 		stat.scope = scope; | ||||
| 		defineLocalVars( stat.names ); | ||||
| 		super.visit(stat); | ||||
| 		popScope(); | ||||
| 	} | ||||
|  | ||||
| 	public void visit(NameExp exp) { | ||||
| 		exp.name.variable = resolveNameReference(exp.name); | ||||
| 		super.visit(exp); | ||||
| 	} | ||||
| 	 | ||||
| 	public void visit(FuncDef stat) { | ||||
| 		stat.name.name.variable = resolveNameReference(stat.name.name); | ||||
| 		stat.name.name.variable.hasassignments = true; | ||||
| 		super.visit(stat); | ||||
| 	} | ||||
| 	 | ||||
| 	public void visit(Assign stat) { | ||||
| 		super.visit(stat); | ||||
| 		for ( int i=0, n=stat.vars.size(); i<n; i++ ) { | ||||
| 			VarExp v = (VarExp) stat.vars.get(i); | ||||
| 			v.markHasAssignment(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public void visit(LocalAssign stat) { | ||||
| 		visitExps(stat.values); | ||||
| 		defineLocalVars( stat.names ); | ||||
| 		int n = stat.names.size(); | ||||
| 		int m = stat.values!=null? stat.values.size(): 0; | ||||
| 		boolean isvarlist = m>0 && m<n && ((Exp)stat.values.get(m-1)).isvarargexp(); | ||||
| 		for ( int i=0; i<n && i<(isvarlist?m-1:m); i++ ) | ||||
| 			if ( stat.values.get(i) instanceof Constant ) | ||||
| 				((Name)stat.names.get(i)).variable.initialValue = ((Constant) stat.values.get(i)).value; | ||||
| 		if ( !isvarlist ) | ||||
| 			for ( int i=m; i<n; i++ ) | ||||
| 				((Name)stat.names.get(i)).variable.initialValue = LuaValue.NIL; | ||||
| 	} | ||||
|  | ||||
| 	public void visit(ParList pars) { | ||||
| 		if ( pars.names != null ) | ||||
| 			defineLocalVars(pars.names); | ||||
| 		if ( pars.isvararg ) | ||||
| 			scope.define("arg"); | ||||
| 		super.visit(pars); | ||||
| 	} | ||||
| 	 | ||||
| 	protected void defineLocalVars(List<Name> names) { | ||||
| 		for ( int i=0, n=names.size(); i<n; i++ ) | ||||
| 			defineLocalVar((Name) names.get(i)); | ||||
| 	} | ||||
|  | ||||
| 	protected void defineLocalVar(Name name) { | ||||
| 		name.variable = scope.define(name.name); | ||||
| 	} | ||||
| 	 | ||||
| 	protected Variable resolveNameReference(Name name) { | ||||
| 		Variable v = scope.find(name.name); | ||||
| 		if ( v.isLocal() && scope.functionNestingCount != v.definingScope.functionNestingCount ) | ||||
| 			v.isupvalue = true; | ||||
| 		return v; | ||||
| 	} | ||||
| } | ||||
| @@ -1,85 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2010 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.ast; | ||||
|  | ||||
| import java.util.HashMap; | ||||
| import java.util.HashSet; | ||||
| import java.util.Map; | ||||
| import java.util.Set; | ||||
|  | ||||
|  | ||||
| public class NameScope { | ||||
|  | ||||
| 	private static final Set<String> LUA_KEYWORDS = new HashSet<String>(); | ||||
| 	 | ||||
| 	static {  | ||||
| 		String[] k = new String[] {  | ||||
| 	        "and", "break", "do", "else", "elseif", "end",  | ||||
| 	        "false", "for", "function", "if", "in", "local", | ||||
| 	        "nil", "not", "or", "repeat", "return",  | ||||
| 	        "then", "true", "until", "while" }; | ||||
| 		for ( int i=0; i<k.length; i++ ) | ||||
| 			LUA_KEYWORDS.add( k[i] ); | ||||
| 	} | ||||
| 	 | ||||
| 	public final Map<String,Variable> namedVariables = new HashMap<String,Variable>(); | ||||
|  | ||||
| 	public final NameScope outerScope; | ||||
|  | ||||
| 	public int functionNestingCount; | ||||
| 	 | ||||
| 	/** Construct default names scope */ | ||||
| 	public NameScope() { | ||||
| 		this.outerScope = null; | ||||
| 		this.functionNestingCount = 0; | ||||
| 	} | ||||
| 	 | ||||
| 	/** Construct name scope within another scope*/ | ||||
| 	public NameScope(NameScope outerScope) { | ||||
| 		this.outerScope = outerScope; | ||||
| 		this.functionNestingCount = outerScope!=null? outerScope.functionNestingCount: 0; | ||||
| 	} | ||||
| 	 | ||||
| 	/** Look up a name.  If it is a global name, then throw IllegalArgumentException. */ | ||||
| 	public Variable find( String name ) throws IllegalArgumentException { | ||||
| 		validateIsNotKeyword(name); | ||||
| 		for ( NameScope n = this; n!=null; n=n.outerScope ) | ||||
| 			if ( n.namedVariables.containsKey(name) ) | ||||
| 				return (Variable)n.namedVariables.get(name); | ||||
| 		Variable value = new Variable(name); | ||||
| 		this.namedVariables.put(name, value); | ||||
| 		return value; | ||||
| 	} | ||||
| 	 | ||||
| 	/** Define a name in this scope.  If it is a global name, then throw IllegalArgumentException. */ | ||||
| 	public Variable define( String name ) throws IllegalStateException, IllegalArgumentException { | ||||
| 		validateIsNotKeyword(name); | ||||
| 		Variable value = new Variable(name, this); | ||||
| 		this.namedVariables.put(name, value); | ||||
| 		return value; | ||||
| 	} | ||||
| 	 | ||||
| 	private void validateIsNotKeyword(String name) { | ||||
| 		if ( LUA_KEYWORDS.contains(name) ) | ||||
| 			throw new IllegalArgumentException("name is a keyword: '"+name+"'"); | ||||
| 	} | ||||
| } | ||||
| @@ -1,42 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2010 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.ast; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| public class ParList { | ||||
| 	public static final List<Name> EMPTY_NAMELIST = new ArrayList<Name>(); | ||||
| 	public static final ParList EMPTY_PARLIST = new ParList(EMPTY_NAMELIST,false); | ||||
| 	 | ||||
| 	public final List<Name> names; | ||||
| 	public final boolean isvararg; | ||||
|  | ||||
| 	public ParList(List<Name> names, boolean isvararg) { | ||||
| 		this.names = names; | ||||
| 		this.isvararg = isvararg; | ||||
| 	} | ||||
|  | ||||
| 	public void accept(Visitor visitor) { | ||||
| 		visitor.visit(this); | ||||
| 	} | ||||
| } | ||||
| @@ -1,250 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2010 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.ast; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| import org.luaj.vm2.ast.Exp.VarExp; | ||||
|  | ||||
| abstract | ||||
| public class Stat { | ||||
| 	public abstract void accept(Visitor visitor); | ||||
|  | ||||
| 	public static Stat block(Block block) { | ||||
| 		return block; | ||||
| 	} | ||||
|  | ||||
| 	public static Stat whiledo(Exp exp, Block block) { | ||||
| 		return new WhileDo(exp, block); | ||||
| 	} | ||||
|  | ||||
| 	public static Stat repeatuntil(Block block, Exp exp) { | ||||
| 		return new RepeatUntil(block, exp); | ||||
| 	}	 | ||||
| 	 | ||||
| 	public static Stat breakstat() { | ||||
| 		return new Break(); | ||||
| 	} | ||||
|  | ||||
| 	public static Stat returnstat(List<Exp> exps) { | ||||
| 		return new Return(exps); | ||||
| 	} | ||||
|  | ||||
| 	public static Stat assignment(List<VarExp> vars, List<Exp> exps) { | ||||
| 		return new Assign(vars,exps); | ||||
| 	} | ||||
|  | ||||
| 	public static Stat functioncall(Exp.FuncCall funccall) { | ||||
| 		return new FuncCallStat(funccall); | ||||
| 	} | ||||
|  | ||||
| 	public static Stat localfunctiondef(String name, FuncBody funcbody) { | ||||
| 		return new LocalFuncDef(name, funcbody); | ||||
| 	} | ||||
|  | ||||
| 	public static Stat fornumeric(String name, Exp initial, Exp limit, Exp step, Block block) { | ||||
| 		return new NumericFor(name, initial, limit, step, block); | ||||
| 	} | ||||
|  | ||||
| 	public static Stat functiondef(FuncName funcname, FuncBody funcbody) { | ||||
| 		return new FuncDef( funcname, funcbody ); | ||||
| 	} | ||||
|  | ||||
| 	public static Stat forgeneric(List<Name> names, List<Exp> exps, Block block) { | ||||
| 		return  new GenericFor(names, exps, block); | ||||
| 	} | ||||
|  | ||||
| 	public static Stat localassignment(List<Name> names, List<Exp> values) { | ||||
| 		return new LocalAssign(names, values); | ||||
| 	} | ||||
|  | ||||
| 	public static Stat ifthenelse(Exp ifexp, Block ifblock, List<Exp> elseifexps, List<Block> elseifblocks, Block elseblock) { | ||||
| 		return new IfThenElse(ifexp, ifblock, elseifexps, elseifblocks, elseblock); | ||||
| 	} | ||||
|  | ||||
| 	public static class Assign extends Stat { | ||||
| 		public final List<VarExp> vars; | ||||
| 		public final List<Exp> exps; | ||||
| 		 | ||||
| 		public Assign(List<VarExp> vars, List<Exp> exps) { | ||||
| 			this.vars = vars; | ||||
| 			this.exps = exps; | ||||
| 		} | ||||
|  | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit(this); | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	public static class WhileDo extends Stat { | ||||
| 		public final Exp exp; | ||||
| 		public final Block block; | ||||
| 		public WhileDo( Exp exp, Block block ) { | ||||
| 			this.exp = exp; | ||||
| 			this.block = block; | ||||
| 		} | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit( this ); | ||||
| 		} | ||||
| 	}	 | ||||
| 	 | ||||
| 	public static class RepeatUntil extends Stat { | ||||
| 		public final Block block; | ||||
| 		public final Exp exp; | ||||
| 		public RepeatUntil( Block block, Exp exp ) { | ||||
| 			this.block = block; | ||||
| 			this.exp = exp; | ||||
| 		} | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit( this ); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public static class Break extends Stat { | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit( this ); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public static class Return extends Stat { | ||||
| 		public final List<Exp> values; | ||||
| 		public Return(List<Exp> values) { | ||||
| 			this.values = values; | ||||
| 		} | ||||
|  | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit( this ); | ||||
| 		} | ||||
| 		 | ||||
| 		public int nreturns() { | ||||
| 			int n = values!=null? values.size(): 0; | ||||
| 			if ( n>0 && ((Exp)values.get(n-1)).isvarargexp() ) | ||||
| 				n = -1; | ||||
| 			return n;		 | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public static class FuncCallStat extends Stat { | ||||
| 		public final Exp.FuncCall funccall; | ||||
| 		public FuncCallStat(Exp.FuncCall funccall) { | ||||
| 			this.funccall = funccall; | ||||
| 		} | ||||
|  | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit( this ); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public static class LocalFuncDef extends Stat { | ||||
| 		public final Name name; | ||||
| 		public final FuncBody body; | ||||
| 		public LocalFuncDef(String name, FuncBody body) { | ||||
| 			this.name = new Name(name); | ||||
| 			this.body = body; | ||||
| 		} | ||||
|  | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit( this ); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public static class FuncDef extends Stat { | ||||
| 		public final FuncName name; | ||||
| 		public final FuncBody body; | ||||
| 		public FuncDef(FuncName name, FuncBody body) { | ||||
| 			this.name = name; | ||||
| 			this.body = body; | ||||
| 		} | ||||
|  | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit( this ); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public static class GenericFor extends Stat { | ||||
| 		public List<Name> names; | ||||
| 		public List<Exp> exps; | ||||
| 		public Block block; | ||||
| 		public NameScope scope; | ||||
| 		public GenericFor(List<Name> names, List<Exp> exps, Block block) { | ||||
| 			this.names = names; | ||||
| 			this.exps = exps; | ||||
| 			this.block = block; | ||||
| 		} | ||||
|  | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit( this ); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public static class NumericFor extends Stat { | ||||
| 		public final Name name; | ||||
| 		public final Exp initial,limit,step; | ||||
| 		public final Block block; | ||||
| 		public NameScope scope; | ||||
| 		public NumericFor(String name, Exp initial, Exp limit, Exp step, Block block) { | ||||
| 			this.name = new Name(name); | ||||
| 			this.initial = initial; | ||||
| 			this.limit = limit; | ||||
| 			this.step = step; | ||||
| 			this.block = block; | ||||
| 		} | ||||
|  | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit( this ); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public static class LocalAssign extends Stat { | ||||
| 		public final List<Name> names; | ||||
| 		public final List<Exp> values; | ||||
| 		public LocalAssign(List<Name> names, List<Exp> values) { | ||||
| 			this.names = names; | ||||
| 			this.values = values; | ||||
| 		} | ||||
|  | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit( this ); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	public static class IfThenElse extends Stat { | ||||
| 		public final Exp ifexp; | ||||
| 		public final Block ifblock; | ||||
| 		public final List<Exp> elseifexps; | ||||
| 		public final List<Block> elseifblocks; | ||||
| 		public final Block elseblock; | ||||
| 		public IfThenElse(Exp ifexp, Block ifblock, List<Exp> elseifexps, | ||||
| 				List<Block> elseifblocks, Block elseblock) { | ||||
| 			this.ifexp = ifexp; | ||||
| 			this.ifblock = ifblock; | ||||
| 			this.elseifexps = elseifexps; | ||||
| 			this.elseifblocks = elseifblocks; | ||||
| 			this.elseblock = elseblock; | ||||
| 		} | ||||
|  | ||||
| 		public void accept(Visitor visitor) { | ||||
| 			visitor.visit( this ); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,93 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2010 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.ast; | ||||
|  | ||||
| import java.io.ByteArrayOutputStream; | ||||
| import java.io.UnsupportedEncodingException; | ||||
|  | ||||
| import org.luaj.vm2.LuaString; | ||||
|  | ||||
| public class Str { | ||||
| 	 | ||||
| 	private Str() {} | ||||
| 	 | ||||
| 	public static LuaString quoteString(String image) { | ||||
| 		String s = image.substring(1, image.length()-1); | ||||
| 		byte[] bytes = unquote(s); | ||||
| 		return LuaString.valueOf(bytes); | ||||
| 	} | ||||
| 	 | ||||
| 	public static LuaString charString(String image) { | ||||
| 		String s = image.substring(1, image.length()-1); | ||||
| 		byte[] bytes = unquote(s); | ||||
| 		return LuaString.valueOf(bytes); | ||||
| 	} | ||||
| 	 | ||||
| 	public static LuaString longString(String image) { | ||||
| 		int i = image.indexOf('[', image.indexOf('[')+1)+1; | ||||
| 		String s = image.substring(i,image.length()-i); | ||||
| 		byte[] b = iso88591bytes(s); | ||||
| 		return LuaString.valueOf(b); | ||||
| 	} | ||||
| 	 | ||||
| 	public static byte[] iso88591bytes( String s ) { | ||||
| 		try { | ||||
| 			return s.getBytes("ISO8859-1"); | ||||
| 		} catch (UnsupportedEncodingException e) { | ||||
| 			throw new IllegalStateException("ISO8859-1 not supported"); | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	public static byte[] unquote(String s) { | ||||
| 		ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||||
| 		char[] c = s.toCharArray(); | ||||
| 		int n = c.length; | ||||
| 		for ( int i=0; i<n; i++ ) { | ||||
| 			if ( c[i] == '\\' && i<n ) { | ||||
| 				switch ( c[++i] ) { | ||||
| 				case '0': case '1': case '2': case '3': case '4': | ||||
| 				case '5': case '6': case '7': case '8': case '9': | ||||
| 					int d=(int) (c[i++]-'0'); | ||||
| 					for ( int j=0; i<n && j<2 && c[i]>='0' && c[i]<='9'; i++, j++ ) | ||||
| 						d = d * 10 + (int) (c[i]-'0'); | ||||
| 					baos.write( (byte) d ); | ||||
| 					--i; | ||||
| 					continue; | ||||
| 				case 'a':  baos.write( (byte) 7 );    continue; | ||||
| 				case 'b':  baos.write( (byte) '\b' ); continue; | ||||
| 				case 'f':  baos.write( (byte) '\f' ); continue; | ||||
| 				case 'n':  baos.write( (byte) '\n' ); continue; | ||||
| 				case 'r':  baos.write( (byte) '\r' ); continue; | ||||
| 				case 't':  baos.write( (byte) '\t' ); continue; | ||||
| 				case 'v':  baos.write( (byte) 11 );   continue; | ||||
| 				case '"':  baos.write( (byte) '"' );  continue; | ||||
| 				case '\'': baos.write( (byte) '\'' ); continue; | ||||
| 				case '\\': baos.write( (byte) '\\' ); continue; | ||||
| 				default: baos.write( (byte) c[i] ); break; | ||||
| 				} | ||||
| 			} else { | ||||
| 				baos.write( (byte) c[i] ); | ||||
| 			} | ||||
| 		} | ||||
| 		return baos.toByteArray(); | ||||
| 	} | ||||
| } | ||||
| @@ -1,32 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2010 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.ast; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| public class TableConstructor extends Exp { | ||||
| 	public List<TableField> fields; | ||||
|  | ||||
| 	public void accept(Visitor visitor) { | ||||
| 		visitor.visit(this); | ||||
| 	} | ||||
| } | ||||
| @@ -1,51 +0,0 @@ | ||||
| /******************************************************************************* | ||||
| * Copyright (c) 2010 Luaj.org. All rights reserved. | ||||
| * | ||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| * of this software and associated documentation files (the "Software"), to deal | ||||
| * in the Software without restriction, including without limitation the rights | ||||
| * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| * copies of the Software, and to permit persons to whom the Software is | ||||
| * furnished to do so, subject to the following conditions: | ||||
| * | ||||
| * The above copyright notice and this permission notice shall be included in | ||||
| * all copies or substantial portions of the Software. | ||||
| *  | ||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| * THE SOFTWARE. | ||||
| ******************************************************************************/ | ||||
| package org.luaj.vm2.ast; | ||||
|  | ||||
| public class TableField { | ||||
|  | ||||
| 	public final Exp index; | ||||
| 	public final String name; | ||||
| 	public final Exp rhs; | ||||
| 	 | ||||
| 	public TableField(Exp index, String name, Exp rhs) { | ||||
| 		this.index = index; | ||||
| 		this.name = name; | ||||
| 		this.rhs = rhs; | ||||
| 	} | ||||
| 	 | ||||
| 	public static TableField keyedField(Exp index, Exp rhs) { | ||||
| 		return new TableField(index, null, rhs); | ||||
| 	} | ||||
|  | ||||
| 	public static TableField namedField(String name, Exp rhs) { | ||||
| 		return new TableField(null, name, rhs); | ||||
| 	} | ||||
|  | ||||
| 	public static TableField listField(Exp rhs) { | ||||
| 		return new TableField(null, null, rhs); | ||||
| 	} | ||||
|  | ||||
| 	public void accept(Visitor visitor) { | ||||
| 		visitor.visit(this); | ||||
| 	} | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user