Compare commits
1278 Commits
colobot-go
...
colobot2
Author | SHA1 | Date |
---|---|---|
|
b98edec8f8 | |
|
d22b32477e | |
|
884129a676 | |
|
0fa486b9f0 | |
|
4251873f49 | |
|
74ab7afb23 | |
|
ab3c22dce3 | |
|
72ca4f2d7c | |
|
3a8f75bd02 | |
|
32fed5af73 | |
![]() |
f07b7a1b60 | |
![]() |
0a95289f9f | |
![]() |
7d75b9cc14 | |
![]() |
909a2b2d2e | |
![]() |
7d22b607cc | |
![]() |
2f80292176 | |
![]() |
53b3062bee | |
![]() |
8e128ff08c | |
![]() |
3c4b9f6d01 | |
![]() |
9d5f88f07c | |
![]() |
b9c8d36d8b | |
![]() |
ff340fda92 | |
![]() |
c0d568241b | |
![]() |
d879fa5fc9 | |
![]() |
510fe6804a | |
![]() |
2b84da8a77 | |
![]() |
670cedd967 | |
![]() |
5a52c66b1f | |
![]() |
434bd0bd3a | |
![]() |
5f854da5fc | |
![]() |
86c2b2f0dc | |
![]() |
7fe75e20ad | |
![]() |
261eaa78e4 | |
![]() |
4d11040dba | |
![]() |
97ea5cc895 | |
![]() |
fe36b0fe29 | |
![]() |
8fab817118 | |
![]() |
8601066761 | |
![]() |
9586474fa8 | |
![]() |
5b79a4eb38 | |
![]() |
1034c2e45c | |
![]() |
fde2b901bd | |
![]() |
3e06584956 | |
![]() |
0ab9ae4b6e | |
![]() |
b296ee4d47 | |
![]() |
dccacd6352 | |
![]() |
b3c6e667f5 | |
![]() |
a48f13fb35 | |
![]() |
7db69f5d53 | |
![]() |
ae5e5b3874 | |
![]() |
b5b3f81840 | |
![]() |
fd81641cf7 | |
![]() |
840ded7e61 | |
![]() |
4c7e7280dd | |
![]() |
af1abfe41e | |
![]() |
8e950e5145 | |
![]() |
e807e7c984 | |
![]() |
d9d401e636 | |
![]() |
9a14d0c837 | |
![]() |
ee9f9d875d | |
![]() |
b12e5ad7cd | |
![]() |
ecb789d059 | |
![]() |
32fb105bca | |
![]() |
7d3e3c91e8 | |
![]() |
1b69589302 | |
![]() |
f7a33bbeb0 | |
![]() |
0ef77132a0 | |
![]() |
550193e570 | |
![]() |
beb29333d5 | |
![]() |
f9714c35f7 | |
![]() |
26598c4247 | |
![]() |
1ee0790785 | |
![]() |
6f05280ccb | |
![]() |
63b6bcf38d | |
![]() |
83b9ded0dc | |
![]() |
84ac0d3ba8 | |
![]() |
acc3c5ae5e | |
![]() |
ec0e735a3f | |
![]() |
a16771425a | |
![]() |
4fcd989e72 | |
![]() |
882672c0b5 | |
![]() |
b152bd5dea | |
![]() |
59600ae5c7 | |
![]() |
11f5073a3f | |
![]() |
cfa9a00024 | |
![]() |
9e1248e459 | |
![]() |
9ccc514a67 | |
![]() |
63ad09b615 | |
![]() |
1376d8b16d | |
![]() |
a04dcd8014 | |
![]() |
9c8a8f4cf4 | |
![]() |
dfac4209ef | |
![]() |
793ef3d0a4 | |
![]() |
0d57ac43bb | |
![]() |
3baf2bbb10 | |
![]() |
7c95855d4f | |
![]() |
dd2fbd2675 | |
![]() |
8eaebb8c84 | |
![]() |
172e1fbff0 | |
![]() |
461f1e2240 | |
![]() |
7c40c10b7a | |
![]() |
017a1571f7 | |
![]() |
f672e89201 | |
![]() |
9417b916da | |
![]() |
4f0854068c | |
![]() |
3171dc4a89 | |
![]() |
10b89e36f9 | |
![]() |
080c46daa1 | |
![]() |
b3d19a9e8d | |
![]() |
1bb918ce23 | |
![]() |
160a4a4f75 | |
![]() |
71e3e78644 | |
![]() |
6e7dee74cf | |
![]() |
8f11fc0126 | |
![]() |
5f9b14f43d | |
![]() |
b66ea8bcee | |
![]() |
37b403c46d | |
![]() |
2e7bf2a7a6 | |
![]() |
4b1b20ec5f | |
![]() |
d24a6b37a4 | |
![]() |
4531dc432e | |
![]() |
06bf44da38 | |
![]() |
9dd0159585 | |
![]() |
158901ff02 | |
![]() |
9a01408eda | |
![]() |
7c0dbd914f | |
![]() |
b990ee81ff | |
![]() |
bfd9dae533 | |
![]() |
cbfcbae7ab | |
![]() |
2e95aeac9b | |
![]() |
efbd296fc3 | |
![]() |
9c5d9d8f17 | |
![]() |
0b978f7dbc | |
![]() |
4634461c1d | |
![]() |
1c9c0929da | |
![]() |
24622e6a75 | |
![]() |
f60c62f05d | |
![]() |
ec9607784c | |
![]() |
5efd8342ec | |
![]() |
0618174b2b | |
![]() |
d47e265863 | |
![]() |
436c316a4a | |
![]() |
1d8e06c7ba | |
![]() |
21b6572b5b | |
![]() |
3b3cdb9961 | |
![]() |
bedd24801c | |
![]() |
983a9a6e03 | |
![]() |
2f50470591 | |
![]() |
5feffc70df | |
![]() |
e3ba33a508 | |
![]() |
b7cb26822b | |
![]() |
0e53336d61 | |
![]() |
0df78e7fa6 | |
![]() |
789c8b2292 | |
![]() |
c0669a591b | |
![]() |
708d3cfd46 | |
![]() |
6cc58b872f | |
![]() |
4c767953ea | |
![]() |
4ec0083cd8 | |
![]() |
87ad81f891 | |
![]() |
afbf687255 | |
![]() |
0693aa5e1e | |
![]() |
2a91d6bf35 | |
![]() |
b09977a503 | |
![]() |
438e4bba62 | |
![]() |
a74adb5f59 | |
![]() |
8632c7404d | |
![]() |
2ea94244e9 | |
![]() |
3c98af04b5 | |
![]() |
b5e27c9f19 | |
![]() |
ec425c768b | |
![]() |
3fd9815138 | |
![]() |
3805851255 | |
![]() |
a88d9cdd39 | |
![]() |
7d31b1e55d | |
![]() |
56e0c915b5 | |
![]() |
a25ce2d5df | |
![]() |
cac34e259b | |
![]() |
2a529ae07f | |
![]() |
a1e4e4b97c | |
![]() |
3b4c2f3049 | |
![]() |
f2cc131ff7 | |
![]() |
b6f2a9e544 | |
![]() |
daa9419557 | |
![]() |
0882b69ec8 | |
![]() |
013d3cccf4 | |
![]() |
8f710a24c8 | |
![]() |
7135a6660b | |
![]() |
7664594b8e | |
![]() |
07541d0bbb | |
![]() |
8fb0f76f6f | |
![]() |
640cde1653 | |
![]() |
4b1b1763df | |
![]() |
829c5fb42f | |
![]() |
fd3c2af358 | |
![]() |
5c2c52ad31 | |
![]() |
aa3efd5841 | |
![]() |
920a4c3fc8 | |
![]() |
d57370578f | |
![]() |
4a16ee76a1 | |
![]() |
7af32caec2 | |
![]() |
2d9db9c90a | |
![]() |
d7a22bf74c | |
![]() |
1a7346b845 | |
![]() |
8c40b7c753 | |
![]() |
fdc1792932 | |
![]() |
483a855848 | |
![]() |
4541db7f21 | |
![]() |
86d8ee4c38 | |
![]() |
73db861cc6 | |
![]() |
061ef44def | |
![]() |
dffb988798 | |
![]() |
d09c5da493 | |
![]() |
c011e49112 | |
![]() |
628567701a | |
![]() |
38990e283b | |
![]() |
fa5e229015 | |
![]() |
05163c09a1 | |
![]() |
8533be8d5c | |
![]() |
89551c83cf | |
![]() |
3001927576 | |
![]() |
baa616050a | |
![]() |
e839f0dec7 | |
![]() |
3168bf4350 | |
![]() |
6447304531 | |
![]() |
6aebf60300 | |
![]() |
0829cd84fe | |
![]() |
8af600692e | |
![]() |
3478ee322b | |
![]() |
550d0f915b | |
![]() |
d9e26c2516 | |
![]() |
4bce63e38d | |
![]() |
ec8a09e4a9 | |
![]() |
05b68a4b80 | |
![]() |
c378009128 | |
![]() |
2d794d1a32 | |
![]() |
e38835cfd4 | |
![]() |
e3ba1a1840 | |
![]() |
08f6c32551 | |
![]() |
2b8d580355 | |
![]() |
ee390bc270 | |
![]() |
14e7cd0e52 | |
![]() |
6d8a52eb15 | |
![]() |
951db17d53 | |
![]() |
0d612b9928 | |
![]() |
aacc2d0596 | |
![]() |
074706e7ec | |
![]() |
1631b9587f | |
![]() |
750a470b9a | |
![]() |
37bdc8665f | |
![]() |
cbf661f69f | |
![]() |
d16144eee4 | |
![]() |
1a190b7f6f | |
![]() |
a7b294025e | |
![]() |
e2d4dd6995 | |
![]() |
d9f3078396 | |
![]() |
0908e10ff6 | |
![]() |
7d9badb542 | |
![]() |
3bd4fee844 | |
![]() |
3405c038c9 | |
![]() |
3400a0fab0 | |
![]() |
85dc3f68e7 | |
![]() |
eff8e885d5 | |
![]() |
cbc07c04a5 | |
![]() |
0003494c9e | |
![]() |
741d5c75ba | |
![]() |
2ff722eee6 | |
![]() |
39b6621463 | |
![]() |
9a07c1d858 | |
![]() |
19ae57c9ad | |
![]() |
6e0207ca5e | |
![]() |
be8d37241a | |
![]() |
e76c00c7f4 | |
![]() |
cba70fc912 | |
![]() |
048393f448 | |
![]() |
710f448477 | |
![]() |
367dab9c5a | |
![]() |
c280924c0e | |
![]() |
5dacb82b22 | |
![]() |
a54a59146d | |
![]() |
a1ea633a3e | |
![]() |
68a222e03a | |
![]() |
67bd982969 | |
![]() |
d9073de251 | |
![]() |
754684bfe9 | |
![]() |
9c37f6cbd5 | |
![]() |
208f142cd2 | |
![]() |
e5d8e2b428 | |
![]() |
0bba168f94 | |
![]() |
db3b1d74d1 | |
![]() |
50fe905455 | |
![]() |
d5e8cfd4ba | |
![]() |
ffe1815ec9 | |
![]() |
2690d04f64 | |
![]() |
3707daf678 | |
![]() |
076dce6981 | |
![]() |
d6d74f200b | |
![]() |
1a7ffa693b | |
![]() |
dbe127569b | |
![]() |
da2471567d | |
![]() |
55f5d25c95 | |
![]() |
4634564f17 | |
![]() |
300a2d8569 | |
![]() |
b4bfb8b242 | |
![]() |
6277e10b3f | |
![]() |
47ad390f1d | |
![]() |
d25d6124a9 | |
![]() |
70151279f6 | |
![]() |
431416d75e | |
![]() |
77c6f8e54f | |
![]() |
dc99e19ed9 | |
![]() |
c659e060c1 | |
![]() |
f8f3a64612 | |
![]() |
7bf37a3999 | |
![]() |
3fabdad1fe | |
![]() |
a806bb2657 | |
![]() |
91c19bff55 | |
![]() |
9691974b1a | |
![]() |
07d3d79e8d | |
![]() |
498f15cc92 | |
![]() |
b36ec266f0 | |
![]() |
c0d067d24b | |
![]() |
12c0f41477 | |
![]() |
f7c66741c6 | |
![]() |
60deb0328a | |
![]() |
0ef4579da8 | |
![]() |
55c692e8bb | |
![]() |
835f84584e | |
![]() |
bd2ad39f6a | |
![]() |
48d2b4a618 | |
![]() |
cd6ea1a4c5 | |
![]() |
4ecfb47f07 | |
![]() |
d3dd99c384 | |
![]() |
69ea470a26 | |
![]() |
65da4c42c4 | |
![]() |
cd059bd511 | |
![]() |
53053b901f | |
![]() |
17f68efb81 | |
![]() |
98ad26da3d | |
![]() |
36ac6d9956 | |
![]() |
1eb17b2fa1 | |
![]() |
33744de372 | |
![]() |
d651b36eb2 | |
![]() |
7e0db31cc1 | |
![]() |
c389156499 | |
![]() |
0207669d61 | |
![]() |
b158318e83 | |
![]() |
11bfcc6d53 | |
![]() |
9269a55e8b | |
![]() |
2583f6fe36 | |
![]() |
193d105a3f | |
![]() |
ea7837b4c6 | |
![]() |
f9c275919e | |
![]() |
38b9b9be4c | |
![]() |
9fd935770a | |
![]() |
d1489a1fb1 | |
![]() |
0568fcdb81 | |
![]() |
39c837d323 | |
![]() |
3aa7c3c2e0 | |
![]() |
7a555e19c4 | |
![]() |
26c0d85c66 | |
![]() |
613efd7599 | |
![]() |
ae179d9005 | |
![]() |
96fece4e6d | |
![]() |
9139239f9f | |
![]() |
57502d2f54 | |
![]() |
ce71f25901 | |
![]() |
fea6b87139 | |
![]() |
4157604458 | |
![]() |
117c72ba72 | |
![]() |
79d4cd9060 | |
![]() |
1438438937 | |
![]() |
80f074e2ba | |
![]() |
171bba1bcd | |
![]() |
95579bbf1d | |
![]() |
c9dca4cebd | |
![]() |
6aa83c93ac | |
![]() |
a69b88e09a | |
![]() |
5daaba6e64 | |
![]() |
2b107736e2 | |
![]() |
30d688c1ec | |
![]() |
58c75ce61a | |
![]() |
100be95113 | |
![]() |
5c037837f5 | |
![]() |
12e696bf1c | |
![]() |
55513703b2 | |
![]() |
f2eafd563e | |
![]() |
16200bbeac | |
![]() |
465fe59dfb | |
![]() |
704e3f2f0d | |
![]() |
fe02cf3e4b | |
![]() |
5e7fb5010f | |
![]() |
b322ce064b | |
![]() |
ec21faf15c | |
![]() |
e0c5ca962f | |
![]() |
37f82acff0 | |
![]() |
c04d3ef50d | |
![]() |
62b14bcf62 | |
![]() |
005f5b5103 | |
![]() |
bb6c32c897 | |
![]() |
8299fe41bc | |
![]() |
d39f1999e7 | |
![]() |
d06b7e1456 | |
![]() |
41cf9974f9 | |
![]() |
bbf5c806d8 | |
![]() |
8f0b367f9c | |
![]() |
65e12621ff | |
![]() |
84d23e91ed | |
![]() |
5e37f84bc7 | |
![]() |
11047ecd53 | |
![]() |
91a290dade | |
![]() |
ea62a449d4 | |
![]() |
faa4eaae20 | |
![]() |
c039e7e859 | |
![]() |
d9c966a95b | |
![]() |
92f574d2ca | |
![]() |
decab29555 | |
![]() |
ecc23dfb3e | |
![]() |
a5d9bae052 | |
![]() |
c04291a55e | |
![]() |
efad9a4dae | |
![]() |
3ab153225a | |
|
76314f522f | |
![]() |
55d6c431f2 | |
![]() |
ce450d1c00 | |
![]() |
9f5ee21bbe | |
![]() |
27466a4223 | |
![]() |
a279541198 | |
![]() |
309f80b25f | |
![]() |
993a6adf6e | |
![]() |
fabbdda964 | |
![]() |
cdb63e2a8c | |
![]() |
8647deafc8 | |
![]() |
dbd9db86a6 | |
![]() |
b338b18f16 | |
![]() |
0b948b655e | |
![]() |
52446c1049 | |
![]() |
fbbe25b25e | |
![]() |
f5519f8936 | |
![]() |
9f2f7780a4 | |
![]() |
9c91fd1e52 | |
![]() |
7b237ce9ad | |
![]() |
404d2dbeb1 | |
![]() |
9a04685101 | |
![]() |
a7aaa07356 | |
![]() |
71ff89a803 | |
![]() |
c336a67afa | |
![]() |
10ec454f6b | |
![]() |
d71ee4ef68 | |
![]() |
05de2baef5 | |
![]() |
f64c610fa4 | |
![]() |
ad2e3db92f | |
![]() |
13098ee378 | |
![]() |
8fdf79958f | |
![]() |
8c6ac4cd16 | |
![]() |
2685a1eb60 | |
![]() |
a54a117ba4 | |
![]() |
a4cfe616a8 | |
![]() |
f08c67bef9 | |
![]() |
b17a4391b0 | |
![]() |
1c9f5f3f64 | |
![]() |
68c254c101 | |
![]() |
d7ec891ab8 | |
![]() |
dbc13bad20 | |
![]() |
d2c8888067 | |
![]() |
8d5cafecb3 | |
![]() |
d0961a517a | |
![]() |
4c1d3eecd1 | |
![]() |
56c99e741e | |
![]() |
4bb6f9f1b3 | |
![]() |
b9305dfd45 | |
![]() |
5749fff377 | |
![]() |
4c14050b27 | |
![]() |
33b7c893cb | |
![]() |
2023756023 | |
![]() |
a92fa950e2 | |
![]() |
e63afb3461 | |
![]() |
25a8d7b5b5 | |
![]() |
4780716c18 | |
![]() |
9cb80daedf | |
![]() |
aa8122f16f | |
|
9e743e86af | |
![]() |
fd36ff3840 | |
|
5eebe300fc | |
![]() |
93f3abee1a | |
![]() |
fbe2191800 | |
![]() |
b685d0060c | |
![]() |
253cca379b | |
![]() |
e6ce4112c6 | |
![]() |
51668c12d7 | |
![]() |
16795e0d49 | |
![]() |
62b770f7d3 | |
![]() |
df415880d0 | |
![]() |
1be69a0a51 | |
![]() |
2b96eda86d | |
![]() |
f57da76ae8 | |
![]() |
a5c7187017 | |
![]() |
5112bf86df | |
![]() |
2d32e3a798 | |
![]() |
fd2b72b296 | |
![]() |
eac74c23ec | |
![]() |
242477e3ee | |
![]() |
c4385961c4 | |
![]() |
f1d6787b08 | |
![]() |
b47ee4dd1e | |
![]() |
dc6cfbb691 | |
![]() |
754dfefefd | |
![]() |
7e6782a1be | |
![]() |
56a8c5eb48 | |
![]() |
63bf6bed08 | |
![]() |
d64d78acfc | |
![]() |
69d2d39c36 | |
![]() |
a0635ae400 | |
![]() |
dc64b95406 | |
![]() |
8390d85e46 | |
![]() |
95cab790c1 | |
![]() |
b72bedaf60 | |
![]() |
5f76722ecb | |
![]() |
4905abe30b | |
![]() |
ac32e40003 | |
![]() |
52ed8041f7 | |
![]() |
0a3cdd342b | |
![]() |
d29570c20a | |
![]() |
174669ec92 | |
![]() |
f87ae45745 | |
![]() |
2fa706a123 | |
![]() |
73429315a7 | |
![]() |
61126af370 | |
![]() |
419bd1cc21 | |
![]() |
167dd01bbe | |
![]() |
df7cdd4b8e | |
![]() |
2143f21828 | |
![]() |
17e38bf66c | |
![]() |
3ec39047e1 | |
![]() |
a9717206f3 | |
![]() |
634efbcabd | |
![]() |
c15efbad7b | |
![]() |
f0ba8ec325 | |
![]() |
fde66a9422 | |
![]() |
17ece36b3e | |
![]() |
83a32b36b3 | |
![]() |
c80a816808 | |
![]() |
a2c62a9da6 | |
![]() |
86f595b8ef | |
![]() |
cc4cfd2122 | |
![]() |
c4037a885f | |
|
a2aeef0155 | |
![]() |
fa5cf01af0 | |
![]() |
1b9d40d2fb | |
![]() |
9e8ebe4595 | |
![]() |
e8f9c0292b | |
![]() |
004c861ba9 | |
![]() |
81ddda4515 | |
![]() |
3da26a38ed | |
![]() |
6c3012b8a1 | |
![]() |
90af1d9c16 | |
![]() |
7d7a29117e | |
![]() |
9cf30fd9bc | |
![]() |
df65862c49 | |
![]() |
f2d91cde80 | |
![]() |
db031c7985 | |
![]() |
a3ceecb21e | |
![]() |
da6c0c66d7 | |
![]() |
767f7f0049 | |
![]() |
85f0f88c20 | |
![]() |
870d5237bb | |
![]() |
4ae0360640 | |
![]() |
b8523aa1db | |
![]() |
bf1982f4e4 | |
![]() |
963cd1b347 | |
![]() |
4c02fe9cda | |
![]() |
70b7a63b66 | |
![]() |
31781f214c | |
![]() |
1b74cc1144 | |
![]() |
535696de28 | |
![]() |
b9297cd9f4 | |
![]() |
a78cc159f8 | |
![]() |
fbb45807f1 | |
![]() |
1c8c01ad96 | |
![]() |
97b266182b | |
![]() |
4eaa8588d7 | |
![]() |
76bb08779a | |
![]() |
03c60202b8 | |
![]() |
dcd84523ab | |
![]() |
6a23e97533 | |
![]() |
4bd6e01b65 | |
![]() |
35b22f7a7f | |
![]() |
6efc977286 | |
![]() |
a6a7b0c96c | |
![]() |
0ef21bfdbb | |
![]() |
6d7aadf987 | |
![]() |
37e4ed8029 | |
![]() |
c50b36118e | |
![]() |
47687931d7 | |
![]() |
cb364a4f96 | |
![]() |
06921e711d | |
![]() |
124467c6e1 | |
![]() |
faa4a6eefa | |
![]() |
e96e8b46b2 | |
![]() |
6a22b709d6 | |
![]() |
7449111a00 | |
![]() |
6c715ffef9 | |
![]() |
a65776e0e7 | |
![]() |
c04b2738de | |
![]() |
86dff7396e | |
![]() |
1cffbb2bd3 | |
![]() |
55c0c3221d | |
![]() |
1b93963413 | |
![]() |
a46fee4d4e | |
![]() |
a5909ac4de | |
![]() |
4a62e9ed76 | |
![]() |
0102e45855 | |
![]() |
736c0894d1 | |
![]() |
04b1944939 | |
![]() |
e108715760 | |
![]() |
3566fb4826 | |
![]() |
a3dbeb9829 | |
![]() |
50b2afbda8 | |
![]() |
5cc565439c | |
![]() |
e2eb5b91e0 | |
![]() |
86ef158c00 | |
![]() |
ebcb124b0e | |
![]() |
dece19fbec | |
![]() |
a2df003b7e | |
![]() |
fb9fa49ce8 | |
![]() |
f449d9c800 | |
![]() |
a7d4eb00b6 | |
![]() |
55b46942cb | |
![]() |
5c0cfba8ae | |
![]() |
6a0234edd5 | |
![]() |
6d584ba481 | |
![]() |
373d8de7d0 | |
![]() |
7f9efea0a2 | |
![]() |
bbf9356628 | |
![]() |
0b9673029d | |
![]() |
9a14c8c7e9 | |
![]() |
354bbf9287 | |
![]() |
7bd18f9c8e | |
![]() |
0f33dbe154 | |
![]() |
f3ae4b4209 | |
![]() |
11e67cc61b | |
![]() |
00d72d8d7b | |
![]() |
d8e0465d6d | |
![]() |
92c9031749 | |
![]() |
17ba464d33 | |
![]() |
ad33e0e624 | |
![]() |
f09768fb2d | |
![]() |
9db6bb63e4 | |
![]() |
87fec23f4b | |
![]() |
5815db4062 | |
![]() |
b925838a91 | |
![]() |
e5d994b9e2 | |
![]() |
ddab760624 | |
![]() |
0c69dc8d30 | |
![]() |
c5e8df16e0 | |
![]() |
0597c0efda | |
![]() |
621453a01c | |
![]() |
3fbfadb0d4 | |
![]() |
8f122d6603 | |
![]() |
d4b2f23c4a | |
![]() |
ad02b55541 | |
![]() |
b5466261d4 | |
![]() |
0d6218bfa0 | |
![]() |
088c661839 | |
![]() |
fc2bd68876 | |
![]() |
853d8eee5d | |
![]() |
5bf6f12ae5 | |
![]() |
a67266553f | |
![]() |
51cde3c868 | |
![]() |
b8c4232312 | |
![]() |
f97da6482b | |
![]() |
4e4c3671c6 | |
![]() |
b9ac5688e9 | |
![]() |
69aba7c352 | |
![]() |
0d30624119 | |
![]() |
1ca213df09 | |
![]() |
8648de9581 | |
![]() |
c9ec197d76 | |
![]() |
587e189e97 | |
![]() |
1a771b0e72 | |
![]() |
68ddaf550b | |
![]() |
4f9d9d0609 | |
![]() |
61a7aa2592 | |
![]() |
2d3d03cc38 | |
![]() |
41379ded7e | |
![]() |
5cefa57dd5 | |
![]() |
50c3c45ef8 | |
![]() |
6f3b14202e | |
![]() |
7d30a82747 | |
![]() |
cd140f1384 | |
![]() |
190e04fdd7 | |
![]() |
9c2ea5f488 | |
![]() |
b8b2d32bc1 | |
![]() |
62620a93cd | |
![]() |
ed8dc04d94 | |
![]() |
0517115557 | |
![]() |
17d85eb434 | |
![]() |
17d0d2abb1 | |
![]() |
e9a153df14 | |
![]() |
5f089f4a9b | |
![]() |
1058a326ad | |
![]() |
bc572aa52f | |
![]() |
c0cdd84e85 | |
![]() |
250ea57e8b | |
![]() |
a66b3d0672 | |
![]() |
97a8cfe6f9 | |
![]() |
44083053ce | |
![]() |
16a1dc7b9d | |
![]() |
d038d18943 | |
![]() |
472aadf9ab | |
![]() |
266944c9d2 | |
![]() |
7268bcca11 | |
![]() |
edeae704f9 | |
![]() |
d4ab82eaae | |
![]() |
ef6b692d41 | |
![]() |
6ec644d20b | |
![]() |
7d99aa954b | |
![]() |
46098834a1 | |
![]() |
aca552242f | |
![]() |
0efb8d50ba | |
![]() |
0eb31a1f45 | |
![]() |
275724ab97 | |
![]() |
e02a3373fd | |
![]() |
a46750ede2 | |
![]() |
0f6e1d7d4a | |
![]() |
0da792c77c | |
![]() |
9fe05f4472 | |
![]() |
bc3fbd21d0 | |
![]() |
b50a71bde4 | |
![]() |
086e07168d | |
![]() |
02fd258697 | |
![]() |
04b8bf6c42 | |
![]() |
2175e7f90a | |
![]() |
4c3440bbe6 | |
![]() |
634248885f | |
![]() |
63bf8e07da | |
![]() |
e3f53dc203 | |
![]() |
be97167994 | |
![]() |
92d2de5325 | |
![]() |
9cf89db8af | |
![]() |
723c552783 | |
![]() |
d57c45cbb2 | |
![]() |
3db153f964 | |
![]() |
508e7529d2 | |
![]() |
d11404a6e9 | |
![]() |
4305f8de03 | |
![]() |
634d087d5e | |
![]() |
7c88a6e667 | |
![]() |
abf1a60a86 | |
![]() |
0dbf82ca4e | |
![]() |
2871bac0ce | |
![]() |
9165a8475e | |
![]() |
3f6e84b418 | |
![]() |
9aa3773752 | |
![]() |
a76bbe49ed | |
![]() |
aed74321cb | |
![]() |
b37cf36a52 | |
![]() |
ee0b46a278 | |
![]() |
31b309fa24 | |
![]() |
7d46ee762a | |
![]() |
47ff155022 | |
![]() |
6f0a294048 | |
![]() |
f3b30625ee | |
![]() |
e823c209fa | |
![]() |
1b47cf76d3 | |
![]() |
7e19622b85 | |
![]() |
cb701cacb8 | |
![]() |
32d3d1eb92 | |
![]() |
f93fd61c26 | |
![]() |
5080cb46b1 | |
![]() |
3383532752 | |
![]() |
d84be03a83 | |
![]() |
df46bcfe2d | |
![]() |
14b6f7cafa | |
![]() |
d90592f7b6 | |
![]() |
5041aa377d | |
![]() |
fb00898035 | |
![]() |
3f04654cd3 | |
![]() |
5b2b632de3 | |
![]() |
5b2f3111b6 | |
![]() |
146581e44c | |
![]() |
02eb4623b9 | |
![]() |
d0e29d4875 | |
![]() |
4bfada2ad6 | |
![]() |
608d59f07b | |
![]() |
359abf9a82 | |
![]() |
abb7d54ef5 | |
![]() |
0c16d9a272 | |
![]() |
073191d1ea | |
![]() |
c218fcce98 | |
![]() |
17447e813b | |
![]() |
dbd1f601da | |
![]() |
be1066912f | |
![]() |
2b933264fc | |
![]() |
cdb8a4871a | |
![]() |
12c969c71c | |
![]() |
af306c4790 | |
![]() |
7aaac449f5 | |
![]() |
acc3362172 | |
![]() |
f538b4f477 | |
![]() |
12cf57409c | |
![]() |
05bc65a90b | |
![]() |
8095dc14f7 | |
![]() |
ed397d2b0f | |
![]() |
319d8e6854 | |
![]() |
e481905a25 | |
![]() |
c9a8a242a0 | |
![]() |
f8ebc6ec21 | |
![]() |
94b30c00a0 | |
![]() |
10fc47476b | |
![]() |
85772376fa | |
![]() |
1ed3f4b215 | |
![]() |
c027b54add | |
![]() |
abe489e294 | |
![]() |
94a18e9648 | |
![]() |
761694fa05 | |
![]() |
807d6e40e3 | |
![]() |
a3def6d683 | |
![]() |
0baf9f8077 | |
![]() |
f03c3dbc10 | |
![]() |
05bdd74bef | |
![]() |
dd40c4d4ee | |
![]() |
db72a36315 | |
![]() |
caf58c8ab8 | |
![]() |
5283865a5c | |
![]() |
182c4c5cbf | |
![]() |
a54f65f71b | |
![]() |
50ed675acd | |
![]() |
f146d2885b | |
![]() |
44f2684c70 | |
![]() |
6e273e7e33 | |
![]() |
05fe7431c4 | |
![]() |
b36d40a509 | |
![]() |
b9e2edce6c | |
![]() |
099a906b17 | |
![]() |
35640b8e3f | |
![]() |
36d2cf14b8 | |
![]() |
1d09ee9b3c | |
![]() |
6ccf32ec68 | |
![]() |
abeb7fceb2 | |
![]() |
0d6fffd91f | |
![]() |
38a34829af | |
![]() |
a918fcabb4 | |
![]() |
6f6cfb136a | |
![]() |
c445d7d9a9 | |
![]() |
282a793a13 | |
![]() |
c49c815ea5 | |
![]() |
fdf67b8217 | |
![]() |
db90fcd2ef | |
![]() |
64ab5e3308 | |
![]() |
8b86a1f222 | |
![]() |
6289ea91b1 | |
![]() |
289b6577d5 | |
![]() |
4bca2b2243 | |
![]() |
419c430f7e | |
![]() |
5e8be5f6bc | |
![]() |
ea64edaa0b | |
![]() |
4119e669d1 | |
![]() |
285350464f | |
![]() |
2a003a27b1 | |
![]() |
e964d3e48c | |
![]() |
1c2bdc9cab | |
![]() |
9f1bd2176f | |
![]() |
72417fc28b | |
![]() |
6978c28ee0 | |
![]() |
5cec29f4e6 | |
![]() |
2f71cce9c9 | |
![]() |
b04d8d205b | |
![]() |
ad6dd00275 | |
![]() |
477dc0cae7 | |
![]() |
0391aaf773 | |
![]() |
da1b7e8c2d | |
![]() |
9c649cd8b2 | |
![]() |
0e6d22a549 | |
![]() |
d371338920 | |
![]() |
1b79e8409f | |
![]() |
ff0f22ef44 | |
![]() |
81b4d0e28b | |
![]() |
5e606336ca | |
![]() |
f51f457023 | |
![]() |
bd0c6d4344 | |
![]() |
a15b3e4dd4 | |
![]() |
0fddd79501 | |
![]() |
ca0ff013d4 | |
![]() |
94aa76e7a1 | |
![]() |
e01a6bd0ef | |
![]() |
7eb1df4119 | |
![]() |
db23c6eecf | |
![]() |
5f8b7a8149 | |
![]() |
e8b93f6cda | |
![]() |
614dc5e591 | |
![]() |
7f6c0cd31e | |
![]() |
03c7d2e7ee | |
![]() |
d06116eb49 | |
![]() |
b72e802ff7 | |
![]() |
46bef8fd92 | |
![]() |
d470d9e63c | |
![]() |
d072680715 | |
![]() |
0b36bdf37f | |
![]() |
9a33551a03 | |
![]() |
37fab2fad2 | |
![]() |
b04d8ca99d | |
![]() |
a024866fd3 | |
![]() |
b5cc7689d1 | |
![]() |
adda82819c | |
![]() |
b143aa38ac | |
![]() |
611c353060 | |
![]() |
f87aa15bb2 | |
![]() |
f01e2b7e01 | |
![]() |
5f5e5234fc | |
![]() |
5021a4091e | |
![]() |
b89b0d2703 | |
![]() |
12dd96c3b2 | |
![]() |
d3b969fb4d | |
![]() |
17d47e9b63 | |
![]() |
387b7b5396 | |
![]() |
0179e4c786 | |
![]() |
ff97df74c6 | |
![]() |
d357de1438 | |
![]() |
1eee06d9f9 | |
![]() |
a9e0874abc | |
![]() |
3801ab87a2 | |
![]() |
6b1dd5dd8b | |
![]() |
ee0f3ff5fd | |
![]() |
9448f6712f | |
![]() |
0a83508547 | |
![]() |
1539e94b09 | |
![]() |
76a8335501 | |
![]() |
2a0c2c38f0 | |
![]() |
bf69b86233 | |
![]() |
dab223e6ce | |
![]() |
94cacdae96 | |
![]() |
1e614d64d0 | |
![]() |
52d9330114 | |
![]() |
dd9439aed2 | |
![]() |
f40756bc46 | |
![]() |
054d1c3e54 | |
![]() |
cf46c2457a | |
![]() |
250c934b9e | |
|
8b0ccf6667 | |
|
2e8798b33d | |
|
2751db3245 | |
![]() |
ee35d35db3 | |
![]() |
959854ec59 | |
![]() |
0de347d430 | |
![]() |
a4482f1a7c | |
![]() |
e3c44e956f | |
![]() |
c03dfc1284 | |
![]() |
b5e0f9966f | |
![]() |
bef6e9eceb | |
![]() |
86870167a6 | |
![]() |
2d2990ff91 | |
![]() |
a29a4f93ac | |
![]() |
75d9f8573b | |
![]() |
d63ed865f4 | |
![]() |
d860a08d21 | |
![]() |
25c79df65f | |
![]() |
bb35585194 | |
![]() |
ac27bdac4a | |
![]() |
5d0e58fcb3 | |
![]() |
8d9b36333b | |
![]() |
4faabf2185 | |
![]() |
a95f736cbe | |
![]() |
bf94bd7130 | |
![]() |
199210c2ad | |
![]() |
92a8140b77 | |
![]() |
8058a89cde | |
![]() |
daacd0036f | |
![]() |
f4614658cf | |
![]() |
15b8cf7f78 | |
![]() |
30210d0de7 | |
![]() |
621911eb64 | |
![]() |
36cd5eeea9 | |
![]() |
1dcc70c097 | |
![]() |
8269f79173 | |
![]() |
02aa281d30 | |
![]() |
28081bfd3e | |
![]() |
6c8ec46725 | |
![]() |
1f477bbc86 | |
![]() |
7216d8d12e | |
![]() |
08d87fa975 | |
![]() |
f60108f367 | |
![]() |
935b789d02 | |
![]() |
5d4dfd8cb5 | |
![]() |
d8b0bd4df8 | |
![]() |
149d1f8156 | |
![]() |
004106eb19 | |
![]() |
648dfd75c4 | |
![]() |
904b7e580b | |
![]() |
2d7911f155 | |
![]() |
aa1a946336 | |
![]() |
417301ff06 | |
![]() |
108551c199 | |
![]() |
11d950221b | |
![]() |
5055c5de11 | |
![]() |
24460ea979 | |
![]() |
df12f87b47 | |
![]() |
cd808ac59f | |
![]() |
a0e5cc25e1 | |
![]() |
7b328fbfc3 | |
![]() |
44d18b77be | |
![]() |
92eb202d5d | |
![]() |
4bb05b32f5 | |
![]() |
47a8f70f0f | |
![]() |
681d5203e5 | |
![]() |
c68f5e276f | |
![]() |
b3ea687d32 | |
![]() |
8948da0612 | |
![]() |
327eafddb7 | |
![]() |
6bebbb3f70 | |
![]() |
f6cc629054 | |
![]() |
cf7c19ef62 | |
![]() |
880f31a7c6 | |
![]() |
6cd72543c4 | |
![]() |
fda58a6008 | |
![]() |
f80db9e8fb | |
![]() |
b032dad578 | |
![]() |
588bf30b94 | |
![]() |
ac3fd15c5a | |
![]() |
3934eec902 | |
![]() |
992ca7e842 | |
![]() |
9eae1e151d | |
![]() |
7fadf7bad5 | |
![]() |
967fb9e30f | |
![]() |
92a8c48953 | |
![]() |
baba6081b3 | |
![]() |
2ff8251a81 | |
![]() |
8e54f7ca9c | |
![]() |
64bc1f1afb | |
![]() |
8fc0151444 | |
![]() |
d7fae300b9 | |
![]() |
8a0c7279dc | |
![]() |
6ec13017eb | |
![]() |
9bdd83771e | |
![]() |
7b3b257580 | |
![]() |
7bb3245092 | |
![]() |
46aa6fc907 | |
![]() |
6a382830a9 | |
![]() |
17511ddb6a | |
![]() |
f33ffaf18b | |
![]() |
5722fdb163 | |
![]() |
8d52e27c2b | |
![]() |
b6cda6cd4c | |
![]() |
e325efa447 | |
![]() |
f0550383d1 | |
![]() |
8ce8b2fff3 | |
![]() |
5dc38f1526 | |
![]() |
eb2a1857dc | |
![]() |
88c6818cfd | |
![]() |
be9dba4788 | |
![]() |
7190c8518e | |
![]() |
b49fbf0cd6 | |
![]() |
48f703282e | |
![]() |
6b7233c6ae | |
![]() |
35d60aaae5 | |
![]() |
191151eb7b | |
![]() |
266b34d578 | |
![]() |
8764d28e9e | |
![]() |
3bac0aabd9 | |
![]() |
856ee9a0fe | |
![]() |
6e4764b97c | |
![]() |
1b074bd94d | |
![]() |
e7c41ae9e6 | |
![]() |
9fe85e280a | |
![]() |
3c71354b42 | |
![]() |
5aa5d91ecb | |
![]() |
993d9e9ed6 | |
![]() |
ae3b2b8572 | |
![]() |
c5b5435b4a | |
![]() |
b8d88c97b0 | |
![]() |
81c7d05d7c | |
![]() |
b0e34bbe6a | |
![]() |
d43562883e | |
![]() |
70853f2b86 | |
![]() |
3c1bf3c014 | |
![]() |
81f4436951 | |
![]() |
ef28b0dd14 | |
![]() |
fee1619c9c | |
![]() |
bb9d1c8265 | |
![]() |
a96835e35f | |
![]() |
d107605007 | |
![]() |
73be03161f | |
![]() |
3472ec6613 | |
![]() |
dc415c3d2a | |
![]() |
89bf0da30c | |
![]() |
ca548e2902 | |
![]() |
81aae35565 | |
![]() |
9ab7f7d140 | |
![]() |
3debfb9182 | |
![]() |
4a14a44f3f | |
![]() |
6b6eca61cb | |
![]() |
ade8566d06 | |
![]() |
84c98546df | |
![]() |
8dc03f40d5 | |
![]() |
e3b3d7c9aa | |
![]() |
e085b4b422 | |
![]() |
514829de60 | |
![]() |
974b6efad5 | |
![]() |
92b1e544ec | |
![]() |
584d782a9f | |
![]() |
3146d4ef35 | |
![]() |
859cec774a | |
![]() |
88227a3647 | |
![]() |
d411c5ebc0 | |
![]() |
71aa7e468b | |
![]() |
b9d4d57e33 | |
![]() |
d83553ca14 | |
![]() |
0ecdee08cc | |
![]() |
4cb2eb6d37 | |
![]() |
191ca3c4eb | |
![]() |
1546c1514a | |
![]() |
66218319dd | |
![]() |
8b3c4302d2 | |
![]() |
6b8e240d26 | |
![]() |
a205eace38 | |
![]() |
f3bf56d9e3 | |
![]() |
e48188b429 | |
![]() |
c03d8beb8b | |
![]() |
fad38cd0e9 | |
![]() |
c89e6f4c28 | |
![]() |
c9c02f5461 | |
![]() |
860cdb0aea | |
![]() |
d0a8a32a57 | |
![]() |
397e312424 | |
![]() |
48666c4604 | |
![]() |
210b5c295d | |
![]() |
dbe7fd6ef0 | |
![]() |
716218aa37 | |
![]() |
ffd688e2d7 | |
![]() |
fef050f6dd | |
![]() |
2c3e90b126 | |
![]() |
5fea22ff03 | |
![]() |
81b7bcc5bc | |
![]() |
aa6345ab5e | |
![]() |
407d855466 | |
![]() |
2b63369060 | |
![]() |
19cc25f716 | |
![]() |
29f0631a2c | |
![]() |
9e545d0d39 | |
![]() |
8a17bc901c | |
![]() |
9b9dd43c2a | |
![]() |
6f412df232 | |
![]() |
fb3245977c | |
![]() |
58815059ea | |
![]() |
7bfe9fdd0a | |
![]() |
11d40197ee | |
![]() |
3e30ccfdfa | |
![]() |
d0d0c4f197 | |
![]() |
64157090e6 | |
![]() |
51665e8396 | |
![]() |
66984a4bb3 | |
![]() |
0d74b4f36b | |
![]() |
3b9b9b322a | |
![]() |
0fbd2d107c | |
![]() |
c304ecd0ca | |
![]() |
5f7a8dbd5d | |
![]() |
8ad53ce327 | |
![]() |
bd4362e26c | |
![]() |
a0b3f7a769 | |
![]() |
125d1a32c7 | |
![]() |
9d9131c3fb | |
![]() |
543df84db6 | |
![]() |
f0ed20fd67 | |
![]() |
bf2e3cdfae | |
![]() |
7ce23fdf52 | |
![]() |
439a416a66 | |
![]() |
cd18341330 | |
![]() |
9017e5a25b | |
![]() |
32629a2f2a | |
![]() |
2168b57cac | |
![]() |
37ab015c8d | |
![]() |
6db2832577 | |
![]() |
0165e8f348 | |
![]() |
b56cd11c98 | |
![]() |
7b32f6388f | |
![]() |
df111dbf98 | |
![]() |
0e101debe0 | |
![]() |
646e5104f6 | |
![]() |
bef27c3b36 | |
![]() |
d80fa387b9 | |
![]() |
89b495c667 | |
![]() |
2dd7ba7e9b | |
![]() |
ebc2e6e26c | |
![]() |
942f746a21 | |
![]() |
9feea63086 | |
![]() |
2bebd0e87f | |
![]() |
aa159bc9b0 | |
![]() |
99a831a03b | |
![]() |
5ab99429d4 | |
![]() |
250047579f | |
![]() |
bd72086704 | |
![]() |
261b26c8e9 | |
![]() |
620620fa61 | |
![]() |
fc7e621471 | |
![]() |
6491ce0aa5 | |
![]() |
c19f97bc24 | |
![]() |
cdd719cc47 | |
![]() |
59c106f7a7 | |
![]() |
213fd6b203 | |
![]() |
8922bb5e84 | |
![]() |
ebca89d920 | |
![]() |
734e6e97c0 | |
![]() |
9870cfe8a8 | |
![]() |
c00a7fd132 | |
![]() |
7c551dc39d | |
![]() |
54a34a9b22 | |
![]() |
e7942962d3 | |
![]() |
952a5423fd | |
![]() |
dd8a324f9b | |
![]() |
d3f808f66d | |
![]() |
4de9d25f04 | |
![]() |
32af7f45df | |
![]() |
e75ed79fb5 | |
![]() |
04d7c343ef | |
![]() |
139592bc00 | |
![]() |
14e2910f83 | |
![]() |
bd9184bd92 | |
![]() |
7f38aca766 | |
![]() |
3e4fbe93a6 | |
![]() |
ed58e7e012 | |
![]() |
4c8da2c503 | |
![]() |
ae4e875729 | |
![]() |
c6c01c332f | |
![]() |
efc5431da2 | |
![]() |
1941020993 | |
![]() |
ac950978a9 | |
![]() |
0d12dedd90 | |
![]() |
71a77c77f6 | |
![]() |
748f0034bd | |
![]() |
61440392d2 | |
![]() |
c94ebb45e7 | |
![]() |
09a586936b | |
![]() |
059a546689 | |
![]() |
14721001e5 | |
![]() |
15702ec856 | |
![]() |
6216daedb3 | |
![]() |
1960b373f1 | |
![]() |
c0780f938e | |
![]() |
98dd9f90c8 | |
![]() |
9639dc5f96 | |
![]() |
72f966b118 | |
![]() |
3a3653d47e | |
![]() |
89389e82e8 | |
![]() |
b5438c3ae4 | |
![]() |
02633e32c3 | |
![]() |
e77f9dbd36 | |
![]() |
37d72351be | |
![]() |
6afdb7b6c8 | |
![]() |
831276f378 | |
![]() |
39b364fa77 | |
![]() |
d84304cba5 | |
![]() |
761c85468f | |
![]() |
a06035ecb8 | |
![]() |
ef0147eb37 | |
![]() |
8ccad5b954 | |
![]() |
7e1b11276c | |
![]() |
2ea453f484 | |
![]() |
64fef98bd7 | |
![]() |
1c5f47703b | |
![]() |
427bbfa630 | |
![]() |
e24d77bde8 | |
![]() |
d38ddcbc41 | |
![]() |
e4f9360e63 | |
![]() |
4af02c86f8 | |
![]() |
45c93f58ec | |
![]() |
7fe65067ee | |
![]() |
d2ac1afcf0 | |
![]() |
adf20f58d4 | |
![]() |
5de577400b | |
![]() |
6585ee9ae8 | |
![]() |
640c0297ef | |
![]() |
02133d0bd4 | |
![]() |
8b7410f803 | |
![]() |
6be1f56288 | |
![]() |
5b3da83715 | |
![]() |
707ef97626 | |
![]() |
accfc93573 | |
![]() |
4a29e8406d |
|
@ -0,0 +1,211 @@
|
||||||
|
name: Build
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-linux:
|
||||||
|
runs-on: ${{ matrix.host_os }}
|
||||||
|
container: ${{ matrix.container }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
target_os: [linux]
|
||||||
|
host_os: [ubuntu-20.04]
|
||||||
|
container: ['']
|
||||||
|
fail-fast: false
|
||||||
|
steps:
|
||||||
|
- name: Install Colobot dependencies
|
||||||
|
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends build-essential cmake libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsndfile1-dev libvorbis-dev libogg-dev libpng-dev libglew-dev libopenal-dev libphysfs-dev gettext git po4a vorbis-tools librsvg2-bin xmlstarlet libglm-dev libmpg123-dev
|
||||||
|
if: matrix.container == ''
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Checkout the Google Test submodule
|
||||||
|
run: git submodule update --init -- lib/googletest
|
||||||
|
- name: Checkout the nlohmann json submodule
|
||||||
|
run: git submodule update --init -- lib/json
|
||||||
|
- name: Create build directory
|
||||||
|
run: cmake -E make_directory build
|
||||||
|
- name: Run CMake (for Linux)
|
||||||
|
run: cmake --preset Linux-CI
|
||||||
|
if: matrix.target_os == 'linux'
|
||||||
|
- name: Build
|
||||||
|
run: cmake --build --preset Linux-CI
|
||||||
|
- name: Install
|
||||||
|
run: cmake --build --preset Linux-CI --target install
|
||||||
|
- name: Patch library path
|
||||||
|
run: patchelf --set-rpath '.' install/colobot
|
||||||
|
if: matrix.target_os == 'linux'
|
||||||
|
- name: Upload build
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: ${{matrix.target_os}}-debug
|
||||||
|
path: install
|
||||||
|
if: matrix.host_os == 'ubuntu-20.04'
|
||||||
|
- name: Create AppImage
|
||||||
|
working-directory: build
|
||||||
|
run: |
|
||||||
|
# Download app image tool
|
||||||
|
wget -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
|
||||||
|
chmod +x linuxdeploy-x86_64.AppImage
|
||||||
|
./linuxdeploy-x86_64.AppImage --appimage-extract
|
||||||
|
|
||||||
|
# Create AppImage
|
||||||
|
NO_STRIP=1 ./squashfs-root/AppRun -e colobot --output appimage --appdir colobot.AppDir -d desktop/colobot.desktop -i ../desktop/colobot.svg
|
||||||
|
chmod +x Colobot-x86_64.AppImage
|
||||||
|
|
||||||
|
# Prepare folder for zip
|
||||||
|
mkdir -p appimage
|
||||||
|
cp -rp ../install/data appimage/data
|
||||||
|
cp -rp ../install/lang appimage/lang
|
||||||
|
cp -p Colobot-x86_64.AppImage appimage/colobot
|
||||||
|
if: matrix.target_os == 'linux'
|
||||||
|
- name: Upload AppImage
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: ${{matrix.target_os}}-debug-AppImage
|
||||||
|
path: build/appimage
|
||||||
|
if: matrix.target_os == 'linux' && matrix.host_os == 'ubuntu-20.04'
|
||||||
|
- name: Run tests
|
||||||
|
# TODO: Maybe run Windows tests using wine as well?
|
||||||
|
working-directory: build
|
||||||
|
run: ./Colobot-UnitTests --gtest_output=xml:gtestresults.xml
|
||||||
|
if: matrix.target_os == 'linux'
|
||||||
|
- name: Upload test results
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: Test results (${{ matrix.target_os }}, ${{ matrix.host_os }})
|
||||||
|
path: build/gtestresults.xml
|
||||||
|
if: matrix.target_os == 'linux'
|
||||||
|
build-macos:
|
||||||
|
runs-on: ${{ matrix.host_os }}
|
||||||
|
container: ${{ matrix.container }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
target_os: [macos]
|
||||||
|
host_os: [macos-11, macos-12]
|
||||||
|
container: ['']
|
||||||
|
fail-fast: false
|
||||||
|
steps:
|
||||||
|
- name: Install Colobot dependencies
|
||||||
|
run: brew install cmake sdl2 sdl2_image sdl2_ttf glew physfs flac libsndfile libvorbis vorbis-tools gettext libicns librsvg wget xmlstarlet glm
|
||||||
|
if: matrix.container == ''
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Checkout the Google Test submodule
|
||||||
|
run: git submodule update --init -- lib/googletest
|
||||||
|
- name: Checkout the nlohmann json submodule
|
||||||
|
run: git submodule update --init -- lib/json
|
||||||
|
- name: Create build directory
|
||||||
|
run: cmake -E make_directory build
|
||||||
|
- name: Run CMake (for Mac)
|
||||||
|
run: cmake --preset MacOS-CI
|
||||||
|
if: matrix.target_os == 'macos'
|
||||||
|
- name: Build
|
||||||
|
run: cmake --build --preset MacOS-CI
|
||||||
|
- name: Run tests
|
||||||
|
# TODO: Maybe run Windows tests using wine as well?
|
||||||
|
working-directory: build
|
||||||
|
run: ./Colobot-UnitTests --gtest_output=xml:gtestresults.xml
|
||||||
|
if: matrix.target_os == 'macos'
|
||||||
|
- name: Upload test results
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: Test results (${{ matrix.target_os }}, ${{ matrix.host_os }})
|
||||||
|
path: build/gtestresults.xml
|
||||||
|
if: matrix.target_os == 'macos'
|
||||||
|
build-windows:
|
||||||
|
runs-on: windows-2019
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- arch: amd64
|
||||||
|
vcpkg_triplet: 'x64-windows-static'
|
||||||
|
- arch: x86
|
||||||
|
vcpkg_triplet: 'x86-windows-static'
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Checkout the Google Test submodule
|
||||||
|
run: git submodule update --init -- lib/googletest
|
||||||
|
- name: Checkout the nlohmann json submodule
|
||||||
|
run: git submodule update --init -- lib/json
|
||||||
|
- name: Install Ninja
|
||||||
|
uses: seanmiddleditch/gha-setup-ninja@master
|
||||||
|
- name: Setup VS Environment
|
||||||
|
uses: seanmiddleditch/gha-setup-vsdevenv@master
|
||||||
|
with:
|
||||||
|
arch: ${{ matrix.arch }}
|
||||||
|
- name: Install Colobot dependencies
|
||||||
|
uses: lukka/run-vcpkg@v7
|
||||||
|
with:
|
||||||
|
setupOnly: true
|
||||||
|
vcpkgGitCommitId: 'f6a5d4e8eb7476b8d7fc12a56dff300c1c986131'
|
||||||
|
vcpkgTriplet: ${{ matrix.vcpkg_triplet }}
|
||||||
|
# SHA-256 hash of the vcpkg.json file, recalculated automatically when it changes
|
||||||
|
appendedCacheKey: ${{ hashFiles( '**/vcpkg.json' ) }}
|
||||||
|
additionalCachedPaths: ${{ github.workspace }}/build/vcpkg_installed
|
||||||
|
- name: Install external tools
|
||||||
|
working-directory: ${{ github.workspace }}
|
||||||
|
run: |
|
||||||
|
echo "Downloading gettext..."
|
||||||
|
(New-Object System.Net.WebClient).DownloadFile("https://github.com/mlocati/gettext-iconv-windows/releases/download/v0.20.2-v1.16/gettext0.20.2-iconv1.16-static-64.zip", "gettext.zip");
|
||||||
|
echo "Unpacking gettext..."
|
||||||
|
7z x -ogettext gettext.zip;
|
||||||
|
echo "Adding gettext to PATH..."
|
||||||
|
echo "${{ github.workspace }}\gettext\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||||
|
echo "Downloading xmlstarlet..."
|
||||||
|
(New-Object System.Net.WebClient).DownloadFile("https://downloads.sourceforge.net/project/xmlstar/xmlstarlet/1.6.1/xmlstarlet-1.6.1-win32.zip", "xmlstarlet.zip");
|
||||||
|
echo "Unpacking xmlstarlet..."
|
||||||
|
7z x -oxmlstarlet xmlstarlet.zip;
|
||||||
|
echo "Renaming xml.exe to xmlstarlet.exe"
|
||||||
|
Rename-Item -Path "${{ github.workspace }}\xmlstarlet\xmlstarlet-1.6.1\xml.exe" -NewName "xmlstarlet.exe"
|
||||||
|
echo "Adding xmlstarlet to PATH..."
|
||||||
|
echo "${{ github.workspace }}\xmlstarlet\xmlstarlet-1.6.1" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||||
|
echo "Downloading rsvg-convert..."
|
||||||
|
(New-Object System.Net.WebClient).DownloadFile("https://downloads.sourceforge.net/project/tumagcc/rsvg-convert-2.40.20.7z", "rsvg-convert.zip");
|
||||||
|
echo "Unpacking xmlstarlet..."
|
||||||
|
7z x -orsvg-convert rsvg-convert.zip;
|
||||||
|
echo "Adding rsvg-convert to PATH..."
|
||||||
|
echo "${{ github.workspace }}\rsvg-convert" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||||
|
shell: pwsh
|
||||||
|
- name: Create build directory
|
||||||
|
run: cmake -E make_directory build
|
||||||
|
- name: Run CMake (for Windows)
|
||||||
|
run: cmake --preset Windows-CI -DVCPKG_TARGET_TRIPLET=${{ matrix.vcpkg_triplet }} -DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_ROOT }}\scripts\buildsystems\vcpkg.cmake
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
$nproc = (Get-CIMInstance -Class 'CIM_Processor').NumberOfLogicalProcessors
|
||||||
|
cmake --build --preset Windows-CI -j $nproc
|
||||||
|
shell: pwsh
|
||||||
|
- name: Install
|
||||||
|
run: cmake --build --preset Windows-CI --target install
|
||||||
|
- name: Upload build
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: windows-msvc-debug-${{ matrix.arch }}
|
||||||
|
path: install
|
||||||
|
- name: Run tests
|
||||||
|
working-directory: build
|
||||||
|
run: ./Colobot-UnitTests --gtest_output=xml:gtestresults.xml
|
||||||
|
- name: Upload test results
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: 'Test results (windows, MSVC, ${{ matrix.arch }})'
|
||||||
|
path: build/gtestresults.xml
|
||||||
|
doc:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Install Colobot dependencies
|
||||||
|
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends build-essential cmake libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsndfile1-dev libvorbis-dev libogg-dev libpng-dev libglew-dev libopenal-dev libphysfs-dev gettext git po4a vorbis-tools librsvg2-bin xmlstarlet doxygen graphviz libglm-dev libmpg123-dev
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Create build directory
|
||||||
|
run: cmake -E make_directory build
|
||||||
|
- name: Checkout the nlohmann json submodule
|
||||||
|
run: git submodule update --init -- lib/json
|
||||||
|
- name: Run CMake
|
||||||
|
working-directory: build
|
||||||
|
run: cmake ..
|
||||||
|
- name: Build docs
|
||||||
|
working-directory: build
|
||||||
|
run: make doc
|
||||||
|
- name: Upload docs
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: doc
|
||||||
|
path: build/doc
|
|
@ -0,0 +1,21 @@
|
||||||
|
name: Verify pull request target
|
||||||
|
|
||||||
|
on: [pull_request_target]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check_pr_target:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Send comment if wrong pull request target
|
||||||
|
if: github.base_ref == 'master'
|
||||||
|
uses: peter-evans/create-or-update-comment@v1
|
||||||
|
with:
|
||||||
|
issue-number: ${{ github.event.number }}
|
||||||
|
body: |
|
||||||
|
Hey! This pull request targets the `master` branch. You should probably target `dev` instead. Make sure to read the [contributing guidelines](https://github.com/colobot/colobot/blob/master/CONTRIBUTING.md#submitting-pull-requests) and [edit the target branch if necessary](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/changing-the-base-branch-of-a-pull-request).
|
||||||
|
- name: Wrong pull request target
|
||||||
|
if: github.base_ref == 'master'
|
||||||
|
run: echo "This pull request targets the master branch. Please edit the pull request to target dev." && exit 1
|
||||||
|
- name: Correct pull request target
|
||||||
|
if: github.base_ref != 'master'
|
||||||
|
run: echo "This pull request targets the correct branch." && exit 0
|
|
@ -11,11 +11,12 @@ Makefile
|
||||||
/src/libcolobotbase.a
|
/src/libcolobotbase.a
|
||||||
|
|
||||||
# Ignore the generated documentation
|
# Ignore the generated documentation
|
||||||
|
CMakeDoxyfile.in
|
||||||
|
CMakeDoxygenDefaults.cmake
|
||||||
/doc
|
/doc
|
||||||
/Doxyfile
|
/Doxyfile
|
||||||
|
|
||||||
# Ignore targets
|
# Ignore targets
|
||||||
/colobot
|
|
||||||
/src/CBot/libCBot.so
|
/src/CBot/libCBot.so
|
||||||
|
|
||||||
# Ignore local data
|
# Ignore local data
|
||||||
|
@ -23,7 +24,7 @@ Makefile
|
||||||
/saves
|
/saves
|
||||||
|
|
||||||
# Standard build directory
|
# Standard build directory
|
||||||
/build
|
/build*
|
||||||
|
|
||||||
# Ignore KDevelop files
|
# Ignore KDevelop files
|
||||||
.kdev4
|
.kdev4
|
||||||
|
@ -35,3 +36,17 @@ Makefile
|
||||||
# Ignore QtCreator temp files
|
# Ignore QtCreator temp files
|
||||||
CMakeLists.txt.user
|
CMakeLists.txt.user
|
||||||
CMakeLists.txt.user.*
|
CMakeLists.txt.user.*
|
||||||
|
|
||||||
|
# Ignore Visual Studio Code files
|
||||||
|
/.vscode
|
||||||
|
|
||||||
|
# Ignore CLion files
|
||||||
|
/.idea
|
||||||
|
|
||||||
|
# Ignore Visual Studio files
|
||||||
|
/CMakeSettings.json
|
||||||
|
/.vs
|
||||||
|
/out
|
||||||
|
|
||||||
|
# Ignore CMakeUserPresets.json
|
||||||
|
CMakeUserPresets.json
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
[submodule "data"]
|
[submodule "data"]
|
||||||
path = data
|
path = data
|
||||||
url = git://github.com/colobot/colobot-data.git
|
url = https://github.com/colobot/colobot-data.git
|
||||||
|
branch = .
|
||||||
|
update = rebase
|
||||||
|
[submodule "lib/googletest"]
|
||||||
|
path = lib/googletest
|
||||||
|
url = https://github.com/google/googletest.git
|
||||||
|
ignore = all
|
||||||
|
[submodule "lib/json"]
|
||||||
|
path = lib/json
|
||||||
|
url = https://github.com/nlohmann/json
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
if(CBOT_STATIC)
|
||||||
|
add_library(CBot STATIC)
|
||||||
|
else()
|
||||||
|
add_library(CBot SHARED)
|
||||||
|
install(TARGETS CBot
|
||||||
|
LIBRARY DESTINATION ${COLOBOT_INSTALL_LIB_DIR}
|
||||||
|
ARCHIVE DESTINATION ${COLOBOT_INSTALL_LIB_DIR}
|
||||||
|
RUNTIME DESTINATION ${COLOBOT_INSTALL_BIN_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_sources(CBot PRIVATE
|
||||||
|
src/CBot/CBot.h
|
||||||
|
src/CBot/CBotCStack.cpp
|
||||||
|
src/CBot/CBotCStack.h
|
||||||
|
src/CBot/CBotClass.cpp
|
||||||
|
src/CBot/CBotClass.h
|
||||||
|
src/CBot/CBotDebug.cpp
|
||||||
|
src/CBot/CBotDebug.h
|
||||||
|
src/CBot/CBotDefParam.cpp
|
||||||
|
src/CBot/CBotDefParam.h
|
||||||
|
src/CBot/CBotDefines.h
|
||||||
|
src/CBot/CBotEnums.h
|
||||||
|
src/CBot/CBotExternalCall.cpp
|
||||||
|
src/CBot/CBotExternalCall.h
|
||||||
|
src/CBot/CBotFileUtils.cpp
|
||||||
|
src/CBot/CBotFileUtils.h
|
||||||
|
src/CBot/CBotInstr/CBotBlock.cpp
|
||||||
|
src/CBot/CBotInstr/CBotBlock.h
|
||||||
|
src/CBot/CBotInstr/CBotBoolExpr.cpp
|
||||||
|
src/CBot/CBotInstr/CBotBoolExpr.h
|
||||||
|
src/CBot/CBotInstr/CBotBreak.cpp
|
||||||
|
src/CBot/CBotInstr/CBotBreak.h
|
||||||
|
src/CBot/CBotInstr/CBotCase.cpp
|
||||||
|
src/CBot/CBotInstr/CBotCase.h
|
||||||
|
src/CBot/CBotInstr/CBotCatch.cpp
|
||||||
|
src/CBot/CBotInstr/CBotCatch.h
|
||||||
|
src/CBot/CBotInstr/CBotCondition.cpp
|
||||||
|
src/CBot/CBotInstr/CBotCondition.h
|
||||||
|
src/CBot/CBotInstr/CBotDefArray.cpp
|
||||||
|
src/CBot/CBotInstr/CBotDefArray.h
|
||||||
|
src/CBot/CBotInstr/CBotDefBoolean.cpp
|
||||||
|
src/CBot/CBotInstr/CBotDefBoolean.h
|
||||||
|
src/CBot/CBotInstr/CBotDefClass.cpp
|
||||||
|
src/CBot/CBotInstr/CBotDefClass.h
|
||||||
|
src/CBot/CBotInstr/CBotDefFloat.cpp
|
||||||
|
src/CBot/CBotInstr/CBotDefFloat.h
|
||||||
|
src/CBot/CBotInstr/CBotDefInt.cpp
|
||||||
|
src/CBot/CBotInstr/CBotDefInt.h
|
||||||
|
src/CBot/CBotInstr/CBotDefString.cpp
|
||||||
|
src/CBot/CBotInstr/CBotDefString.h
|
||||||
|
src/CBot/CBotInstr/CBotDo.cpp
|
||||||
|
src/CBot/CBotInstr/CBotDo.h
|
||||||
|
src/CBot/CBotInstr/CBotEmpty.cpp
|
||||||
|
src/CBot/CBotInstr/CBotEmpty.h
|
||||||
|
src/CBot/CBotInstr/CBotExprLitBool.cpp
|
||||||
|
src/CBot/CBotInstr/CBotExprLitBool.h
|
||||||
|
src/CBot/CBotInstr/CBotExprLitChar.cpp
|
||||||
|
src/CBot/CBotInstr/CBotExprLitChar.h
|
||||||
|
src/CBot/CBotInstr/CBotExprLitNan.cpp
|
||||||
|
src/CBot/CBotInstr/CBotExprLitNan.h
|
||||||
|
src/CBot/CBotInstr/CBotExprLitNull.cpp
|
||||||
|
src/CBot/CBotInstr/CBotExprLitNull.h
|
||||||
|
src/CBot/CBotInstr/CBotExprLitNum.cpp
|
||||||
|
src/CBot/CBotInstr/CBotExprLitNum.h
|
||||||
|
src/CBot/CBotInstr/CBotExprLitString.cpp
|
||||||
|
src/CBot/CBotInstr/CBotExprLitString.h
|
||||||
|
src/CBot/CBotInstr/CBotExprRetVar.cpp
|
||||||
|
src/CBot/CBotInstr/CBotExprRetVar.h
|
||||||
|
src/CBot/CBotInstr/CBotExprUnaire.cpp
|
||||||
|
src/CBot/CBotInstr/CBotExprUnaire.h
|
||||||
|
src/CBot/CBotInstr/CBotExprVar.cpp
|
||||||
|
src/CBot/CBotInstr/CBotExprVar.h
|
||||||
|
src/CBot/CBotInstr/CBotExpression.cpp
|
||||||
|
src/CBot/CBotInstr/CBotExpression.h
|
||||||
|
src/CBot/CBotInstr/CBotFieldExpr.cpp
|
||||||
|
src/CBot/CBotInstr/CBotFieldExpr.h
|
||||||
|
src/CBot/CBotInstr/CBotFor.cpp
|
||||||
|
src/CBot/CBotInstr/CBotFor.h
|
||||||
|
src/CBot/CBotInstr/CBotFunction.cpp
|
||||||
|
src/CBot/CBotInstr/CBotFunction.h
|
||||||
|
src/CBot/CBotInstr/CBotIf.cpp
|
||||||
|
src/CBot/CBotInstr/CBotIf.h
|
||||||
|
src/CBot/CBotInstr/CBotIndexExpr.cpp
|
||||||
|
src/CBot/CBotInstr/CBotIndexExpr.h
|
||||||
|
src/CBot/CBotInstr/CBotInstr.cpp
|
||||||
|
src/CBot/CBotInstr/CBotInstr.h
|
||||||
|
src/CBot/CBotInstr/CBotInstrCall.cpp
|
||||||
|
src/CBot/CBotInstr/CBotInstrCall.h
|
||||||
|
src/CBot/CBotInstr/CBotInstrMethode.cpp
|
||||||
|
src/CBot/CBotInstr/CBotInstrMethode.h
|
||||||
|
src/CBot/CBotInstr/CBotInstrUtils.cpp
|
||||||
|
src/CBot/CBotInstr/CBotInstrUtils.h
|
||||||
|
src/CBot/CBotInstr/CBotLeftExpr.cpp
|
||||||
|
src/CBot/CBotInstr/CBotLeftExpr.h
|
||||||
|
src/CBot/CBotInstr/CBotLeftExprVar.cpp
|
||||||
|
src/CBot/CBotInstr/CBotLeftExprVar.h
|
||||||
|
src/CBot/CBotInstr/CBotListArray.cpp
|
||||||
|
src/CBot/CBotInstr/CBotListArray.h
|
||||||
|
src/CBot/CBotInstr/CBotListExpression.cpp
|
||||||
|
src/CBot/CBotInstr/CBotListExpression.h
|
||||||
|
src/CBot/CBotInstr/CBotListInstr.cpp
|
||||||
|
src/CBot/CBotInstr/CBotListInstr.h
|
||||||
|
src/CBot/CBotInstr/CBotLogicExpr.cpp
|
||||||
|
src/CBot/CBotInstr/CBotLogicExpr.h
|
||||||
|
src/CBot/CBotInstr/CBotNew.cpp
|
||||||
|
src/CBot/CBotInstr/CBotNew.h
|
||||||
|
src/CBot/CBotInstr/CBotParExpr.cpp
|
||||||
|
src/CBot/CBotInstr/CBotParExpr.h
|
||||||
|
src/CBot/CBotInstr/CBotPostIncExpr.cpp
|
||||||
|
src/CBot/CBotInstr/CBotPostIncExpr.h
|
||||||
|
src/CBot/CBotInstr/CBotPreIncExpr.cpp
|
||||||
|
src/CBot/CBotInstr/CBotPreIncExpr.h
|
||||||
|
src/CBot/CBotInstr/CBotRepeat.cpp
|
||||||
|
src/CBot/CBotInstr/CBotRepeat.h
|
||||||
|
src/CBot/CBotInstr/CBotReturn.cpp
|
||||||
|
src/CBot/CBotInstr/CBotReturn.h
|
||||||
|
src/CBot/CBotInstr/CBotSwitch.cpp
|
||||||
|
src/CBot/CBotInstr/CBotSwitch.h
|
||||||
|
src/CBot/CBotInstr/CBotThrow.cpp
|
||||||
|
src/CBot/CBotInstr/CBotThrow.h
|
||||||
|
src/CBot/CBotInstr/CBotTry.cpp
|
||||||
|
src/CBot/CBotInstr/CBotTry.h
|
||||||
|
src/CBot/CBotInstr/CBotTwoOpExpr.cpp
|
||||||
|
src/CBot/CBotInstr/CBotTwoOpExpr.h
|
||||||
|
src/CBot/CBotInstr/CBotWhile.cpp
|
||||||
|
src/CBot/CBotInstr/CBotWhile.h
|
||||||
|
src/CBot/CBotProgram.cpp
|
||||||
|
src/CBot/CBotProgram.h
|
||||||
|
src/CBot/CBotStack.cpp
|
||||||
|
src/CBot/CBotStack.h
|
||||||
|
src/CBot/CBotToken.cpp
|
||||||
|
src/CBot/CBotToken.h
|
||||||
|
src/CBot/CBotTypResult.cpp
|
||||||
|
src/CBot/CBotTypResult.h
|
||||||
|
src/CBot/CBotUtils.cpp
|
||||||
|
src/CBot/CBotUtils.h
|
||||||
|
src/CBot/CBotVar/CBotVar.cpp
|
||||||
|
src/CBot/CBotVar/CBotVar.h
|
||||||
|
src/CBot/CBotVar/CBotVarValue.h
|
||||||
|
src/CBot/CBotVar/CBotVarArray.cpp
|
||||||
|
src/CBot/CBotVar/CBotVarArray.h
|
||||||
|
src/CBot/CBotVar/CBotVarBoolean.cpp
|
||||||
|
src/CBot/CBotVar/CBotVarBoolean.h
|
||||||
|
src/CBot/CBotVar/CBotVarByte.h
|
||||||
|
src/CBot/CBotVar/CBotVarChar.h
|
||||||
|
src/CBot/CBotVar/CBotVarClass.cpp
|
||||||
|
src/CBot/CBotVar/CBotVarClass.h
|
||||||
|
src/CBot/CBotVar/CBotVarDouble.h
|
||||||
|
src/CBot/CBotVar/CBotVarFloat.cpp
|
||||||
|
src/CBot/CBotVar/CBotVarFloat.h
|
||||||
|
src/CBot/CBotVar/CBotVarInt.cpp
|
||||||
|
src/CBot/CBotVar/CBotVarInt.h
|
||||||
|
src/CBot/CBotVar/CBotVarLong.h
|
||||||
|
src/CBot/CBotVar/CBotVarPointer.cpp
|
||||||
|
src/CBot/CBotVar/CBotVarPointer.h
|
||||||
|
src/CBot/CBotVar/CBotVarShort.h
|
||||||
|
src/CBot/CBotVar/CBotVarString.cpp
|
||||||
|
src/CBot/CBotVar/CBotVarString.h
|
||||||
|
src/CBot/stdlib/Compilation.cpp
|
||||||
|
src/CBot/stdlib/Compilation.h
|
||||||
|
src/CBot/stdlib/FileFunctions.cpp
|
||||||
|
src/CBot/stdlib/MathFunctions.cpp
|
||||||
|
src/CBot/stdlib/StringFunctions.cpp
|
||||||
|
src/CBot/stdlib/stdlib.h
|
||||||
|
src/CBot/stdlib/stdlib_public.h
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(CBot PUBLIC src)
|
||||||
|
target_link_libraries(CBot PRIVATE
|
||||||
|
Colobot-Common
|
||||||
|
)
|
||||||
|
|
||||||
|
if(COLOBOT_LINT_BUILD)
|
||||||
|
add_fake_header_sources("src/CBot" CBot)
|
||||||
|
endif()
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* \dir src/CBot
|
* \dir CBot
|
||||||
* \brief CBot library
|
* \brief CBot library
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -7,3 +7,4 @@
|
||||||
* \namespace CBot
|
* \namespace CBot
|
||||||
* \brief CBot engine
|
* \brief CBot engine
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "CBot/CBotCStack.h"
|
#include "CBot/CBotCStack.h"
|
||||||
|
|
||||||
|
#include "CBot/CBotClass.h"
|
||||||
#include "CBot/CBotToken.h"
|
#include "CBot/CBotToken.h"
|
||||||
#include "CBot/CBotExternalCall.h"
|
#include "CBot/CBotExternalCall.h"
|
||||||
|
|
||||||
|
@ -30,107 +31,100 @@
|
||||||
namespace CBot
|
namespace CBot
|
||||||
{
|
{
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
struct CBotCStack::Data
|
||||||
CBotProgram* CBotCStack::m_prog = nullptr; // init the static variable
|
{
|
||||||
CBotError CBotCStack::m_error = CBotNoErr;
|
//! The program currently being compiled
|
||||||
int CBotCStack::m_end = 0;
|
CBotProgram* prog = nullptr;
|
||||||
CBotTypResult CBotCStack::m_retTyp = CBotTypResult(0);
|
//! The current error state of the compile stack
|
||||||
|
CBotError error = CBotNoErr;
|
||||||
|
int errEnd = 0;
|
||||||
|
//! The return type of the function currently being compiled
|
||||||
|
CBotTypResult retTyp = CBotTypResult(CBotTypVoid);
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
CBotCStack::CBotCStack(CBotCStack* ppapa)
|
CBotCStack::CBotCStack(CBotCStack* ppapa)
|
||||||
{
|
{
|
||||||
m_next = nullptr;
|
|
||||||
m_prev = ppapa;
|
m_prev = ppapa;
|
||||||
|
|
||||||
if (ppapa == nullptr)
|
if (ppapa == nullptr)
|
||||||
{
|
{
|
||||||
m_error = CBotNoErr;
|
m_data = new CBotCStack::Data;
|
||||||
m_start = 0;
|
m_errStart = 0;
|
||||||
m_end = 0;
|
|
||||||
m_bBlock = true;
|
m_bBlock = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_start = ppapa->m_start;
|
m_data = ppapa->m_data;
|
||||||
|
m_errStart = ppapa->m_errStart;
|
||||||
m_bBlock = false;
|
m_bBlock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_listVar = nullptr;
|
|
||||||
m_var = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotCStack::~CBotCStack()
|
CBotCStack::~CBotCStack()
|
||||||
{
|
{
|
||||||
if (m_next != nullptr) delete m_next;
|
if (m_prev == nullptr) delete m_data;
|
||||||
if (m_prev != nullptr) m_prev->m_next = nullptr; // removes chain
|
|
||||||
|
|
||||||
delete m_var;
|
|
||||||
delete m_listVar;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotCStack* CBotCStack::TokenStack(CBotToken* pToken, bool bBlock)
|
CBotCStack* CBotCStack::TokenStack(CBotToken* pToken, bool bBlock)
|
||||||
{
|
{
|
||||||
if (m_next != nullptr) return m_next; // include on an existing stack
|
if (m_next) return m_next.get(); // include on an existing stack
|
||||||
|
|
||||||
CBotCStack* p = new CBotCStack(this);
|
m_next.reset(new CBotCStack(this));
|
||||||
m_next = p; // channel element
|
m_next->m_bBlock = bBlock;
|
||||||
p->m_bBlock = bBlock;
|
|
||||||
|
|
||||||
if (pToken != nullptr) p->SetStartError(pToken->GetStart());
|
if (pToken != nullptr) m_next->SetStartError(pToken->GetStart());
|
||||||
|
|
||||||
return p;
|
return m_next.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBotCStack::DeleteNext()
|
||||||
|
{
|
||||||
|
m_next.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
CBotInstr* CBotCStack::Return(CBotInstr* inst, CBotCStack* pfils)
|
CBotInstr* CBotCStack::Return(CBotInstr* inst, CBotCStack* pfils)
|
||||||
{
|
{
|
||||||
if ( pfils == this ) return inst;
|
if ( pfils == this ) return inst;
|
||||||
|
|
||||||
if (m_var != nullptr) delete m_var; // value replaced?
|
m_var = std::move(pfils->m_var); // result transmitted
|
||||||
m_var = pfils->m_var; // result transmitted
|
|
||||||
pfils->m_var = nullptr; // not to destroy the variable
|
|
||||||
|
|
||||||
if (m_error)
|
if (m_data->error != CBotNoErr)
|
||||||
{
|
{
|
||||||
m_start = pfils->m_start; // retrieves the position of the error
|
m_errStart = pfils->m_errStart; // retrieves the position of the error
|
||||||
m_end = pfils->m_end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete pfils;
|
m_next.reset();
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotFunction* CBotCStack::ReturnFunc(CBotFunction* inst, CBotCStack* pfils)
|
CBotFunction* CBotCStack::ReturnFunc(CBotFunction* inst, CBotCStack* pfils)
|
||||||
{
|
{
|
||||||
if (m_var != nullptr) delete m_var; // value replaced?
|
m_var = std::move(pfils->m_var); // result transmitted
|
||||||
m_var = pfils->m_var; // result transmitted
|
|
||||||
pfils->m_var = nullptr; // not to destroy the variable
|
|
||||||
|
|
||||||
if (m_error)
|
if (m_data->error != CBotNoErr)
|
||||||
{
|
{
|
||||||
m_start = pfils->m_start; // retrieves the position of the error
|
m_errStart = pfils->m_errStart; // retrieves the position of the error
|
||||||
m_end = pfils->m_end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete pfils;
|
m_next.reset();
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotError CBotCStack::GetError(int& start, int& end)
|
CBotError CBotCStack::GetError(int& start, int& end)
|
||||||
{
|
{
|
||||||
start = m_start;
|
start = m_errStart;
|
||||||
end = m_end;
|
end = m_data->errEnd;
|
||||||
return m_error;
|
return m_data->error;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotError CBotCStack::GetError()
|
CBotError CBotCStack::GetError()
|
||||||
{
|
{
|
||||||
return m_error;
|
return m_data->error;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -170,18 +164,13 @@ void CBotCStack::SetType(CBotTypResult& type)
|
||||||
CBotVar* CBotCStack::FindVar(CBotToken* &pToken)
|
CBotVar* CBotCStack::FindVar(CBotToken* &pToken)
|
||||||
{
|
{
|
||||||
CBotCStack* p = this;
|
CBotCStack* p = this;
|
||||||
std::string name = pToken->GetString();
|
const auto& name = pToken->GetString();
|
||||||
|
|
||||||
while (p != nullptr)
|
while (p != nullptr)
|
||||||
{
|
{
|
||||||
CBotVar* pp = p->m_listVar;
|
if (p->m_bBlock) for (auto& var : p->m_listVar)
|
||||||
while ( pp != nullptr)
|
|
||||||
{
|
{
|
||||||
if (name == pp->GetName())
|
if (name == var->GetName()) return var.get();
|
||||||
{
|
|
||||||
return pp;
|
|
||||||
}
|
|
||||||
pp = pp->m_next;
|
|
||||||
}
|
}
|
||||||
p = p->m_prev;
|
p = p->m_prev;
|
||||||
}
|
}
|
||||||
|
@ -210,39 +199,39 @@ CBotVar* CBotCStack::CopyVar(CBotToken& Token)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotCStack::IsOk()
|
bool CBotCStack::IsOk()
|
||||||
{
|
{
|
||||||
return (m_error == 0);
|
return (m_data->error == CBotNoErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotCStack::SetStartError( int pos )
|
void CBotCStack::SetStartError( int pos )
|
||||||
{
|
{
|
||||||
if ( m_error != 0) return; // does not change existing error
|
if (m_data->error != CBotNoErr) return; // does not change existing error
|
||||||
m_start = pos;
|
m_errStart = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotCStack::SetError(CBotError n, int pos)
|
void CBotCStack::SetError(CBotError n, int pos)
|
||||||
{
|
{
|
||||||
if ( n!= 0 && m_error != 0) return; // does not change existing error
|
if (n != CBotNoErr && m_data->error != CBotNoErr) return; // does not change existing error
|
||||||
m_error = n;
|
m_data->error = n;
|
||||||
m_end = pos;
|
m_data->errEnd = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotCStack::SetError(CBotError n, CBotToken* p)
|
void CBotCStack::SetError(CBotError n, CBotToken* p)
|
||||||
{
|
{
|
||||||
if (m_error) return; // does not change existing error
|
if (m_data->error != CBotNoErr) return; // does not change existing error
|
||||||
m_error = n;
|
m_data->error = n;
|
||||||
m_start = p->GetStart();
|
m_errStart = p->GetStart();
|
||||||
m_end = p->GetEnd();
|
m_data->errEnd = p->GetEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotCStack::ResetError(CBotError n, int start, int end)
|
void CBotCStack::ResetError(CBotError n, int start, int end)
|
||||||
{
|
{
|
||||||
m_error = n;
|
m_data->error = n;
|
||||||
m_start = start;
|
m_errStart = start;
|
||||||
m_end = end;
|
m_data->errEnd = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -260,48 +249,47 @@ bool CBotCStack::NextToken(CBotToken* &p)
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotCStack::SetProgram(CBotProgram* p)
|
void CBotCStack::SetProgram(CBotProgram* p)
|
||||||
{
|
{
|
||||||
m_prog = p;
|
m_data->prog = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotProgram* CBotCStack::GetProgram()
|
CBotProgram* CBotCStack::GetProgram()
|
||||||
{
|
{
|
||||||
return m_prog;
|
return m_data->prog;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotCStack::SetRetType(CBotTypResult& type)
|
void CBotCStack::SetRetType(CBotTypResult& type)
|
||||||
{
|
{
|
||||||
m_retTyp = type;
|
m_data->retTyp = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotTypResult CBotCStack::GetRetType()
|
CBotTypResult CBotCStack::GetRetType()
|
||||||
{
|
{
|
||||||
return m_retTyp;
|
return m_data->retTyp;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotCStack::SetVar( CBotVar* var )
|
void CBotCStack::SetVar( CBotVar* var )
|
||||||
{
|
{
|
||||||
if (m_var) delete m_var; // replacement of a variable
|
m_var.reset(var);
|
||||||
m_var = var;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotCStack::SetCopyVar( CBotVar* var )
|
void CBotCStack::SetCopyVar( CBotVar* var )
|
||||||
{
|
{
|
||||||
if (m_var) delete m_var; // replacement of a variable
|
m_var.reset();
|
||||||
|
|
||||||
if ( var == nullptr ) return;
|
if ( var == nullptr ) return;
|
||||||
m_var = CBotVar::Create("", var->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC));
|
m_var.reset(CBotVar::Create("", var->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC)));
|
||||||
m_var->Copy( var );
|
m_var->Copy( var );
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotVar* CBotCStack::GetVar()
|
CBotVar* CBotCStack::GetVar()
|
||||||
{
|
{
|
||||||
return m_var;
|
return m_var.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -309,34 +297,70 @@ void CBotCStack::AddVar(CBotVar* pVar)
|
||||||
{
|
{
|
||||||
CBotCStack* p = this;
|
CBotCStack* p = this;
|
||||||
|
|
||||||
// returns to the father element
|
// find the level of the current block
|
||||||
while (p != nullptr && p->m_bBlock == 0) p = p->m_prev;
|
while (p != nullptr && p->m_bBlock == 0) p = p->m_prev;
|
||||||
|
|
||||||
if ( p == nullptr ) return;
|
if (p == nullptr || pVar == nullptr) return;
|
||||||
|
|
||||||
CBotVar** pp = &p->m_listVar;
|
p->m_listVar.emplace_back(pVar);
|
||||||
while ( *pp != nullptr ) pp = &(*pp)->m_next;
|
}
|
||||||
|
|
||||||
*pp = pVar; // added after
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void CBotCStack::CreateVarThis(CBotClass* pClass)
|
||||||
|
{
|
||||||
|
if ( pClass == nullptr ) return;
|
||||||
|
|
||||||
|
CBotVar* pThis = CBotVar::Create("this", CBotTypResult(CBotTypClass, pClass));
|
||||||
|
|
||||||
|
pThis->SetUniqNum(-2); // special ID for "this"
|
||||||
|
AddVar(pThis);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void CBotCStack::CreateVarSuper(CBotClass* pClass)
|
||||||
|
{
|
||||||
|
if ( pClass == nullptr ) return;
|
||||||
|
|
||||||
|
CBotVar* pSuper = CBotVar::Create("super", CBotTypResult(CBotTypClass, pClass));
|
||||||
|
|
||||||
|
pSuper->SetUniqNum(-3); // special ID for "super"
|
||||||
|
AddVar(pSuper);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void CBotCStack::CreateMemberVars(CBotClass* pClass, bool setDefined)
|
||||||
|
{
|
||||||
|
while (pClass != nullptr)
|
||||||
|
{
|
||||||
|
CBotVar* pv = pClass->GetVar();
|
||||||
|
while (pv != nullptr)
|
||||||
|
{
|
||||||
|
CBotVar* pcopy = CBotVar::Create(pv);
|
||||||
|
CBotVar::InitType initType = CBotVar::InitType::UNDEF;
|
||||||
|
if (setDefined || pv->IsStatic())
|
||||||
|
initType = CBotVar::InitType::DEF;
|
||||||
|
pcopy->SetInit(initType);
|
||||||
|
pcopy->SetUniqNum(pv->GetUniqNum());
|
||||||
|
pcopy->SetPrivate(pv->GetPrivate());
|
||||||
|
AddVar(pcopy);
|
||||||
|
pv = pv->GetNext();
|
||||||
|
}
|
||||||
|
pClass = pClass->GetParent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotCStack::CheckVarLocal(CBotToken* &pToken)
|
bool CBotCStack::CheckVarLocal(CBotToken* &pToken)
|
||||||
{
|
{
|
||||||
CBotCStack* p = this;
|
CBotCStack* p = this;
|
||||||
std::string name = pToken->GetString();
|
const auto& name = pToken->GetString();
|
||||||
|
|
||||||
while (p != nullptr)
|
// find the level of the current block
|
||||||
|
while (p != nullptr && p->m_bBlock == 0) p = p->m_prev;
|
||||||
|
|
||||||
|
if (p != nullptr) for (auto& var : p->m_listVar)
|
||||||
{
|
{
|
||||||
CBotVar* pp = p->m_listVar;
|
if (name == var->GetName()) return true;
|
||||||
while ( pp != nullptr)
|
|
||||||
{
|
|
||||||
if (name == pp->GetName())
|
|
||||||
return true;
|
|
||||||
pp = pp->m_next;
|
|
||||||
}
|
|
||||||
if ( p->m_bBlock ) return false;
|
|
||||||
p = p->m_prev;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -347,10 +371,10 @@ CBotTypResult CBotCStack::CompileCall(CBotToken* &p, CBotVar** ppVars, long& nId
|
||||||
nIdent = 0;
|
nIdent = 0;
|
||||||
CBotTypResult val(-1);
|
CBotTypResult val(-1);
|
||||||
|
|
||||||
val = m_prog->GetExternalCalls()->CompileCall(p, nullptr, ppVars, this);
|
val = GetProgram()->GetExternalCalls()->CompileCall(p, nullptr, ppVars, this);
|
||||||
if (val.GetType() < 0)
|
if (val.GetType() < 0)
|
||||||
{
|
{
|
||||||
val = m_prog->GetFunctions()->CompileCall(p->GetString(), ppVars, nIdent);
|
val = CBotFunction::CompileCall(p->GetString(), ppVars, nIdent, GetProgram());
|
||||||
if ( val.GetType() < 0 )
|
if ( val.GetType() < 0 )
|
||||||
{
|
{
|
||||||
// pVar = nullptr; // the error is not on a particular parameter
|
// pVar = nullptr; // the error is not on a particular parameter
|
||||||
|
@ -363,28 +387,32 @@ CBotTypResult CBotCStack::CompileCall(CBotToken* &p, CBotVar** ppVars, long& nId
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam)
|
bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam, const std::string& className)
|
||||||
{
|
{
|
||||||
std::string name = pToken->GetString();
|
const auto& name = pToken->GetString();
|
||||||
|
|
||||||
if ( m_prog->GetExternalCalls()->CheckCall(name) ) return true;
|
if ( GetProgram()->GetExternalCalls()->CheckCall(name) ) return true;
|
||||||
|
|
||||||
CBotFunction* pp = m_prog->GetFunctions();
|
for (CBotFunction* pp : GetProgram()->GetFunctions())
|
||||||
while ( pp != nullptr )
|
|
||||||
{
|
{
|
||||||
if ( pToken->GetString() == pp->GetName() )
|
if ( name == pp->GetName() )
|
||||||
{
|
{
|
||||||
|
// ignore methods for a different class
|
||||||
|
if ( className != pp->GetClassName() )
|
||||||
|
continue;
|
||||||
// are parameters exactly the same?
|
// are parameters exactly the same?
|
||||||
if ( pp->CheckParam( pParam ) )
|
if ( pp->CheckParam( pParam ) )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
pp = pp->Next();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (CBotFunction* pp : CBotFunction::m_publicFunctions)
|
for (CBotFunction* pp : CBotFunction::m_publicFunctions)
|
||||||
{
|
{
|
||||||
if ( pToken->GetString() == pp->GetName() )
|
if ( name == pp->GetName() )
|
||||||
{
|
{
|
||||||
|
// ignore methods for a different class
|
||||||
|
if ( className != pp->GetClassName() )
|
||||||
|
continue;
|
||||||
// are parameters exactly the same?
|
// are parameters exactly the same?
|
||||||
if ( pp->CheckParam( pParam ) )
|
if ( pp->CheckParam( pParam ) )
|
||||||
return true;
|
return true;
|
||||||
|
@ -394,4 +422,4 @@ bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace CBot
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -22,6 +22,9 @@
|
||||||
#include "CBot/CBotVar/CBotVar.h"
|
#include "CBot/CBotVar/CBotVar.h"
|
||||||
#include "CBot/CBotProgram.h"
|
#include "CBot/CBotProgram.h"
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace CBot
|
namespace CBot
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -100,6 +103,25 @@ public:
|
||||||
*/
|
*/
|
||||||
void AddVar(CBotVar* p);
|
void AddVar(CBotVar* p);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Create 'this' as a local variable.
|
||||||
|
* \param pClass The current class referred to by 'this'
|
||||||
|
*/
|
||||||
|
void CreateVarThis(CBotClass* pClass);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Create 'super' as a local variable.
|
||||||
|
* \param pClass The parent class referred to by 'super'
|
||||||
|
*/
|
||||||
|
void CreateVarSuper(CBotClass* pClass);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Create member variables of the current class as local variables.
|
||||||
|
* \param pClass The current class.
|
||||||
|
* \param setDefined Whether to mark the variables as initialized.
|
||||||
|
*/
|
||||||
|
void CreateMemberVars(CBotClass* pClass, bool setDefined);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief FindVar Finds a variable. Seeks a variable on the stack the token
|
* \brief FindVar Finds a variable. Seeks a variable on the stack the token
|
||||||
* may be a result of TokenTypVar (object of a class) or a pointer in the
|
* may be a result of TokenTypVar (object of a class) or a pointer in the
|
||||||
|
@ -138,6 +160,11 @@ public:
|
||||||
*/
|
*/
|
||||||
CBotCStack* TokenStack(CBotToken* pToken = nullptr, bool bBlock = false);
|
CBotCStack* TokenStack(CBotToken* pToken = nullptr, bool bBlock = false);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Deletes all subsequent stack frames created by TokenStack.
|
||||||
|
*/
|
||||||
|
void DeleteNext();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Return Transmits the result upper.
|
* \brief Return Transmits the result upper.
|
||||||
* \param p
|
* \param p
|
||||||
|
@ -235,11 +262,12 @@ public:
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief CheckCall Test if a procedure name is already defined somewhere.
|
* \brief CheckCall Test if a procedure name is already defined somewhere.
|
||||||
* \param pToken
|
* \param pToken Token representing the name of a function.
|
||||||
* \param pParam
|
* \param pParam List of parameters.
|
||||||
|
* \param className Name of a class when checking for methods.
|
||||||
* \return
|
* \return
|
||||||
*/
|
*/
|
||||||
bool CheckCall(CBotToken* &pToken, CBotDefParam* pParam);
|
bool CheckCall(CBotToken* &pToken, CBotDefParam* pParam, const std::string& className);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief NextToken
|
* \brief NextToken
|
||||||
|
@ -249,21 +277,20 @@ public:
|
||||||
bool NextToken(CBotToken* &p);
|
bool NextToken(CBotToken* &p);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CBotCStack* m_next;
|
std::unique_ptr<CBotCStack> m_next;
|
||||||
CBotCStack* m_prev;
|
CBotCStack* m_prev;
|
||||||
|
|
||||||
static CBotError m_error;
|
int m_errStart = 0;
|
||||||
static int m_end;
|
|
||||||
int m_start;
|
struct Data;
|
||||||
|
|
||||||
|
CBotCStack::Data* m_data;
|
||||||
|
|
||||||
//! Result of the operations.
|
//! Result of the operations.
|
||||||
CBotVar* m_var;
|
std::unique_ptr<CBotVar> m_var;
|
||||||
//! Is part of a block (variables are local to this block).
|
//! Is part of a block (variables are local to this block).
|
||||||
bool m_bBlock;
|
bool m_bBlock;
|
||||||
CBotVar* m_listVar;
|
std::list<std::unique_ptr<CBotVar>> m_listVar;
|
||||||
//! List of compiled functions.
|
|
||||||
static CBotProgram* m_prog;
|
|
||||||
static CBotTypResult m_retTyp;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CBot
|
} // namespace CBot
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -19,8 +19,10 @@
|
||||||
|
|
||||||
#include "CBot/CBotClass.h"
|
#include "CBot/CBotClass.h"
|
||||||
|
|
||||||
|
#include "CBot/CBotInstr/CBotInstrUtils.h"
|
||||||
#include "CBot/CBotInstr/CBotNew.h"
|
#include "CBot/CBotInstr/CBotNew.h"
|
||||||
#include "CBot/CBotInstr/CBotLeftExprVar.h"
|
#include "CBot/CBotInstr/CBotLeftExprVar.h"
|
||||||
|
#include "CBot/CBotInstr/CBotExprLitNull.h"
|
||||||
#include "CBot/CBotInstr/CBotTwoOpExpr.h"
|
#include "CBot/CBotInstr/CBotTwoOpExpr.h"
|
||||||
#include "CBot/CBotInstr/CBotFunction.h"
|
#include "CBot/CBotInstr/CBotFunction.h"
|
||||||
#include "CBot/CBotInstr/CBotExpression.h"
|
#include "CBot/CBotInstr/CBotExpression.h"
|
||||||
|
@ -32,9 +34,8 @@
|
||||||
#include "CBot/CBotExternalCall.h"
|
#include "CBot/CBotExternalCall.h"
|
||||||
#include "CBot/CBotStack.h"
|
#include "CBot/CBotStack.h"
|
||||||
#include "CBot/CBotCStack.h"
|
#include "CBot/CBotCStack.h"
|
||||||
|
#include "CBot/CBotDefParam.h"
|
||||||
#include "CBot/CBotUtils.h"
|
#include "CBot/CBotUtils.h"
|
||||||
#include "CBot/CBotFileUtils.h"
|
|
||||||
#include "CBot/CBotCallMethode.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
@ -52,8 +53,7 @@ CBotClass::CBotClass(const std::string& name,
|
||||||
m_parent = parent;
|
m_parent = parent;
|
||||||
m_name = name;
|
m_name = name;
|
||||||
m_pVar = nullptr;
|
m_pVar = nullptr;
|
||||||
m_pCalls = nullptr;
|
m_externalMethods = new CBotExternalCallList();
|
||||||
m_pMethod = nullptr;
|
|
||||||
m_rUpdate = nullptr;
|
m_rUpdate = nullptr;
|
||||||
m_IsDef = true;
|
m_IsDef = true;
|
||||||
m_bIntrinsic= bIntrinsic;
|
m_bIntrinsic= bIntrinsic;
|
||||||
|
@ -68,8 +68,7 @@ CBotClass::~CBotClass()
|
||||||
m_publicClasses.erase(this);
|
m_publicClasses.erase(this);
|
||||||
|
|
||||||
delete m_pVar;
|
delete m_pVar;
|
||||||
delete m_pCalls;
|
delete m_externalMethods;
|
||||||
delete m_pMethod;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -83,26 +82,24 @@ CBotClass* CBotClass::Create(const std::string& name,
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotClass::ClearPublic()
|
void CBotClass::ClearPublic()
|
||||||
{
|
{
|
||||||
m_publicClasses.clear();
|
while ( !m_publicClasses.empty() )
|
||||||
|
{
|
||||||
|
auto it = m_publicClasses.begin();
|
||||||
|
delete *it; // calling destructor removes the class from the list
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotClass::Purge()
|
void CBotClass::Purge()
|
||||||
{
|
{
|
||||||
if ( this == nullptr ) return;
|
|
||||||
|
|
||||||
delete m_pVar;
|
delete m_pVar;
|
||||||
m_pVar = nullptr;
|
m_pVar = nullptr;
|
||||||
delete m_pCalls;
|
m_externalMethods->Clear();
|
||||||
m_pCalls = nullptr;
|
for (CBotFunction* f : m_pMethod) delete f;
|
||||||
delete m_pMethod;
|
m_pMethod.clear();
|
||||||
m_pMethod = nullptr;
|
|
||||||
m_IsDef = false;
|
m_IsDef = false;
|
||||||
|
|
||||||
m_nbVar = m_parent == nullptr ? 0 : m_parent->m_nbVar;
|
m_nbVar = m_parent == nullptr ? 0 : m_parent->m_nbVar;
|
||||||
|
|
||||||
m_next->Purge();
|
|
||||||
m_next = nullptr; // no longer belongs to this chain
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -194,7 +191,7 @@ bool CBotClass::AddItem(CBotVar* pVar)
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
std::string CBotClass::GetName()
|
const std::string& CBotClass::GetName()
|
||||||
{
|
{
|
||||||
return m_name;
|
return m_name;
|
||||||
}
|
}
|
||||||
|
@ -202,7 +199,6 @@ std::string CBotClass::GetName()
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotClass* CBotClass::GetParent()
|
CBotClass* CBotClass::GetParent()
|
||||||
{
|
{
|
||||||
if ( this == nullptr ) return nullptr;
|
|
||||||
return m_parent;
|
return m_parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,6 +248,19 @@ CBotVar* CBotClass::GetItemRef(int nIdent)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool CBotClass::CheckVar(const std::string &name)
|
||||||
|
{
|
||||||
|
CBotVar* p = m_pVar;
|
||||||
|
|
||||||
|
while ( p != nullptr )
|
||||||
|
{
|
||||||
|
if ( p->GetName() == name ) return true;
|
||||||
|
p = p->GetNext();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotClass::IsIntrinsic()
|
bool CBotClass::IsIntrinsic()
|
||||||
{
|
{
|
||||||
|
@ -280,29 +289,7 @@ bool CBotClass::AddFunction(const std::string& name,
|
||||||
bool rExec(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user),
|
bool rExec(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user),
|
||||||
CBotTypResult rCompile(CBotVar* pThis, CBotVar*& pVar))
|
CBotTypResult rCompile(CBotVar* pThis, CBotVar*& pVar))
|
||||||
{
|
{
|
||||||
// stores pointers to the two functions
|
return m_externalMethods->AddFunction(name, std::unique_ptr<CBotExternalCall>(new CBotExternalCallClass(rExec, rCompile)));
|
||||||
CBotCallMethode* p = m_pCalls;
|
|
||||||
CBotCallMethode* pp = nullptr;
|
|
||||||
|
|
||||||
while ( p != nullptr )
|
|
||||||
{
|
|
||||||
if ( name == p->m_name )
|
|
||||||
{
|
|
||||||
if ( pp == nullptr ) m_pCalls = p->m_next;
|
|
||||||
else pp->m_next = p->m_next;
|
|
||||||
delete p;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pp = p;
|
|
||||||
p = p->m_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = new CBotCallMethode(name, rExec, rCompile);
|
|
||||||
|
|
||||||
if (m_pCalls == nullptr) m_pCalls = p;
|
|
||||||
else m_pCalls->AddNext(p); // added to the list
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -313,7 +300,7 @@ bool CBotClass::SetUpdateFunc(void rUpdate(CBotVar* thisVar, void* user))
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotTypResult CBotClass::CompileMethode(const std::string& name,
|
CBotTypResult CBotClass::CompileMethode(CBotToken* name,
|
||||||
CBotVar* pThis,
|
CBotVar* pThis,
|
||||||
CBotVar** ppParams,
|
CBotVar** ppParams,
|
||||||
CBotCStack* pStack,
|
CBotCStack* pStack,
|
||||||
|
@ -323,115 +310,123 @@ CBotTypResult CBotClass::CompileMethode(const std::string& name,
|
||||||
|
|
||||||
// find the methods declared by AddFunction
|
// find the methods declared by AddFunction
|
||||||
|
|
||||||
CBotTypResult r = m_pCalls->CompileCall(name, pThis, ppParams, pStack);
|
CBotTypResult r = m_externalMethods->CompileCall(name, pThis, ppParams, pStack);
|
||||||
if ( r.GetType() >= 0) return r;
|
if ( r.GetType() >= 0) return r;
|
||||||
|
|
||||||
// find the methods declared by user
|
// find the methods declared by user
|
||||||
|
|
||||||
r = m_pMethod->CompileCall(name, ppParams, nIdent);
|
r = CBotFunction::CompileMethodCall(name->GetString(), ppParams, nIdent, pStack, this);
|
||||||
if ( r.Eq(CBotErrUndefCall) && m_parent != nullptr )
|
if ( r.Eq(CBotErrUndefCall) && m_parent != nullptr )
|
||||||
return m_parent->m_pMethod->CompileCall(name, ppParams, nIdent);
|
return m_parent->CompileMethode(name, pThis, ppParams, pStack, nIdent);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotClass::ExecuteMethode(long& nIdent,
|
bool CBotClass::ExecuteMethode(long& nIdent,
|
||||||
const std::string& name,
|
|
||||||
CBotVar* pThis,
|
CBotVar* pThis,
|
||||||
CBotVar** ppParams,
|
CBotVar** ppParams,
|
||||||
CBotVar*& pResult,
|
CBotTypResult pResultType,
|
||||||
CBotStack*& pStack,
|
CBotStack*& pStack,
|
||||||
CBotToken* pToken)
|
CBotToken* pToken)
|
||||||
{
|
{
|
||||||
int ret = m_pCalls->DoCall(name, pThis, ppParams, pResult, pStack, pToken);
|
int ret = m_externalMethods->DoCall(pToken, pThis, ppParams, pStack, pResultType);
|
||||||
if (ret >= 0) return ret;
|
if (ret >= 0) return ret;
|
||||||
|
|
||||||
ret = m_pMethod->DoCall(nIdent, name, pThis, ppParams, pStack, pToken, this);
|
ret = CBotFunction::DoCall(nIdent, pToken->GetString(), pThis, ppParams, pStack, pToken, this);
|
||||||
if (ret >= 0) return ret;
|
if (ret >= 0) return ret;
|
||||||
|
|
||||||
if (m_parent != nullptr)
|
if (m_parent != nullptr)
|
||||||
{
|
{
|
||||||
ret = m_parent->m_pCalls->DoCall(name, pThis, ppParams, pResult, pStack, pToken);
|
ret = m_parent->ExecuteMethode(nIdent, pThis, ppParams, pResultType, pStack, pToken);
|
||||||
if (ret >= 0) return ret;
|
|
||||||
ret = m_parent->m_pMethod->DoCall(nIdent, name, pThis, ppParams, pStack, pToken, m_parent);
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotClass::RestoreMethode(long& nIdent,
|
void CBotClass::RestoreMethode(long& nIdent,
|
||||||
const std::string& name,
|
CBotToken* name,
|
||||||
CBotVar* pThis,
|
CBotVar* pThis,
|
||||||
CBotVar** ppParams,
|
CBotVar** ppParams,
|
||||||
CBotStack*& pStack)
|
CBotStack*& pStack)
|
||||||
{
|
{
|
||||||
m_pMethod->RestoreCall(nIdent, name, pThis, ppParams, pStack, this);
|
if (m_externalMethods->RestoreCall(name, pThis, ppParams, pStack))
|
||||||
|
return;
|
||||||
|
|
||||||
|
CBotClass* pClass = this;
|
||||||
|
while (pClass != nullptr)
|
||||||
|
{
|
||||||
|
bool ok = CBotFunction::RestoreCall(nIdent, name->GetString(), pThis, ppParams, pStack, pClass);
|
||||||
|
if (ok) return;
|
||||||
|
pClass = pClass->m_parent;
|
||||||
|
}
|
||||||
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotClass::SaveStaticState(FILE* pf)
|
bool CBotClass::SaveStaticState(std::ostream &ostr)
|
||||||
{
|
{
|
||||||
if (!WriteWord( pf, CBOTVERSION*2)) return false;
|
if (!WriteLong(ostr, CBOTVERSION*2)) return false;
|
||||||
|
|
||||||
// saves the state of static variables in classes
|
// saves the state of static variables in classes
|
||||||
for (CBotClass* p : m_publicClasses)
|
for (CBotClass* p : m_publicClasses)
|
||||||
{
|
{
|
||||||
if (!WriteWord( pf, 1 )) return false;
|
if (!WriteWord(ostr, 1)) return false;
|
||||||
// save the name of the class
|
// save the name of the class
|
||||||
if (!WriteString( pf, p->GetName() )) return false;
|
if (!WriteString(ostr, p->GetName())) return false;
|
||||||
|
|
||||||
CBotVar* pv = p->GetVar();
|
CBotVar* pv = p->GetVar();
|
||||||
while( pv != nullptr )
|
while( pv != nullptr )
|
||||||
{
|
{
|
||||||
if ( pv->IsStatic() )
|
if ( pv->IsStatic() )
|
||||||
{
|
{
|
||||||
if (!WriteWord( pf, 1 )) return false;
|
if (!WriteWord(ostr, 1)) return false;
|
||||||
if (!WriteString( pf, pv->GetName() )) return false;
|
if (!WriteString(ostr, pv->GetName())) return false;
|
||||||
|
|
||||||
if ( !pv->Save0State(pf) ) return false; // common header
|
if (!pv->Save0State(ostr)) return false; // common header
|
||||||
if ( !pv->Save1State(pf) ) return false; // saves as the child class
|
if (!pv->Save1State(ostr)) return false; // saves as the child class
|
||||||
if ( !WriteWord( pf, 0 ) ) return false;
|
if (!WriteWord(ostr, 0)) return false;
|
||||||
}
|
}
|
||||||
pv = pv->GetNext();
|
pv = pv->GetNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!WriteWord( pf, 0 )) return false;
|
if (!WriteWord(ostr, 0)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!WriteWord( pf, 0 )) return false;
|
if (!WriteWord(ostr, 0)) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotClass::RestoreStaticState(FILE* pf)
|
bool CBotClass::RestoreStaticState(std::istream &istr)
|
||||||
{
|
{
|
||||||
std::string ClassName, VarName;
|
std::string ClassName, VarName;
|
||||||
CBotClass* pClass;
|
CBotClass* pClass;
|
||||||
unsigned short w;
|
unsigned short w;
|
||||||
|
|
||||||
if (!ReadWord( pf, w )) return false;
|
long version;
|
||||||
if ( w != CBOTVERSION*2 ) return false;
|
if (!ReadLong(istr, version)) return false;
|
||||||
|
if (version != CBOTVERSION*2) return false;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (!ReadWord( pf, w )) return false;
|
if (!ReadWord(istr, w)) return false;
|
||||||
if ( w == 0 ) return true;
|
if ( w == 0 ) return true;
|
||||||
|
|
||||||
if (!ReadString( pf, ClassName )) return false;
|
if (!ReadString(istr, ClassName)) return false;
|
||||||
pClass = Find(ClassName);
|
pClass = Find(ClassName);
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (!ReadWord( pf, w )) return false;
|
if (!ReadWord(istr, w)) return false;
|
||||||
if ( w == 0 ) break;
|
if ( w == 0 ) break;
|
||||||
|
|
||||||
CBotVar* pVar = nullptr;
|
CBotVar* pVar = nullptr;
|
||||||
CBotVar* pv = nullptr;
|
CBotVar* pv = nullptr;
|
||||||
|
|
||||||
if (!ReadString( pf, VarName )) return false;
|
if (!ReadString(istr, VarName)) return false;
|
||||||
if ( pClass != nullptr ) pVar = pClass->GetItem(VarName);
|
if ( pClass != nullptr ) pVar = pClass->GetItem(VarName);
|
||||||
|
|
||||||
if (!CBotVar::RestoreState(pf, pv)) return false; // the temp variable
|
if (!CBotVar::RestoreState(istr, pv)) return false; // the temp variable
|
||||||
|
|
||||||
if ( pVar != nullptr ) pVar->Copy(pv);
|
if ( pVar != nullptr ) pVar->Copy(pv);
|
||||||
delete pv;
|
delete pv;
|
||||||
|
@ -447,8 +442,7 @@ bool CBotClass::CheckCall(CBotProgram* program, CBotDefParam* pParam, CBotToken*
|
||||||
|
|
||||||
if ( program->GetExternalCalls()->CheckCall(name) ) return true;
|
if ( program->GetExternalCalls()->CheckCall(name) ) return true;
|
||||||
|
|
||||||
CBotFunction* pp = m_pMethod;
|
for (CBotFunction* pp : m_pMethod)
|
||||||
while ( pp != nullptr )
|
|
||||||
{
|
{
|
||||||
if ( pToken->GetString() == pp->GetName() )
|
if ( pToken->GetString() == pp->GetName() )
|
||||||
{
|
{
|
||||||
|
@ -456,7 +450,6 @@ bool CBotClass::CheckCall(CBotProgram* program, CBotDefParam* pParam, CBotToken*
|
||||||
if ( pp->CheckParam( pParam ) )
|
if ( pp->CheckParam( pParam ) )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
pp = pp->Next();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -475,49 +468,85 @@ CBotClass* CBotClass::Compile1(CBotToken* &p, CBotCStack* pStack)
|
||||||
|
|
||||||
std::string name = p->GetString();
|
std::string name = p->GetString();
|
||||||
|
|
||||||
CBotClass* pOld = CBotClass::Find(name);
|
|
||||||
if ( pOld != nullptr && pOld->m_IsDef )
|
|
||||||
{
|
|
||||||
pStack->SetError( CBotErrRedefClass, p );
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// a name of the class is there?
|
// a name of the class is there?
|
||||||
if (IsOfType(p, TokenTypVar))
|
if (IsOfType(p, TokenTypVar))
|
||||||
{
|
{
|
||||||
|
CBotClass* pOld = CBotClass::Find(name);
|
||||||
|
if ((pOld != nullptr && pOld->m_IsDef) || /* public class exists in different program */
|
||||||
|
pStack->GetProgram()->ClassExists(name)) /* class exists in this program */
|
||||||
|
{
|
||||||
|
pStack->SetError(CBotErrRedefClass, p->GetPrev());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
CBotClass* pPapa = nullptr;
|
CBotClass* pPapa = nullptr;
|
||||||
if ( IsOfType( p, ID_EXTENDS ) )
|
if ( IsOfType( p, ID_EXTENDS ) )
|
||||||
{
|
{
|
||||||
std::string name = p->GetString();
|
std::string name = p->GetString();
|
||||||
pPapa = CBotClass::Find(name);
|
pPapa = CBotClass::Find(name);
|
||||||
|
CBotToken* pp = p;
|
||||||
|
|
||||||
if (!IsOfType(p, TokenTypVar) || pPapa == nullptr )
|
if (!IsOfType(p, TokenTypVar) || pPapa == nullptr )
|
||||||
{
|
{
|
||||||
pStack->SetError( CBotErrNotClass, p );
|
pStack->SetError(CBotErrNoClassName, pp);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CBotClass* classe = (pOld == nullptr) ? new CBotClass(name, pPapa) : pOld;
|
CBotClass* classe = (pOld == nullptr) ? new CBotClass(name, pPapa) : pOld;
|
||||||
classe->Purge(); // empty the old definitions // TODO: Doesn't this remove all classes of the current program?
|
classe->Purge(); // empty the old definitions
|
||||||
classe->m_IsDef = false; // current definition
|
classe->m_IsDef = false; // current definition
|
||||||
|
|
||||||
|
classe->m_pOpenblk = p;
|
||||||
|
|
||||||
if ( !IsOfType( p, ID_OPBLK) )
|
if ( !IsOfType( p, ID_OPBLK) )
|
||||||
{
|
{
|
||||||
pStack->SetError(CBotErrOpenBlock, p);
|
pStack->SetError(CBotErrOpenBlock, p);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ( pStack->IsOk() && !IsOfType( p, ID_CLBLK ) )
|
int level = 1;
|
||||||
|
while (level > 0 && p != nullptr)
|
||||||
{
|
{
|
||||||
classe->CompileDefItem(p, pStack, false);
|
int type = p->GetType();
|
||||||
|
p = p->GetNext();
|
||||||
|
if (type == ID_OPBLK) level++;
|
||||||
|
if (type == ID_CLBLK) level--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (level > 0) pStack->SetError(CBotErrCloseBlock, classe->m_pOpenblk);
|
||||||
|
|
||||||
if (pStack->IsOk()) return classe;
|
if (pStack->IsOk()) return classe;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
pStack->SetError(CBotErrNoClassName, p);
|
||||||
|
|
||||||
pStack->SetError(CBotErrNoTerminator, p);
|
pStack->SetError(CBotErrNoTerminator, p);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void CBotClass::DefineClasses(std::list<CBotClass*> pClassList, CBotCStack* pStack)
|
||||||
|
{
|
||||||
|
for (CBotClass* pClass : pClassList)
|
||||||
|
{
|
||||||
|
CBotClass* pParent = pClass->m_parent;
|
||||||
|
pClass->m_nbVar = (pParent == nullptr) ? 0 : pParent->m_nbVar;
|
||||||
|
CBotToken* p = pClass->m_pOpenblk->GetNext();
|
||||||
|
|
||||||
|
while (pStack->IsOk() && !IsOfType(p, ID_CLBLK))
|
||||||
|
{
|
||||||
|
pClass->CompileDefItem(p, pStack, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pStack->IsOk()) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::list<CBotFunction*>& CBotClass::GetFunctions() const
|
||||||
|
{
|
||||||
|
return m_pMethod;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
||||||
{
|
{
|
||||||
|
@ -549,6 +578,9 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
||||||
|
|
||||||
while (pStack->IsOk())
|
while (pStack->IsOk())
|
||||||
{
|
{
|
||||||
|
CBotTypResult type2 = CBotTypResult(type); // reset type after comma
|
||||||
|
CBotToken* varToken = p;
|
||||||
|
|
||||||
std::string pp = p->GetString();
|
std::string pp = p->GetString();
|
||||||
if ( IsOfType(p, ID_NOT) )
|
if ( IsOfType(p, ID_NOT) )
|
||||||
{
|
{
|
||||||
|
@ -557,115 +589,44 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
||||||
|
|
||||||
if (IsOfType(p, TokenTypVar))
|
if (IsOfType(p, TokenTypVar))
|
||||||
{
|
{
|
||||||
CBotInstr* limites = nullptr;
|
|
||||||
while ( IsOfType( p, ID_OPBRK ) ) // a table?
|
|
||||||
{
|
|
||||||
CBotInstr* i = nullptr;
|
|
||||||
|
|
||||||
if ( p->GetType() != ID_CLBRK )
|
|
||||||
i = CBotExpression::Compile( p, pStack ); // expression for the value
|
|
||||||
else
|
|
||||||
i = new CBotEmpty(); // special if not a formula
|
|
||||||
|
|
||||||
type = CBotTypResult(CBotTypArrayPointer, type);
|
|
||||||
|
|
||||||
if (!pStack->IsOk() || !IsOfType( p, ID_CLBRK ) )
|
|
||||||
{
|
|
||||||
pStack->SetError(CBotErrCloseIndex, p->GetStart());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* CBotVar* pv = pStack->GetVar();
|
|
||||||
if ( pv->GetType()>= CBotTypBoolean )
|
|
||||||
{
|
|
||||||
pStack->SetError(CBotErrBadType1, p->GetStart());
|
|
||||||
return false;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (limites == nullptr) limites = i;
|
|
||||||
else limites->AddNext3(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( p->GetType() == ID_OPENPAR )
|
if ( p->GetType() == ID_OPENPAR )
|
||||||
{
|
{
|
||||||
if ( !bSecond )
|
if ( !bSecond )
|
||||||
{
|
{
|
||||||
p = pBase;
|
p = pBase;
|
||||||
CBotFunction* f =
|
CBotFunction* f = CBotFunction::Compile1(p, pStack, this);
|
||||||
CBotFunction::Compile1(p, pStack, this);
|
|
||||||
|
|
||||||
if ( f == nullptr ) return false;
|
if ( f == nullptr ) return false;
|
||||||
|
|
||||||
if (m_pMethod == nullptr) m_pMethod = f;
|
m_pMethod.push_back(f);
|
||||||
else m_pMethod->AddNext(f);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// return a method precompiled in pass 1
|
// return a method precompiled in pass 1
|
||||||
CBotFunction* pf = m_pMethod;
|
CBotCStack* pStk = pStack->TokenStack(nullptr, true);
|
||||||
CBotFunction* prev = nullptr;
|
CBotDefParam* params = CBotDefParam::Compile(p, pStk );
|
||||||
while ( pf != nullptr )
|
pStack->DeleteNext();
|
||||||
|
auto pfIter = std::find_if(m_pMethod.begin(), m_pMethod.end(), [&pp, ¶ms](CBotFunction* x)
|
||||||
{
|
{
|
||||||
if (pf->GetName() == pp) break;
|
return x->GetName() == pp && x->CheckParam( params );
|
||||||
prev = pf;
|
});
|
||||||
pf = pf->Next();
|
assert(pfIter != m_pMethod.end());
|
||||||
}
|
CBotFunction* pf = *pfIter;
|
||||||
|
delete params;
|
||||||
|
|
||||||
bool bConstructor = (pp == GetName());
|
|
||||||
CBotCStack* pile = pStack->TokenStack(nullptr, true);
|
CBotCStack* pile = pStack->TokenStack(nullptr, true);
|
||||||
|
|
||||||
// make "this" known
|
|
||||||
CBotToken TokenThis(std::string("this"), std::string());
|
|
||||||
CBotVar* pThis = CBotVar::Create(TokenThis, CBotTypResult( CBotTypClass, this ) );
|
|
||||||
pThis->SetUniqNum(-2);
|
|
||||||
pile->AddVar(pThis);
|
|
||||||
|
|
||||||
if (m_parent)
|
|
||||||
{
|
|
||||||
// makes "super" known
|
|
||||||
CBotToken TokenSuper(std::string("super"), std::string());
|
|
||||||
CBotVar* pThis = CBotVar::Create(TokenSuper, CBotTypResult(CBotTypClass, m_parent) );
|
|
||||||
pThis->SetUniqNum(-3);
|
|
||||||
pile->AddVar(pThis);
|
|
||||||
}
|
|
||||||
|
|
||||||
// int num = 1;
|
|
||||||
CBotClass* my = this;
|
|
||||||
while (my != nullptr)
|
|
||||||
{
|
|
||||||
// places a copy of variables of a class (this) on a stack
|
|
||||||
CBotVar* pv = my->m_pVar;
|
|
||||||
while (pv != nullptr)
|
|
||||||
{
|
|
||||||
CBotVar* pcopy = CBotVar::Create(pv);
|
|
||||||
CBotVar::InitType initType = CBotVar::InitType::UNDEF;
|
|
||||||
if (!bConstructor || pv->IsStatic())
|
|
||||||
initType = CBotVar::InitType::DEF;
|
|
||||||
pcopy->SetInit(initType);
|
|
||||||
pcopy->SetUniqNum(pv->GetUniqNum());
|
|
||||||
pile->AddVar(pcopy);
|
|
||||||
pv = pv->GetNext();
|
|
||||||
}
|
|
||||||
my = my->m_parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// compiles a method
|
// compiles a method
|
||||||
p = pBase;
|
p = pBase;
|
||||||
CBotFunction* f =
|
CBotFunction* f =
|
||||||
CBotFunction::Compile(p, pile, nullptr/*, false*/);
|
CBotFunction::Compile(p, pile, pf/*, false*/);
|
||||||
|
|
||||||
if ( f != nullptr )
|
if ( f != nullptr )
|
||||||
{
|
{
|
||||||
f->m_pProg = pStack->GetProgram();
|
f->m_pProg = pStack->GetProgram();
|
||||||
f->m_bSynchro = bSynchro;
|
f->m_bSynchro = bSynchro;
|
||||||
// replaces the element in the chain
|
|
||||||
f->m_next = pf->m_next;
|
|
||||||
pf->m_next = nullptr;
|
|
||||||
delete pf;
|
|
||||||
if (prev == nullptr) m_pMethod = f;
|
|
||||||
else prev->m_next = f;
|
|
||||||
}
|
}
|
||||||
pStack->Return(nullptr, pile);
|
pStack->DeleteNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
return pStack->IsOk();
|
return pStack->IsOk();
|
||||||
|
@ -678,25 +639,89 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pp[0] == '~' || pp == GetName()) // bad variable name
|
||||||
|
{
|
||||||
|
pStack->SetError(CBotErrNoVar, varToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bSecond && CheckVar(pp)) // variable already exists
|
||||||
|
{
|
||||||
|
pStack->SetError(CBotErrRedefVar, varToken);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CBotInstr* limites = nullptr;
|
||||||
|
while ( IsOfType( p, ID_OPBRK ) ) // an array
|
||||||
|
{
|
||||||
|
CBotInstr* i = nullptr;
|
||||||
|
pStack->SetStartError( p->GetStart() );
|
||||||
|
if ( p->GetType() != ID_CLBRK )
|
||||||
|
{
|
||||||
|
i = CBotExpression::Compile( p, pStack ); // expression for the value
|
||||||
|
if (i == nullptr || pStack->GetType() != CBotTypInt) // must be a number
|
||||||
|
{
|
||||||
|
pStack->SetError(CBotErrBadIndex, p->GetStart());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
i = new CBotEmpty(); // special if not a formula
|
||||||
|
|
||||||
|
type2 = CBotTypResult(CBotTypArrayPointer, type2);
|
||||||
|
|
||||||
|
if (limites == nullptr) limites = i;
|
||||||
|
else limites->AddNext3(i);
|
||||||
|
|
||||||
|
if (pStack->IsOk() && IsOfType(p, ID_CLBRK)) continue;
|
||||||
|
pStack->SetError(CBotErrCloseIndex, p->GetStart());
|
||||||
|
delete limites;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
CBotInstr* i = nullptr;
|
CBotInstr* i = nullptr;
|
||||||
if ( IsOfType(p, ID_ASS ) )
|
if ( IsOfType(p, ID_ASS ) )
|
||||||
{
|
{
|
||||||
if ( type.Eq(CBotTypArrayPointer) )
|
pStack->SetStartError(p->GetStart());
|
||||||
|
if ( IsOfType(p, ID_SEP) )
|
||||||
{
|
{
|
||||||
i = CBotListArray::Compile(p, pStack, type.GetTypElem());
|
pStack->SetError(CBotErrNoExpression, p->GetStart());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( type2.Eq(CBotTypArrayPointer) )
|
||||||
|
{
|
||||||
|
if ( nullptr == (i = CBotListArray::Compile(p, pStack, type2.GetTypElem())) )
|
||||||
|
{
|
||||||
|
if (pStack->IsOk())
|
||||||
|
{
|
||||||
|
i = CBotTwoOpExpr::Compile(p, pStack);
|
||||||
|
if (i == nullptr || !pStack->GetTypResult().Compare(type2))
|
||||||
|
{
|
||||||
|
pStack->SetError(CBotErrBadType1, p->GetStart());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// it has an assignmet to calculate
|
// it has an assignmet to calculate
|
||||||
i = CBotTwoOpExpr::Compile(p, pStack);
|
i = CBotTwoOpExpr::Compile(p, pStack);
|
||||||
|
|
||||||
|
if ( !(type.Eq(CBotTypPointer) && pStack->GetTypResult().Eq(CBotTypNullPointer)) &&
|
||||||
|
!TypesCompatibles( type2, pStack->GetTypResult()) )
|
||||||
|
{
|
||||||
|
pStack->SetError(CBotErrBadType1, p->GetStart());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ( !pStack->IsOk() ) return false;
|
if ( !pStack->IsOk() ) return false;
|
||||||
}
|
}
|
||||||
|
else if ( type2.Eq(CBotTypArrayPointer) ) i = new CBotExprLitNull();
|
||||||
|
|
||||||
|
|
||||||
if ( !bSecond )
|
if ( !bSecond )
|
||||||
{
|
{
|
||||||
CBotVar* pv = CBotVar::Create(pp, type);
|
CBotVar* pv = CBotVar::Create(pp, type2);
|
||||||
pv -> SetStatic( bStatic );
|
pv -> SetStatic( bStatic );
|
||||||
pv -> SetPrivate( mProtect );
|
pv -> SetPrivate( mProtect );
|
||||||
|
|
||||||
|
@ -709,13 +734,23 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond)
|
||||||
if ( pv->IsStatic() && pv->m_InitExpr != nullptr )
|
if ( pv->IsStatic() && pv->m_InitExpr != nullptr )
|
||||||
{
|
{
|
||||||
CBotStack* pile = CBotStack::AllocateStack(); // independent stack
|
CBotStack* pile = CBotStack::AllocateStack(); // independent stack
|
||||||
|
if ( type2.Eq(CBotTypArrayPointer) )
|
||||||
|
{
|
||||||
|
while(pile->IsOk() && !pv->m_InitExpr->Execute(pile, pv));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
while(pile->IsOk() && !pv->m_InitExpr->Execute(pile)); // evaluates the expression without timer
|
while(pile->IsOk() && !pv->m_InitExpr->Execute(pile)); // evaluates the expression without timer
|
||||||
pv->SetVal( pile->GetVar() ) ;
|
pv->SetVal( pile->GetVar() ) ;
|
||||||
|
}
|
||||||
pile->Delete();
|
pile->Delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
delete i;
|
delete i;
|
||||||
|
delete limites;
|
||||||
|
}
|
||||||
|
|
||||||
if ( IsOfType(p, ID_COMMA) ) continue;
|
if ( IsOfType(p, ID_COMMA) ) continue;
|
||||||
if ( IsOfType(p, ID_SEP) ) break;
|
if ( IsOfType(p, ID_SEP) ) break;
|
||||||
|
@ -744,10 +779,11 @@ CBotClass* CBotClass::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
// TODO: Not sure how correct is that - I have no idea how the precompilation (Compile1 method) works ~krzys_h
|
// TODO: Not sure how correct is that - I have no idea how the precompilation (Compile1 method) works ~krzys_h
|
||||||
std::string name = p->GetString();
|
std::string name = p->GetString();
|
||||||
CBotClass* pPapa = CBotClass::Find(name);
|
CBotClass* pPapa = CBotClass::Find(name);
|
||||||
|
CBotToken* pp = p;
|
||||||
|
|
||||||
if (!IsOfType(p, TokenTypVar) || pPapa == nullptr)
|
if (!IsOfType(p, TokenTypVar) || pPapa == nullptr)
|
||||||
{
|
{
|
||||||
pStack->SetError( CBotErrNotClass, p );
|
pStack->SetError(CBotErrNoClassName, pp);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
pOld->m_parent = pPapa;
|
pOld->m_parent = pPapa;
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
namespace CBot
|
namespace CBot
|
||||||
{
|
{
|
||||||
|
@ -37,6 +38,7 @@ class CBotStack;
|
||||||
class CBotDefParam;
|
class CBotDefParam;
|
||||||
class CBotToken;
|
class CBotToken;
|
||||||
class CBotCStack;
|
class CBotCStack;
|
||||||
|
class CBotExternalCallList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A CBot class definition
|
* \brief A CBot class definition
|
||||||
|
@ -102,7 +104,7 @@ class CBotCStack;
|
||||||
* float y = var->GetValFloat();
|
* float y = var->GetValFloat();
|
||||||
* \endcode
|
* \endcode
|
||||||
*/
|
*/
|
||||||
class CBotClass : public CBotLinkedList<CBotClass>
|
class CBotClass
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
|
@ -133,13 +135,8 @@ public:
|
||||||
bool intrinsic = false);
|
bool intrinsic = false);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief AddFunction This call allows to add as external new method
|
* \brief Add a function that can be called from CBot
|
||||||
* used by the objects of this class. See (**) at end of this file for
|
* \see CBotProgram::AddFunction
|
||||||
* more details.
|
|
||||||
* \param name
|
|
||||||
* \param rExec
|
|
||||||
* \param rCompile
|
|
||||||
* \return
|
|
||||||
*/
|
*/
|
||||||
bool AddFunction(const std::string& name,
|
bool AddFunction(const std::string& name,
|
||||||
bool rExec(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user),
|
bool rExec(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user),
|
||||||
|
@ -176,7 +173,7 @@ public:
|
||||||
* \brief GetName Gives the name of the class.
|
* \brief GetName Gives the name of the class.
|
||||||
* \return
|
* \return
|
||||||
*/
|
*/
|
||||||
std::string GetName();
|
const std::string& GetName();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief GetParent Gives the parent class (or nullptr).
|
* \brief GetParent Gives the parent class (or nullptr).
|
||||||
|
@ -224,6 +221,13 @@ public:
|
||||||
*/
|
*/
|
||||||
CBotVar* GetItemRef(int nIdent);
|
CBotVar* GetItemRef(int nIdent);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Check whether a variable is already defined in a class
|
||||||
|
* \param name Name of the variable
|
||||||
|
* \return True if a variable is defined in the class
|
||||||
|
*/
|
||||||
|
bool CheckVar(const std::string &name);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief CompileMethode Compiles a method associated with an instance of
|
* \brief CompileMethode Compiles a method associated with an instance of
|
||||||
* class the method can be declared by the user or AddFunction.
|
* class the method can be declared by the user or AddFunction.
|
||||||
|
@ -234,7 +238,7 @@ public:
|
||||||
* \param nIdent
|
* \param nIdent
|
||||||
* \return
|
* \return
|
||||||
*/
|
*/
|
||||||
CBotTypResult CompileMethode(const std::string& name,
|
CBotTypResult CompileMethode(CBotToken* name,
|
||||||
CBotVar* pThis,
|
CBotVar* pThis,
|
||||||
CBotVar** ppParams,
|
CBotVar** ppParams,
|
||||||
CBotCStack* pStack,
|
CBotCStack* pStack,
|
||||||
|
@ -246,18 +250,13 @@ public:
|
||||||
* \param name
|
* \param name
|
||||||
* \param pThis
|
* \param pThis
|
||||||
* \param ppParams
|
* \param ppParams
|
||||||
* \param pResult
|
* \param pResultType
|
||||||
* \param pStack
|
* \param pStack
|
||||||
* \param pToken
|
* \param pToken
|
||||||
* \return
|
* \return
|
||||||
*/
|
*/
|
||||||
bool ExecuteMethode(long& nIdent,
|
bool ExecuteMethode(long &nIdent, CBotVar* pThis, CBotVar** ppParams, CBotTypResult pResultType,
|
||||||
const std::string& name,
|
CBotStack*&pStack, CBotToken* pToken);
|
||||||
CBotVar* pThis,
|
|
||||||
CBotVar** ppParams,
|
|
||||||
CBotVar*& pResult,
|
|
||||||
CBotStack*& pStack,
|
|
||||||
CBotToken* pToken);
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief RestoreMethode Restored the execution stack.
|
* \brief RestoreMethode Restored the execution stack.
|
||||||
|
@ -268,7 +267,7 @@ public:
|
||||||
* \param pStack
|
* \param pStack
|
||||||
*/
|
*/
|
||||||
void RestoreMethode(long &nIdent,
|
void RestoreMethode(long &nIdent,
|
||||||
const std::string& name,
|
CBotToken* name,
|
||||||
CBotVar* pThis,
|
CBotVar* pThis,
|
||||||
CBotVar** ppParams,
|
CBotVar** ppParams,
|
||||||
CBotStack*&pStack);
|
CBotStack*&pStack);
|
||||||
|
@ -283,14 +282,33 @@ public:
|
||||||
CBotCStack* pStack);
|
CBotCStack* pStack);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Compile1
|
* \brief Pre-compile a new class
|
||||||
* \param p
|
* \param p[in, out] Pointer to first token of the class, will be updated to point to first token after the class definition
|
||||||
* \param pStack
|
* \param pStack Compile stack
|
||||||
* \return
|
*
|
||||||
|
* This function is used to find the beginning and end of class definition.
|
||||||
|
*
|
||||||
|
* If any errors in the code are detected, this function will set the error on compile stack and return nullptr.
|
||||||
|
*
|
||||||
|
* \return Precompiled class, or nullptr in case of error
|
||||||
*/
|
*/
|
||||||
static CBotClass* Compile1(CBotToken* &p,
|
static CBotClass* Compile1(CBotToken* &p,
|
||||||
CBotCStack* pStack);
|
CBotCStack* pStack);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief DefineClasses Calls CompileDefItem for each class in a list
|
||||||
|
* of classes, defining fields and pre-compiling methods.
|
||||||
|
* \param pClassList List of classes
|
||||||
|
* \param pStack
|
||||||
|
*/
|
||||||
|
static void DefineClasses(std::list<CBotClass*> pClassList, CBotCStack* pStack);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Get the list of user-defined methods in this class.
|
||||||
|
* \return List of methods, can be empty.
|
||||||
|
*/
|
||||||
|
const std::list<CBotFunction*>& GetFunctions() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief CompileDefItem
|
* \brief CompileDefItem
|
||||||
* \param p
|
* \param p
|
||||||
|
@ -319,18 +337,18 @@ public:
|
||||||
static void ClearPublic();
|
static void ClearPublic();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief SaveStaticState
|
* \brief Save all static variables from each public class
|
||||||
* \param pf
|
* \param ostr Output stream
|
||||||
* \return
|
* \return true on success
|
||||||
*/
|
*/
|
||||||
static bool SaveStaticState(FILE* pf);
|
static bool SaveStaticState(std::ostream &ostr);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief RestoreStaticState
|
* \brief Restore all static variables in each public class
|
||||||
* \param pf
|
* \param istr Input stream
|
||||||
* \return
|
* \return true on success
|
||||||
*/
|
*/
|
||||||
static bool RestoreStaticState(FILE* pf);
|
static bool RestoreStaticState(std::istream &istr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Request a lock on this class (for "synchronized" keyword)
|
* \brief Request a lock on this class (for "synchronized" keyword)
|
||||||
|
@ -380,11 +398,13 @@ private:
|
||||||
//! Linked list of all class fields
|
//! Linked list of all class fields
|
||||||
CBotVar* m_pVar;
|
CBotVar* m_pVar;
|
||||||
//! Linked list of all class external calls
|
//! Linked list of all class external calls
|
||||||
CBotCallMethode* m_pCalls;
|
CBotExternalCallList* m_externalMethods;
|
||||||
//! Linked list of all class methods
|
//! List of all class methods
|
||||||
CBotFunction* m_pMethod;
|
std::list<CBotFunction*> m_pMethod{};
|
||||||
void (*m_rUpdate)(CBotVar* thisVar, void* user);
|
void (*m_rUpdate)(CBotVar* thisVar, void* user);
|
||||||
|
|
||||||
|
CBotToken* m_pOpenblk;
|
||||||
|
|
||||||
//! How many times the program currently holding the lock called Lock()
|
//! How many times the program currently holding the lock called Lock()
|
||||||
int m_lockCurrentCount = 0;
|
int m_lockCurrentCount = 0;
|
||||||
//! Programs waiting for lock. m_lockProg[0] is the program currently holding the lock, if any
|
//! Programs waiting for lock. m_lockProg[0] is the program currently holding the lock, if any
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -23,10 +23,11 @@
|
||||||
#include "CBot/CBotInstr/CBotFunction.h"
|
#include "CBot/CBotInstr/CBotFunction.h"
|
||||||
#include "CBot/CBotInstr/CBotInstrCall.h"
|
#include "CBot/CBotInstr/CBotInstrCall.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <functional>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
|
||||||
|
|
||||||
namespace CBot
|
namespace CBot
|
||||||
{
|
{
|
||||||
|
@ -36,12 +37,10 @@ void CBotDebug::DumpCompiledProgram(CBotProgram* program)
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "digraph {" << std::endl;
|
ss << "digraph {" << std::endl;
|
||||||
|
|
||||||
CBotFunction* func = program->GetFunctions();
|
|
||||||
std::map<long, CBotFunction*> funcIdMap;
|
std::map<long, CBotFunction*> funcIdMap;
|
||||||
while (func != nullptr)
|
for (CBotFunction* func : program->GetFunctions())
|
||||||
{
|
{
|
||||||
funcIdMap[func->m_nFuncIdent] = func;
|
funcIdMap[func->m_nFuncIdent] = func;
|
||||||
func = func->Next();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<CBotInstr*> finished;
|
std::set<CBotInstr*> finished;
|
||||||
|
@ -54,22 +53,34 @@ void CBotDebug::DumpCompiledProgram(CBotProgram* program)
|
||||||
instructions[ptr] = instructionsNextId++;
|
instructions[ptr] = instructionsNextId++;
|
||||||
}
|
}
|
||||||
|
|
||||||
char buffer[20];
|
std::array<char, 20> buffer;
|
||||||
sprintf(buffer, "instr%d", instructions[ptr]);
|
snprintf(buffer.data(), buffer.size(), "instr%d", instructions[ptr]);
|
||||||
return std::string(buffer);
|
return std::string(buffer.data());
|
||||||
};
|
};
|
||||||
std::function<void(CBotInstr*)> DumpInstr = [&](CBotInstr* instr)
|
std::function<void(CBotInstr*)> DumpInstr = [&](CBotInstr* instr)
|
||||||
{
|
{
|
||||||
if (finished.find(instr) != finished.end()) return;
|
if (finished.find(instr) != finished.end()) return;
|
||||||
finished.insert(instr);
|
finished.insert(instr);
|
||||||
|
|
||||||
std::string label = "<b>"+instr->GetDebugName()+"</b>\n";
|
auto replaceAll = [](std::string& text, const std::string& from, const std::string& to)
|
||||||
|
{
|
||||||
|
std::size_t pos = 0;
|
||||||
|
|
||||||
|
while ((pos = text.find(from, pos)) != std::string::npos)
|
||||||
|
{
|
||||||
|
text.replace(pos, from.length(), to);
|
||||||
|
pos += to.length();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
std::string data = instr->GetDebugData();
|
std::string data = instr->GetDebugData();
|
||||||
boost::algorithm::replace_all(data, "&", "&");
|
replaceAll(data, "&", "&");
|
||||||
boost::algorithm::replace_all(data, "<", "<");
|
replaceAll(data, "<", "<");
|
||||||
boost::algorithm::replace_all(data, ">", ">");
|
replaceAll(data, ">", ">");
|
||||||
|
|
||||||
|
std::string label = "<b>"+instr->GetDebugName()+"</b>\n";
|
||||||
label += data;
|
label += data;
|
||||||
boost::algorithm::replace_all(label, "\n", "<br/>");
|
replaceAll(label, "\n", "<br/>");
|
||||||
|
|
||||||
std::string additional = "";
|
std::string additional = "";
|
||||||
if (instr->GetDebugName() == "CBotFunction")
|
if (instr->GetDebugName() == "CBotFunction")
|
||||||
|
@ -111,9 +122,8 @@ void CBotDebug::DumpCompiledProgram(CBotProgram* program)
|
||||||
{
|
{
|
||||||
DumpInstr(program->m_entryPoint);
|
DumpInstr(program->m_entryPoint);
|
||||||
}
|
}
|
||||||
func = program->GetFunctions();
|
|
||||||
std::string prev = GetPointerAsString(program->m_entryPoint);
|
std::string prev = GetPointerAsString(program->m_entryPoint);
|
||||||
while (func != nullptr)
|
for (CBotFunction* func : program->GetFunctions())
|
||||||
{
|
{
|
||||||
if (func != program->m_entryPoint)
|
if (func != program->m_entryPoint)
|
||||||
{
|
{
|
||||||
|
@ -122,8 +132,6 @@ void CBotDebug::DumpCompiledProgram(CBotProgram* program)
|
||||||
//ss << prev << " -> " << GetPointerAsString(func) << " [style=invis]" << std::endl;
|
//ss << prev << " -> " << GetPointerAsString(func) << " [style=invis]" << std::endl;
|
||||||
prev = GetPointerAsString(func);
|
prev = GetPointerAsString(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
func = func->Next();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ss << "}" << std::endl;
|
ss << "}" << std::endl;
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -19,6 +19,9 @@
|
||||||
|
|
||||||
#include "CBot/CBotDefParam.h"
|
#include "CBot/CBotDefParam.h"
|
||||||
|
|
||||||
|
#include "CBot/CBotInstr/CBotInstrUtils.h"
|
||||||
|
#include "CBot/CBotInstr/CBotParExpr.h"
|
||||||
|
|
||||||
#include "CBot/CBotUtils.h"
|
#include "CBot/CBotUtils.h"
|
||||||
#include "CBot/CBotCStack.h"
|
#include "CBot/CBotCStack.h"
|
||||||
|
|
||||||
|
@ -33,11 +36,13 @@ namespace CBot
|
||||||
CBotDefParam::CBotDefParam()
|
CBotDefParam::CBotDefParam()
|
||||||
{
|
{
|
||||||
m_nIdent = 0;
|
m_nIdent = 0;
|
||||||
|
m_expr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotDefParam::~CBotDefParam()
|
CBotDefParam::~CBotDefParam()
|
||||||
{
|
{
|
||||||
|
delete m_expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -51,17 +56,16 @@ CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
if (IsOfType(p, ID_OPENPAR))
|
if (IsOfType(p, ID_OPENPAR))
|
||||||
{
|
{
|
||||||
CBotDefParam* list = nullptr;
|
CBotDefParam* list = nullptr;
|
||||||
|
bool prevHasDefault = false;
|
||||||
|
|
||||||
while (!IsOfType(p, ID_CLOSEPAR))
|
if (!IsOfType(p, ID_CLOSEPAR)) while (true)
|
||||||
{
|
{
|
||||||
CBotDefParam* param = new CBotDefParam();
|
CBotDefParam* param = new CBotDefParam();
|
||||||
if (list == nullptr) list = param;
|
if (list == nullptr) list = param;
|
||||||
else list->AddNext(param); // added to the list
|
else list->AddNext(param); // added to the list
|
||||||
|
|
||||||
// CBotClass* pClass = nullptr;//= CBotClass::Find(p);
|
|
||||||
param->m_typename = p->GetString();
|
param->m_typename = p->GetString();
|
||||||
CBotTypResult type = param->m_type = TypeParam(p, pStack);
|
CBotTypResult type = param->m_type = TypeParam(p, pStack);
|
||||||
// if ( type == CBotTypPointer ) type = CBotTypClass; // we must create a new object
|
|
||||||
|
|
||||||
if (param->m_type.GetType() > 0)
|
if (param->m_type.GetType() > 0)
|
||||||
{
|
{
|
||||||
|
@ -77,19 +81,40 @@ CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsOfType(p, ID_ASS)) // default value assignment
|
||||||
|
{
|
||||||
|
CBotCStack* pStk = pStack->TokenStack(nullptr, true);
|
||||||
|
if (nullptr != (param->m_expr = CBotParExpr::CompileLitExpr(p, pStk)))
|
||||||
|
{
|
||||||
|
CBotTypResult valueType = pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
||||||
|
|
||||||
|
if (!TypesCompatibles(type, valueType))
|
||||||
|
pStack->SetError(CBotErrBadType1, p->GetPrev());
|
||||||
|
|
||||||
|
prevHasDefault = true;
|
||||||
|
}
|
||||||
|
else pStack->SetError(CBotErrNoExpression, p);
|
||||||
|
pStack->DeleteNext();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (prevHasDefault) pStack->SetError(CBotErrDefaultValue, p->GetPrev());
|
||||||
|
|
||||||
|
if (!pStack->IsOk()) break;
|
||||||
|
|
||||||
if ( type.Eq(CBotTypArrayPointer) ) type.SetType(CBotTypArrayBody);
|
if ( type.Eq(CBotTypArrayPointer) ) type.SetType(CBotTypArrayBody);
|
||||||
CBotVar* var = CBotVar::Create(pp->GetString(), type); // creates the variable
|
CBotVar* var = CBotVar::Create(pp->GetString(), type); // creates the variable
|
||||||
// if ( pClass ) var->SetClass(pClass);
|
|
||||||
var->SetInit(CBotVar::InitType::IS_POINTER); // mark initialized
|
var->SetInit(CBotVar::InitType::IS_POINTER); // mark initialized
|
||||||
param->m_nIdent = CBotVar::NextUniqNum();
|
param->m_nIdent = CBotVar::NextUniqNum();
|
||||||
var->SetUniqNum(param->m_nIdent);
|
var->SetUniqNum(param->m_nIdent);
|
||||||
pStack->AddVar(var); // place on the stack
|
pStack->AddVar(var); // place on the stack
|
||||||
|
|
||||||
if (IsOfType(p, ID_COMMA) || p->GetType() == ID_CLOSEPAR)
|
if (IsOfType(p, ID_COMMA)) continue;
|
||||||
continue;
|
if (IsOfType(p, ID_CLOSEPAR)) break;
|
||||||
}
|
|
||||||
pStack->SetError(CBotErrClosePar, p->GetStart());
|
pStack->SetError(CBotErrClosePar, p->GetStart());
|
||||||
}
|
}
|
||||||
|
pStack->SetError(CBotErrNoVar, p->GetStart());
|
||||||
|
}
|
||||||
pStack->SetError(CBotErrNoType, p);
|
pStack->SetError(CBotErrNoType, p);
|
||||||
delete list;
|
delete list;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -106,35 +131,91 @@ bool CBotDefParam::Execute(CBotVar** ppVars, CBotStack* &pj)
|
||||||
int i = 0;
|
int i = 0;
|
||||||
CBotDefParam* p = this;
|
CBotDefParam* p = this;
|
||||||
|
|
||||||
|
bool useDefault = false;
|
||||||
|
CBotStack* pile = pj->AddStack();
|
||||||
|
|
||||||
while ( p != nullptr )
|
while ( p != nullptr )
|
||||||
{
|
{
|
||||||
|
pile = pile->AddStack();
|
||||||
|
if (pile->StackOver()) return pj->Return(pile);
|
||||||
|
if (pile->GetState() == 1) // already done?
|
||||||
|
{
|
||||||
|
if (ppVars != nullptr && ppVars[i] != nullptr) ++i;
|
||||||
|
p = p->m_next;
|
||||||
|
continue; // next param
|
||||||
|
}
|
||||||
|
|
||||||
|
CBotVar* pVar = nullptr;
|
||||||
|
|
||||||
|
if (useDefault || (ppVars == nullptr || ppVars[i] == nullptr))
|
||||||
|
{
|
||||||
|
useDefault = true; // end of arguments found
|
||||||
|
if (p->m_expr != nullptr) // has default expression ?
|
||||||
|
{
|
||||||
|
if (!p->m_expr->Execute(pile)) return false; // interupt here
|
||||||
|
pVar = pile->GetVar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pVar = ppVars[i];
|
||||||
|
|
||||||
|
pile->SetState(1); // mark this param done
|
||||||
|
|
||||||
// creates a local variable on the stack
|
// creates a local variable on the stack
|
||||||
CBotVar* newvar = CBotVar::Create(p->m_token.GetString(), p->m_type);
|
CBotVar* newvar = CBotVar::Create(p->m_token.GetString(), p->m_type);
|
||||||
|
|
||||||
// serves to make the transformation of types:
|
// serves to make the transformation of types:
|
||||||
if ( ppVars != nullptr && ppVars[i] != nullptr )
|
if ((useDefault && pVar != nullptr) ||
|
||||||
|
(ppVars != nullptr && pVar != nullptr))
|
||||||
{
|
{
|
||||||
switch (p->m_type.GetType())
|
switch (p->m_type.GetType())
|
||||||
{
|
{
|
||||||
|
case CBotTypByte:
|
||||||
|
newvar->SetValByte(pVar->GetValByte());
|
||||||
|
newvar->SetInit(pVar->GetInit()); // copy nan
|
||||||
|
break;
|
||||||
|
case CBotTypShort:
|
||||||
|
newvar->SetValShort(pVar->GetValShort());
|
||||||
|
newvar->SetInit(pVar->GetInit()); // copy nan
|
||||||
|
break;
|
||||||
|
case CBotTypChar:
|
||||||
|
newvar->SetValChar(pVar->GetValChar());
|
||||||
|
newvar->SetInit(pVar->GetInit()); // copy nan
|
||||||
|
break;
|
||||||
case CBotTypInt:
|
case CBotTypInt:
|
||||||
newvar->SetValInt(ppVars[i]->GetValInt());
|
newvar->SetValInt(pVar->GetValInt());
|
||||||
|
newvar->SetInit(pVar->GetInit()); // copy nan
|
||||||
|
break;
|
||||||
|
case CBotTypLong:
|
||||||
|
newvar->SetValLong(pVar->GetValLong());
|
||||||
|
newvar->SetInit(pVar->GetInit()); // copy nan
|
||||||
break;
|
break;
|
||||||
case CBotTypFloat:
|
case CBotTypFloat:
|
||||||
newvar->SetValFloat(ppVars[i]->GetValFloat());
|
newvar->SetValFloat(pVar->GetValFloat());
|
||||||
|
newvar->SetInit(pVar->GetInit()); // copy nan
|
||||||
|
break;
|
||||||
|
case CBotTypDouble:
|
||||||
|
newvar->SetValDouble(pVar->GetValDouble());
|
||||||
|
newvar->SetInit(pVar->GetInit()); // copy nan
|
||||||
break;
|
break;
|
||||||
case CBotTypString:
|
case CBotTypString:
|
||||||
newvar->SetValString(ppVars[i]->GetValString());
|
newvar->SetValString(pVar->GetValString());
|
||||||
break;
|
break;
|
||||||
case CBotTypBoolean:
|
case CBotTypBoolean:
|
||||||
newvar->SetValInt(ppVars[i]->GetValInt());
|
newvar->SetValInt(pVar->GetValInt());
|
||||||
break;
|
break;
|
||||||
case CBotTypIntrinsic:
|
case CBotTypIntrinsic:
|
||||||
(static_cast<CBotVarClass*>(newvar))->Copy(ppVars[i], false);
|
(static_cast<CBotVarClass*>(newvar))->Copy(pVar, false);
|
||||||
break;
|
break;
|
||||||
case CBotTypPointer:
|
case CBotTypPointer:
|
||||||
|
{
|
||||||
|
newvar->SetPointer(pVar->GetPointer());
|
||||||
|
newvar->SetType(p->m_type); // keep pointer type
|
||||||
|
}
|
||||||
|
break;
|
||||||
case CBotTypArrayPointer:
|
case CBotTypArrayPointer:
|
||||||
{
|
{
|
||||||
newvar->SetPointer(ppVars[i]->GetPointer());
|
newvar->SetPointer(pVar->GetPointer());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -144,23 +225,41 @@ bool CBotDefParam::Execute(CBotVar** ppVars, CBotStack* &pj)
|
||||||
newvar->SetUniqNum(p->m_nIdent);
|
newvar->SetUniqNum(p->m_nIdent);
|
||||||
pj->AddVar(newvar); // add a variable
|
pj->AddVar(newvar); // add a variable
|
||||||
p = p->m_next;
|
p = p->m_next;
|
||||||
i++;
|
if (!useDefault) i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool CBotDefParam::HasDefault()
|
||||||
|
{
|
||||||
|
return (m_expr != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotDefParam::RestoreState(CBotStack* &pj, bool bMain)
|
void CBotDefParam::RestoreState(CBotStack* &pj, bool bMain)
|
||||||
{
|
{
|
||||||
// int i = 0;
|
|
||||||
CBotDefParam* p = this;
|
CBotDefParam* p = this;
|
||||||
|
|
||||||
|
CBotStack* pile = nullptr;
|
||||||
|
if (bMain) pile = pj->RestoreStack();
|
||||||
|
|
||||||
while ( p != nullptr )
|
while ( p != nullptr )
|
||||||
{
|
{
|
||||||
|
if (bMain && pile != nullptr)
|
||||||
|
{
|
||||||
|
pile = pile->RestoreStack();
|
||||||
|
if (pile != nullptr && pile->GetState() == 0)
|
||||||
|
{
|
||||||
|
assert(p->m_expr != nullptr);
|
||||||
|
p->m_expr->RestoreState(pile, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
// creates a local variable on the stack
|
// creates a local variable on the stack
|
||||||
CBotVar* var = pj->FindVar(p->m_token.GetString());
|
CBotVar* var = pj->FindVar(p->m_token.GetString());
|
||||||
var->SetUniqNum(p->m_nIdent);
|
if (var != nullptr) var->SetUniqNum(p->m_nIdent);
|
||||||
p = p->m_next;
|
p = p->m_next;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -63,6 +63,12 @@ public:
|
||||||
*/
|
*/
|
||||||
bool Execute(CBotVar** ppVars, CBotStack* &pj);
|
bool Execute(CBotVar** ppVars, CBotStack* &pj);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Check if this parameter has a default value expression.
|
||||||
|
* \return true if the parameter was compiled with a default value.
|
||||||
|
*/
|
||||||
|
bool HasDefault();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief RestoreState
|
* \brief RestoreState
|
||||||
* \param pj
|
* \param pj
|
||||||
|
@ -96,6 +102,9 @@ private:
|
||||||
//! Type of paramteter.
|
//! Type of paramteter.
|
||||||
CBotTypResult m_type;
|
CBotTypResult m_type;
|
||||||
long m_nIdent;
|
long m_nIdent;
|
||||||
|
|
||||||
|
//! Default value expression for the parameter.
|
||||||
|
CBotInstr* m_expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CBot
|
} // namespace CBot
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -35,13 +35,13 @@ namespace CBot
|
||||||
enum CBotType
|
enum CBotType
|
||||||
{
|
{
|
||||||
CBotTypVoid = 0, //!< void
|
CBotTypVoid = 0, //!< void
|
||||||
CBotTypByte = 1, //!< byte (NOT IMPLEMENTED)
|
CBotTypByte = 1, //!< byte
|
||||||
CBotTypShort = 2, //!< short (NOT IMPLEMENTED)
|
CBotTypShort = 2, //!< short
|
||||||
CBotTypChar = 3, //!< char (NOT IMPLEMENTED)
|
CBotTypChar = 3, //!< char
|
||||||
CBotTypInt = 4, //!< int
|
CBotTypInt = 4, //!< int
|
||||||
CBotTypLong = 5, //!< long (NOT IMPLEMENTED)
|
CBotTypLong = 5, //!< long
|
||||||
CBotTypFloat = 6, //!< float
|
CBotTypFloat = 6, //!< float
|
||||||
CBotTypDouble = 7, //!< double (NOT IMPLEMENTED)
|
CBotTypDouble = 7, //!< double
|
||||||
CBotTypBoolean = 8, //!< bool
|
CBotTypBoolean = 8, //!< bool
|
||||||
CBotTypString = 9, //!< string
|
CBotTypString = 9, //!< string
|
||||||
|
|
||||||
|
@ -100,12 +100,18 @@ enum TokenId
|
||||||
ID_STATIC,
|
ID_STATIC,
|
||||||
ID_PROTECTED,
|
ID_PROTECTED,
|
||||||
ID_PRIVATE,
|
ID_PRIVATE,
|
||||||
|
ID_REPEAT,
|
||||||
ID_INT,
|
ID_INT,
|
||||||
ID_FLOAT,
|
ID_FLOAT,
|
||||||
ID_BOOLEAN,
|
ID_BOOLEAN,
|
||||||
ID_STRING,
|
ID_STRING,
|
||||||
ID_VOID,
|
ID_VOID,
|
||||||
ID_BOOL,
|
ID_BOOL,
|
||||||
|
ID_BYTE,
|
||||||
|
ID_SHORT,
|
||||||
|
ID_CHAR,
|
||||||
|
ID_LONG,
|
||||||
|
ID_DOUBLE,
|
||||||
|
|
||||||
TokenKeyVal = 2200, //!< keywords that represent values (true, false, null, nan)
|
TokenKeyVal = 2200, //!< keywords that represent values (true, false, null, nan)
|
||||||
ID_TRUE = 2200,
|
ID_TRUE = 2200,
|
||||||
|
@ -177,7 +183,8 @@ enum TokenType
|
||||||
TokenTypNum = 2, //!< number
|
TokenTypNum = 2, //!< number
|
||||||
TokenTypString = 3, //!< string
|
TokenTypString = 3, //!< string
|
||||||
TokenTypVar = 4, //!< a variable name
|
TokenTypVar = 4, //!< a variable name
|
||||||
TokenTypDef = 5 //!< value according DefineNum
|
TokenTypDef = 5, //!< value according DefineNum
|
||||||
|
TokenTypChar = 6, //!< character literal
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -235,6 +242,20 @@ enum CBotError : int
|
||||||
CBotErrBadIndex = 5040, //!< wrong index type "[ false ]"
|
CBotErrBadIndex = 5040, //!< wrong index type "[ false ]"
|
||||||
CBotErrPrivate = 5041, //!< protected item
|
CBotErrPrivate = 5041, //!< protected item
|
||||||
CBotErrNoPublic = 5042, //!< missing word "public"
|
CBotErrNoPublic = 5042, //!< missing word "public"
|
||||||
|
CBotErrNoExpression = 5043, //!< expression expected after =
|
||||||
|
CBotErrAmbiguousCall = 5044, //!< ambiguous call to overloaded function
|
||||||
|
CBotErrFuncNotVoid = 5045, //!< function needs return type "void"
|
||||||
|
CBotErrNoClassName = 5046, //!< class name expected
|
||||||
|
CBotErrNoReturn = 5047, //!< non-void function needs "return;"
|
||||||
|
CBotErrDefaultValue = 5048, //!< this parameter needs a default value
|
||||||
|
CBotErrEndQuote = 5049, //!< missing end quote
|
||||||
|
CBotErrBadEscape = 5050, //!< unknown escape sequence
|
||||||
|
CBotErrOctalRange = 5051, //!< octal value out of range
|
||||||
|
CBotErrHexDigits = 5052, //!< missing hex digits after escape sequence
|
||||||
|
CBotErrHexRange = 5053, //!< hex value out of range
|
||||||
|
CBotErrUnicodeName = 5054, //!< invalid universal character name
|
||||||
|
CBotErrCharEmpty = 5055, //!< empty character constant
|
||||||
|
CBotErrRedefCase = 5056, //!< duplicate label in switch
|
||||||
|
|
||||||
// Runtime errors
|
// Runtime errors
|
||||||
CBotErrZeroDiv = 6000, //!< division by zero
|
CBotErrZeroDiv = 6000, //!< division by zero
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -82,19 +82,23 @@ int CBotExternalCallList::DoCall(CBotToken* token, CBotVar* thisVar, CBotVar** p
|
||||||
|
|
||||||
CBotExternalCall* pt = m_list[token->GetString()].get();
|
CBotExternalCall* pt = m_list[token->GetString()].get();
|
||||||
|
|
||||||
if (pStack->IsCallFinished()) return true;
|
if (thisVar == nullptr && pStack->IsCallFinished()) return true; // only for non-method external call
|
||||||
CBotStack* pile = pStack->AddStackExternalCall(pt);
|
|
||||||
|
|
||||||
// lists the parameters depending on the contents of the stack (pStackVar)
|
// if this is a method call we need to use AddStack()
|
||||||
|
CBotStack* pile = (thisVar != nullptr) ? pStack->AddStack() : pStack->AddStackExternalCall(pt);
|
||||||
|
|
||||||
|
if (pile->GetState() == 0) // the first time?
|
||||||
|
{
|
||||||
|
// lists the parameters depending on the contents of the stack
|
||||||
CBotVar* pVar = MakeListVars(ppVar, true);
|
CBotVar* pVar = MakeListVars(ppVar, true);
|
||||||
|
|
||||||
// creates a variable to the result
|
|
||||||
CBotVar* pResult = rettype.Eq(CBotTypVoid) ? nullptr : CBotVar::Create("", rettype);
|
|
||||||
|
|
||||||
pile->SetVar(pVar);
|
pile->SetVar(pVar);
|
||||||
|
|
||||||
CBotStack* pile2 = pile->AddStack();
|
CBotStack* pile2 = pile->AddStack();
|
||||||
|
// creates a variable to the result
|
||||||
|
CBotVar* pResult = rettype.Eq(CBotTypVoid) ? nullptr : CBotVar::Create("", rettype);
|
||||||
pile2->SetVar(pResult);
|
pile2->SetVar(pResult);
|
||||||
|
pile->IncState(); // increment state to mark this step done
|
||||||
|
}
|
||||||
|
|
||||||
pile->SetError(CBotNoErr, token); // save token for the position in case of error
|
pile->SetError(CBotNoErr, token); // save token for the position in case of error
|
||||||
return pt->Run(thisVar, pStack);
|
return pt->Run(thisVar, pStack);
|
||||||
|
@ -107,7 +111,8 @@ bool CBotExternalCallList::RestoreCall(CBotToken* token, CBotVar* thisVar, CBotV
|
||||||
|
|
||||||
CBotExternalCall* pt = m_list[token->GetString()].get();
|
CBotExternalCall* pt = m_list[token->GetString()].get();
|
||||||
|
|
||||||
CBotStack* pile = pStack->RestoreStackEOX(pt);
|
// if this is a method call we need to use RestoreStack()
|
||||||
|
CBotStack* pile = (thisVar != nullptr) ? pStack->RestoreStack() : pStack->RestoreStackEOX(pt);
|
||||||
if (pile == nullptr) return true;
|
if (pile == nullptr) return true;
|
||||||
|
|
||||||
pile->RestoreStack();
|
pile->RestoreStack();
|
||||||
|
@ -163,9 +168,51 @@ bool CBotExternalCallDefault::Run(CBotVar* thisVar, CBotStack* pStack)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != nullptr) pStack->SetCopyVar(result);
|
pStack->Return(pile2); // return 'result' and clear extra stack
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
CBotExternalCallClass::CBotExternalCallClass(RuntimeFunc rExec, CompileFunc rCompile)
|
||||||
|
{
|
||||||
|
m_rExec = rExec;
|
||||||
|
m_rComp = rCompile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CBotExternalCallClass::~CBotExternalCallClass()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CBotTypResult CBotExternalCallClass::Compile(CBotVar* thisVar, CBotVar* args, void* user)
|
||||||
|
{
|
||||||
|
return m_rComp(thisVar, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBotExternalCallClass::Run(CBotVar* thisVar, CBotStack* pStack)
|
||||||
|
{
|
||||||
|
assert(thisVar != nullptr);
|
||||||
|
CBotStack* pile = pStack->AddStack();
|
||||||
|
CBotVar* args = pile->GetVar();
|
||||||
|
|
||||||
|
CBotStack* pile2 = pile->AddStack();
|
||||||
|
|
||||||
|
CBotVar* result = pile2->GetVar();
|
||||||
|
|
||||||
|
int exception = CBotNoErr; // TODO: Change to CBotError
|
||||||
|
bool res = m_rExec(thisVar, args, result, exception, pStack->GetUserPtr());
|
||||||
|
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
if (exception != CBotNoErr)
|
||||||
|
{
|
||||||
|
pStack->SetError(static_cast<CBotError>(exception));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pStack->Return(pile2); // return 'result' and clear extra stack
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace CBot
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -105,6 +105,36 @@ private:
|
||||||
CompileFunc m_rComp;
|
CompileFunc m_rComp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Implementation of CBot external call for class methods, using compilation and runtime functions
|
||||||
|
*/
|
||||||
|
class CBotExternalCallClass : public CBotExternalCall
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef bool (*RuntimeFunc)(CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user);
|
||||||
|
typedef CBotTypResult (*CompileFunc)(CBotVar* pThis, CBotVar*& pVar);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Constructor
|
||||||
|
* \param rExec Runtime function
|
||||||
|
* \param rCompile Compilation function
|
||||||
|
* \see CBotProgram::AddFunction()
|
||||||
|
*/
|
||||||
|
CBotExternalCallClass(RuntimeFunc rExec, CompileFunc rCompile);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Destructor
|
||||||
|
*/
|
||||||
|
virtual ~CBotExternalCallClass();
|
||||||
|
|
||||||
|
virtual CBotTypResult Compile(CBotVar* thisVar, CBotVar* args, void* user) override;
|
||||||
|
virtual bool Run(CBotVar* thisVar, CBotStack* pStack) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
RuntimeFunc m_rExec;
|
||||||
|
CompileFunc m_rComp;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Class for mangaging CBot external calls
|
* \brief Class for mangaging CBot external calls
|
|
@ -0,0 +1,367 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see http://gnu.org/licenses
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CBot/CBotFileUtils.h"
|
||||||
|
|
||||||
|
#include "CBot/CBotClass.h"
|
||||||
|
#include "CBot/CBotEnums.h"
|
||||||
|
|
||||||
|
namespace CBot
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static bool WriteBinary(std::ostream &ostr, T value, unsigned padTo = 0)
|
||||||
|
{
|
||||||
|
unsigned char chr;
|
||||||
|
unsigned count = 1;
|
||||||
|
while (value > 127) // unsigned LEB128
|
||||||
|
{
|
||||||
|
++count;
|
||||||
|
chr = (value & 0x7F) | 0x80;
|
||||||
|
if (!ostr.write(reinterpret_cast<char*>(&chr), 1)) return false;
|
||||||
|
value >>= 7;
|
||||||
|
}
|
||||||
|
chr = value & 0x7F;
|
||||||
|
if (count < padTo) chr |= 0x80;
|
||||||
|
if (!ostr.write(reinterpret_cast<char*>(&chr), 1)) return false;
|
||||||
|
|
||||||
|
if (count < padTo)
|
||||||
|
{
|
||||||
|
while (++count < padTo)
|
||||||
|
if (!(ostr << '\x80')) return false;
|
||||||
|
if (!(ostr << '\x00')) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static bool ReadBinary(std::istream &istr, T &value)
|
||||||
|
{
|
||||||
|
value = 0;
|
||||||
|
unsigned char chr;
|
||||||
|
unsigned shift = 0;
|
||||||
|
while (true) // unsigned LEB128
|
||||||
|
{
|
||||||
|
if (!istr.read(reinterpret_cast<char*>(&chr), 1)) return false;
|
||||||
|
if (shift < sizeof(T) * 8)
|
||||||
|
value |= static_cast<T>(chr & 0x7F) << shift;
|
||||||
|
shift += 7;
|
||||||
|
if ((chr & 0x80) == 0) break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static bool WriteSignedBinary(std::ostream &ostr, T value, unsigned padTo = 0)
|
||||||
|
{
|
||||||
|
signed char sign = value >> (8 * sizeof(T) - 1);
|
||||||
|
unsigned count = 0;
|
||||||
|
while (true) // signed LEB128
|
||||||
|
{
|
||||||
|
++count;
|
||||||
|
unsigned char chr = value & 0x7F;
|
||||||
|
value >>= 7;
|
||||||
|
if (!(value != sign || ((chr ^ sign) & 0x40) != 0))
|
||||||
|
{
|
||||||
|
if (count < padTo) chr |= 0x80;
|
||||||
|
if (!ostr.write(reinterpret_cast<char*>(&chr), 1)) return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
chr |= 0x80;
|
||||||
|
if (!ostr.put(chr)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count < padTo)
|
||||||
|
{
|
||||||
|
char chr = (sign < 0) ? 0x7F : 0x00;
|
||||||
|
while (++count < padTo)
|
||||||
|
if (!ostr.put(chr | 0x80)) return false;
|
||||||
|
if (!ostr.put(chr)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static bool ReadSignedBinary(std::istream &istr, T &value)
|
||||||
|
{
|
||||||
|
value = 0;
|
||||||
|
unsigned char chr;
|
||||||
|
unsigned shift = 0;
|
||||||
|
while (true) // signed LEB128
|
||||||
|
{
|
||||||
|
if (!istr.read(reinterpret_cast<char*>(&chr), 1)) return false;
|
||||||
|
if (shift < sizeof(T) * 8 - 1)
|
||||||
|
value |= (static_cast<T>(chr & 0x7F) << shift);
|
||||||
|
shift += 7;
|
||||||
|
if ((chr & 0x80) == 0) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shift >= 8 * sizeof(T) - 1) shift = 8 * sizeof(T) - 1;
|
||||||
|
if ((chr & 0x40) != 0)
|
||||||
|
value |= static_cast<T>(-1) << shift;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteWord(std::ostream &ostr, unsigned short w)
|
||||||
|
{
|
||||||
|
return WriteBinary<unsigned short>(ostr, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadWord(std::istream &istr, unsigned short &w)
|
||||||
|
{
|
||||||
|
return ReadBinary<unsigned short>(istr, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteByte(std::ostream &ostr, char c)
|
||||||
|
{
|
||||||
|
if (!ostr.put(c)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadByte(std::istream &istr, char& c)
|
||||||
|
{
|
||||||
|
if (!istr.get(c)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteShort(std::ostream &ostr, short s)
|
||||||
|
{
|
||||||
|
return WriteSignedBinary<short>(ostr, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadShort(std::istream &istr, short &s)
|
||||||
|
{
|
||||||
|
return ReadSignedBinary<short>(istr, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteUInt32(std::ostream &ostr, uint32_t i)
|
||||||
|
{
|
||||||
|
return WriteBinary<uint32_t>(ostr, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadUInt32(std::istream &istr, uint32_t &i)
|
||||||
|
{
|
||||||
|
return ReadBinary<uint32_t>(istr, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteInt(std::ostream &ostr, int i)
|
||||||
|
{
|
||||||
|
return WriteSignedBinary<int>(ostr, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadInt(std::istream &istr, int &i)
|
||||||
|
{
|
||||||
|
return ReadSignedBinary<int>(istr, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteLong(std::ostream &ostr, long l, unsigned padTo)
|
||||||
|
{
|
||||||
|
return WriteSignedBinary<long>(ostr, l, padTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadLong(std::istream &istr, long &l)
|
||||||
|
{
|
||||||
|
return ReadSignedBinary<long>(istr, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteFloat(std::ostream &ostr, float f)
|
||||||
|
{
|
||||||
|
union TypeConverter
|
||||||
|
{
|
||||||
|
float fValue;
|
||||||
|
uint32_t iValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
TypeConverter u;
|
||||||
|
u.fValue = 0.0f;
|
||||||
|
u.iValue = 0;
|
||||||
|
|
||||||
|
u.fValue = f;
|
||||||
|
return WriteBinary<uint32_t>(ostr, u.iValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadFloat(std::istream &istr, float &f)
|
||||||
|
{
|
||||||
|
union TypeConverter
|
||||||
|
{
|
||||||
|
float fValue;
|
||||||
|
uint32_t iValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
TypeConverter u;
|
||||||
|
u.fValue = 0.0f;
|
||||||
|
u.iValue = 0;
|
||||||
|
|
||||||
|
if (!ReadBinary<uint32_t>(istr, u.iValue)) return false;
|
||||||
|
f = u.fValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteDouble(std::ostream &ostr, double d)
|
||||||
|
{
|
||||||
|
union TypeConverter
|
||||||
|
{
|
||||||
|
double dValue;
|
||||||
|
uint64_t iValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
TypeConverter u;
|
||||||
|
u.dValue = 0.0;
|
||||||
|
u.iValue = 0;
|
||||||
|
|
||||||
|
u.dValue = d;
|
||||||
|
return WriteBinary<uint64_t>(ostr, u.iValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadDouble(std::istream &istr, double &d)
|
||||||
|
{
|
||||||
|
union TypeConverter
|
||||||
|
{
|
||||||
|
double dValue;
|
||||||
|
uint64_t iValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
TypeConverter u;
|
||||||
|
u.dValue = 0.0;
|
||||||
|
u.iValue = 0;
|
||||||
|
|
||||||
|
if (!ReadBinary<uint64_t>(istr, u.iValue)) return false;
|
||||||
|
d = u.dValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteString(std::ostream &ostr, const std::string &s)
|
||||||
|
{
|
||||||
|
if (!WriteBinary<size_t>(ostr, s.size())) return false;
|
||||||
|
if (!ostr.write(&(s[0]), s.size())) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadString(std::istream &istr, std::string &s)
|
||||||
|
{
|
||||||
|
size_t length = 0;
|
||||||
|
if (!ReadBinary<size_t>(istr, length)) return false;
|
||||||
|
|
||||||
|
s.resize(length);
|
||||||
|
if (length != 0)
|
||||||
|
{
|
||||||
|
if (!istr.read(&(s[0]), length)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteType(std::ostream &ostr, const CBotTypResult &type)
|
||||||
|
{
|
||||||
|
int typ = type.GetType();
|
||||||
|
if ( typ == CBotTypIntrinsic ) typ = CBotTypClass;
|
||||||
|
if ( !WriteWord(ostr, typ) ) return false;
|
||||||
|
if ( typ == CBotTypClass )
|
||||||
|
{
|
||||||
|
CBotClass* p = type.GetClass();
|
||||||
|
if (!WriteString(ostr, p->GetName())) return false;
|
||||||
|
}
|
||||||
|
if ( type.Eq( CBotTypArrayBody ) ||
|
||||||
|
type.Eq( CBotTypArrayPointer ) )
|
||||||
|
{
|
||||||
|
if (!WriteWord(ostr, type.GetLimite())) return false;
|
||||||
|
if (!WriteType(ostr, type.GetTypElem())) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( type.Eq(CBotTypPointer) )
|
||||||
|
{
|
||||||
|
if (type.GetClass() != nullptr)
|
||||||
|
{
|
||||||
|
if (!WriteString(ostr, type.GetClass()->GetName())) return false;
|
||||||
|
}
|
||||||
|
else if (!WriteString(ostr, "")) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadType(std::istream &istr, CBotTypResult &type)
|
||||||
|
{
|
||||||
|
unsigned short w, ww;
|
||||||
|
if (!ReadWord(istr, w)) return false;
|
||||||
|
type.SetType(w);
|
||||||
|
|
||||||
|
if ( type.Eq( CBotTypIntrinsic ) )
|
||||||
|
{
|
||||||
|
type = CBotTypResult( w, "point" );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( type.Eq( CBotTypClass ) )
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
if (!ReadString(istr, s)) return false;
|
||||||
|
type = CBotTypResult( w, s );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( type.Eq( CBotTypArrayPointer ) ||
|
||||||
|
type.Eq( CBotTypArrayBody ) )
|
||||||
|
{
|
||||||
|
CBotTypResult r;
|
||||||
|
if (!ReadWord(istr, ww)) return false;
|
||||||
|
if (!ReadType(istr, r)) return false;
|
||||||
|
type = CBotTypResult( w, r );
|
||||||
|
type.SetLimite(static_cast<short>(ww));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( type.Eq(CBotTypPointer) )
|
||||||
|
{
|
||||||
|
std::string className;
|
||||||
|
if (!ReadString(istr, className)) return false;
|
||||||
|
type = CBotTypResult(w, className);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteStream(std::ostream &ostr, std::istream& istr)
|
||||||
|
{
|
||||||
|
if (!istr.seekg(0, istr.end)) return false;
|
||||||
|
auto size = istr.tellg();
|
||||||
|
|
||||||
|
if (size == 0) return WriteLong(ostr, 0);
|
||||||
|
if (!WriteLong(ostr, size)) return false;
|
||||||
|
|
||||||
|
if (!istr.seekg(0, istr.beg)) return false;
|
||||||
|
while (size > 0)
|
||||||
|
{
|
||||||
|
size -= 1;
|
||||||
|
if (!ostr.put(istr.get())) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadStream(std::istream& istr, std::ostream &ostr)
|
||||||
|
{
|
||||||
|
long length;
|
||||||
|
if (!ReadLong(istr, length)) return false;
|
||||||
|
if (length == 0) return true;
|
||||||
|
|
||||||
|
while (length-- > 0)
|
||||||
|
{
|
||||||
|
if (!ostr.put(istr.get())) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace CBot
|
|
@ -0,0 +1,217 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see http://gnu.org/licenses
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace CBot
|
||||||
|
{
|
||||||
|
|
||||||
|
class CBotVar;
|
||||||
|
class CBotTypResult;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Save a linked list if variables
|
||||||
|
* \param ostr Output stream
|
||||||
|
* \param pVar First variable in the list
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool SaveVars(std::ostream &ostr, CBotVar* pVar);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief WriteWord
|
||||||
|
* \param ostr Output stream
|
||||||
|
* \param w
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool WriteWord(std::ostream &ostr, unsigned short w);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief ReadWord
|
||||||
|
* \param istr Input stream
|
||||||
|
* \param[out] w
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool ReadWord(std::istream &istr, unsigned short &w);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief WriteByte
|
||||||
|
* \param ostr Output stream
|
||||||
|
* \param c
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool WriteByte(std::ostream &ostr, char c);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief ReadByte
|
||||||
|
* \param istr Input stream
|
||||||
|
* \param[out] c
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool ReadByte(std::istream &istr, char& c);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief WriteShort
|
||||||
|
* \param ostr Output stream
|
||||||
|
* \param s
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool WriteShort(std::ostream &ostr, short s);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief ReadShort
|
||||||
|
* \param istr Input stream
|
||||||
|
* \param[out] s
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool ReadShort(std::istream &istr, short &s);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief WriteUInt32
|
||||||
|
* \param ostr Output stream
|
||||||
|
* \param i
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool WriteUInt32(std::ostream &ostr, uint32_t i);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief ReadUInt32
|
||||||
|
* \param istr Input stream
|
||||||
|
* \param[out] i
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool ReadUInt32(std::istream &istr, uint32_t &i);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief WriteInt
|
||||||
|
* \param ostr Output stream
|
||||||
|
* \param i
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool WriteInt(std::ostream &ostr, int i);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief ReadInt
|
||||||
|
* \param istr Input stream
|
||||||
|
* \param[out] i
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool ReadInt(std::istream &istr, int &i);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief WriteLong
|
||||||
|
* \param ostr Output stream
|
||||||
|
* \param l
|
||||||
|
* \param padTo minimum number of bytes to write
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool WriteLong(std::ostream &ostr, long l, unsigned padTo = 0);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief ReadLong
|
||||||
|
* \param istr Input stream
|
||||||
|
* \param[out] l
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool ReadLong(std::istream &istr, long &l);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief WriteFloat
|
||||||
|
* \param ostr Output stream
|
||||||
|
* \param f
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool WriteFloat(std::ostream &ostr, float f);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief ReadFloat
|
||||||
|
* \param istr Input stream
|
||||||
|
* \param[out] f
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool ReadFloat(std::istream &istr, float &f);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief WriteDouble
|
||||||
|
* \param ostr Output stream
|
||||||
|
* \param d
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool WriteDouble(std::ostream &ostr, double d);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief ReadDouble
|
||||||
|
* \param istr Input stream
|
||||||
|
* \param[out] d
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool ReadDouble(std::istream &istr, double &d);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief WriteString
|
||||||
|
* \param ostr Output stream
|
||||||
|
* \param s
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool WriteString(std::ostream &ostr, const std::string &s);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief ReadString
|
||||||
|
* \param istr Input stream
|
||||||
|
* \param[out] s
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool ReadString(std::istream &istr, std::string &s);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief WriteType
|
||||||
|
* \param ostr Output stream
|
||||||
|
* \param type
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool WriteType(std::ostream &ostr, const CBotTypResult &type);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief ReadType
|
||||||
|
* \param istr Input stream
|
||||||
|
* \param[out] type
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool ReadType(std::istream &istr, CBotTypResult &type);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief WriteStream
|
||||||
|
* \param ostr Output stream
|
||||||
|
* \param istr Input stream
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool WriteStream(std::ostream &ostr, std::istream& istr);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief ReadStream
|
||||||
|
* \param istr Input stream
|
||||||
|
* \param ostr Output stream
|
||||||
|
* \return true on success
|
||||||
|
*/
|
||||||
|
bool ReadStream(std::istream& istr, std::ostream &ostr);
|
||||||
|
|
||||||
|
} // namespace CBot
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see http://gnu.org/licenses
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CBot/CBotInstr/CBotCase.h"
|
||||||
|
|
||||||
|
#include "CBot/CBotInstr/CBotTwoOpExpr.h"
|
||||||
|
|
||||||
|
#include "CBot/CBotStack.h"
|
||||||
|
#include "CBot/CBotCStack.h"
|
||||||
|
|
||||||
|
namespace CBot
|
||||||
|
{
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
CBotCase::CBotCase()
|
||||||
|
{
|
||||||
|
m_instr = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
CBotCase::~CBotCase()
|
||||||
|
{
|
||||||
|
delete m_instr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CBotInstr* CBotCase::Compile(CBotToken* &p, CBotCStack* pStack, std::unordered_map<long, CBotInstr*>& labels)
|
||||||
|
{
|
||||||
|
CBotToken* pp = p; // preserves at the ^ token (starting position)
|
||||||
|
|
||||||
|
if (!IsOfType(p, ID_CASE, ID_DEFAULT)) return nullptr; // should never happen
|
||||||
|
pStack->SetStartError(pp->GetStart());
|
||||||
|
|
||||||
|
long labelValue = 0;
|
||||||
|
|
||||||
|
if (pp->GetType() == ID_CASE)
|
||||||
|
{
|
||||||
|
CBotInstr* i = nullptr;
|
||||||
|
if (nullptr != (i = CBotTwoOpExpr::Compile(p, pStack, nullptr, true)))
|
||||||
|
{
|
||||||
|
if (pStack->GetType() <= CBotTypLong)
|
||||||
|
{
|
||||||
|
CBotStack* pile = CBotStack::AllocateStack();
|
||||||
|
while ( !i->Execute(pile) );
|
||||||
|
labelValue = pile->GetVar()->GetValLong();
|
||||||
|
pile->Delete();
|
||||||
|
|
||||||
|
if (labels.count(labelValue) > 0)
|
||||||
|
{
|
||||||
|
pStack->SetError(CBotErrRedefCase, p->GetStart());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pStack->SetError(CBotErrBadNum, p->GetStart());
|
||||||
|
delete i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pStack->SetError(CBotErrBadNum, p->GetStart());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pStack->IsOk() && IsOfType(p, ID_DOTS))
|
||||||
|
{
|
||||||
|
CBotCase* newCase = new CBotCase();
|
||||||
|
newCase->SetToken(pp);
|
||||||
|
if (pp->GetType() == ID_CASE)
|
||||||
|
labels[labelValue] = newCase;
|
||||||
|
return newCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
pStack->SetError(CBotErrNoDoubleDots, p->GetStart());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool CBotCase::Execute(CBotStack* &pj)
|
||||||
|
{
|
||||||
|
if (m_instr == nullptr) return true;
|
||||||
|
CBotStack* pile = pj->AddStack(this, CBotStack::BlockVisibilityType::BLOCK);
|
||||||
|
|
||||||
|
int state = pile->GetState();
|
||||||
|
CBotInstr* p = m_instr;
|
||||||
|
while (state-- > 0) p = p->GetNext();
|
||||||
|
|
||||||
|
while (p != nullptr)
|
||||||
|
{
|
||||||
|
if (!p->Execute(pile)) return false;
|
||||||
|
pile->IncState();
|
||||||
|
p = p->GetNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
pile->Delete();
|
||||||
|
return pj->IsOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void CBotCase::RestoreState(CBotStack* &pj, bool bMain)
|
||||||
|
{
|
||||||
|
if (!bMain) return;
|
||||||
|
|
||||||
|
CBotStack* pile = pj->RestoreStack(this);
|
||||||
|
if (pile == nullptr) return;
|
||||||
|
|
||||||
|
CBotInstr* p = m_instr;
|
||||||
|
|
||||||
|
int state = pile->GetState();
|
||||||
|
while (p != nullptr && state-- > 0)
|
||||||
|
{
|
||||||
|
p->RestoreState(pile, bMain);
|
||||||
|
p = p->GetNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p != nullptr) p->RestoreState(pile, bMain);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, CBotInstr*> CBotCase::GetDebugLinks()
|
||||||
|
{
|
||||||
|
auto links = CBotInstr::GetDebugLinks();
|
||||||
|
links["m_instr"] = m_instr;
|
||||||
|
return links;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace CBot
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -21,6 +21,8 @@
|
||||||
|
|
||||||
#include "CBot/CBotInstr/CBotInstr.h"
|
#include "CBot/CBotInstr/CBotInstr.h"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace CBot
|
namespace CBot
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -42,7 +44,7 @@ public:
|
||||||
* \param pStack
|
* \param pStack
|
||||||
* \return
|
* \return
|
||||||
*/
|
*/
|
||||||
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
|
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, std::unordered_map<long, CBotInstr*>& labels);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Execute Execution of instruction "case".
|
* \brief Execute Execution of instruction "case".
|
||||||
|
@ -58,22 +60,15 @@ public:
|
||||||
*/
|
*/
|
||||||
void RestoreState(CBotStack* &pj, bool bMain) override;
|
void RestoreState(CBotStack* &pj, bool bMain) override;
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief CompCase Routine to find the entry point of "case" corresponding
|
|
||||||
* to the value seen.
|
|
||||||
* \param pj
|
|
||||||
* \param val
|
|
||||||
* \return
|
|
||||||
*/
|
|
||||||
bool CompCase(CBotStack* &pj, int val) override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual const std::string GetDebugName() override { return "CBotCase"; }
|
virtual const std::string GetDebugName() override { return "CBotCase"; }
|
||||||
virtual std::map<std::string, CBotInstr*> GetDebugLinks() override;
|
virtual std::map<std::string, CBotInstr*> GetDebugLinks() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! Value to compare.
|
//! List of instructions after case label
|
||||||
CBotInstr* m_value;
|
CBotInstr* m_instr;
|
||||||
|
|
||||||
|
friend class CBotSwitch;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CBot
|
} // namespace CBot
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -72,20 +72,27 @@ CBotInstr* CBotDefArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResul
|
||||||
CBotInstr* i;
|
CBotInstr* i;
|
||||||
while (IsOfType(p, ID_OPBRK))
|
while (IsOfType(p, ID_OPBRK))
|
||||||
{
|
{
|
||||||
|
pStk->SetStartError(p->GetStart());
|
||||||
if (p->GetType() != ID_CLBRK)
|
if (p->GetType() != ID_CLBRK)
|
||||||
|
{
|
||||||
i = CBotExpression::Compile(p, pStk); // expression for the value
|
i = CBotExpression::Compile(p, pStk); // expression for the value
|
||||||
|
if (i == nullptr || pStk->GetType() != CBotTypInt) // must be a number
|
||||||
|
{
|
||||||
|
pStk->SetError(CBotErrBadIndex, p->GetStart());
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
i = new CBotEmpty(); // if no special formula
|
i = new CBotEmpty(); // if no special formula
|
||||||
|
|
||||||
inst->AddNext3b(i); // construct a list
|
inst->AddNext3b(i); // construct a list
|
||||||
type = CBotTypResult(CBotTypArrayPointer, type);
|
type = CBotTypResult(CBotTypArrayPointer, type);
|
||||||
|
|
||||||
if (!pStk->IsOk() || !IsOfType(p, ID_CLBRK ))
|
if (IsOfType(p, ID_CLBRK)) continue;
|
||||||
{
|
|
||||||
pStk->SetError(CBotErrCloseIndex, p->GetStart());
|
pStk->SetError(CBotErrCloseIndex, p->GetStart());
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
CBotVar* var = CBotVar::Create(*vartoken, type); // create an instance
|
CBotVar* var = CBotVar::Create(*vartoken, type); // create an instance
|
||||||
inst->m_typevar = type;
|
inst->m_typevar = type;
|
||||||
|
@ -96,17 +103,32 @@ CBotInstr* CBotDefArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResul
|
||||||
|
|
||||||
if (IsOfType(p, ID_ASS)) // with an assignment
|
if (IsOfType(p, ID_ASS)) // with an assignment
|
||||||
{
|
{
|
||||||
if ((inst->m_listass = CBotTwoOpExpr::Compile(p, pStk)) != nullptr)
|
pStk->SetStartError(p->GetStart());
|
||||||
|
if ( IsOfType(p, ID_SEP) )
|
||||||
{
|
{
|
||||||
if (!pStk->GetTypResult().Compare(type)) // compatible type ?
|
pStk->SetError(CBotErrNoExpression, p->GetPrev());
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if ( nullptr == (inst->m_listass = CBotListArray::Compile(p, pStk, type.GetTypElem())) )
|
||||||
|
{
|
||||||
|
if (pStk->IsOk())
|
||||||
|
{
|
||||||
|
inst->m_listass = CBotTwoOpExpr::Compile(p, pStk);
|
||||||
|
if (inst->m_listass == nullptr || !pStk->GetTypResult().Compare(type)) // compatible type ?
|
||||||
{
|
{
|
||||||
pStk->SetError(CBotErrBadType1, p->GetStart());
|
pStk->SetError(CBotErrBadType1, p->GetStart());
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
|
||||||
|
if (pStk->IsOk()) while (true) // mark initialized
|
||||||
{
|
{
|
||||||
inst->m_listass = CBotListArray::Compile(p, pStk, type.GetTypElem());
|
var = var->GetItem(0, true);
|
||||||
|
if (var == nullptr) break;
|
||||||
|
if (var->GetType() == CBotTypArrayPointer) continue;
|
||||||
|
if (var->GetType() <= CBotTypString) var->SetInit(CBotVar::InitType::DEF);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -82,16 +82,17 @@ CBotInstr* CBotDefBoolean::Compile(CBotToken* &p, CBotCStack* pStack, bool cont,
|
||||||
|
|
||||||
inst = static_cast<CBotDefBoolean*>(CBotDefArray::Compile(p, pStk, CBotTypBoolean));
|
inst = static_cast<CBotDefBoolean*>(CBotDefArray::Compile(p, pStk, CBotTypBoolean));
|
||||||
|
|
||||||
if (!pStk->IsOk() )
|
|
||||||
{
|
|
||||||
pStk->SetError(CBotErrCloseIndex, p->GetStart());
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
goto suite; // no assignment, variable already created
|
goto suite; // no assignment, variable already created
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsOfType(p, ID_ASS))
|
if (IsOfType(p, ID_ASS))
|
||||||
{
|
{
|
||||||
|
pStk->SetStartError(p->GetStart());
|
||||||
|
if ( IsOfType(p, ID_SEP) )
|
||||||
|
{
|
||||||
|
pStk->SetError(CBotErrNoExpression, p->GetStart());
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
if (nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )))
|
if (nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )))
|
||||||
{
|
{
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -109,7 +110,7 @@ CBotInstr* CBotDefBoolean::Compile(CBotToken* &p, CBotCStack* pStack, bool cont,
|
||||||
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
|
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
|
||||||
pStack->AddVar(var);
|
pStack->AddVar(var);
|
||||||
suite:
|
suite:
|
||||||
if (IsOfType(p, ID_COMMA))
|
if (pStk->IsOk() && IsOfType(p, ID_COMMA))
|
||||||
{
|
{
|
||||||
if (nullptr != ( inst->m_next2b = CBotDefBoolean::Compile(p, pStk, true, noskip)))
|
if (nullptr != ( inst->m_next2b = CBotDefBoolean::Compile(p, pStk, true, noskip)))
|
||||||
{
|
{
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "CBot/CBotInstr/CBotDefClass.h"
|
#include "CBot/CBotInstr/CBotDefClass.h"
|
||||||
|
|
||||||
|
#include "CBot/CBotInstr/CBotExprRetVar.h"
|
||||||
#include "CBot/CBotInstr/CBotInstrUtils.h"
|
#include "CBot/CBotInstr/CBotInstrUtils.h"
|
||||||
|
|
||||||
#include "CBot/CBotInstr/CBotLeftExprVar.h"
|
#include "CBot/CBotInstr/CBotLeftExprVar.h"
|
||||||
|
@ -44,11 +45,15 @@ CBotDefClass::CBotDefClass()
|
||||||
m_expr = nullptr;
|
m_expr = nullptr;
|
||||||
m_hasParams = false;
|
m_hasParams = false;
|
||||||
m_nMethodeIdent = 0;
|
m_nMethodeIdent = 0;
|
||||||
|
m_exprRetVar = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotDefClass::~CBotDefClass()
|
CBotDefClass::~CBotDefClass()
|
||||||
{
|
{
|
||||||
|
delete m_parameters;
|
||||||
|
delete m_exprRetVar;
|
||||||
|
delete m_expr;
|
||||||
delete m_var;
|
delete m_var;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,11 +106,6 @@ CBotInstr* CBotDefClass::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* p
|
||||||
|
|
||||||
inst = static_cast<CBotDefClass*>(CBotDefArray::Compile(p, pStk, type ));
|
inst = static_cast<CBotDefClass*>(CBotDefArray::Compile(p, pStk, type ));
|
||||||
|
|
||||||
if (!pStk->IsOk() )
|
|
||||||
{
|
|
||||||
pStk->SetError(CBotErrCloseIndex, p->GetStart());
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
goto suite; // no assignment, variable already created
|
goto suite; // no assignment, variable already created
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,13 +134,13 @@ CBotInstr* CBotDefClass::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* p
|
||||||
{
|
{
|
||||||
// the constructor is there?
|
// the constructor is there?
|
||||||
// std::string noname;
|
// std::string noname;
|
||||||
CBotTypResult r = pClass->CompileMethode(pClass->GetName(), var, ppVars, pStk, inst->m_nMethodeIdent);
|
CBotTypResult r = pClass->CompileMethode(&token, var, ppVars, pStk, inst->m_nMethodeIdent);
|
||||||
delete pStk->TokenStack(); // releases the supplement stack
|
pStk->DeleteNext(); // releases the supplement stack
|
||||||
int typ = r.GetType();
|
int typ = r.GetType();
|
||||||
|
|
||||||
if (typ == CBotErrUndefCall)
|
if (typ == CBotErrUndefCall)
|
||||||
{
|
{
|
||||||
// si le constructeur n'existe pas
|
// if the ctor don't exist
|
||||||
if (inst->m_parameters != nullptr) // with parameters
|
if (inst->m_parameters != nullptr) // with parameters
|
||||||
{
|
{
|
||||||
pStk->SetError(CBotErrNoConstruct, vartoken);
|
pStk->SetError(CBotErrNoConstruct, vartoken);
|
||||||
|
@ -155,16 +155,33 @@ CBotInstr* CBotDefClass::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* p
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pStk->SetCopyVar(var);
|
||||||
|
// chained method ?
|
||||||
|
if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStk, true)))
|
||||||
|
{
|
||||||
|
inst->m_exprRetVar->SetToken(vartoken);
|
||||||
|
pStk->DeleteNext();
|
||||||
|
}
|
||||||
|
pStk->SetVar(nullptr);
|
||||||
|
|
||||||
|
if ( !pStk->IsOk() ) goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsOfType(p, ID_ASS)) // with a assignment?
|
if (IsOfType(p, ID_ASS)) // with a assignment?
|
||||||
{
|
{
|
||||||
|
pStk->SetStartError(p->GetStart());
|
||||||
if (inst->m_hasParams)
|
if (inst->m_hasParams)
|
||||||
{
|
{
|
||||||
pStk->SetError(CBotErrNoTerminator, p->GetStart());
|
pStk->SetError(CBotErrNoTerminator, p->GetStart());
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( IsOfType(p, ID_SEP) )
|
||||||
|
{
|
||||||
|
pStk->SetError(CBotErrNoExpression, p->GetStart());
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
if ( nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )) )
|
if ( nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )) )
|
||||||
{
|
{
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -172,7 +189,8 @@ CBotInstr* CBotDefClass::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* p
|
||||||
CBotClass* result = pStk->GetClass();
|
CBotClass* result = pStk->GetClass();
|
||||||
if ( !pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_POINTER).Eq(CBotTypNullPointer) &&
|
if ( !pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_POINTER).Eq(CBotTypNullPointer) &&
|
||||||
( !pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_POINTER).Eq(CBotTypPointer) ||
|
( !pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_POINTER).Eq(CBotTypPointer) ||
|
||||||
( result != nullptr && !pClass->IsChildOf(result) ))) // type compatible ?
|
( result != nullptr && !(pClass->IsChildOf(result) ||
|
||||||
|
result->IsChildOf(pClass))))) // type compatible ?
|
||||||
{
|
{
|
||||||
pStk->SetError(CBotErrBadType1, p->GetStart());
|
pStk->SetError(CBotErrBadType1, p->GetStart());
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -200,7 +218,7 @@ CBotInstr* CBotDefClass::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* p
|
||||||
var->SetInit(CBotVar::InitType::IS_POINTER); // marks the pointer as init
|
var->SetInit(CBotVar::InitType::IS_POINTER); // marks the pointer as init
|
||||||
}
|
}
|
||||||
suite:
|
suite:
|
||||||
if (IsOfType(p, ID_COMMA)) // several chained definitions
|
if (pStk->IsOk() && IsOfType(p, ID_COMMA)) // several chained definitions
|
||||||
{
|
{
|
||||||
if ( nullptr != ( inst->m_next = CBotDefClass::Compile(p, pStk, pClass) )) // compiles the following
|
if ( nullptr != ( inst->m_next = CBotDefClass::Compile(p, pStk, pClass) )) // compiles the following
|
||||||
{
|
{
|
||||||
|
@ -208,7 +226,7 @@ suite:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsOfType(p, ID_SEP)) // complete instruction
|
if (!pStk->IsOk() || IsOfType(p, ID_SEP)) // complete instruction
|
||||||
{
|
{
|
||||||
return pStack->Return(inst, pStk);
|
return pStack->Return(inst, pStk);
|
||||||
}
|
}
|
||||||
|
@ -229,6 +247,19 @@ bool CBotDefClass::Execute(CBotStack* &pj)
|
||||||
CBotStack* pile = pj->AddStack(this);//essential for SetState()
|
CBotStack* pile = pj->AddStack(this);//essential for SetState()
|
||||||
// if ( pile == EOX ) return true;
|
// if ( pile == EOX ) return true;
|
||||||
|
|
||||||
|
if (m_exprRetVar != nullptr) // Class c().method();
|
||||||
|
{
|
||||||
|
if (pile->GetState() == 4)
|
||||||
|
{
|
||||||
|
if (pile->IfStep()) return false;
|
||||||
|
CBotStack* pile3 = pile->AddStack();
|
||||||
|
if (!m_exprRetVar->Execute(pile3)) return false;
|
||||||
|
pile3->SetVar(nullptr);
|
||||||
|
pile->Return(pile3); // release pile3 stack
|
||||||
|
pile->SetState(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CBotToken* pt = &m_token;
|
CBotToken* pt = &m_token;
|
||||||
CBotClass* pClass = CBotClass::Find(pt);
|
CBotClass* pClass = CBotClass::Find(pt);
|
||||||
|
|
||||||
|
@ -266,9 +297,10 @@ bool CBotDefClass::Execute(CBotStack* &pj)
|
||||||
// evaluates the expression for the assignment
|
// evaluates the expression for the assignment
|
||||||
if (!m_expr->Execute(pile)) return false;
|
if (!m_expr->Execute(pile)) return false;
|
||||||
|
|
||||||
|
CBotVar* pv = pile->GetVar();
|
||||||
|
|
||||||
if ( bIntrincic )
|
if ( bIntrincic )
|
||||||
{
|
{
|
||||||
CBotVar* pv = pile->GetVar();
|
|
||||||
if ( pv == nullptr || pv->GetPointer() == nullptr )
|
if ( pv == nullptr || pv->GetPointer() == nullptr )
|
||||||
{
|
{
|
||||||
pile->SetError(CBotErrNull, &m_token);
|
pile->SetError(CBotErrNull, &m_token);
|
||||||
|
@ -278,9 +310,20 @@ bool CBotDefClass::Execute(CBotStack* &pj)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if ( !(pv == nullptr || pv->GetPointer() == nullptr) )
|
||||||
|
{
|
||||||
|
if ( !pv->GetClass()->IsChildOf(pClass))
|
||||||
|
{
|
||||||
|
pile->SetError(CBotErrBadType1, &m_token);
|
||||||
|
return pj->Return(pile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CBotVarClass* pInstance;
|
CBotVarClass* pInstance;
|
||||||
pInstance = (static_cast<CBotVarPointer*>(pile->GetVar()))->GetPointer(); // value for the assignment
|
pInstance = pv->GetPointer(); // value for the assignment
|
||||||
|
CBotTypResult type = pThis->GetTypResult();
|
||||||
pThis->SetPointer(pInstance);
|
pThis->SetPointer(pInstance);
|
||||||
|
pThis->SetType(type); // keep pointer type
|
||||||
}
|
}
|
||||||
pThis->SetInit(CBotVar::InitType::DEF);
|
pThis->SetInit(CBotVar::InitType::DEF);
|
||||||
}
|
}
|
||||||
|
@ -317,6 +360,7 @@ bool CBotDefClass::Execute(CBotStack* &pj)
|
||||||
if ( p != nullptr) while ( true )
|
if ( p != nullptr) while ( true )
|
||||||
{
|
{
|
||||||
pile2 = pile2->AddStack(); // place on the stack for the results
|
pile2 = pile2->AddStack(); // place on the stack for the results
|
||||||
|
if (pile2->StackOver()) return pj->Return(pile2);
|
||||||
if ( pile2->GetState() == 0 )
|
if ( pile2->GetState() == 0 )
|
||||||
{
|
{
|
||||||
if (!p->Execute(pile2)) return false; // interrupted here?
|
if (!p->Execute(pile2)) return false; // interrupted here?
|
||||||
|
@ -329,11 +373,7 @@ bool CBotDefClass::Execute(CBotStack* &pj)
|
||||||
ppVars[i] = nullptr;
|
ppVars[i] = nullptr;
|
||||||
|
|
||||||
// creates a variable for the result
|
// creates a variable for the result
|
||||||
CBotVar* pResult = nullptr; // constructor still void
|
if ( !pClass->ExecuteMethode(m_nMethodeIdent, pThis, ppVars, CBotTypResult(CBotTypVoid), pile2, GetToken())) return false; // interrupt
|
||||||
|
|
||||||
if ( !pClass->ExecuteMethode(m_nMethodeIdent, pClass->GetName(),
|
|
||||||
pThis, ppVars,
|
|
||||||
pResult, pile2, GetToken())) return false; // interrupt
|
|
||||||
|
|
||||||
pThis->SetInit(CBotVar::InitType::DEF);
|
pThis->SetInit(CBotVar::InitType::DEF);
|
||||||
pThis->ConstructorSet(); // indicates that the constructor has been called
|
pThis->ConstructorSet(); // indicates that the constructor has been called
|
||||||
|
@ -348,6 +388,14 @@ bool CBotDefClass::Execute(CBotStack* &pj)
|
||||||
pile->SetState(3); // finished this part
|
pile->SetState(3); // finished this part
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_exprRetVar != nullptr && pile->GetState() == 3) // Class c().method();
|
||||||
|
{
|
||||||
|
CBotStack* pile3 = pile->AddStack();
|
||||||
|
pile3->SetCopyVar(pThis);
|
||||||
|
pile->SetState(4);
|
||||||
|
return false; // go back to the top ^^^
|
||||||
|
}
|
||||||
|
|
||||||
if ( pile->IfStep() ) return false;
|
if ( pile->IfStep() ) return false;
|
||||||
|
|
||||||
if ( m_next2b != nullptr &&
|
if ( m_next2b != nullptr &&
|
||||||
|
@ -372,6 +420,16 @@ void CBotDefClass::RestoreState(CBotStack* &pj, bool bMain)
|
||||||
pThis->SetUniqNum((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent); // its attribute a unique number
|
pThis->SetUniqNum((static_cast<CBotLeftExprVar*>(m_var))->m_nIdent); // its attribute a unique number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_exprRetVar != nullptr) // Class c().method();
|
||||||
|
{
|
||||||
|
if (pile->GetState() == 4)
|
||||||
|
{
|
||||||
|
CBotStack* pile3 = pile->RestoreStack();
|
||||||
|
m_exprRetVar->RestoreState(pile3, bMain);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CBotToken* pt = &m_token;
|
CBotToken* pt = &m_token;
|
||||||
CBotClass* pClass = CBotClass::Find(pt);
|
CBotClass* pClass = CBotClass::Find(pt);
|
||||||
bool bIntrincic = pClass->IsIntrinsic();
|
bool bIntrincic = pClass->IsIntrinsic();
|
||||||
|
@ -425,9 +483,7 @@ void CBotDefClass::RestoreState(CBotStack* &pj, bool bMain)
|
||||||
ppVars[i] = nullptr;
|
ppVars[i] = nullptr;
|
||||||
|
|
||||||
// creates a variable for the result
|
// creates a variable for the result
|
||||||
// CBotVar* pResult = nullptr; // constructor still void
|
pClass->RestoreMethode(m_nMethodeIdent, pt, pThis, ppVars, pile2);
|
||||||
|
|
||||||
pClass->RestoreMethode(m_nMethodeIdent, pClass->GetName(), pThis, ppVars, pile2);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -85,6 +85,9 @@ private:
|
||||||
//! Constructor method unique identifier
|
//! Constructor method unique identifier
|
||||||
long m_nMethodeIdent;
|
long m_nMethodeIdent;
|
||||||
|
|
||||||
|
//! Instruction to chain method calls after constructor
|
||||||
|
CBotInstr* m_exprRetVar;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CBot
|
} // namespace CBot
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -46,13 +46,22 @@ CBotDefFloat::~CBotDefFloat()
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotInstr* CBotDefFloat::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, bool noskip)
|
CBotInstr* CBotDefFloat::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, bool noskip, CBotTypResult vartype)
|
||||||
{
|
{
|
||||||
CBotToken* pp = cont ? nullptr : p;
|
CBotToken* pp = cont ? nullptr : p;
|
||||||
|
|
||||||
if (!cont && !IsOfType(p, ID_FLOAT)) return nullptr;
|
if (!cont)
|
||||||
|
{
|
||||||
|
switch (p->GetType())
|
||||||
|
{
|
||||||
|
case ID_FLOAT: vartype.SetType(CBotTypFloat ); break;
|
||||||
|
case ID_DOUBLE: vartype.SetType(CBotTypDouble); break;
|
||||||
|
default: return nullptr;
|
||||||
|
}
|
||||||
|
p = p->GetNext();
|
||||||
|
}
|
||||||
|
|
||||||
CBotDefFloat* inst = static_cast<CBotDefFloat*>(CompileArray(p, pStack, CBotTypFloat));
|
CBotDefFloat* inst = static_cast<CBotDefFloat*>(CompileArray(p, pStack, vartype));
|
||||||
if (inst != nullptr || !pStack->IsOk()) return inst;
|
if (inst != nullptr || !pStack->IsOk()) return inst;
|
||||||
|
|
||||||
CBotCStack* pStk = pStack->TokenStack(pp);
|
CBotCStack* pStk = pStack->TokenStack(pp);
|
||||||
|
@ -67,7 +76,7 @@ CBotInstr* CBotDefFloat::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, b
|
||||||
|
|
||||||
if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )))
|
if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )))
|
||||||
{
|
{
|
||||||
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = CBotTypFloat;
|
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = vartype;
|
||||||
if (pStk->CheckVarLocal(vartoken)) // redefinition of a variable
|
if (pStk->CheckVarLocal(vartoken)) // redefinition of a variable
|
||||||
{
|
{
|
||||||
pStk->SetStartError(vartoken->GetStart());
|
pStk->SetStartError(vartoken->GetStart());
|
||||||
|
@ -79,18 +88,19 @@ CBotInstr* CBotDefFloat::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, b
|
||||||
{
|
{
|
||||||
delete inst;
|
delete inst;
|
||||||
p = vartoken;
|
p = vartoken;
|
||||||
inst = static_cast<CBotDefFloat*>(CBotDefArray::Compile(p, pStk, CBotTypFloat));
|
inst = static_cast<CBotDefFloat*>(CBotDefArray::Compile(p, pStk, vartype));
|
||||||
|
|
||||||
if (!pStk->IsOk() )
|
|
||||||
{
|
|
||||||
pStk->SetError(CBotErrCloseIndex, p->GetStart());
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
goto suite; // no assignment, variable already created
|
goto suite; // no assignment, variable already created
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsOfType(p, ID_ASS))
|
if (IsOfType(p, ID_ASS))
|
||||||
{
|
{
|
||||||
|
pStk->SetStartError(p->GetStart());
|
||||||
|
if ( IsOfType(p, ID_SEP) )
|
||||||
|
{
|
||||||
|
pStk->SetError(CBotErrNoExpression, p->GetStart());
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
if (nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )))
|
if (nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )))
|
||||||
{
|
{
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -102,15 +112,15 @@ CBotInstr* CBotDefFloat::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var = CBotVar::Create(*vartoken, CBotTypFloat);
|
var = CBotVar::Create(*vartoken, vartype);
|
||||||
var->SetInit(inst->m_expr != nullptr ? CBotVar::InitType::DEF : CBotVar::InitType::UNDEF);
|
var->SetInit(inst->m_expr != nullptr ? CBotVar::InitType::DEF : CBotVar::InitType::UNDEF);
|
||||||
var->SetUniqNum(
|
var->SetUniqNum(
|
||||||
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
|
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
|
||||||
pStack->AddVar(var);
|
pStack->AddVar(var);
|
||||||
suite:
|
suite:
|
||||||
if (IsOfType(p, ID_COMMA))
|
if (pStk->IsOk() && IsOfType(p, ID_COMMA))
|
||||||
{
|
{
|
||||||
if (nullptr != ( inst->m_next2b = CBotDefFloat::Compile(p, pStk, true, noskip)))
|
if (nullptr != ( inst->m_next2b = CBotDefFloat::Compile(p, pStk, true, noskip, vartype)))
|
||||||
{
|
{
|
||||||
return pStack->Return(inst, pStk);
|
return pStack->Return(inst, pStk);
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -41,7 +41,7 @@ public:
|
||||||
* \param noskip
|
* \param noskip
|
||||||
* \return
|
* \return
|
||||||
*/
|
*/
|
||||||
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool cont = false, bool noskip=false);
|
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool cont = false, bool noskip=false, CBotTypResult vartype = CBotTypFloat);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Execute Executes the definition of a real variable.
|
* \brief Execute Executes the definition of a real variable.
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -47,13 +47,25 @@ CBotDefInt::~CBotDefInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotInstr* CBotDefInt::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, bool noskip)
|
CBotInstr* CBotDefInt::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, bool noskip, CBotTypResult vartype)
|
||||||
{
|
{
|
||||||
CBotToken* pp = cont ? nullptr : p; // no repetition of the token "int"
|
CBotToken* pp = cont ? nullptr : p; // no repetition of the token "int"
|
||||||
|
|
||||||
if (!cont && !IsOfType(p, ID_INT)) return nullptr;
|
if (!cont)
|
||||||
|
{
|
||||||
|
switch (p->GetType())
|
||||||
|
{
|
||||||
|
case ID_BYTE: vartype.SetType(CBotTypByte ); break;
|
||||||
|
case ID_SHORT: vartype.SetType(CBotTypShort); break;
|
||||||
|
case ID_CHAR: vartype.SetType(CBotTypChar ); break;
|
||||||
|
case ID_INT: vartype.SetType(CBotTypInt ); break;
|
||||||
|
case ID_LONG: vartype.SetType(CBotTypLong ); break;
|
||||||
|
default: return nullptr;
|
||||||
|
}
|
||||||
|
p = p->GetNext();
|
||||||
|
}
|
||||||
|
|
||||||
CBotDefInt* inst = static_cast<CBotDefInt*>(CompileArray(p, pStack, CBotTypInt));
|
CBotDefInt* inst = static_cast<CBotDefInt*>(CompileArray(p, pStack, vartype));
|
||||||
if (inst != nullptr || !pStack->IsOk()) return inst;
|
if (inst != nullptr || !pStack->IsOk()) return inst;
|
||||||
|
|
||||||
CBotCStack* pStk = pStack->TokenStack(pp);
|
CBotCStack* pStk = pStack->TokenStack(pp);
|
||||||
|
@ -68,7 +80,7 @@ CBotInstr* CBotDefInt::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, boo
|
||||||
// determines the expression is valid for the item on the left side
|
// determines the expression is valid for the item on the left side
|
||||||
if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )))
|
if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )))
|
||||||
{
|
{
|
||||||
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = CBotTypInt;
|
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_typevar = vartype;
|
||||||
if (pStk->CheckVarLocal(vartoken)) // redefinition of the variable
|
if (pStk->CheckVarLocal(vartoken)) // redefinition of the variable
|
||||||
{
|
{
|
||||||
pStk->SetError(CBotErrRedefVar, vartoken);
|
pStk->SetError(CBotErrRedefVar, vartoken);
|
||||||
|
@ -82,27 +94,20 @@ CBotInstr* CBotDefInt::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, boo
|
||||||
|
|
||||||
// compiles an array declaration
|
// compiles an array declaration
|
||||||
|
|
||||||
CBotInstr* inst2 = CBotDefArray::Compile(p, pStk, CBotTypInt);
|
CBotInstr* inst2 = CBotDefArray::Compile(p, pStk, vartype);
|
||||||
|
|
||||||
if (!pStk->IsOk() )
|
|
||||||
{
|
|
||||||
pStk->SetError(CBotErrCloseIndex, p->GetStart());
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsOfType(p, ID_COMMA)) // several definition chained
|
|
||||||
{
|
|
||||||
if (nullptr != ( inst2->m_next2b = CBotDefInt::Compile(p, pStk, true, noskip))) // compile the next one
|
|
||||||
{
|
|
||||||
return pStack->Return(inst2, pStk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inst = static_cast<CBotDefInt*>(inst2);
|
inst = static_cast<CBotDefInt*>(inst2);
|
||||||
goto suite; // no assignment, variable already created
|
goto suite; // no assignment, variable already created
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsOfType(p, ID_ASS)) // with an assignment?
|
if (IsOfType(p, ID_ASS)) // with an assignment?
|
||||||
{
|
{
|
||||||
|
pStk->SetStartError(p->GetStart());
|
||||||
|
if ( IsOfType(p, ID_SEP) )
|
||||||
|
{
|
||||||
|
pStk->SetError(CBotErrNoExpression, p->GetStart());
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
if (nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )))
|
if (nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )))
|
||||||
{
|
{
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -115,21 +120,21 @@ CBotInstr* CBotDefInt::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, boo
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
CBotVar* var = CBotVar::Create(*vartoken, CBotTypInt);// create the variable (evaluated after the assignment)
|
CBotVar* var = CBotVar::Create(*vartoken, vartype); // create the variable (evaluated after the assignment)
|
||||||
var->SetInit(inst->m_expr != nullptr ? CBotVar::InitType::DEF : CBotVar::InitType::UNDEF); // if initialized with assignment
|
var->SetInit(inst->m_expr != nullptr ? CBotVar::InitType::DEF : CBotVar::InitType::UNDEF); // if initialized with assignment
|
||||||
var->SetUniqNum( //set it with a unique number
|
var->SetUniqNum( //set it with a unique number
|
||||||
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
|
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
|
||||||
pStack->AddVar(var); // place it on the stack
|
pStack->AddVar(var); // place it on the stack
|
||||||
}
|
}
|
||||||
|
suite:
|
||||||
if (IsOfType(p, ID_COMMA)) // chained several definitions
|
if (pStk->IsOk() && IsOfType(p, ID_COMMA)) // chained several definitions
|
||||||
{
|
{
|
||||||
if (nullptr != ( inst->m_next2b = CBotDefInt::Compile(p, pStk, true, noskip))) // compile next one
|
if (nullptr != ( inst->m_next2b = CBotDefInt::Compile(p, pStk, true, noskip, vartype))) // compile next one
|
||||||
{
|
{
|
||||||
return pStack->Return(inst, pStk);
|
return pStack->Return(inst, pStk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
suite:
|
|
||||||
if (noskip || IsOfType(p, ID_SEP)) // instruction is completed
|
if (noskip || IsOfType(p, ID_SEP)) // instruction is completed
|
||||||
{
|
{
|
||||||
return pStack->Return(inst, pStk);
|
return pStack->Return(inst, pStk);
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -41,7 +41,7 @@ public:
|
||||||
* \param noskip
|
* \param noskip
|
||||||
* \return
|
* \return
|
||||||
*/
|
*/
|
||||||
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool cont = false, bool noskip = false);
|
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool cont = false, bool noskip = false, CBotTypResult vartype = CBotTypInt);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Execute Execute the definition of the integer variable.
|
* \brief Execute Execute the definition of the integer variable.
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -20,6 +20,7 @@
|
||||||
#include "CBot/CBotInstr/CBotDefString.h"
|
#include "CBot/CBotInstr/CBotDefString.h"
|
||||||
|
|
||||||
#include "CBot/CBotInstr/CBotLeftExprVar.h"
|
#include "CBot/CBotInstr/CBotLeftExprVar.h"
|
||||||
|
#include "CBot/CBotInstr/CBotDefArray.h"
|
||||||
#include "CBot/CBotInstr/CBotTwoOpExpr.h"
|
#include "CBot/CBotInstr/CBotTwoOpExpr.h"
|
||||||
|
|
||||||
#include "CBot/CBotStack.h"
|
#include "CBot/CBotStack.h"
|
||||||
|
@ -61,6 +62,7 @@ CBotInstr* CBotDefString::Compile(CBotToken* &p, CBotCStack* pStack, bool cont,
|
||||||
inst->m_expr = nullptr;
|
inst->m_expr = nullptr;
|
||||||
|
|
||||||
CBotToken* vartoken = p;
|
CBotToken* vartoken = p;
|
||||||
|
CBotVar* var = nullptr;
|
||||||
inst->SetToken(vartoken);
|
inst->SetToken(vartoken);
|
||||||
|
|
||||||
if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )))
|
if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk )))
|
||||||
|
@ -73,8 +75,27 @@ CBotInstr* CBotDefString::Compile(CBotToken* &p, CBotCStack* pStack, bool cont,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsOfType(p, ID_OPBRK))
|
||||||
|
{
|
||||||
|
delete inst; // type is not CBotDefString
|
||||||
|
p = vartoken; // returns the variable name
|
||||||
|
|
||||||
|
// compiles an array declaration
|
||||||
|
|
||||||
|
CBotInstr* inst2 = CBotDefArray::Compile(p, pStk, CBotTypString);
|
||||||
|
|
||||||
|
inst = static_cast<CBotDefString*>(inst2);
|
||||||
|
goto suite; // no assignment, variable already created
|
||||||
|
}
|
||||||
|
|
||||||
if (IsOfType(p, ID_ASS))
|
if (IsOfType(p, ID_ASS))
|
||||||
{
|
{
|
||||||
|
pStk->SetStartError(p->GetStart());
|
||||||
|
if ( IsOfType(p, ID_SEP) )
|
||||||
|
{
|
||||||
|
pStk->SetError(CBotErrNoExpression, p->GetStart());
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
if (nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )))
|
if (nullptr == ( inst->m_expr = CBotTwoOpExpr::Compile( p, pStk )))
|
||||||
{
|
{
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -86,13 +107,13 @@ CBotInstr* CBotDefString::Compile(CBotToken* &p, CBotCStack* pStack, bool cont,
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
CBotVar* var = CBotVar::Create(*vartoken, CBotTypString);
|
var = CBotVar::Create(*vartoken, CBotTypString);
|
||||||
var->SetInit(inst->m_expr != nullptr ? CBotVar::InitType::DEF : CBotVar::InitType::UNDEF);
|
var->SetInit(inst->m_expr != nullptr ? CBotVar::InitType::DEF : CBotVar::InitType::UNDEF);
|
||||||
var->SetUniqNum(
|
var->SetUniqNum(
|
||||||
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
|
(static_cast<CBotLeftExprVar*>(inst->m_var))->m_nIdent = CBotVar::NextUniqNum());
|
||||||
pStack->AddVar(var);
|
pStack->AddVar(var);
|
||||||
|
suite:
|
||||||
if (IsOfType(p, ID_COMMA))
|
if (pStk->IsOk() && IsOfType(p, ID_COMMA))
|
||||||
{
|
{
|
||||||
if (nullptr != ( inst->m_next2b = CBotDefString::Compile(p, pStk, true, noskip)))
|
if (nullptr != ( inst->m_next2b = CBotDefString::Compile(p, pStk, true, noskip)))
|
||||||
{
|
{
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -57,7 +57,7 @@ CBotInstr* CBotDo::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
inst->SetToken(p);
|
inst->SetToken(p);
|
||||||
if (!IsOfType(p, ID_DO)) return nullptr; // should never happen
|
if (!IsOfType(p, ID_DO)) return nullptr; // should never happen
|
||||||
|
|
||||||
CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp
|
CBotCStack* pStk = pStack->TokenStack(pp); // some space for a stack, plz
|
||||||
|
|
||||||
|
|
||||||
// looking for a statement block after the do
|
// looking for a statement block after the do
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see http://gnu.org/licenses
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CBot/CBotInstr/CBotExprLitChar.h"
|
||||||
|
|
||||||
|
#include "CBot/CBotStack.h"
|
||||||
|
#include "CBot/CBotCStack.h"
|
||||||
|
|
||||||
|
#include "CBot/CBotVar/CBotVar.h"
|
||||||
|
|
||||||
|
namespace CBot
|
||||||
|
{
|
||||||
|
|
||||||
|
CBotExprLitChar::CBotExprLitChar()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CBotExprLitChar::~CBotExprLitChar()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CBotInstr* CBotExprLitChar::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
|
{
|
||||||
|
CBotCStack* pStk = pStack->TokenStack();
|
||||||
|
|
||||||
|
const auto& s = p->GetString();
|
||||||
|
|
||||||
|
auto it = s.cbegin();
|
||||||
|
if (++it != s.cend())
|
||||||
|
{
|
||||||
|
if (*it != '\'') // not empty quotes ?
|
||||||
|
{
|
||||||
|
uint32_t valchar = 0;
|
||||||
|
int pos = p->GetStart() + 1;
|
||||||
|
|
||||||
|
if (*it != '\\') valchar = *(it++); // not escape sequence ?
|
||||||
|
else if (++it != s.cend())
|
||||||
|
{
|
||||||
|
pStk->SetStartError(pos++);
|
||||||
|
unsigned char c = *(it++);
|
||||||
|
if (c == '\"' || c == '\'' || c == '\\') valchar = c;
|
||||||
|
else if (c == 'a') valchar = '\a'; // alert bell
|
||||||
|
else if (c == 'b') valchar = '\b'; // backspace
|
||||||
|
else if (c == 'f') valchar = '\f'; // form feed
|
||||||
|
else if (c == 'n') valchar = '\n'; // new line
|
||||||
|
else if (c == 'r') valchar = '\r'; // carriage return
|
||||||
|
else if (c == 't') valchar = '\t'; // horizontal tab
|
||||||
|
else if (c == 'v') valchar = '\v'; // vertical tab
|
||||||
|
else if (c == 'u' || c == 'U') // unicode escape
|
||||||
|
{
|
||||||
|
if (it != s.cend())
|
||||||
|
{
|
||||||
|
std::string hex = "";
|
||||||
|
size_t maxlen = (c == 'u') ? 4 : 8;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < maxlen; i++)
|
||||||
|
{
|
||||||
|
if (!CharInList(*it, "0123456789ABCDEFabcdef")) break;
|
||||||
|
++pos;
|
||||||
|
hex += *it;
|
||||||
|
if (++it == s.cend()) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxlen == hex.length()) // unicode character
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
valchar = std::stoi(hex, nullptr, 16);
|
||||||
|
if (0x10FFFF < valchar || (0xD7FF < valchar && valchar < 0xE000))
|
||||||
|
pStk->SetError(CBotErrUnicodeName, pos + 1);
|
||||||
|
}
|
||||||
|
catch (const std::out_of_range& e)
|
||||||
|
{
|
||||||
|
pStk->SetError(CBotErrHexRange, pos + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pStk->SetError(CBotErrHexDigits, pos + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pStk->SetError(CBotErrHexDigits, pos + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pStk->SetError(CBotErrBadEscape, pos + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it == s.cend() || *it != '\'')
|
||||||
|
pStk->SetError(CBotErrEndQuote, p);
|
||||||
|
|
||||||
|
if (pStk->IsOk())
|
||||||
|
{
|
||||||
|
CBotExprLitChar* inst = new CBotExprLitChar();
|
||||||
|
inst->m_valchar = valchar;
|
||||||
|
inst->SetToken(p);
|
||||||
|
p = p->GetNext();
|
||||||
|
|
||||||
|
CBotVar* var = CBotVar::Create("", CBotTypChar);
|
||||||
|
pStk->SetVar(var);
|
||||||
|
|
||||||
|
return pStack->Return(inst, pStk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pStk->SetError(CBotErrCharEmpty, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
pStk->SetError(CBotErrEndQuote, p);
|
||||||
|
return pStack->Return(nullptr, pStk);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBotExprLitChar::Execute(CBotStack* &pj)
|
||||||
|
{
|
||||||
|
CBotStack* pile = pj->AddStack(this);
|
||||||
|
|
||||||
|
if (pile->IfStep()) return false;
|
||||||
|
|
||||||
|
CBotVar* var = CBotVar::Create("", CBotTypChar);
|
||||||
|
|
||||||
|
var->SetValChar(m_valchar);
|
||||||
|
|
||||||
|
pile->SetVar(var);
|
||||||
|
|
||||||
|
return pj->Return(pile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBotExprLitChar::RestoreState(CBotStack* &pj, bool bMain)
|
||||||
|
{
|
||||||
|
if (bMain) pj->RestoreStack(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CBotExprLitChar::GetDebugData()
|
||||||
|
{
|
||||||
|
return m_token.GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace CBot
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -19,41 +19,44 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CBot/CBotVar/CBotVar.h"
|
#include "CBot/CBotInstr/CBotInstr.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace CBot
|
namespace CBot
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief CBotVar subclass for managing string values (::CBotTypString)
|
* \brief A character literal
|
||||||
|
* \verbatim 'a', '\n', '\t', '\uFFFD', '\U0000FFFD', etc. \endverbatim
|
||||||
*/
|
*/
|
||||||
class CBotVarString : public CBotVar
|
class CBotExprLitChar : public CBotInstr
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
CBotExprLitChar();
|
||||||
* \brief Constructor. Do not call directly, use CBotVar::Create()
|
~CBotExprLitChar();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Compile a character literal
|
||||||
*/
|
*/
|
||||||
CBotVarString(const CBotToken& name);
|
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
|
||||||
|
|
||||||
void SetValString(const std::string& val) override;
|
/*!
|
||||||
std::string GetValString() override;
|
* \brief Execute, returns the corresponding char.
|
||||||
|
*/
|
||||||
|
bool Execute(CBotStack* &pj) override;
|
||||||
|
|
||||||
void Copy(CBotVar* pSrc, bool bName = true) override;
|
/*!
|
||||||
|
* \brief RestoreState
|
||||||
|
*/
|
||||||
|
void RestoreState(CBotStack* &pj, bool bMain) override;
|
||||||
|
|
||||||
void Add(CBotVar* left, CBotVar* right) override;
|
protected:
|
||||||
|
virtual const std::string GetDebugName() override { return "CBotExprLitChar"; }
|
||||||
bool Lo(CBotVar* left, CBotVar* right) override;
|
virtual std::string GetDebugData() override;
|
||||||
bool Hi(CBotVar* left, CBotVar* right) override;
|
|
||||||
bool Ls(CBotVar* left, CBotVar* right) override;
|
|
||||||
bool Hs(CBotVar* left, CBotVar* right) override;
|
|
||||||
bool Eq(CBotVar* left, CBotVar* right) override;
|
|
||||||
bool Ne(CBotVar* left, CBotVar* right) override;
|
|
||||||
|
|
||||||
bool Save1State(FILE* pf) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! The value.
|
uint32_t m_valchar = 0;
|
||||||
std::string m_val;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CBot
|
} // namespace CBot
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -23,6 +23,8 @@
|
||||||
|
|
||||||
#include "CBot/CBotVar/CBotVar.h"
|
#include "CBot/CBotVar/CBotVar.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
namespace CBot
|
namespace CBot
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -41,9 +43,9 @@ bool CBotExprLitNan::Execute(CBotStack* &pj)
|
||||||
CBotStack* pile = pj->AddStack(this);
|
CBotStack* pile = pj->AddStack(this);
|
||||||
|
|
||||||
if (pile->IfStep()) return false;
|
if (pile->IfStep()) return false;
|
||||||
CBotVar* var = CBotVar::Create("", CBotTypInt);
|
CBotVar* var = CBotVar::Create("", CBotTypFloat);
|
||||||
|
|
||||||
var->SetInit(CBotVar::InitType::IS_NAN); // nan
|
var->SetValFloat(nanf(""));
|
||||||
pile->SetVar(var); // put on the stack
|
pile->SetVar(var); // put on the stack
|
||||||
return pj->Return(pile); // forward below
|
return pj->Return(pile); // forward below
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -0,0 +1,199 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see http://gnu.org/licenses
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CBot/CBotInstr/CBotExprLitNum.h"
|
||||||
|
#include "CBot/CBotStack.h"
|
||||||
|
|
||||||
|
#include "CBot/CBotCStack.h"
|
||||||
|
#include "CBot/CBotVar/CBotVar.h"
|
||||||
|
|
||||||
|
#include "CBot/CBotUtils.h"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
namespace CBot
|
||||||
|
{
|
||||||
|
|
||||||
|
template <>
|
||||||
|
CBotExprLitNum<int>::CBotExprLitNum(int val) : m_numtype(CBotTypInt), m_value(val)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
CBotExprLitNum<long>::CBotExprLitNum(long val) : m_numtype(CBotTypLong), m_value(val)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
CBotExprLitNum<float>::CBotExprLitNum(float val) : m_numtype(CBotTypFloat), m_value(val)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
CBotExprLitNum<double>::CBotExprLitNum(double val) : m_numtype(CBotTypDouble), m_value(val)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
CBotExprLitNum<T>::~CBotExprLitNum()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CBotInstr* CompileExprLitNum(CBotToken* &p, CBotCStack* pStack)
|
||||||
|
{
|
||||||
|
CBotCStack* pStk = pStack->TokenStack();
|
||||||
|
|
||||||
|
const auto& s = p->GetString();
|
||||||
|
|
||||||
|
CBotInstr* inst = nullptr;
|
||||||
|
CBotType numtype = CBotTypInt;
|
||||||
|
|
||||||
|
if (p->GetType() == TokenTypDef)
|
||||||
|
{
|
||||||
|
inst = new CBotExprLitNum<int>(static_cast<int>(p->GetKeywordId()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (s.find('.') != std::string::npos || ( s.find('x') == std::string::npos && ( s.find_first_of("eE") != std::string::npos ) ))
|
||||||
|
{
|
||||||
|
double val = GetNumFloat(s);
|
||||||
|
if (val > static_cast<double>(std::numeric_limits<float>::max()))
|
||||||
|
{
|
||||||
|
numtype = CBotTypDouble;
|
||||||
|
inst = new CBotExprLitNum<double>(val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
numtype = CBotTypFloat;
|
||||||
|
inst = new CBotExprLitNum<float>(static_cast<float>(val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
long val = GetNumInt(s);
|
||||||
|
if (val > std::numeric_limits<int>::max())
|
||||||
|
{
|
||||||
|
numtype = CBotTypLong;
|
||||||
|
inst = new CBotExprLitNum<long>(val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inst = new CBotExprLitNum<int>(static_cast<int>(val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inst->SetToken(p);
|
||||||
|
if (pStk->NextToken(p))
|
||||||
|
{
|
||||||
|
CBotVar* var = CBotVar::Create("", numtype);
|
||||||
|
pStk->SetVar(var);
|
||||||
|
|
||||||
|
return pStack->Return(inst, pStk);
|
||||||
|
}
|
||||||
|
delete inst;
|
||||||
|
return pStack->Return(nullptr, pStk);
|
||||||
|
}
|
||||||
|
|
||||||
|
CBotInstr* CompileSizeOf(CBotToken* &p, CBotCStack* pStack)
|
||||||
|
{
|
||||||
|
CBotToken* pp = p;
|
||||||
|
|
||||||
|
if (!IsOfType(p, TokenTypVar)) return nullptr;
|
||||||
|
if (pp->GetString() == "sizeof" && IsOfType(p, ID_OPENPAR))
|
||||||
|
{
|
||||||
|
CBotCStack* pStk = pStack->TokenStack();
|
||||||
|
|
||||||
|
int value;
|
||||||
|
|
||||||
|
if (IsOfType(p, ID_BYTE)) value = sizeof(signed char);
|
||||||
|
else if (IsOfType(p, ID_SHORT)) value = sizeof(short);
|
||||||
|
else if (IsOfType(p, ID_CHAR)) value = sizeof(uint32_t);
|
||||||
|
else if (IsOfType(p, ID_INT)) value = sizeof(int);
|
||||||
|
else if (IsOfType(p, ID_LONG)) value = sizeof(long);
|
||||||
|
else if (IsOfType(p, ID_FLOAT)) value = sizeof(float);
|
||||||
|
else if (IsOfType(p, ID_DOUBLE)) value = sizeof(double);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = pp;
|
||||||
|
return pStack->Return(nullptr, pStk);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsOfType(p, ID_CLOSEPAR))
|
||||||
|
{
|
||||||
|
auto inst = new CBotExprLitNum<int>(value);
|
||||||
|
inst->SetToken(pp);
|
||||||
|
|
||||||
|
CBotVar* var = CBotVar::Create("", CBotTypInt);
|
||||||
|
pStk->SetVar(var);
|
||||||
|
return pStack->Return(inst, pStk);
|
||||||
|
}
|
||||||
|
pStk->SetError(CBotErrClosePar, p->GetStart());
|
||||||
|
return pStack->Return(nullptr, pStk);
|
||||||
|
}
|
||||||
|
p = pp;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool CBotExprLitNum<T>::Execute(CBotStack* &pj)
|
||||||
|
{
|
||||||
|
CBotStack* pile = pj->AddStack(this);
|
||||||
|
|
||||||
|
if (pile->IfStep()) return false;
|
||||||
|
|
||||||
|
CBotVar* var = CBotVar::Create("", m_numtype);
|
||||||
|
|
||||||
|
if (m_token.GetType() == TokenTypDef)
|
||||||
|
{
|
||||||
|
var->SetValInt(m_value, m_token.GetString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*var = m_value;
|
||||||
|
}
|
||||||
|
pile->SetVar(var); // place on the stack
|
||||||
|
|
||||||
|
return pj->Return(pile); // it's ok
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void CBotExprLitNum<T>::RestoreState(CBotStack* &pj, bool bMain)
|
||||||
|
{
|
||||||
|
if (bMain) pj->RestoreStack(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::string CBotExprLitNum<T>::GetDebugData()
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
switch (m_numtype)
|
||||||
|
{
|
||||||
|
case CBotTypInt : ss << "(int) "; break;
|
||||||
|
case CBotTypLong : ss << "(long) "; break;
|
||||||
|
case CBotTypFloat : ss << "(float) "; break;
|
||||||
|
case CBotTypDouble: ss << "(double) "; break;
|
||||||
|
default: assert(false);
|
||||||
|
}
|
||||||
|
ss << m_value;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace CBot
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -24,25 +24,24 @@
|
||||||
namespace CBot
|
namespace CBot
|
||||||
{
|
{
|
||||||
|
|
||||||
|
CBotInstr* CompileExprLitNum(CBotToken* &p, CBotCStack* pStack);
|
||||||
|
|
||||||
|
CBotInstr* CompileSizeOf(CBotToken* &p, CBotCStack* pStack);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A number literal - 5, 1, 2.5, 3.75, etc. or a predefined numerical constant (see CBotToken::DefineNum())
|
* \brief A number literal - 5, 1, 2.5, 3.75, etc. or a predefined numerical constant (see CBotToken::DefineNum())
|
||||||
*
|
*
|
||||||
* Can be of type ::CBotTypInt or ::CBotTypFloat
|
* Can be of type ::CBotTypInt, ::CBotTypLong, ::CBotTypFloat, or ::CBotTypDouble
|
||||||
*/
|
*/
|
||||||
|
template <typename T>
|
||||||
class CBotExprLitNum : public CBotInstr
|
class CBotExprLitNum : public CBotInstr
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CBotExprLitNum();
|
// To keep linter happy, instead of = delete (see https://stackoverflow.com/a/37593094)
|
||||||
~CBotExprLitNum();
|
CBotExprLitNum(T val) { static_assert(sizeof(T) == 0, "Only specializations of CBotExprLitNum can be used"); };
|
||||||
|
|
||||||
/*!
|
~CBotExprLitNum();
|
||||||
* \brief Compile
|
|
||||||
* \param p
|
|
||||||
* \param pStack
|
|
||||||
* \return
|
|
||||||
*/
|
|
||||||
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Execute Execute, returns the corresponding number.
|
* \brief Execute Execute, returns the corresponding number.
|
||||||
|
@ -65,10 +64,8 @@ protected:
|
||||||
private:
|
private:
|
||||||
//! The type of number.
|
//! The type of number.
|
||||||
CBotType m_numtype;
|
CBotType m_numtype;
|
||||||
//! Value for an int.
|
//! Value
|
||||||
long m_valint;
|
T m_value;
|
||||||
//! Value for a float.
|
|
||||||
float m_valfloat;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,207 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see http://gnu.org/licenses
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CBot/CBotInstr/CBotExprLitString.h"
|
||||||
|
|
||||||
|
#include "CBot/CBotStack.h"
|
||||||
|
#include "CBot/CBotCStack.h"
|
||||||
|
|
||||||
|
#include "CBot/CBotVar/CBotVar.h"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace CBot
|
||||||
|
{
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
CBotExprLitString::CBotExprLitString()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
CBotExprLitString::~CBotExprLitString()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
CBotInstr* CBotExprLitString::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
|
{
|
||||||
|
CBotCStack* pStk = pStack->TokenStack();
|
||||||
|
|
||||||
|
const auto& s = p->GetString();
|
||||||
|
|
||||||
|
auto it = s.cbegin();
|
||||||
|
if (++it != s.cend())
|
||||||
|
{
|
||||||
|
int pos = p->GetStart();
|
||||||
|
std::string valstring = "";
|
||||||
|
while (it != s.cend() && *it != '\"')
|
||||||
|
{
|
||||||
|
++pos;
|
||||||
|
if (*it != '\\') // not escape sequence ?
|
||||||
|
{
|
||||||
|
valstring += *(it++);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++it == s.cend()) break;
|
||||||
|
pStk->SetStartError(pos);
|
||||||
|
|
||||||
|
if (CharInList(*it, "01234567")) // octal
|
||||||
|
{
|
||||||
|
std::string octal = "";
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (!CharInList(*it, "01234567")) break;
|
||||||
|
++pos;
|
||||||
|
octal += *it;
|
||||||
|
if (++it == s.cend()) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int val = std::stoi(octal, nullptr, 8);
|
||||||
|
if (val <= 255)
|
||||||
|
{
|
||||||
|
valstring.push_back(val);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pStk->SetError(CBotErrOctalRange, pos + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++pos;
|
||||||
|
unsigned char c = *(it++);
|
||||||
|
if (c == '\"' || c == '\'' || c == '\\') valstring += c;
|
||||||
|
else if (c == 'a') valstring += '\a'; // alert bell
|
||||||
|
else if (c == 'b') valstring += '\b'; // backspace
|
||||||
|
else if (c == 'f') valstring += '\f'; // form feed
|
||||||
|
else if (c == 'n') valstring += '\n'; // new line
|
||||||
|
else if (c == 'r') valstring += '\r'; // carriage return
|
||||||
|
else if (c == 't') valstring += '\t'; // horizontal tab
|
||||||
|
else if (c == 'v') valstring += '\v'; // vertical tab
|
||||||
|
else if (c == 'x' || c == 'u' || c == 'U') // hex or unicode
|
||||||
|
{
|
||||||
|
if (it != s.cend())
|
||||||
|
{
|
||||||
|
std::string hex = "";
|
||||||
|
bool isHexCode = (c == 'x');
|
||||||
|
size_t maxlen = (c == 'u') ? 4 : 8;
|
||||||
|
|
||||||
|
for (size_t i = 0; isHexCode || i < maxlen; i++)
|
||||||
|
{
|
||||||
|
if (!CharInList(*it, "0123456789ABCDEFabcdef")) break;
|
||||||
|
++pos;
|
||||||
|
hex += *it;
|
||||||
|
if (++it == s.cend()) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hex.empty())
|
||||||
|
{
|
||||||
|
unsigned int val = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
val = std::stoi(hex, nullptr, 16);
|
||||||
|
}
|
||||||
|
catch (const std::out_of_range& e)
|
||||||
|
{
|
||||||
|
pStk->SetError(CBotErrHexRange, pos + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pStk->IsOk())
|
||||||
|
{
|
||||||
|
if (isHexCode) // hexadecimal
|
||||||
|
{
|
||||||
|
if (val <= 255)
|
||||||
|
{
|
||||||
|
valstring.push_back(val);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pStk->SetError(CBotErrHexRange, pos + 1);
|
||||||
|
}
|
||||||
|
else if (maxlen == hex.length()) // unicode character
|
||||||
|
{
|
||||||
|
if (val < 0xD800 || (0xDFFF < val && val < 0x110000))
|
||||||
|
{
|
||||||
|
valstring += CodePointToUTF8(val);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pStk->SetError(CBotErrUnicodeName, pos + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pStk->SetError(CBotErrHexDigits, pos + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pStk->SetError(CBotErrBadEscape, pos + 1); // unknown escape code
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pStk->IsOk()) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it == s.cend() || *it != '\"')
|
||||||
|
pStk->SetError(CBotErrEndQuote, p);
|
||||||
|
|
||||||
|
if (pStk->IsOk())
|
||||||
|
{
|
||||||
|
CBotExprLitString* inst = new CBotExprLitString();
|
||||||
|
inst->m_valstring.swap(valstring);
|
||||||
|
inst->SetToken(p);
|
||||||
|
p = p->GetNext();
|
||||||
|
|
||||||
|
CBotVar* var = CBotVar::Create("", CBotTypString);
|
||||||
|
pStk->SetVar(var);
|
||||||
|
|
||||||
|
return pStack->Return(inst, pStk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pStk->SetError(CBotErrEndQuote, p);
|
||||||
|
return pStack->Return(nullptr, pStk);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool CBotExprLitString::Execute(CBotStack* &pj)
|
||||||
|
{
|
||||||
|
CBotStack* pile = pj->AddStack(this);
|
||||||
|
|
||||||
|
if (pile->IfStep()) return false;
|
||||||
|
|
||||||
|
CBotVar* var = CBotVar::Create("", CBotTypString);
|
||||||
|
|
||||||
|
var->SetValString(m_valstring);
|
||||||
|
|
||||||
|
pile->SetVar(var); // put on the stack
|
||||||
|
|
||||||
|
return pj->Return(pile);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void CBotExprLitString::RestoreState(CBotStack* &pj, bool bMain)
|
||||||
|
{
|
||||||
|
if (bMain) pj->RestoreStack(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CBotExprLitString::GetDebugData()
|
||||||
|
{
|
||||||
|
return m_token.GetString();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace CBot
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -58,6 +58,9 @@ public:
|
||||||
protected:
|
protected:
|
||||||
virtual const std::string GetDebugName() override { return "CBotExprLitString"; }
|
virtual const std::string GetDebugName() override { return "CBotExprLitString"; }
|
||||||
virtual std::string GetDebugData() override;
|
virtual std::string GetDebugData() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_valstring = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CBot
|
} // namespace CBot
|
|
@ -0,0 +1,209 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see http://gnu.org/licenses
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
#include "CBot/CBotInstr/CBotExprRetVar.h"
|
||||||
|
|
||||||
|
#include "CBot/CBotInstr/CBotExpression.h"
|
||||||
|
#include "CBot/CBotInstr/CBotInstrMethode.h"
|
||||||
|
#include "CBot/CBotInstr/CBotIndexExpr.h"
|
||||||
|
#include "CBot/CBotInstr/CBotFieldExpr.h"
|
||||||
|
|
||||||
|
#include "CBot/CBotStack.h"
|
||||||
|
|
||||||
|
namespace CBot
|
||||||
|
{
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
CBotExprRetVar::CBotExprRetVar()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
CBotExprRetVar::~CBotExprRetVar()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
CBotInstr* CBotExprRetVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bMethodsOnly)
|
||||||
|
{
|
||||||
|
if (p->GetType() == ID_DOT)
|
||||||
|
{
|
||||||
|
CBotVar* var = pStack->GetVar();
|
||||||
|
|
||||||
|
if (var == nullptr) return nullptr;
|
||||||
|
|
||||||
|
CBotCStack* pStk = pStack->TokenStack();
|
||||||
|
CBotInstr* inst = new CBotExprRetVar();
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
pStk->SetStartError(p->GetStart());
|
||||||
|
if (var->GetType() == CBotTypArrayPointer)
|
||||||
|
{
|
||||||
|
if (bMethodsOnly) goto err;
|
||||||
|
|
||||||
|
if (IsOfType( p, ID_OPBRK ))
|
||||||
|
{
|
||||||
|
CBotIndexExpr* i = new CBotIndexExpr();
|
||||||
|
i->m_expr = CBotExpression::Compile(p, pStk);
|
||||||
|
inst->AddNext3(i);
|
||||||
|
|
||||||
|
var = var->GetItem(0,true);
|
||||||
|
|
||||||
|
if (i->m_expr == nullptr || pStk->GetType() != CBotTypInt)
|
||||||
|
{
|
||||||
|
pStk->SetError(CBotErrBadIndex, p->GetStart());
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (!pStk->IsOk() || !IsOfType( p, ID_CLBRK ))
|
||||||
|
{
|
||||||
|
pStk->SetError(CBotErrCloseIndex, p->GetStart());
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (var->GetType(CBotVar::GetTypeMode::CLASS_AS_POINTER) == CBotTypPointer)
|
||||||
|
{
|
||||||
|
if (IsOfType(p, ID_DOT))
|
||||||
|
{
|
||||||
|
CBotToken* pp = p;
|
||||||
|
|
||||||
|
if (p->GetType() == TokenTypVar)
|
||||||
|
{
|
||||||
|
if (p->GetNext()->GetType() == ID_OPENPAR)
|
||||||
|
{
|
||||||
|
CBotInstr* i = CBotInstrMethode::Compile(p, pStk, var, bMethodsOnly);
|
||||||
|
if (!pStk->IsOk()) goto err;
|
||||||
|
inst->AddNext3(i);
|
||||||
|
return pStack->Return(inst, pStk);
|
||||||
|
}
|
||||||
|
else if (bMethodsOnly)
|
||||||
|
{
|
||||||
|
p = p->GetPrev();
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CBotFieldExpr* i = new CBotFieldExpr();
|
||||||
|
i->SetToken(pp);
|
||||||
|
inst->AddNext3(i);
|
||||||
|
CBotVar* preVar = var;
|
||||||
|
var = var->GetItem(p->GetString());
|
||||||
|
if (var != nullptr)
|
||||||
|
{
|
||||||
|
i->SetUniqNum(var->GetUniqNum());
|
||||||
|
if (CBotFieldExpr::CheckProtectionError(pStk, preVar, var))
|
||||||
|
{
|
||||||
|
pStk->SetError(CBotErrPrivate, pp);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var != nullptr)
|
||||||
|
{
|
||||||
|
p = p->GetNext();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pStk->SetError(CBotErrUndefItem, p);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
pStk->SetError(CBotErrUndefClass, p);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pStk->SetCopyVar(var);
|
||||||
|
if (pStk->IsOk()) return pStack->Return(inst, pStk);
|
||||||
|
|
||||||
|
pStk->SetError(CBotErrUndefVar, p);
|
||||||
|
err:
|
||||||
|
delete inst;
|
||||||
|
return pStack->Return(nullptr, pStk);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool CBotExprRetVar::Execute(CBotStack* &pj)
|
||||||
|
{
|
||||||
|
|
||||||
|
CBotStack* pile = pj->AddStack();
|
||||||
|
CBotStack* pile1 = pile;
|
||||||
|
CBotVar* pVar;
|
||||||
|
|
||||||
|
if (pile1->GetState() == 0)
|
||||||
|
{
|
||||||
|
pVar = pj->GetVar();
|
||||||
|
pVar->Update(pj->GetUserPtr());
|
||||||
|
if (pVar->GetType(CBotVar::GetTypeMode::CLASS_AS_POINTER) == CBotTypNullPointer)
|
||||||
|
{
|
||||||
|
pile1->SetError(CBotErrNull, &m_token);
|
||||||
|
return pj->Return(pile1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !m_next3->ExecuteVar(pVar, pile, &m_token, true, false) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (pVar)
|
||||||
|
pile1->SetCopyVar(pVar);
|
||||||
|
else
|
||||||
|
return pj->Return(pile1);
|
||||||
|
|
||||||
|
pile1->IncState();
|
||||||
|
}
|
||||||
|
pVar = pile1->GetVar();
|
||||||
|
|
||||||
|
if (pVar == nullptr)
|
||||||
|
{
|
||||||
|
return pj->Return(pile1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pVar->IsUndefined())
|
||||||
|
{
|
||||||
|
pile1->SetError(CBotErrNotInit, &m_token);
|
||||||
|
return pj->Return(pile1);
|
||||||
|
}
|
||||||
|
return pj->Return(pile1);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void CBotExprRetVar::RestoreState(CBotStack* &pj, bool bMain)
|
||||||
|
{
|
||||||
|
if (!bMain) return;
|
||||||
|
|
||||||
|
CBotStack* pile = pj->RestoreStack();
|
||||||
|
if ( pile == nullptr ) return;
|
||||||
|
|
||||||
|
if (pile->GetState() == 0)
|
||||||
|
m_next3->RestoreStateVar(pile, bMain);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string CBotExprRetVar::GetDebugData()
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << m_token.GetString() << "func(...).something" << std::endl;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace CBot
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see http://gnu.org/licenses
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CBot/CBotInstr/CBotInstr.h"
|
||||||
|
|
||||||
|
namespace CBot
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Access a member/element of the variable on the stack
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class CBotExprRetVar : public CBotInstr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CBotExprRetVar();
|
||||||
|
~CBotExprRetVar();
|
||||||
|
|
||||||
|
static CBotInstr* Compile(CBotToken*& p, CBotCStack* pStack, bool bMethodsOnly = false);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Execute
|
||||||
|
* \param pj
|
||||||
|
* \return
|
||||||
|
*/
|
||||||
|
bool Execute(CBotStack* &pj) override;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief RestoreState
|
||||||
|
* \param pj
|
||||||
|
* \param bMain
|
||||||
|
*/
|
||||||
|
void RestoreState(CBotStack* &pj, bool bMain) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual const std::string GetDebugName() override { return "CBotExprRetVar"; }
|
||||||
|
virtual std::string GetDebugData() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace CBot
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -40,8 +40,7 @@ CBotExprUnaire::~CBotExprUnaire()
|
||||||
delete m_expr;
|
delete m_expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
CBotInstr* CBotExprUnaire::Compile(CBotToken* &p, CBotCStack* pStack, bool bLiteral, bool bConstExpr)
|
||||||
CBotInstr* CBotExprUnaire::Compile(CBotToken* &p, CBotCStack* pStack)
|
|
||||||
{
|
{
|
||||||
int op = p->GetType();
|
int op = p->GetType();
|
||||||
CBotToken* pp = p;
|
CBotToken* pp = p;
|
||||||
|
@ -52,7 +51,12 @@ CBotInstr* CBotExprUnaire::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
CBotExprUnaire* inst = new CBotExprUnaire();
|
CBotExprUnaire* inst = new CBotExprUnaire();
|
||||||
inst->SetToken(pp);
|
inst->SetToken(pp);
|
||||||
|
|
||||||
if (nullptr != (inst->m_expr = CBotParExpr::Compile(p, pStk )))
|
if (bConstExpr || !bLiteral)
|
||||||
|
inst->m_expr = CBotParExpr::Compile(p, pStk, bConstExpr);
|
||||||
|
else
|
||||||
|
inst->m_expr = CBotParExpr::CompileLitExpr(p, pStk);
|
||||||
|
|
||||||
|
if (inst->m_expr != nullptr)
|
||||||
{
|
{
|
||||||
if (op == ID_ADD && pStk->GetType() < CBotTypBoolean) // only with the number
|
if (op == ID_ADD && pStk->GetType() < CBotTypBoolean) // only with the number
|
||||||
return pStack->Return(inst, pStk);
|
return pStack->Return(inst, pStk);
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -34,12 +34,13 @@ public:
|
||||||
~CBotExprUnaire();
|
~CBotExprUnaire();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Compile
|
* \brief Compile an expression with a unary operator
|
||||||
* \param p
|
* \param p[in, out] Pointer to first token of the expression, will be updated to point to first token after the expression
|
||||||
* \param pStack
|
* \param pStack Current compilation stack frame
|
||||||
* \return
|
* \param bLiteral If true, compiles only literal expressions Ex: ~11, -4.0, !false, not true
|
||||||
|
* \return The compiled instruction or nullptr
|
||||||
*/
|
*/
|
||||||
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack);
|
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool bLiteral = false, bool bConstExpr = false);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Execute
|
* \brief Execute
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -44,7 +44,7 @@ CBotExprVar::~CBotExprVar()
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, CBotVar::ProtectionLevel privat)
|
CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, bool bCheckReadOnly)
|
||||||
{
|
{
|
||||||
// CBotToken* pDebut = p;
|
// CBotToken* pDebut = p;
|
||||||
CBotCStack* pStk = pStack->TokenStack();
|
CBotCStack* pStk = pStack->TokenStack();
|
||||||
|
@ -67,8 +67,7 @@ CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, CBotVar::Prot
|
||||||
|
|
||||||
if (ident > 0 && ident < 9000)
|
if (ident > 0 && ident < 9000)
|
||||||
{
|
{
|
||||||
if ( var->IsPrivate(privat) &&
|
if (CBotFieldExpr::CheckProtectionError(pStk, nullptr, var, bCheckReadOnly))
|
||||||
!pStk->GetProgram()->m_bCompileClass)
|
|
||||||
{
|
{
|
||||||
pStk->SetError(CBotErrPrivate, p);
|
pStk->SetError(CBotErrPrivate, p);
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -77,6 +76,8 @@ CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, CBotVar::Prot
|
||||||
// This is an element of the current class
|
// This is an element of the current class
|
||||||
// ads the equivalent of this. before
|
// ads the equivalent of this. before
|
||||||
CBotToken token("this");
|
CBotToken token("this");
|
||||||
|
// invisible 'this.' highlights member token on error
|
||||||
|
token.SetPos(p->GetStart(), p->GetEnd());
|
||||||
inst->SetToken(&token);
|
inst->SetToken(&token);
|
||||||
(static_cast<CBotExprVar*>(inst))->m_nIdent = -2; // identificator for this
|
(static_cast<CBotExprVar*>(inst))->m_nIdent = -2; // identificator for this
|
||||||
|
|
||||||
|
@ -123,6 +124,8 @@ CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, CBotVar::Prot
|
||||||
{
|
{
|
||||||
if (p->GetNext()->GetType() == ID_OPENPAR) // a method call?
|
if (p->GetNext()->GetType() == ID_OPENPAR) // a method call?
|
||||||
{
|
{
|
||||||
|
if (bCheckReadOnly) goto err; // don't allow increment a method call "++"
|
||||||
|
|
||||||
CBotInstr* i = CBotInstrMethode::Compile(p, pStk, var);
|
CBotInstr* i = CBotInstrMethode::Compile(p, pStk, var);
|
||||||
if (!pStk->IsOk()) goto err;
|
if (!pStk->IsOk()) goto err;
|
||||||
inst->AddNext3(i); // added after
|
inst->AddNext3(i); // added after
|
||||||
|
@ -133,12 +136,12 @@ CBotInstr* CBotExprVar::Compile(CBotToken*& p, CBotCStack* pStack, CBotVar::Prot
|
||||||
CBotFieldExpr* i = new CBotFieldExpr(); // new element
|
CBotFieldExpr* i = new CBotFieldExpr(); // new element
|
||||||
i->SetToken(pp); // keeps the name of the token
|
i->SetToken(pp); // keeps the name of the token
|
||||||
inst->AddNext3(i); // add after
|
inst->AddNext3(i); // add after
|
||||||
|
CBotVar* preVar = var;
|
||||||
var = var->GetItem(p->GetString()); // get item correspondent
|
var = var->GetItem(p->GetString()); // get item correspondent
|
||||||
if (var != nullptr)
|
if (var != nullptr)
|
||||||
{
|
{
|
||||||
i->SetUniqNum(var->GetUniqNum());
|
i->SetUniqNum(var->GetUniqNum());
|
||||||
if ( var->IsPrivate() &&
|
if (CBotFieldExpr::CheckProtectionError(pStk, preVar, var, bCheckReadOnly))
|
||||||
!pStk->GetProgram()->m_bCompileClass)
|
|
||||||
{
|
{
|
||||||
pStk->SetError(CBotErrPrivate, pp);
|
pStk->SetError(CBotErrPrivate, pp);
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -195,6 +198,8 @@ CBotInstr* CBotExprVar::CompileMethode(CBotToken* &p, CBotCStack* pStack)
|
||||||
// this is an element of the current class
|
// this is an element of the current class
|
||||||
// adds the equivalent of this. before
|
// adds the equivalent of this. before
|
||||||
|
|
||||||
|
// invisible 'this.' highlights member token on error
|
||||||
|
pthis.SetPos(pp->GetStart(), pp->GetEnd());
|
||||||
inst->SetToken(&pthis);
|
inst->SetToken(&pthis);
|
||||||
(static_cast<CBotExprVar*>(inst))->m_nIdent = -2; // ident for this
|
(static_cast<CBotExprVar*>(inst))->m_nIdent = -2; // ident for this
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -40,14 +40,13 @@ public:
|
||||||
~CBotExprVar();
|
~CBotExprVar();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Compile
|
* \brief Compile an expression of a variable, possibly chained with index operators and/or dot operators
|
||||||
* \param p
|
* \param p[in, out] Pointer to first token of the expression, will be updated to point to first token after the expression
|
||||||
* \param pStack
|
* \param pStack Current compilation stack frame
|
||||||
* \param privat
|
* \param bCheckReadOnly True for operations that would modify the value of the variable
|
||||||
* \return
|
* \return
|
||||||
*/
|
*/
|
||||||
static CBotInstr* Compile(CBotToken*& p, CBotCStack* pStack,
|
static CBotInstr* Compile(CBotToken*& p, CBotCStack* pStack, bool bCheckReadOnly = false);
|
||||||
CBotVar::ProtectionLevel privat = CBotVar::ProtectionLevel::Protected);
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief CompileMethode
|
* \brief CompileMethode
|
||||||
|
@ -81,6 +80,8 @@ public:
|
||||||
*/
|
*/
|
||||||
bool ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, bool bStep);
|
bool ExecuteVar(CBotVar* &pVar, CBotStack* &pile, CBotToken* prevToken, bool bStep);
|
||||||
|
|
||||||
|
using CBotInstr::ExecuteVar;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief RestoreStateVar Fetch variable at runtime.
|
* \brief RestoreStateVar Fetch variable at runtime.
|
||||||
* \param pj
|
* \param pj
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -71,6 +71,13 @@ CBotInstr* CBotExpression::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( p->GetType() == ID_SEP )
|
||||||
|
{
|
||||||
|
pStack->SetError(CBotErrNoExpression, p);
|
||||||
|
delete inst;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
inst->m_rightop = CBotExpression::Compile(p, pStack);
|
inst->m_rightop = CBotExpression::Compile(p, pStack);
|
||||||
if (inst->m_rightop == nullptr)
|
if (inst->m_rightop == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -118,13 +125,13 @@ CBotInstr* CBotExpression::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
break;
|
break;
|
||||||
case ID_ASSADD:
|
case ID_ASSADD:
|
||||||
if (type2.Eq(CBotTypBoolean) ||
|
if (type2.Eq(CBotTypBoolean) ||
|
||||||
type2.Eq(CBotTypPointer) ) type2 = -1; // numbers and strings
|
type2.GetType() > CBotTypString ) type2.SetType(-1); // numbers and strings
|
||||||
break;
|
break;
|
||||||
case ID_ASSSUB:
|
case ID_ASSSUB:
|
||||||
case ID_ASSMUL:
|
case ID_ASSMUL:
|
||||||
case ID_ASSDIV:
|
case ID_ASSDIV:
|
||||||
case ID_ASSMODULO:
|
case ID_ASSMODULO:
|
||||||
if (type2.GetType() >= CBotTypBoolean) type2 = -1; // numbers only
|
if (type2.GetType() >= CBotTypBoolean) type2.SetType(-1); // numbers only
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,6 +186,18 @@ bool CBotExpression::Execute(CBotStack* &pj)
|
||||||
if ( pile2->GetState()==0)
|
if ( pile2->GetState()==0)
|
||||||
{
|
{
|
||||||
if (m_rightop && !m_rightop->Execute(pile2)) return false; // initial value // interrupted?
|
if (m_rightop && !m_rightop->Execute(pile2)) return false; // initial value // interrupted?
|
||||||
|
if (m_rightop)
|
||||||
|
{
|
||||||
|
CBotVar* var = pile1->GetVar();
|
||||||
|
CBotVar* value = pile2->GetVar();
|
||||||
|
if (var->GetType() == CBotTypString && value->GetType() != CBotTypString)
|
||||||
|
{
|
||||||
|
CBotVar* newVal = CBotVar::Create("", var->GetTypResult());
|
||||||
|
value->Update(pj->GetUserPtr());
|
||||||
|
newVal->SetValString(value->GetValString());
|
||||||
|
pile2->SetVar(newVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
pile2->IncState();
|
pile2->IncState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,12 +206,6 @@ bool CBotExpression::Execute(CBotStack* &pj)
|
||||||
if (m_token.GetType() != ID_ASS)
|
if (m_token.GetType() != ID_ASS)
|
||||||
{
|
{
|
||||||
pVar = pile1->GetVar(); // recovers if interrupted
|
pVar = pile1->GetVar(); // recovers if interrupted
|
||||||
initKind = pVar->GetInit();
|
|
||||||
if (initKind == CBotVar::InitType::IS_NAN)
|
|
||||||
{
|
|
||||||
pile2->SetError(CBotErrNan, m_leftop->GetToken());
|
|
||||||
return pj->Return(pile2);
|
|
||||||
}
|
|
||||||
result = CBotVar::Create("", pVar->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC));
|
result = CBotVar::Create("", pVar->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -134,4 +134,56 @@ std::string CBotFieldExpr::GetDebugData()
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool CBotFieldExpr::CheckProtectionError(CBotCStack* pStack, CBotVar* pPrev, CBotVar* pVar, bool bCheckReadOnly)
|
||||||
|
{
|
||||||
|
CBotVar::ProtectionLevel varPriv = pVar->GetPrivate();
|
||||||
|
|
||||||
|
if (bCheckReadOnly && varPriv == CBotVar::ProtectionLevel::ReadOnly)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (varPriv == CBotVar::ProtectionLevel::Public) return false;
|
||||||
|
|
||||||
|
std::string prevName = (pPrev == nullptr) ? "" : pPrev->GetName();
|
||||||
|
|
||||||
|
// implicit 'this.'var, this.var, or super.var
|
||||||
|
if (pPrev == nullptr || prevName == "this" || prevName == "super") // member of the current class
|
||||||
|
{
|
||||||
|
if (varPriv == CBotVar::ProtectionLevel::Private) // var is private ?
|
||||||
|
{
|
||||||
|
CBotToken token("this");
|
||||||
|
CBotVar* pThis = pStack->FindVar(token);
|
||||||
|
CBotClass* pClass = pThis->GetClass(); // the current class
|
||||||
|
|
||||||
|
CBotVar* pVarList = pClass->GetVar();
|
||||||
|
|
||||||
|
int ident = pVar->GetUniqNum();
|
||||||
|
// check if var is inherited from a parent class
|
||||||
|
if (pVarList == nullptr || ident < pVarList->GetUniqNum())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // any other context
|
||||||
|
{
|
||||||
|
if (pVar->IsPrivate()) // var is protected or private ?
|
||||||
|
{
|
||||||
|
CBotToken token("this");
|
||||||
|
CBotVar* pThis = pStack->FindVar(token);
|
||||||
|
|
||||||
|
if (pThis == nullptr) return true; // inside a function ?
|
||||||
|
if (pThis->GetType() != CBotTypPointer) return true;
|
||||||
|
|
||||||
|
CBotClass* pClass = pThis->GetClass(); // the current class
|
||||||
|
|
||||||
|
if (!pClass->IsChildOf(pPrev->GetClass())) // var is member of some other class ?
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (varPriv == CBotVar::ProtectionLevel::Private && // private member of a parent class
|
||||||
|
pClass != pPrev->GetClass()) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace CBot
|
} // namespace CBot
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -65,6 +65,20 @@ public:
|
||||||
*/
|
*/
|
||||||
void RestoreStateVar(CBotStack* &pj, bool bMain) override;
|
void RestoreStateVar(CBotStack* &pj, bool bMain) override;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Check if access to a variable is allowed or not depending on public/private/protected setting
|
||||||
|
*
|
||||||
|
* If this function returns true, the caller is responsible for failing the compilation with ::CBotErrPrivate error.
|
||||||
|
* This function doesn't set the error flag itself.
|
||||||
|
*
|
||||||
|
* \param pStack Current compilation stack frame
|
||||||
|
* \param pPrev Class instance which variable to check is part of, or nullptr when compiler inserts 'this.' before
|
||||||
|
* \param pVar Variable to check
|
||||||
|
* \param bCheckReadOnly True for operations that would modify the value of the variable
|
||||||
|
* \return true if pVar is inaccessible in the current context, false if access should be allowed
|
||||||
|
*/
|
||||||
|
static bool CheckProtectionError(CBotCStack* pStack, CBotVar* pPrev, CBotVar* pVar, bool bCheckReadOnly = false);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual const std::string GetDebugName() override { return "CBotFieldExpr"; }
|
virtual const std::string GetDebugName() override { return "CBotFieldExpr"; }
|
||||||
virtual std::string GetDebugData() override;
|
virtual std::string GetDebugData() override;
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -67,7 +67,7 @@ CBotInstr* CBotFor::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CBotCStack* pStk = pStack->TokenStack(pp, true); // un petit bout de pile svp
|
CBotCStack* pStk = pStack->TokenStack(pp, true); // some size for a stack, plz
|
||||||
|
|
||||||
// compiles instructions for initialization
|
// compiles instructions for initialization
|
||||||
inst->m_init = CBotListExpression::Compile(p, pStk );
|
inst->m_init = CBotListExpression::Compile(p, pStk );
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -46,7 +46,6 @@ CBotFunction::CBotFunction()
|
||||||
{
|
{
|
||||||
m_param = nullptr; // empty parameter list
|
m_param = nullptr; // empty parameter list
|
||||||
m_block = nullptr; // the instruction block
|
m_block = nullptr; // the instruction block
|
||||||
m_next = nullptr; // functions can be chained
|
|
||||||
m_bPublic = false; // function not public
|
m_bPublic = false; // function not public
|
||||||
m_bExtern = false; // function not extern
|
m_bExtern = false; // function not extern
|
||||||
m_pProg = nullptr;
|
m_pProg = nullptr;
|
||||||
|
@ -63,7 +62,6 @@ CBotFunction::~CBotFunction()
|
||||||
{
|
{
|
||||||
delete m_param; // empty parameter list
|
delete m_param; // empty parameter list
|
||||||
delete m_block; // the instruction block
|
delete m_block; // the instruction block
|
||||||
delete m_next;
|
|
||||||
|
|
||||||
// remove public list if there is
|
// remove public list if there is
|
||||||
if (m_bPublic)
|
if (m_bPublic)
|
||||||
|
@ -78,6 +76,18 @@ bool CBotFunction::IsPublic()
|
||||||
return m_bPublic;
|
return m_bPublic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool CBotFunction::IsProtected() const
|
||||||
|
{
|
||||||
|
return m_bProtect;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool CBotFunction::IsPrivate() const
|
||||||
|
{
|
||||||
|
return m_bPrivate;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
bool CBotFunction::IsExtern()
|
bool CBotFunction::IsExtern()
|
||||||
{
|
{
|
||||||
|
@ -131,19 +141,15 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
|
||||||
{
|
{
|
||||||
CBotToken* pp;
|
CBotToken* pp;
|
||||||
CBotFunction* func = finput;
|
CBotFunction* func = finput;
|
||||||
if ( func == nullptr ) func = new CBotFunction();
|
assert(func != nullptr); // a pre-compiled function is required
|
||||||
|
|
||||||
CBotCStack* pStk = pStack->TokenStack(p, bLocal);
|
CBotCStack* pStk = pStack->TokenStack(p, bLocal);
|
||||||
|
|
||||||
// func->m_nFuncIdent = CBotVar::NextUniqNum();
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if ( IsOfType(p, ID_PUBLIC) )
|
if (IsOfType(p, ID_PRIVATE)) break;
|
||||||
{
|
if (IsOfType(p, ID_PROTECTED)) break;
|
||||||
func->m_bPublic = true;
|
if (IsOfType(p, ID_PUBLIC)) continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pp = p;
|
pp = p;
|
||||||
if (IsOfType(p, ID_EXTERN))
|
if (IsOfType(p, ID_EXTERN))
|
||||||
{
|
{
|
||||||
|
@ -167,10 +173,11 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
|
||||||
if ( IsOfType(p, ID_NOT) )
|
if ( IsOfType(p, ID_NOT) )
|
||||||
{
|
{
|
||||||
CBotToken d(std::string("~") + p->GetString());
|
CBotToken d(std::string("~") + p->GetString());
|
||||||
|
d.SetPos(pp->GetStart(), p->GetEnd());
|
||||||
func->m_token = d;
|
func->m_token = d;
|
||||||
}
|
}
|
||||||
|
|
||||||
// un nom de fonction est-il là ?
|
// is there a function name here ?
|
||||||
if (IsOfType(p, TokenTypVar))
|
if (IsOfType(p, TokenTypVar))
|
||||||
{
|
{
|
||||||
if ( IsOfType( p, ID_DBLDOTS ) ) // method for a class
|
if ( IsOfType( p, ID_DBLDOTS ) ) // method for a class
|
||||||
|
@ -178,14 +185,32 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
|
||||||
func->m_MasterClass = pp->GetString();
|
func->m_MasterClass = pp->GetString();
|
||||||
func->m_classToken = *pp;
|
func->m_classToken = *pp;
|
||||||
CBotClass* pClass = CBotClass::Find(pp);
|
CBotClass* pClass = CBotClass::Find(pp);
|
||||||
if ( pClass == nullptr ) goto bad;
|
if ( pClass == nullptr )
|
||||||
|
{
|
||||||
|
pStk->SetError(CBotErrNoClassName, pp);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
|
||||||
// pp = p;
|
pp = p;
|
||||||
func->m_token = *p;
|
func->m_token = *p;
|
||||||
if (!IsOfType(p, TokenTypVar)) goto bad;
|
if (!IsOfType(p, TokenTypVar)) goto bad;
|
||||||
|
// check if the class has a method like this
|
||||||
|
if (pClass->CheckCall(pStack->GetProgram(), func->m_param, pp))
|
||||||
|
{
|
||||||
|
pStk->SetStartError(func->m_classToken.GetStart());
|
||||||
|
pStk->SetError(CBotErrRedefFunc, pp->GetEnd());
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
// check if a constructor has return type void
|
||||||
|
if (func->GetName() == pClass->GetName() && !func->m_retTyp.Eq(CBotTypVoid))
|
||||||
|
{
|
||||||
|
pp = &(func->m_retToken);
|
||||||
|
pStk->SetError(CBotErrFuncNotVoid, pp);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
func->m_openpar = *p;
|
func->m_openpar = *p;
|
||||||
|
delete func->m_param;
|
||||||
func->m_param = CBotDefParam::Compile(p, pStk );
|
func->m_param = CBotDefParam::Compile(p, pStk );
|
||||||
func->m_closepar = *(p->GetPrev());
|
func->m_closepar = *(p->GetPrev());
|
||||||
if (pStk->IsOk())
|
if (pStk->IsOk())
|
||||||
|
@ -194,28 +219,13 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
|
||||||
|
|
||||||
if (!func->m_MasterClass.empty())
|
if (!func->m_MasterClass.empty())
|
||||||
{
|
{
|
||||||
// return "this" known
|
CBotClass* pClass = CBotClass::Find(func->m_MasterClass);
|
||||||
CBotVar* pThis = CBotVar::Create("this", CBotTypResult( CBotTypClass, func->m_MasterClass ));
|
|
||||||
pThis->SetInit(CBotVar::InitType::IS_POINTER);
|
|
||||||
// pThis->SetUniqNum(func->m_nThisIdent = -2); //CBotVar::NextUniqNum() will not
|
|
||||||
pThis->SetUniqNum(-2);
|
|
||||||
pStk->AddVar(pThis);
|
|
||||||
|
|
||||||
// initialize variables acording to This
|
pStk->CreateVarThis(pClass);
|
||||||
// only saves the pointer to the first,
|
pStk->CreateVarSuper(pClass->GetParent());
|
||||||
// the rest is chained
|
|
||||||
CBotVar* pv = pThis->GetItemList();
|
bool bConstructor = (func->GetName() == func->m_MasterClass);
|
||||||
// int num = 1;
|
pStk->CreateMemberVars(pClass, !bConstructor);
|
||||||
while (pv != nullptr)
|
|
||||||
{
|
|
||||||
CBotVar* pcopy = CBotVar::Create(pv);
|
|
||||||
// pcopy->SetInit(2);
|
|
||||||
pcopy->Copy(pv);
|
|
||||||
pcopy->SetPrivate(pv->GetPrivate());
|
|
||||||
// pcopy->SetUniqNum(pv->GetUniqNum()); //num++);
|
|
||||||
pStk->AddVar(pcopy);
|
|
||||||
pv = pv->GetNext();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// and compiles the following instruction block
|
// and compiles the following instruction block
|
||||||
|
@ -224,9 +234,11 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct
|
||||||
func->m_closeblk = (p != nullptr && p->GetPrev() != nullptr) ? *(p->GetPrev()) : CBotToken();
|
func->m_closeblk = (p != nullptr && p->GetPrev() != nullptr) ? *(p->GetPrev()) : CBotToken();
|
||||||
if ( pStk->IsOk() )
|
if ( pStk->IsOk() )
|
||||||
{
|
{
|
||||||
if ( func->m_bPublic ) // public function, return known for all
|
if (!func->m_retTyp.Eq(CBotTypVoid) && !func->HasReturn())
|
||||||
{
|
{
|
||||||
CBotFunction::AddPublic(func);
|
int errPos = func->m_closeblk.GetStart();
|
||||||
|
pStk->ResetError(CBotErrNoReturn, errPos, errPos);
|
||||||
|
goto bad;
|
||||||
}
|
}
|
||||||
return pStack->ReturnFunc(func, pStk);
|
return pStack->ReturnFunc(func, pStk);
|
||||||
}
|
}
|
||||||
|
@ -236,7 +248,6 @@ bad:
|
||||||
pStk->SetError(CBotErrNoFunc, p);
|
pStk->SetError(CBotErrNoFunc, p);
|
||||||
}
|
}
|
||||||
pStk->SetError(CBotErrNoType, p);
|
pStk->SetError(CBotErrNoType, p);
|
||||||
if ( finput == nullptr ) delete func;
|
|
||||||
return pStack->ReturnFunc(nullptr, pStk);
|
return pStack->ReturnFunc(nullptr, pStk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,14 +259,30 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
|
||||||
|
|
||||||
CBotCStack* pStk = pStack->TokenStack(p, true);
|
CBotCStack* pStk = pStack->TokenStack(p, true);
|
||||||
|
|
||||||
|
CBotToken* pPriv = p;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
if (!func->m_bPublic) // don't repeat 'public'
|
||||||
|
{
|
||||||
|
pPriv = p;
|
||||||
|
if (IsOfType(p, ID_PRIVATE))
|
||||||
|
{
|
||||||
|
func->m_bPrivate = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (IsOfType(p, ID_PROTECTED))
|
||||||
|
{
|
||||||
|
func->m_bProtect = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (IsOfType(p, ID_PUBLIC))
|
if (IsOfType(p, ID_PUBLIC))
|
||||||
{
|
{
|
||||||
// func->m_bPublic = true; // will be done in two passes
|
func->m_bPublic = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ( IsOfType(p, ID_EXTERN) )
|
}
|
||||||
|
if (!func->m_bExtern && IsOfType(p, ID_EXTERN))
|
||||||
{
|
{
|
||||||
func->m_bExtern = true;
|
func->m_bExtern = true;
|
||||||
continue;
|
continue;
|
||||||
|
@ -274,32 +301,67 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas
|
||||||
if ( IsOfType(p, ID_NOT) )
|
if ( IsOfType(p, ID_NOT) )
|
||||||
{
|
{
|
||||||
CBotToken d(std::string("~") + p->GetString());
|
CBotToken d(std::string("~") + p->GetString());
|
||||||
|
d.SetPos(pp->GetStart(), p->GetEnd());
|
||||||
func->m_token = d;
|
func->m_token = d;
|
||||||
}
|
}
|
||||||
|
|
||||||
// un nom de fonction est-il là ?
|
// is there a function name here ?
|
||||||
if (IsOfType(p, TokenTypVar))
|
if (IsOfType(p, TokenTypVar))
|
||||||
{
|
{
|
||||||
if ( IsOfType( p, ID_DBLDOTS ) ) // method for a class
|
if ( IsOfType( p, ID_DBLDOTS ) ) // method for a class
|
||||||
{
|
{
|
||||||
func->m_MasterClass = pp->GetString();
|
func->m_MasterClass = pp->GetString();
|
||||||
CBotClass* pClass = CBotClass::Find(pp);
|
// existence of the class is checked
|
||||||
if ( pClass == nullptr )
|
// later in CBotFunction::Compile()
|
||||||
{
|
|
||||||
pStk->SetError(CBotErrNotClass, pp);
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
|
|
||||||
pp = p;
|
pp = p;
|
||||||
func->m_token = *p;
|
func->m_token = *p;
|
||||||
if (!IsOfType(p, TokenTypVar)) goto bad;
|
if (!IsOfType(p, TokenTypVar)) goto bad;
|
||||||
|
|
||||||
}
|
}
|
||||||
func->m_param = CBotDefParam::Compile(p, pStk );
|
else if (pClass == nullptr) // not method in a class ?
|
||||||
|
{
|
||||||
|
if (func->m_bPrivate || func->m_bProtect) // not allowed for regular functions
|
||||||
|
{
|
||||||
|
pStk->SetError(CBotErrNoType, pPriv);
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CBotToken* openPar = p;
|
||||||
|
func->m_param = CBotDefParam::Compile(p, pStk); // compile parameters
|
||||||
|
|
||||||
|
if (pStk->IsOk() && pClass != nullptr) // method in a class
|
||||||
|
{
|
||||||
|
func->m_MasterClass = pClass->GetName();
|
||||||
|
// check if a constructor has return type void
|
||||||
|
if (func->GetName() == pClass->GetName() && !func->m_retTyp.Eq(CBotTypVoid))
|
||||||
|
{
|
||||||
|
pp = &(func->m_retToken);
|
||||||
|
pStk->SetError(CBotErrFuncNotVoid, pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pStk->IsOk() && pp->GetString() == "~") // destructor
|
||||||
|
{
|
||||||
|
// check destructor name
|
||||||
|
if (func->GetName() != ("~" + pClass->GetName()))
|
||||||
|
pStk->SetError(CBotErrNoFunc, pp);
|
||||||
|
// confirm no parameters
|
||||||
|
if (pStk->IsOk() && func->m_param != nullptr)
|
||||||
|
pStk->SetError(CBotErrClosePar, openPar->GetNext());
|
||||||
|
// must return void
|
||||||
|
if (pStk->IsOk() && !func->m_retTyp.Eq(CBotTypVoid))
|
||||||
|
{
|
||||||
|
pp = &(func->m_retToken);
|
||||||
|
pStk->SetError(CBotErrFuncNotVoid, pp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pStk->IsOk())
|
if (pStk->IsOk())
|
||||||
{
|
{
|
||||||
// looks if the function exists elsewhere
|
// looks if the function exists elsewhere
|
||||||
if (( pClass != nullptr || !pStack->CheckCall(pp, func->m_param)) &&
|
pp = &(func->m_token);
|
||||||
|
if (( pClass != nullptr || !pStack->CheckCall(pp, func->m_param, func->m_MasterClass)) &&
|
||||||
( pClass == nullptr || !pClass->CheckCall(pStack->GetProgram(), func->m_param, pp)) )
|
( pClass == nullptr || !pClass->CheckCall(pStack->GetProgram(), func->m_param, pp)) )
|
||||||
{
|
{
|
||||||
if (IsOfType(p, ID_OPBLK))
|
if (IsOfType(p, ID_OPBLK))
|
||||||
|
@ -338,9 +400,19 @@ bool CBotFunction::Execute(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInstance)
|
||||||
|
|
||||||
pile->SetProgram(m_pProg); // bases for routines
|
pile->SetProgram(m_pProg); // bases for routines
|
||||||
|
|
||||||
|
if ( pile->IfStep() ) return false;
|
||||||
|
|
||||||
if ( pile->GetState() == 0 )
|
if ( pile->GetState() == 0 )
|
||||||
{
|
{
|
||||||
|
if (m_param != nullptr)
|
||||||
|
{
|
||||||
|
// stack for parameters and default args
|
||||||
|
CBotStack* pile3b = pile->AddStack();
|
||||||
|
pile3b->SetState(1);
|
||||||
|
|
||||||
if ( !m_param->Execute(ppVars, pile) ) return false; // define parameters
|
if ( !m_param->Execute(ppVars, pile) ) return false; // define parameters
|
||||||
|
pile3b->Delete(); // done with param stack
|
||||||
|
}
|
||||||
pile->IncState();
|
pile->IncState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,9 +445,7 @@ bool CBotFunction::Execute(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInstance)
|
||||||
pile->IncState();
|
pile->IncState();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( pile->IfStep() ) return false;
|
if (!pile->GetRetVar(m_block->Execute(pile)))
|
||||||
|
|
||||||
if ( !m_block->Execute(pile) )
|
|
||||||
{
|
{
|
||||||
if ( pile->GetError() < 0 )
|
if ( pile->GetError() < 0 )
|
||||||
pile->SetError( CBotNoErr );
|
pile->SetError( CBotNoErr );
|
||||||
|
@ -403,12 +473,28 @@ void CBotFunction::RestoreState(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInst
|
||||||
pile2->Delete();
|
pile2->Delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_param->RestoreState(pile2, true); // parameters
|
if ( pile->GetState() == 0 )
|
||||||
|
{
|
||||||
|
if (m_param != nullptr)
|
||||||
|
{
|
||||||
|
CBotStack* pile3b = pile2->RestoreStack();
|
||||||
|
|
||||||
|
if (pile3b != nullptr && pile3b->GetState() == 1)
|
||||||
|
m_param->RestoreState(pile2, true); // restore executing default arguments
|
||||||
|
else
|
||||||
|
m_param->RestoreState(pile2, false); // restore parameter IDs
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_param != nullptr)
|
||||||
|
m_param->RestoreState(pile2, false); // restore parameter IDs
|
||||||
|
|
||||||
if ( !m_MasterClass.empty() )
|
if ( !m_MasterClass.empty() )
|
||||||
{
|
{
|
||||||
CBotVar* pThis = pile->FindVar("this");
|
CBotVar* pThis = pile->FindVar("this");
|
||||||
pThis->SetInit(CBotVar::InitType::IS_POINTER);
|
pThis->SetInit(CBotVar::InitType::IS_POINTER);
|
||||||
|
pThis->SetPointer(pInstance);
|
||||||
pThis->SetUniqNum(-2);
|
pThis->SetUniqNum(-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,35 +502,26 @@ void CBotFunction::RestoreState(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInst
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotFunction::AddNext(CBotFunction* p)
|
CBotTypResult CBotFunction::CompileCall(const std::string &name, CBotVar** ppVars, long &nIdent, CBotProgram* program)
|
||||||
{
|
{
|
||||||
CBotFunction* pp = this;
|
|
||||||
while (pp->m_next != nullptr) pp = pp->m_next;
|
|
||||||
|
|
||||||
pp->m_next = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
CBotTypResult CBotFunction::CompileCall(const std::string& name, CBotVar** ppVars, long& nIdent)
|
|
||||||
{
|
|
||||||
nIdent = 0;
|
|
||||||
CBotTypResult type;
|
CBotTypResult type;
|
||||||
|
if (!FindLocalOrPublic(program->GetFunctions(), nIdent, name, ppVars, type, program))
|
||||||
// CBotFunction* pt = FindLocalOrPublic(nIdent, name, ppVars, type);
|
{
|
||||||
FindLocalOrPublic(nIdent, name, ppVars, type);
|
// Reset the identifier to "not found" value
|
||||||
|
nIdent = 0;
|
||||||
|
}
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotFunction* CBotFunction::FindLocalOrPublic(long& nIdent, const std::string& name, CBotVar** ppVars,
|
CBotFunction* CBotFunction::FindLocalOrPublic(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name,
|
||||||
CBotTypResult& TypeOrError, bool bPublic)
|
CBotVar** ppVars, CBotTypResult &TypeOrError, CBotProgram* baseProg)
|
||||||
{
|
{
|
||||||
TypeOrError.SetType(CBotErrUndefCall); // no routine of the name
|
TypeOrError.SetType(CBotErrUndefCall); // no routine of the name
|
||||||
CBotFunction* pt;
|
|
||||||
|
|
||||||
if ( nIdent )
|
if ( nIdent )
|
||||||
{
|
{
|
||||||
if ( this != nullptr ) for ( pt = this ; pt != nullptr ; pt = pt->m_next )
|
for (CBotFunction* pt : localFunctionList)
|
||||||
{
|
{
|
||||||
if (pt->m_nFuncIdent == nIdent)
|
if (pt->m_nFuncIdent == nIdent)
|
||||||
{
|
{
|
||||||
|
@ -466,121 +543,200 @@ CBotFunction* CBotFunction::FindLocalOrPublic(long& nIdent, const std::string& n
|
||||||
|
|
||||||
if ( name.empty() ) return nullptr;
|
if ( name.empty() ) return nullptr;
|
||||||
|
|
||||||
int delta = 99999; // seeks the lowest signature
|
std::map<CBotFunction*, int> funcMap;
|
||||||
CBotFunction* pFunc = nullptr; // the best function found
|
|
||||||
|
|
||||||
if ( this != nullptr )
|
CBotFunction::SearchList(localFunctionList, name, ppVars, TypeOrError, funcMap);
|
||||||
|
|
||||||
|
CBotFunction::SearchPublic(name, ppVars, TypeOrError, funcMap);
|
||||||
|
|
||||||
|
if (baseProg != nullptr && baseProg->m_thisVar != nullptr)
|
||||||
{
|
{
|
||||||
for ( pt = this ; pt != nullptr ; pt = pt->m_next )
|
// find object:: functions
|
||||||
|
CBotClass* pClass = baseProg->m_thisVar->GetClass();
|
||||||
|
CBotFunction::SearchList(localFunctionList, name, ppVars, TypeOrError, funcMap, pClass);
|
||||||
|
CBotFunction::SearchPublic(name, ppVars, TypeOrError, funcMap, pClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CBotFunction::BestFunction(funcMap, nIdent, TypeOrError);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void CBotFunction::SearchList(const std::list<CBotFunction*>& functionList,
|
||||||
|
const std::string& name, CBotVar** ppVars, CBotTypResult& TypeOrError,
|
||||||
|
std::map<CBotFunction*, int>& funcMap, CBotClass* pClass)
|
||||||
|
{
|
||||||
|
for (CBotFunction* pt : functionList)
|
||||||
{
|
{
|
||||||
if ( pt->m_token.GetString() == name )
|
if ( pt->m_token.GetString() == name )
|
||||||
{
|
{
|
||||||
|
if (pClass != nullptr) // looking for a method ?
|
||||||
|
{
|
||||||
|
if (pt->m_MasterClass != pClass->GetName()) continue;
|
||||||
|
}
|
||||||
|
else // looking for a function
|
||||||
|
{
|
||||||
|
if (!pt->m_MasterClass.empty()) continue;
|
||||||
|
}
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int alpha = 0; // signature of parameters
|
int alpha = 0; // signature of parameters
|
||||||
// parameters are compatible?
|
// parameters are compatible?
|
||||||
CBotDefParam* pv = pt->m_param; // expected list of parameters
|
CBotDefParam* pv = pt->m_param; // expected list of parameters
|
||||||
CBotVar* pw = ppVars[i++]; // provided list parameter
|
CBotVar* pw = ppVars[i++]; // provided list parameter
|
||||||
while ( pv != nullptr && pw != nullptr)
|
while ( pv != nullptr && (pw != nullptr || pv->HasDefault()) )
|
||||||
{
|
{
|
||||||
if (!TypesCompatibles(pv->GetTypResult(), pw->GetTypResult()))
|
if (pw == nullptr) // end of arguments
|
||||||
{
|
{
|
||||||
if ( pFunc == nullptr ) TypeOrError = CBotErrBadParam;
|
pv = pv->GetNext();
|
||||||
|
continue; // skip params with default values
|
||||||
|
}
|
||||||
|
CBotTypResult paramType = pv->GetTypResult();
|
||||||
|
CBotTypResult argType = pw->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
||||||
|
|
||||||
|
if (!TypesCompatibles(paramType, argType))
|
||||||
|
{
|
||||||
|
if ( funcMap.empty() ) TypeOrError.SetType(CBotErrBadParam);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (paramType.Eq(CBotTypPointer) && !argType.Eq(CBotTypNullPointer))
|
||||||
|
{
|
||||||
|
CBotClass* c1 = paramType.GetClass();
|
||||||
|
CBotClass* c2 = argType.GetClass();
|
||||||
|
while (c2 != c1 && c2 != nullptr) // implicit cast
|
||||||
|
{
|
||||||
|
alpha += 10;
|
||||||
|
c2 = c2->GetParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
int d = pv->GetType() - pw->GetType(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
int d = pv->GetType() - pw->GetType(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
||||||
alpha += d>0 ? d : -10*d; // quality loss, 10 times more expensive!
|
alpha += d>0 ? d : -10*d; // quality loss, 10 times more expensive!
|
||||||
|
}
|
||||||
pv = pv->GetNext();
|
pv = pv->GetNext();
|
||||||
pw = ppVars[i++];
|
pw = ppVars[i++];
|
||||||
}
|
}
|
||||||
if ( pw != nullptr )
|
if ( pw != nullptr )
|
||||||
{
|
{
|
||||||
if ( pFunc != nullptr ) continue;
|
if ( !funcMap.empty() ) continue;
|
||||||
if ( TypeOrError.Eq(CBotErrLowParam) ) TypeOrError.SetType(CBotErrNbParam);
|
if ( TypeOrError.Eq(CBotErrLowParam) ) TypeOrError.SetType(CBotErrNbParam);
|
||||||
if ( TypeOrError.Eq(CBotErrUndefCall)) TypeOrError.SetType(CBotErrOverParam);
|
if ( TypeOrError.Eq(CBotErrUndefCall)) TypeOrError.SetType(CBotErrOverParam);
|
||||||
continue; // too many parameters
|
continue; // too many parameters
|
||||||
}
|
}
|
||||||
if ( pv != nullptr )
|
if ( pv != nullptr )
|
||||||
{
|
{
|
||||||
if ( pFunc != nullptr ) continue;
|
if ( !funcMap.empty() ) continue;
|
||||||
if ( TypeOrError.Eq(CBotErrOverParam) ) TypeOrError.SetType(CBotErrNbParam);
|
if ( TypeOrError.Eq(CBotErrOverParam) ) TypeOrError.SetType(CBotErrNbParam);
|
||||||
if ( TypeOrError.Eq(CBotErrUndefCall) ) TypeOrError.SetType(CBotErrLowParam);
|
if ( TypeOrError.Eq(CBotErrUndefCall) ) TypeOrError.SetType(CBotErrLowParam);
|
||||||
continue; // not enough parameters
|
continue; // not enough parameters
|
||||||
}
|
}
|
||||||
|
funcMap.insert( std::pair<CBotFunction*, int>(pt, alpha) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (alpha == 0) // perfect signature
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void CBotFunction::SearchPublic(const std::string& name, CBotVar** ppVars, CBotTypResult& TypeOrError,
|
||||||
|
std::map<CBotFunction*, int>& funcMap, CBotClass* pClass)
|
||||||
{
|
{
|
||||||
nIdent = pt->m_nFuncIdent;
|
|
||||||
TypeOrError = pt->m_retTyp;
|
|
||||||
return pt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( alpha < delta ) // a better signature?
|
|
||||||
{
|
|
||||||
pFunc = pt;
|
|
||||||
delta = alpha;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( bPublic )
|
|
||||||
{
|
{
|
||||||
for (CBotFunction* pt : m_publicFunctions)
|
for (CBotFunction* pt : m_publicFunctions)
|
||||||
{
|
{
|
||||||
if ( pt->m_token.GetString() == name )
|
if ( pt->m_token.GetString() == name )
|
||||||
{
|
{
|
||||||
|
if (pClass != nullptr) // looking for a method ?
|
||||||
|
{
|
||||||
|
if (pt->m_MasterClass != pClass->GetName()) continue;
|
||||||
|
}
|
||||||
|
else // looking for a function
|
||||||
|
{
|
||||||
|
if (!pt->m_MasterClass.empty()) continue;
|
||||||
|
}
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int alpha = 0; // signature of parameters
|
int alpha = 0; // signature of parameters
|
||||||
// parameters sont-ils compatibles ?
|
// are parameters compatible ?
|
||||||
CBotDefParam* pv = pt->m_param; // list of expected parameters
|
CBotDefParam* pv = pt->m_param; // list of expected parameters
|
||||||
CBotVar* pw = ppVars[i++]; // list of provided parameters
|
CBotVar* pw = ppVars[i++]; // list of provided parameters
|
||||||
while ( pv != nullptr && pw != nullptr)
|
while ( pv != nullptr && (pw != nullptr || pv->HasDefault()) )
|
||||||
{
|
{
|
||||||
if (!TypesCompatibles(pv->GetTypResult(), pw->GetTypResult()))
|
if (pw == nullptr) // end of arguments
|
||||||
{
|
{
|
||||||
if ( pFunc == nullptr ) TypeOrError = CBotErrBadParam;
|
pv = pv->GetNext();
|
||||||
|
continue; // skip params with default values
|
||||||
|
}
|
||||||
|
CBotTypResult paramType = pv->GetTypResult();
|
||||||
|
CBotTypResult argType = pw->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
||||||
|
|
||||||
|
if (!TypesCompatibles(paramType, argType))
|
||||||
|
{
|
||||||
|
if ( funcMap.empty() ) TypeOrError.SetType(CBotErrBadParam);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (paramType.Eq(CBotTypPointer) && !argType.Eq(CBotTypNullPointer))
|
||||||
|
{
|
||||||
|
CBotClass* c1 = paramType.GetClass();
|
||||||
|
CBotClass* c2 = argType.GetClass();
|
||||||
|
while (c2 != c1 && c2 != nullptr) // implicit cast
|
||||||
|
{
|
||||||
|
alpha += 10;
|
||||||
|
c2 = c2->GetParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
int d = pv->GetType() - pw->GetType(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
int d = pv->GetType() - pw->GetType(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
||||||
alpha += d>0 ? d : -10*d; // quality loss, 10 times more expensive!
|
alpha += d>0 ? d : -10*d; // quality loss, 10 times more expensive!
|
||||||
|
}
|
||||||
pv = pv->GetNext();
|
pv = pv->GetNext();
|
||||||
pw = ppVars[i++];
|
pw = ppVars[i++];
|
||||||
}
|
}
|
||||||
if ( pw != nullptr )
|
if ( pw != nullptr )
|
||||||
{
|
{
|
||||||
if ( pFunc != nullptr ) continue;
|
if ( !funcMap.empty() ) continue; // previous useable function
|
||||||
if ( TypeOrError.Eq(CBotErrLowParam) ) TypeOrError.SetType(CBotErrNbParam);
|
if ( TypeOrError.Eq(CBotErrLowParam) ) TypeOrError.SetType(CBotErrNbParam);
|
||||||
if ( TypeOrError.Eq(CBotErrUndefCall)) TypeOrError.SetType(CBotErrOverParam);
|
if ( TypeOrError.Eq(CBotErrUndefCall)) TypeOrError.SetType(CBotErrOverParam);
|
||||||
continue; // to many parameters
|
continue; // to many parameters
|
||||||
}
|
}
|
||||||
if ( pv != nullptr )
|
if ( pv != nullptr )
|
||||||
{
|
{
|
||||||
if ( pFunc != nullptr ) continue;
|
if ( !funcMap.empty() ) continue; // previous useable function
|
||||||
if ( TypeOrError.Eq(CBotErrOverParam) ) TypeOrError.SetType(CBotErrNbParam);
|
if ( TypeOrError.Eq(CBotErrOverParam) ) TypeOrError.SetType(CBotErrNbParam);
|
||||||
if ( TypeOrError.Eq(CBotErrUndefCall) ) TypeOrError.SetType(CBotErrLowParam);
|
if ( TypeOrError.Eq(CBotErrUndefCall) ) TypeOrError.SetType(CBotErrLowParam);
|
||||||
continue; // not enough parameters
|
continue; // not enough parameters
|
||||||
}
|
}
|
||||||
|
funcMap.insert( std::pair<CBotFunction*, int>(pt, alpha) );
|
||||||
if (alpha == 0) // perfect signature
|
|
||||||
{
|
|
||||||
nIdent = pt->m_nFuncIdent;
|
|
||||||
TypeOrError = pt->m_retTyp;
|
|
||||||
return pt;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( alpha < delta ) // a better signature?
|
|
||||||
{
|
|
||||||
pFunc = pt;
|
|
||||||
delta = alpha;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( pFunc != nullptr )
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
CBotFunction* CBotFunction::BestFunction(std::map<CBotFunction*, int>& funcMap,
|
||||||
|
long& nIdent, CBotTypResult& TypeOrError)
|
||||||
{
|
{
|
||||||
|
if ( !funcMap.empty() )
|
||||||
|
{
|
||||||
|
auto it = funcMap.begin();
|
||||||
|
CBotFunction* pFunc = it->first; // the best function found
|
||||||
|
signed int delta = it->second; // seeks the lowest signature
|
||||||
|
|
||||||
|
for (++it ; it != funcMap.end() ; it++)
|
||||||
|
{
|
||||||
|
if (it->second < delta) // a better signature?
|
||||||
|
{
|
||||||
|
TypeOrError.SetType(CBotNoErr);
|
||||||
|
pFunc = it->first;
|
||||||
|
delta = it->second;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it->second == delta) TypeOrError.SetType(CBotErrAmbiguousCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TypeOrError.Eq(CBotErrAmbiguousCall)) return nullptr;
|
||||||
nIdent = pFunc->m_nFuncIdent;
|
nIdent = pFunc->m_nFuncIdent;
|
||||||
TypeOrError = pFunc->m_retTyp;
|
TypeOrError = pFunc->m_retTyp;
|
||||||
return pFunc;
|
return pFunc;
|
||||||
|
@ -589,12 +745,14 @@ CBotFunction* CBotFunction::FindLocalOrPublic(long& nIdent, const std::string& n
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken)
|
int CBotFunction::DoCall(CBotProgram* program, const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name,
|
||||||
|
CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken)
|
||||||
{
|
{
|
||||||
CBotTypResult type;
|
CBotTypResult type;
|
||||||
CBotFunction* pt = nullptr;
|
CBotFunction* pt = nullptr;
|
||||||
|
CBotProgram* baseProg = pStack->GetProgram(true);
|
||||||
|
|
||||||
pt = FindLocalOrPublic(nIdent, name, ppVars, type);
|
pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type, baseProg);
|
||||||
|
|
||||||
if ( pt != nullptr )
|
if ( pt != nullptr )
|
||||||
{
|
{
|
||||||
|
@ -611,9 +769,12 @@ int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar** ppVars
|
||||||
|
|
||||||
if ( pStk1->GetState() == 0 )
|
if ( pStk1->GetState() == 0 )
|
||||||
{
|
{
|
||||||
if ( !pt->m_MasterClass.empty() )
|
// stack for parameters and default args
|
||||||
|
CBotStack* pStk3b = pStk3->AddStack();
|
||||||
|
|
||||||
|
if (pStk3b->GetState() == 0 && !pt->m_MasterClass.empty())
|
||||||
{
|
{
|
||||||
CBotVar* pInstance = m_pProg->m_thisVar;
|
CBotVar* pInstance = (baseProg != nullptr) ? baseProg->m_thisVar : nullptr;
|
||||||
// make "this" known
|
// make "this" known
|
||||||
CBotVar* pThis ;
|
CBotVar* pThis ;
|
||||||
if ( pInstance == nullptr )
|
if ( pInstance == nullptr )
|
||||||
|
@ -637,10 +798,21 @@ int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar** ppVars
|
||||||
pThis->SetUniqNum(-2);
|
pThis->SetUniqNum(-2);
|
||||||
pStk1->AddVar(pThis);
|
pStk1->AddVar(pThis);
|
||||||
}
|
}
|
||||||
|
pStk3b->SetState(1); // set 'this' was created
|
||||||
|
|
||||||
// initializes the variables as parameters
|
// initializes the variables as parameters
|
||||||
pt->m_param->Execute(ppVars, pStk3); // cannot be interrupted
|
if (pt->m_param != nullptr)
|
||||||
|
{
|
||||||
|
if (!pt->m_param->Execute(ppVars, pStk3)) // interupt here
|
||||||
|
{
|
||||||
|
if (!pStk3->IsOk() && pt->m_pProg != program)
|
||||||
|
{
|
||||||
|
pStk3->SetPosError(pToken); // indicates the error on the procedure call
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pStk3b->Delete(); // done with param stack
|
||||||
pStk1->IncState();
|
pStk1->IncState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -649,7 +821,7 @@ int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar** ppVars
|
||||||
if ( !pStk3->GetRetVar( // puts the result on the stack
|
if ( !pStk3->GetRetVar( // puts the result on the stack
|
||||||
pt->m_block->Execute(pStk3) )) // GetRetVar said if it is interrupted
|
pt->m_block->Execute(pStk3) )) // GetRetVar said if it is interrupted
|
||||||
{
|
{
|
||||||
if ( !pStk3->IsOk() && pt->m_pProg != m_pProg )
|
if ( !pStk3->IsOk() && pt->m_pProg != program )
|
||||||
{
|
{
|
||||||
pStk3->SetPosError(pToken); // indicates the error on the procedure call
|
pStk3->SetPosError(pToken); // indicates the error on the procedure call
|
||||||
}
|
}
|
||||||
|
@ -662,16 +834,16 @@ int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar** ppVars
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotFunction::RestoreCall(long& nIdent, const std::string& name, CBotVar** ppVars, CBotStack* pStack)
|
void CBotFunction::RestoreCall(const std::list<CBotFunction*>& localFunctionList,
|
||||||
|
long &nIdent, const std::string &name, CBotVar** ppVars, CBotStack* pStack)
|
||||||
{
|
{
|
||||||
CBotTypResult type;
|
CBotTypResult type;
|
||||||
CBotFunction* pt = nullptr;
|
CBotFunction* pt = nullptr;
|
||||||
CBotStack* pStk1;
|
CBotStack* pStk1;
|
||||||
CBotStack* pStk3;
|
CBotStack* pStk3;
|
||||||
|
CBotProgram* baseProg = pStack->GetProgram(true);
|
||||||
|
|
||||||
// search function to return the ok identifier
|
pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type, baseProg);
|
||||||
|
|
||||||
pt = FindLocalOrPublic(nIdent, name, ppVars, type);
|
|
||||||
|
|
||||||
if ( pt != nullptr )
|
if ( pt != nullptr )
|
||||||
{
|
{
|
||||||
|
@ -698,34 +870,152 @@ void CBotFunction::RestoreCall(long& nIdent, const std::string& name, CBotVar**
|
||||||
{
|
{
|
||||||
if ( !pt->m_MasterClass.empty() )
|
if ( !pt->m_MasterClass.empty() )
|
||||||
{
|
{
|
||||||
// CBotVar* pInstance = m_pProg->m_thisVar;
|
CBotVar* pInstance = (baseProg != nullptr) ? baseProg->m_thisVar : nullptr;
|
||||||
// make "this" known
|
// make "this" known
|
||||||
CBotVar* pThis = pStk1->FindVar("this");
|
CBotVar* pThis = pStk1->FindVar("this");
|
||||||
pThis->SetInit(CBotVar::InitType::IS_POINTER);
|
pThis->SetInit(CBotVar::InitType::IS_POINTER);
|
||||||
|
pThis->SetPointer(pInstance);
|
||||||
pThis->SetUniqNum(-2);
|
pThis->SetUniqNum(-2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( pStk1->GetState() == 0 )
|
if ( pStk1->GetState() == 0 )
|
||||||
{
|
{
|
||||||
pt->m_param->RestoreState(pStk3, true);
|
if (pt->m_param != nullptr)
|
||||||
|
{
|
||||||
|
CBotStack* pStk3b = pStk3->RestoreStack();
|
||||||
|
|
||||||
|
if (pStk3b != nullptr && pStk3b->GetState() == 1)
|
||||||
|
pt->m_param->RestoreState(pStk3, true); // restore executing default arguments
|
||||||
|
else
|
||||||
|
pt->m_param->RestoreState(pStk3, false); // restore parameter IDs
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// initializes the variables as parameters
|
// initializes the variables as parameters
|
||||||
pt->m_param->RestoreState(pStk3, false);
|
if (pt->m_param != nullptr)
|
||||||
|
pt->m_param->RestoreState(pStk3, false); // restore parameter IDs
|
||||||
pt->m_block->RestoreState(pStk3, true);
|
pt->m_block->RestoreState(pStk3, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar* pThis, CBotVar** ppVars, CBotStack* pStack,
|
CBotTypResult CBotFunction::CompileMethodCall(const std::string& name, CBotVar** ppVars,
|
||||||
CBotToken* pToken, CBotClass* pClass)
|
long& nIdent, CBotCStack* pStack, CBotClass* pClass)
|
||||||
|
{
|
||||||
|
nIdent = 0;
|
||||||
|
CBotTypResult type;
|
||||||
|
|
||||||
|
CBotFunction* pt = FindMethod(nIdent, name, ppVars, type, pClass, pStack->GetProgram());
|
||||||
|
|
||||||
|
if (pt != nullptr)
|
||||||
|
{
|
||||||
|
CBotToken token("this");
|
||||||
|
CBotVar* pThis = pStack->FindVar(token); // for 'this' context
|
||||||
|
|
||||||
|
if (pThis == nullptr || pThis->GetType() != CBotTypPointer) // called from inside a function
|
||||||
|
{
|
||||||
|
if (pt->IsPrivate() || pt->IsProtected())
|
||||||
|
type.SetType(CBotErrPrivate);
|
||||||
|
}
|
||||||
|
else // called from inside a method
|
||||||
|
{
|
||||||
|
CBotClass* thisClass = pThis->GetClass(); // current class
|
||||||
|
CBotClass* funcClass = CBotClass::Find(pt->m_MasterClass); // class of the method
|
||||||
|
|
||||||
|
if (pt->IsPrivate() && thisClass != funcClass)
|
||||||
|
type.SetType(CBotErrPrivate);
|
||||||
|
|
||||||
|
if (pt->IsProtected() && !thisClass->IsChildOf(funcClass))
|
||||||
|
type.SetType(CBotErrPrivate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
CBotFunction* CBotFunction::FindMethod(long& nIdent, const std::string& name,
|
||||||
|
CBotVar** ppVars, CBotTypResult& TypeOrError,
|
||||||
|
CBotClass* pClass, CBotProgram* program)
|
||||||
|
{
|
||||||
|
TypeOrError.SetType(CBotErrUndefCall); // no routine of the name
|
||||||
|
|
||||||
|
auto methods = pClass->GetFunctions();
|
||||||
|
|
||||||
|
if ( nIdent )
|
||||||
|
{
|
||||||
|
// search methods in the class
|
||||||
|
for (CBotFunction* pt : methods)
|
||||||
|
{
|
||||||
|
if ( pt->m_nFuncIdent == nIdent )
|
||||||
|
{
|
||||||
|
TypeOrError = pt->m_retTyp;
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool skipPublic = false;
|
||||||
|
if (program != nullptr)
|
||||||
|
{
|
||||||
|
// search the current program
|
||||||
|
for (CBotFunction* pt : program->GetFunctions())
|
||||||
|
{
|
||||||
|
if ( pt->m_nFuncIdent == nIdent )
|
||||||
|
{
|
||||||
|
// check if the method is inherited
|
||||||
|
if ( pt->GetClassName() != pClass->GetName() )
|
||||||
|
{
|
||||||
|
skipPublic = true;
|
||||||
|
break; // break in case there is an override
|
||||||
|
}
|
||||||
|
TypeOrError = pt->m_retTyp;
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// search the list of public functions
|
||||||
|
if (!skipPublic)
|
||||||
|
{
|
||||||
|
for (CBotFunction* pt : m_publicFunctions)
|
||||||
|
{
|
||||||
|
if (pt->m_nFuncIdent == nIdent)
|
||||||
|
{
|
||||||
|
// check if the method is inherited, break in case there is an override
|
||||||
|
if ( pt->GetClassName() != pClass->GetName() ) break;
|
||||||
|
TypeOrError = pt->m_retTyp;
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( name.empty() ) return nullptr;
|
||||||
|
|
||||||
|
std::map<CBotFunction*, int> funcMap;
|
||||||
|
|
||||||
|
// search methods in the class
|
||||||
|
CBotFunction::SearchList(methods, name, ppVars, TypeOrError, funcMap, pClass);
|
||||||
|
|
||||||
|
// search the current program for methods
|
||||||
|
if (program != nullptr)
|
||||||
|
CBotFunction::SearchList(program->GetFunctions(), name, ppVars, TypeOrError, funcMap, pClass);
|
||||||
|
|
||||||
|
CBotFunction::SearchPublic(name, ppVars, TypeOrError, funcMap, pClass);
|
||||||
|
|
||||||
|
return CBotFunction::BestFunction(funcMap, nIdent, TypeOrError);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int CBotFunction::DoCall(long &nIdent, const std::string &name, CBotVar* pThis,
|
||||||
|
CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken, CBotClass* pClass)
|
||||||
{
|
{
|
||||||
CBotTypResult type;
|
CBotTypResult type;
|
||||||
CBotProgram* pProgCurrent = pStack->GetProgram();
|
CBotProgram* pProgCurrent = pStack->GetProgram();
|
||||||
|
|
||||||
CBotFunction* pt = FindLocalOrPublic(nIdent, name, ppVars, type, false);
|
CBotFunction* pt = FindMethod(nIdent, name, ppVars, type, pClass, pProgCurrent);
|
||||||
|
|
||||||
if ( pt != nullptr )
|
if ( pt != nullptr )
|
||||||
{
|
{
|
||||||
|
@ -740,6 +1030,11 @@ int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar* pThis,
|
||||||
// preparing parameters on the stack
|
// preparing parameters on the stack
|
||||||
|
|
||||||
if ( pStk->GetState() == 0 )
|
if ( pStk->GetState() == 0 )
|
||||||
|
{
|
||||||
|
// stack for parameters and default args
|
||||||
|
CBotStack* pStk3b = pStk3->AddStack();
|
||||||
|
|
||||||
|
if (pStk3b->GetState() == 0)
|
||||||
{
|
{
|
||||||
// sets the variable "this" on the stack
|
// sets the variable "this" on the stack
|
||||||
CBotVar* pthis = CBotVar::Create("this", CBotTypNullPointer);
|
CBotVar* pthis = CBotVar::Create("this", CBotTypNullPointer);
|
||||||
|
@ -756,8 +1051,22 @@ int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar* pThis,
|
||||||
psuper->SetUniqNum(-3); // special value
|
psuper->SetUniqNum(-3); // special value
|
||||||
pStk->AddVar(psuper);
|
pStk->AddVar(psuper);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
pStk3b->SetState(1); // set 'this' was created
|
||||||
|
|
||||||
// initializes the variables as parameters
|
// initializes the variables as parameters
|
||||||
pt->m_param->Execute(ppVars, pStk3); // cannot be interrupted
|
if (pt->m_param != nullptr)
|
||||||
|
{
|
||||||
|
if (!pt->m_param->Execute(ppVars, pStk3)) // interupt here
|
||||||
|
{
|
||||||
|
if (!pStk3->IsOk() && pt->m_pProg != pProgCurrent)
|
||||||
|
{
|
||||||
|
pStk3->SetPosError(pToken); // indicates the error on the procedure call
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pStk3b->Delete(); // done with param stack
|
||||||
pStk->IncState();
|
pStk->IncState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -801,25 +1110,45 @@ int CBotFunction::DoCall(long& nIdent, const std::string& name, CBotVar* pThis,
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void CBotFunction::RestoreCall(long& nIdent, const std::string& name, CBotVar* pThis, CBotVar** ppVars,
|
bool CBotFunction::RestoreCall(long &nIdent, const std::string &name, CBotVar* pThis,
|
||||||
CBotStack* pStack, CBotClass* pClass)
|
CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass)
|
||||||
{
|
{
|
||||||
CBotTypResult type;
|
CBotTypResult type;
|
||||||
CBotFunction* pt = FindLocalOrPublic(nIdent, name, ppVars, type);
|
CBotFunction* pt = FindMethod(nIdent, name, ppVars, type, pClass, pStack->GetProgram());
|
||||||
|
|
||||||
if ( pt != nullptr )
|
if ( pt != nullptr )
|
||||||
{
|
{
|
||||||
CBotStack* pStk = pStack->RestoreStack(pt);
|
CBotStack* pStk = pStack->RestoreStack(pt);
|
||||||
if ( pStk == nullptr ) return;
|
if ( pStk == nullptr ) return true;
|
||||||
pStk->SetProgram(pt->m_pProg); // it may have changed module
|
pStk->SetProgram(pt->m_pProg); // it may have changed module
|
||||||
|
|
||||||
CBotVar* pthis = pStk->FindVar("this");
|
CBotVar* pthis = pStk->FindVar("this");
|
||||||
pthis->SetUniqNum(-2);
|
pthis->SetUniqNum(-2);
|
||||||
|
|
||||||
CBotStack* pStk3 = pStk->RestoreStack(nullptr); // to set parameters passed
|
if (pClass->GetParent() != nullptr)
|
||||||
if ( pStk3 == nullptr ) return;
|
{
|
||||||
|
CBotVar* psuper = pStk->FindVar("super");
|
||||||
|
if (psuper != nullptr) psuper->SetUniqNum(-3);
|
||||||
|
}
|
||||||
|
|
||||||
pt->m_param->RestoreState(pStk3, true); // parameters
|
CBotStack* pStk3 = pStk->RestoreStack(nullptr); // to set parameters passed
|
||||||
|
if ( pStk3 == nullptr ) return true;
|
||||||
|
|
||||||
|
if ( pStk->GetState() == 0 )
|
||||||
|
{
|
||||||
|
if (pt->m_param != nullptr)
|
||||||
|
{
|
||||||
|
CBotStack* pStk3b = pStk3->RestoreStack();
|
||||||
|
if (pStk3b != nullptr && pStk3b->GetState() == 1)
|
||||||
|
pt->m_param->RestoreState(pStk3, true); // restore executing default arguments
|
||||||
|
else
|
||||||
|
pt->m_param->RestoreState(pStk3, false); // restore parameter IDs
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pt->m_param != nullptr)
|
||||||
|
pt->m_param->RestoreState(pStk3, false); // restore parameter IDs
|
||||||
|
|
||||||
if ( pStk->GetState() > 1 && // latching is effective?
|
if ( pStk->GetState() > 1 && // latching is effective?
|
||||||
pt->m_bSynchro )
|
pt->m_bSynchro )
|
||||||
|
@ -831,7 +1160,9 @@ void CBotFunction::RestoreCall(long& nIdent, const std::string& name, CBotVar* p
|
||||||
// finally calls the found function
|
// finally calls the found function
|
||||||
|
|
||||||
pt->m_block->RestoreState(pStk3, true); // interrupt !
|
pt->m_block->RestoreState(pStk3, true); // interrupt !
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -840,8 +1171,8 @@ bool CBotFunction::CheckParam(CBotDefParam* pParam)
|
||||||
CBotDefParam* pp = m_param;
|
CBotDefParam* pp = m_param;
|
||||||
while ( pp != nullptr && pParam != nullptr )
|
while ( pp != nullptr && pParam != nullptr )
|
||||||
{
|
{
|
||||||
CBotTypResult type1 = pp->GetType();
|
CBotTypResult type1 = pp->GetTypResult();
|
||||||
CBotTypResult type2 = pParam->GetType();
|
CBotTypResult type2 = pParam->GetTypResult();
|
||||||
if ( !type1.Compare(type2) ) return false;
|
if ( !type1.Compare(type2) ) return false;
|
||||||
pp = pp->GetNext();
|
pp = pp->GetNext();
|
||||||
pParam = pParam->GetNext();
|
pParam = pParam->GetNext();
|
||||||
|
@ -850,7 +1181,7 @@ bool CBotFunction::CheckParam(CBotDefParam* pParam)
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
std::string CBotFunction::GetName()
|
const std::string& CBotFunction::GetName()
|
||||||
{
|
{
|
||||||
return m_token.GetString();
|
return m_token.GetString();
|
||||||
}
|
}
|
||||||
|
@ -875,9 +1206,9 @@ std::string CBotFunction::GetParams()
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotFunction* CBotFunction::Next()
|
const std::string& CBotFunction::GetClassName() const
|
||||||
{
|
{
|
||||||
return m_next;
|
return m_MasterClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -886,6 +1217,12 @@ void CBotFunction::AddPublic(CBotFunction* func)
|
||||||
m_publicFunctions.insert(func);
|
m_publicFunctions.insert(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CBotFunction::HasReturn()
|
||||||
|
{
|
||||||
|
if (m_block != nullptr) return m_block->HasReturn();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::string CBotFunction::GetDebugData()
|
std::string CBotFunction::GetDebugData()
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
|
@ -0,0 +1,370 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see http://gnu.org/licenses
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CBot/CBotInstr/CBotInstr.h"
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
namespace CBot
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief A function declaration in the code
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
* \code
|
||||||
|
* void test() { ... }
|
||||||
|
* void test(int a, float b) { ... }
|
||||||
|
* int test(int a, float b, string c) { ... }
|
||||||
|
* public bool test(int a, float b, string c, SomeClass d) { ... }
|
||||||
|
* extern void test() { ... }
|
||||||
|
* void classname::test() { ... }
|
||||||
|
* \endcode
|
||||||
|
*/
|
||||||
|
class CBotFunction : public CBotInstr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CBotFunction();
|
||||||
|
~CBotFunction();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Compile Compiles a new function
|
||||||
|
* \param p
|
||||||
|
* \param pStack
|
||||||
|
* \param pFunc
|
||||||
|
* \param bLocal allows of the declaration of parameters on the same level
|
||||||
|
* as the elements belonging to the class for methods.
|
||||||
|
* \return
|
||||||
|
*/
|
||||||
|
static CBotFunction* Compile(CBotToken* &p,
|
||||||
|
CBotCStack* pStack,
|
||||||
|
CBotFunction* pFunc,
|
||||||
|
bool bLocal = true);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Pre-compile a new function
|
||||||
|
* \param p[in, out] Pointer to first token of the function, will be updated to point to first token after the function definition
|
||||||
|
* \param pStack Compile stack
|
||||||
|
* \param pClass If this is a class method, pointer to class this function is part of, otherwise nullptr
|
||||||
|
*
|
||||||
|
* This function is used to find the beginning and end of function definition.
|
||||||
|
*
|
||||||
|
* If any errors in the code are detected, this function will set the error on compile stack and return nullptr.
|
||||||
|
*
|
||||||
|
* \return Precompiled function, or nullptr in case of error
|
||||||
|
*/
|
||||||
|
static CBotFunction* Compile1(CBotToken* &p,
|
||||||
|
CBotCStack* pStack,
|
||||||
|
CBotClass* pClass);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Execute
|
||||||
|
* \param ppVars
|
||||||
|
* \param pj
|
||||||
|
* \param pInstance
|
||||||
|
* \return
|
||||||
|
*/
|
||||||
|
bool Execute(CBotVar** ppVars,
|
||||||
|
CBotStack* &pj,
|
||||||
|
CBotVar* pInstance = nullptr);
|
||||||
|
|
||||||
|
using CBotInstr::Execute;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief RestoreState
|
||||||
|
* \param ppVars
|
||||||
|
* \param pj
|
||||||
|
* \param pInstance
|
||||||
|
*/
|
||||||
|
void RestoreState(CBotVar** ppVars,
|
||||||
|
CBotStack* &pj,
|
||||||
|
CBotVar* pInstance = nullptr);
|
||||||
|
|
||||||
|
using CBotInstr::RestoreState;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Compile a function call
|
||||||
|
*
|
||||||
|
* See FindLocalOrPublic for more detailed explanation
|
||||||
|
*
|
||||||
|
* \param name Name of the function
|
||||||
|
* \param ppVars List of function arguments
|
||||||
|
* \param nIdent[in, out] Unique identifier of the function
|
||||||
|
* \param program The current program, to search for functions.
|
||||||
|
* \return Type returned by the function or error code
|
||||||
|
* \see FindLocalOrPublic
|
||||||
|
*/
|
||||||
|
static CBotTypResult CompileCall(const std::string &name, CBotVar** ppVars,
|
||||||
|
long &nIdent, CBotProgram* program);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Finds a local or public function
|
||||||
|
*
|
||||||
|
* <p>First, it looks for a function according to its unique identifier.<br>
|
||||||
|
* If the identifier is not found, looks by name and parameters.
|
||||||
|
*
|
||||||
|
* \param localFunctionList Linked list of local functions to search in, can be null
|
||||||
|
* \param nIdent[in, out] Unique identifier of the function
|
||||||
|
* \param name Name of the function
|
||||||
|
* \param ppVars List of function arguments
|
||||||
|
* \param TypeOrError Type returned by the function or error code
|
||||||
|
* \param baseProg Initial program, for context of the object/bot
|
||||||
|
* \return Pointer to found CBotFunction instance, or nullptr in case of no match or ambiguity (see TypeOrError for error code)
|
||||||
|
*/
|
||||||
|
static CBotFunction* FindLocalOrPublic(const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name,
|
||||||
|
CBotVar** ppVars, CBotTypResult &TypeOrError, CBotProgram* baseProg);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Find all functions that match the name and arguments.
|
||||||
|
* \param functionList List of functions to search, can be empty.
|
||||||
|
* \param name Name of the function to find.
|
||||||
|
* \param ppVars Arguments to compare with parameters.
|
||||||
|
* \param TypeOrError Contains a CBotError when no useable function has been found.
|
||||||
|
* \param funcMap Container for suitable functions and their signature values.
|
||||||
|
* \param pClass Pointer to class when searching for methods.
|
||||||
|
*/
|
||||||
|
static void SearchList(const std::list<CBotFunction*>& functionList,
|
||||||
|
const std::string& name, CBotVar** ppVars, CBotTypResult& TypeOrError,
|
||||||
|
std::map<CBotFunction*, int>& funcMap, CBotClass* pClass = nullptr);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Find all public functions that match the name and arguments.
|
||||||
|
* \param name Name of the function to find.
|
||||||
|
* \param ppVars Arguments to compare with parameters.
|
||||||
|
* \param TypeOrError Contains a CBotError when no useable function has been found.
|
||||||
|
* \param funcMap Container for suitable functions and their signature values.
|
||||||
|
* \param pClass Pointer to class when searching for methods.
|
||||||
|
*/
|
||||||
|
static void SearchPublic(const std::string& name, CBotVar** ppVars, CBotTypResult& TypeOrError,
|
||||||
|
std::map<CBotFunction*, int>& funcMap, CBotClass* pClass = nullptr);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Find the function with the lowest signature value. If there is more
|
||||||
|
* than one of the same signature value, TypeOrError is set to CBotErrAmbiguousCall.
|
||||||
|
* \param funcMap List of functions and their signature values, can be empty.
|
||||||
|
* \param[out] nIdent Unique identifier of the function.
|
||||||
|
* \param TypeOrError Type returned by the function or error code.
|
||||||
|
* \return Pointer to the function with the lowest signature or nullptr.
|
||||||
|
*/
|
||||||
|
static CBotFunction* BestFunction(std::map<CBotFunction*, int>& funcMap,
|
||||||
|
long& nIdent, CBotTypResult& TypeOrError);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief DoCall Fait un appel à une fonction.
|
||||||
|
* \param program
|
||||||
|
* \param localFunctionList
|
||||||
|
* \param nIdent
|
||||||
|
* \param name
|
||||||
|
* \param ppVars
|
||||||
|
* \param pStack
|
||||||
|
* \param pToken
|
||||||
|
* \return
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int DoCall(CBotProgram* program, const std::list<CBotFunction*>& localFunctionList, long &nIdent, const std::string &name,
|
||||||
|
CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief RestoreCall
|
||||||
|
* \param localFunctionList
|
||||||
|
* \param nIdent
|
||||||
|
* \param name
|
||||||
|
* \param ppVars
|
||||||
|
* \param pStack
|
||||||
|
*/
|
||||||
|
static void RestoreCall(const std::list<CBotFunction*>& localFunctionList,
|
||||||
|
long &nIdent, const std::string &name, CBotVar** ppVars, CBotStack* pStack);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Find a method matching the name and arguments.
|
||||||
|
* \param name Name of the method to find.
|
||||||
|
* \param ppVars Arguments to compare with parameters.
|
||||||
|
* \param[out] nIdent Unique identifier of the method.
|
||||||
|
* \param pStack Current compilation stack frame.
|
||||||
|
* \param pClass Pointer to the class.
|
||||||
|
* \return The return type for the method or a CBotError.
|
||||||
|
*/
|
||||||
|
static CBotTypResult CompileMethodCall(const std::string& name, CBotVar** ppVars,
|
||||||
|
long& nIdent, CBotCStack* pStack, CBotClass* pClass);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Find a method by its unique identifier or by name and parameters.
|
||||||
|
* \param[in,out] nIdent Unique identifier of the method.
|
||||||
|
* \param name Name of the method to find.
|
||||||
|
* \param ppVars Arguments to compare with parameters.
|
||||||
|
* \param TypeOrError The return type for the method or a CBotError.
|
||||||
|
* \param pClass Pointer to the class.
|
||||||
|
* \param program The current program, to search for out-of-class methods.
|
||||||
|
* \return Pointer to the method that best matches the given arguments or nullptr.
|
||||||
|
*/
|
||||||
|
static CBotFunction* FindMethod(long& nIdent, const std::string& name,
|
||||||
|
CBotVar** ppVars, CBotTypResult& TypeOrError,
|
||||||
|
CBotClass* pClass, CBotProgram* program);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief DoCall Makes call of a method
|
||||||
|
* \param nIdent
|
||||||
|
* \param name
|
||||||
|
* \param pThis
|
||||||
|
* \param ppVars
|
||||||
|
* \param pStack
|
||||||
|
* \param pToken
|
||||||
|
* \param pClass
|
||||||
|
* \return
|
||||||
|
*/
|
||||||
|
static int DoCall(long &nIdent, const std::string &name, CBotVar* pThis,
|
||||||
|
CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken, CBotClass* pClass);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief RestoreCall
|
||||||
|
* \param nIdent
|
||||||
|
* \param name
|
||||||
|
* \param pThis
|
||||||
|
* \param ppVars
|
||||||
|
* \param pStack
|
||||||
|
* \param pClass
|
||||||
|
* \return Returns true if the method call was restored.
|
||||||
|
*/
|
||||||
|
static bool RestoreCall(long &nIdent, const std::string &name, CBotVar* pThis,
|
||||||
|
CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief CheckParam See if the "signature" of parameters is identical.
|
||||||
|
* \param pParam
|
||||||
|
* \return
|
||||||
|
*/
|
||||||
|
bool CheckParam(CBotDefParam* pParam);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief AddPublic
|
||||||
|
* \param pfunc
|
||||||
|
*/
|
||||||
|
static void AddPublic(CBotFunction* pfunc);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief GetName
|
||||||
|
* \return
|
||||||
|
*/
|
||||||
|
const std::string& GetName();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief GetParams
|
||||||
|
* \return
|
||||||
|
*/
|
||||||
|
std::string GetParams();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Get the name of the class for a method.
|
||||||
|
* \return The name of a class or empty string if it's not a method.
|
||||||
|
*/
|
||||||
|
const std::string& GetClassName() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief IsPublic
|
||||||
|
* \return
|
||||||
|
*/
|
||||||
|
bool IsPublic();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Check if a method is protected.
|
||||||
|
* \return true if a method was compiled with "protected" keyword.
|
||||||
|
*/
|
||||||
|
bool IsProtected() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Check if a method is private.
|
||||||
|
* \return true if a method was compiled with "private" keyword.
|
||||||
|
*/
|
||||||
|
bool IsPrivate() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief IsExtern
|
||||||
|
* \return
|
||||||
|
*/
|
||||||
|
bool IsExtern();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief GetPosition
|
||||||
|
* \param start
|
||||||
|
* \param stop
|
||||||
|
* \param modestart
|
||||||
|
* \param modestop
|
||||||
|
* \return
|
||||||
|
*/
|
||||||
|
bool GetPosition(int& start, int& stop,
|
||||||
|
CBotGet modestart,
|
||||||
|
CBotGet modestop);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Check if the function has a return statment that will execute.
|
||||||
|
* \return true if a return statment was found.
|
||||||
|
*/
|
||||||
|
bool HasReturn() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual const std::string GetDebugName() override { return "CBotFunction"; }
|
||||||
|
virtual std::string GetDebugData() override;
|
||||||
|
virtual std::map<std::string, CBotInstr*> GetDebugLinks() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class CBotDebug;
|
||||||
|
long m_nFuncIdent;
|
||||||
|
//! Synchronized method.
|
||||||
|
bool m_bSynchro;
|
||||||
|
|
||||||
|
//! Parameter list.
|
||||||
|
CBotDefParam* m_param;
|
||||||
|
//! The instruction block.
|
||||||
|
CBotInstr* m_block;
|
||||||
|
//! If returns CBotTypClass.
|
||||||
|
CBotToken m_retToken;
|
||||||
|
//! Complete type of the result.
|
||||||
|
CBotTypResult m_retTyp;
|
||||||
|
//! Public function.
|
||||||
|
bool m_bPublic;
|
||||||
|
//! Protected method.
|
||||||
|
bool m_bProtect = false;
|
||||||
|
//! Private method.
|
||||||
|
bool m_bPrivate = false;
|
||||||
|
//! Extern function.
|
||||||
|
bool m_bExtern;
|
||||||
|
//! Name of the class we are part of
|
||||||
|
std::string m_MasterClass;
|
||||||
|
//! Token of the class we are part of
|
||||||
|
CBotToken m_classToken;
|
||||||
|
CBotProgram* m_pProg;
|
||||||
|
//! For the position of the word "extern".
|
||||||
|
CBotToken m_extern;
|
||||||
|
CBotToken m_openpar;
|
||||||
|
CBotToken m_closepar;
|
||||||
|
CBotToken m_openblk;
|
||||||
|
CBotToken m_closeblk;
|
||||||
|
|
||||||
|
//! List of public functions
|
||||||
|
static std::set<CBotFunction*> m_publicFunctions;
|
||||||
|
|
||||||
|
friend class CBotProgram;
|
||||||
|
friend class CBotClass;
|
||||||
|
friend class CBotCStack;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace CBot
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -163,6 +163,15 @@ void CBotIf :: RestoreState(CBotStack* &pj, bool bMain)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CBotIf::HasReturn()
|
||||||
|
{
|
||||||
|
if (m_block != nullptr && m_blockElse != nullptr)
|
||||||
|
{
|
||||||
|
if (m_block->HasReturn() && m_blockElse->HasReturn()) return true;
|
||||||
|
}
|
||||||
|
return CBotInstr::HasReturn(); // check next block or instruction
|
||||||
|
}
|
||||||
|
|
||||||
std::map<std::string, CBotInstr*> CBotIf::GetDebugLinks()
|
std::map<std::string, CBotInstr*> CBotIf::GetDebugLinks()
|
||||||
{
|
{
|
||||||
auto links = CBotInstr::GetDebugLinks();
|
auto links = CBotInstr::GetDebugLinks();
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -56,6 +56,14 @@ public:
|
||||||
*/
|
*/
|
||||||
void RestoreState(CBotStack* &pj, bool bMain) override;
|
void RestoreState(CBotStack* &pj, bool bMain) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check 'if' and 'else' for return statements.
|
||||||
|
* Returns true when 'if' and 'else' have return statements,
|
||||||
|
* if not, the next block or instruction is checked.
|
||||||
|
* \return true if a return statement is found.
|
||||||
|
*/
|
||||||
|
bool HasReturn() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual const std::string GetDebugName() override { return "CBotIf"; }
|
virtual const std::string GetDebugName() override { return "CBotIf"; }
|
||||||
virtual std::map<std::string, CBotInstr*> GetDebugLinks() override;
|
virtual std::map<std::string, CBotInstr*> GetDebugLinks() override;
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -69,6 +69,7 @@ private:
|
||||||
CBotInstr* m_expr;
|
CBotInstr* m_expr;
|
||||||
friend class CBotLeftExpr;
|
friend class CBotLeftExpr;
|
||||||
friend class CBotExprVar;
|
friend class CBotExprVar;
|
||||||
|
friend class CBotExprRetVar;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CBot
|
} // namespace CBot
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -30,6 +30,7 @@
|
||||||
#include "CBot/CBotInstr/CBotExpression.h"
|
#include "CBot/CBotInstr/CBotExpression.h"
|
||||||
#include "CBot/CBotInstr/CBotFor.h"
|
#include "CBot/CBotInstr/CBotFor.h"
|
||||||
#include "CBot/CBotInstr/CBotIf.h"
|
#include "CBot/CBotInstr/CBotIf.h"
|
||||||
|
#include "CBot/CBotInstr/CBotRepeat.h"
|
||||||
#include "CBot/CBotInstr/CBotReturn.h"
|
#include "CBot/CBotInstr/CBotReturn.h"
|
||||||
#include "CBot/CBotInstr/CBotSwitch.h"
|
#include "CBot/CBotInstr/CBotSwitch.h"
|
||||||
#include "CBot/CBotInstr/CBotThrow.h"
|
#include "CBot/CBotInstr/CBotThrow.h"
|
||||||
|
@ -176,7 +177,7 @@ CBotInstr* CBotInstr::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
{
|
{
|
||||||
type = pp->GetType();
|
type = pp->GetType();
|
||||||
// Allow only instructions that accept a label
|
// Allow only instructions that accept a label
|
||||||
if (!IsOfTypeList(pp, ID_WHILE, ID_FOR, ID_DO, 0))
|
if (!IsOfTypeList(pp, ID_WHILE, ID_FOR, ID_DO, ID_REPEAT, 0))
|
||||||
{
|
{
|
||||||
pStack->SetError(CBotErrLabel, pp->GetStart());
|
pStack->SetError(CBotErrLabel, pp->GetStart());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -195,6 +196,9 @@ CBotInstr* CBotInstr::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
case ID_DO:
|
case ID_DO:
|
||||||
return CBotDo::Compile(p, pStack);
|
return CBotDo::Compile(p, pStack);
|
||||||
|
|
||||||
|
case ID_REPEAT:
|
||||||
|
return CBotRepeat::Compile(p, pStack);
|
||||||
|
|
||||||
case ID_BREAK:
|
case ID_BREAK:
|
||||||
case ID_CONTINUE:
|
case ID_CONTINUE:
|
||||||
return CBotBreak::Compile(p, pStack);
|
return CBotBreak::Compile(p, pStack);
|
||||||
|
@ -208,10 +212,15 @@ CBotInstr* CBotInstr::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
case ID_THROW:
|
case ID_THROW:
|
||||||
return CBotThrow::Compile(p, pStack);
|
return CBotThrow::Compile(p, pStack);
|
||||||
|
|
||||||
|
case ID_BYTE:
|
||||||
|
case ID_SHORT:
|
||||||
|
case ID_CHAR:
|
||||||
case ID_INT:
|
case ID_INT:
|
||||||
|
case ID_LONG:
|
||||||
return CBotDefInt::Compile(p, pStack);
|
return CBotDefInt::Compile(p, pStack);
|
||||||
|
|
||||||
case ID_FLOAT:
|
case ID_FLOAT:
|
||||||
|
case ID_DOUBLE:
|
||||||
return CBotDefFloat::Compile(p, pStack);
|
return CBotDefFloat::Compile(p, pStack);
|
||||||
|
|
||||||
case ID_STRING:
|
case ID_STRING:
|
||||||
|
@ -312,13 +321,6 @@ void CBotInstr::RestoreStateVar(CBotStack* &pile, bool bMain)
|
||||||
assert(0); // dad do not know, see the girls
|
assert(0); // dad do not know, see the girls
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
bool CBotInstr::CompCase(CBotStack* &pj, int val)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
CBotInstr* CBotInstr::CompileArray(CBotToken* &p, CBotCStack* pStack, CBotTypResult type, bool first)
|
CBotInstr* CBotInstr::CompileArray(CBotToken* &p, CBotCStack* pStack, CBotTypResult type, bool first)
|
||||||
{
|
{
|
||||||
if (IsOfType(p, ID_OPBRK))
|
if (IsOfType(p, ID_OPBRK))
|
||||||
|
@ -359,6 +361,12 @@ CBotInstr* CBotInstr::CompileArray(CBotToken* &p, CBotCStack* pStack, CBotTypRes
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CBotInstr::HasReturn()
|
||||||
|
{
|
||||||
|
if (m_next != nullptr) return m_next->HasReturn();
|
||||||
|
return false; // end of the list
|
||||||
|
}
|
||||||
|
|
||||||
std::map<std::string, CBotInstr*> CBotInstr::GetDebugLinks()
|
std::map<std::string, CBotInstr*> CBotInstr::GetDebugLinks()
|
||||||
{
|
{
|
||||||
return {
|
return {
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -38,7 +38,7 @@ class CBotDebug;
|
||||||
* \endcode
|
* \endcode
|
||||||
* the following structure is generated:
|
* the following structure is generated:
|
||||||
* \dot
|
* \dot
|
||||||
* # Generated using the CBot_compile_graph tool
|
* # Generated using the CBot-CompileGraph tool
|
||||||
* # and slightly modified
|
* # and slightly modified
|
||||||
* digraph {
|
* digraph {
|
||||||
* start [label=<START> shape=box3d color=cyan]
|
* start [label=<START> shape=box3d color=cyan]
|
||||||
|
@ -191,17 +191,6 @@ public:
|
||||||
virtual void RestoreStateVar(CBotStack* &pile,
|
virtual void RestoreStateVar(CBotStack* &pile,
|
||||||
bool bMain);
|
bool bMain);
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief CompCase This routine is defined only for the subclass CBotCase
|
|
||||||
* this allows to make the call on all instructions CompCase to see if it's
|
|
||||||
* a case to the desired value..
|
|
||||||
* \param pj
|
|
||||||
* \param val
|
|
||||||
* \return
|
|
||||||
*/
|
|
||||||
virtual bool CompCase(CBotStack* &pj,
|
|
||||||
int val);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief SetToken Set the token corresponding to the instruction.
|
* \brief SetToken Set the token corresponding to the instruction.
|
||||||
* \param p
|
* \param p
|
||||||
|
@ -281,6 +270,12 @@ public:
|
||||||
*/
|
*/
|
||||||
static bool ChkLvl(const std::string& label, int type);
|
static bool ChkLvl(const std::string& label, int type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check a list of instructions for a return statement.
|
||||||
|
* \return true if a return statement was found.
|
||||||
|
*/
|
||||||
|
virtual bool HasReturn();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class CBotDebug;
|
friend class CBotDebug;
|
||||||
/**
|
/**
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -18,7 +18,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "CBot/CBotInstr/CBotInstrCall.h"
|
#include "CBot/CBotInstr/CBotInstrCall.h"
|
||||||
#include "CBot/CBotInstr/CBotExpression.h"
|
#include "CBot/CBotInstr/CBotExprRetVar.h"
|
||||||
|
#include "CBot/CBotInstr/CBotInstrUtils.h"
|
||||||
|
|
||||||
#include "CBot/CBotStack.h"
|
#include "CBot/CBotStack.h"
|
||||||
|
|
||||||
|
@ -35,6 +36,7 @@ namespace CBot
|
||||||
CBotInstrCall::CBotInstrCall()
|
CBotInstrCall::CBotInstrCall()
|
||||||
{
|
{
|
||||||
m_parameters = nullptr;
|
m_parameters = nullptr;
|
||||||
|
m_exprRetVar = nullptr;
|
||||||
m_nFuncIdent = 0;
|
m_nFuncIdent = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,67 +44,32 @@ CBotInstrCall::CBotInstrCall()
|
||||||
CBotInstrCall::~CBotInstrCall()
|
CBotInstrCall::~CBotInstrCall()
|
||||||
{
|
{
|
||||||
delete m_parameters;
|
delete m_parameters;
|
||||||
|
delete m_exprRetVar;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack)
|
CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
{
|
{
|
||||||
CBotVar* ppVars[1000];
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
CBotToken* pp = p;
|
CBotToken* pp = p;
|
||||||
p = p->GetNext();
|
p = p->GetNext();
|
||||||
|
|
||||||
pStack->SetStartError(p->GetStart());
|
if (p->GetType() == ID_OPENPAR)
|
||||||
CBotCStack* pile = pStack;
|
|
||||||
|
|
||||||
if ( IsOfType(p, ID_OPENPAR) )
|
|
||||||
{
|
{
|
||||||
int start, end;
|
|
||||||
|
CBotVar* ppVars[1000];
|
||||||
|
|
||||||
CBotInstrCall* inst = new CBotInstrCall();
|
CBotInstrCall* inst = new CBotInstrCall();
|
||||||
inst->SetToken(pp);
|
inst->SetToken(pp);
|
||||||
|
|
||||||
// compile la list of parameters
|
// compile la list of parameters
|
||||||
if (!IsOfType(p, ID_CLOSEPAR)) while (true)
|
inst->m_parameters = CompileParams(p, pStack, ppVars);
|
||||||
{
|
|
||||||
start = p->GetStart();
|
|
||||||
pile = pile->TokenStack(); // keeps the results on the stack
|
|
||||||
|
|
||||||
CBotInstr* param = CBotExpression::Compile(p, pile);
|
if ( !pStack->IsOk() )
|
||||||
end = p->GetStart();
|
|
||||||
if (inst->m_parameters == nullptr ) inst->m_parameters = param;
|
|
||||||
else inst->m_parameters->AddNext(param); // constructs the list
|
|
||||||
|
|
||||||
if ( !pile->IsOk() )
|
|
||||||
{
|
{
|
||||||
delete inst;
|
|
||||||
return pStack->Return(nullptr, pile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( param != nullptr )
|
|
||||||
{
|
|
||||||
if ( pile->GetTypResult().Eq(99) )
|
|
||||||
{
|
|
||||||
delete pStack->TokenStack();
|
|
||||||
pStack->SetError(CBotErrVoid, p->GetStart());
|
|
||||||
delete inst;
|
delete inst;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
ppVars[i] = pile->GetVar();
|
|
||||||
ppVars[i]->GetToken()->SetPos(start, end);
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if (IsOfType(p, ID_COMMA)) continue; // skips the comma
|
|
||||||
if (IsOfType(p, ID_CLOSEPAR)) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pStack->SetError(CBotErrClosePar, p->GetStart());
|
|
||||||
delete pStack->TokenStack();
|
|
||||||
delete inst;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
ppVars[i] = nullptr;
|
|
||||||
|
|
||||||
// the routine is known?
|
// the routine is known?
|
||||||
// CBotClass* pClass = nullptr;
|
// CBotClass* pClass = nullptr;
|
||||||
|
@ -111,12 +78,12 @@ CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
{
|
{
|
||||||
// if (pVar2!=nullptr) pp = pVar2->RetToken();
|
// if (pVar2!=nullptr) pp = pVar2->RetToken();
|
||||||
pStack->SetError( static_cast<CBotError>(inst->m_typRes.GetType()), pp );
|
pStack->SetError( static_cast<CBotError>(inst->m_typRes.GetType()), pp );
|
||||||
delete pStack->TokenStack();
|
pStack->DeleteNext();
|
||||||
delete inst;
|
delete inst;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete pStack->TokenStack();
|
pStack->DeleteNext();
|
||||||
if ( inst->m_typRes.GetType() > 0 )
|
if ( inst->m_typRes.GetType() > 0 )
|
||||||
{
|
{
|
||||||
CBotVar* pRes = CBotVar::Create("", inst->m_typRes);
|
CBotVar* pRes = CBotVar::Create("", inst->m_typRes);
|
||||||
|
@ -124,10 +91,21 @@ CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
}
|
}
|
||||||
else pStack->SetVar(nullptr); // routine returns void
|
else pStack->SetVar(nullptr); // routine returns void
|
||||||
|
|
||||||
|
if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStack)))
|
||||||
|
{
|
||||||
|
inst->m_exprRetVar->SetToken(&inst->m_token);
|
||||||
|
pStack->DeleteNext();
|
||||||
|
}
|
||||||
|
if ( !pStack->IsOk() )
|
||||||
|
{
|
||||||
|
delete inst;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
p = pp;
|
p = pp;
|
||||||
delete pStack->TokenStack();
|
pStack->DeleteNext();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +116,17 @@ bool CBotInstrCall::Execute(CBotStack* &pj)
|
||||||
CBotStack* pile = pj->AddStack(this);
|
CBotStack* pile = pj->AddStack(this);
|
||||||
if ( pile->StackOver() ) return pj->Return( pile );
|
if ( pile->StackOver() ) return pj->Return( pile );
|
||||||
|
|
||||||
|
CBotStack* pile3 = nullptr;
|
||||||
|
if (m_exprRetVar != nullptr) // func().member
|
||||||
|
{
|
||||||
|
pile3 = pile->AddStack2();
|
||||||
|
if (pile3->GetState() == 1) // function call is done?
|
||||||
|
{
|
||||||
|
if (!m_exprRetVar->Execute(pile3)) return false;
|
||||||
|
return pj->Return(pile3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// CBotStack* pile1 = pile;
|
// CBotStack* pile1 = pile;
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -149,6 +138,7 @@ bool CBotInstrCall::Execute(CBotStack* &pj)
|
||||||
if ( p != nullptr) while ( true )
|
if ( p != nullptr) while ( true )
|
||||||
{
|
{
|
||||||
pile = pile->AddStack(); // place on the stack for the results
|
pile = pile->AddStack(); // place on the stack for the results
|
||||||
|
if (pile->StackOver()) return pj->Return(pile);
|
||||||
if ( pile->GetState() == 0 )
|
if ( pile->GetState() == 0 )
|
||||||
{
|
{
|
||||||
if (!p->Execute(pile)) return false; // interrupted here?
|
if (!p->Execute(pile)) return false; // interrupted here?
|
||||||
|
@ -165,6 +155,14 @@ bool CBotInstrCall::Execute(CBotStack* &pj)
|
||||||
|
|
||||||
if ( !pile2->ExecuteCall(m_nFuncIdent, GetToken(), ppVars, m_typRes)) return false; // interrupt
|
if ( !pile2->ExecuteCall(m_nFuncIdent, GetToken(), ppVars, m_typRes)) return false; // interrupt
|
||||||
|
|
||||||
|
if (m_exprRetVar != nullptr) // func().member
|
||||||
|
{
|
||||||
|
pile3->SetCopyVar( pile2->GetVar() ); // copy the result
|
||||||
|
pile2->SetVar(nullptr);
|
||||||
|
pile3->SetState(1); // set call is done
|
||||||
|
return false; // go back to the top ^^^
|
||||||
|
}
|
||||||
|
|
||||||
return pj->Return(pile2); // release the entire stack
|
return pj->Return(pile2); // release the entire stack
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,6 +174,16 @@ void CBotInstrCall::RestoreState(CBotStack* &pj, bool bMain)
|
||||||
CBotStack* pile = pj->RestoreStack(this);
|
CBotStack* pile = pj->RestoreStack(this);
|
||||||
if ( pile == nullptr ) return;
|
if ( pile == nullptr ) return;
|
||||||
|
|
||||||
|
if (m_exprRetVar != nullptr) // func().member
|
||||||
|
{
|
||||||
|
CBotStack* pile3 = pile->AddStack2();
|
||||||
|
if (pile3->GetState() == 1) // function call is done?
|
||||||
|
{
|
||||||
|
m_exprRetVar->RestoreState(pile3, bMain);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// CBotStack* pile1 = pile;
|
// CBotStack* pile1 = pile;
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -69,6 +69,10 @@ private:
|
||||||
CBotTypResult m_typRes;
|
CBotTypResult m_typRes;
|
||||||
//! Id of a function.
|
//! Id of a function.
|
||||||
long m_nFuncIdent;
|
long m_nFuncIdent;
|
||||||
|
|
||||||
|
//! Instruction to return a member of the returned object.
|
||||||
|
CBotInstr* m_exprRetVar;
|
||||||
|
|
||||||
friend class CBotDebug;
|
friend class CBotDebug;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -20,6 +20,7 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "CBot/CBotInstr/CBotInstrMethode.h"
|
#include "CBot/CBotInstr/CBotInstrMethode.h"
|
||||||
|
|
||||||
|
#include "CBot/CBotInstr/CBotExprRetVar.h"
|
||||||
#include "CBot/CBotInstr/CBotInstrUtils.h"
|
#include "CBot/CBotInstr/CBotInstrUtils.h"
|
||||||
|
|
||||||
#include "CBot/CBotStack.h"
|
#include "CBot/CBotStack.h"
|
||||||
|
@ -35,6 +36,7 @@ namespace CBot
|
||||||
CBotInstrMethode::CBotInstrMethode()
|
CBotInstrMethode::CBotInstrMethode()
|
||||||
{
|
{
|
||||||
m_parameters = nullptr;
|
m_parameters = nullptr;
|
||||||
|
m_exprRetVar = nullptr;
|
||||||
m_MethodeIdent = 0;
|
m_MethodeIdent = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,10 +44,11 @@ CBotInstrMethode::CBotInstrMethode()
|
||||||
CBotInstrMethode::~CBotInstrMethode()
|
CBotInstrMethode::~CBotInstrMethode()
|
||||||
{
|
{
|
||||||
delete m_parameters;
|
delete m_parameters;
|
||||||
|
delete m_exprRetVar;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotInstr* CBotInstrMethode::Compile(CBotToken* &p, CBotCStack* pStack, CBotVar* var)
|
CBotInstr* CBotInstrMethode::Compile(CBotToken* &p, CBotCStack* pStack, CBotVar* var, bool bMethodChain)
|
||||||
{
|
{
|
||||||
CBotInstrMethode* inst = new CBotInstrMethode();
|
CBotInstrMethode* inst = new CBotInstrMethode();
|
||||||
inst->SetToken(p); // corresponding token
|
inst->SetToken(p); // corresponding token
|
||||||
|
@ -63,11 +66,11 @@ CBotInstr* CBotInstrMethode::Compile(CBotToken* &p, CBotCStack* pStack, CBotVar*
|
||||||
|
|
||||||
if (pStack->IsOk())
|
if (pStack->IsOk())
|
||||||
{
|
{
|
||||||
|
inst->m_thisIdent = var->GetUniqNum();
|
||||||
CBotClass* pClass = var->GetClass(); // pointer to the class
|
CBotClass* pClass = var->GetClass(); // pointer to the class
|
||||||
inst->m_className = pClass->GetName(); // name of the class
|
inst->m_className = pClass->GetName(); // name of the class
|
||||||
CBotTypResult r = pClass->CompileMethode(inst->m_methodName, var, ppVars,
|
CBotTypResult r = pClass->CompileMethode(pp, var, ppVars, pStack, inst->m_MethodeIdent);
|
||||||
pStack, inst->m_MethodeIdent);
|
pStack->DeleteNext(); // release parameters on the stack
|
||||||
delete pStack->TokenStack(); // release parameters on the stack
|
|
||||||
inst->m_typRes = r;
|
inst->m_typRes = r;
|
||||||
|
|
||||||
if (inst->m_typRes.GetType() > 20)
|
if (inst->m_typRes.GetType() > 20)
|
||||||
|
@ -86,6 +89,16 @@ CBotInstr* CBotInstrMethode::Compile(CBotToken* &p, CBotCStack* pStack, CBotVar*
|
||||||
}
|
}
|
||||||
pStack->SetVar(pResult);
|
pStack->SetVar(pResult);
|
||||||
}
|
}
|
||||||
|
else pStack->SetVar(nullptr);
|
||||||
|
|
||||||
|
pp = p;
|
||||||
|
if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStack, bMethodChain)))
|
||||||
|
{
|
||||||
|
inst->m_exprRetVar->SetToken(pp);
|
||||||
|
pStack->DeleteNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pStack->IsOk() )
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
delete inst;
|
delete inst;
|
||||||
|
@ -103,6 +116,19 @@ bool CBotInstrMethode::ExecuteVar(CBotVar* &pVar, CBotStack* &pj, CBotToken* pre
|
||||||
if (pVar->GetPointer() == nullptr)
|
if (pVar->GetPointer() == nullptr)
|
||||||
{
|
{
|
||||||
pj->SetError(CBotErrNull, prevToken);
|
pj->SetError(CBotErrNull, prevToken);
|
||||||
|
return pj->Return(pile1);
|
||||||
|
}
|
||||||
|
|
||||||
|
CBotStack* pile3 = nullptr;
|
||||||
|
if (m_exprRetVar != nullptr) // .func().member
|
||||||
|
{
|
||||||
|
pile3 = pile1->AddStack2();
|
||||||
|
if (pile3->GetState() == 1)
|
||||||
|
{
|
||||||
|
if (!m_exprRetVar->Execute(pile3)) return false;
|
||||||
|
pVar = nullptr;
|
||||||
|
return pj->Return(pile3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pile1->IfStep()) return false;
|
if (pile1->IfStep()) return false;
|
||||||
|
@ -119,7 +145,7 @@ bool CBotInstrMethode::ExecuteVar(CBotVar* &pVar, CBotStack* &pj, CBotToken* pre
|
||||||
|
|
||||||
pThis->SetName("this");
|
pThis->SetName("this");
|
||||||
pThis->SetUniqNum(-2);
|
pThis->SetUniqNum(-2);
|
||||||
pile1->AddVar(pThis);
|
pile1->SetVar(pThis);
|
||||||
pile1->IncState();
|
pile1->IncState();
|
||||||
}
|
}
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -138,25 +164,30 @@ bool CBotInstrMethode::ExecuteVar(CBotVar* &pVar, CBotStack* &pj, CBotToken* pre
|
||||||
}
|
}
|
||||||
ppVars[i++] = pile2->GetVar(); // construct the list of pointers
|
ppVars[i++] = pile2->GetVar(); // construct the list of pointers
|
||||||
pile2 = pile2->AddStack(); // space on the stack for the result
|
pile2 = pile2->AddStack(); // space on the stack for the result
|
||||||
|
if (pile2->StackOver()) return pj->Return(pile2);
|
||||||
p = p->GetNext();
|
p = p->GetNext();
|
||||||
if ( p == nullptr) break;
|
if ( p == nullptr) break;
|
||||||
}
|
}
|
||||||
ppVars[i] = nullptr;
|
ppVars[i] = nullptr;
|
||||||
|
|
||||||
CBotClass* pClass = CBotClass::Find(m_className);
|
CBotVar* pThis = pile1->GetVar();
|
||||||
CBotVar* pThis = pile1->FindVar(-2, false);
|
CBotClass* pClass;
|
||||||
CBotVar* pResult = nullptr;
|
|
||||||
if (m_typRes.GetType() > 0) pResult = CBotVar::Create("", m_typRes);
|
|
||||||
if (m_typRes.Eq(CBotTypClass))
|
|
||||||
{
|
|
||||||
pResult->SetClass(m_typRes.GetClass());
|
|
||||||
}
|
|
||||||
CBotVar* pRes = pResult;
|
|
||||||
|
|
||||||
if ( !pClass->ExecuteMethode(m_MethodeIdent, m_methodName,
|
if (m_thisIdent == -3) // super.method()
|
||||||
pThis, ppVars,
|
pClass = CBotClass::Find(m_className);
|
||||||
pResult, pile2, GetToken())) return false;
|
else
|
||||||
if (pRes != pResult) delete pRes;
|
pClass = pThis->GetClass();
|
||||||
|
|
||||||
|
if ( !pClass->ExecuteMethode(m_MethodeIdent, pThis, ppVars, m_typRes, pile2, GetToken())) return false;
|
||||||
|
|
||||||
|
if (m_exprRetVar != nullptr) // .func().member
|
||||||
|
{
|
||||||
|
pile3->SetCopyVar( pile2->GetVar() );
|
||||||
|
pile2->SetVar(nullptr);
|
||||||
|
pile3->SetState(1); // set call is done
|
||||||
|
pVar = nullptr;
|
||||||
|
return false; // go back to the top ^^^
|
||||||
|
}
|
||||||
|
|
||||||
pVar = nullptr; // does not return value for this
|
pVar = nullptr; // does not return value for this
|
||||||
return pj->Return(pile2); // release the entire stack
|
return pj->Return(pile2); // release the entire stack
|
||||||
|
@ -171,10 +202,23 @@ void CBotInstrMethode::RestoreStateVar(CBotStack* &pile, bool bMain)
|
||||||
CBotStack* pile1 = pile->RestoreStack(this); // place for the copy of This
|
CBotStack* pile1 = pile->RestoreStack(this); // place for the copy of This
|
||||||
if (pile1 == nullptr) return;
|
if (pile1 == nullptr) return;
|
||||||
|
|
||||||
|
if (m_exprRetVar != nullptr) // .func().member
|
||||||
|
{
|
||||||
|
CBotStack* pile3 = pile1->AddStack2();
|
||||||
|
if (pile3->GetState() == 1) // function call is done?
|
||||||
|
{
|
||||||
|
m_exprRetVar->RestoreState(pile3, bMain);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CBotStack* pile2 = pile1->RestoreStack(); // and for the parameters coming
|
CBotStack* pile2 = pile1->RestoreStack(); // and for the parameters coming
|
||||||
if (pile2 == nullptr) return;
|
if (pile2 == nullptr) return;
|
||||||
|
|
||||||
CBotVar* pThis = pile1->FindVar("this");
|
CBotVar* pThis = pile1->GetVar();
|
||||||
|
|
||||||
|
assert(pThis != nullptr); // see fix for issues #256 & #436
|
||||||
|
|
||||||
pThis->SetUniqNum(-2);
|
pThis->SetUniqNum(-2);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -200,13 +244,18 @@ void CBotInstrMethode::RestoreStateVar(CBotStack* &pile, bool bMain)
|
||||||
}
|
}
|
||||||
ppVars[i] = nullptr;
|
ppVars[i] = nullptr;
|
||||||
|
|
||||||
CBotClass* pClass = CBotClass::Find(m_className);
|
CBotClass* pClass;
|
||||||
|
|
||||||
|
if (m_thisIdent == -3) // super.method()
|
||||||
|
pClass = CBotClass::Find(m_className);
|
||||||
|
else
|
||||||
|
pClass = pThis->GetClass();
|
||||||
|
|
||||||
// CBotVar* pResult = nullptr;
|
// CBotVar* pResult = nullptr;
|
||||||
|
|
||||||
// CBotVar* pRes = pResult;
|
// CBotVar* pRes = pResult;
|
||||||
|
|
||||||
pClass->RestoreMethode(m_MethodeIdent, m_methodName,
|
pClass->RestoreMethode(m_MethodeIdent, &m_token, pThis, ppVars, pile2);
|
||||||
pThis, ppVars, pile2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -226,7 +275,7 @@ bool CBotInstrMethode::Execute(CBotStack* &pj)
|
||||||
// Test.Action (Test = Other);
|
// Test.Action (Test = Other);
|
||||||
// Action must act on the value before test = Other!
|
// Action must act on the value before test = Other!
|
||||||
pThis->SetName("this");
|
pThis->SetName("this");
|
||||||
pile1->AddVar(pThis);
|
pile1->SetVar(pThis);
|
||||||
pile1->IncState();
|
pile1->IncState();
|
||||||
}
|
}
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -249,26 +298,20 @@ bool CBotInstrMethode::Execute(CBotStack* &pj)
|
||||||
}
|
}
|
||||||
ppVars[i] = nullptr;
|
ppVars[i] = nullptr;
|
||||||
|
|
||||||
CBotClass* pClass = CBotClass::Find(m_className);
|
CBotVar* pThis = pile1->GetVar();
|
||||||
CBotVar* pThis = pile1->FindVar("this");
|
CBotClass* pClass;
|
||||||
CBotVar* pResult = nullptr;
|
|
||||||
if (m_typRes.GetType()>0) pResult = CBotVar::Create("", m_typRes);
|
|
||||||
if (m_typRes.Eq(CBotTypClass))
|
|
||||||
{
|
|
||||||
pResult->SetClass(m_typRes.GetClass());
|
|
||||||
}
|
|
||||||
CBotVar* pRes = pResult;
|
|
||||||
|
|
||||||
if ( !pClass->ExecuteMethode(m_MethodeIdent, m_methodName,
|
if (m_thisIdent == -3) // super.method()
|
||||||
pThis, ppVars,
|
pClass = CBotClass::Find(m_className);
|
||||||
pResult, pile2, GetToken())) return false; // interupted
|
else
|
||||||
|
pClass = pThis->GetClass();
|
||||||
|
|
||||||
|
if ( !pClass->ExecuteMethode(m_MethodeIdent, pThis, ppVars, m_typRes, pile2, GetToken())) return false; // interupted
|
||||||
|
|
||||||
// set the new value of this in place of the old variable
|
// set the new value of this in place of the old variable
|
||||||
CBotVar* old = pile1->FindVar(m_token, false);
|
CBotVar* old = pile1->FindVar(m_token, false);
|
||||||
old->Copy(pThis, false);
|
old->Copy(pThis, false);
|
||||||
|
|
||||||
if (pRes != pResult) delete pRes;
|
|
||||||
|
|
||||||
return pj->Return(pile2); // release the entire stack
|
return pj->Return(pile2); // release the entire stack
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -38,9 +38,10 @@ public:
|
||||||
* \param p
|
* \param p
|
||||||
* \param pStack
|
* \param pStack
|
||||||
* \param pVar
|
* \param pVar
|
||||||
|
* \param bMethodChain If true, allows chaining methods only
|
||||||
* \return
|
* \return
|
||||||
*/
|
*/
|
||||||
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, CBotVar* pVar);
|
static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, CBotVar* pVar, bool bMethodChain = false);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Execute
|
* \brief Execute
|
||||||
|
@ -83,6 +84,12 @@ private:
|
||||||
long m_MethodeIdent;
|
long m_MethodeIdent;
|
||||||
//! Name of the class.
|
//! Name of the class.
|
||||||
std::string m_className;
|
std::string m_className;
|
||||||
|
//! Variable ID
|
||||||
|
long m_thisIdent;
|
||||||
|
|
||||||
|
//! Instruction to return a member of the returned object.
|
||||||
|
CBotInstr* m_exprRetVar;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CBot
|
} // namespace CBot
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -65,7 +65,7 @@ CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars)
|
||||||
{
|
{
|
||||||
if (pile->GetTypResult().Eq(99))
|
if (pile->GetTypResult().Eq(99))
|
||||||
{
|
{
|
||||||
delete pStack->TokenStack();
|
pStack->DeleteNext();
|
||||||
pStack->SetError(CBotErrVoid, p->GetStart());
|
pStack->SetError(CBotErrVoid, p->GetStart());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars)
|
||||||
}
|
}
|
||||||
|
|
||||||
pStack->SetError(CBotErrClosePar, p->GetStart());
|
pStack->SetError(CBotErrClosePar, p->GetStart());
|
||||||
delete pStack->TokenStack();
|
pStack->DeleteNext();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,9 +97,9 @@ bool TypeCompatible(CBotTypResult& type1, CBotTypResult& type2, int op)
|
||||||
if (max == 99) return false; // result is void?
|
if (max == 99) return false; // result is void?
|
||||||
|
|
||||||
// special case for strin concatenation
|
// special case for strin concatenation
|
||||||
if (op == ID_ADD && max >= CBotTypString) return true;
|
if (op == ID_ADD && t1 == CBotTypString) return true;
|
||||||
if (op == ID_ASSADD && max >= CBotTypString) return true;
|
if (op == ID_ASSADD && t2 == CBotTypString) return true;
|
||||||
if (op == ID_ASS && t1 == CBotTypString) return true;
|
if (op == ID_ASS && t2 == CBotTypString) return true;
|
||||||
|
|
||||||
if (max >= CBotTypBoolean)
|
if (max >= CBotTypBoolean)
|
||||||
{
|
{
|
||||||
|
@ -129,6 +129,13 @@ bool TypeCompatible(CBotTypResult& type1, CBotTypResult& type2, int op)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (op == ID_ASR || op == ID_SR || op == ID_SL ||
|
||||||
|
op == ID_ASSOR || op == ID_ASSSL || op == ID_ASSSR ||
|
||||||
|
op == ID_ASSAND || op == ID_ASSXOR || op == ID_ASSASR)
|
||||||
|
{
|
||||||
|
if (max > CBotTypLong) return false;
|
||||||
|
}
|
||||||
|
|
||||||
type1.SetType(max);
|
type1.SetType(max);
|
||||||
type2.SetType(max);
|
type2.SetType(max);
|
||||||
return true;
|
return true;
|
||||||
|
@ -149,12 +156,20 @@ bool TypesCompatibles(const CBotTypResult& type1, const CBotTypResult& type2)
|
||||||
|
|
||||||
if (max >= CBotTypBoolean)
|
if (max >= CBotTypBoolean)
|
||||||
{
|
{
|
||||||
|
if (t1 == CBotTypPointer && t2 == CBotTypNullPointer) return true;
|
||||||
if (t2 != t1) return false;
|
if (t2 != t1) return false;
|
||||||
|
|
||||||
|
if (max == CBotTypPointer)
|
||||||
|
{
|
||||||
|
CBotClass* c1 = type1.GetClass();
|
||||||
|
CBotClass* c2 = type2.GetClass();
|
||||||
|
return c2->IsChildOf(c1);
|
||||||
|
}
|
||||||
|
|
||||||
if (max == CBotTypArrayPointer)
|
if (max == CBotTypArrayPointer)
|
||||||
return TypesCompatibles(type1.GetTypElem(), type2.GetTypElem());
|
return TypesCompatibles(type1.GetTypElem(), type2.GetTypElem());
|
||||||
|
|
||||||
if (max == CBotTypClass || max == CBotTypPointer)
|
if (max == CBotTypClass)
|
||||||
return type1.GetClass() == type2.GetClass() ;
|
return type1.GetClass() == type2.GetClass() ;
|
||||||
|
|
||||||
return true ;
|
return true ;
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -39,7 +39,13 @@ CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief TypeCompatible Check if two results are consistent to make an
|
* \brief TypeCompatible Check if two results are consistent to make an
|
||||||
* operation.
|
* operation. TypeCompatible is used in two ways:
|
||||||
|
* For non-assignment operations: see CBotTwoOpExpr::Compile
|
||||||
|
* TypeCompatible( leftType, rightType, opType )
|
||||||
|
|
||||||
|
* For assignment or compound assignment operations (it's reversed):
|
||||||
|
* see CBotReturn::Compile & CBotExpression::Compile
|
||||||
|
* TypeCompatible( valueType, varType, opType )
|
||||||
* \param type1
|
* \param type1
|
||||||
* \param type2
|
* \param type2
|
||||||
* \param op
|
* \param op
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -64,8 +64,7 @@ CBotLeftExpr* CBotLeftExpr::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
inst->m_nIdent = var->GetUniqNum();
|
inst->m_nIdent = var->GetUniqNum();
|
||||||
if (inst->m_nIdent > 0 && inst->m_nIdent < 9000)
|
if (inst->m_nIdent > 0 && inst->m_nIdent < 9000)
|
||||||
{
|
{
|
||||||
if ( var->IsPrivate(CBotVar::ProtectionLevel::ReadOnly) &&
|
if (CBotFieldExpr::CheckProtectionError(pStk, nullptr, var, true))
|
||||||
!pStk->GetProgram()->m_bCompileClass)
|
|
||||||
{
|
{
|
||||||
pStk->SetError(CBotErrPrivate, p);
|
pStk->SetError(CBotErrPrivate, p);
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -73,6 +72,8 @@ CBotLeftExpr* CBotLeftExpr::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
// this is an element of the current class
|
// this is an element of the current class
|
||||||
// adds the equivalent of this. before
|
// adds the equivalent of this. before
|
||||||
CBotToken pthis("this");
|
CBotToken pthis("this");
|
||||||
|
// invisible 'this.' highlights member token on error
|
||||||
|
pthis.SetPos(p->GetStart(), p->GetEnd());
|
||||||
inst->SetToken(&pthis);
|
inst->SetToken(&pthis);
|
||||||
inst->m_nIdent = -2; // indent for this
|
inst->m_nIdent = -2; // indent for this
|
||||||
|
|
||||||
|
@ -125,11 +126,11 @@ CBotLeftExpr* CBotLeftExpr::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
|
|
||||||
if (p->GetType() == TokenTypVar) // must be a name
|
if (p->GetType() == TokenTypVar) // must be a name
|
||||||
{
|
{
|
||||||
|
CBotVar* preVar = var;
|
||||||
var = var->GetItem(p->GetString()); // get item correspondent
|
var = var->GetItem(p->GetString()); // get item correspondent
|
||||||
if (var != nullptr)
|
if (var != nullptr)
|
||||||
{
|
{
|
||||||
if ( var->IsPrivate(CBotVar::ProtectionLevel::ReadOnly) &&
|
if (CBotFieldExpr::CheckProtectionError(pStk, preVar, var, true))
|
||||||
!pStk->GetProgram()->m_bCompileClass)
|
|
||||||
{
|
{
|
||||||
pStk->SetError(CBotErrPrivate, pp);
|
pStk->SetError(CBotErrPrivate, pp);
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -182,14 +183,17 @@ bool CBotLeftExpr::Execute(CBotStack* &pj, CBotStack* array)
|
||||||
if (t2.Eq(CBotTypPointer))
|
if (t2.Eq(CBotTypPointer))
|
||||||
{
|
{
|
||||||
CBotClass* c1 = t1.GetClass();
|
CBotClass* c1 = t1.GetClass();
|
||||||
CBotClass* c2 = t2.GetClass();
|
CBotClass* c2 = var2->GetClass();
|
||||||
if ( !c2->IsChildOf(c1))
|
if ( !c2->IsChildOf(c1))
|
||||||
{
|
{
|
||||||
CBotToken* pt = &m_token;
|
CBotToken* pt = &m_token;
|
||||||
pile->SetError(CBotErrBadType1, pt);
|
pile->SetError(CBotErrBadType1, pt);
|
||||||
return pj->Return(pile); // operation performed
|
return pj->Return(pile); // operation performed
|
||||||
}
|
}
|
||||||
|
var1->SetVal(var2); // set pointer
|
||||||
|
var1->SetType(t1); // keep pointer type
|
||||||
}
|
}
|
||||||
|
else
|
||||||
var1->SetVal(var2); // do assignment
|
var1->SetVal(var2); // do assignment
|
||||||
}
|
}
|
||||||
pile->SetCopyVar(var1); // replace the stack with the copy of the variable
|
pile->SetCopyVar(var1); // replace the stack with the copy of the variable
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -61,6 +61,8 @@ public:
|
||||||
*/
|
*/
|
||||||
bool Execute(CBotStack* &pStack, CBotStack* array);
|
bool Execute(CBotStack* &pStack, CBotStack* array);
|
||||||
|
|
||||||
|
using CBotInstr::Execute;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief ExecuteVar Fetch a variable during compilation.
|
* \brief ExecuteVar Fetch a variable during compilation.
|
||||||
* \param pVar
|
* \param pVar
|
||||||
|
@ -69,6 +71,8 @@ public:
|
||||||
*/
|
*/
|
||||||
bool ExecuteVar(CBotVar* &pVar, CBotCStack* &pile) override;
|
bool ExecuteVar(CBotVar* &pVar, CBotCStack* &pile) override;
|
||||||
|
|
||||||
|
using CBotInstr::ExecuteVar;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief ExecuteVar Fetch the variable at runtume.
|
* \brief ExecuteVar Fetch the variable at runtume.
|
||||||
* \param pVar
|
* \param pVar
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -64,6 +64,12 @@ bool CBotLeftExprVar::Execute(CBotStack* &pj)
|
||||||
CBotVar* var2 = pj->GetVar(); // Initial value on the stack
|
CBotVar* var2 = pj->GetVar(); // Initial value on the stack
|
||||||
if (var2 != nullptr)
|
if (var2 != nullptr)
|
||||||
{
|
{
|
||||||
|
if (m_typevar.Eq(CBotTypString) && var2->GetType() != CBotTypString)
|
||||||
|
{
|
||||||
|
var2->Update(pj->GetUserPtr());
|
||||||
|
var1->SetValString(var2->GetValString());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
var1->SetVal(var2); // Set the value
|
var1->SetVal(var2); // Set the value
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -51,12 +51,13 @@ CBotInstr* CBotListArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResu
|
||||||
|
|
||||||
CBotToken* pp = p;
|
CBotToken* pp = p;
|
||||||
|
|
||||||
if (IsOfType( p, ID_NULL ))
|
if (IsOfType( p, ID_NULL ) || (IsOfType(p, ID_OPBLK) && IsOfType(p, ID_CLBLK)))
|
||||||
{
|
{
|
||||||
CBotInstr* inst = new CBotExprLitNull();
|
CBotInstr* inst = new CBotExprLitNull();
|
||||||
inst->SetToken(pp);
|
inst->SetToken(pp);
|
||||||
return pStack->Return(inst, pStk); // ok with empty element
|
return pStack->Return(inst, pStk); // ok with empty element
|
||||||
}
|
}
|
||||||
|
p = pp;
|
||||||
|
|
||||||
CBotListArray* inst = new CBotListArray();
|
CBotListArray* inst = new CBotListArray();
|
||||||
|
|
||||||
|
@ -65,25 +66,45 @@ CBotInstr* CBotListArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResu
|
||||||
// each element takes the one after the other
|
// each element takes the one after the other
|
||||||
if (type.Eq( CBotTypArrayPointer ))
|
if (type.Eq( CBotTypArrayPointer ))
|
||||||
{
|
{
|
||||||
type = type.GetTypElem();
|
|
||||||
|
|
||||||
pStk->SetStartError(p->GetStart());
|
pStk->SetStartError(p->GetStart());
|
||||||
if (nullptr == ( inst->m_expr = CBotListArray::Compile( p, pStk, type ) ))
|
if (nullptr == ( inst->m_expr = CBotListArray::Compile( p, pStk, type.GetTypElem() ) ))
|
||||||
{
|
{
|
||||||
|
if (pStk->IsOk())
|
||||||
|
{
|
||||||
|
inst->m_expr = CBotTwoOpExpr::Compile(p, pStk);
|
||||||
|
if (inst->m_expr == nullptr || !pStk->GetTypResult().Compare(type)) // compatible type ?
|
||||||
|
{
|
||||||
|
pStk->SetError(CBotErrBadType1, p->GetStart());
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (IsOfType( p, ID_COMMA )) // other elements?
|
while (IsOfType( p, ID_COMMA )) // other elements?
|
||||||
{
|
{
|
||||||
pStk->SetStartError(p->GetStart());
|
pStk->SetStartError(p->GetStart());
|
||||||
|
|
||||||
CBotInstr* i = CBotListArray::Compile(p, pStk, type);
|
CBotInstr* i = nullptr;
|
||||||
if (nullptr == i)
|
if (nullptr == ( i = CBotListArray::Compile(p, pStk, type.GetTypElem() ) ))
|
||||||
{
|
{
|
||||||
|
if (pStk->IsOk())
|
||||||
|
{
|
||||||
|
i = CBotTwoOpExpr::Compile(p, pStk);
|
||||||
|
if (i == nullptr || !pStk->GetTypResult().Compare(type)) // compatible type ?
|
||||||
|
{
|
||||||
|
pStk->SetError(CBotErrBadType1, p->GetStart());
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inst->m_expr->AddNext3(i);
|
inst->m_expr->AddNext3b(i);
|
||||||
|
|
||||||
|
if ( p->GetType() == ID_COMMA ) continue;
|
||||||
|
if ( p->GetType() == ID_CLBLK ) break;
|
||||||
|
|
||||||
|
pStk->SetError(CBotErrClosePar, p);
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -93,9 +114,10 @@ CBotInstr* CBotListArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResu
|
||||||
{
|
{
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
CBotVar* pv = pStk->GetVar(); // result of the expression
|
|
||||||
|
|
||||||
if (pv == nullptr || !TypesCompatibles( type, pv->GetTypResult())) // compatible type?
|
CBotTypResult valType = pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
||||||
|
|
||||||
|
if (!TypeCompatible(valType, type, ID_ASS) )
|
||||||
{
|
{
|
||||||
pStk->SetError(CBotErrBadType1, p->GetStart());
|
pStk->SetError(CBotErrBadType1, p->GetStart());
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -111,14 +133,20 @@ CBotInstr* CBotListArray::Compile(CBotToken* &p, CBotCStack* pStack, CBotTypResu
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
CBotVar* pv = pStk->GetVar(); // result of the expression
|
CBotTypResult valType = pStk->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC);
|
||||||
|
|
||||||
if (pv == nullptr || !TypesCompatibles( type, pv->GetTypResult())) // compatible type?
|
if (!TypeCompatible(valType, type, ID_ASS) )
|
||||||
{
|
{
|
||||||
pStk->SetError(CBotErrBadType1, p->GetStart());
|
pStk->SetError(CBotErrBadType1, p->GetStart());
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
inst->m_expr->AddNext3(i);
|
inst->m_expr->AddNext3b(i);
|
||||||
|
|
||||||
|
if (p->GetType() == ID_COMMA) continue;
|
||||||
|
if (p->GetType() == ID_CLBLK) break;
|
||||||
|
|
||||||
|
pStk->SetError(CBotErrClosePar, p);
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +174,7 @@ bool CBotListArray::Execute(CBotStack* &pj, CBotVar* pVar)
|
||||||
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
|
||||||
for (; p != nullptr ; n++, p = p->GetNext3())
|
for (; p != nullptr ; n++, p = p->GetNext3b())
|
||||||
{
|
{
|
||||||
if (pile1->GetState() > n) continue;
|
if (pile1->GetState() > n) continue;
|
||||||
|
|
||||||
|
@ -157,9 +185,12 @@ bool CBotListArray::Execute(CBotStack* &pj, CBotVar* pVar)
|
||||||
pj->SetError(CBotErrOutArray, p->GetToken());
|
pj->SetError(CBotErrOutArray, p->GetToken());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
CBotTypResult type = pVar2->GetTypResult();
|
||||||
|
|
||||||
if (!p->Execute(pile1, pVar2)) return false; // evaluate expression
|
if (!p->Execute(pile1, pVar2)) return false; // evaluate expression
|
||||||
|
|
||||||
|
if (type.Eq(CBotTypPointer)) pVar2->SetType(type); // keep pointer type
|
||||||
|
|
||||||
pile1->IncState();
|
pile1->IncState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +209,7 @@ void CBotListArray::RestoreState(CBotStack* &pj, bool bMain)
|
||||||
|
|
||||||
int state = pile->GetState();
|
int state = pile->GetState();
|
||||||
|
|
||||||
while(state-- > 0) p = p->GetNext3() ;
|
while(state-- > 0) p = p->GetNext3b() ;
|
||||||
|
|
||||||
p->RestoreState(pile, bMain); // size calculation //interrupted!
|
p->RestoreState(pile, bMain); // size calculation //interrupted!
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -62,7 +62,7 @@ protected:
|
||||||
virtual std::map<std::string, CBotInstr*> GetDebugLinks() override;
|
virtual std::map<std::string, CBotInstr*> GetDebugLinks() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! An expression for an element others are linked with CBotInstr :: m_next3;
|
//! An expression for an element others are linked with CBotInstr :: m_next3b;
|
||||||
CBotInstr* m_expr;
|
CBotInstr* m_expr;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -52,7 +52,7 @@ CBotInstr* CBotListInstr::Compile(CBotToken* &p, CBotCStack* pStack, bool bLocal
|
||||||
if (IsOfType(p, ID_SEP)) continue; // empty statement ignored
|
if (IsOfType(p, ID_SEP)) continue; // empty statement ignored
|
||||||
if (p->GetType() == ID_CLBLK) break;
|
if (p->GetType() == ID_CLBLK) break;
|
||||||
|
|
||||||
if (IsOfType(p, 0))
|
if (p->GetType() == TokenTypNone)
|
||||||
{
|
{
|
||||||
pStack->SetError(CBotErrCloseBlock, p->GetStart());
|
pStack->SetError(CBotErrCloseBlock, p->GetStart());
|
||||||
delete inst;
|
delete inst;
|
||||||
|
@ -117,6 +117,12 @@ void CBotListInstr::RestoreState(CBotStack* &pj, bool bMain)
|
||||||
if (p != nullptr) p->RestoreState(pile, true);
|
if (p != nullptr) p->RestoreState(pile, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CBotListInstr::HasReturn()
|
||||||
|
{
|
||||||
|
if (m_instr != nullptr && m_instr->HasReturn()) return true;
|
||||||
|
return CBotInstr::HasReturn(); // check next block or instruction
|
||||||
|
}
|
||||||
|
|
||||||
std::map<std::string, CBotInstr*> CBotListInstr::GetDebugLinks()
|
std::map<std::string, CBotInstr*> CBotListInstr::GetDebugLinks()
|
||||||
{
|
{
|
||||||
auto links = CBotInstr::GetDebugLinks();
|
auto links = CBotInstr::GetDebugLinks();
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -56,6 +56,13 @@ public:
|
||||||
*/
|
*/
|
||||||
void RestoreState(CBotStack* &pj, bool bMain) override;
|
void RestoreState(CBotStack* &pj, bool bMain) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check this block of instructions for a return statement.
|
||||||
|
* If not found, the next block or instruction is checked.
|
||||||
|
* \return true if a return statement was found.
|
||||||
|
*/
|
||||||
|
bool HasReturn() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual const std::string GetDebugName() override { return "CBotListInstr"; }
|
virtual const std::string GetDebugName() override { return "CBotListInstr"; }
|
||||||
virtual std::map<std::string, CBotInstr*> GetDebugLinks() override;
|
virtual std::map<std::string, CBotInstr*> GetDebugLinks() override;
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* This file is part of the Colobot: Gold Edition source code
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
* Copyright (C) 2001-2016, Daniel Roux, EPSITEC SA & TerranovaTeam
|
* Copyright (C) 2001-2023, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -24,6 +24,7 @@
|
||||||
#include "CBot/CBotCStack.h"
|
#include "CBot/CBotCStack.h"
|
||||||
#include "CBot/CBotClass.h"
|
#include "CBot/CBotClass.h"
|
||||||
|
|
||||||
|
#include "CBot/CBotInstr/CBotExprRetVar.h"
|
||||||
#include "CBot/CBotInstr/CBotInstrUtils.h"
|
#include "CBot/CBotInstr/CBotInstrUtils.h"
|
||||||
|
|
||||||
#include "CBot/CBotVar/CBotVar.h"
|
#include "CBot/CBotVar/CBotVar.h"
|
||||||
|
@ -35,12 +36,15 @@ namespace CBot
|
||||||
CBotNew::CBotNew()
|
CBotNew::CBotNew()
|
||||||
{
|
{
|
||||||
m_parameters = nullptr;
|
m_parameters = nullptr;
|
||||||
|
m_exprRetVar = nullptr;
|
||||||
m_nMethodeIdent = 0;
|
m_nMethodeIdent = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CBotNew::~CBotNew()
|
CBotNew::~CBotNew()
|
||||||
{
|
{
|
||||||
|
delete m_parameters;
|
||||||
|
delete m_exprRetVar;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -50,7 +54,11 @@ CBotInstr* CBotNew::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
if (!IsOfType(p, ID_NEW)) return nullptr;
|
if (!IsOfType(p, ID_NEW)) return nullptr;
|
||||||
|
|
||||||
// verifies that the token is a class name
|
// verifies that the token is a class name
|
||||||
if (p->GetType() != TokenTypVar) return nullptr;
|
if (p->GetType() != TokenTypVar)
|
||||||
|
{
|
||||||
|
pStack->SetError(CBotErrBadNew, p);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
CBotClass* pClass = CBotClass::Find(p);
|
CBotClass* pClass = CBotClass::Find(p);
|
||||||
if (pClass == nullptr)
|
if (pClass == nullptr)
|
||||||
|
@ -78,8 +86,8 @@ CBotInstr* CBotNew::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
if (!pStk->IsOk()) goto error;
|
if (!pStk->IsOk()) goto error;
|
||||||
|
|
||||||
// constructor exist?
|
// constructor exist?
|
||||||
CBotTypResult r = pClass->CompileMethode(pClass->GetName(), pVar, ppVars, pStk, inst->m_nMethodeIdent);
|
CBotTypResult r = pClass->CompileMethode(&inst->m_vartoken, pVar, ppVars, pStk, inst->m_nMethodeIdent);
|
||||||
delete pStk->TokenStack(); // release extra stack
|
pStk->DeleteNext(); // release extra stack
|
||||||
int typ = r.GetType();
|
int typ = r.GetType();
|
||||||
|
|
||||||
// if there is no constructor, and no parameters either, it's ok
|
// if there is no constructor, and no parameters either, it's ok
|
||||||
|
@ -101,6 +109,16 @@ CBotInstr* CBotNew::Compile(CBotToken* &p, CBotCStack* pStack)
|
||||||
|
|
||||||
// makes pointer to the object on the stack
|
// makes pointer to the object on the stack
|
||||||
pStk->SetVar(pVar);
|
pStk->SetVar(pVar);
|
||||||
|
|
||||||
|
pp = p;
|
||||||
|
// chained method ?
|
||||||
|
if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStk, true)))
|
||||||
|
{
|
||||||
|
inst->m_exprRetVar->SetToken(pp);
|
||||||
|
pStk->DeleteNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pStack->IsOk())
|
||||||
return pStack->Return(inst, pStk);
|
return pStack->Return(inst, pStk);
|
||||||
}
|
}
|
||||||
error:
|
error:
|
||||||
|
@ -113,6 +131,16 @@ bool CBotNew::Execute(CBotStack* &pj)
|
||||||
{
|
{
|
||||||
CBotStack* pile = pj->AddStack(this); //main stack
|
CBotStack* pile = pj->AddStack(this); //main stack
|
||||||
|
|
||||||
|
if (m_exprRetVar != nullptr) // new Class().method()
|
||||||
|
{
|
||||||
|
if (pile->GetState() == 2)
|
||||||
|
{
|
||||||
|
CBotStack* pile3 = pile->AddStack();
|
||||||
|
if (!m_exprRetVar->Execute(pile3)) return false;
|
||||||
|
return pj->Return(pile3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pile->IfStep()) return false;
|
if (pile->IfStep()) return false;
|
||||||
|
|
||||||
CBotStack* pile1 = pj->AddStack2(); //secondary stack
|
CBotStack* pile1 = pj->AddStack2(); //secondary stack
|
||||||
|
@ -161,6 +189,7 @@ bool CBotNew::Execute(CBotStack* &pj)
|
||||||
if (p != nullptr) while ( true)
|
if (p != nullptr) while ( true)
|
||||||
{
|
{
|
||||||
pile2 = pile2->AddStack(); // space on the stack for the result
|
pile2 = pile2->AddStack(); // space on the stack for the result
|
||||||
|
if (pile2->StackOver()) return pj->Return(pile2);
|
||||||
if (pile2->GetState() == 0)
|
if (pile2->GetState() == 0)
|
||||||
{
|
{
|
||||||
if (!p->Execute(pile2)) return false; // interrupted here?
|
if (!p->Execute(pile2)) return false; // interrupted here?
|
||||||
|
@ -172,16 +201,21 @@ bool CBotNew::Execute(CBotStack* &pj)
|
||||||
}
|
}
|
||||||
ppVars[i] = nullptr;
|
ppVars[i] = nullptr;
|
||||||
|
|
||||||
// create a variable for the result
|
if ( !pClass->ExecuteMethode(m_nMethodeIdent, pThis, ppVars, CBotTypResult(CBotTypVoid), pile2, &m_vartoken)) return false; // interrupt
|
||||||
CBotVar* pResult = nullptr; // constructos still void
|
|
||||||
|
|
||||||
if ( !pClass->ExecuteMethode(m_nMethodeIdent, pClass->GetName(),
|
|
||||||
pThis, ppVars,
|
|
||||||
pResult, pile2, GetToken())) return false; // interrupt
|
|
||||||
|
|
||||||
pThis->ConstructorSet(); // indicates that the constructor has been called
|
pThis->ConstructorSet(); // indicates that the constructor has been called
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_exprRetVar != nullptr) // new Class().method()
|
||||||
|
{
|
||||||
|
pile->AddStack()->Delete(); // release pile2 stack
|
||||||
|
CBotStack* pile3 = pile->AddStack(); // add new stack
|
||||||
|
pile3->SetCopyVar(pThis); // copy the pointer (from pile1)
|
||||||
|
pile1->Delete(); // release secondary stack(pile1)
|
||||||
|
pile->SetState(2);
|
||||||
|
return false; // go back to the top ^^^
|
||||||
|
}
|
||||||
|
|
||||||
return pj->Return(pile1); // passes below
|
return pj->Return(pile1); // passes below
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,6 +227,16 @@ void CBotNew::RestoreState(CBotStack* &pj, bool bMain)
|
||||||
CBotStack* pile = pj->RestoreStack(this); //primary stack
|
CBotStack* pile = pj->RestoreStack(this); //primary stack
|
||||||
if (pile == nullptr) return;
|
if (pile == nullptr) return;
|
||||||
|
|
||||||
|
if (m_exprRetVar != nullptr) // new Class().method()
|
||||||
|
{
|
||||||
|
if (pile->GetState() == 2)
|
||||||
|
{
|
||||||
|
CBotStack* pile3 = pile->RestoreStack();
|
||||||
|
m_exprRetVar->RestoreState(pile3, bMain);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CBotStack* pile1 = pj->AddStack2(); //secondary stack
|
CBotStack* pile1 = pj->AddStack2(); //secondary stack
|
||||||
|
|
||||||
CBotToken* pt = &m_vartoken;
|
CBotToken* pt = &m_vartoken;
|
||||||
|
@ -239,8 +283,7 @@ void CBotNew::RestoreState(CBotStack* &pj, bool bMain)
|
||||||
}
|
}
|
||||||
ppVars[i] = nullptr;
|
ppVars[i] = nullptr;
|
||||||
|
|
||||||
pClass->RestoreMethode(m_nMethodeIdent, m_vartoken.GetString(), pThis,
|
pClass->RestoreMethode(m_nMethodeIdent, &m_vartoken, pThis, ppVars, pile2); // interrupt here!
|
||||||
ppVars, pile2) ; // interrupt here!
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue