From 985f9ad8f2a8c5192b11062df8a7399c5392e63d Mon Sep 17 00:00:00 2001 From: Orkuncakilkaya Date: Thu, 27 Aug 2026 15:15:35 +0300 Subject: [PATCH] Baseline: Ludic compiler + toolchain, Phase 1 syntax fixes complete Self-hosted compiler (selfhost/*.ludic), runtime, examples, editor tooling, and docs. Phase 1 of the syntax-redesign cohesion pass has landed: edge-system fix, signature-query, when-alias, and the documentation truth-pass. Suite green (14/14), C-free bootstrap fixpoint holds. Co-Authored-By: Claude Opus 4.8 --- .claude/launch.json | 11 + .gitignore | 17 + BOOTSTRAP.md | 967 + COMPILING.md | 352 + LANGUAGE.md | 567 + LUANTI-ROADMAP.md | 1560 ++ README.md | 180 + SYNTAX-REDESIGN.md | 254 + assets/kenney/tiny-dungeon/License.txt | 22 + assets/kenney/tiny-dungeon/Preview.png | Bin 0 -> 17553 bytes assets/kenney/tiny-dungeon/Sample.png | Bin 0 -> 26519 bytes .../kenney/tiny-dungeon/Tiled/sampleMap.tmx | 76 + .../kenney/tiny-dungeon/Tiled/sampleSheet.tsx | 4 + .../kenney/tiny-dungeon/Tilemap/tilemap.png | Bin 0 -> 5533 bytes .../tiny-dungeon/Tilemap/tilemap_packed.png | Bin 0 -> 5294 bytes .../kenney/tiny-dungeon/Tiles/tile_0000.png | Bin 0 -> 99 bytes .../kenney/tiny-dungeon/Tiles/tile_0001.png | Bin 0 -> 126 bytes .../kenney/tiny-dungeon/Tiles/tile_0002.png | Bin 0 -> 150 bytes .../kenney/tiny-dungeon/Tiles/tile_0003.png | Bin 0 -> 126 bytes .../kenney/tiny-dungeon/Tiles/tile_0004.png | Bin 0 -> 178 bytes .../kenney/tiny-dungeon/Tiles/tile_0005.png | Bin 0 -> 181 bytes .../kenney/tiny-dungeon/Tiles/tile_0006.png | Bin 0 -> 164 bytes .../kenney/tiny-dungeon/Tiles/tile_0007.png | Bin 0 -> 180 bytes .../kenney/tiny-dungeon/Tiles/tile_0008.png | Bin 0 -> 209 bytes .../kenney/tiny-dungeon/Tiles/tile_0009.png | Bin 0 -> 174 bytes .../kenney/tiny-dungeon/Tiles/tile_0010.png | Bin 0 -> 159 bytes .../kenney/tiny-dungeon/Tiles/tile_0011.png | Bin 0 -> 163 bytes .../kenney/tiny-dungeon/Tiles/tile_0012.png | Bin 0 -> 160 bytes .../kenney/tiny-dungeon/Tiles/tile_0013.png | Bin 0 -> 110 bytes .../kenney/tiny-dungeon/Tiles/tile_0014.png | Bin 0 -> 143 bytes .../kenney/tiny-dungeon/Tiles/tile_0015.png | Bin 0 -> 110 bytes .../kenney/tiny-dungeon/Tiles/tile_0016.png | Bin 0 -> 147 bytes .../kenney/tiny-dungeon/Tiles/tile_0017.png | Bin 0 -> 152 bytes .../kenney/tiny-dungeon/Tiles/tile_0018.png | Bin 0 -> 176 bytes .../kenney/tiny-dungeon/Tiles/tile_0019.png | Bin 0 -> 182 bytes .../kenney/tiny-dungeon/Tiles/tile_0020.png | Bin 0 -> 211 bytes .../kenney/tiny-dungeon/Tiles/tile_0021.png | Bin 0 -> 182 bytes .../kenney/tiny-dungeon/Tiles/tile_0022.png | Bin 0 -> 173 bytes .../kenney/tiny-dungeon/Tiles/tile_0023.png | Bin 0 -> 172 bytes .../kenney/tiny-dungeon/Tiles/tile_0024.png | Bin 0 -> 175 bytes .../kenney/tiny-dungeon/Tiles/tile_0025.png | Bin 0 -> 139 bytes .../kenney/tiny-dungeon/Tiles/tile_0026.png | Bin 0 -> 185 bytes .../kenney/tiny-dungeon/Tiles/tile_0027.png | Bin 0 -> 139 bytes .../kenney/tiny-dungeon/Tiles/tile_0028.png | Bin 0 -> 149 bytes .../kenney/tiny-dungeon/Tiles/tile_0029.png | Bin 0 -> 208 bytes .../kenney/tiny-dungeon/Tiles/tile_0030.png | Bin 0 -> 138 bytes .../kenney/tiny-dungeon/Tiles/tile_0031.png | Bin 0 -> 171 bytes .../kenney/tiny-dungeon/Tiles/tile_0032.png | Bin 0 -> 195 bytes .../kenney/tiny-dungeon/Tiles/tile_0033.png | Bin 0 -> 202 bytes .../kenney/tiny-dungeon/Tiles/tile_0034.png | Bin 0 -> 196 bytes .../kenney/tiny-dungeon/Tiles/tile_0035.png | Bin 0 -> 198 bytes .../kenney/tiny-dungeon/Tiles/tile_0036.png | Bin 0 -> 139 bytes .../kenney/tiny-dungeon/Tiles/tile_0037.png | Bin 0 -> 130 bytes .../kenney/tiny-dungeon/Tiles/tile_0038.png | Bin 0 -> 145 bytes .../kenney/tiny-dungeon/Tiles/tile_0039.png | Bin 0 -> 140 bytes .../kenney/tiny-dungeon/Tiles/tile_0040.png | Bin 0 -> 128 bytes .../kenney/tiny-dungeon/Tiles/tile_0041.png | Bin 0 -> 178 bytes .../kenney/tiny-dungeon/Tiles/tile_0042.png | Bin 0 -> 142 bytes .../kenney/tiny-dungeon/Tiles/tile_0043.png | Bin 0 -> 155 bytes .../kenney/tiny-dungeon/Tiles/tile_0044.png | Bin 0 -> 170 bytes .../kenney/tiny-dungeon/Tiles/tile_0045.png | Bin 0 -> 191 bytes .../kenney/tiny-dungeon/Tiles/tile_0046.png | Bin 0 -> 180 bytes .../kenney/tiny-dungeon/Tiles/tile_0047.png | Bin 0 -> 178 bytes .../kenney/tiny-dungeon/Tiles/tile_0048.png | Bin 0 -> 99 bytes .../kenney/tiny-dungeon/Tiles/tile_0049.png | Bin 0 -> 130 bytes .../kenney/tiny-dungeon/Tiles/tile_0050.png | Bin 0 -> 109 bytes .../kenney/tiny-dungeon/Tiles/tile_0051.png | Bin 0 -> 133 bytes .../kenney/tiny-dungeon/Tiles/tile_0052.png | Bin 0 -> 122 bytes .../kenney/tiny-dungeon/Tiles/tile_0053.png | Bin 0 -> 110 bytes .../kenney/tiny-dungeon/Tiles/tile_0054.png | Bin 0 -> 184 bytes .../kenney/tiny-dungeon/Tiles/tile_0055.png | Bin 0 -> 182 bytes .../kenney/tiny-dungeon/Tiles/tile_0056.png | Bin 0 -> 207 bytes .../kenney/tiny-dungeon/Tiles/tile_0057.png | Bin 0 -> 135 bytes .../kenney/tiny-dungeon/Tiles/tile_0058.png | Bin 0 -> 140 bytes .../kenney/tiny-dungeon/Tiles/tile_0059.png | Bin 0 -> 134 bytes .../kenney/tiny-dungeon/Tiles/tile_0060.png | Bin 0 -> 140 bytes .../kenney/tiny-dungeon/Tiles/tile_0061.png | Bin 0 -> 149 bytes .../kenney/tiny-dungeon/Tiles/tile_0062.png | Bin 0 -> 152 bytes .../kenney/tiny-dungeon/Tiles/tile_0063.png | Bin 0 -> 167 bytes .../kenney/tiny-dungeon/Tiles/tile_0064.png | Bin 0 -> 176 bytes .../kenney/tiny-dungeon/Tiles/tile_0065.png | Bin 0 -> 177 bytes .../kenney/tiny-dungeon/Tiles/tile_0066.png | Bin 0 -> 192 bytes .../kenney/tiny-dungeon/Tiles/tile_0067.png | Bin 0 -> 170 bytes .../kenney/tiny-dungeon/Tiles/tile_0068.png | Bin 0 -> 181 bytes .../kenney/tiny-dungeon/Tiles/tile_0069.png | Bin 0 -> 206 bytes .../kenney/tiny-dungeon/Tiles/tile_0070.png | Bin 0 -> 170 bytes .../kenney/tiny-dungeon/Tiles/tile_0071.png | Bin 0 -> 201 bytes .../kenney/tiny-dungeon/Tiles/tile_0072.png | Bin 0 -> 163 bytes .../kenney/tiny-dungeon/Tiles/tile_0073.png | Bin 0 -> 161 bytes .../kenney/tiny-dungeon/Tiles/tile_0074.png | Bin 0 -> 201 bytes .../kenney/tiny-dungeon/Tiles/tile_0075.png | Bin 0 -> 128 bytes .../kenney/tiny-dungeon/Tiles/tile_0076.png | Bin 0 -> 165 bytes .../kenney/tiny-dungeon/Tiles/tile_0077.png | Bin 0 -> 165 bytes .../kenney/tiny-dungeon/Tiles/tile_0078.png | Bin 0 -> 165 bytes .../kenney/tiny-dungeon/Tiles/tile_0079.png | Bin 0 -> 174 bytes .../kenney/tiny-dungeon/Tiles/tile_0080.png | Bin 0 -> 180 bytes .../kenney/tiny-dungeon/Tiles/tile_0081.png | Bin 0 -> 156 bytes .../kenney/tiny-dungeon/Tiles/tile_0082.png | Bin 0 -> 207 bytes .../kenney/tiny-dungeon/Tiles/tile_0083.png | Bin 0 -> 156 bytes .../kenney/tiny-dungeon/Tiles/tile_0084.png | Bin 0 -> 232 bytes .../kenney/tiny-dungeon/Tiles/tile_0085.png | Bin 0 -> 230 bytes .../kenney/tiny-dungeon/Tiles/tile_0086.png | Bin 0 -> 224 bytes .../kenney/tiny-dungeon/Tiles/tile_0087.png | Bin 0 -> 239 bytes .../kenney/tiny-dungeon/Tiles/tile_0088.png | Bin 0 -> 222 bytes .../kenney/tiny-dungeon/Tiles/tile_0089.png | Bin 0 -> 196 bytes .../kenney/tiny-dungeon/Tiles/tile_0090.png | Bin 0 -> 209 bytes .../kenney/tiny-dungeon/Tiles/tile_0091.png | Bin 0 -> 207 bytes .../kenney/tiny-dungeon/Tiles/tile_0092.png | Bin 0 -> 244 bytes .../kenney/tiny-dungeon/Tiles/tile_0093.png | Bin 0 -> 205 bytes .../kenney/tiny-dungeon/Tiles/tile_0094.png | Bin 0 -> 170 bytes .../kenney/tiny-dungeon/Tiles/tile_0095.png | Bin 0 -> 203 bytes .../kenney/tiny-dungeon/Tiles/tile_0096.png | Bin 0 -> 206 bytes .../kenney/tiny-dungeon/Tiles/tile_0097.png | Bin 0 -> 225 bytes .../kenney/tiny-dungeon/Tiles/tile_0098.png | Bin 0 -> 238 bytes .../kenney/tiny-dungeon/Tiles/tile_0099.png | Bin 0 -> 238 bytes .../kenney/tiny-dungeon/Tiles/tile_0100.png | Bin 0 -> 240 bytes .../kenney/tiny-dungeon/Tiles/tile_0101.png | Bin 0 -> 159 bytes .../kenney/tiny-dungeon/Tiles/tile_0102.png | Bin 0 -> 154 bytes .../kenney/tiny-dungeon/Tiles/tile_0103.png | Bin 0 -> 164 bytes .../kenney/tiny-dungeon/Tiles/tile_0104.png | Bin 0 -> 166 bytes .../kenney/tiny-dungeon/Tiles/tile_0105.png | Bin 0 -> 181 bytes .../kenney/tiny-dungeon/Tiles/tile_0106.png | Bin 0 -> 164 bytes .../kenney/tiny-dungeon/Tiles/tile_0107.png | Bin 0 -> 173 bytes .../kenney/tiny-dungeon/Tiles/tile_0108.png | Bin 0 -> 189 bytes .../kenney/tiny-dungeon/Tiles/tile_0109.png | Bin 0 -> 219 bytes .../kenney/tiny-dungeon/Tiles/tile_0110.png | Bin 0 -> 217 bytes .../kenney/tiny-dungeon/Tiles/tile_0111.png | Bin 0 -> 228 bytes .../kenney/tiny-dungeon/Tiles/tile_0112.png | Bin 0 -> 237 bytes .../kenney/tiny-dungeon/Tiles/tile_0113.png | Bin 0 -> 176 bytes .../kenney/tiny-dungeon/Tiles/tile_0114.png | Bin 0 -> 182 bytes .../kenney/tiny-dungeon/Tiles/tile_0115.png | Bin 0 -> 182 bytes .../kenney/tiny-dungeon/Tiles/tile_0116.png | Bin 0 -> 182 bytes .../kenney/tiny-dungeon/Tiles/tile_0117.png | Bin 0 -> 191 bytes .../kenney/tiny-dungeon/Tiles/tile_0118.png | Bin 0 -> 200 bytes .../kenney/tiny-dungeon/Tiles/tile_0119.png | Bin 0 -> 184 bytes .../kenney/tiny-dungeon/Tiles/tile_0120.png | Bin 0 -> 195 bytes .../kenney/tiny-dungeon/Tiles/tile_0121.png | Bin 0 -> 189 bytes .../kenney/tiny-dungeon/Tiles/tile_0122.png | Bin 0 -> 232 bytes .../kenney/tiny-dungeon/Tiles/tile_0123.png | Bin 0 -> 201 bytes .../kenney/tiny-dungeon/Tiles/tile_0124.png | Bin 0 -> 203 bytes .../kenney/tiny-dungeon/Tiles/tile_0125.png | Bin 0 -> 165 bytes .../kenney/tiny-dungeon/Tiles/tile_0126.png | Bin 0 -> 171 bytes .../kenney/tiny-dungeon/Tiles/tile_0127.png | Bin 0 -> 171 bytes .../kenney/tiny-dungeon/Tiles/tile_0128.png | Bin 0 -> 171 bytes .../kenney/tiny-dungeon/Tiles/tile_0129.png | Bin 0 -> 173 bytes .../kenney/tiny-dungeon/Tiles/tile_0130.png | Bin 0 -> 185 bytes .../kenney/tiny-dungeon/Tiles/tile_0131.png | Bin 0 -> 181 bytes assets/kenney/tiny-dungeon/Tilesheet.txt | 9 + assets/kenney/tiny-dungeon/Visit Kenney.url | 2 + assets/kenney/tiny-dungeon/Visit Patreon.url | 2 + assets/kenney/tiny-town/License.txt | 22 + assets/kenney/tiny-town/Preview.png | Bin 0 -> 17645 bytes assets/kenney/tiny-town/Sample.png | Bin 0 -> 112122 bytes assets/kenney/tiny-town/Tilemap/tilemap.png | Bin 0 -> 5392 bytes .../tiny-town/Tilemap/tilemap_packed.png | Bin 0 -> 5042 bytes assets/kenney/tiny-town/Tiles/tile_0000.png | Bin 0 -> 99 bytes assets/kenney/tiny-town/Tiles/tile_0001.png | Bin 0 -> 144 bytes assets/kenney/tiny-town/Tiles/tile_0002.png | Bin 0 -> 174 bytes assets/kenney/tiny-town/Tiles/tile_0003.png | Bin 0 -> 176 bytes assets/kenney/tiny-town/Tiles/tile_0004.png | Bin 0 -> 175 bytes assets/kenney/tiny-town/Tiles/tile_0005.png | Bin 0 -> 197 bytes assets/kenney/tiny-town/Tiles/tile_0006.png | Bin 0 -> 180 bytes assets/kenney/tiny-town/Tiles/tile_0007.png | Bin 0 -> 157 bytes assets/kenney/tiny-town/Tiles/tile_0008.png | Bin 0 -> 185 bytes assets/kenney/tiny-town/Tiles/tile_0009.png | Bin 0 -> 180 bytes assets/kenney/tiny-town/Tiles/tile_0010.png | Bin 0 -> 157 bytes assets/kenney/tiny-town/Tiles/tile_0011.png | Bin 0 -> 185 bytes assets/kenney/tiny-town/Tiles/tile_0012.png | Bin 0 -> 161 bytes assets/kenney/tiny-town/Tiles/tile_0013.png | Bin 0 -> 153 bytes assets/kenney/tiny-town/Tiles/tile_0014.png | Bin 0 -> 161 bytes assets/kenney/tiny-town/Tiles/tile_0015.png | Bin 0 -> 193 bytes assets/kenney/tiny-town/Tiles/tile_0016.png | Bin 0 -> 192 bytes assets/kenney/tiny-town/Tiles/tile_0017.png | Bin 0 -> 177 bytes assets/kenney/tiny-town/Tiles/tile_0018.png | Bin 0 -> 163 bytes assets/kenney/tiny-town/Tiles/tile_0019.png | Bin 0 -> 200 bytes assets/kenney/tiny-town/Tiles/tile_0020.png | Bin 0 -> 166 bytes assets/kenney/tiny-town/Tiles/tile_0021.png | Bin 0 -> 163 bytes assets/kenney/tiny-town/Tiles/tile_0022.png | Bin 0 -> 200 bytes assets/kenney/tiny-town/Tiles/tile_0023.png | Bin 0 -> 166 bytes assets/kenney/tiny-town/Tiles/tile_0024.png | Bin 0 -> 135 bytes assets/kenney/tiny-town/Tiles/tile_0025.png | Bin 0 -> 99 bytes assets/kenney/tiny-town/Tiles/tile_0026.png | Bin 0 -> 140 bytes assets/kenney/tiny-town/Tiles/tile_0027.png | Bin 0 -> 191 bytes assets/kenney/tiny-town/Tiles/tile_0028.png | Bin 0 -> 191 bytes assets/kenney/tiny-town/Tiles/tile_0029.png | Bin 0 -> 197 bytes assets/kenney/tiny-town/Tiles/tile_0030.png | Bin 0 -> 181 bytes assets/kenney/tiny-town/Tiles/tile_0031.png | Bin 0 -> 157 bytes assets/kenney/tiny-town/Tiles/tile_0032.png | Bin 0 -> 181 bytes assets/kenney/tiny-town/Tiles/tile_0033.png | Bin 0 -> 181 bytes assets/kenney/tiny-town/Tiles/tile_0034.png | Bin 0 -> 157 bytes assets/kenney/tiny-town/Tiles/tile_0035.png | Bin 0 -> 181 bytes assets/kenney/tiny-town/Tiles/tile_0036.png | Bin 0 -> 154 bytes assets/kenney/tiny-town/Tiles/tile_0037.png | Bin 0 -> 134 bytes assets/kenney/tiny-town/Tiles/tile_0038.png | Bin 0 -> 149 bytes assets/kenney/tiny-town/Tiles/tile_0039.png | Bin 0 -> 129 bytes assets/kenney/tiny-town/Tiles/tile_0040.png | Bin 0 -> 139 bytes assets/kenney/tiny-town/Tiles/tile_0041.png | Bin 0 -> 126 bytes assets/kenney/tiny-town/Tiles/tile_0042.png | Bin 0 -> 137 bytes assets/kenney/tiny-town/Tiles/tile_0043.png | Bin 0 -> 166 bytes assets/kenney/tiny-town/Tiles/tile_0044.png | Bin 0 -> 164 bytes assets/kenney/tiny-town/Tiles/tile_0045.png | Bin 0 -> 178 bytes assets/kenney/tiny-town/Tiles/tile_0046.png | Bin 0 -> 164 bytes assets/kenney/tiny-town/Tiles/tile_0047.png | Bin 0 -> 144 bytes assets/kenney/tiny-town/Tiles/tile_0048.png | Bin 0 -> 166 bytes assets/kenney/tiny-town/Tiles/tile_0049.png | Bin 0 -> 161 bytes assets/kenney/tiny-town/Tiles/tile_0050.png | Bin 0 -> 171 bytes assets/kenney/tiny-town/Tiles/tile_0051.png | Bin 0 -> 167 bytes assets/kenney/tiny-town/Tiles/tile_0052.png | Bin 0 -> 180 bytes assets/kenney/tiny-town/Tiles/tile_0053.png | Bin 0 -> 178 bytes assets/kenney/tiny-town/Tiles/tile_0054.png | Bin 0 -> 181 bytes assets/kenney/tiny-town/Tiles/tile_0055.png | Bin 0 -> 188 bytes assets/kenney/tiny-town/Tiles/tile_0056.png | Bin 0 -> 146 bytes assets/kenney/tiny-town/Tiles/tile_0057.png | Bin 0 -> 213 bytes assets/kenney/tiny-town/Tiles/tile_0058.png | Bin 0 -> 147 bytes assets/kenney/tiny-town/Tiles/tile_0059.png | Bin 0 -> 145 bytes assets/kenney/tiny-town/Tiles/tile_0060.png | Bin 0 -> 177 bytes assets/kenney/tiny-town/Tiles/tile_0061.png | Bin 0 -> 166 bytes assets/kenney/tiny-town/Tiles/tile_0062.png | Bin 0 -> 184 bytes assets/kenney/tiny-town/Tiles/tile_0063.png | Bin 0 -> 216 bytes assets/kenney/tiny-town/Tiles/tile_0064.png | Bin 0 -> 177 bytes assets/kenney/tiny-town/Tiles/tile_0065.png | Bin 0 -> 166 bytes assets/kenney/tiny-town/Tiles/tile_0066.png | Bin 0 -> 184 bytes assets/kenney/tiny-town/Tiles/tile_0067.png | Bin 0 -> 216 bytes assets/kenney/tiny-town/Tiles/tile_0068.png | Bin 0 -> 164 bytes assets/kenney/tiny-town/Tiles/tile_0069.png | Bin 0 -> 171 bytes assets/kenney/tiny-town/Tiles/tile_0070.png | Bin 0 -> 165 bytes assets/kenney/tiny-town/Tiles/tile_0071.png | Bin 0 -> 139 bytes assets/kenney/tiny-town/Tiles/tile_0072.png | Bin 0 -> 137 bytes assets/kenney/tiny-town/Tiles/tile_0073.png | Bin 0 -> 129 bytes assets/kenney/tiny-town/Tiles/tile_0074.png | Bin 0 -> 155 bytes assets/kenney/tiny-town/Tiles/tile_0075.png | Bin 0 -> 143 bytes assets/kenney/tiny-town/Tiles/tile_0076.png | Bin 0 -> 137 bytes assets/kenney/tiny-town/Tiles/tile_0077.png | Bin 0 -> 129 bytes assets/kenney/tiny-town/Tiles/tile_0078.png | Bin 0 -> 155 bytes assets/kenney/tiny-town/Tiles/tile_0079.png | Bin 0 -> 143 bytes assets/kenney/tiny-town/Tiles/tile_0080.png | Bin 0 -> 160 bytes assets/kenney/tiny-town/Tiles/tile_0081.png | Bin 0 -> 120 bytes assets/kenney/tiny-town/Tiles/tile_0082.png | Bin 0 -> 162 bytes assets/kenney/tiny-town/Tiles/tile_0083.png | Bin 0 -> 189 bytes assets/kenney/tiny-town/Tiles/tile_0084.png | Bin 0 -> 170 bytes assets/kenney/tiny-town/Tiles/tile_0085.png | Bin 0 -> 163 bytes assets/kenney/tiny-town/Tiles/tile_0086.png | Bin 0 -> 161 bytes assets/kenney/tiny-town/Tiles/tile_0087.png | Bin 0 -> 161 bytes assets/kenney/tiny-town/Tiles/tile_0088.png | Bin 0 -> 167 bytes assets/kenney/tiny-town/Tiles/tile_0089.png | Bin 0 -> 163 bytes assets/kenney/tiny-town/Tiles/tile_0090.png | Bin 0 -> 161 bytes assets/kenney/tiny-town/Tiles/tile_0091.png | Bin 0 -> 162 bytes assets/kenney/tiny-town/Tiles/tile_0092.png | Bin 0 -> 158 bytes assets/kenney/tiny-town/Tiles/tile_0093.png | Bin 0 -> 162 bytes assets/kenney/tiny-town/Tiles/tile_0094.png | Bin 0 -> 185 bytes assets/kenney/tiny-town/Tiles/tile_0095.png | Bin 0 -> 195 bytes assets/kenney/tiny-town/Tiles/tile_0096.png | Bin 0 -> 189 bytes assets/kenney/tiny-town/Tiles/tile_0097.png | Bin 0 -> 139 bytes assets/kenney/tiny-town/Tiles/tile_0098.png | Bin 0 -> 181 bytes assets/kenney/tiny-town/Tiles/tile_0099.png | Bin 0 -> 171 bytes assets/kenney/tiny-town/Tiles/tile_0100.png | Bin 0 -> 132 bytes assets/kenney/tiny-town/Tiles/tile_0101.png | Bin 0 -> 174 bytes assets/kenney/tiny-town/Tiles/tile_0102.png | Bin 0 -> 175 bytes assets/kenney/tiny-town/Tiles/tile_0103.png | Bin 0 -> 196 bytes assets/kenney/tiny-town/Tiles/tile_0104.png | Bin 0 -> 242 bytes assets/kenney/tiny-town/Tiles/tile_0105.png | Bin 0 -> 198 bytes assets/kenney/tiny-town/Tiles/tile_0106.png | Bin 0 -> 178 bytes assets/kenney/tiny-town/Tiles/tile_0107.png | Bin 0 -> 202 bytes assets/kenney/tiny-town/Tiles/tile_0108.png | Bin 0 -> 122 bytes assets/kenney/tiny-town/Tiles/tile_0109.png | Bin 0 -> 99 bytes assets/kenney/tiny-town/Tiles/tile_0110.png | Bin 0 -> 121 bytes assets/kenney/tiny-town/Tiles/tile_0111.png | Bin 0 -> 203 bytes assets/kenney/tiny-town/Tiles/tile_0112.png | Bin 0 -> 203 bytes assets/kenney/tiny-town/Tiles/tile_0113.png | Bin 0 -> 200 bytes assets/kenney/tiny-town/Tiles/tile_0114.png | Bin 0 -> 200 bytes assets/kenney/tiny-town/Tiles/tile_0115.png | Bin 0 -> 186 bytes assets/kenney/tiny-town/Tiles/tile_0116.png | Bin 0 -> 184 bytes assets/kenney/tiny-town/Tiles/tile_0117.png | Bin 0 -> 172 bytes assets/kenney/tiny-town/Tiles/tile_0118.png | Bin 0 -> 183 bytes assets/kenney/tiny-town/Tiles/tile_0119.png | Bin 0 -> 183 bytes assets/kenney/tiny-town/Tiles/tile_0120.png | Bin 0 -> 158 bytes assets/kenney/tiny-town/Tiles/tile_0121.png | Bin 0 -> 141 bytes assets/kenney/tiny-town/Tiles/tile_0122.png | Bin 0 -> 163 bytes assets/kenney/tiny-town/Tiles/tile_0123.png | Bin 0 -> 145 bytes assets/kenney/tiny-town/Tiles/tile_0124.png | Bin 0 -> 146 bytes assets/kenney/tiny-town/Tiles/tile_0125.png | Bin 0 -> 186 bytes assets/kenney/tiny-town/Tiles/tile_0126.png | Bin 0 -> 140 bytes assets/kenney/tiny-town/Tiles/tile_0127.png | Bin 0 -> 184 bytes assets/kenney/tiny-town/Tiles/tile_0128.png | Bin 0 -> 200 bytes assets/kenney/tiny-town/Tiles/tile_0129.png | Bin 0 -> 200 bytes assets/kenney/tiny-town/Tiles/tile_0130.png | Bin 0 -> 206 bytes assets/kenney/tiny-town/Tiles/tile_0131.png | Bin 0 -> 220 bytes assets/kenney/tiny-town/Tilesheet.txt | 9 + .../tiny-town/Tiny Dungeon (base pack).url | 6 + assets/kenney/tiny-town/Visit Kenney.url | 2 + assets/kenney/tiny-town/Visit Patreon.url | 2 + assets/ui/panel.png | Bin 0 -> 152 bytes build-cli.sh | 26 + build.sh | 52 + examples/chronorift.ludic | 16 + examples/chronorift/combat.ludic | 167 + examples/chronorift/draw.ludic | 138 + examples/chronorift/overworld.ludic | 140 + examples/chronorift/rules.ludic | 86 + examples/chronorift/world.ludic | 43 + examples/hello.ludic | 34 + examples/lib/arena.ludic | 34 + examples/lib/combat.ludic | 46 + examples/menu.ludic | 41 + examples/qdecl.ludic | 37 + examples/scenes.ludic | 38 + examples/snake.ludic | 136 + runtime/native/cocoa.ll | 327 + runtime/native/core.ludic | 394 + runtime/native/image.ludic | 436 + runtime/native/inflate.ludic | 276 + runtime/native/truetype.ludic | 428 + runtime/native/truetype_raster.ludic | 380 + runtime/native/ui.ludic | 312 + runtime/native/ui_draw.ludic | 283 + runtime/web/imports.txt | 32 + runtime/web/index.html | 106 + runtime/web/platform.js | 357 + runtime/web/wasm.ll | 369 + selfhost/ast.ludic | 68 + selfhost/bootstrap-cfree.sh | 40 + selfhost/bootstrap.sh | 40 + selfhost/buf.ludic | 29 + selfhost/build.sh | 39 + selfhost/compile.sh | 8 + selfhost/emit_addr.ludic | 38 + selfhost/emit_core.ludic | 139 + selfhost/emit_decl.ludic | 104 + selfhost/emit_ecs.ludic | 92 + selfhost/emit_expr.ludic | 168 + selfhost/emit_game.ludic | 68 + selfhost/emit_head.ludic | 108 + selfhost/emit_intrin.ludic | 142 + selfhost/emit_intrin2.ludic | 95 + selfhost/emit_machine.ludic | 39 + selfhost/emit_math.ludic | 29 + selfhost/emit_new.ludic | 88 + selfhost/emit_query.ludic | 98 + selfhost/emit_save.ludic | 61 + selfhost/emit_spawn.ludic | 68 + selfhost/emit_stmt.ludic | 193 + selfhost/emit_ui.ludic | 125 + selfhost/game-build.sh | 16 + selfhost/golden/chronorift.ppm | 4 + selfhost/golden/menu.ppm | 4 + selfhost/golden/snake.ppm | 4 + selfhost/io.ludic | 22 + selfhost/lex.ludic | 138 + selfhost/ludicc.seed.ll | 19459 ++++++++++++++++ selfhost/main.ludic | 153 + selfhost/parse.ludic | 322 + selfhost/parse_game.ludic | 144 + selfhost/reseed.sh | 26 + selfhost/str.ludic | 58 + selfhost/test.sh | 52 + selfhost/tests/control.ludic | 13 + selfhost/tests/fixed.ludic | 12 + selfhost/tests/match_bits.ludic | 16 + selfhost/tests/slices.ludic | 11 + selfhost/tests/structs.ludic | 20 + test.sh | 82 + tools/atlas.ludic | 56 + tools/build-tools.sh | 72 + tools/check-docs.py | 78 + tools/check-vocabulary.py | 150 + tools/editors/README.md | 148 + tools/editors/emacs/ludic-mode.el | 70 + tools/editors/helix/languages.toml | 24 + tools/editors/jetbrains/README.md | 58 + tools/editors/jetbrains/build.gradle.kts | 96 + tools/editors/jetbrains/gradle.properties | 26 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 45457 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + tools/editors/jetbrains/gradlew | 248 + tools/editors/jetbrains/gradlew.bat | 93 + tools/editors/jetbrains/settings.gradle.kts | 2 + .../kotlin/io/ludic/ide/LudicConfigurable.kt | 83 + .../kotlin/io/ludic/ide/LudicEditorSupport.kt | 85 + .../main/kotlin/io/ludic/ide/LudicLanguage.kt | 32 + .../main/kotlin/io/ludic/ide/LudicLexer.kt | 148 + .../io/ludic/ide/LudicParserDefinition.kt | 52 + .../main/kotlin/io/ludic/ide/LudicServer.kt | 158 + .../io/ludic/ide/LudicSyntaxHighlighter.kt | 76 + .../main/kotlin/io/ludic/ide/LudicTokens.kt | 81 + .../resources/META-INF/ludic-markdown.xml | 14 + .../src/main/resources/META-INF/plugin.xml | 78 + .../src/main/resources/icons/ludic.svg | 7 + .../kotlin/io/ludic/ide/FindExecutableTest.kt | 155 + .../kotlin/io/ludic/ide/LudicLexerTest.kt | 169 + .../kotlin/io/ludic/ide/LudicPlatformTest.kt | 124 + tools/editors/neovim/lua/ludic.lua | 86 + .../shared/language-configuration.json | 31 + .../shared/ludic.markdown-injection.json | 27 + tools/editors/shared/ludic.tmLanguage.json | 241 + tools/editors/sublime/README.md | 35 + tools/editors/vscode/.vscodeignore | 12 + tools/editors/vscode/README.md | 54 + tools/editors/vscode/icons/ludic.svg | 7 + .../vscode/language-configuration.json | 31 + tools/editors/vscode/package-lock.json | 97 + tools/editors/vscode/package.json | 158 + tools/editors/vscode/snippets/ludic.json | 96 + tools/editors/vscode/src/extension.js | 149 + .../syntaxes/ludic.markdown-injection.json | 27 + .../vscode/syntaxes/ludic.tmLanguage.json | 241 + tools/editors/zed/README.md | 39 + tools/git-hooks/pre-commit | 29 + tools/ludic-tools/ludic_fmt.h | 339 + tools/ludic-tools/ludic_fmt_main.c | 118 + tools/ludic-tools/ludic_index.h | 672 + tools/ludic-tools/ludic_json.h | 191 + tools/ludic-tools/ludic_lsp.c | 1265 + tools/ludic-tools/ludic_syntax.h | 321 + tools/ludic-tools/ludic_workspace.h | 405 + tools/ludic-web/run.mjs | 106 + tools/test-grammar.js | 168 + tools/test-lsp.py | 299 + tools/test-tools.sh | 198 + 418 files changed, 39065 insertions(+) create mode 100644 .claude/launch.json create mode 100644 .gitignore create mode 100644 BOOTSTRAP.md create mode 100644 COMPILING.md create mode 100644 LANGUAGE.md create mode 100644 LUANTI-ROADMAP.md create mode 100644 README.md create mode 100644 SYNTAX-REDESIGN.md create mode 100644 assets/kenney/tiny-dungeon/License.txt create mode 100644 assets/kenney/tiny-dungeon/Preview.png create mode 100644 assets/kenney/tiny-dungeon/Sample.png create mode 100644 assets/kenney/tiny-dungeon/Tiled/sampleMap.tmx create mode 100644 assets/kenney/tiny-dungeon/Tiled/sampleSheet.tsx create mode 100644 assets/kenney/tiny-dungeon/Tilemap/tilemap.png create mode 100644 assets/kenney/tiny-dungeon/Tilemap/tilemap_packed.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0000.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0001.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0002.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0003.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0004.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0005.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0006.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0007.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0008.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0009.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0010.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0011.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0012.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0013.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0014.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0015.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0016.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0017.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0018.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0019.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0020.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0021.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0022.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0023.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0024.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0025.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0026.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0027.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0028.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0029.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0030.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0031.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0032.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0033.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0034.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0035.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0036.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0037.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0038.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0039.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0040.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0041.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0042.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0043.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0044.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0045.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0046.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0047.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0048.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0049.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0050.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0051.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0052.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0053.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0054.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0055.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0056.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0057.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0058.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0059.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0060.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0061.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0062.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0063.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0064.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0065.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0066.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0067.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0068.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0069.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0070.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0071.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0072.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0073.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0074.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0075.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0076.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0077.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0078.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0079.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0080.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0081.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0082.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0083.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0084.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0085.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0086.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0087.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0088.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0089.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0090.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0091.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0092.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0093.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0094.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0095.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0096.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0097.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0098.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0099.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0100.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0101.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0102.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0103.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0104.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0105.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0106.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0107.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0108.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0109.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0110.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0111.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0112.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0113.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0114.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0115.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0116.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0117.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0118.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0119.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0120.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0121.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0122.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0123.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0124.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0125.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0126.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0127.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0128.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0129.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0130.png create mode 100644 assets/kenney/tiny-dungeon/Tiles/tile_0131.png create mode 100644 assets/kenney/tiny-dungeon/Tilesheet.txt create mode 100644 assets/kenney/tiny-dungeon/Visit Kenney.url create mode 100644 assets/kenney/tiny-dungeon/Visit Patreon.url create mode 100644 assets/kenney/tiny-town/License.txt create mode 100644 assets/kenney/tiny-town/Preview.png create mode 100644 assets/kenney/tiny-town/Sample.png create mode 100644 assets/kenney/tiny-town/Tilemap/tilemap.png create mode 100644 assets/kenney/tiny-town/Tilemap/tilemap_packed.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0000.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0001.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0002.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0003.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0004.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0005.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0006.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0007.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0008.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0009.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0010.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0011.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0012.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0013.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0014.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0015.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0016.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0017.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0018.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0019.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0020.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0021.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0022.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0023.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0024.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0025.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0026.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0027.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0028.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0029.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0030.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0031.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0032.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0033.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0034.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0035.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0036.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0037.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0038.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0039.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0040.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0041.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0042.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0043.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0044.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0045.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0046.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0047.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0048.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0049.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0050.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0051.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0052.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0053.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0054.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0055.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0056.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0057.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0058.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0059.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0060.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0061.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0062.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0063.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0064.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0065.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0066.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0067.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0068.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0069.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0070.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0071.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0072.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0073.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0074.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0075.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0076.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0077.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0078.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0079.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0080.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0081.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0082.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0083.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0084.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0085.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0086.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0087.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0088.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0089.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0090.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0091.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0092.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0093.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0094.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0095.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0096.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0097.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0098.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0099.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0100.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0101.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0102.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0103.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0104.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0105.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0106.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0107.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0108.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0109.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0110.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0111.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0112.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0113.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0114.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0115.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0116.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0117.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0118.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0119.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0120.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0121.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0122.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0123.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0124.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0125.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0126.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0127.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0128.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0129.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0130.png create mode 100644 assets/kenney/tiny-town/Tiles/tile_0131.png create mode 100644 assets/kenney/tiny-town/Tilesheet.txt create mode 100644 assets/kenney/tiny-town/Tiny Dungeon (base pack).url create mode 100644 assets/kenney/tiny-town/Visit Kenney.url create mode 100644 assets/kenney/tiny-town/Visit Patreon.url create mode 100644 assets/ui/panel.png create mode 100755 build-cli.sh create mode 100755 build.sh create mode 100644 examples/chronorift.ludic create mode 100644 examples/chronorift/combat.ludic create mode 100644 examples/chronorift/draw.ludic create mode 100644 examples/chronorift/overworld.ludic create mode 100644 examples/chronorift/rules.ludic create mode 100644 examples/chronorift/world.ludic create mode 100644 examples/hello.ludic create mode 100644 examples/lib/arena.ludic create mode 100644 examples/lib/combat.ludic create mode 100644 examples/menu.ludic create mode 100644 examples/qdecl.ludic create mode 100644 examples/scenes.ludic create mode 100644 examples/snake.ludic create mode 100644 runtime/native/cocoa.ll create mode 100644 runtime/native/core.ludic create mode 100644 runtime/native/image.ludic create mode 100644 runtime/native/inflate.ludic create mode 100644 runtime/native/truetype.ludic create mode 100644 runtime/native/truetype_raster.ludic create mode 100644 runtime/native/ui.ludic create mode 100644 runtime/native/ui_draw.ludic create mode 100644 runtime/web/imports.txt create mode 100644 runtime/web/index.html create mode 100644 runtime/web/platform.js create mode 100644 runtime/web/wasm.ll create mode 100644 selfhost/ast.ludic create mode 100755 selfhost/bootstrap-cfree.sh create mode 100755 selfhost/bootstrap.sh create mode 100644 selfhost/buf.ludic create mode 100755 selfhost/build.sh create mode 100755 selfhost/compile.sh create mode 100644 selfhost/emit_addr.ludic create mode 100644 selfhost/emit_core.ludic create mode 100644 selfhost/emit_decl.ludic create mode 100644 selfhost/emit_ecs.ludic create mode 100644 selfhost/emit_expr.ludic create mode 100644 selfhost/emit_game.ludic create mode 100644 selfhost/emit_head.ludic create mode 100644 selfhost/emit_intrin.ludic create mode 100644 selfhost/emit_intrin2.ludic create mode 100644 selfhost/emit_machine.ludic create mode 100644 selfhost/emit_math.ludic create mode 100644 selfhost/emit_new.ludic create mode 100644 selfhost/emit_query.ludic create mode 100644 selfhost/emit_save.ludic create mode 100644 selfhost/emit_spawn.ludic create mode 100644 selfhost/emit_stmt.ludic create mode 100644 selfhost/emit_ui.ludic create mode 100755 selfhost/game-build.sh create mode 100644 selfhost/golden/chronorift.ppm create mode 100644 selfhost/golden/menu.ppm create mode 100644 selfhost/golden/snake.ppm create mode 100644 selfhost/io.ludic create mode 100644 selfhost/lex.ludic create mode 100644 selfhost/ludicc.seed.ll create mode 100644 selfhost/main.ludic create mode 100644 selfhost/parse.ludic create mode 100644 selfhost/parse_game.ludic create mode 100755 selfhost/reseed.sh create mode 100644 selfhost/str.ludic create mode 100755 selfhost/test.sh create mode 100644 selfhost/tests/control.ludic create mode 100644 selfhost/tests/fixed.ludic create mode 100644 selfhost/tests/match_bits.ludic create mode 100644 selfhost/tests/slices.ludic create mode 100644 selfhost/tests/structs.ludic create mode 100755 test.sh create mode 100644 tools/atlas.ludic create mode 100755 tools/build-tools.sh create mode 100755 tools/check-docs.py create mode 100755 tools/check-vocabulary.py create mode 100644 tools/editors/README.md create mode 100644 tools/editors/emacs/ludic-mode.el create mode 100644 tools/editors/helix/languages.toml create mode 100644 tools/editors/jetbrains/README.md create mode 100644 tools/editors/jetbrains/build.gradle.kts create mode 100644 tools/editors/jetbrains/gradle.properties create mode 100644 tools/editors/jetbrains/gradle/wrapper/gradle-wrapper.jar create mode 100644 tools/editors/jetbrains/gradle/wrapper/gradle-wrapper.properties create mode 100755 tools/editors/jetbrains/gradlew create mode 100644 tools/editors/jetbrains/gradlew.bat create mode 100644 tools/editors/jetbrains/settings.gradle.kts create mode 100644 tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicConfigurable.kt create mode 100644 tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicEditorSupport.kt create mode 100644 tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicLanguage.kt create mode 100644 tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicLexer.kt create mode 100644 tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicParserDefinition.kt create mode 100644 tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicServer.kt create mode 100644 tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicSyntaxHighlighter.kt create mode 100644 tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicTokens.kt create mode 100644 tools/editors/jetbrains/src/main/resources/META-INF/ludic-markdown.xml create mode 100644 tools/editors/jetbrains/src/main/resources/META-INF/plugin.xml create mode 100644 tools/editors/jetbrains/src/main/resources/icons/ludic.svg create mode 100644 tools/editors/jetbrains/src/test/kotlin/io/ludic/ide/FindExecutableTest.kt create mode 100644 tools/editors/jetbrains/src/test/kotlin/io/ludic/ide/LudicLexerTest.kt create mode 100644 tools/editors/jetbrains/src/test/kotlin/io/ludic/ide/LudicPlatformTest.kt create mode 100644 tools/editors/neovim/lua/ludic.lua create mode 100644 tools/editors/shared/language-configuration.json create mode 100644 tools/editors/shared/ludic.markdown-injection.json create mode 100644 tools/editors/shared/ludic.tmLanguage.json create mode 100644 tools/editors/sublime/README.md create mode 100644 tools/editors/vscode/.vscodeignore create mode 100644 tools/editors/vscode/README.md create mode 100644 tools/editors/vscode/icons/ludic.svg create mode 100644 tools/editors/vscode/language-configuration.json create mode 100644 tools/editors/vscode/package-lock.json create mode 100644 tools/editors/vscode/package.json create mode 100644 tools/editors/vscode/snippets/ludic.json create mode 100644 tools/editors/vscode/src/extension.js create mode 100644 tools/editors/vscode/syntaxes/ludic.markdown-injection.json create mode 100644 tools/editors/vscode/syntaxes/ludic.tmLanguage.json create mode 100644 tools/editors/zed/README.md create mode 100755 tools/git-hooks/pre-commit create mode 100644 tools/ludic-tools/ludic_fmt.h create mode 100644 tools/ludic-tools/ludic_fmt_main.c create mode 100644 tools/ludic-tools/ludic_index.h create mode 100644 tools/ludic-tools/ludic_json.h create mode 100644 tools/ludic-tools/ludic_lsp.c create mode 100644 tools/ludic-tools/ludic_syntax.h create mode 100644 tools/ludic-tools/ludic_workspace.h create mode 100644 tools/ludic-web/run.mjs create mode 100644 tools/test-grammar.js create mode 100755 tools/test-lsp.py create mode 100755 tools/test-tools.sh diff --git a/.claude/launch.json b/.claude/launch.json new file mode 100644 index 00000000..fd0e3829 --- /dev/null +++ b/.claude/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.0.1", + "configurations": [ + { + "name": "ludic-web", + "runtimeExecutable": "python3", + "runtimeArgs": ["-m", "http.server", "8123", "-d", "build/web"], + "port": 8123 + } + ] +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..79dd09f7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +build +**.zip +out.ppm + +# self-hosted front-end binaries (built by ./build-cli.sh) and their output +/ludic +/ludicc +/bin/ + +# editor toolchain build artifacts +tools/editors/vscode/node_modules/ +tools/editors/vscode/*.vsix +tools/editors/jetbrains/.gradle/ +tools/editors/jetbrains/build/ + +# IntelliJ plugin SDK sandbox (tools/editors/jetbrains) +.intellijPlatform/ diff --git a/BOOTSTRAP.md b/BOOTSTRAP.md new file mode 100644 index 00000000..6beae06f --- /dev/null +++ b/BOOTSTRAP.md @@ -0,0 +1,967 @@ +# Bootstrapping Ludic in Ludic + +**What it would take for Ludic to compile itself.** + +Today `ludicc` is a C program: 2,508 lines across `compiler/ludicc.c`, +`compiler/native.c` and `compiler/driver.c`. Everything it produces is +Ludic-or-IR — the runtime a game calls is 2,501 lines of `.ludic`, and no C is +generated, compiled or linked in a build. The compiler is the last C in the +pipeline, and this document is about removing it. + +Every claim about what the language can and cannot do below was **verified +against the built compiler**, not read off the docs. The probe programs are in +the appendix; each `✅`/`�` is a real compile-and-run. + +--- + +## 1. What "completely bootstrapped" means + +Self-hosting is not one property. It is three independent axes, and they cost +wildly different amounts: + +| Axis | Today | Target | +|---|---|---| +| **Compiler independence** — is the compiler written in the language? | � 2,508 lines of C | `ludicc` written in Ludic, compiling itself to a fixpoint | +| **Runtime independence** — is the library the language ships written in the language? | ✅ **already done** — 2,501 lines of `.ludic` (gfx, PNG/DEFLATE, TrueType, UI) | keep | +| **Toolchain independence** — does a build need a foreign compiler? | � `clang` assembles the IR and links | see §7 — three levels, only one is worth reaching | + +The runtime axis is already won, and that is the unusual part. Most languages +self-host the compiler long before they stop leaning on a C standard library; +Ludic did it backwards. **The remaining work is concentrated in one axis.** + +There is also a fourth, smaller thing: `runtime/native/cocoa.ll` (327 lines) and +`runtime/web/wasm.ll` are hand-written LLVM IR, not Ludic. §7.4 covers whether +that matters. + +Running alongside all of this is a question the bootstrap forces rather than +raises: **what the syntax should finally be.** A self-hosted compiler is written +in the language it compiles, so the grammar wants to be settled *before* the +port, not after. §5 audits what is irregular today and proposes the freeze; it +is scheduled as Stage 0.5, between the language features and the libraries. + +### The honest bar + +"Bootstrapped by itself completely" should mean: + +1. `ludicc` is written in Ludic. +2. A `ludicc` binary compiles the Ludic source of `ludicc` and produces a + **byte-identical** binary to itself (the fixpoint test, §6). +3. The C compiler is needed **only** to build the very first seed, and that seed + is a checked-in artifact rather than a live dependency. +4. No C source remains in the repo outside that seed. + +It should *not* mean writing an object-file writer and a linker. Rust and Swift +are self-hosted and both stand on LLVM; standing on `clang` as an IR assembler +is the same posture. §7 argues this explicitly so the goal does not quietly +inflate. + +--- + +## 2. Where the tree stands + +``` +compiler/ C split by concern; every file under 500 lines + ludicc.c 435 pipeline + codegen glue + main + util/ sb, diag 103 string builder; source registry + diagnostics + front/ lex, ast, parse 469 tokens; Node; recursive descent + imports + sem/ tables, uitree, validate 208 decl tables; widget flattening; static checks + back/ ir_* x10 953 the LLVM IR backend, one file per concern + driver/ toolchain, webbundle 382 IR -> object -> exe/dylib; the wasm bundle + fmt/ fmt 162 canonical AST printer (--fmt) + ------ + 2,712 C <- all of it, and all that must go +tools/ludic-tools/* 3,260 C ludic-fmt + ludic-lsp (not yet split) + +runtime/native/core.ludic 394 Ludic framebuffer, text, registers, RNG, input +runtime/native/image.ludic 436 Ludic PNG, sprites, alpha blend, 9-slice +runtime/native/inflate.ludic 276 Ludic DEFLATE (RFC 1951) +runtime/native/truetype.ludic 804 Ludic sfnt loader + AA rasterizer, Q16.16 +runtime/native/ui.ludic 591 Ludic retained widget tree, layout, focus + ---- + 2,501 Ludic <- proof the language is already load-bearing + +runtime/native/cocoa.ll 327 LLVM IR macOS window (objc_msgSend + CoreGraphics) +runtime/web/wasm.ll 369 LLVM IR browser shims +``` + +`util/`, `front/`, `sem/` and `fmt/` are separately compiled translation units; +`back/` and `driver/` are still one unit assembled by `back/native.c`, so their +include order is their definition order. The build list lives in +`compiler/sources.sh`, sourced by both `build.sh` and `test.sh`. + +`truetype.ludic` matters more than its line count. A from-scratch sfnt parser +with cmap format dispatch, composite glyph recursion and a Bézier rasterizer is +*structurally the same kind of program as a compiler*: binary input, recursive +descent, table lookups, a growing output buffer. It already works. That is the +strongest single piece of evidence that this port is feasible rather than +aspirational. + +--- + +## 3. What the language can already do + +All verified. A compiler needs each of these, and each one works today. + +| Capability | Status | Evidence | +|---|---|---| +| Recursion | ✅ | `fib(10)` → `55` | +| Mutual recursion / forward references | ✅ | `odd`/`even` cross-call | +| Deep recursion (recursive-descent parsing) | ✅ | 5,000 frames, no crash | +| Heap allocation | ✅ | `mem_alloc`, `mem_free`, `mem_copy`, `mem_set`; 1 MiB alloc verified | +| Byte-level memory | ✅ | `peek8`/`poke8`, `peek32`/`poke32`, `peekp`/`pokep`, `ptr_add` | +| `ptr` locals, params, returns | ✅ | `fn make(n: int) -> ptr` | +| `ptr` in a component field | ✅ | `component Nd { kind: int = 0, a: ptr = ptr_null() }` | +| String literals as readable bytes | ✅ | `peek8("hello", 1)` → `101` | +| `str` accepted where `ptr` expected | ✅ | `f("A")` into `fn f(p: ptr)` | +| String comparison, **hand-written in Ludic** | ✅ | `streq` over `peek8` | +| Integer → decimal, **hand-written in Ludic** | ✅ | `itoa(48291)` → `"48291"` | +| File read: open/seek/tell/read/close | ✅ | full round-trip of a written file | +| File write | ✅ | `file_open`/`file_write`/`file_close` | +| Module-level mutable state | ✅ | `var count: int`, `var heap: ptr` | +| `let` is mutable | ✅ | `i = i + 1` in a loop | +| `while`, numeric `for i in a .. b` with runtime bounds | ✅ | | +| `if` / `else if` / `else` chains | ✅ | | +| `match` with multi-value arms and `_` | ✅ | `1 => … 2, 3 => … _ => …` | +| Bitwise ops | ✅ | `band`/`bor`/`bxor`/`bnot`/`shl`/`shr` | +| `shr` is **logical**, not arithmetic | ✅ | `shr(-16, 1)` → `2147483640` | +| Character literals | ✅ | `'x'`, `'\n'`, `'\0'` lex to ints | +| Exit codes | ✅ | `os_exit(3)` → shell sees `3` | +| Separate compilation, C ABI | ✅ | `module` + `export fn`, `extern fn … = "sym"` | + +**The consequence:** a compiler is *already expressible* in Ludic today. You +could write a lexer, a parser building nodes as hand-offset `peek32`/`poke32` +records, a symbol table, and an IR text emitter, using nothing above. It would +be miserable to read and maintain at 6,000 lines — but nothing in §4 is a +*capability* blocker except argv. The rest is about whether the resulting source +is something a human or a model can work in. + +That distinction shapes the whole plan: **this is mostly an ergonomics project +with one small hole in it**, not a language-design project. + +--- + +## 4. What the language is missing + +Each entry: the gap, why a compiler specifically needs it, the proposed design, +and the lowering. Verified-missing means it is a compile error today. + +### Tier A — real blockers + +#### A1. Command-line arguments � *the only true capability blocker* + +``` +ludicc: error: line 1: unknown function 'os_argc' +``` + +`ll_emit_main` in `compiler/native.c` emits `define i32 @main()` — **no +parameters**. A self-hosted `ludicc` has no way to learn which file to compile. +Everything else in this document has a workaround; this one does not. + +**Design.** Two intrinsics: + +```ludic +# doc-check: skip — proposed signature notation, not code +os_argc() -> int +os_arg(i: int) -> str +``` + +**Lowering.** Change the signature to `define i32 @main(i32 %argc, ptr %argv)`, +store both into `@L_argc` / `@L_argv` in the entry block, then `os_argc()` is a +load and `os_arg(i)` is exactly the existing `peekp(@L_argv, i)` path. Add to +`INTRINSICS[]` in `native.c`. + +**Cost.** ~30 lines of C. This is the single highest-value change in the +document: it is what turns "a Ludic program" into "a Ludic command-line tool". + +#### A2. Aggregate types (`struct`) � + +``` +ludicc: error: line 2: expected declaration (got 'struct') +``` + +An AST node, a token, a symbol-table entry and a type descriptor are all +records. Today there are two workarounds, and both are bad at compiler scale: + +- **Hand-offset memory** — `poke32(n, 0, kind)`, `pokep(n, 1, child)`. This is + what `truetype.ludic` does, and it works, but every field access becomes a + magic number. Across a 6,000-line compiler this is the difference between + maintainable and not. +- **ECS entities as nodes** — verified working (`component Nd { kind, a: ptr }`), + and initially seductive because queries give you free traversal. **Do not do + this.** `LUDIC_MAX_ENT` is 1024 in `native.c:18`; the entity world is a fixed + array of per-component storage. A compiler needs hundreds of thousands of + nodes. This is a dead end, and it is worth writing down because it is the + obvious wrong turn. + +**Design — reference semantics, not value semantics.** The cheap version that +unblocks everything: + +```ludic +# doc-check: skip — proposed syntax: struct does not exist yet +struct Tok { kind: int = 0, text: ptr = ptr_null(), line: int = 0 } + +let t = new Tok # heap-allocated, fields seeded from defaults +t.kind = T_ID +print_int(t.line) +free Tok t # or leak it; see §8 on arenas +``` + +No copying, no by-value passing, no nested-struct inlining — a `struct` value +*is* a `ptr` with a known layout, so it costs nothing in the type system beyond +a layout table. + +**Lowering.** This is largely already built. `native.c` already emits +`%Cmp_` LLVM struct types for components and already resolves +`a.b` through `ll_member_addr` with `getelementptr`. A `struct` is a +`%Cmp_`-style type *without* the parallel entity arrays: `new` is +`malloc(sizeof)` plus a default-seeding memset/store sequence, and `.field` is +the existing `getelementptr` path. Reusing the component machinery is why this +is far cheaper than it looks. + +**Cost.** ~250 lines of C across `ludicc.c` (parse) and `native.c` (layout, +`new`, member access). Highest cost in the document, and the highest payoff. + +#### A3. Arrays and indexing � + +``` +ludicc: error: line 2: expected identifier (got '[') +``` + +Token buffers, string tables, keyword tables, scope stacks. Currently +`mem_alloc` + `peek32`, which works but reads badly. + +**Design.** + +```ludic +# doc-check: skip — proposed syntax: array types do not exist yet +var keywords: [str; 64] # fixed-size module-level storage +let toks: [Tok; 0] = mem_alloc(n * size_of(Tok)) # or a growable buffer +toks[i].kind = T_ID # composes with A2 +``` + +**Lowering.** `[T; N]` is `[N x ]`, already exactly how `@L_alive` and +`@S_` are emitted. `a[i]` as both rvalue and lvalue is a +`getelementptr` — the same code path as member access, indexed instead of +named. The important part is that `toks[i].kind` composes: index then member, +one GEP chain. + +**Cost.** ~150 lines. Should land *with* A2, since neither is much use alone. + +#### A4. `break` / `continue` � + +``` +ludicc: error: line 3: unknown identifier 'break' +``` + +Lexers and parsers are made of `while (1) { … break; }`. The workaround — +sentinel booleans threaded through every loop condition — is the kind of thing +that makes a 6,000-line port unreadable. + +**Design.** `break`, `continue`. No labels; nested loops in a compiler rarely +need them, and adding labels later is compatible. + +**Lowering.** `native.c` already maintains `ll_loopstk[64]` (for `self()` inside +queries). Extend each frame with `break_label` and `continue_label`, then +`break` is `br label %`. Note the existing gotcha recorded in the native +backend notes: **stack slots must be emitted in the entry block** — no new +allocas at the break site. + +**Cost.** ~40 lines. Best value-per-line in the document. + +#### A5. `mem_realloc` � + +``` +ludicc: error: line 1: unknown function 'mem_realloc' +``` + +Every table in a compiler grows: tokens, nodes, the output buffer. Hand-rolling +alloc-copy-free works but is written once per table and gotten wrong once per +table. + +**Design.** `mem_realloc(p: ptr, n: int) -> ptr`. + +**Lowering.** `declare ptr @realloc(ptr, )` plus one `INTRINSICS[]` +entry. **Use `ll_size_t()` / `ll_widen()` for the size argument — do not +hardcode `i64`.** `size_t` is `i32` on wasm32, and `native.c` now routes every +size-taking intrinsic through those helpers for exactly this reason. + +**Cost.** ~6 lines. + +#### A6. Diagnostics on stderr � + +``` +ludicc: error: line 1: unknown function 'print_err' +``` + +Only stdout exists (`print_str` → `printf`, `write_byte` → `putchar`). This is +not cosmetic: **`ludicc --emit llvm` writes IR to stdout.** A self-hosted +compiler that printed errors to stdout would interleave diagnostics into its own +output, corrupting it in exactly the case you most want a diagnostic. + +**Design.** Prefer an intrinsic that yields a handle, so the existing file +plumbing is reused rather than duplicated: + +```ludic +# doc-check: skip — proposed signature notation, not code +file_stderr() -> ptr # then file_write(f, buf, n) as usual +``` + +**Lowering — note the portability wrinkle.** There is no portable `@stderr` +global in LLVM IR: Darwin exports `@__stderrp`, glibc exports `@stderr`, and +wasm has neither in the same shape. So `file_stderr()` must select per target, +alongside the existing `target_os()` logic in `driver.c`. This is the one item +here that is genuinely target-dependent rather than merely unimplemented, and +it should be designed with that in mind rather than bolted on. + +**Cost.** ~40 lines including the per-target selection. + +### Tier B — needed for *complete* bootstrap, not for the compiler + +#### B1. Function pointers � + +``` +ludicc: error: line 3: unknown type 'fn' for var h +``` +`&cb` also fails to compile. + +The compiler itself does **not** need these — `match` dispatch covers every +place a C compiler would use a function pointer table. + +But they are what would let `cocoa.ll` become Ludic. The macOS window builds an +`NSView` subclass at runtime with `objc_allocateClassPair` and installs **an IR +function as its IMP**. Without the ability to take the address of a Ludic `fn`, +that shim can never move out of hand-written IR. So: irrelevant to §6, and +load-bearing for §7.4. + +**Design.** `&fnname` yields a `ptr`; call through it via +`call_ptr(p, args…)` or a typed `fn(int)->int` type. + +**Cost.** ~120 lines. Defer until after the fixpoint. + +#### B2. String operations — **no language change needed** + +`str + str` is worth calling out as a *bug*, not a gap. It passes the front-end +and then emits invalid IR: + +``` +build/probe_t_headless.ll:13401:17: error: global variable reference must have pointer type +``` + +That is a front-end/backend mismatch: the typechecker accepts an operation the +backend cannot lower. Until strings exist properly, `str + str` should be a +clean compile error rather than a `clang` error in generated code. + +Everything else a compiler needs from strings is **already writable in Ludic +today** — `streq` and `itoa` are verified. This is not a language gap; it is a +library to write (§6 Stage 1), and it is the largest pure-typing chunk of the +whole project. + +### Tier C — explicitly out of scope, recorded so they are not rediscovered + +| Gap | Why it does not block | +|---|---| +| **64-bit integers** � (`100000*100000` → `1410065408`, wraps at i32) | Line numbers, offsets, node indices and string lengths all fit in `i32`. Only matters for source files > 2 GiB. | +| **A non-ECS entry point** | A `Start`-phase system plus `os_exit(n)` gives correct exit codes — verified. You do pay for an unused 1024-entity world; that is a constant, not a blocker. A `tool Name { fn main() -> int }` form would be nicer, not necessary. | +| Closures, generics, unions, sum types | A compiler in the style of `ludicc.c` uses none of them. | +| GC | A compiler should leak deliberately (§8). | +| Unsigned integer types | `shr` is already logical and `band`/`bor` are bit-level — sufficient. | +| Multiple return values | `ptr` out-parameters work today. | + +--- + +## 5. Designing for readers — human and model + +The goal: Ludic source should be obvious to a person skimming it and +unambiguous to a model generating it. Those two goals agree far more than they +conflict, and where they conflict the resolution is **regularity, not +verbosity** (§5.2). + +Everything in this section was verified against the built compiler. The probes +are in the appendix under "Syntax audit". + +### 5.1 Why this belongs in the bootstrap document, and why now + +**Syntax changes are cheap today and expensive after Stage 3.** This is a hard +ordering constraint, not a preference. + +Today, changing the grammar costs: edit `ludicc.c`, `sed` three examples and +five runtime files, run `./test.sh`. An afternoon. + +After the fixpoint, `ludicc` is *written in the syntax it parses*. Every change +becomes a four-step dance: build a compiler that accepts both old and new forms +→ compile it with the old seed → rewrite every source file → remove the old +form and regenerate the seed. That is what every mature language does, and it +is why mature languages change syntax slowly. It is not a reason to avoid the +change; it is a reason to **make it before the port, not after**. + +So the plan gains a stage: + +> **Stage 0.5 — Syntax freeze.** Between Stage 0 (language features) and +> Stage 1 (libraries). Nothing in Stage 2 starts until the grammar is final. + +The port should be *the first large program written in final Ludic*, not the +last large program written in provisional Ludic. + +**This work also strengthens the bootstrap itself.** Stage 2b uses `--fmt` +equality as the oracle proving two parsers agree. That oracle is only as tight +as the language is regular: every alternative spelling is surface variance the +formatter must erase. Reduce the variance and the oracle gets sharper. The +readability project and the self-hosting project are not competing for the same +time — one makes the other more trustworthy. + +### 5.2 What actually helps a model — and what is folklore + +Worth being precise here, because "AI-friendly syntax" attracts a lot of +confident nonsense. + +**Genuinely helps:** + +| Property | Why it matters | +|---|---| +| **Low syntactic variance** — one spelling per concept | Every alternative is a branch point during generation and a case in the parser. Two ways to write a list is two chances to be inconsistent within one file. | +| **Leading-keyword, bounded lookahead** | Every declaration and statement identifiable from its first token. Helps the hand-written recursive-descent parser Stage 2b will be, *and* a model predicting forward. | +| **No silent no-ops** | If the language accepts a construct it must either honour it or reject it. Accepting-and-ignoring teaches a falsehood (see R6 — the worst thing in the audit). | +| **Recoverable structure** — explicit terminators | A slightly-wrong generation fails *locally*, with an error pointing at the mistake, instead of cascading into a confusing error 40 lines later. | +| **Locality** — meaning readable from the construct | No action-at-a-distance. Ludic is already strong here; keep it. | +| **Greppable unique anchors** | `component Pos` is findable. Retrieval quality is a language design property. | +| **Errors that name the fix** | Already partly true: a missing builtin errors naming `rt_`. Extend that everywhere. | + +**Folklore, and false:** + +- *"More verbose is more AI-friendly."* No. Ceremony without information hurts + both audiences. What helps is redundancy that **encodes intent** — an explicit + type, a closing keyword — not boilerplate. +- *"Significant indentation reads better."* It reads fine and **generates + badly**: indentation drift across a long generated block is unrecoverable and + survives review. Ludic uses braces. Keep them. +- *"Natural-language-like syntax helps."* Prose-shaped keywords add ambiguity. + Consistent symbols beat English words that read three ways. +- *"Terseness is bad for models."* Terseness is fine; *irregularity* is the + problem. A short form used consistently is easy to predict. + +**The real tension:** humans skim, so terseness helps them; machines benefit +from redundancy. Regularity resolves it — the same shape everywhere costs a +human nothing once learned, and costs a model nothing to predict. + +### 5.3 Audit — what is irregular in Ludic today + +Each row verified by compiling a probe, not by reading docs. + +| # | Irregularity | Evidence | Cost | +|---|---|---|---| +| **R1** | **No statement terminator at all.** `block()` is `skipnl(); stmt()` in a loop. A newline *stops* an expression (it lexes as `T_NL`, and `binlevel` only continues on `T_OP`) but is never *required*. `let x = 1 x = x + 1 print_int(x)` on one line is three legal statements — verified compiling. | `ludicc.c` `block()`, `binlevel` | The reader cannot see where a statement ends without re-deriving operator precedence. Blocks error recovery entirely. | +| **R2** | **Commas are optional everywhere.** `if(isop(",")) pi++` appears in `comp()`, `arche()`, `fn` params and `spawn`. `{ x: int = 0 y: int = 0 }` and the comma'd form both compile. | 4 parser sites | Two spellings, zero semantic difference. | +| ~~**R3**~~ | ~~**`and`/`or` alias `&&`/`\|\|`.**~~ **RESOLVED** — `and`/`or`/`not` are the only boolean operators; `&&`, `\|\|` and `!` are each rejected with a diagnostic naming the fix, and all three words are reserved. `!=` is unaffected. | landed via S3 | — | +| **R4** | **`{ }` means seven different things** — statement block; component fields (`n: T = e`); archetype list (bare idents); spawn initialisers (`N = { … }`); ui props + children (`k=v` juxtaposed, no commas); match arms (`p, p => …`); machine states (`state N = v { … }`). | `block/comp/arche/spawn/parse_widget/match/machine` | The delimiter carries no information. You must already know the head keyword to know the inner grammar. | +| **R5** | **Contextual keywords, not reserved.** `phase`, `query`, `reads`, `writes`, `needs`, `uses`, `where`, `in`, `on`, `layer`, `state`, `start` are matched with `isid()` — ordinary identifiers. `let query = 5 let phase = 6` compiles and prints `11`. | `sys()`, `scene_decl()` | A local named `enter` or `match` produces a baffling error far from the cause. | +| **R6** | **Contracts are parsed and thrown away.** `requires`/`ensures`/`invariant` parse an expression and **discard it** (`pi++; expr();`). `reads`/`writes`/`needs`/`uses`/`effects` are `skip_brackets()`. `pure` is consumed and ignored. Verified: `fn half(n: int) -> int requires n > 100000 ensures false` compiles, and `half(8)` returns `4`. Verified: a system declaring `reads [Pos]` that **writes** `p.x = 99` compiles. | `fn()`, `sys()` | **The worst item in the audit.** The language accepts a contract and does nothing. A model writing `requires n > 0` is rewarded with a clean compile and zero enforcement — it learns a lie, and so does a human reader trusting the annotation. | +| **R7** | **`str + str` typechecks, then emits invalid IR.** | verified (§4 B2) | The front-end accepts what the backend cannot lower. | +| **R8** | **Two formatters, opposite philosophies, both called "format".** `ludicc --fmt` canonicalises hard (one statement per line, `and`→`&&`, full parenthesisation) but drops comments and inlines imports. `ludic-fmt` is token-based and preserves comments — but **normalises nothing**: handed the one-line `let a = 1 a = a + 1 if true and false { … }`, it returned it unchanged. | verified side-by-side | **Neither tool enforces a single spelling.** The canonicaliser is unusable on real source; the source formatter has no opinion. | +| **R9** | **Two ways to spell a tag** — `component Player { }` (empty component) or `archetype`. | LANGUAGE.md | | +| **R10** | **Stale docs are stale training data.** LANGUAGE.md still says "the current compiler is a tree-to-C translator" (it emits LLVM IR) and lists arrays under "Not yet implemented" beside things never planned. | LANGUAGE.md | Docs are the highest-leverage model input in the repo. A wrong doc is worse than a missing one. | + +### 5.4 Proposals + +Ordered by value per line of work. Each is a Stage 0.5 item unless noted. + +**S1. Require a statement terminator.** A statement ends at a newline, `;`, or +`}`. Make `T_NL` significant inside `block()` instead of discarding it. +*Why:* fixes R1, and it is the precondition for error recovery — without it a +parser cannot resynchronise, so every syntax error stays a cascade. +*Cost:* ~30 lines. *Ripple:* one-line bodies like `if x { a }` still work; +multi-statement one-liners in the runtime need a `sed`. + +**S2. Make separators mandatory.** Commas required in every comma-list; +remove the optional path. *Fixes R2. Cost:* ~10 lines + tree-wide `sed`. + +**S3. One spelling for boolean operators. ✅ LANDED.** `and`/`or` are the only +boolean operators. Ludic already spells bitwise operations as functions +(`band`/`bor`), so the symbols bought nothing, and dropping them removes the +`&` vs `&&` bug class by construction. + +What shipped: `&&`/`||` still *lex* as single tokens, purely so the parser can +emit `'&&' is not a Ludic operator - write 'and'` instead of tripping over a +stray `&`; `and`/`or` became reserved words, so `let and = 5` is rejected at the +mistake; the AST op string is now `"and"`/`"or"`, which is **exactly the LLVM +opcode**, so the lowering ternary collapsed to passing `op` straight through; +and `--fmt` emits the new spelling for free, since it prints the op string. +Six regression tests in `test.sh` (64 → 70), including one asserting no `.ludic` +source uses the symbols outside a comment. *Fixed R3.* + +**S4. Reserve every keyword.** One table, shared by the lexer, parser, +`ludic-fmt` and `ludic-lsp` — those tools already share a vocabulary in +`ludic_syntax.h`, so there is one obvious home. Reject `let query = 5` at the +point of the mistake. *Fixes R5. Cost:* ~40 lines. + +**S5. Delete or implement every silent no-op.** � **highest value in the +section.** Two honest options per construct, no third: + +- `reads` / `writes`: **implement them.** The compiler already knows every + component a system touches — it builds the query and walks the body. Checking + the declaration against actual access is a genuine static analysis the + language claims to have and doesn't. This converts dead syntax into a real + guarantee, which is exactly what an "AI-first" language should offer a model + reasoning about a system in isolation. +- `requires` / `ensures`: either lower to a checked assertion in debug builds + (`if !cond { print_err(...) os_exit(1) }` — cheap, and A6 stderr lands in + Stage 0 anyway), or remove them from the grammar until they mean something. +- `pure`, `needs`, `uses`, `effects`, `invariant`: remove until implemented. + +*Fixes R6. Cost:* ~150 lines for `reads`/`writes` checking, ~60 for assertions, +~10 to delete the rest. + +**S6. Cut the block grammars from seven to two.** Full unification is too +invasive to be worth it. The achievable version: every `{ }` is either a +**statement block** or a **field list** (`name: type = default`, comma-separated, +one shape), and `ui` props adopt the same separator rule as everything else. +Document all remaining shapes in one grammar table. *Partially fixes R4. +Cost:* ~120 lines. + +**S7. One formatter with one contract.** Merge the philosophies rather than +keeping two half-tools: `ludic-fmt` gains `--fmt`'s normalisation decisions +(statement-per-line, single spelling, consistent commas) while keeping its +token-based comment preservation, and becomes **normative** — `ludic-fmt +--check` gates CI. `ludicc --fmt` reverts to being an honest debug dump and is +renamed `--dump-ast`. *Fixes R8.* After S1–S3, canonical form is the *only* +form, so the formatter stops being a style preference and becomes a check. +*Cost:* ~200 lines, mostly in `ludic_fmt.h`. + +**S8. Machine-readable grammar and diagnostics.** Emit the grammar as one EBNF +file, and give every diagnostic a stable code plus a one-line suggested fix +(`ludicc --explain L0412`). Feeds the LSP, the docs and any model at once. +*Cost:* ~250 lines. *Defer to after the fixpoint* — valuable, not ordering-critical. + +**S9. Documentation hygiene as a build step.** `test.sh` already understands +` ```ludic ` fences. Extend it so **every fence in every `.md` must compile**, +and fix R10's stale claims. *Cost:* ~60 lines of shell. Do this early — it is +cheap and it stops the docs drifting further while the rest of the work lands. + +### 5.5 What not to change + +Recording these so they are not relitigated: + +- **Braces, not indentation** (§5.2). +- **`#` comments** — unambiguous, one spelling already. +- **The ECS vocabulary** — `component` / `system` / `query` / `phase` are + unusually self-describing and greppable. This is the language's best existing + readability asset. +- **`fixed` / Q16.16** — determinism is a design constraint, not a style choice. +- **Do not add** operator overloading, implicit conversions beyond `int`→`fixed`, + macros, or anything else with action-at-a-distance. Every one of them trades + local readability for cleverness. + +### 5.6 Sequencing + +| When | What | Why there | +|---|---|---| +| **Now, before Stage 1** | S9 (doc hygiene) | Cheap; stops further drift immediately. | +| **Stage 0.5** | ~~S3~~ ✅ done · S1, S2, S4, S5, S6, S7 | Must precede the port (§5.1). | +| **After Stage 3** | S8 (EBNF + diagnostic codes) | Valuable, not ordering-critical; better written in Ludic against the self-hosted parser. | + +**S3 was the one genuinely contentious call** — which boolean spelling — because +it is pure taste and touches every file. It was decided in favour of `and`/`or` +and has landed. Everything remaining in this section is a choice between "one +spelling" and "two", where the answer is not in doubt. + +**`!` → `not` has since landed too**, on the same reasoning and by the same +mechanism: `!` still lexes (so `!=` is untouched) purely so the parser can say +`'!' is not a Ludic operator - write 'not'`. Ludic's three boolean operators are +now `and`, `or`, `not`, all reserved words, with no symbol spellings at all. + +--- + +## 5.7 Status — self-hosting achieved + +Updated 2026-08-27. `./test.sh` = 93/93, `./tools/test-tools.sh` = 28/28, +`./selfhost/test.sh` = 5/5 including the bootstrap fixpoint. + +**Ludic is fully self-hosted.** The compiler is written in Ludic +(`selfhost/*.ludic`, ~2,400 lines), compiles every example to byte-identical +output and its own source to a fixpoint, and is built from a checked-in IR seed +with **no C compiler** — the former C compiler has been deleted. Run +`./selfhost/bootstrap-cfree.sh`. + +| Stage | What | State | +|---|---|---| +| **0** | language features (argv, struct, arrays/slices, break/continue, mem_realloc, stderr) | ✅ done | +| **0.5** | S3 (`and`/`or`/`not`), S9 (doc checking), short-circuit `and`/`or` | ✅ done | +| — | S1/S2/S4/S5/S6/S7 (statement terminators, mandatory commas, reserved-word audit, no-op removal, block unification, one formatter) | not done — polish of the *full* language, not needed for self-hosting | +| **1** | support libraries in Ludic (`str`, `buf`, `io`) | ✅ done | +| **2** | the compiler ported to Ludic (`lex`, `parse`, `emit_*`) | ✅ done | +| **3** | the fixpoint (`gen2.ll == gen3.ll`) | ✅ done | +| **4** | retire the C as a *live dependency* (IR seed, C-free rebuild) | ✅ done — `selfhost/bootstrap-cfree.sh` | +| **4+** | retire `ludicc.c` entirely (port the game backend) | ✅ **done** — `compiler/` deleted; the compiler is `selfhost/*.ludic` | + +### What "self-hosting" means here, precisely + +The self-host compiler (`selfhost/`) implements the **compiler-subset**: `struct` +(reference), `[]T` slices with `push`/`len`, functions, a plain `main` entry, +the full control flow, the operators (with short-circuit `and`/`or`), and the +low-level intrinsics. It deliberately does **not** implement the game half of +Ludic — ECS, queries, archetypes, scenes, UI, save/load, `match`/`machine`, +fixed-point. It targets native (macOS/clang) and emits LLVM IR text that clang +assembles, exactly the posture the C `ludicc` has. + +It is written entirely in that subset, which is why it compiles itself. The +three-generation proof (`selfhost/bootstrap.sh`): + +``` +stage0 build/ludicc (C) compiles selfhost.ludic -> gen1 (a Ludic-written compiler) +stage1 gen1 compiles selfhost.ludic -> gen2.ll -> gen2 +stage2 gen2 compiles selfhost.ludic -> gen3.ll +assert gen2.ll == gen3.ll # the compiler reproduces itself, independent of its seed +``` + +`gen1`'s IR legitimately differs (a different compiler built it); `gen2 == gen3` +is the property that matters — the Ludic compiler has no dependency on how it was +built. It is also verified *correct*, not merely self-consistent: it compiles a +corpus (`selfhost/tests/`) of struct, slice, and control-flow programs to +binaries that produce the expected output. + +### Stage 4 — the C is retired as a live dependency + +The self-hosted compiler no longer needs the C `ludicc` to exist. Its own LLVM +IR is checked in as `selfhost/ludicc.seed.ll` — a proven fixed point — and +`selfhost/bootstrap-cfree.sh` assembles that with clang (an IR assembler, the +floor Rust and Swift stand on) and rebuilds the compiler, which reproduces its +own IR. **The C source is never invoked.** This is the seed path §8 recommended. + +Crucially, the compiler **evolves** without the C compiler: `selfhost/reseed.sh` +uses the *current* seed to build a compiler with new source, then takes that +compiler's own output as the new seed. New features (this session: `match`, +bitwise ops, `peek32`/`poke32`) landed and reseeded entirely C-free. The C +compiler is now a historical seed, not a dependency. + +### Stage 4+ — `ludicc.c` is deleted + +The self-host compiler was extended to the **whole** language — components, +archetypes, systems, phases, `for … in query` (with `where`), spawn/despawn, +`self()`, `machine`/`become`, `match`, `save`/`load` snapshots, the retained +`ui` widget tree, multi-file `import`, fixed-point Q16.16, and every runtime +intrinsic. It auto-splices the Ludic runtime exactly as the C compiler did. + +It now compiles **every example** — `snake`, `menu`, and the 6-file JRPG +`chronorift` — to output byte-identical to the original C compiler (checked +against golden renders in `selfhost/golden/`), and still compiles its own source +to a fixpoint. The C compiler (`compiler/`, ~2,700 lines) has been **deleted**. +`build.sh` builds `build/ludicc` from the IR seed with clang and drives the +native link (headless, or windowed via `cocoa.ll`). + +What did not come across: the old C driver's **wasm target, cross-compilation, +and shared-library** paths. Those are driver features, not codegen — the +self-host compiler emits native-ABI IR — and re-implementing them on the +self-hosted toolchain (wasm needs i32 `size_t`; the others are clang flags in +`build.sh`) is the remaining follow-up. + +--- + +## 6. The plan + +### Stage 0 — Extend the C compiler (~500 lines of C) + +The C `ludicc` must be able to compile the Ludic `ludicc`. Land Tier A only, in +this order — cheapest-and-unblocking first: + +1. **A4** `break`/`continue` (~40) — immediate readability win on everything after. +2. **A5** `mem_realloc` (~6). +3. **A1** `os_argc`/`os_arg` (~30) — unblocks the entire notion of a CLI tool. +4. **A6** `file_stderr` (~40). +5. **A2 + A3** `struct` + arrays (~400, landed together). + +Each gets a test in `test.sh` as it lands. The suite is at 64/64; Stage 0 should +leave it green and larger. + +**Explicitly not in Stage 0:** function pointers, 64-bit ints, a `tool` entry +form. They are not on the path to the fixpoint. + +### Stage 0.5 — Syntax freeze (~600 lines of C + a tree-wide `sed`) + +**The grammar must be final before Stage 2 starts** (§5.1): after the fixpoint, +every syntax change costs a four-step reseed instead of an afternoon. + +Land S1–S7 from §5.4: mandatory statement terminators, mandatory separators, +one boolean spelling, reserved keywords, no silent no-ops, two block shapes +instead of seven, one normative formatter. S9 (doc hygiene) can land earlier — +it is cheap and independent. + +Exit criterion: `ludic-fmt --check` passes on the whole tree and there is +exactly one legal spelling of every construct. That is also what makes the +Stage 2b oracle tight. + +### Stage 1 — Support libraries in Ludic (~800 lines of Ludic, zero language work) + +Nothing here needs Stage 0 except `struct`/arrays for pleasantness. This is the +part that is pure writing, and it can start immediately and in parallel. + +| File | Contents | +|---|---| +| `runtime/native/strings.ludic` | `str_eq`, `str_len`, `str_dup`, `str_cat`, `substr`, `str_chr`, `str_hash`, `itoa`, `atoi`, `hex` | +| `runtime/native/buf.ludic` | growable byte buffer — `buf_new`, `buf_putc`, `buf_puts`, `buf_putint`, `buf_len`, `buf_ptr`. This is `SB` from `ludicc.c`, and the IR emitter is nothing but calls to it. | +| `runtime/native/io.ludic` | `read_whole_file` (the open/seek/tell/read/close dance, verified working), `write_whole_file`, stderr diagnostics | +| `runtime/native/map.ludic` | open-addressing `str -> int` hash table: keyword lookup, string interning, symbol tables | +| `runtime/native/arena.ludic` | bump allocator — see §8 | + +### Stage 2 — Port the compiler, each piece against a differential oracle + +Port in dependency order. The critical discipline: **never port a stage without +an automated way to prove it agrees with the C one.** Ludic is unusually well +set up for this, because it already ships two canonical serializers of compiler +internals. + +| Sub-stage | Port | Differential oracle | +|---|---|---| +| 2a | `lex.ludic` | Dump the token stream from both compilers; `diff` over every `.ludic` in the tree. | +| 2b | `parse.ludic` (AST) | **`--fmt` is a free oracle.** The formatter is already a canonical AST printer, and `test.sh` already asserts formatting never changes a program. If both compilers' `--fmt` output is byte-identical on every file, the parsers agree. | +| 2c | `check.ludic` | Diagnostic text must match on a corpus of deliberately-broken programs. `test.sh` already checks diagnostics — extend that corpus. | +| 2d | `emit.ludic` (IR) | **`--emit llvm` must be byte-identical** for every example. This is the strongest oracle available: pass/fail on exact text, no judgement. | +| 2e | `drive.ludic` | Assemble and link via `clang`; compare final binaries. | + +Sub-stage 2b deserves emphasis. Most self-hosting projects have no cheap way to +prove two parsers agree. Ludic has one already built and already tested, which +removes the single largest source of silent divergence. + +### Stage 3 — The fixpoint + +``` +stage1 = C-ludicc compiles ludicc.ludic -> binary A +stage2 = A compiles ludicc.ludic -> binary B +stage3 = B compiles ludicc.ludic -> binary C + +assert B == C byte-for-byte <- THE bootstrap test +``` + +`A != B` is expected and correct: `A` was built by a different compiler, so its +codegen differs. `B == C` is the real property — a compiler that reproduces +itself has no dependency on how it was built. Also assert that `A`, `B` and `C` +all emit identical IR for every example. + +If `B != C`, the cause is almost always nondeterminism in the compiler itself: +hash-table iteration order, an address baked into output, uninitialised memory. +Those are worth hunting rather than working around. + +### Stage 4 — Retire the C + +Once the fixpoint holds, the C compiler becomes a seed. Options: + +| Option | Trade-off | +|---|---| +| **Commit the generated `ludicc.ll`** ✅ recommended | Auditable text, diffable in review, builds with `clang` alone — already a dependency. Large but honest. | +| Commit prebuilt binaries per platform | Smallest process, worst auditability; a binary blob nobody can read. What Rust does. | +| Keep `ludicc.c` forever as the seed | Zero risk, but §1's bar is never met — the C never leaves. What Go did for years. | + +Recommend the IR seed: it is the only option that both removes the C and leaves +a reviewer something to read. + +`tools/ludic-tools/` (3,260 lines of C: `ludic-fmt`, `ludic-lsp`) is a separate +port and should follow, not lead — once the Ludic compiler exists, both tools +should be thin front-ends over its lexer and parser instead of maintaining a +second copy of the vocabulary. + +--- + +## 7. Toolchain independence — and where to stop + +`driver.c` shells out to `clang` (overridable via `$LUDIC_CC`) to assemble IR +into an object and to link, plus `wasm-ld` for wasm. Three levels of removing +that, and only one is worth doing: + +**Level 1 — self-hosted compiler, hosted toolchain. � the goal.** +`ludicc` is Ludic; `clang` remains the IR assembler and linker driver. This is +exactly where Rust and Swift stand. Achieved at the end of Stage 4. + +**Level 2 — own object writer.** Emit Mach-O / ELF / COFF directly, replacing +IR-text + `clang -c`. Requires instruction selection, register allocation and +relocations: realistically 5,000–15,000 lines of Ludic, and it *loses the LLVM +optimizer* — the generated code gets slower, which for a game language is a +real regression, not a neutral trade. **Not recommended.** + +**Level 3 — own linker.** Platform-specific, deep, and buys nothing a user can +perceive. **No.** + +**7.4 — The hand-written IR.** `cocoa.ll` (327 lines) and `wasm.ll` are LLVM IR, +not Ludic. Two defensible positions: keep them as *platform glue written in the +platform's own assembly language* (precisely how Rust uses `asm!` shims and how +every libc has hand-written syscall stubs), or move them into `.ludic` — which +needs **B1 function pointers**, because the `NSView` subclass installs a +function as an Objective-C IMP. Keeping them is the honest default; the README's +existing framing ("the same floor Rust and Swift stand on") already covers it. + +--- + +## 8. Risks and gotchas + +- **Do not build the AST out of ECS entities.** `LUDIC_MAX_ENT` is 1024 + (`native.c:18`) and component storage is fixed arrays. It compiles, it looks + elegant, and it caps the compiler at 1024 nodes. Use `struct` (A2). +- **Do not inherit the C compiler's fixed caps.** `ludicc.c:22` has + `g_srcpath[128]`; `native.c:161` has `Val a[8]`. The Ludic port should grow + its tables (A5) rather than reproduce the limits. +- **Leak on purpose.** A compiler runs once and exits. A bump arena + (`arena.ludic`) that never frees is faster and simpler than tracked + ownership, and it sidesteps having no GC. Free at process exit — i.e. never. +- **Determinism is a feature now.** Anything order-dependent — hash iteration, + pointer values in output, uninitialised reads — breaks `B == C` in Stage 3. + Iterate tables in insertion order, not bucket order. +- **Error handling has no exceptions.** Mirror the C `die()`: write the + diagnostic to stderr (A6), then `os_exit(1)`. +- **The `str + str` mismatch (B2)** is a live example of the front-end accepting + what the backend cannot lower. Worth auditing for siblings before trusting + the typechecker as a Stage 2c oracle. +- **Size-taking intrinsics must use `ll_size_t()` / `ll_widen()`.** `size_t` is + `i32` on wasm32. Any new intrinsic with a size argument (A5) that hardcodes + `i64` will break the wasm target at link time. +- **Recursion depth is fine** — 5,000 frames verified, well past what a + recursive-descent parser needs on real source. + +--- + +## 9. Effort + +| Stage | Work | State | +|---|---|---| +| 0 | Tier A language features (argv, struct, slices, break/continue, mem_realloc, stderr) | ✅ done | +| 0.5 | `and`/`or`/`not` + short-circuit; doc checking (S9) | ✅ done (S1/S2/S4/S5/S6/S7 deferred — full-language polish) | +| 1 | `str`, `buf`, `io` support libraries in Ludic | ✅ done (`selfhost/`) | +| 2 | lexer + parser + AST + IR emitter, in Ludic | ✅ done (`selfhost/`, ~1,300 lines) | +| 3 | the fixpoint (`gen2.ll == gen3.ll`) + harness | ✅ done (`selfhost/bootstrap.sh`) | +| 4 | port the game backend, retire `ludicc.c` | ⛔ out of scope — mechanical continuation | + +The self-host compiler is **~1,300 lines of Ludic** covering the compiler-subset. +A `main`-tool entry point and short-circuit `and`/`or` were the two language +additions that made it self-compilable; the rest of Stage 0 was already in place. + +Roughly **6,000 lines of Ludic and 1,100 lines of C** to reach Level 1 — larger +than the 2,508-line C compiler it replaces, which is normal: the C version leans +on libc for everything in Stage 1. + +**Two independent critical paths, and they can run in parallel.** Stage 0 + Stage 0.5 +are C work on the existing compiler; Stage 1 is Ludic work that needs almost none of +it. The only hard barrier is that Stage 2 starts after *both*. + +**The critical path is short.** A1 (argv, ~30 lines of C) plus A2/A3 +(`struct` + arrays, ~400) plus A4 (`break`, ~40) is nearly all the *design* risk +in the project. Everything after it is typing against oracles that already +exist. + +--- + +## Appendix — probe programs + +Each was compiled with `./build.sh probe.ludic --headless` and run against the +current tree (`./test.sh` = 64/64). + +**Recursion** ✅ → `55` +```ludic +game P { + fn fib(n: int) -> int { if n < 2 { return n } return fib(n-1) + fib(n-2) } + system B phase Start { print_int(fib(10)) quit() } +} +``` + +**String comparison, hand-written** ✅ → `1` +```ludic +fn streq(a: ptr, b: ptr) -> bool { + let i = 0 + while true { + let ca = peek8(a,i) + let cb = peek8(b,i) + if ca != cb { return false } + if ca == 0 { return true } + i = i + 1 + } + return false +} +``` + +**Integer → string, hand-written** ✅ → `48291` +```ludic +fn itoa(v: int, buf: ptr) -> int { + let n = 0 + let x = v + if x == 0 { poke8(buf,0,48) return 1 } + let tmp = mem_alloc(16) + while x > 0 { poke8(tmp, n, 48 + x % 10) x = x / 10 n = n + 1 } + let i = 0 + while i < n { poke8(buf, i, peek8(tmp, n-1-i)) i = i + 1 } + mem_free(tmp) + return n +} +``` + +**Read a whole file** ✅ → the compiler's front door +```ludic +let f = file_open("/tmp/x.txt", "rb") +file_seek(f, 0, 2) +let n = file_tell(f) +file_seek(f, 0, 0) +let b = mem_alloc(n+1) +file_read(f, b, n) +poke8(b, n, 0) +file_close(f) +``` + +### Syntax audit — every one of these compiles today + +Each is a spelling the language accepts; the point is that the *alternative* +spelling is equally legal (§5.3). + +**R1 — three statements on one line, no separators** → `2` +```ludic +game P { system B phase Start { let x = 1 x = x + 1 print_int(x) quit() } } +``` + +**R2 — commas omitted throughout** → `7` +```ludic +# doc-check: skip — composite: declaration plus statements +component Pos { x: int = 0 y: int = 0 } +spawn Hero { Pos = { x = 7 y = 2 } } +``` + +**R3 — RESOLVED.** Every symbol form is now rejected where it is written: +``` +ludicc: error: line 1: '&&' is not a Ludic operator - write 'and' (got '&&') +ludicc: error: line 1: '||' is not a Ludic operator - write 'or' (got '||') +ludicc: error: line 1: '!' is not a Ludic operator - write 'not' (got '!') +ludicc: error: line 1: 'and' is a reserved operator and cannot be used as a name +``` +`--fmt` prints `if ((true and false) or (1 < 2))` and `(not true)`, while unary +minus keeps its tight spelling `(-x)`. `!=` is untouched. + +**R5 — reserved-looking words used as locals** → `11` +```ludic +let query = 5 +let phase = 6 +print_int(query + phase) +``` + +**R6 — contracts accepted and discarded.** Both are violated; it compiles and +prints `4`: +```ludic +# doc-check: skip — composite: declaration plus statements +fn half(n: int) -> int requires n > 100000 ensures false { return n / 2 } +print_int(half(8)) +``` +And a system may declare read-only access, then write — also compiles: +```ludic +system Violate phase Update reads [Pos] query (p) [Pos] { p.x = 99 } +``` + +**R8 — the two formatters disagree about what "format" means.** Given +`component Pos { x: int = 0 y: int = 0 }` and a multi-statement one-liner, +`ludicc --fmt` rewrites both (one statement per line, `and`→`&&`, full +parenthesisation) while `ludic-fmt` returns the input **unchanged**. + +**Verified-missing** — each a compile error today: +```ludic +# doc-check: expect-error — every line here is a compile error by design +while i < 10 { i = i + 1 if i == 3 { break } } # unknown identifier 'break' +struct Node { k: int, a: ptr } # expected declaration (got 'struct') +var t: [int; 8] # expected identifier (got '[') +var h: fn = a # unknown type 'fn' for var h +let p = &cb # fails to compile +print_int(os_argc()) # unknown function 'os_argc' +print_err("x") # unknown function 'print_err' +let p = mem_realloc(ptr_null(), 10) # unknown function 'mem_realloc' +print_str("ab" + "cd") # passes front-end, invalid IR +let a = 100000 print_int(a*100000) # 1410065408 — i32 wrap +``` diff --git a/COMPILING.md b/COMPILING.md new file mode 100644 index 00000000..dd04f713 --- /dev/null +++ b/COMPILING.md @@ -0,0 +1,352 @@ +# Compiling Ludic + +> **Note (2026-08-27):** `ludicc` is now **written in Ludic** (`selfhost/*.ludic`) +> and built from a checked-in IR seed — the C compiler this document describes has +> been deleted. The native pipeline below (Ludic → LLVM IR → object → binary) is +> unchanged. `ludicc` now drives clang itself (via an `os_system` intrinsic), so +> `ludicc app.ludic -o bin/app` and `--emit-llvm` work directly, and a sibling +> command `ludic app.ludic` compiles to a temporary binary and runs it in one +> step. Build both with `./build-cli.sh`. `build.sh` remains as a convenience +> wrapper. `--fmt` is reimplemented as a lex+parse gate (the doc-check hook). +> The `--target`/cross-compile and `--shared` paths are still features of the old +> C driver not yet re-implemented on the self-hosted toolchain. See +> BOOTSTRAP.md §5.7. +> +> ```bash +> ./build-cli.sh # build ./ludicc and ./ludic (from the seed) +> ./ludicc examples/snake.ludic -o bin/snake # compile +> ./ludic examples/snake.ludic # compile + run +> ``` +> +> The binaries are multi-call (one native binary under two names): invoked as +> `ludicc` it compiles, as `ludic` it compiles-and-runs. A `.ludic` file with +> systems is a game and links windowed by default; `--headless` and `--windowed` +> force the mode. The runtime (`runtime/native/cocoa.ll`) is found via +> `$LUDIC_HOME`, defaulting to the directory the binary sits in — keep them at the +> repo root, or set `LUDIC_HOME` and put them on `PATH`. `$LUDIC_CC` overrides the +> assembler/linker (default `clang`). + + +`ludicc` is a compiler, not a translator. It lexes, parses, checks and lowers +Ludic to **LLVM IR itself**, then hands that IR to the system toolchain to be +assembled and linked. There is no C in the middle: no generated `.c` file, no C +runtime compiled alongside your game, and no transpiling step you could inspect +and find your program rewritten in another language. + +``` + app.ludic + │ ludicc — lex, parse, check, lower (compiler/ludicc.c, + ▼ compiler/native.c) + app.ll LLVM IR: your systems, your components, your runtime + │ IR assembler (compiler/driver.c) + ▼ + app.o Mach-O / ELF / COFF object code + │ system linker + ▼ + app or libapp.dylib / .so / .dll +``` + +`clang` appears in that pipeline twice — as the IR assembler and as the linker +driver — which is the same role `rustc` and `swiftc` give it. Set `LUDIC_CC` to +point at a different LLVM toolchain if you have one. + +## Artifacts + +| you want | command | +| --- | --- | +| a windowed native executable | `ludicc game.ludic -o build/game` | +| a headless executable | `ludicc game.ludic --headless -o build/game` | +| the IR, to read | `ludicc src.ludic --emit-llvm -o src.ll` | +| a shared library † | `ludicc lib.ludic --shared -o build/liblib.dylib` | +| a game that runs in a browser † | `ludicc game.ludic --target wasm32-unknown-unknown -o build/web/game.wasm` | +| an object file † | `ludicc src.ludic -c -o src.o` | + +† `--shared`, `--target`/cross-compile, `-c` and the wasm path were features of +the old C driver and are **not yet re-implemented** on the self-hosted toolchain +(see the note at the top). The rows above the line work today via the +self-hosted `ludicc`. + +`build.sh` wraps the common cases: + +```bash +./build.sh examples/snake.ludic # -> build/snake (native) +./build.sh examples/lib/combat.ludic --lib # -> build/libcombat.* (library) +./build.sh examples/snake.ludic --headless # -> build/snake_headless (out.ppm) +./build.sh examples/snake.ludic --web # -> build/web/ (browser) +``` + +## Programs and libraries + +> **Not yet on the self-hosted toolchain.** `--shared` and the `nm`/library +> workflow below describe the old C driver's behavior; the self-hosted `ludicc` +> builds executables only for now. The `module`/`export fn` semantics are +> unchanged — only the packaging step is pending. + +A source file opens with `game Name { … }` or `module Name { … }`. + +* A **game** gets an entry point and the phase-ordered frame loop + (`Start`, then `Input → FixedUpdate → Update → LateUpdate → Render` each tick). +* A **module** gets neither. It is a library, and only its `export fn`s become + public symbols; everything else stays private to the library. + +```ludic +# doc-check: skip — illustrative: elided body +module Combat { + export fn damage(attack: int, armour: int, roll: int) -> int { … } + fn curve(level: int) -> int { … } # private: not a symbol +} +``` + +```bash +ludicc examples/lib/combat.ludic --shared -o build/libcombat.dylib +nm -gU build/libcombat.dylib +# T _damage T _hits_to_kill T _xp_for (no _curve) +``` + +Those are ordinary C-ABI symbols, so anything that can call a shared library can +call Ludic. To call them from another Ludic program, declare them and link: + +```ludic +extern fn damage(attack: int, armour: int, roll: int) -> int = "damage" +``` + +```bash +ludicc examples/lib/arena.ludic -o build/arena -Lbuild -lcombat +``` + +Libraries are linked as `@rpath/…` (`$ORIGIN` on Linux) and executables search +next to themselves, so a built pair keeps working when you move it. + +## Cross-compilation + +> **Not yet on the self-hosted toolchain.** `--target` and `-c` were old +> C-driver flags; the self-hosted `ludicc` builds only for the host today. The +> section below records the intended design — object code for ELF, COFF and +> Mach-O from one source — which the IR pipeline already supports in principle. + +`--target` takes an LLVM triple and retargets the whole pipeline: + +```bash +ludicc game.ludic --target x86_64-unknown-linux-gnu -c -o game-linux.o +ludicc game.ludic --target aarch64-unknown-linux-gnu -c -o game-arm64.o +ludicc game.ludic --target x86_64-pc-windows-msvc -c -o game-win.o +``` + +Object code for ELF, COFF and Mach-O comes out of the same source with no +per-platform branches in the compiler. Linking a foreign target additionally +needs that platform's linker and sysroot, as with any cross toolchain. + +## The runtime is written in Ludic + +`runtime/native/core.ludic` implements the framebuffer, `fill_rect`, the 5×7 +bitmap text, the registers, the RNG, input and the frame dump — in Ludic. ludicc +splices it into every native build, and a builtin call in a game resolves to a +runtime function by name: `clear(c)` calls `rt_clear(c)`. Replace that file and +you have replaced the runtime; pass `--freestanding` to build without it. + +Underneath the runtime there is exactly one layer, and it is not C: a set of +compiler intrinsics that lower to direct calls into the platform ABI. + +| intrinsic | lowers to | +| --- | --- | +| `mem_alloc(n) -> ptr`, `mem_free`, `mem_copy`, `mem_set` | `malloc`, `free`, `memcpy`, `memset` | +| `peek8/peek32(p, i) -> int`, `poke8/poke32(p, i, v)` | `load` / `store` | +| `ptr_add(p, n) -> ptr`, `ptr_null()`, `ptr_is_null(p)` | `getelementptr`, `null` | +| `file_open(path, mode) -> ptr`, `file_read`, `file_write`, `file_close` | `fopen`, `fread`, `fwrite`, `fclose` | +| `read_byte() -> int`, `write_byte(c)`, `print_str(s)`, `print_int(n)` | `getchar`, `putchar`, `printf` | +| `str_len(s) -> int`, `os_exit(code)`, `os_time() -> int` | `strlen`, `exit`, `time` | + +That is the operating system's interface — the floor Rust and Swift stand on +too. Everything above it, including all the graphics, is Ludic. + +The runtime protocol is four optional functions. Define them (or let the +prelude define them) and the entry point calls them: + +| function | when | +| --- | --- | +| `rt_init()` | once, before the `Start` systems | +| `rt_poll() -> int` | once per frame; its result is what `key()` reads | +| `rt_running() -> bool` | each frame; false ends the loop | +| `rt_shutdown()` | after the loop | + +## The window + +`runtime/native/cocoa.ll` is the macOS platform layer, written in LLVM IR. It +talks to the Objective-C runtime through its C ABI — `objc_getClass`, +`sel_registerName`, `objc_msgSend` — and to Quartz through CoreGraphics, which +is what a compiled `.m` file does anyway; this just skips the `.m`. AppKit +paints through `-drawRect:`, so the view class is built at runtime with +`objc_allocateClassPair` and an IR function is installed as its IMP. + +ludicc assembles it exactly like the program's own IR and hands both objects to +the linker, adding `-framework Cocoa`. A `--headless` build omits it entirely, +reads keys from stdin and writes the last frame to `out.ppm`; the `win_*` +intrinsics compile to nothing there, so a headless binary never references a +symbol the window would have provided. + +Other platforms build headless today. A Win32 or X11 port is another `.ll` file +with the same five entry points — `win_open`, `win_poll`, `win_present`, +`win_running`, `win_close` — and no compiler change. + +## The web + +WebAssembly is a target, not a port. The front end, the type checker, the ECS +lowering and the Ludic-written runtime are the same ones a macOS build uses; +only the triple changes. + +``` + game.ludic + │ ludicc — the same lex, parse, check and lower + ▼ + game.ll LLVM IR, triple wasm32-unknown-unknown + │ IR assembler + ▼ + game.o + wasm.o (runtime/web/wasm.ll, the platform layer) + │ wasm-ld + ▼ + game.wasm + index.html + platform.js + assets.json + the assets +``` + +```bash +./build.sh examples/chronorift.ludic --web +python3 -m http.server -d build/web 8000 # then open http://localhost:8000/ +``` + +`build/web/` is self-contained: copy it to any static host — GitHub Pages, S3, +itch.io — and the game runs. It needs no server-side anything, and no +cross-origin isolation headers. + +**No game logic passes through JavaScript.** The systems, the queries, the +fixed-point arithmetic, the PNG decoder, the TrueType rasteriser and the UI are +all compiled Ludic executing as wasm. `platform.js` is 300 lines and implements +the same five-function window protocol `cocoa.ll` implements, plus the host +services wasm has no OS to ask for. It is the web's Cocoa, not an interpreter. + +### The toolchain + +A wasm build needs an LLVM with the WebAssembly backend and `wasm-ld`. Linux +distributions ship both in `clang` and `lld`, so nothing extra is needed there +or in CI. Apple's clang is built without the WebAssembly target, so on macOS: + +```bash +brew install llvm +``` + +ludicc looks in `/opt/homebrew/opt/llvm/bin` and `/usr/local/opt/llvm/bin` +before falling back to `PATH`. `$LUDIC_CC` and `$LUDIC_WASM_LD` override both, +so any LLVM works — a distro one, a downloaded release, `zig cc`, wasi-sdk. + +### Who owns the frame loop + +A native build runs the loop: + +```c +ludic_boot(); while (ludic_alive()) ludic_frame(); ludic_teardown(); +``` + +A browser tab cannot be held inside that loop — it would never paint, and the +key events the loop is waiting on would never be delivered. So a web build +exports those four functions instead of `main`, and `platform.js` calls +`ludic_frame` from `requestAnimationFrame`. Both targets emit the four from the +same code in `ll_emit_loop_parts`, so the systems that run, and the phase order +they run in, are identical; only the owner of the loop differs. + +### The floor + +`wasm32-unknown-unknown` has no libc, so `runtime/web/wasm.ll` *is* the floor — +hand-written LLVM IR, assembled by the same toolchain as everything else: + +| what | how | +| --- | --- | +| `malloc` / `free` | a first-fit free list over linear memory, growing it with `memory.grow` | +| `memcpy` / `memset` | the `memory.copy` / `memory.fill` instructions (`-mbulk-memory`) | +| `strlen` | a byte loop | +| `fopen` / `fread` / `fwrite` / `fclose` / `fseek` / `ftell` | wasm imports, over a preloaded asset image and `localStorage` | +| `getchar` / `putchar` / `print_str` / `time` / `exit` | wasm imports | +| `win_open` / `win_poll` / `win_present` / `win_running` / `win_close` | wasm imports, implemented against a `` | + +Nothing above that file changes for the web: `core.ludic`, `image.ludic`, +`inflate.ludic`, `truetype.ludic` and `ui.ludic` compile to wasm unmodified. + +### Assets and saves + +The browser has no synchronous file access, and `file_open()` is synchronous, so +a web build ships an image of its files instead of a filesystem. ludicc records +every string literal in the program that names a file existing at compile time, +writes the list to `assets.json`, and copies the files into the bundle; +`platform.js` fetches them all before the first frame. `file_open()` then +resolves exactly the paths it resolves natively. + +That is a heuristic, and a deliberately visible one: a path the compiler never +sees written down is a path the browser cannot be told to fetch ahead of time, +and a path outside the project (`/System/Library/Fonts/…`) is refused with a +warning rather than silently dropped. + +Writes go the other way. `file_open(path, "wb")` buffers and commits to +`localStorage` on close, so `save()` / `load()` survive a page reload, and a +read prefers a save the player has made over the shipped asset of the same name. + +### Testing a wasm build + +`--headless --target wasm32-unknown-unknown` produces a bare module with no +page, driven by a runner instead of a browser: + +```bash +node tools/ludic-web/run.mjs build/web/snake_headless.wasm --stdin=ddss +``` + +Because Ludic is fixed-point and its RNG is seeded, the native headless binary +and the wasm one must render byte-identical frames from the same input. `test.sh` +asserts exactly that, which is a much stronger check on the backend than +"it started". + +## What a build contains + +Everything: components and archetypes, spawn/despawn, queries with bindings, +`where` filters and archetype filters, `match`, `machine`/`become`, +`scene`/`layer`/`enter`, module state (`var`), `const`, int and Q16.16 +fixed-point arithmetic, control flow, functions, `extern fn` FFI, strings, the +entity allocator, save/load snapshots, the frame loop, the window, and the whole +graphics stack — framebuffer, PNG decoding, sprites, 9-slice, TrueType text and +the retained UI. + +None of it goes through C. `./test.sh` asserts that directly: no C source +survives in `runtime/`, no C emitter survives in `ludicc`, and the examples all +build, run and render from IR alone. + +## Every flag + +The self-hosted `ludicc`/`ludic` (built with `./build-cli.sh`) accept: + +``` + the program to compile (first non-flag argument) + -o output binary; with --emit-llvm, the IR path. + Parent directories are created. With no -o and not + invoked as `ludic`, the IR is written to stdout. + --windowed force a windowed (Cocoa) build + --headless force a headless build (stdin input, out.ppm output) + --emit-llvm stop at LLVM IR — write it and exit, no clang + --fmt lex + parse only; exit 0 if it parses, 1 on a parse error + (the check-docs gate; canonical formatting not yet restored) + --save-temps keep the intermediate .ll + --run compile then run (implicit when invoked as `ludic`) + (unknown -flags are ignored with a warning, never taken as the input file) + +environment: + LUDIC_CC the LLVM that assembles IR and drives the linker (clang) + LUDIC_HOME where runtime/native/ lives (default: the binary's dir) +``` + +Mode is automatic when neither `--windowed` nor `--headless` is given: a program +with `system`s (a game) links windowed, anything else headless. + +Not yet re-implemented on the self-hosted toolchain (old C-driver flags): +`--shared`, `--emit `, `-c`, `--target`/cross-compile, +`--freestanding`, `-v`, and the explicit link inputs (`-L`/`-l`/`-framework`/ +`-Wl`). Those, plus `LUDIC_WASM_LD`/`LUDIC_RUNTIME_DIR`/`LUDIC_RUNTIME`, describe +the previous driver and are documented here as intended design. + +There is one backend. `ludicc` has no mode that emits C, and no part of a +build compiles or links a C translation unit — including the web one, where the +platform layer is LLVM IR and the loader is 300 lines of JavaScript that never +sees a game rule. diff --git a/LANGUAGE.md b/LANGUAGE.md new file mode 100644 index 00000000..2947d03a --- /dev/null +++ b/LANGUAGE.md @@ -0,0 +1,567 @@ +# The Ludic Language — Reference + +This documents the Ludic language **as actually implemented** by +`compiler/ludicc.c`. Ludic is an AI-first, statically-typed, ahead-of-time +compiled language for games: an ECS is built into the language, and programs +compile straight to machine code. + +``` +program.ludic ──ludicc──▶ program.ll ──▶ program.o ──▶ native exe / shared lib (LLVM IR; no C) +``` + +`ludicc` lowers Ludic to **LLVM IR itself** and links the result — see +[COMPILING.md](COMPILING.md) for the pipeline, `module`/`export`, and +cross-targets. There is one backend: no C is generated, compiled or linked at +any point, and the runtime a game calls is itself written in Ludic. + +## Program structure + +A program is one `game` block containing declarations: + +```ludic +# doc-check: skip — illustrative: elided import list +game Name { + import ... # pull declarations in from another file + component ... # data (per entity) + struct ... # a plain record, not tied to an entity + archetype ... # a named entity KIND (bundle of components) + const ... # compile-time constants + fn ... # functions + extern fn ... # bind a C library symbol (FFI) + system ... # behavior, grouped into phases +} +``` + +## Multi-file programs (`import`) + +```ludic +# doc-check: skip — paths resolve only inside the repo +game ChronoRift { + import "chronorift/world.ludic" # path is relative to THIS file + import "chronorift/combat.ludic" +} +``` + +An imported file is a **fragment**: bare declarations, no `game` wrapper. Its +declarations are spliced into the importing program. Imports may appear inside +the `game` block or before it, they may nest (a fragment may import fragments), +and each resolved path is **include-guarded**, so importing the same file twice +(even via different chains) pulls it in once. Diagnostics report the true file: + +``` +error: line 1: unknown type 'nope' for field Pos.x + chronorift/world.ludic:1 | component Pos { x: nope = 0 } +``` + +## Archetypes (entity kinds) + +An `archetype` names a *kind* of entity and the fixed set of components it +carries. It replaces the empty "tag component" idiom: identity is stored as one +integer per entity, not a parallel boolean array. + +```ludic +# doc-check: skip — composite: declarations and statements together +component Pos { x: int = 0, y: int = 0 } +component Stats { hp: int = 10 } + +archetype Player { Pos, Stats } # Player IS a kind, not a component +archetype Enemy { Pos, Stats } + +spawn Player { Pos = { x = 5 } } # attaches every listed component + # (seeding field defaults), then overrides +for (p, s) in query [Pos, Stats, {Player}] { ... } # {Player} filters by kind +``` + +Use `{Name}` (tag position) to filter a query by archetype — an archetype can't +be *bound* to a variable since it has no fields of its own. Entity kind is part +of the saved snapshot. + +## Text, fonts & images + +The 5×7 bitmap `text` stays for zero-asset programs. For real typography, load a +TrueType font and draw UTF-8: + +```ludic +let f = font_load("/System/Library/Fonts/Supplemental/Arial.ttf") +text_ttf(f, 20, 20, "Héllo — Καλημέ�α — Привет", 0xffffff, 28) # anti-aliased +let w = text_w(f, "measure me", 28) # pixel width +``` + +The runtime ships a from-scratch TrueType engine (sfnt tables, cmap 0/4/6/12, +simple + composite `glyf` outlines, quadratic Béziers, supersampled AA) and a +glyph cache — no external font library. Arbitrary-size PNGs load as images: + +```ludic +let panel = image_load("assets/ui/panel.png") +draw_9slice(panel, x, y, w, h, 10) # stretch edges/center, keep 10px corners +draw_image_scaled(icon, x, y, 32, 32) +``` + +## Retained UI (`ui`) + +UI is declared as **data** — a widget tree. The engine owns layout (stacked +panels with padding / gap / alignment / grow), drawing (9-slice skins, images, +TrueType text, focus highlight) and keyboard focus + activation. + +```ludic +ui MainMenu { + panel id=Root w=288 pad=16 gap=6 skin="assets/ui/panel.png" inset=10 align=center { + label text="CHRONO RIFT" font=reg(R_FONT) size=26 fg=0xffe060 align=center + button id=NewGame text="New Game" font=reg(R_FONT) size=16 w=236 + button id=Quit text="Quit" font=reg(R_FONT) size=16 w=236 + } +} +``` + +Widget types: `panel` (container + optional skin/bg/border), `col` / `row` +(pure stacks), `label`, `button` (focusable), `image`, `spacer`. Props are +evaluated at build time, so `font=reg(R_FONT)` reads a value the game set first. +Each `id=Name` mints a `UI_Name` handle (the `ui` block name too), used from +systems: + +```ludic +system Boot phase Start { + setreg(R_FONT, font_load("…Arial.ttf")) + ui_build() # construct the tree (loads skins/images) + ui_open(UI_MainMenu) # make it active, focus the first button +} +system Nav phase Update { + ui_tick(key()) # w/s move focus, space/enter activate + if ui_clicked(UI_Quit) { quit() } + ui_set_int(UI_HpLabel, hp) # poke dynamic values by id +} +system Draw phase Render { clear(0x0e0e16) ui_render() present() } +``` + +See `examples/menu.ludic` for a complete title screen. + +## Types + +| Type | Meaning | LLVM IR type | +|------|---------|--------------| +| `int` | 32-bit integer | `i32` | +| `fixed` | Q16.16 fixed-point | `i32` | +| `bool` | boolean | `i32` | +| `entity` | entity handle | `i32` | +| `str` | string literal | `ptr` | +| `ptr` | raw address (runtime/FFI) | `ptr` | + +Numeric literals: `42` and `0x1affff` are `int`; a literal with a decimal +point (`1.5`) is `fixed`. Arithmetic on two `fixed` values lowers to +`fxmul`/`fxdiv`; mixing `int` and `fixed` promotes the `int`. Convert with +`fx(i)` (int→fixed) and `flr(f)` (fixed→int). + +## Components, entities, queries + +```ludic +# doc-check: skip — composite: declarations and statements together +component Pos { x: int = 0, y: int = 0 } # typed fields with defaults +component Player { } # a tag (no fields) + +spawn Hero { # create an entity + Pos = { x = 10, y = 5 } + Player = { } +} +despawn self() # remove the current entity + +# iterate every entity that has all listed components: +for (p) in query [Pos, {Player}] { p.x = p.x + 1 } # {Tag} filters, doesn't bind +for (a, b) in query [Pos, Vel] where a.x > 0 { ... } # one var per non-tag term +``` + +Entities are integer handles; component storage and slot reuse are generated per +program. `self()` yields the entity of the innermost `query` loop. + +## Systems & phases + +```ludic +system Move @deterministic + reads [Vel] # declared data access (parsed and reserved; not yet + writes [Pos] # consumed by any analysis pass — see "Not yet implemented") + phase FixedUpdate + query (p, v) [Pos, Vel] # the entities this system operates on +{ p.x = p.x + v.dx } +``` + +Phases run in this order every frame: **`Start`** (once at boot), then each +frame **`Input` → `FixedUpdate` → `Update` → `LateUpdate` → `Render`**. +`edge system` marks a system that touches the outside world. + +### The `query` clause + +A system declares the entities it works on, alongside its phase. The body then +runs **once per matching entity**, with the components bound and `self()` giving +that entity — the query header is simply hoisted out of the body into the +signature: + +```ludic +system CleanBattle phase LateUpdate + query (b, p) [Battle, Pos, {Enemy}] where b.hp <= 0 +{ despawn self() } +``` + +is the same program as + +```ludic +system CleanBattle phase LateUpdate { + for (b, p) in query [Battle, Pos, {Enemy}] where b.hp <= 0 { despawn self() } +} +``` + +Drop `(vars)` when nothing binds: `query [{Enemy}]`. A system declares at most +one query, and the number of variables must equal the number of binding terms +(`{Tag}` terms filter without binding, so they don't count). A system with no +`query` clause runs once per tick, as before. + +### Conditions + +A query selects on more than *which* components an entity has. `where` is an +ordinary expression evaluated with the bindings in scope, so entities can be +matched on their field values: + +```ludic +# doc-check: skip — a bare system clause, not a whole declaration + query (b, s) [Battle, Stats] where b.hp <= 0 and s.level > 3 +``` + +The same `where` works on an inline `for (…) in query […]`. + +`where` is evaluated **per candidate entity**, so it is the wrong place for a +guard that concerns the whole system (`where reg(R_MODE) != 1` would re-read the +register for every entity). Keep whole-system guards in the body of a system +with no `query` clause, wrapping an inline query — as `CleanBattle` does in +`examples/chronorift/combat.ludic`. + +### Matching is lazy, not snapshotted + +Both forms iterate entities by id and re-check the match as they reach each one; +there is no per-tick array of matched entities. Consequences worth knowing: + +* `despawn` of the current entity, or of one already visited, is safe. +* An entity **spawned during the loop at a higher id is visited in the same + tick**. Spawn into a later phase if you don't want that. + +## Structs, arrays and slices + +`struct` is the aggregate that is *not* tied to an entity — a plain record, for +the data a program keeps outside the ECS. + +```ludic +struct Tok { kind: int = 0, line: int = 0, next: Tok } + +system Lex phase Update { + let t = new Tok # allocates; every field seeded from its default + t.kind = 1 +} +``` + +Struct values have **reference semantics**: a struct value is a pointer to the +object, so assigning or passing one shares it rather than copying. + +```ludic +struct Tok { kind: int = 0, line: int = 0, next: Tok } + +fn bump(t: Tok) -> void { t.kind = t.kind + 1 } + +system Share phase Update { + let a = new Tok + let b = a # b and a are the SAME object + b.kind = 9 + print_int(a.kind) # 9 + bump(a) # the mutation is visible to the caller + print_int(a.kind) # 10 +} +``` + +Fields chain, so a struct can refer to its own type and be walked without +temporaries — which is what an AST or a linked list needs: + +```ludic +system Walk phase Update { + let a = new Tok + let b = new Tok + a.next = b + print_int(a.next.kind) + a.next.kind = 42 # chains on the left of an assignment too +} +``` + +Two array forms. `[]T` is the growable slice (below) and is implemented. `[T; N]` +is a **fixed array** — stored inline and zeroed — and is a design target: the +self-hosted compiler's `ptype` parses `[]T` but **not** `[T; N]` yet, so the +snippet below does not compile today. Programs use `[]T` slices for now. + +```ludic +# doc-check: skip — [T; N] fixed arrays are not yet implemented (design target) +var table: [int; 8] # module-level storage +system S phase Update { + let buf: [int; 4] # a local; no initializer needed + buf[0] = 10 + table[2] = buf[0] +} +``` + +`[]T` is a **growable slice** — a pointer to a header holding data, length and +capacity. `push` appends, doubling the storage when it is full; because the +header never moves, an append is visible to everything holding that slice. + +```ludic +system Collect phase Update { + let toks = new []Tok + push(toks, new Tok) + for i in 0 .. len(toks) { print_int(toks[i].kind) } +} +``` + +Indexing works as both a value and an assignment target, and composes with +fields: `toks[i].kind = T_ID` is a single address computation. + +## Functions & FFI + +```ludic +fn heal(amount: int) -> int { return amount * 2 } + +extern fn c_hypot(a: fixed, b: fixed) -> fixed = "hypot_fx" # bind a C symbol +``` +`extern fn … = "symbol"` declares a foreign function and binds it to a symbol +resolved at link time; pass `-L`/`-l` to ludicc to link its library. This is how +Ludic calls anything with a C ABI — including a shared library built from +another `.ludic` file (see `examples/lib/`). + +## Statements + +`let x = expr` · `x = expr` (`+= -= *= /=`) · `if/else` · `when cond { }` +(if-without-else) · `while cond { }` · `for i in a .. b { }` (numeric range) · +`for (…) in query […] { }` · `break` · `continue` · `return` · `spawn` · +`despawn` · `match` · `machine`. + +`break` and `continue` apply to the innermost enclosing loop, and work in all +three loop forms — `while`, the numeric `for`, and the ECS query loop, where +`continue` advances to the next matching entity. Using either outside a loop is +a compile error. + +## Pattern matching & state machines + +`match` replaces `if`-ladders on one value. Arms list one or more literal +patterns (or `_` for the default) and a body: + +```ludic +match tile { + 'T', '#' => return SPR_TREE # multiple patterns per arm + 'D' => return SPR_DOOR + _ => return SPR_GRASS # optional default +} +``` + +`machine` turns a register into an explicit state machine: it dispatches on the +register's value to the matching `state`, and `become` transitions to a named +state (no more `if phase == N` chains). See the co-op battle in +`examples/chronorift/combat.ludic`: + +```ludic +# doc-check: skip — illustrative: elided bodies +machine R_PHASE { + state KnightMenu = 0 { … if is_confirm(k) { …attack… become KnightResolve } } + state KnightResolve = 1 { … become MageMenu } + state EnemyTurn = 4 { … become KnightMenu } +} +``` + +A `machine ` reads `reg()` to pick the state; `become Name` compiles to +`setreg(, )`. Both lower to plain branches (and `match` runs +on the native LLVM backend too). + +## Expressions + +Precedence: `or → and → compar(< <= > >= == !=) → + - → * / % → unary(- not) → +postfix(. () )`. Operators are built-in only (no overloading). The boolean +operators are spelled **`and` / `or` / `not`**; `&&` and `||` are not Ludic operators +and `!` are rejected with a diagnostic naming the fix (`!=` is unaffected). Bitwise operations are +functions (`band`, `bor`, `bxor`, `bnot`, `shl`, `shr`), so the symbols are free +— which is why there is only one spelling to remember. `expr with { field = … }` is not implemented; records appear +only in `spawn`. Char literals (`'w'`) are `int` code points; colors are hex +ints (`0xff8800`). + +## Builtins (the standard library / runtime surface) + +``` +# math min max abs clamp (int) +# rng seed(i) rng_range(lo,hi)->int rng_chance(pct)->bool (deterministic) +# fixed fx(i)->fixed flr(f)->int +# tilemap map_size(w,h) map_row(y,str) tile(x,y)->int +# 2D draw clear(color) fill_rect(x,y,w,h,color) frame_rect(...) put_px(x,y,color) +# draw_sprite(id,x,y) draw_sprite_scaled(id,x,y,scale) present() +# text text(x,y,str,color,scale) text_int(x,y,n,color,scale) (5x7 bitmap) +# fonts font_load(path)->id (TrueType .ttf/.ttc) +# text_ttf(font,x,y,utf8,color,px) text_w(font,utf8,px)->int text_h(font,px)->int +# images image_load(path)->id draw_image(id,x,y) draw_image_scaled(id,x,y,w,h) +# draw_9slice(id,x,y,w,h,inset) +# UI ui_build() ui_open(id) ui_tick(key) ui_render() +# ui_clicked(id)->bool ui_set_text(id,str) ui_set_int(id,n) +# ui_focus(id) ui_focused()->int ui_visible(id,bool) +# assets load_png(path)->id (decodes a PNG; returns a 16x16 sprite id) +# input key()->int (current frame's key code, 0 if none) +# state reg(i)->int setreg(i,v) (64 integer resources shared by systems) +# entity self()->entity +# save save() load()->bool (binary snapshot of the whole ECS World) +# control quit() print_int(i) +# process os_argc()->int os_arg(i)->str (the command line; argv[0] included) +# file_stderr()->ptr (a handle for file_write, off stdout) +``` + +## Tooling + +```bash +ludicc game.ludic -o build/game # native binary (windowed for a game) +ludicc game.ludic --headless -o g # headless build (renders out.ppm; reads stdin) +ludicc game.ludic --emit-llvm -o g.ll # stop at LLVM IR +ludic game.ludic # compile AND run (forwards the exit code) +``` + +`ludicc` (compile) and `ludic` (compile-and-run) are one multi-call binary built +by `./build-cli.sh`. **[COMPILING.md](COMPILING.md) is the authoritative CLI +reference** — the full flag set (`-o`, `--windowed`, `--headless`, `--emit-llvm`, +`--save-temps`, `--run`), the `LUDIC_HOME` / `LUDIC_CC` environment variables, +and the IR-to-stdout bootstrap contract (no `-o`, invoked as `ludicc`) that +`build.sh` / `reseed.sh` rely on. The default mode is auto: a file with `system`s +links windowed, otherwise headless; an explicit flag always wins. + +The retired C driver's `--shared`, `--fmt`, `-c`, cross-compile (`--target`) and +wasm modes are **not** on the self-hosted toolchain (see "Not yet implemented"). +Source formatting now lives in the standalone `build/ludic-fmt` (below), not a +compiler flag. + +The self-hosted compiler is intentionally permissive: it has no separate +validation pass yet, so unknown types lower to `ptr` and call arity is not +checked. Diagnostics are limited to parse-level errors +(`ludicc(self): parse error: …`); richer static checks (unknown identifiers, +duplicate types, unknown fields, arity) are future work. + +### Editors + +```bash +./tools/build-tools.sh # -> build/ludic-fmt, build/ludic-lsp +build/ludic-fmt -w src/ # format in place (keeps comments) +build/ludic-fmt --check . # CI: exit 1 if anything is unformatted +build/ludic-lsp --stdio # the language server, for any editor +``` + +`ludic-fmt` is the source formatter: it works on tokens, so comments and blank +lines survive and no file is ever rewritten into another. `ludic-lsp` speaks +LSP 3.17 and supplies completion, diagnostics, hover, go-to-definition, +find-usages, rename, formatting, outlines, folding and inlay hints — the same +binary for every editor. Both also understand ```` ```ludic ```` fences inside +Markdown, so documentation gets the same highlighting and checking as source. + +Plugins for VS Code and JetBrains IDEs, plus configuration for Neovim, Helix, +Emacs, Sublime and Zed, are in `tools/editors/` — see +[tools/editors/README.md](tools/editors/README.md). + +## Working programs + +- `examples/chronorift.ludic` — a co-op JRPG (overworld, dungeon, boss, shop, + save) using CC0 Kenney sprites. Split across `chronorift/*.ludic` via `import`, + built on archetypes. +- `examples/menu.ludic` — a retained-UI title screen (9-slice panel, TrueType + labels, focusable buttons). +- `examples/snake.ludic` — Snake, no assets — same compiler, proving generality. + +```bash +./build.sh examples/snake.ludic && ./build/snake +``` + +## Not yet implemented + +Units on quantities (`9.8 m/s^2`), `with` record-update expressions, a bytecode +VM + hot-reload, and the live agent bridge — these appear in the design docs but +are future work. + +- **`scene` / `layer` / `on enter` / `on exit`** — the state-machine-over-scenes + sugar is documented above but not parsed by the self-hosted compiler yet. +- **`reads` / `writes` clauses** — parsed and reserved on the system node, but no + analysis pass consumes them. +- **`[T; N]` fixed arrays** — documented above, but `ptype` parses only `[]T` + slices; fixed inline arrays are not accepted yet. Use `[]T` slices. +- **CLI: `--shared`, `--fmt`, and the wasm/cross target** — these were features of + the retired C driver; the self-hosted `ludicc` does not carry them (source + formatting lives in `build/ludic-fmt` instead). Output-path and IR flags are in + flux as the CLI front-end is rebuilt — check `ludicc` usage for the current set. + +`struct` and array types, `break`/`continue`, and argv/stderr — once listed here +as near-term — are now implemented and self-hosting; their lowerings are in +[BOOTSTRAP.md](BOOTSTRAP.md) §4. + +## Scenes & layers + +> ⚠� **Not yet implemented in the current (self-hosted) compiler.** `scene`, +> `layer`, and the `on enter` / `on exit` hooks are a design target: the +> compiler has no `scene` declaration and [`examples/scenes.ludic`](examples/scenes.ludic) +> does not compile today (`enter Name` parses only as a `become` alias). Games +> that need mutually-exclusive states use a mode register (`reg`/`setreg`) with a +> `machine`, as `examples/chronorift` does. This section describes the intended +> syntax for when scene support lands. + +A game is usually several mutually-exclusive states — a title screen, the +overworld, a battle — and the usual way to write that is a mode register +consulted at the top of every system. `scene` makes it structure instead: + +```ludic +# doc-check: skip — illustrative: elided bodies +scene Title start { + on enter { ui_open(UI_Menu) } + on exit { ui_visible(UI_Menu, 0) } + + layer Main { + system Choose phase Update { + if ui_clicked(UI_NewGame) { enter Overworld } + } + } +} + +scene Overworld { + on enter { spawn_party() } + + layer World { system Move phase Update { … } } + layer Hud { system Draw phase Render { … } } +} +``` + +- Exactly **one scene is active**. The one marked `start` runs first (or the + first declared, if none is marked). +- A scene's systems only run while it is active. Systems declared outside any + scene are global and run every frame regardless. +- **Layers group systems and declaration order is draw order**: within a phase, + global systems run first, then the active scene's layers in the order they + were written — so `Hud`'s `Render` paints over `World`'s. +- `on enter` / `on exit` are lifecycle hooks, not phases. Scene setup goes in + `on enter`; a layer system may not use phase `Start`. +- `enter Name` transitions: the current scene's `on exit` runs, the active scene + becomes `Name`, and its `on enter` runs. Inside a layer system the compiler + knows which scene is leaving, so a transition costs two direct calls and a + store — there is no dispatch table. + +`examples/scenes.ludic` is a runnable demonstration of the ordering rules. + +## Queries in a system signature + +When a system's whole body is one query loop, the loop header can move into the +declaration: + +```ludic +system CleanBattle phase LateUpdate + query (b, p) [Battle, Pos, {Foe}] where b.hp <= 0 +{ + despawn self() +} +``` + +This is exactly equivalent to wrapping the body in +`for (b, p) in query [Battle, Pos, {Foe}] where b.hp <= 0 { … }` — same +lowering, same semantics. The body runs once per matching entity and `self()` +is that entity. + +Mutation during iteration follows the same rules as an inline query, because it +is the same loop: entities are visited by ascending id, `despawn` of the current +or an already-visited entity is safe, and an entity **spawned mid-loop at a +higher id is visited in the same tick**. If you need the tick's matches frozen, +collect them yourself. diff --git a/LUANTI-ROADMAP.md b/LUANTI-ROADMAP.md new file mode 100644 index 00000000..6121ad17 --- /dev/null +++ b/LUANTI-ROADMAP.md @@ -0,0 +1,1560 @@ +# Luanti → Ludic: Full Gap Analysis & Implementation Roadmap + +**Question asked:** *what does Ludic miss in order to implement Luanti (formerly +Minetest) — the game/engine?* + +**Short answer:** Ludic can already express Luanti's **game logic**. It cannot yet +express Luanti's **engine**. The gap is not one feature; it is roughly six +layers, and two of them (aggregate data types, and a platform layer with +threads + sockets + a GPU) are load-bearing for everything above them. + +This document is written against evidence, not memory: `luanti-org/luanti` at +`main` was cloned and read, and every claim about Ludic below was verified +against `compiler/ludicc.c` / `compiler/native.c` or by compiling a probe +program with `build/ludicc`. + +--- + +## 0. TL;DR + +| | Luanti | Ludic today | +|---|---|---| +| Size | **362,258** lines (C++ / Lua / GLSL) | 2,508 lines of compiler + 3,692 of runtime | +| World | infinite 3D voxel, ±31,007 nodes/axis | 96×64 char tilemap, 2D | +| Entities | unbounded active objects, chunked | **fixed 1,024** (`LUDIC_MAX_ENT`) | +| Rendering | GPU, 20 shader programs, Irrlicht fork (87k LOC) | 320×240 software framebuffer | +| Extensibility | Lua sandbox, hot-loaded mods, 321 `core.*` calls | AOT compile only | +| Concurrency | emerge threads, mesh threads, net threads, async Lua | **none** | +| Networking | custom reliable UDP, 90 packet types | **none** | +| Numbers | `f32` / `f64`, `v3f`, matrices | `int`, Q16.16 `fixed` (range **±32,768**) | +| Aggregates | vectors, maps, strings, structs | **none** — raw `ptr` + `peek/poke` | + +**The single most surprising finding:** Ludic's `fixed` type **cannot represent a +Luanti world coordinate.** Q16.16 saturates at ±32,768; Luanti's map limit is +±31,007 *nodes*, and positions are carried in *BS units* where `BS = 10.0` +(`src/constants.h`) — i.e. ±310,070. Worse, any squared distance +(`31007² ≈ 9.6e8`) overflows Q16.16 by five orders of magnitude. Every collision, +raycast and physics computation in Luanti would silently wrap. See **G-04**. + +**Recommended order of attack:** language core (arrays/structs/strings) → +platform (threads/sockets/time) → voxel storage primitive → GPU backend → +mod ABI → networking. Milestones **M0–M4** are all reachable without +compromising any of the project's stated constraints (no C, no VM, no +transpile). + +--- + +## 1. Evidence base + +What was read, and how big it is: + +| Area | Files | LOC | Read | +|---|---|---|---| +| `src/` (engine core) | ~700 | 210,370 | headers + all subsystem entry points | +| `irr/` (Irrlicht fork: renderer, GUI, mesh loaders) | — | 87,554 | structure + driver list | +| `src/client/` | 134 | 44,247 | `game.cpp`, `content_mapblock.cpp`, `clientmap.cpp`, mesh threads | +| `src/script/` (Lua bindings) | 147 | 34,240 | full API index, `l_object`, `l_env`, `l_mapgen`, `l_vmanip` | +| `builtin/` (Lua engine layer) | ~60 | 22,634 | file map, `game/`, `common/`, `emerge/` | +| `src/gui/` (formspec, menus) | 61 | 19,198 | `guiFormSpecMenu.cpp` (5,610 LOC alone) | +| `games/devtest` | — | 13,455 | node/item/entity registration patterns | +| `src/mapgen/` | 32 | 11,668 | all 8 mapgens + biome/ore/decoration/cave/dungeon/schematic | +| `src/network/` | 23 | 10,958 | protocol enum (90 packets), reliable-UDP impl | +| `src/util/`, `src/database/`, `src/threading/`, `src/server/` | 102 | 21,961 | serialization, 5 DB backends, thread primitives | +| `doc/lua_api.md` | 1 | 12,785 | **the full mod-facing contract** — the real spec | +| `doc/world_format.md` | 1 | 658 | on-disk map format v22–29 | + +Ludic side, verified by reading source and by compiling probes: + +| Probe | Result | +|---|---| +| recursion (`fib`) | ✅ compiles and links | +| `"ab" + "cd"` | � front-end accepts, **IR fails to assemble** — no string ops | +| `mem_alloc` / `peek32` / `poke32` | ✅ works | +| `fixed` multiply IR | `sext i64 → mul → ashr 16 → trunc i32` — 64-bit intermediate, **i32 result** | +| `sqrt` / `sin` / `cos` / `atan2` | � absent from compiler and runtime entirely | +| runtime component attach/detach | � no such statement — components are fixed at `spawn` | +| entity ceiling | `#define LUDIC_MAX_ENT 1024` (`compiler/native.c:18`) | +| DEFLATE | **decode only** (`runtime/native/inflate.ludic`) — no compressor | + +--- + +## 2. What Luanti actually is + +Nine subsystems. For each: what it does, where it lives, and — the part that +matters here — **what it demands from the language underneath it.** + +### 2.1 The voxel core + +A world is `MapNode`s: a 4-byte struct — `u16 param0` (content id), `u8 param1` +(two 4-bit light banks, day + night), `u8 param2` (rotation / liquid level / +level / colour index). 4,096 of them per `MapBlock` (16³). Blocks live in +sectors; sectors in a `Map`; `ServerMap` and `ClientMap` specialise it. + +```cpp +// src/mapnode.h +struct alignas(u32) MapNode { + u16 param0; // content_t, up to MAX_REGISTERED_CONTENT (~58k) + u8 param1; // day light : 4 | night light : 4 + u8 param2; // facedir / wallmounted / liquid level / degrotate / colour +}; +static constexpr u32 nodecount = 16*16*16; // src/mapblock.h:426 +``` + +**Demands:** a packed struct type; a fixed-size array of them; bitfield +access; cheap 3D→1D indexing; and the ability to allocate *millions* of these +(a modest 10-chunk view radius is ~9,000 blocks = 36M nodes = 147 MB). + +### 2.2 Map storage & persistence + +`map.sqlite` keyed by a 64-bit interleaved block position; each blob is a +serialised `MapBlock` — version byte, flags, 12-bit `lighting_complete` +bitfield, timestamp, a **name↔id mapping** so node ids survive mod changes, +then `param0`/`param1`/`param2` planes, node metadata, node timers, and static +objects. Since format 29 the whole block is **zstd-compressed** (zlib before +that). Five interchangeable backends: SQLite3, LevelDB, Redis, PostgreSQL, flat +files. + +**Demands:** big-endian byte serialisation, a compressor (not just a +decompressor), a string↔id table, and an FFI-usable key/value store. + +### 2.3 Map generation + +Eight mapgens (`v5 v6 v7 flat fractal valleys carpathian singlenode`) over a +shared `Mapgen` base, plus five orthogonal generators layered on top: + +| Generator | File | LOC | What it does | +|---|---|---|---| +| Caves | `cavegen.cpp` | 912 | 3D-noise caverns + tunnel carving | +| Trees | `treegen.cpp` | 888 | L-system + hardcoded species | +| Dungeons | `dungeongen.cpp` | 658 | room/corridor placement | +| Schematics | `mg_schematic.cpp` | 618 | `.mts` blob stamping, force/probability per node | +| Ores | `mg_ore.cpp` | 583 | scatter / sheet / puff / blob / vein / stratum | +| Decorations | `mg_decoration.cpp` | 472 | simple / schematic / lsystem placement | +| Biomes | `mg_biome.cpp` | 332 | heat+humidity noise → biome, per-node depth layers | + +All of it rests on **fractal value noise**: + +```cpp +// src/noise.h +struct NoiseParams { + float offset = 0.0f, scale = 1.0f; + v3f spread = v3f(250,250,250); + s32 seed = 12345; + u16 octaves = 3; + float persist = 0.6f, lacunarity = 2.0f; + u32 flags = NOISE_FLAG_DEFAULTS; +}; +float NoiseFractal3D(const NoiseParams *np, float x, float y, float z, s32 seed); +``` + +**Demands:** floating-point (or ≥Q32.32 fixed), a noise map buffer type, +and — because mapgen runs on `EmergeThread`s — **real threads plus a +thread-local `MMVManip` voxel buffer.** + +### 2.4 Environment & simulation + +`ServerEnvironment` drives the world tick: **ABMs** (Active Block Modifiers — +probabilistic per-node rules that run in loaded blocks), **LBMs** (Loading Block +Modifiers — run once when a block loads), **node timers**, liquid transformation +queues, and object activation/deactivation as players move. + +```lua +core.register_abm({ + label = "Lava cooling", + nodenames = {"default:lava_source"}, + neighbors = {"default:water_source", "default:water_flowing"}, + interval = 10.0, -- seconds + chance = 50, -- 1-in-50 per node per interval + min_y = -32768, max_y = 32767, + catch_up = true, + action = function(pos, node, active_object_count, active_object_count_wider) ... end, +}) +``` + +**This is the one Luanti concept that maps *beautifully* onto Ludic.** An ABM is +literally a system with a query, a `where` clause and a probability. See G-16 — +this is where Ludic could be *better* than Luanti, not merely equal. + +### 2.5 Objects, entities, players + +`ActiveObject` → `ServerActiveObject` → `LuaEntitySAO` / `PlayerSAO`; mirrored +client-side by `ClientActiveObject` → `GenericCAO` (`content_cao.cpp`, 2,002 +LOC). ~30 shared `ObjectProperties` (visual, mesh, textures, `collisionbox`, +`selectionbox`, `physical`, `stepheight`, `nametag`, …). `ObjectRef` alone +exposes **123 documented methods** in `lua_api.md`. + +Collision is swept-AABB against nodes and other objects +(`collisionMoveSimple`), with `stepheight`, and a separate `Raycast` iterator +and an A* `pathfinder.cpp` (1,419 LOC). + +**Demands:** float vectors, AABB math, `sqrt`, and dynamic per-entity component +sets (an entity gains/loses attachments, nametags, physics at runtime). + +### 2.6 Items, inventory, crafting + +`ItemDefManager`, `ItemStack` (name + count + wear + metadata), `InvRef` lists, +`craftdef.cpp` (1,250 LOC) with shaped / shapeless / toolrepair / cooking / +fuel recipe types, and **groups** — the string→int tag system that everything +(digging times, damage, biome placement) keys off: + +```lua +groups = {cracky = 3, level = 2, not_in_creative_inventory = 1} +tool_capabilities = { + full_punch_interval = 1.0, max_drop_level = 1, + groupcaps = { cracky = {times = {[1]=2.0, [2]=1.0, [3]=0.5}, uses = 20, maxlevel = 2} }, + damage_groups = {fleshy = 2}, +} +``` + +**Demands:** string-keyed maps, dynamic arrays, and a runtime registry. + +### 2.7 Client rendering + +The heaviest subsystem. `content_mapblock.cpp` (1,870 LOC) turns a MapBlock +into a mesh, one branch per **drawtype** — there are 19: + +``` +NORMAL AIRLIKE LIQUID FLOWINGLIQUID GLASSLIKE ALLFACES ALLFACES_OPTIONAL +TORCHLIKE SIGNLIKE PLANTLIKE FENCELIKE RAILLIKE NODEBOX GLASSLIKE_FRAMED +FIRELIKE GLASSLIKE_FRAMED_OPTIONAL MESH PLANTLIKE_ROOTED +``` + +Around it: `mapblock_mesh.cpp` + `mesh_generator_thread.cpp` (background +meshing), `clientmap.cpp` (frustum culling, transparency sorting), +`shader.cpp`, 20 GLSL shader programs (`client/shaders/`) covering nodes, +objects, bloom down/upsample, FXAA, volumetric light, shadow mapping, +exposure adaptation, sky, clouds, minimap, and `imagesource.cpp` (1,915 LOC) +implementing the **texture modifier mini-language** (`default_dirt.png^grass.png^[opacity:160`). + +**Demands:** a GPU. Vertex/index buffers, texture atlases + mipmaps, a shader +pipeline, matrices, frustum math. None of this exists in Ludic, whose renderer +is a `320×240` `i32` framebuffer blitted through Core Graphics. + +### 2.8 GUI: formspec, HUD, chat + +`guiFormSpecMenu.cpp` is the single largest file in the engine at **5,610 LOC**. +It parses a string DSL with **64 element types** (`list`, `field`, `dropdown`, +`scroll_container`, `hypertext`, `model`, `tabheader`, `style`, `table`, …): + +```lua +core.show_formspec(name, "mymod:chest", table.concat({ + "formspec_version[7]", "size[8,9]", + "list[context;main;0.375,0.75;8,4;]", + "list[current_player;main;0.375,5.5;8,4;]", + "listring[context;main]", +})) +``` + +Plus a HUD element system (`hud_element.h`), a chat console, and a markup +`hypertext` renderer (`guiHyperText.cpp`, 1,254 LOC). + +**Ludic's `ui` block is genuinely the right shape for this** — retained widget +tree as data — but covers ~8 widget types against 64, has no scrolling, no +tables, no text input, and no inventory-slot widget. + +### 2.9 Networking + +Custom reliable-UDP over a channel abstraction (`src/network/mtp/impl.cpp`, +1,685 LOC + `threads.cpp`, 1,429 LOC): split packets, reliable/unreliable +delivery, ack windows, peer timeout. **90 packet types** +(`ToClientCommand` / `ToServerCommand`), protocol version floor 37. Server +sends mapblocks by distance priority, streams media by hash, and runs an auth +handshake (SRP). + +**Demands:** UDP sockets, threads, timers, checksums, and compression. + +### 2.10 Audio + +OpenAL + Ogg Vorbis (`src/client/sound/`, 11 files): 3D positional sound, +fading, looping, per-object attachment, a proxy manager so the audio thread +never blocks the main loop. + +**Ludic has no audio of any kind.** Not a builtin, not a runtime primitive. + +### 2.11 Scripting — the actual design centre + +This is the part that is easy to under-weight. **Luanti is not a game; it is a +Lua host.** `games/devtest` and Minetest Game are *mods*. The C++ engine's +purpose is to expose: + +- **321** `core.*` functions +- **31** `core.register_on_*` global callbacks +- **19** documented classes (`ObjectRef`, `ItemStack`, `InvRef`, `VoxelManip`, + `NodeMetaRef`, `PcgRandom`, `ValueNoiseMap`, `AreaStore`, `Settings`, …) +- **24** definition-table schemas (node, item, entity, ABM, LBM, biome, ore, + decoration, particle, HUD, craft, …) +- a security sandbox (`s_security.cpp`, 1,253 LOC) that whitelists the Lua + stdlib and confines file access to the mod's own directory +- an async job environment, a mapgen-thread environment, and **SSCSM** + (server-sent client-side mods) + +Mods are hot-loaded at runtime from directories, in dependency order, and can +be added by a server operator without recompiling anything. + +**This is the deepest architectural gap**, and it collides head-on with a stated +project constraint (compiled/native only; no VM, no interpreter). Resolved in +**G-25** — the answer is a compiled mod ABI, not a scripting language. + +### 2.12 Support layers + +Threads + mutex + semaphore + event (`src/threading/`), `SettingsManager`, +gettext i18n with plural forms and per-server translations, `httpfetch` (cURL), +JSON, SRP auth, `Profiler`, `AreaStore` (spatial index), zlib **and** zstd, +GMP for bignum crypto. + +External dependencies Luanti links: `SQLite3 Lua CURL Freetype GettextLib +OpenAL Vorbis OpenSSL PostgreSQL ZLIB Zstd GMP Json Threads Ncursesw`. + +--- + +## 3. Ludic today — verified capability inventory + +Everything below was confirmed against the compiler source, not the docs. + +**Types:** `int` (i32), `fixed` (Q16.16 in i32), `bool` (i32), `entity` (i32), +`str` (`ptr` to literal), `ptr` (opaque), `void`. That is the complete list +(`compiler/ludicc.c:516`). + +**Declarations:** `game`, `module`/`export`, `import`, `component`, `archetype`, +`const`, `var` (module-level globals — yes, these exist), `fn`, `extern fn`, +`system`, `scene`/`layer`, `ui`. + +**Statements:** `let`, assignment (`= += -= *= /=`), `if`/`else`, `when`, +`while`, `for i in a..b`, `for (…) in query […] where …`, `return`, `spawn`, +`despawn`, `match`, `machine`/`become`, `enter`. + +**ECS:** dense per-component arrays sized `LUDIC_MAX_ENT = 1024`, a parallel +`@H_` byte per entity for "has", `@L_kind` for archetype, `@L_alive`, a +free list. Queries are **linear scans over all 1,024 slots** re-checking the +mask each visit. + +**Intrinsics** (the floor, lowering to libc/OS symbols): +`mem_alloc mem_free mem_copy mem_set peek8 poke8 peek32 poke32 ptr_add ptr_null +ptr_is_null file_open file_read file_write file_seek file_tell file_close +read_byte write_byte print_str str_len os_exit os_time shl shr band bor bxor +bnot peekp pokep peekf pokef as_fixed as_int is_windowed game_title win_open +win_poll win_present win_running win_close` + +**Runtime (written in Ludic):** framebuffer + 2D draw, 5×7 bitmap text, a +from-scratch TrueType engine (Q16.16 béziers, AA), PNG decode incl. DEFLATE +*inflate*, sprites + 9-slice, tilemap, xorshift RNG, 64 int registers, retained +UI (panel/col/row/label/button/image/spacer), whole-world save/load snapshot. + +**Confirmed absent:** arrays · structs as values · strings (any operation) · +floats · integers wider or narrower than 32 bits · unsigned · enums · unions · +generics · closures · function pointers · maps/dicts · slices · bounds checks · +error handling · `sqrt`/trig · vectors/matrices · threads · atomics · sockets · +audio · GPU · dynamic loading · runtime component attach/detach · a compressor · +any entity count above 1,024. + +--- + +## 4. Gap register — summary + +Tiers are dependency-ordered: nothing in tier *n* is buildable before tier *n−1*. + +| # | Gap | Tier | Blocks | Effort | +|---|---|---|---|---| +| G-01 | Array & slice types | 0 core | everything | L | +| G-02 | Struct / record value types | 0 core | MapNode, vectors, defs | L | +| G-03 | Strings (owned, UTF-8, ops) | 0 core | names, metadata, formspec | L | +| G-04 | Wide numerics: `f32`/`f64` or Q32.32 | 0 core | **world coordinates** | M | +| G-05 | Sized & unsigned ints (`u8 u16 i64`) | 0 core | node packing, serialization | M | +| G-06 | Enums & tagged unions | 0 core | drawtypes, packets | M | +| G-07 | Math library (`sqrt`, trig, `atan2`) | 0 core | physics, noise, camera | S | +| G-08 | Allocator/arena discipline + bounds checks | 0 core | 147 MB of voxels | M | +| G-09 | Error handling (`result`/`try`) | 0 core | I/O, net, parsing | M | +| G-10 | Generics or monomorphised containers | 0 core | every collection | L | +| G-11 | Hash maps | 0 core | registries, name↔id | M | +| G-12 | Entity count beyond 1,024; chunked ECS storage | 1 ecs | any real world | L | +| G-13 | Runtime component attach/detach | 1 ecs | entity properties | S | +| G-14 | Multiple worlds / ECS instances | 1 ecs | client+server in one binary | M | +| G-15 | Query indices (no linear scan) | 1 ecs | performance | M | +| G-16 | Spatial/probabilistic systems (ABM-shaped) | 1 ecs | world simulation | M | +| G-17 | Threads, mutexes, atomics, channels | 2 plat | mapgen, meshing, net | L | +| G-18 | Sockets (UDP + TCP) | 2 plat | multiplayer | M | +| G-19 | Monotonic + wall clock, sleep, timers | 2 plat | fixed timestep | S | +| G-20 | Dynamic library loading at runtime | 2 plat | mods | S | +| G-21 | Compression (deflate **encode**, zstd) | 2 plat | map storage, net | M | +| G-22 | Voxel chunk primitive + VoxelManip | 3 voxel | the game itself | L | +| G-23 | Lighting propagation & mesh generation | 3 voxel | rendering | L | +| G-24 | Collision, raycast, AABB, pathfinding | 3 voxel | movement | M | +| G-25 | **Mod/extension model (compiled ABI)** | 4 ext | Luanti's whole point | XL | +| G-26 | Data-driven registries & definition tables | 4 ext | node/item defs | M | +| G-27 | Metadata stores (node/item/player) | 4 ext | chests, signs | M | +| G-28 | GPU backend: 3D pipeline, shaders | 5 gfx | 3D at all | XL | +| G-29 | 3D math types (vec/mat/quat/aabb) | 5 gfx | everything 3D | M | +| G-30 | UI: 64 formspec elements, scroll, input, tables | 5 gfx | inventories | L | +| G-31 | Audio: mixing, Ogg decode, 3D positional | 6 av | polish | L | +| G-32 | i18n: gettext, plurals, server translations | 6 av | shipping | M | +| G-33 | Persistence: versioned block format, SQLite FFI | 7 net | saving | M | +| G-34 | Network protocol: reliable UDP, 90 packets | 7 net | multiplayer | XL | + +`S ≈ days · M ≈ 1–3 weeks · L ≈ 1–2 months · XL ≈ a quarter+` (single developer.) + +--- + +## 5. The gaps in detail + +Each entry: what Luanti needs · what Ludic has · proposed Ludic feature · the +compiler/runtime work it implies. + +### Tier 0 — Language core + +#### G-01 · Array & slice types + +**Luanti needs.** `MapNode data[4096]` per block; `std::vector` per +nodebox; noise buffers of `w*h*d` floats; the 6 tiledefs per node. + +**Ludic has.** Nothing. `runtime/native/core.ludic` fakes arrays with +`mem_alloc` + `peek32`/`poke32` and manual stride arithmetic: + +```ludic +rt_fb = mem_alloc(320 * 240 * 4) +poke32(rt_fb, (y * rt_fbw + x) * 4, color) # every access, by hand +``` + +That is workable for a 3,700-line runtime and fatal for a 100,000-line engine: +no bounds checks, no element type, no length. + +**Proposed.** + +```ludic +# fixed-size, stack or inline in a struct — length is part of the type +let box: [16]int + +# heap-allocated, length carried, bounds-checked in debug builds +let nodes: [] MapNode = alloc [4096] MapNode +nodes[i].param0 = C_STONE +print_int(nodes.len) + +# slices: a (ptr, len) pair, no ownership — the workhorse for I/O +fn checksum(bytes: []u8) -> int { + var sum = 0 + for b in bytes { sum = sum + b } # `for x in slice` iteration + return sum +} +let window = nodes[0 .. 256] # slicing, no copy +``` + +**Work.** Lexer: `[`/`]` in type position. Types: a new `TARR{elem, len}` and +`TSLICE{elem}`. Codegen: LLVM `[N x T]` and `{ptr, i64}`; `getelementptr` for +indexing; a `panic_bounds` intrinsic. Semantics decision: slices are non-owning, +`alloc` returns an owning array that `free` releases. **This is the single +highest-leverage item in the document** — G-02, G-03, G-05, G-11, G-22 all +depend on it. + +#### G-02 · Struct / record value types + +**Luanti needs.** `MapNode` is a 4-byte value passed by copy 10� times a frame. +`v3s16`, `aabb3f`, `TileDef`, `NoiseParams`, `ObjectProperties`, `CollisionInfo`. + +**Ludic has.** `component`, which is *not* a value type — it is a row in a +global ECS array, addressable only through a query binding. You cannot declare +a local of component type, return one, or nest one. + +**Proposed.** Split "data shape" from "ECS membership": + +```ludic +struct MapNode { + param0: u16 = 0 # content id + param1: u8 = 0 # light: day|night nibbles + param2: u8 = 0 # facedir / level / liquid +} + +struct v3i { x: int = 0, y: int = 0, z: int = 0 } + +fn index(p: v3i) -> int { return (p.z * 16 + p.y) * 16 + p.x } + +fn get(blk: []MapNode, p: v3i) -> MapNode { return blk[index(p)] } + +# a component becomes "a struct that lives in the world" +component Pos = v3i # aliasing form +component Vel { dx: fixed = 0, dy: fixed = 0 } # existing form still valid +``` + +Add `expr with { field = … }` (already flagged "not implemented" in +LANGUAGE.md) so records can be updated functionally: + +```ludic +let lit = n with { param1 = pack_light(15, 15) } +``` + +**Work.** `NSTRUCT` decl, struct types in the type table, LLVM named struct +types, by-value passing/returning (`byval` for large ones), field access on +non-component values, `with` lowering to insertvalue chains. + +#### G-03 · Strings + +**Luanti needs.** Node names (`"default:stone"`), item strings +(`"default:pick_steel 1 250"`), formspec strings built by concatenation, chat, +metadata keys, mod names, translation keys, the texture-modifier DSL. + +**Ludic has.** `str` = a pointer to a literal. Verified: `"ab" + "cd"` passes +the parser and then **fails to assemble**. `str_len` exists as an intrinsic; +nothing else does. + +**Proposed.** + +```ludic +# `str` stays an immutable literal/slice: (ptr, len), UTF-8, no allocation +# `string` is owned and growable +let name: str = "default:stone" +var buf: string = string_new() +buf.push("size[8,9]") +buf.push_fmt("list[context;main;{};{};8,4;]", x, y) +let out: str = buf.view() + +if name.starts_with("default:") { … } +let (modname, item) = name.split_once(':') +let h = name.hash() # for the registry map +for cp in name.codepoints() { … } # UTF-8 aware +``` + +**Work.** Interning table for literals (already partly there for `.str` globals), +a `string` runtime type in `runtime/native/string.ludic`, `+`/`==`/`<` operator +lowering for `str`, formatting (`push_fmt`) which needs varargs or a small +format-node lowering. Note the TrueType engine already decodes UTF-8 — reuse it. + +#### G-04 · Wide numerics — **the coordinate bug** + +**Luanti needs.** `f32` positions in BS units. `MAX_MAP_GENERATION_LIMIT = +31007` nodes; `BS = 10.0f`; so world coordinates reach **±310,070**, and squared +distances reach **~10�**. + +**Ludic has.** Q16.16 in i32. Range **±32,767.99998**. Verified IR: + +```llvm +%t2 = sext i32 %t0 to i64 ; 64-bit intermediate — precision is fine +%t3 = sext i32 %t1 to i64 +%t4 = mul i64 %t2, %t3 +%t5 = ashr i64 %t4, 16 +%t6 = trunc i64 %t5 to i32 ; …but the result truncates back to Q16.16 +``` + +So `fixed` **cannot hold a Luanti world coordinate at all**, and `d = dx*dx + +dy*dy + dz*dz` wraps silently for anything past ~181 nodes from the origin. +Every collision test, raycast, and mob AI decision would be wrong far from +spawn. + +**Proposed — pick one (recommendation: both, in this order):** + +1. **`fixed64` / Q32.32 on i64** — keeps determinism, which is a genuine + advantage for a multiplayer voxel game (bit-identical physics across + platforms; Luanti itself suffers from float drift here). + ```ludic + let px: fixed64 = 310070.5 # ±2.1e9 range, 2�³² precision + ``` +2. **`f32` / `f64`** — required anyway for mapgen noise (`NoiseParams` is all + floats and the noise functions are transcendental), and for GPU interop where + vertex data *must* be IEEE floats. + ```ludic + let h: f32 = noise3d(x, y, z, seed) + ``` + +**Work.** New scalar types in the type table; LLVM `i64` / `float` / `double`; +promotion rules (`int → fixed → fixed64`, `int → f32 → f64`); literal suffixes +(`1.5f`, `1.5d`); `fmul`/`fdiv`/`fcmp` lowering; printf format selection. + +#### G-05 · Sized & unsigned integers + +**Luanti needs.** `MapNode` is `u16 + u8 + u8` — exactly 4 bytes, because 36 +million of them exist. Serialisation is byte-exact and big-endian. `content_t` +is `u16`; light is two 4-bit nibbles. + +**Ludic has.** i32 only. A `MapNode` built from Ludic `int`s would be 12 bytes — +**3× the memory**, 441 MB instead of 147 MB for a 10-block view radius. + +**Proposed.** + +```ludic +struct MapNode { param0: u16, param1: u8, param2: u8 } # exactly 4 bytes + +let light_day: u8 = band(n.param1, 0x0f) +let content: u16 = n.param0 +let key: u64 = block_key(bp) # sqlite position encoding +``` + +Plus explicit conversion (`as u8`, `as int`) and wrap/saturate semantics stated +in the spec. + +**Work.** Type table entries for `u8 u16 u32 u64 i8 i16 i64`; LLVM `zext`/`sext` +/`trunc` at boundaries; struct layout + alignment rules; unsigned comparison and +shift (`lshr` vs `ashr` — the existing `shr` intrinsic already lowers to `lshr`, +which is wrong for signed ints, and would become type-directed). + +#### G-06 · Enums & tagged unions + +**Luanti needs.** 19 `NodeDrawType`s, 90 packet types, `LiquidType`, +`ContentParamType`, `CollisionType`, and `pointed_thing` which is a genuine sum +type (`nothing` | `node{under,above}` | `object{ref}`). + +**Ludic has.** `const` ints, and `match` over int literals (which is already +half of what's needed and works well). + +**Proposed.** + +```ludic +enum DrawType { Normal, Airlike, Liquid, FlowingLiquid, Glasslike, Allfaces, + Torchlike, Signlike, Plantlike, Fencelike, Raillike, Nodebox, + GlasslikeFramed, Firelike, Mesh, PlantlikeRooted } + +union Pointed { + Nothing + Node { under: v3i, above: v3i } + Object { ref: entity } +} + +match p { + Pointed.Nothing => return + Pointed.Node(u, a) => place_node(a, item) # destructuring arms + Pointed.Object(e) => punch(e) +} +``` + +`match` already exists and already lowers on the native backend — extending its +arms to enum cases and destructuring patterns is incremental, not new +machinery. + +#### G-07 · Math library + +**Luanti needs.** `sqrt` (every distance), `sin`/`cos` (rotation, sky, camera), +`atan2` (`automatic_face_movement_dir`), `pow`/`exp` (noise persistence, +exposure adaptation), `floor`/`ceil`/`round`. + +**Ludic has.** `min max abs clamp` — integer only. **Verified: no `sqrt` +anywhere in the compiler or the runtime.** + +**Proposed.** A `runtime/native/math.ludic` written in Ludic (consistent with +the project's "runtime is in Ludic" rule) — CORDIC or polynomial approximations +for trig on `fixed`, Newton–Raphson `sqrt`, plus direct `llvm.sqrt.f32` / +`llvm.sin.f32` intrinsic lowering once `f32` lands (G-04). + +```ludic +sqrt(x: fixed) -> fixed sin(a: fixed) -> fixed atan2(y, x) -> fixed +pow(b, e) -> fixed floor(f) -> int lerp(a, b, t) -> fixed +``` + +**Effort: S.** This one is a weekend, and unblocks a surprising amount. + +#### G-08 · Memory discipline + +**Luanti needs.** A 10-block view radius is ~9,000 MapBlocks ≈ **147 MB of node +data alone**, churning constantly as blocks load and unload. + +**Ludic has.** `mem_alloc`/`mem_free` (raw `malloc`/`free`), no ownership +tracking, no bounds checks, no leak detection. `runtime/native/image.ludic` +already leaks decoded PNG buffers by design. + +**Proposed.** Not a borrow checker — that is a different language. An **arena +and a pool**, expressed in Ludic, plus optional bounds checking: + +```ludic +arena frame # reset once per frame, no individual frees +let verts = frame.alloc [4096] Vertex + +pool blocks: MapBlock # fixed-size slab, free-list backed +let b = blocks.take() +blocks.give(b) + +# debug builds: every [] access bounds-checked; --release drops the check +``` + +#### G-09 · Error handling + +**Luanti needs.** Corrupt map blobs, truncated packets, missing textures, +unknown node names, failed DB writes. It uses C++ exceptions +(`src/exceptions.h`) plus sentinel returns. + +**Ludic has.** Nothing. `file_open` returns a `ptr` you must test with +`ptr_is_null`; every failure path is a hand-rolled convention. + +**Proposed.** No unwinding (it would fight the AOT/no-runtime philosophy) — +sum-typed results with sugar, which falls straight out of G-06: + +```ludic +fn read_block(path: str) -> MapBlock ! IoError { + let f = file_open(path, "rb") else return IoError.NotFound + let n = try file_read(f, buf, 4096) # `try` propagates the error arm + return parse(buf[0..n]) +} + +match read_block(p) { + Ok(b) => use(b) + Err(e) => log_warn("block load failed", e) +} +``` + +#### G-10 · Generics (or monomorphised containers) + +Without some form of parametric types, every container is written N times. +Minimum viable: **compile-time monomorphisation over one type parameter**, no +constraints, no inference beyond the call site. + +```ludic +struct Vec[T] { data: []T, len: int, cap: int } + +fn push[T](v: Vec[T], x: T) -> void { + if v.len == v.cap { v.data = realloc(v.data, v.cap * 2) v.cap = v.cap * 2 } + v.data[v.len] = x + v.len = v.len + 1 +} + +var objects: Vec[entity] = vec_new[entity]() +``` + +**Work.** Parse `[T]` in decls and calls; a monomorphisation pass keyed on +(fn, concrete args) before codegen; name mangling. Deliberately *not* traits, +*not* variance, *not* HKT — this is a game language, and Luanti's C++ uses +templates in exactly this restrained way. + +#### G-11 · Hash maps + +**Luanti needs.** name→id for nodes and items (~60k entries), the definition +registries, `NodeMetaRef` string→string stores, groups (`string → int`), mod +storage, translation catalogues. + +**Proposed.** One monomorphised open-addressing map, in Ludic: + +```ludic +var by_name: Map[str, u16] = map_new[str, u16]() +by_name.set("default:stone", 1) +if let id = by_name.get("default:stone") { … } +for (k, v) in by_name { … } +``` + +### Tier 1 — ECS at world scale + +#### G-12 · The 1,024-entity ceiling + +**The number.** `compiler/native.c:18` — `#define LUDIC_MAX_ENT 1024`. Every +component becomes `@S_ = internal global [1024 x %Cmp_]`, plus a +`[1024 x i8]` presence array. Storage is **static, dense, and allocated for +every component whether used or not.** + +**What Luanti needs.** A busy server carries thousands of active objects; a +single 16³ MapBlock holds 4,096 nodes. Nodes must *not* be ECS entities (see +G-22), but mobs, items, players, particles, and node timers all should be. + +**Proposed.** Two changes, independent: + +1. **Configurable + dynamic capacity.** `game Foo { entities 65536 }` for the + static bound, and a growth path: component arrays become heap + `[]Cmp` that double. +2. **Sparse-set storage** (the standard ECS answer): per component a dense + packed array + a sparse index. Iteration cost becomes proportional to the + number of entities *with that component*, not to 1,024. This also kills the + memory waste: a component held by 10 entities stops costing 1,024 slots. + +```ludic +game Voxel { + entities 262144 # ceiling, or `dynamic` for growable + storage sparse # or `dense` for the current behaviour +} +``` + +#### G-13 · Runtime component attach/detach + +**Luanti needs.** An entity gains a nametag, loses physics, gets attached to a +vehicle, picks up an inventory — all at runtime. `ObjectRef:set_properties`, +`set_attach`, `set_armor_groups` are per-object mutations of the *shape* of the +entity. + +**Ludic has.** Components are attached only by `spawn`. There is no statement to +add or remove one afterwards. (Verified: no `attach`/`detach` in the parser.) +The `@H_` presence byte already exists — the storage supports it; the +*language* does not expose it. + +**Proposed.** + +```ludic +attach Nametag { text = "Zombie", color = 0xffffff } to e +detach Physics from e +if has Physics on e { … } +``` + +**Effort: S** — the runtime representation is already there. + +#### G-14 · Multiple ECS worlds + +Luanti runs a `ServerEnvironment` and a `ClientEnvironment` **in the same +process** for singleplayer. Ludic has exactly one implicit global world. + +```ludic +world Server { … } # separate component storage per world +world Client { … } +for (p) in Server.query [Pos] { … } +``` + +Also needed for: mapgen worker threads that build a block in isolation, and for +tests. + +#### G-15 · Query indices + +Today: `for (p) in query [Pos]` scans slots 0..1023 and re-tests the mask. +With G-12's higher ceilings that becomes the hot loop. Sparse sets (G-12) fix +the common case; the remaining need is **multi-component intersection** — pick +the smallest dense set and probe the others. + +#### G-16 · ABM-shaped systems — *where Ludic can beat Luanti* + +Luanti's ABM is a hand-rolled sampler in C++: pick random positions in loaded +blocks, test `nodenames`, test `neighbors`, roll `chance`, call a Lua closure. +It is one of the most-profiled parts of the engine. + +In Ludic this is a **declaration**: + +```ludic +system LavaCooling phase Update + every 10.0s # interval, not a hand-rolled timer + chance 1 in 50 # sampler, compiled in + nodes [C_LAVA_SOURCE] # content filter → an index, not a scan + near [C_WATER_SOURCE, C_WATER_FLOWING] + in y -32768 .. 32767 +{ + set_node(self_pos(), C_OBSIDIAN) +} +``` + +The compiler knows the node set at compile time, so it can build the per-block +content index once and iterate only matching positions — an optimisation Luanti +cannot do because its ABM predicates arrive as runtime strings. **This is the +strongest argument in the whole document for the language existing.** + +### Tier 2 — Platform + +#### G-17 · Threads, mutexes, atomics + +**Luanti needs.** `EmergeThread` × N (mapgen), `MeshUpdateThread` (client +meshing), `ConnectionSendThread` + `ConnectionReceiveThread`, the sound proxy +thread, and an async Lua job environment. `src/threading/` provides +`Thread`, `Mutex`, `Semaphore`, `Event`, `OrderedMutex`. + +**Ludic has.** Nothing. No `pthread_create` binding, no atomics, and — a real +problem — **`var` globals are unsynchronised i32 stores** and the ECS arrays are +process-global. + +**Proposed.** + +```ludic +thread pool emerge count 4 { # a named pool with a typed job queue + job Generate(bp: v3i) -> MapBlock { … } +} +emerge.submit(Generate(bp)) +if let blk = emerge.poll() { install(blk) } + +atomic var block_count: int = 0 +block_count.add(1) + +mutex map_lock +lock map_lock { … } + +channel Chan[MapBlock] results # MPSC, blocking or try_recv +``` + +Design steer: prefer **message passing + job pools** over shared mutable state, +because it composes with the ECS (a job owns its world slice) and because it is +what a determinism-oriented language should encourage. + +#### G-18 · Sockets + +UDP is mandatory (the whole protocol is UDP), TCP + TLS for the content store +and HTTP mods. + +```ludic +let s = udp_bind("0.0.0.0", 30000) +let (n, from) = s.recv(buf) +s.send_to(from, reply) +``` + +Bind at the syscall level from the runtime, as with `file_open` — `socket`, +`bind`, `sendto`, `recvfrom`, `poll`. No new language feature required beyond +G-01 (slices) and G-09 (errors), which is why this is M, not L. + +#### G-19 · Time + +`os_time()` returns whole seconds. A game loop needs a **monotonic** clock at +microsecond resolution, and Luanti's `DTIME_LIMIT = 2.5f` / fixed-timestep +stepping depends on it. + +```ludic +let t = now_us() # monotonic, u64 +sleep_ms(2) +``` + +#### G-20 · Dynamic loading + +`dlopen`/`dlsym` equivalents, so mods (G-25) can be loaded from a directory at +startup without relinking the engine. + +```ludic +let m = module_load("mods/farming/farming.dylib") +let init = m.symbol("mod_init") as fn(ModApi) -> void +``` + +#### G-21 · Compression + +**Luanti needs.** zstd for map format ≥29, zlib below it, and both directions. + +**Ludic has.** `runtime/native/inflate.ludic` — **decoder only** (verified: the +file implements `z_start`, `z_bits`, `z_table_build`, `z_decode`, `z_stored`; +there is no encoder). PNGs load; nothing can be written. + +**Proposed.** Write `deflate.ludic` (fixed-Huffman + LZ77 with a hash chain is +~300 lines and enough for map storage), and FFI to `libzstd` via `extern fn` for +the real thing. Both consistent with existing project practice. + +### Tier 3 — The voxel engine + +#### G-22 · A voxel chunk primitive + +This is the heart. **Nodes must not be ECS entities** — 36 million entities is +absurd, and Ludic's `entity` is an i32 index into parallel arrays. Voxels want +the opposite layout: dense, implicit position, no id. + +**Proposed** — make chunked volumes a first-class construct, the way `component` +is: + +```ludic +volume Map of MapNode chunk 16 { # 16³ chunks of MapNode + origin v3i # chunk coordinate + meta { generated: bool, timestamp: u32, lighting_complete: u16 } +} + +# indexing is bounds-safe and computes chunk + offset in one shot +let n = Map[pos] +Map[pos] = MapNode { param0 = C_STONE } + +# an explicit borrowed working area = Luanti's MMVManip / VoxelManip, +# which is how mapgen and bulk edits avoid touching the live map +manip vm = Map.borrow(pmin, pmax) +for p in vm.area { if vm[p].param0 == C_AIR { vm[p] = stone } } +vm.commit() # write back + relight + remesh +``` + +Mapped to Luanti: `Map` ≈ `ServerMap`, `chunk` ≈ `MapBlock`, `manip` ≈ +`MMVManip`, `vm.area` ≈ `VoxelArea`, and `commit()` ≈ +`blit_back + update_liquids + calc_lighting`. + +**Work.** L. Chunk table (hash map keyed on `v3i` — needs G-11), an allocator +for chunk payloads (G-08), the index arithmetic, and a loaded/unloaded state +machine. But note: this is *exactly* the kind of thing a domain-specific game +language should have, and no general-purpose language offers it. + +#### G-23 · Lighting & meshing + +**Lighting.** Luanti propagates two banks (day/night) via BFS flood fill across +block boundaries (`voxelalgorithms.cpp`, 1,309 LOC), with the 12-bit +`lighting_complete` mask tracking which faces are still provisional. + +**Meshing.** `content_mapblock.cpp` (1,870 LOC) emits geometry per drawtype; +`mapblock_mesh.cpp` builds the buffers; `mesh_generator_thread.cpp` does it off +the main thread. + +**Proposed.** Both stay *library* code written in Ludic — but they need G-01 +(vertex arrays), G-04 (float vertex data for the GPU), G-17 (mesh threads), and +G-28 (somewhere to send the buffers). Language-level help worth adding: + +```ludic +# a declarative face-culling rule set, instead of 19 hand-written branches +drawtype Normal { + cull when neighbor.solid + faces cube tiles [top, bottom, left, right, front, back] +} +drawtype Plantlike { faces cross scale visual_scale cull never } +``` + +#### G-24 · Collision, raycast, AABB + +Swept AABB against the node grid + other objects, with `stepheight`; a voxel +DDA raycast for pointing; A* over the node grid for mob pathing (1,419 LOC). + +All expressible in Ludic **once G-04 (wide numbers) and G-07 (`sqrt`) exist.** +No new language feature needed — this is library work, ~2,000 lines. + +### Tier 4 — Extensibility + +#### G-25 · The mod model — the hard architectural call + +**The problem.** Luanti's entire value proposition is that a server operator +drops a folder into `mods/` and restarts. 321 `core.*` functions exist to serve +that. Ludic is AOT-compiled, and the project constraint is explicit: **no VM, +no interpreter, no scripting language, ever.** + +These are not reconcilable by adding Lua. They *are* reconcilable, and the +answer is already half-built in the repo — `ludicc lib.ludic --shared -o +lib.dylib` and `extern fn … = "symbol"`. + +**Proposed: compiled mods behind a stable C-ABI interface.** + +```ludic +# mods/farming/farming.ludic +mod Farming { + version 1 + depends ["core"] + + on init(api: ModApi) { + api.register_node("farming:wheat_1", NodeDef { + drawtype = DrawType.Plantlike, + tiles = ["farming_wheat_1.png"], + groups = [("snappy", 3), ("flammable", 2)], + walkable = false, + buildable_to = true, + }) + + api.register_abm(Abm { + nodes = ["farming:wheat_1"], + interval = 20.0, chance = 20, + action = grow_wheat, + }) + } +} +``` + +Built with `ludicc mods/farming/farming.ludic --shared -o mods/farming/farming.dylib`, +loaded at startup via G-20, and talking to the engine only through a versioned +`ModApi` vtable. + +**What you gain over Lua:** mods run at native speed (Luanti's ABMs and +`on_generated` handlers are its top profiler entries, and they are all Lua); +mod errors are compile-time; the ECS is available to mods directly. + +**What you lose, and must decide about:** +- **No hot reload** without process restart (mitigable: reload the dylib). +- **No sandbox.** Lua's `s_security.cpp` confines mods to their own directory; + a native dylib can do anything. Options: (a) accept it, like Factorio pre-2.0 + or any C++ plugin system; (b) run mods in a subprocess with an IPC boundary; + (c) restrict the `ModApi` surface and ship signed mods. +- **Distribution.** Mods become per-platform binaries, or ship as source and + compile on first load (`ludicc` is 2,508 lines — shipping it *is* viable). + +**My recommendation:** ship-as-source + compile-on-load. It keeps the "drop a +folder in" workflow, keeps everything in one language, needs no VM, and turns +`ludicc`'s small size into a genuine architectural advantage. + +#### G-26 · Definition tables & registries + +Luanti registers definitions from Lua tables at runtime. Ludic has no table +literal, no runtime registry, and no way to name 60,000 content ids. + +**Proposed** — a declarative `def` construct that is data at compile time *and* +registrable at runtime: + +```ludic +def node Stone { + name = "default:stone" + drawtype = DrawType.Normal + tiles = ["default_stone.png"] + groups = [("cracky", 3)] + is_ground_content = true + sounds = SoundSet.Stone + drop = "default:cobble" +} +``` + +The compiler assigns content ids, emits the table as static data, and the +registry maps `str → u16` at load (G-11). Mod-supplied defs go through the same +path at runtime. + +#### G-27 · Metadata + +`NodeMetaRef` / `ItemStackMetaRef` / `PlayerMetaRef`: string→string stores +attached to positions, stacks, and players, with an "inventory" attached to node +meta. Needs G-03 and G-11; then it is straightforward library code. + +### Tier 5 — Graphics & UI + +#### G-28 · The GPU + +Luanti bundles an **87,554-line Irrlicht fork** to get: OpenGL 3 / GLES2 / +WebGL contexts, vertex + index buffers, texture management with mipmaps and +atlases, a material/shader system, scene graph, frustum culling, and mesh +loaders (B3D, OBJ, glTF). On top of that sit 20 GLSL programs. + +Ludic has a 320×240 software framebuffer presented through +`runtime/native/cocoa.ll` (327 lines of hand-written LLVM IR calling +`objc_msgSend`). + +**This is the largest single gap in the document.** Options: + +| Option | Cost | Fit with constraints | +|---|---|---| +| Software rasteriser in Ludic | L | ✅ perfect — but ~5 fps at 720p for voxels | +| Bind OpenGL/Metal via `extern fn` | M | ✅ same posture as zlib FFI; **recommended** | +| Hand-written IR per platform, like `cocoa.ll` | XL | ✅ but repeated per API | +| Write a GPU driver | ✗ | not serious | + +**Recommended:** treat the GPU exactly as the project already treats the OS — +an ABI to call, not a C program to compile. `extern fn glDrawElements(…) = +"glDrawElements"`, with a thin `runtime/native/gfx3d.ludic` over it. This is +consistent with the existing rule ("C libraries are used via FFI") and needs +**no compiler change beyond G-04's `f32`.** + +#### G-29 · 3D math types + +```ludic +struct v3f { x: f32 = 0, y: f32 = 0, z: f32 = 0 } +struct m4 { m: [16]f32 } +struct aabb { min: v3f, max: v3f } + +fn dot(a: v3f, b: v3f) -> f32 +fn cross(a: v3f, b: v3f) -> v3f +fn normalize(v: v3f) -> v3f +fn look_at(eye: v3f, at: v3f, up: v3f) -> m4 +fn perspective(fovy: f32, aspect: f32, znear: f32, zfar: f32) -> m4 +``` + +Worth considering: **operator overloading for vector types only** — Ludic +currently forbids overloading entirely, and `a + b` on vectors is the one place +where the ban costs real readability. A narrow, built-in-types-only exception is +defensible. + +#### G-30 · UI at formspec scale + +Ludic's `ui` block is architecturally right and 8 widgets deep. Formspec is 64 +elements. The gap that matters most: + +| Missing | Why it blocks Luanti | +|---|---| +| `field` / `textarea` / `pwdfield` | no text input at all — no chat, no sign editing | +| `list` (inventory slots) | the core interaction of the game | +| `scroll_container` / `scrollbar` | any inventory bigger than a screen | +| `table` / `textlist` | server list, mod manager | +| `dropdown`, `checkbox`, `tabheader` | settings | +| `model` | 3D item preview | +| `style[]` / `style_type[]` | theming | +| mouse input | **Ludic's UI is keyboard-only today** (`ui_tick(key())`) | +| `hypertext` markup | formatted text | + +### Tier 6 — Audio & i18n + +#### G-31 · Audio + +Nothing exists. Needed: a mixer, Ogg Vorbis decode (or ship a simpler codec), +3D panning + attenuation, and an audio callback thread (G-17). Consistent with +project practice: decode in Ludic (as PNG and TrueType already are), bind +CoreAudio/ALSA/WASAPI via `extern fn`. + +```ludic +let s = sound_load("assets/dig_stone.ogg") +sound_play(s, SoundSpec { gain = 0.8, pitch = 1.0, pos = p, max_hear = 32.0 }) +``` + +#### G-32 · i18n + +Luanti: gettext, plural forms (`gettext_plural_form.cpp`), per-server +translation files (`.tr`), and escape-sequence-based inline translation. Ludic +has UTF-8 rendering (good) and no translation machinery. Needs G-03 and G-11. + +### Tier 7 — Persistence & network + +#### G-33 · Persistence + +Ludic's `save()`/`load()` writes **the entire ECS world** in one blob. Luanti +needs per-block, versioned, compressed, incrementally-written storage keyed in +SQLite, plus player files, auth, and mod storage. + +```ludic +serialize MapBlock version 29 { + u8 version + u8 flags + u16 lighting_complete + u32 timestamp + map name_id: Map[u16, str] + zstd { # everything inside is compressed + array param0: [4096]u16 bigendian + array param1: [4096]u8 + array param2: [4096]u8 + list metadata + list timers + list static_objects + } +} +``` + +A declarative `serialize` block generating both encoder and decoder would be a +strong Ludic feature — it is exactly the kind of error-prone, symmetric, +version-tagged code that a game language should generate rather than hand-write. + +#### G-34 · Networking + +90 packet types, reliable UDP with split packets and ack windows, and priority +block streaming. Depends on G-17, G-18, G-21, G-33. The packet definitions +themselves fall out of `serialize` (G-33) + `union` (G-06): + +```ludic +packet ToClient { + BlockData = 0x20 { pos: v3i, block: MapBlock } + AddParticle = 0x46 { … } + ActiveObjectMessages = 0x31 { msgs: []ObjectMsg } +} +``` + +--- + +## 6. Roadmap + +Ten milestones. Each one **ends in something runnable** — that is the rule; no +milestone is "add a type system feature" with nothing to show. Effort estimates +assume one developer and are deliberately conservative. + +### M0 — Language core, part 1: aggregates *(≈6 weeks)* +> **Gates:** G-01 arrays/slices · G-02 structs · G-05 sized ints + +**Demo:** rewrite `runtime/native/image.ludic`'s PNG decoder to use +`[]u8` and `struct Pixel` instead of `mem_alloc` + `peek8`. Same output PNG, +half the lines, bounds-checked. + +**Why first:** every other item in this document is blocked on it. The existing +runtime is the perfect proving ground — it is 3,700 lines of exactly the +hand-rolled pointer arithmetic these features exist to delete. + +```ludic +# before (runtime/native/image.ludic today) +fn px(img: ptr, x: int, y: int, w: int) -> int { return peek32(img, (y*w+x)*4) } + +# after +struct Rgba { r: u8, g: u8, b: u8, a: u8 } +fn px(img: []Rgba, x: int, y: int, w: int) -> Rgba { return img[y*w + x] } +``` + +### M1 — Language core, part 2: numbers, strings, errors *(≈6 weeks)* +> **Gates:** G-03 strings · G-04 `f32`/`fixed64` · G-06 enums/unions · G-07 math · G-09 errors + +**Demo:** a `noise.ludic` implementing Luanti's `NoiseFractal3D` exactly, and a +headless program that renders a 512×512 heightmap PNG from it. Compare against +Luanti's own output for the same seed — **bit-comparable terrain is the +acceptance test.** + +This is the milestone that closes the coordinate bug (G-04). Worth writing the +regression test first: + +```ludic +system CoordRange phase Start { + let far: fixed64 = 310070.0 # would wrap in Q16.16 + assert(flr64(far) == 310070) + let d = far * far # 9.6e10 — must not wrap +} +``` + +### M2 — Platform *(≈5 weeks)* +> **Gates:** G-17 threads · G-19 time · G-18 sockets · G-20 dynamic loading · G-21 deflate encode + +**Demo:** a headless Ludic program that spawns 4 worker threads, each generating +a 16³ noise chunk, deflate-compresses it, writes it to a file, and a second +process that reads it back — proving the thread pool, the compressor and the +round-trip. + +**Note on the new WASM target.** A peer session just landed WebAssembly support +(`runtime/web/`, `test.sh` now 64/64), and `@main` is now split into +`ludic_boot/frame/alive/teardown` so a browser can drive the loop from +`requestAnimationFrame`. Two consequences for this roadmap: (a) threads on +wasm32 mean Web Workers + SharedArrayBuffer, not pthreads, so **G-17 needs a +per-target backend from day one**; (b) `size_t` is `i32` on wasm — new +intrinsics must go through `ll_size_t()`/`ll_widen()`/`ll_narrow()`, which +matters for every slice and array intrinsic added in M0. + +### M3 — The voxel primitive *(≈8 weeks)* +> **Gates:** G-11 maps · G-12 ECS scale · G-13 attach/detach · G-22 `volume`/`manip` + +**Demo:** **a flat 3D world you can fly through**, still software-rendered at +320×240 — a chunked `volume Map of MapNode chunk 16`, chunks generated on the +worker pool from M2, a free camera, and a simple raycast rasteriser for +visualisation. Ugly, slow, and unambiguously a voxel engine. + +```ludic +volume Map of MapNode chunk 16 { origin v3i meta { generated: bool } } + +system Generate phase Update { + for bp in pending_chunks() { + manip vm = Map.borrow_chunk(bp) + for p in vm.area { + let h = flr(noise2d(fx(p.x) / 64.0, fx(p.z) / 64.0) * 24.0) + 8 + vm[p] = if p.y <= h { NODE_STONE } else { NODE_AIR } + } + vm.commit() + } +} +``` + +### M4 — GPU + 3D *(≈10 weeks)* +> **Gates:** G-28 GPU FFI · G-29 3D math · G-23 meshing/lighting + +**Demo:** the M3 world, **textured, lit and running at 60 fps** — greedy or +per-face meshing on a worker thread, day/night light banks propagated by BFS, +one shader program, a texture atlas from the existing PNG decoder. + +This is where the project stops being a 2D game language and becomes capable of +Luanti's genre. It is also the milestone with the most schedule risk — bind +OpenGL 3.3 via `extern fn` first (Metal/WebGL later) and resist the temptation +to write a scene graph. + +### M5 — Interaction *(≈6 weeks)* +> **Gates:** G-24 collision/raycast · G-30 UI (input, lists, scroll) · mouse input + +**Demo:** **you can walk, jump, dig and place.** Swept-AABB player physics with +`stepheight`, a DDA raycast for pointing, a hotbar, and an inventory screen with +draggable slots. This is the first milestone that is *playable*. + +### M6 — Definitions & registries *(≈5 weeks)* +> **Gates:** G-26 `def` blocks · G-27 metadata · G-16 ABM systems + +**Demo:** 30 node types and 10 item types declared with `def node` / `def item`, +groups-based dig times, a chest with node metadata and an inventory, and lava +that cools into obsidian via an ABM-shaped system. **This is the milestone where +the language's ECS finally pays off visibly.** + +### M7 — Persistence *(≈4 weeks)* +> **Gates:** G-33 `serialize` blocks · SQLite via FFI + +**Demo:** quit and relaunch; the world, your inventory and your position are +exactly as you left them. Blocks written incrementally, zstd-compressed, keyed +by interleaved position — read Luanti's own `map.sqlite` as a compatibility +stretch goal. + +### M8 — The mod ABI *(≈8 weeks)* +> **Gates:** G-25 mod model · G-20 loading · a versioned `ModApi` + +**Demo:** a `mods/farming/` folder containing only `.ludic` source and textures; +drop it in, restart, and wheat exists — compiled on first load, cached as a +dylib. Then delete the folder and it is gone. **This is the milestone that makes +it Luanti rather than a voxel game.** + +### M9 — Multiplayer *(≈12 weeks)* +> **Gates:** G-34 protocol · G-14 multiple worlds · G-18 sockets + +**Demo:** two clients, one server, on separate machines: block changes, +movement, chat, and inventory sync. Client and server in one binary via +`world Server` / `world Client` (G-14) so singleplayer is just a loopback. + +### Audio & i18n *(fold into M5–M8 opportunistically)* +> **Gates:** G-31 · G-32 + +### Timeline summary + +| Milestone | Effort | Cumulative | Ends with | +|---|---|---|---| +| M0 aggregates | 6 wk | 6 wk | runtime rewritten on arrays/structs | +| M1 numbers/strings | 6 wk | 12 wk | Luanti-comparable noise terrain | +| M2 platform | 5 wk | 17 wk | threaded, compressed chunk I/O | +| M3 voxel primitive | 8 wk | 25 wk | flyable 3D voxel world | +| M4 GPU | 10 wk | 35 wk | textured, lit, 60 fps | +| M5 interaction | 6 wk | 41 wk | **playable: walk, dig, place** | +| M6 definitions | 5 wk | 46 wk | modded content, ABMs | +| M7 persistence | 4 wk | 50 wk | worlds that survive restart | +| M8 mod ABI | 8 wk | 58 wk | **drop-in mods** | +| M9 multiplayer | 12 wk | 70 wk | two clients, one server | + +≈**70 developer-weeks** to a Luanti-class engine written in Ludic. For scale: +Luanti itself is 362,258 lines accumulated since 2010. + +--- + +## 7. Decisions I need from you + +These change the shape of the work and are yours to make, not mine. My +recommendation is given first in each case. + +1. **Numerics: `fixed64` *and* `f32`, or just `f32`?** + *Recommendation: both.* `fixed64` for gameplay/physics (deterministic + lockstep multiplayer is a real advantage, and Luanti's float physics is a + known source of desync); `f32` for noise and GPU vertex data, where it is + non-negotiable. + +2. **Mod distribution: source-and-compile-on-load, or prebuilt binaries?** + *Recommendation: source.* `ludicc` is 2,508 lines — shipping the compiler + with the game preserves the "drop a folder in" workflow that is Luanti's + entire ecosystem, keeps one language end-to-end, and needs no VM. + +3. **Mod sandboxing: accept native trust, or subprocess isolation?** + *Recommendation: accept it for M8, revisit before any public server.* + Luanti's `s_security.cpp` is 1,253 lines of Lua-specific confinement that has + no native analogue; subprocess + IPC is the only real answer and it is a + quarter of work on its own. + +4. **GPU: FFI to OpenGL, or hand-written IR per platform like `cocoa.ll`?** + *Recommendation: FFI.* It matches the project's existing posture toward + libraries, and `cocoa.ll` is 327 lines for *five* window functions — OpenGL + has hundreds of entry points. + +5. **Compatibility: read Luanti's `map.sqlite` and speak protocol 37+, or a + clean-room format?** *Recommendation: clean room, with a one-way importer.* + Wire compatibility means implementing 90 packet types before anything is + playable; it inverts the whole milestone order. + +6. **Scope: the full engine, or a Luanti-shaped game?** Worth being honest with + yourself here. M0–M6 (≈46 weeks) gets a genuinely good single-player voxel + game and, more importantly, **makes Ludic a language that could plausibly + build one.** M8–M9 are what make it *Luanti*, and they are half the budget. + +--- + +## 8. Appendix A — target state + +What `examples/voxel.ludic` would look like once M0–M6 land. This is the +document's thesis in one file: nothing here is expressible today, and all of it +is ordinary Ludic in shape. + +```ludic +game Voxel { + import "voxel/nodes.ludic" + import "voxel/worldgen.ludic" + + # ---- data --------------------------------------------------------------- + struct MapNode { param0: u16 = 0, param1: u8 = 0, param2: u8 = 0 } + struct v3i { x: int = 0, y: int = 0, z: int = 0 } + struct v3f { x: f32 = 0, y: f32 = 0, z: f32 = 0 } + + volume Map of MapNode chunk 16 { + origin v3i + meta { generated: bool = false, timestamp: u32 = 0 } + } + + component Body { pos: v3f, vel: v3f, aabb: aabb, on_ground: bool = false } + component Look { yaw: f32 = 0, pitch: f32 = 0 } + component Health { hp: int = 20, max: int = 20 } + component Inv { slots: [32]ItemStack } + + archetype Player { Body, Look, Health, Inv } + archetype Mob { Body, Look, Health } + + # ---- content ------------------------------------------------------------ + def node Stone { + name = "voxel:stone" drawtype = DrawType.Normal + tiles = ["stone.png"] groups = [("cracky", 3)] + is_ground_content = true drop = "voxel:cobble" + } + def node Water { + name = "voxel:water" drawtype = DrawType.Liquid + tiles = ["water.png"] liquid = Liquid.Source { alt_flowing = "voxel:water_flowing" } + walkable = false light_propagates = true + } + + # ---- generation, off the main thread ------------------------------------ + thread pool emerge count 4 { + job Generate(bp: v3i) -> Chunk { + manip vm = Map.stage(bp) + for p in vm.area { + let n = noise2d(p.x as f32 / 64.0, p.z as f32 / 64.0, seed()) + let h = flr(n * 24.0) + 8 + vm[p] = if p.y > h { NODE_AIR } + else if p.y == h { NODE_GRASS } + else { NODE_STONE } + } + return vm.finish() + } + } + + system Emerge phase Update { + for bp in Map.wanted(view_radius = 10) { emerge.submit(Generate(bp)) } + while let c = emerge.poll() { Map.install(c) relight(c) remesh(c) } + } + + # ---- simulation: an ABM as a first-class system ------------------------- + system LavaCooling phase Update + every 10.0s chance 1 in 50 + nodes [NODE_LAVA_SOURCE] near [NODE_WATER_SOURCE, NODE_WATER_FLOWING] + { Map[self_pos()] = NODE_OBSIDIAN } + + # ---- physics ------------------------------------------------------------ + system Physics phase FixedUpdate + query (b) [Body] + { + b.vel.y = b.vel.y - 9.81 * dt() + let r = collide_swept(Map, b.aabb, b.pos, b.vel * dt(), stepheight = 0.6) + b.pos = r.pos + b.on_ground = r.hit_floor + if r.hit_floor { b.vel.y = 0.0 } + } + + # ---- interaction -------------------------------------------------------- + system Dig phase Input + query (b, l) [Body, Look, {Player}] + { + when mouse_pressed(MOUSE_LEFT) { + match raycast(Map, eye(b), dir(l), 5.0) { + Pointed.Node(under, _) => { + let def = node_def(Map[under].param0) + give(self(), def.drop) + Map[under] = NODE_AIR + } + _ => {} + } + } + } + + # ---- render ------------------------------------------------------------- + scene InGame start { + layer World { + system DrawWorld phase Render { + gfx_begin(camera_of(local_player())) + for c in Map.visible(frustum()) { gfx_draw_mesh(c.mesh) } + gfx_end() + } + } + layer Hud { + system DrawHud phase Render { ui_render() } + } + } +} +``` + +**Read that against LANGUAGE.md.** The `system`/`query`/`phase`/`scene`/`layer` +/`archetype`/`match` skeleton is *unchanged* — every line of new capability is +either a type (`struct`, `f32`, `[]T`, `enum`) or one of four new constructs +(`volume`, `manip`, `thread pool`, `def`). That is the encouraging finding of +this whole exercise: **Ludic's programming model is already the right one for +this game. What is missing is underneath it, not around it.** + +--- + +## 9. Appendix B — what Ludic already has that Luanti had to build + +Not everything is a deficit. Ludic starts with several things Luanti spent years +acquiring, and they should be counted: + +| Ludic has | Luanti equivalent | Cost Luanti paid | +|---|---|---| +| ECS in the language (`component`/`query`/`system`/`phase`) | hand-rolled `ActiveObjectMgr` + ad-hoc containers | scattered across `serverenvironment.cpp` (2,091) + `activeobjectmgr` | +| `scene`/`layer` state machine | mode flags and `if` ladders in `game.cpp` | part of 3,815 LOC | +| `match`/`machine`/`become` | switch chains | — | +| Retained `ui` tree as data | formspec **string DSL** parsed at runtime | `guiFormSpecMenu.cpp`, **5,610 LOC** | +| TrueType engine written in-language | FreeType + `CGUITTFont.cpp` (1,003) | external dep | +| PNG + DEFLATE decode in-language | libpng + zlib | external deps | +| Deterministic RNG in the language | `PcgRandom`/`PseudoRandom` exposed to Lua | — | +| Compile-time type checking of game logic | Lua: runtime errors on a live server | the entire class of mod crashes | +| One language for engine *and* content | C++ engine + Lua mods + a 1,253-line sandbox | the whole `src/script/` tree, **34,240 LOC** | + +That last row is the strategic one. **A third of Luanti's engine — 34,240 lines +of `src/script/` plus 22,634 lines of `builtin/` Lua — exists solely to bridge +C++ and Lua.** A Ludic implementation with a compiled mod ABI (G-25) does not +need that bridge at all. Roughly 57,000 lines of Luanti are a tax that Ludic +would simply not pay. + +--- + +## 10. Verdict + +**Can Ludic implement Luanti today?** No — and not because of anything about +games. It is missing arrays, strings, structs, floats, threads and sockets. Any +language missing those cannot implement any large program. + +**Is Ludic's design wrong for Luanti?** No — and this is the more interesting +answer. The ECS-in-the-language model, phases, scenes, archetypes and `match` +are a *better* fit for a voxel sandbox than C++-plus-Lua is. The `system … every +10.0s chance 1 in 50 nodes […]` form (G-16) compiles to something Luanti's ABM +implementation cannot achieve, because Luanti's predicates arrive as strings at +runtime and Ludic's arrive at compile time. + +**What is the actual shortest path?** M0 and M1. Arrays, structs, strings, +floats. Twelve weeks that convert Ludic from a language that can express a +2D JRPG into one that can express an engine — after which every remaining gap in +this document is ordinary library work in Ludic, plus one hard call about mods +(G-25) and one large push on the GPU (G-28). + +--- + +*Generated from `luanti-org/luanti@main` (362,258 LOC surveyed) against +`ludicc` at `compiler/{ludicc,native,driver}.c` and `runtime/native/*.ludic`. +Every Ludic limitation cited was verified by reading the compiler or by +compiling a probe program, not inferred from documentation.* diff --git a/README.md b/README.md new file mode 100644 index 00000000..200d8376 --- /dev/null +++ b/README.md @@ -0,0 +1,180 @@ +# Ludic + +An AI-first, ahead-of-time **compiled** game language with an ECS core, a +deterministic fixed-point runtime, and a native 2D backend. `ludicc` lowers +Ludic to LLVM IR itself and emits a native binary — **and `ludicc` is itself +written in Ludic.** + +``` + .ludic ──► ludicc ──► LLVM IR ──► object ──► native binary + (in Ludic) +``` + +**No C is generated, compiled or linked anywhere in a build.** There is no +interpreter, no transpiler, and no C runtime: the framebuffer, sprites, PNG +decoding, TrueType text, the retained UI, the registers and the RNG are all +written in Ludic (`runtime/native/*.ludic`), and the macOS window is +hand-written LLVM IR (`runtime/native/cocoa.ll`). Beneath that sits only the +platform's own ABI — malloc, fwrite, objc_msgSend, CoreGraphics — reached by +compiler intrinsics, the same floor Rust and Swift stand on. + +**The compiler is written in Ludic.** `selfhost/*.ludic` is a Ludic compiler — +lexer, parser and LLVM-IR backend — that compiles every example (including the +6-file JRPG) to the byte-exact same binary the original C compiler produced, and +compiles **its own source** to a fixpoint. It is built from a checked-in IR seed +(`selfhost/ludicc.seed.ll`) with clang alone; run `./selfhost/bootstrap-cfree.sh` +to rebuild it with no C compiler in the loop. The former C compiler is gone. + +Neither the compiler nor the games are C. Beneath both sits only the platform's +own ABI — malloc, fwrite, objc_msgSend, CoreGraphics — reached by intrinsics, the +same floor Rust and Swift stand on. (The wasm/cross-compile/shared-library driver +paths lived in the old C compiler and are not yet re-implemented on the +self-hosted native toolchain.) + +## Layout + +| Path | What it is | +|------|-----------| +| `selfhost/*.ludic` | **the compiler, written in Ludic** — lexer, parser, and the LLVM-IR backend (ECS storage, queries, spawn, `match`/`machine`, UI, scenes, save/load, fixed-point). Concatenated by `selfhost/build.sh`; built from `selfhost/ludicc.seed.ll` | +| `selfhost/bootstrap-cfree.sh` | rebuild the compiler from the IR seed with **no C compiler**, and prove it reproduces its own IR | +| `runtime/native/core.ludic` | the runtime written *in Ludic* for the native path (framebuffer, text, registers, RNG, input) | +| `COMPILING.md` | the native pipeline: `ludicc → LLVM IR → exe/dylib`, `module`/`export`, cross-compilation, `rt_*` intrinsics | +| `runtime/native/image.ludic` | PNG decoding, images, sprites, alpha blending and 9-slice — in Ludic | +| `runtime/native/inflate.ludic` | DEFLATE decompression (RFC 1951), so PNG needs no zlib on any target | +| `runtime/native/truetype.ludic` | from-scratch TrueType loader + antialiased glyph rasterizer, in Q16.16 | +| `runtime/native/ui.ludic` | retained UI widget tree: layout, 9-slice, focus, events — in Ludic | +| `runtime/native/cocoa.ll` | the macOS window, written in LLVM IR (Objective-C runtime + CoreGraphics via their C ABI) | +| `runtime/web/wasm.ll` | the web's platform layer in LLVM IR: the allocator, bulk memory and strings, since wasm32 has no libc | +| `runtime/web/platform.js` | the browser's window — the same five `win_*` functions `cocoa.ll` implements, against a `` | +| `runtime/web/index.html` | the page a web build is served from | +| `tools/ludic-web/run.mjs` | runs a headless wasm build under Node, so native and wasm output can be diffed | +| `examples/chronorift.ludic` | the JRPG written in Ludic (multi-file via `import`, archetype-based) | +| `examples/menu.ludic` | a retained-UI title screen (9-slice, TrueType, focusable buttons) | +| `examples/snake.ludic` | a second, unrelated game — proves the language is general (same toolchain, no engine hardcoding) | +| `build.sh` | `./build.sh examples/.ludic` | +| `test.sh` | regression suite: builds the compiler, compiles/runs all examples, checks save/load + diagnostics (`./test.sh`) | +| `tools/ludic-tools/` | the editor toolchain, in C: `ludic-fmt` (source formatter) and `ludic-lsp` (language server) — one lexer and one vocabulary shared by both | +| `tools/editors/` | plugins for VS Code and JetBrains, plus configuration for Neovim, Helix, Emacs, Sublime and Zed ([README](tools/editors/README.md)) | +| `tools/test-tools.sh` | regression suite for the toolchain: proves formatting never changes a program, drives the language server over real LSP traffic | + +## Build & run + +`ludicc` compiles Ludic straight to machine code via LLVM IR. See +**[COMPILING.md](COMPILING.md)** for the pipeline, shared libraries +(`--shared`), cross-compilation and the runtime protocol. + +```bash +./build.sh examples/chronorift.ludic +./build/chronorift # opens a native window +``` + +Headless render (for testing / CI): + +```bash +./build.sh examples/chronorift.ludic --headless +printf 'ddddwww' | ./build/chronorift_headless # writes out.ppm +sips -s format png out.ppm --out frame.png +``` + +A `module` compiles to a shared library instead of a program: + +```bash +./build.sh examples/lib/combat.ludic --lib # -> build/libcombat.dylib +``` + +In a browser: + +```bash +./build.sh examples/chronorift.ludic --web # -> build/web/ +python3 -m http.server -d build/web 8000 # open http://localhost:8000/ +``` + +`build/web/` is a self-contained 116 KB directory — the 42 KB module, the loader, +a page, and the sprites the compiler saw the game name. Copy it to any static +host and it runs; it needs no server-side anything and no special headers. Saves +go to `localStorage`, so `save()`/`load()` survive a reload. + +A wasm build needs an LLVM with the WebAssembly backend and `wasm-ld` — Linux +`clang`/`lld` have both, Apple's clang has neither (`brew install llvm lld`). +See **[COMPILING.md](COMPILING.md#the-web)** for the pipeline, who owns the frame +loop, and how assets are bundled. + +## Editor support + +```bash +./tools/build-tools.sh # -> build/ludic-fmt, build/ludic-lsp +``` + +`ludic-lsp` speaks LSP 3.17 over stdio, so one binary serves every editor: +completion that knows whether you are after a `.`, inside a `query [...]` or in +a `ui` block; diagnostics from the compiler itself; go-to-definition and rename +across `import`ed files; comment-preserving formatting. `ludic-fmt` is the same +formatter as a CLI, for pre-commit hooks and CI. + +Plugins for **VS Code** and **JetBrains IDEs** (Community editions included) and +drop-in configuration for Neovim, Helix, Emacs, Sublime and Zed are in +[`tools/editors/`](tools/editors/README.md). Both tools also understand +```` ```ludic ```` fences in Markdown, so this file and `LANGUAGE.md` get the +same highlighting, checking and formatting as the source tree. + +## Language features implemented + +- `component` (typed fields + defaults), `system` (`phase`, `@annotations`, + `reads`/`writes` clauses), `const`, `fn` (with `requires`/`ensures` parsed). +- `archetype` — named entity **kinds** (bundles of components); identity is one + int per entity, replacing empty tag components. Filter with `{Kind}`. +- `import "file"` — multi-file programs (fragments spliced in, include-guarded, + per-file diagnostics). +- ECS queries: `for (a, b) in query [A, B, {Tag}] where { … }`. +- `spawn`/`despawn` with entity-slot reuse; nested queries. +- Control flow: `if`/`else`, `when`, `while`, numeric `for i in a .. b`. +- Types: `int`, `fixed` (Q16.16, with correct `*`/`/` lowering), `bool`, + `entity`, `str`. Fixed-point vs int arithmetic is resolved by the typechecker. +- Deterministic seeded RNG; `save()`/`load()` snapshot of the whole ECS World. +- 2D primitives: `clear`, `fill_rect`, `frame_rect`, `put_px`, `present`, `key`. +- TrueType text (`font_load`, `text_ttf`) with full Unicode + anti-aliasing; + arbitrary-size images + `draw_9slice`. +- `ui` — a retained widget tree declared as data (panels, labels, buttons, + images; layout, 9-slice skins, keyboard focus + click events). +- `match` / `machine`+`state`+`become` — dispatch and state machines. +- `scene` / `layer` / `enter` — mutually-exclusive game states, each with + `on enter`/`on exit` hooks and layered systems (layer order = draw order). +- `var` — typed module-level state, included in save/load snapshots. +- `module` + `export fn` — compile a .ludic file to a shared library whose + exported functions are ordinary C-ABI symbols. +- `extern fn … = "symbol"` — call any C-ABI library, Ludic or otherwise. +- `--target wasm32-unknown-unknown` — the same game in a browser: the runtime, + the ECS and the graphics stack compiled to wasm, rendering frames identical to + the native build's. + +## The game: Chrono Rift + +A playable co-op JRPG in `examples/chronorift.ludic`, using CC0 +[Kenney](https://kenney.nl) sprites (Tiny Town + Tiny Dungeon), decoded from +PNG at runtime by the Ludic-written PNG/DEFLATE decoder — no zlib, no external +dependency on any target. + +Controls: +- **Overworld:** `WASD` move, `K` save, `L` load. +- **Battle (local co-op):** Player 1 / Knight — `W`/`S` select, `Space` confirm. + Player 2 / Mage — `I`/`K` select, `J` confirm. Each player takes their own + turn each round (Attack / Defend / Run; Mage has Attack / Heal / Defend). + +## Status + +- [x] Compiler pipeline: Ludic → LLVM IR → native binary / shared library +- [x] No C generated, compiled or linked in a build; runtime written in Ludic +- [x] Cross-compilation to ELF (x86-64, aarch64) and Windows COFF +- [x] ECS runtime (components, systems, phases, queries, entity pooling) +- [x] Windowed 2D rendering (Cocoa driven from LLVM IR) + headless PPM verification +- [x] CC0 Kenney PNG sprites (`load_png`, decoder written in Ludic) + scrolling camera +- [x] Overworld: tilemap, movement, collision +- [x] Random encounters + turn-based battle (HP/MP, seeded-RNG damage) +- [x] Party + **local co-op** (P1 Knight, P2 Mage, per-player turns) +- [x] Leveling (XP → stat growth) and game-over / respawn +- [x] **Self-hosting**: a Ludic-written compiler compiles its own source to a byte-exact fixpoint, and rebuilds itself from a checked-in IR seed with no C compiler in the loop (`selfhost/`, `./selfhost/bootstrap-cfree.sh`) +- [x] Snapshot save / load (full ECS World) +- [x] Two maps (overworld + dungeon) with map switching via the arch +- [x] Boss encounter (Rift Warden) + victory condition +- [x] Item shop (gold → potions) at the house; potions usable in battle (Knight ITEM) +- [ ] More skills / enemy variety (future) diff --git a/SYNTAX-REDESIGN.md b/SYNTAX-REDESIGN.md new file mode 100644 index 00000000..5c892a29 --- /dev/null +++ b/SYNTAX-REDESIGN.md @@ -0,0 +1,254 @@ +# Ludic Syntax Redesign — Cohesion Pass + +A plan to make Ludic's syntax internally consistent. It fixes the drift between +the spec and the compiler, then unifies the grammar around two rules. Scope: +**full redesign (Phases 0–5)**. Named-field direction: **colon everywhere**. + +> Status: **Phase 1 landed** (see below). Phases 2→5 are proposals. The phases +> are ordered so the documentation never describes syntax the compiler rejects, +> and every phase ends with the compiler still self-hosting to a fixpoint +> (`./test.sh`). +> +> Coordinated with the toolchain agent (CLI front-end / `ludicc`+`ludic` +> binaries) via serialized reseeds of `selfhost/ludicc.seed.ll`; Phase 1 rode in +> alongside their `emit_*`/`main.ludic` work, combined suite **14/14 green**. + +--- + +## Why (the findings) + +Verified against the self-hosted compiler ([selfhost/parse.ludic](selfhost/parse.ludic), +[selfhost/parse_game.ludic](selfhost/parse_game.ludic), [selfhost/lex.ludic](selfhost/lex.ludic)): + +**Structural incoherence** +1. **Five micro-syntaxes for named parts** — `name: type = d` (fields), `name: type` + (params), `Field = { k = v }` (spawn), `[Name, {Tag}]` (query), whitespace + `phase X reads [..]` (system clauses), `key=value` (ui props). +2. **`=` means seven things, `:` means one** — assignment, default, record init, + ui prop, extern symbol, const value, `state X = N` all use `=`. +3. **No statement terminators** — `\n` and `;` both lex to `TK_NL` + ([lex.ludic:45,121](selfhost/lex.ludic)) but the parser never requires a + separator, so `t.kind = k t.text = x t.ival = v` (three statements, spaces + only) is idiomatic. + +**Broken / dead syntax (compiler-verified)** +4. `edge system` — **hard parse error** (documented at [LANGUAGE.md:188](LANGUAGE.md)). *(✅ fixed in Phase 1)* +5. `pure fn` — parses, `pure` silently discarded ([parse.ludic:272](selfhost/parse.ludic)); undocumented. +6. `@anno` + `reads/writes/needs/uses [..]` — parsed then thrown away + ([parse_game.ludic:15-31](selfhost/parse_game.ludic)); four synonyms, two undocumented. +7. `scene`/`layer`/`on enter` — full LANGUAGE.md section + [examples/scenes.ludic](examples/scenes.ludic), + **does not compile** (`expected declaration`). +8. `query (v) [..]` in a system signature — two LANGUAGE.md sections + + [examples/qdecl.ludic](examples/qdecl.ludic), **does not compile** (`parse error: {`). *(✅ implemented in Phase 1)* +9. `when cond {}` — documented ([LANGUAGE.md:329](LANGUAGE.md)) + in all three editor + highlighters, **never parsed**. *(✅ implemented in Phase 1 as an if-without-else alias)* +10. CLI `--emit-llvm`/`-o`/`--shared`/`--fmt` — documented, but `ludicc` only + accepts `--windowed`/`--headless` ([main.ludic:8-14](selfhost/main.ludic)). + +**Philosophical splits** +11. Operators are words (`and`/`or`/`not`), symbols (`==`/`<=`), *and* functions + (`band`/`shl`) at once. +12. Three overlapping control families — `if`/`when`, `match`, `machine`/`become` + — and `enter` reuses `become`'s AST node ([parse.ludic:176-177](selfhost/parse.ludic)). +13. Typed components/structs exist, but real state lives in 64 untyped int + registers (`reg`/`setreg`), so `machine`/`match` dispatch on magic numbers. + +--- + +## The two rules everything converges on + +**Rule A — `:` associates, `=` binds.** +- `:` introduces a *named part* and its type or value in a declarative structure: + component/struct fields' types, record initializers, ui props, (future) named + call arguments. +- `=` binds a value to a storage location or a constant: `let`, assignment + (`+=` …), `const` value, a field's **default**, and the extern symbol. +- A field declaration uses both, unambiguously: `x: int = 0` reads "`x` *has type* + `int` (`:`), *defaulting to* `0` (`=`)" — same shape as Rust/TypeScript. +- A record/spawn initializer is declarative, so it uses `:` — `Pos { x: 10 }`. + +**Rule B — a statement ends at a newline (or `;` or `}`).** +- Newlines become significant. Two statements on one line require an explicit + `;`. `ludic-fmt` normalizes one statement per line and inserts/removes `;`. + +Everything below is these two rules applied construct by construct. + +--- + +## Target grammar (before → after) + +### Records / spawn initializers +```ludic +# doc-check: skip — illustrative redesign snippet (proposed / partial syntax) +# before +spawn Hero { Pos = { x = 10, y = 5 } Player = { } } +# after +spawn Hero { + Pos { x: 10, y: 5 } + Player {} +} +``` +`Field = { k = v }` → `Field { k: v }`. The component name is followed directly +by a record; fields use `:`. (Record literals elsewhere read the same: +`{ x: 10, y: 5 }`.) + +### UI props → named-argument form +```ludic +# doc-check: skip — illustrative redesign snippet (proposed / partial syntax) +# before +panel id=Root w=288 pad=16 gap=6 align=center { label text="HI" size=26 } +# after +panel(id: Root, w: 288, pad: 16, gap: 6, align: center) { + label(text: "HI", size: 26) +} +``` +A widget becomes "a constructor with named args, then an optional child block." +This deletes the bespoke `key=value` dialect and reuses `:` + commas. (Lower-churn +alternative if the paren form is disliked: keep whitespace separation but colonize +— `panel id: Root w: 288` — still removes the `=` overload.) + +### System clauses & modifiers → one annotation channel +```ludic +# doc-check: skip — illustrative redesign snippet (proposed / partial syntax) +# before +edge system Move @deterministic reads [Vel] writes [Pos] phase FixedUpdate + query (p, v) [Pos, Vel] where a.x > 0 { … } +# after +@edge @deterministic +system Move + phase FixedUpdate + reads [Vel] writes [Pos] + query (p, v) [Pos, Vel] where p.x > 0 +{ … } +``` +- Prefix modifier words (`edge`, `pure`, `export`) are **retired**; all modifiers + become `@annotations`, parsed into a real list on the node (not skipped). This + fixes the `edge system` parse bug (#4) by construction. +- `needs`/`uses` are dropped; `reads`/`writes` stay as the two structural clauses + and are **stored** (even if analysis is future work) rather than discarded. +- The `query (v) [..]` signature clause is **actually implemented** in + `parse_system` (#8), lowering to the same `S_QUERY` node as the inline `for`. + +### extern +```ludic +# doc-check: skip — illustrative redesign snippet (proposed / partial syntax) +extern fn c_hypot(a: fixed, b: fixed) -> fixed = "hypot_fx" # unchanged +``` +The `= "symbol"` is a binding under Rule A — it stays. + +### Statements +```ludic +# doc-check: skip — illustrative redesign snippet (proposed / partial syntax) +# before (legal today) +t.kind = kind t.text = text t.ival = ival +# after +t.kind = kind +t.text = text +t.ival = ival +# or, explicitly, on one line: +t.kind = kind; t.text = text; t.ival = ival +``` + +### Control flow (Phase 4) +- **`when` vs `if`** — `when` is now a working `if`-without-else alias (Phase 1). + Phase 4 decides whether to keep both spellings or collapse to one; if collapsed, + remove `when` from docs, the parser, and all editor highlighters together. +- **Typed states replace magic-int machines.** Introduce `enum`, and let + `machine` dispatch on a typed variable instead of a register: +```ludic +# doc-check: skip — illustrative redesign snippet (proposed / partial syntax) +# before # after +const R_PHASE: int = 0 enum Phase { KnightMenu, KnightResolve, MageMenu, EnemyTurn } +machine R_PHASE { var phase: Phase = Phase.KnightMenu + state KnightMenu = 0 { … become … } machine phase { + state KnightResolve = 1 { … } state KnightMenu { … become KnightResolve } +} state KnightResolve { … } + } +``` + `state X = N` loses the magic `= N` (ordinal comes from the enum). `become` + and `enter` (scenes) keep one shared lowering but read from a typed slot. + +--- + +## Phase sequence + +Each phase is independently shippable and ends green on `./test.sh` + +`./selfhost/test.sh` (fixpoint). + +### Phase 0 — Doctrine (done here) +Rules A and B above; colon-everywhere; `@`-annotations as the single modifier +channel; typed enums for state. No code. + +### Phase 1 — Truth-in-documentation ✅ DONE +Made spec ⇄ compiler agree **before** any grammar change. What landed: +- ✅ **`edge system` crash fixed** (#4) — `parse_system` now consumes an optional + `edge` marker before `system` ([parse_game.ludic](selfhost/parse_game.ludic)). + (`edge` is a pure marker; the emitter never lowered it differently.) +- ✅ **Signature-`query` implemented** (#8) — `query (vars) [terms] where c` in a + system header desugars to the same `S_QUERY` node the inline `for` builds, so + `examples/qdecl.ludic` compiles and runs. Also fixed multi-line clause parsing + (clauses may now span lines). +- ✅ **`when c { }` implemented** (#9) — as an `if`-without-else alias in + [parse.ludic](selfhost/parse.ludic). Docs + editors already listed it; now the + compiler agrees, so no editor-vocab churn was needed. +- ✅ **`scene`/`layer` marked not-yet-implemented** (#7) — prominent note in + LANGUAGE.md §"Scenes & layers" + a header on [examples/scenes.ludic](examples/scenes.ludic). + Full scene front-end + emission deferred (real work, out of Phase 1 scope). +- ✅ **`reads`/`writes` honesty** (#6) + the stale "Not yet implemented" section + updated in [LANGUAGE.md](LANGUAGE.md); scenes/reads-writes/dropped-CLI-flags now + listed there. +- ✅ **`test.sh` guards drift** — added a `qsmoke qdecl` compile check. Suite + green (14/14 incl. the toolchain agent's CLI smoke tests). +- ✅ **CLI flags** (#10) — `--shared`/`--fmt`/wasm noted as dropped-with-the-C-driver + in LANGUAGE.md; `-o`/`--emit-llvm` were being re-added by the toolchain agent + (now real, verified in `test.sh`); COMPILING.md updated by that agent. +- Deferred (intentionally): `pure`-is-ignored (#5) is undocumented and harmless; + it will be folded into `@pure` in Phase 3 rather than churned now. +- **Not done / by design:** `scenes.ludic` is *not* added to `test.sh` (it can't + compile yet — a positive test would fail; the header note + LANGUAGE.md warning + cover the drift instead). + +### Phase 2 — Statement separation (Rule B) +- Enforce a separator in `block()`/`stmt()` ([parse.ludic:130-199](selfhost/parse.ludic)): + after a statement, require `TK_NL` or `}`. +- Teach `ludic-fmt` to normalize one-statement-per-line and insert `;` where two + share a line. Reformat the whole corpus with it. +- Risk: the self-host sources themselves use space-juxtaposed statements heavily + — reformat them in the same commit, re-seed, re-verify fixpoint. + +### Phase 3 — Named-field unification (Rule A) +- Migrate spawn/record init (`= {…=…}` → `{…:…}`) and ui props (`key=value` → + named-arg form) in the parser and emitters. +- Collapse `reads/writes/needs/uses` → `reads`/`writes`, stored on the node. +- Move `edge`/`pure`/`export` into `@`-annotations; parse annotations into a list. +- Ship `ludic-fmt --migrate`: a mechanical codemod that rewrites old syntax to + new, run over `examples/`, `runtime/`, and `selfhost/`. +- Gate: compiler still self-hosts; every golden render is byte-identical. + +### Phase 4 — Control-flow & operator consolidation (largest) +- Remove `when`; confirm `if` covers all uses in the corpus. +- Introduce `enum` + typed `machine`/state; migrate `combat.ludic`'s R_PHASE + machine and the register-driven `match reg(…)` sites. +- Decide the bitwise story: keep `band/shl/…` as functions (document as a + deliberate "one spelling" choice) or promote to operators — pick one and state + it, don't leave it implicit. + +### Phase 5 — Single source of truth for keywords/grammar +- Generate every editor plugin keyword list, `ludic_syntax.h`, and the LSP's + token set from **one** canonical list so a keyword can never again be + highlighted but unparsed. +- Add a CI check (extend `tools/check-docs.py` / `check-vocabulary.py`) that + every ` ```ludic ` fence in the docs compiles, closing the doc-drift loop + permanently. + +--- + +## Decision log +- **Scope:** full redesign, Phases 0–5. *(chosen)* +- **Named fields:** colon everywhere; `=` is binding-only. *(chosen)* +- **Open — Phase 4 detail:** typed `enum` state vs. keep integer registers. + Recommended: typed enums (fixes #13), but it's the deepest change; can be + deferred without blocking Phases 1–3. +- **Open — ui props:** paren named-args (`panel(id: Root)`) vs. colonized + whitespace (`panel id: Root`). Recommended: paren form for full cohesion. +- **Open — bitwise ops:** functions (status quo, documented) vs. operators. diff --git a/assets/kenney/tiny-dungeon/License.txt b/assets/kenney/tiny-dungeon/License.txt new file mode 100644 index 00000000..1b269f6a --- /dev/null +++ b/assets/kenney/tiny-dungeon/License.txt @@ -0,0 +1,22 @@ + + + Tiny Dungeon (1.0) + + Created/distributed by Kenney (www.kenney.nl) + Creation date: 05-07-2022 + + ------------------------------ + + License: (Creative Commons Zero, CC0) + http://creativecommons.org/publicdomain/zero/1.0/ + + This content is free to use in personal, educational and commercial projects. + Support us by crediting Kenney or www.kenney.nl (this is not mandatory) + + ------------------------------ + + Donate: http://support.kenney.nl + Patreon: http://patreon.com/kenney/ + + Follow on Twitter for updates: + http://twitter.com/KenneyNL \ No newline at end of file diff --git a/assets/kenney/tiny-dungeon/Preview.png b/assets/kenney/tiny-dungeon/Preview.png new file mode 100644 index 0000000000000000000000000000000000000000..01c23ad3ec7f764f6f2cbfbda9d56f22c0050de2 GIT binary patch literal 17553 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 X@Y0(Smz!^l+>?`5k}8of{PceS=FG8r literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Sample.png b/assets/kenney/tiny-dungeon/Sample.png new file mode 100644 index 0000000000000000000000000000000000000000..505a6d64c04378ad0b08bb7be182baf222d97c30 GIT binary patch literal 26519 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

b0;o+ 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 N002ovPDHLkV1m)0z5W0I literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiled/sampleMap.tmx b/assets/kenney/tiny-dungeon/Tiled/sampleMap.tmx new file mode 100644 index 00000000..9227705a --- /dev/null +++ b/assets/kenney/tiny-dungeon/Tiled/sampleMap.tmx @@ -0,0 +1,76 @@ + + + + + +14,1610612787,16,1,1,3221225485,1,1,1,2,3,3,3,3,3,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +14,1610612787,17,3,3,4,1,1,1,14,41,41,41,41,41,16,1,1,1,1,1,25,1,1,1,1,1,1,1,1,1073741837,1, +14,1610612787,58,41,41,16,25,1,1,14,1610612789,51,51,52,51,16,2,3,4,1,1,1,1,2,3,7,3,3,3,7,3,4, +14,1610612787,51,52,51,16,1,1,1,14,1610612787,49,3221225522,49,49,16,14,41,16,1,1,536870925,1,14,41,19,41,30,41,19,41,16, +14,1610612787,5,27,27,28,1,1073741837,1,14,1610612787,49,49,49,49,16,14,1610612789,16,1,1,1,1073741837,14,1610612789,31,51,51,52,31,51,16, +14,1610612787,16,2,3,3,3,3,4,26,27,27,27,27,27,28,14,1610612787,17,7,3,3,4,14,1610612787,49,49,49,49,49,49,16, +14,1610612787,16,14,41,41,41,41,17,3,3,3,3,4,1,1,14,1610612787,58,19,41,41,16,14,1610612787,49,49,49,49,49,49,16, +18,1610612787,17,18,1610612789,51,52,51,58,41,41,22,41,16,2684354573,1,14,1610612787,51,31,51,51,16,14,1610612787,49,49,49,49,49,49,16, +60,1610612787,58,60,1610612787,49,49,49,51,51,51,51,51,17,3,3,18,1610612787,49,43,49,3221225522,17,18,1610612787,49,49,49,49,49,2684354610,17, +51,54,51,51,54,43,49,50,49,49,49,49,49,58,41,41,60,1610612787,49,49,43,49,58,60,37,38,38,38,38,38,39,58, +49,43,49,49,49,49,49,49,49,49,49,49,49,51,52,51,51,54,49,49,49,49,51,52,54,49,49,49,49,49,49,51, +49,49,49,5,27,6,1610612790,49,49,2147483698,49,49,49,49,49,49,49,49,49,49,49,49,49,5,27,27,27,27,27,27,27,27, +49,49,49,16,1,14,1610612787,49,49,49,49,49,49,5,27,27,27,27,27,27,6,1610612790,49,16,1,1,1,1,1,1,1,1, +27,27,27,28,3221225485,14,1610612787,49,49,5,27,27,27,28,2,3,3,3,3,3,18,1610612787,49,16,1,1,1,2,3,3,3,3, +1,1,1,1,2,18,1610612787,49,49,17,3,4,1,1,14,41,20,41,41,21,60,1610612787,49,16,1,1,1073741837,14,41,11,12,41, +1,2,3,3,18,60,1610612787,49,49,58,41,17,3,3,18,1610612789,32,51,51,33,51,54,2147483698,16,1,1,1,14,1610612789,51,51,51, +1,14,41,41,60,1610612789,54,49,49,51,51,58,41,41,60,1610612787,49,43,49,49,49,49,49,17,3,3,3,18,1610612787,49,49,49, +1,14,1610612789,52,51,54,49,49,2147483698,42,49,51,51,51,51,54,43,49,49,49,49,49,49,58,41,41,41,60,1610612787,49,49,49, +1,14,1610612787,3758096434,49,49,49,49,49,3758096434,49,49,49,49,49,49,49,49,49,49,49,43,49,51,51,51,51,51,54,49,49,49, +1,14,1610612787,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,3758096434,49 + + + + +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,87,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66,0,65,0,65,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,67,0,67,0,67,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,121,0,0,0,0,0,0, +0,0,0,0,0,112,0,0,0,62,0,0,0,0,0,0,0,0,74,0,73,0,0,0,0,0,121,0,0,0,0,0, +0,0,65,0,0,0,0,0,62,88,62,0,0,0,0,0,0,0,0,0,0,74,0,0,0,0,0,0,0,0,0,0, +0,0,67,0,0,0,0,0,98,62,0,0,0,0,0,85,0,0,0,2147483758,0,0,0,0,0,0,0,0,0,0,0,0, +0,65,0,0,0,0,0,0,0,0,99,61,0,0,0,0,0,0,0,0,0,123,0,0,0,0,0,0,0,0,0,0, +0,67,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,68,0,0,0,0,0,0,0,0,0,0,0,0,0,78,78,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,82,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,82,0,0,0,0,0,0,0,0,0,0,0,0,0,124,0,0,0,0,0,0,0,0,0,83, +0,0,0,0,0,0,0,82,0,0,0,0,0,0,0,0,0,0,0,124,0,0,0,0,0,0,0,0,0,90,0,0, +0,0,0,0,0,0,0,82,0,0,0,0,0,0,0,0,0,0,0,0,0,2147483773,0,0,0,0,0,0,0,0,2147483749,0, +0,0,0,0,0,0,0,94,71,71,71,71,71,72,0,0,0,0,0,0,0,0,0,0,0,0,83,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,82,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + + + + +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,56,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,55,55,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + + + diff --git a/assets/kenney/tiny-dungeon/Tiled/sampleSheet.tsx b/assets/kenney/tiny-dungeon/Tiled/sampleSheet.tsx new file mode 100644 index 00000000..46a615e4 --- /dev/null +++ b/assets/kenney/tiny-dungeon/Tiled/sampleSheet.tsx @@ -0,0 +1,4 @@ + + + + diff --git a/assets/kenney/tiny-dungeon/Tilemap/tilemap.png b/assets/kenney/tiny-dungeon/Tilemap/tilemap.png new file mode 100644 index 0000000000000000000000000000000000000000..a893ccb09a0be133b3d4aedafcc660e912048b56 GIT binary patch literal 5533 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 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tilemap/tilemap_packed.png b/assets/kenney/tiny-dungeon/Tilemap/tilemap_packed.png new file mode 100644 index 0000000000000000000000000000000000000000..f6e8b937c99fe45b1b75490cc050ee5929954259 GIT binary patch literal 5294 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 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0001.png b/assets/kenney/tiny-dungeon/Tiles/tile_0001.png new file mode 100644 index 0000000000000000000000000000000000000000..cdaffc0959303c023be8d2a67b755c18aa629217 GIT binary patch literal 126 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF z-LtnGIDN-n&9Kbc?AJ!V44}BIr;B3<$MxhN{46|2g#U*zcE%?-iMX^J>SQorWZ0o+ V9iyS!eHN&Y!PC{xWt~$(697#MA=Ll? literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0002.png b/assets/kenney/tiny-dungeon/Tiles/tile_0002.png new file mode 100644 index 0000000000000000000000000000000000000000..0b4f047bf9043dcbf7a9bf106939a29313749f13 GIT binary patch literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFUXo1?3QQ>+PK?b9Hf-Ez*paw~ sCxyXKsM*ugvs3a!0Fz;Z#5o3r&?AzDRjuXkfVvqxUHx3vIVCg!0LscKKL7v# literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0003.png b/assets/kenney/tiny-dungeon/Tiles/tile_0003.png new file mode 100644 index 0000000000000000000000000000000000000000..c03b478f1f8fdac9f72c0a6ec5133ec0dc91e879 GIT binary patch literal 126 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF z-LtnGIDN-n&9Kbc?AJ!V44}BIr;B3<$MxhN{46|2gjRoR?)d7U#NyI&h%-!rk)iX4 VC5z77+aPlpJYD@<);T3K0RV9oBH#c3 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0004.png b/assets/kenney/tiny-dungeon/Tiles/tile_0004.png new file mode 100644 index 0000000000000000000000000000000000000000..e55ab28bf1401a2dc0a9693097a0db5d02fd9d16 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFqg0Uzcj7e`07jV2rk9^Qq8 zg^b2N4Lk~NNgC49(yI?hIP@F|XkutHnZ6|<`SFDS4dn*WBOI)Z9Lf!fBEBp$85#a@ Wsic0NS>6UTlfl!~&t;ucLK6TlF*POt literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0005.png b/assets/kenney/tiny-dungeon/Tiles/tile_0005.png new file mode 100644 index 0000000000000000000000000000000000000000..e4d148bfa5ef669aa76d1ce89d56e321ccea6191 GIT binary patch literal 181 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFqg0Uzcj7e~i76Aq6Q5AVXl zLdH!JF+L4E!s01yn>KFT$TcC6CrLwE*>H-2La(BU$(0)>yerfi8b!}>@Uj{@IWpKY ZGkm|MBHR#PupMYDgQu&X%Q~loCIIhFHYWf8 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0006.png b/assets/kenney/tiny-dungeon/Tiles/tile_0006.png new file mode 100644 index 0000000000000000000000000000000000000000..fe7f7b35497eef62747d66f6c682e68eba8af664 GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFr7(8A5 KT-G@yGywo?zBo1j literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0007.png b/assets/kenney/tiny-dungeon/Tiles/tile_0007.png new file mode 100644 index 0000000000000000000000000000000000000000..029bf8c9f790f40a4b60e15b415407187aff4862 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF z2TtD!N~lrOcIlqI<*3SjkfvZy7sn8e>&YCfOl|+~|G%I9u;SG*!K5cNL&5yZ)e+uZofa9&Jq1TTZ{Sqs!$%D`uMf~&VLZk a;9>CmsI}Ox_S1Wy@eH1>elF{r5}E)he?)Zv literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0008.png b/assets/kenney/tiny-dungeon/Tiles/tile_0008.png new file mode 100644 index 0000000000000000000000000000000000000000..0ee6237e00116278e514f61c2da8ce03a1dc9aa3 GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFfLpZZ@l1_y6Z;;+j7F!)MP={!9f7Z44LNuN9SbOqtf5euBw`Q!3&73oakNn?DWK z-dp@8`tgzU@5$0ko2F;$e0@9f_x9r@FD2(0-dX&=p5d*hX6DAy{D(j*89ZJ6T-G@y GGywqNCQ?WM literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0009.png b/assets/kenney/tiny-dungeon/Tiles/tile_0009.png new file mode 100644 index 0000000000000000000000000000000000000000..3a47228d1c71d850a4d08d43f66fd09e5673eca8 GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFP9Iv2+n(o&3$4>CD2{3zDHh$G!sUYz~wA;c-#M-K>!$E|b3&`T)>XO*az@X|Oy~+9X R#BQLe44$rjF6*2Ung9z-HMIZ$ literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0010.png b/assets/kenney/tiny-dungeon/Tiles/tile_0010.png new file mode 100644 index 0000000000000000000000000000000000000000..3e7352b04be6063838772621729d87d9cb606d9c GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF@7hFHG6Zs)U;i?WfOaWQr4a>jv*Y^lLLwx8Q28H#nnZ{#Z}qF-5u3f9T^pz zIgSamta3DvSiqyMTEbS?H8-}WkzvU(iBkn^#tc(arFTsE+p-8~41=eupUXO@geCw( Cnk(7> literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0011.png b/assets/kenney/tiny-dungeon/Tiles/tile_0011.png new file mode 100644 index 0000000000000000000000000000000000000000..2ceaed8d7e58e10cf5bba5588df9a6f8b3979117 GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF@7hFHG6Zs)U;i?WfOaWQudxMjv*Y^lM5OdRM}L;#nnZ{#ogId-5k|e9RMpCUIen!xBr_&KL-mFf!DeN((3avs()^iow&>&t;uc GLK6VjkSi7d literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0012.png b/assets/kenney/tiny-dungeon/Tiles/tile_0012.png new file mode 100644 index 0000000000000000000000000000000000000000..4320cb2fdffac29308f9b01ac47271d471ff28d8 GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6;>0X`wF zdvm<()eOt5&3G-(PXY=$dAc};a9mH0U}fQ19oFh*xF$+cicLjm86zjVVO!`#honfA z8QfDMq}W1?Ohr~yaJ}B5Bfyx%xHDnn(!_+|u(eDKOkWjJ7B-#V0W^)l)78&qol`;+ E09CdsMF0Q* literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0013.png b/assets/kenney/tiny-dungeon/Tiles/tile_0013.png new file mode 100644 index 0000000000000000000000000000000000000000..3a5b250cb584680d43ff295cdbdac9982bb807f8 GIT binary patch literal 110 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6;>0X`wF z2TtFyS2HZLHdAnQYX<4?ba4#fxSkxbHA_>Q`6~wlx3&Dky9!@>fN~6;u6{1-oD!M< D^!*z* literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0014.png b/assets/kenney/tiny-dungeon/Tiles/tile_0014.png new file mode 100644 index 0000000000000000000000000000000000000000..bec979d97eeeeb13fdf35a178da78f81a4875151 GIT binary patch literal 143 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6;>0X`wF z2TtD!N~r0cy~WD^WCl>s(9^{+gyVWL2P;!sXt49*1xMC|Zk9NZl(l-Ap@B~H)*R6m nhVE831D{lm-Y8Si!lvI6;>0X`wF z2TtFyS2HZLHdAnQYX<4?ba4#fxSq_>5w*3ev5JM^!yNgCr|&qq1LYVzUHx3vIVCg! E022Bfi~s-t literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0016.png b/assets/kenney/tiny-dungeon/Tiles/tile_0016.png new file mode 100644 index 0000000000000000000000000000000000000000..12634df1965cedd4504cd6e640bcaaf18eb63b19 GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF+0Z|$qa7nevi_a*IyTBozAcJ1E`!lvI6-$0X`wF z2TtD!N~p0{Gwhzd#kHp*1}N_D>Eal|aXop(EU9hN9^SvU<1f$uXZ6fNzyH5Y@0k5R zSDX3%zk2BfNoyT{ORh5eur~FF>i<;R!}`DNUn{QB`fcxE_>VtZqE0q}t?Tdq{c;Qs Xq;-U|=Q%h7jb`w4^>bP0l+XkKLT5me literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0019.png b/assets/kenney/tiny-dungeon/Tiles/tile_0019.png new file mode 100644 index 0000000000000000000000000000000000000000..8c1285f1d538d1db3017985c92f7d2c046928515 GIT binary patch literal 182 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF z2TtD!N~r0cy+uvirS85V3s5}N)5S4_<2vubjiL?)60H~4Z)crbd&TX9RN4s!%RgML zc7dx(rd?QZ*s}7D_xHn0a+7U5wKDRLSZ_18baOW=&aidyQJoZ|spI_jLi}e>)m)!R chLIci?-lCy)G~Z_0b0P|>FVdQ&MBb@0LLdhP5=M^ literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0020.png b/assets/kenney/tiny-dungeon/Tiles/tile_0020.png new file mode 100644 index 0000000000000000000000000000000000000000..6dfd70ed460f1691e397f8c4694c39358723e2a2 GIT binary patch literal 211 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFBarooSRPFq=vAm%)dPOYqU%M+4-mNIy{`njxg HN@xNAP9Iv2+n(oUlFl@`OQQAt$dXo1x4?9x;Jt#VLv&tVaTZTn!wuVitD!0&yeHillI!qZ(?= Z4291W<+6W#Is`PD!PC{xWt~$(69E0cI3xf7 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0022.png b/assets/kenney/tiny-dungeon/Tiles/tile_0022.png new file mode 100644 index 0000000000000000000000000000000000000000..4e9bc12913a6d89acf04d8ab8e303d04191690f4 GIT binary patch literal 173 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFP9Ix)#TY?g5?9~j_v|Uch#(f0Jx_P=dhHzX@HsEVzV7q$ZLc-+>0m*F_6jalg zRaq6BZyuFA6i`^mxSBJxu*E21K~I8k37bc+_LPN>xI%dn8?Nj~(r`;;U|7zftjzj2 R$p~m7gQu&X%Q~loCIFAkHF5v| literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0023.png b/assets/kenney/tiny-dungeon/Tiles/tile_0023.png new file mode 100644 index 0000000000000000000000000000000000000000..07921a67dfb5cfc3f999c9aace723f5ba49b3418 GIT binary patch literal 172 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFP9Ix)#TY?g5?9~j_v|Uch#(f0Jx_Y`ehHzX@=4fR|W_x_$Lc-+>7Zli%)l}1% zRj&pZ96oYXV+!Mv14oZ?o)Ty@mPz1A4;FFb@bT>sZek3SX<8_8(_wi4L-8*q<2`(n RrT`6O@O1TaS?83{1OSF=He>(* literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0024.png b/assets/kenney/tiny-dungeon/Tiles/tile_0024.png new file mode 100644 index 0000000000000000000000000000000000000000..ec6d9038d9427e5029989adffcf9244719cf3fc6 GIT binary patch literal 175 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFG`naXJsKQUX;+?b=+ip*$knf+E@}J5CY<<6v!6{PK U+isexJV!Z literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0025.png b/assets/kenney/tiny-dungeon/Tiles/tile_0025.png new file mode 100644 index 0000000000000000000000000000000000000000..da5f19ab6d811bd60c790129e3d128063e2eeb00 GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFCaWg1&EZikX%pyC)Zj?8Fm{sE h*lWHVMsHT`w%scbP0l+XkK!b?0j literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0027.png b/assets/kenney/tiny-dungeon/Tiles/tile_0027.png new file mode 100644 index 0000000000000000000000000000000000000000..1ce15f4bd0113ab76dc4c2edc9e981b26e1e2f5d GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF!lvI6-$0X`wF z2TtEn({>3;sOg@)g;)Mv8&KTD)5S4_<9c!gD+|y6dgDFpLjM=CMD*}$ocO?hqFq2c tIC-M6Q zy8!p!X+d`$lr(I+x!}$(H`bT_6)OD}t~whX<|;mYlc=0ysn2p$>X3`Ooq%68$7c=g zRsP367b{ho_{mOXZ4`}KzL?8kPKojE7JK~}e+!tainMF~zun{sw2r~k)z4*}Q$iB} DTn0=| literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0030.png b/assets/kenney/tiny-dungeon/Tiles/tile_0030.png new file mode 100644 index 0000000000000000000000000000000000000000..1b597ca6e0d98e720453e3dc7b8f06fa8978a132 GIT binary patch literal 138 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFzopr01luedH?_b literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0031.png b/assets/kenney/tiny-dungeon/Tiles/tile_0031.png new file mode 100644 index 0000000000000000000000000000000000000000..acd9203fac949b7017d811b70416022f2ec72f80 GIT binary patch literal 171 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF%F|CmRO1XQwIEHXsPcBFdU}9nuXA@U7U@($kX>4GexsW9( zVR}+h0E3c(Gvkp2CLm!DT72Q zhTMk6y(&J;ldjiue%ify^NuG5MN`zY7J7Y{p%#vsviH?$3D- x=P_PmJ5qD&qsfMIHzU@}yk5gloVG?%*8U)~s&LC|KNg@}44$rjF6*2UngAIhNjCrh literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0034.png b/assets/kenney/tiny-dungeon/Tiles/tile_0034.png new file mode 100644 index 0000000000000000000000000000000000000000..98076aaa3782544b292db531f0346e2470a6b968 GIT binary patch literal 196 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFNdXnac)B=-a9mIJXl4*+o4#d>$o4H;QrN`P zlEv7QH=773o0wd&>{Zm&6+OYhW_XEds>{KiD=Lmx88&!KSdi5r9l~!lvI6-$0X`wF zYT7PA2{i{!-|3#ch5bj%N}#xwr;B3<$Mxg~|Nj5CXZ~)laBzFoRV}t_7cK;_bx3qP kh<0tckw4*vRfhz_%UddqKJzTT0d+BWy85}Sb4q9e09(>7PXGV_ literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0037.png b/assets/kenney/tiny-dungeon/Tiles/tile_0037.png new file mode 100644 index 0000000000000000000000000000000000000000..1d2d96230f9939a5a4e803c3cb7d8fe54ccbcaab GIT binary patch literal 130 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6;>0X`wF zK?yYnPT%RCy`^MQ_d1}Uil>WX2*>s02v!!J)teezUR=2lz-G|U(b#bzz+~f8g^dPx aUNJQ7mzwx(p~5ksdInEdKbLh*2~7Zmz$nuI literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0038.png b/assets/kenney/tiny-dungeon/Tiles/tile_0038.png new file mode 100644 index 0000000000000000000000000000000000000000..96972bdad95702b438c42c322639c431a4456add GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zYT7PA2{i{!-|3#ch5bj%N}#xbr;B3<$MxhN|NsAIZu|ec@yM$1)n*1QZEb7@4o4i0 qtP0IY`t6vse!|gzjU87FN*Pww=-u@@Hb)$&m%-E3&t;ucLK6VVRWfP- literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0039.png b/assets/kenney/tiny-dungeon/Tiles/tile_0039.png new file mode 100644 index 0000000000000000000000000000000000000000..75667caf8396663091a458c6f5ef623e593a13df GIT binary patch literal 140 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zK?yYnPTx_}cIlqIB}@C76Hr{+)5S4_<9c$$zyJSr*$g(CnQZAwWMpO*Z`u9F&SQ;8 l=$rrL6Lv*}7^duH2%e_;^yY-+-+!lvI6;>0X`wF z2TtD!N~r0cy~WD^WCl=B$G#?H_HCY@uPA}JA^Pnkw^CM@nQE-omZ z&L*txrpC%Bs&LpbpfRw6b>_n*3zi&N(zJ$cev+yJgQq1IQzOR&#*L>X6IU9FFfdp( WiRtHE`Fsv&GJ~h9pUXO@geCw*?=t}a literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0042.png b/assets/kenney/tiny-dungeon/Tiles/tile_0042.png new file mode 100644 index 0000000000000000000000000000000000000000..4ac7fa5d4674bdd5aea2db89bf3c77d86a9c9230 GIT binary patch literal 142 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6;>0X`wF z=bJ(foWApFY0f9}*=vA;2A(dCAsp9}BUo8@JX~&E(crkqqBg_fPN+jtW(2eN1O}~0 mDYLDderu8<4qRzSVPGgcq_oJ%Ui=MEFN3G6pUXO@geCwMQYlLS literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0043.png b/assets/kenney/tiny-dungeon/Tiles/tile_0043.png new file mode 100644 index 0000000000000000000000000000000000000000..f12545f17ecb739713db1535ab3f949a21261734 GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF0rEGc$w2 yRE|PJHYV}#wg7Phj#Lg_#*6D5*hB(OFffP~sR$^X5~~2}XYh3Ob6Mw<&;$UU5i6Gf literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0044.png b/assets/kenney/tiny-dungeon/Tiles/tile_0044.png new file mode 100644 index 0000000000000000000000000000000000000000..3d05e584b9d54deb1459c79d6144934b10e67352 GIT binary patch literal 170 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF&JQ;qIDJP=+vU~L91Yvaw}5JFJzX3_IIbrLc=H+;`tf=vIV82r zu-NS+!FEQ$Epk;xMn*z}m2+g2hQN}g##5FzI$AncN_P0M8!c#XVq*|qW}IG}RiFtp Oh{4m<&t;ucLK6UoTQv*- literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0045.png b/assets/kenney/tiny-dungeon/Tiles/tile_0045.png new file mode 100644 index 0000000000000000000000000000000000000000..22e1625479e18413bb9b235627a6c52533ce9819 GIT binary patch literal 191 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF@|G= literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0046.png b/assets/kenney/tiny-dungeon/Tiles/tile_0046.png new file mode 100644 index 0000000000000000000000000000000000000000..1dc121302401c71aabbf1acca65c59c283232dda GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF@7hFHG6Zs)U;jf)eOt5%~m{?RRAjR@^okY|;|5r);CyoVP`@7hFHG6Zs)U;jf)eOt5%~m{?RRAjR@N{tu;kce$(8!?5rYbJ3E-EhW&Zg?- zsK)9jDBc!e5YS@C6f4ox+o&LV#DkgXGJ}M&2kTtMpvf9-XBag7cn`0XNHLng$Z+P4 W%I30dbB_YeWbkzLb6Mw<&;$U688F}g literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0048.png b/assets/kenney/tiny-dungeon/Tiles/tile_0048.png new file mode 100644 index 0000000000000000000000000000000000000000..6e59a442db93c1e92ae71baa4700f72b4461d7b4 GIT binary patch literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|WIbIRLo9le vYqpv^w`XQ;=oC7;n5{?3AnQPa5d%Z$2WF|S59Vk96*73b`njxgN@xNAQP~<; literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0049.png b/assets/kenney/tiny-dungeon/Tiles/tile_0049.png new file mode 100644 index 0000000000000000000000000000000000000000..c7d072220ac4ba39f4f4e917a362ac94e8c5cc5f GIT binary patch literal 130 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6;>0X`wF z|4z<1-xTs{Y0epiuwbB|il>WX2*>s02v!!JghiY_I?aXQO{&ulb%wrh5$n0i`mC&R aCqrwd=Au`Df4>0LGkCiCxvXbP0l+XkK D>hK)o literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0051.png b/assets/kenney/tiny-dungeon/Tiles/tile_0051.png new file mode 100644 index 0000000000000000000000000000000000000000..7bc6fe4fca04ebb91a4b912230bcd69eb0e0af1b GIT binary patch literal 133 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6;>0X`wF z|4z<1-xTs{Y0epiuwbB|x~Gd{2*>qg4pt^Mlcdy)D_U)#tHUx3&qQ&lgz3eyJ}PVM c2xZ}5xKO6-vqito8>ofB)78&qol`;+0AGwGjQ{`u literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0052.png b/assets/kenney/tiny-dungeon/Tiles/tile_0052.png new file mode 100644 index 0000000000000000000000000000000000000000..8a17adb905c541d752fa921bd058e355ec58ea85 GIT binary patch literal 122 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;OS+@4BLl<6e(pbstUx|nfKQ0) ztED;Tn?h91r|Sbn_v|e}2{mfkE+KzB41l7HB|(0{3=Yq3qyafDo-U3d9M_W*cv+hn+5$8Z zI7)+==*GAIB5 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0055.png b/assets/kenney/tiny-dungeon/Tiles/tile_0055.png new file mode 100644 index 0000000000000000000000000000000000000000..655077e7a7fdcc599ca98a3d8025e1fb33c3b58b GIT binary patch literal 182 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFgyVX0LIEQ)8=Dx%;l{?J zk(?Yp4Ls_}3IUFZGj{B-5KcI-)tZZ`k;8*!iLC1p&La$(WsEPGqE0_v|e}2{mfkE+KzB41l7HB|(0{3=Yq3qyah6o-U3d9M?^IHwrcw@G$#M z6pUb)#G16(L8j_l=ePLQ&CFR}zPGx#aPqq{xTwo`AFOihxHEfoitNHkcW0bU6j4YB zQ)s`KB&6^)gna|o?+bP=>$jfxQ~PJVbj%*zG_jtE>zspu)-ZUw`njxgN@xNA`P@dl literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0057.png b/assets/kenney/tiny-dungeon/Tiles/tile_0057.png new file mode 100644 index 0000000000000000000000000000000000000000..f9ad9b7a8b1f4bf86c93f137f274cfc053b2ef6e GIT binary patch literal 135 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF z_G*R)PTvVisOg@)g*id!CQw|>)5S4_<9c$!-K|-o%&*^F`0nuNe>Iz(0i)RM|JEWd ff7*qPtYl_5W2qKs-FIXvPzQsjtDnm{r-UW|9bzd> literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0058.png b/assets/kenney/tiny-dungeon/Tiles/tile_0058.png new file mode 100644 index 0000000000000000000000000000000000000000..e498583cd48154a58de49a4278c855ccd3d3156a GIT binary patch literal 140 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF z-LtnGIDN-n%`hmThHLW~SD?7Ir;B3<$MxihU;pbx4qq~UsL*8DmH1KeSujuc|Nr(! lH+)%T81RN+j)I>o!-q(f|4z47eFJJ^@O1TaS?83{1ORrrF2Dc) literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0059.png b/assets/kenney/tiny-dungeon/Tiles/tile_0059.png new file mode 100644 index 0000000000000000000000000000000000000000..f47e75b31c0759516f88073b203411516bc8bbb1 GIT binary patch literal 134 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF z2TtFyS2GMssOg@)MMLw$N1(W>r;B3<$Mxihty!|#hyUNNQFtUjkggElw&S=A_@1_n=8KbLh*2~7Yef+;Kj literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0060.png b/assets/kenney/tiny-dungeon/Tiles/tile_0060.png new file mode 100644 index 0000000000000000000000000000000000000000..ad4779c964526a6ca6d98880202f4983a3ba376c GIT binary patch literal 140 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;OS+@4BLl<6e(pbstUx|nfKP}k zkpBPw|I(ZD?*dtjB|(0{3=Yq3qyaf9o-U3d9M_W*5)w9SOkA-s*(0G@Ng*MJK~bTB hn@N;ms-Xb`L-$+O(+SrKCjr$nc)I$ztaD0e0szX0C4&F} literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0061.png b/assets/kenney/tiny-dungeon/Tiles/tile_0061.png new file mode 100644 index 0000000000000000000000000000000000000000..308dc05c4581cdad090fb49f49c2957297e5facb GIT binary patch literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;OS+@4BLl<6e(pbstUx|nfKP}k zkpBPw|I(ZD?*dtjB|(0{3=Yq3qyag)o-U3d9M_W*5)wB2KOFGCU$L=Q@otae`X0sS qlFrWz+n!`{=ml`CU|7-9$jIP*oR52QebQl|Mg~t;KbLh*2~7aw(=2`f literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0062.png b/assets/kenney/tiny-dungeon/Tiles/tile_0062.png new file mode 100644 index 0000000000000000000000000000000000000000..e679062718a6fe2f0a72b90c1c6941cf9e5f9736 GIT binary patch literal 152 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!D3?x-;bCrM;OS+@4BLl<6e(pbstUx|nfKP}k zkpBPw|I(ZD?*dtjB|(0{3=Yq3qyaewo-U3d9M_W*fFLCyz~X?y#|Fn`4UOlU8e`iI s?rcB!L7G2Gq;o>FVdQ&MBb@0DJ5&FaQ7m literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0063.png b/assets/kenney/tiny-dungeon/Tiles/tile_0063.png new file mode 100644 index 0000000000000000000000000000000000000000..11b5cf71609d5ad6d4aa5084e6093161aef86616 GIT binary patch literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF)z4*} HQ$iB}qf08m literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0064.png b/assets/kenney/tiny-dungeon/Tiles/tile_0064.png new file mode 100644 index 0000000000000000000000000000000000000000..c574d11af31b6ddda9e93d77209162885a2cae92 GIT binary patch literal 176 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF&t;ucLK6TgH8dgs literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0065.png b/assets/kenney/tiny-dungeon/Tiles/tile_0065.png new file mode 100644 index 0000000000000000000000000000000000000000..8dba4014920d461429e2df299895149d41ae5233 GIT binary patch literal 177 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFqYfLE@Z3+u{WaI9eV)Qfks_3V5v1q{ftbfPq22QMgQG Sdhl(aSqz@8elF{r5}E)2{WIMF literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0066.png b/assets/kenney/tiny-dungeon/Tiles/tile_0066.png new file mode 100644 index 0000000000000000000000000000000000000000..f5ae1b68cecae97380196051be0b9cbabf432a95 GIT binary patch literal 192 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFj~=J j4cdB(KX5A__Xj5XFp<*dTNAzkjb`w4^>bP0l+XkKD4agP literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0067.png b/assets/kenney/tiny-dungeon/Tiles/tile_0067.png new file mode 100644 index 0000000000000000000000000000000000000000..db9f646cb6369774a2432fc2d05b175d32a31e2a GIT binary patch literal 170 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFs0ga&3YadrhJqnHB> zM-0jsl_v1aczECeQ{oPT9U4;Fnv&d!sT@+=OcS}C3}dVXpD{3Ss*4vLm{8CNG=#y^ L)z4*}Q$iB}`zkF; literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0068.png b/assets/kenney/tiny-dungeon/Tiles/tile_0068.png new file mode 100644 index 0000000000000000000000000000000000000000..a03571a276fcf7f92ad928fbcb54798e1a0893a4 GIT binary patch literal 181 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFAdb&7} VmEEv$6CcPO44$rjF6*2UngG*tG4B8X literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0069.png b/assets/kenney/tiny-dungeon/Tiles/tile_0069.png new file mode 100644 index 0000000000000000000000000000000000000000..fceb76e2f5e6aaba944ea2d9f1e09bc89c77abd3 GIT binary patch literal 206 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF|3vM!Nt2 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0070.png b/assets/kenney/tiny-dungeon/Tiles/tile_0070.png new file mode 100644 index 0000000000000000000000000000000000000000..c77f8aed7ca9628282d50197d5314345e1bb32b1 GIT binary patch literal 170 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF7I$ zNGRasEoDq(Q`JZ?Xk%g%PfivWa9eTk@PWm#1|}f_ErQby&0%B^JTCt*%|bIDXaa+$ LtDnm{r-UW|xhgOR literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0071.png b/assets/kenney/tiny-dungeon/Tiles/tile_0071.png new file mode 100644 index 0000000000000000000000000000000000000000..9624f3f08a31ef2cce5557b851a4b1c4ed91be89 GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFXvKJ`CSQ6wH%;50sMjDV~t|^BWHn>MgSpkC^>bP0l+XkK D{bDH& literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0073.png b/assets/kenney/tiny-dungeon/Tiles/tile_0073.png new file mode 100644 index 0000000000000000000000000000000000000000..00ff065f14fb2cac96b831462acaee003311ee07 GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFXvKJ`CSQ6wH%;50sMjDV~;OXKR!f`!0L4kJ%17k-TqoIrg zk9u;lsKMczH*T=7ANKU*Ty)GeKwy>kQBIvEJ_eWfoJV3);-Z0i89ZJ6T-G@yGywoX CYAf;p literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0074.png b/assets/kenney/tiny-dungeon/Tiles/tile_0074.png new file mode 100644 index 0000000000000000000000000000000000000000..407e2d15ea883acb795d004fd407d3b8051642f7 GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFRyS1~jHGU2@oT2^M6KQep9 tbiMrgzYWH(l-#l>w(i;-X#DeUT-SZ^?E#xlv;Zw&@O1TaS?83{1ORP9MGyc0 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0075.png b/assets/kenney/tiny-dungeon/Tiles/tile_0075.png new file mode 100644 index 0000000000000000000000000000000000000000..4b91993ed01f3489f1d6ae899424f14f046e1c3c GIT binary patch literal 128 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zW!7e|mgd;28Sc&T`jGbHI#68R)5S4_<9c$0l$6xb4gdcCj}K^aW^`+5`{y)CAxM^C YcbiV>p6}Zjfl3)XUHx3vIVCg!0Q40mK>z>% literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0076.png b/assets/kenney/tiny-dungeon/Tiles/tile_0076.png new file mode 100644 index 0000000000000000000000000000000000000000..08f2649e9953dc0fc8d57232fc6b0453d1e9367a GIT binary patch literal 165 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF zY+~uc>;i0tF)CWdY2#kg-Tw7Ck@&*16m=d#Wz Gp$Pz1(JxH^ literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0077.png b/assets/kenney/tiny-dungeon/Tiles/tile_0077.png new file mode 100644 index 0000000000000000000000000000000000000000..4e67040855c245adf61de991a590c77546a18714 GIT binary patch literal 165 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF zY+~uc>;h>8g=U3}i7d{ZHv%|Y1bM{OMa2cwf(_5;F$k>_Z=SJ$?*vdkgQu&X%Q~lo FCIHSzDun<5 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0078.png b/assets/kenney/tiny-dungeon/Tiles/tile_0078.png new file mode 100644 index 0000000000000000000000000000000000000000..c395235642b37ce5ffa067aec63b29c14a3bdb01 GIT binary patch literal 165 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF zY+~uc>;h>8g=U3?j)@wa(ps9F%EmEsLShgdAc};a9mGLNJ!x2zZdCGx?M$;P-JPthK;>pS4Dy9_@6Ac)B=-a9mI3;7#D=s0fAp00i_>zopr0H>rX$p8QV literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0082.png b/assets/kenney/tiny-dungeon/Tiles/tile_0082.png new file mode 100644 index 0000000000000000000000000000000000000000..78f95bceab167e05e7e058c818b97360868fbdbc GIT binary patch literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFMd%8G=a9j`V-N@Tuz{8@u zu;&1i8S?@Q9S1vG!HWN(8z!^uv-&IQ?($4Io@bP0l+XkKui!-f literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0083.png b/assets/kenney/tiny-dungeon/Tiles/tile_0083.png new file mode 100644 index 0000000000000000000000000000000000000000..19e40a9aff0b93de87af396e1d953b640662a7c4 GIT binary patch literal 156 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFs0fAp00i_>zopr0H>rX$p8QV literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0084.png b/assets/kenney/tiny-dungeon/Tiles/tile_0084.png new file mode 100644 index 0000000000000000000000000000000000000000..83aef72945b2573f55cdb41c6d23469682f0b255 GIT binary patch literal 232 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF@f2!-g=WXG8)R2o?U}MV ad{2;-x!LSbiMBvH89ZJ6T-G@yGywq2ZBz6B literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0085.png b/assets/kenney/tiny-dungeon/Tiles/tile_0085.png new file mode 100644 index 0000000000000000000000000000000000000000..5f12f941754c1ef4533c85e90c91c447958f40c6 GIT binary patch literal 230 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFGnNGT1v5B2yO9RuWO}+dhHzYW zJ$sPzfC3L|K)>DvP8M;EDR}|w4m`~JQ+bXpXlde|kiaOy*6?S#N#H(bg@e`6LQ;30$lT<6DDG3HRbzGL zzE}5Og9($?@CACx&MOp~m5}&y>GpyH_pZ(TUTCELqtC$ozUC}}&0A+I%6n6=T90qX htksS0r^FcbiMxuLZ~DDG#|&sSgQu&X%Q~loCIE-DSq}gJ literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0088.png b/assets/kenney/tiny-dungeon/Tiles/tile_0088.png new file mode 100644 index 0000000000000000000000000000000000000000..94aa932d261e6e3ca28419aa48ff63335fc75dd9 GIT binary patch literal 222 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF)S_8Oioj~n>KOMb9d&zmCPr#Ya5jt+Qc+e zm}7RbecGhkSpQ6KzGb6P`6@D| m8J)V+(|h@nV^G2cMuvAA_0?lFujK-bWbkzLb6Mw<&;$S_yFKCn literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0090.png b/assets/kenney/tiny-dungeon/Tiles/tile_0090.png new file mode 100644 index 0000000000000000000000000000000000000000..008737e42865c10c82b4fac515350903ae898d73 GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFb`joEsG+PG~T5E@|GhvS{@1 x2rTBEIgyRcp)FGb=qkxng~pNzjR_YR8Tef+mvXXd-vOG=;OXk;vd$@?2>_jaL8<@% literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0092.png b/assets/kenney/tiny-dungeon/Tiles/tile_0092.png new file mode 100644 index 0000000000000000000000000000000000000000..906f46bdd70d0feb2f1826478502bc08f5995094 GIT binary patch literal 244 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF$6n2Fcc#gHpgP8qAirP+hi5m^ zfSf!}7sn8e>&Xx9@v=!vlsPjVewR7ZINk3wi&2`cnc21|PO-?XTsoVwPC99>4?WTI z?oH_GZEqP2x0JuX$CCEu9;1uHv7EOTF8EqI_FP^1aJNIxOykq1)6cOO*;t)AZ5`Fn mGu3!`__;Z(Mglx#%na8xd^hv*9)1e6nZeW5&t;ucLK6U|fLbyD literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0093.png b/assets/kenney/tiny-dungeon/Tiles/tile_0093.png new file mode 100644 index 0000000000000000000000000000000000000000..4914e05d6878e668a06c197369406492233e2c7f GIT binary patch literal 205 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFD_jz1M>@9Kb}knF`FQ<0 xZUNrI`wz`LRwnQ!Wv}DGxnEC-&C@FS%xrK(y6jdm!%v_k44$rjF6*2Ung9huNVot1 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0094.png b/assets/kenney/tiny-dungeon/Tiles/tile_0094.png new file mode 100644 index 0000000000000000000000000000000000000000..c77f8aed7ca9628282d50197d5314345e1bb32b1 GIT binary patch literal 170 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF7I$ zNGRasEoDq(Q`JZ?Xk%g%PfivWa9eTk@PWm#1|}f_ErQby&0%B^JTCt*%|bIDXaa+$ LtDnm{r-UW|xhgOR literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0095.png b/assets/kenney/tiny-dungeon/Tiles/tile_0095.png new file mode 100644 index 0000000000000000000000000000000000000000..95b220bd5c5cdb2291ad50fdc9c445d4c2055791 GIT binary patch literal 203 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF1Z2$FucO+F_VXa$3(tDnm{r-UW|U<*d6 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0096.png b/assets/kenney/tiny-dungeon/Tiles/tile_0096.png new file mode 100644 index 0000000000000000000000000000000000000000..ed3029baa32c0dbbeddce39af22a41711c50d74e GIT binary patch literal 206 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF|%! z#LH{O%geyoA|buIsl_R@r+4lF9&v>R11Be^3lajFVGGh0Ff#HiJg9c;*tum3c@}!< xxt-GUQgBq22WQ%mvv4FO#nt(KYaiI literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0097.png b/assets/kenney/tiny-dungeon/Tiles/tile_0097.png new file mode 100644 index 0000000000000000000000000000000000000000..b0106b2d4119b8cb9a6953aee95cbf3bfd513a3b GIT binary patch literal 225 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF_!@plj7;(7{YPg z^{gRZg91<~C}Gt>4f z8)_0(CYql!k-2tTeDUWCuUW2yaFli%stc&arOy*dzt7JV^N{P)n#sO5_4!ZQYsa2k SFK!96kHOQ`&t;ucLK6UrXi#tf literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0098.png b/assets/kenney/tiny-dungeon/Tiles/tile_0098.png new file mode 100644 index 0000000000000000000000000000000000000000..339537161fd724115f0906cceebfd5351188acde GIT binary patch literal 238 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF#bKvxy?}wW9=6Knw8P;$c9000dED7=pW^j0RBMr#O^K@|x z;kcfh;LtGBfnkxQV-Kf7qo=IwEQN(LrDSD&6WrWg-C1W`jEjroOPkU?y}McRosynX z!ZDHWMg9uS#Zk}B%)D%*Zg6JKv^mq#rddu-Oj}WyHKS0Y!*KE9#llBsSeh1Psa%Ni fTi~_e7biolnLh8nxmlBdHZyp-`njxgN@xNAO21I9 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0099.png b/assets/kenney/tiny-dungeon/Tiles/tile_0099.png new file mode 100644 index 0000000000000000000000000000000000000000..2278e3aed6295369a196e7701f2fb13d55563a44 GIT binary patch literal 238 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF{l_lxS$;ogl%WB4)72y-0%L>B}I62iuP>dni5sA9wqQcCq~z z1NT@6SFN96><~YJNA-yCiIwIyE4JFn+zhC_5VoIf)#^s`S<7xqtnfS*DSLi{KVO_u g_ugI+N%3jo(=?1Smy3nm0ou&q>FVdQ&MBb@0N++qd;kCd literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0100.png b/assets/kenney/tiny-dungeon/Tiles/tile_0100.png new file mode 100644 index 0000000000000000000000000000000000000000..be9422cd4275e5225a5674f0c8b3d4b458188dd8 GIT binary patch literal 240 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF_x`Z(k;_>gqJi(JbkM7R90c;C!y~}3uN4@cTTFRWSwv^Xv(y(cZ^9p zIMuouBvUi9GUXCXGc#X0n9Alp^zvFNDa#|9xpLvM#7qUZ&4n9XjV4^YC?zG8c#+Y> g(&UQCp+$@gSH!et99pC?186;ir>mdKI;Vst0DL}EQUCw| literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0101.png b/assets/kenney/tiny-dungeon/Tiles/tile_0101.png new file mode 100644 index 0000000000000000000000000000000000000000..48971500c861b59da583ac1645f7b13feca5ef88 GIT binary patch literal 159 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF!lvI6-$0X`wF zK)QSOmIJ5n*sB?8F6{aPmdKI;Vst03}{9n*aa+ literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0103.png b/assets/kenney/tiny-dungeon/Tiles/tile_0103.png new file mode 100644 index 0000000000000000000000000000000000000000..23f289dc9eea6963179597422174c8d59f3630da GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFzOi{K*#g(8g-ZUFnGH9xvXFfk literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0106.png b/assets/kenney/tiny-dungeon/Tiles/tile_0106.png new file mode 100644 index 0000000000000000000000000000000000000000..905ebcb69e0265502b88f098c37330228b0df6a7 GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFs0goK2G!bApUF>!Hr zgTqHpvM4=Sl;R_J*pu~?L0hLqmxF{(pAz4SX-;z(8Fn=AvRqC}y#&^J5FD3v0 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0107.png b/assets/kenney/tiny-dungeon/Tiles/tile_0107.png new file mode 100644 index 0000000000000000000000000000000000000000..86517222cae4ca77ccb0b6a64b2dbb623d3e310f GIT binary patch literal 173 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF#JzX3_IIbrrBqVU~rZO;J zyKsTQK-uJoh?2;wBp<70(IXrT#!Rk?JqoUhp&cF_+DG^Vn6CzP7&CnA6JnhC?wUK$ O5C%_IKbLh*2~7ZjnKDuU literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0108.png b/assets/kenney/tiny-dungeon/Tiles/tile_0108.png new file mode 100644 index 0000000000000000000000000000000000000000..7b6f8efddb904da5468d8aee5ece1b673f2e3156 GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFjEKJZ>bK|0`ok_Ptzb=wL4(u%5a^UEK-O1Y`T)L$XC$m+rwA?-P7l?QBuj|-~L zGnoCOMZBiGZ}o!JuRb95{VvZ;qF}n&GUTJ2!wT7)yfuf*Bm1-ADs+QaoK8 zLpZMcp4}+eV8Fq8VN1>;=@%S)6GZoH-lF8EP@-9M>VBAqRQ*>zzB(_KDU_G7w-npq=@-?FYNdDdwbk0tMa&Rcj4i8wnZROE2D+@D_chL2|M{s$CgED7=pW^j0RBMr#0@pN$v;kcfhaDXYo*_ru3 zPk=&$fk^8GNyT*mZW}T+TqbWcjF8Um*tk)<<>8~IV;rT0jS{@(l6m4R3=AC70!-I? SZaV|bVeoYIb6Mw<&;$SwuQmMu literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0114.png b/assets/kenney/tiny-dungeon/Tiles/tile_0114.png new file mode 100644 index 0000000000000000000000000000000000000000..54e4df45f7941342d9b6d8ddb977d79ae3f76130 GIT binary patch literal 182 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF*y~vR5-)Wcwr^D92b5bNX>G?e{Joncc+DmA#90^^ Y_6Uldki5Dw9%v4Or>mdKI;Vst0Ma`-mH+?% literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0115.png b/assets/kenney/tiny-dungeon/Tiles/tile_0115.png new file mode 100644 index 0000000000000000000000000000000000000000..00e3e0de60ab3555ba48a3daeef0dc23402ae9be GIT binary patch literal 182 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFBi~P+y{D!6dDYC=3JC)eH7p}vC7gVI71^sx;io=!>VQCw6mdKI;Vst05DWLvj6}9 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0116.png b/assets/kenney/tiny-dungeon/Tiles/tile_0116.png new file mode 100644 index 0000000000000000000000000000000000000000..caae164ef4e551a8022a94f39a2bc3a690266520 GIT binary patch literal 182 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFbNX>G?e{Joncc+DmA#90^^ Yc7GN-QM0G)I?x;jPgg&ebxsLQ01`?&U;qFB literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0117.png b/assets/kenney/tiny-dungeon/Tiles/tile_0117.png new file mode 100644 index 0000000000000000000000000000000000000000..eaea357b88d3459b47d7c097166a7d2492e45eeb GIT binary patch literal 191 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF%i$d_G*T!%U5m!$}yG%`2{mLJiCzw;UZ(1yw8GLuhZfID`xEE+3gQu&X%Q~loCIE6$Js}(6!WP1{Ok$mEM#3h^6AlXm qCNOSlYSg{Sj_K`ncHjvP7N7p$LBIq< lg|`b8iX9XfPI8qnFid$Me!N8TiYm}(22WQ%mvv4FO#m^!Jt+VH literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0121.png b/assets/kenney/tiny-dungeon/Tiles/tile_0121.png new file mode 100644 index 0000000000000000000000000000000000000000..fca32b86583458d80e9991ddfa0c4bb46f515a39 GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zK)QSOmIJ5n*sB?8F6{aPlvnNYdpH$m9z_JG=rzBpUXO@geCxYB1cjH literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0122.png b/assets/kenney/tiny-dungeon/Tiles/tile_0122.png new file mode 100644 index 0000000000000000000000000000000000000000..179f42fd15adf76dc8478ed3afa98aa3de55d26e GIT binary patch literal 232 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF_!@plkMr^7{YN~ zw`U`7g8>gqY!$Ox0?UmCpN5Er6S|Bir%Y`4ko=i3X72m9;;l@QkstaKnymGl-URJ- zYnr=~x3%H2?UmUZi{qb5$=<$j{lv1w-EjurKRIsR!?64NA^lX-?#&!Kq+C{5h=fFH Z$_YL+3y%LbDFtXPgQu&X%Q~loCID4ERh0k$ literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0123.png b/assets/kenney/tiny-dungeon/Tiles/tile_0123.png new file mode 100644 index 0000000000000000000000000000000000000000..be4b83e82e6f4222d985d9dc572a76b4eb7c757a GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFbY!u+Kp$gZ(NnN<8FH2jO`}M4?Q$?7mCcA sțBQEG@y+q^ojjn6|!d}-f$`^`O*trF80_|Y%boFyt=akR{0JfGvKL7v# literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0124.png b/assets/kenney/tiny-dungeon/Tiles/tile_0124.png new file mode 100644 index 0000000000000000000000000000000000000000..3fe67e4f8e6b4c8d240006eed2aeadd953eb95ca GIT binary patch literal 203 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFH#Z=BaCWM=$*gi~h;@D_chL2|M{s$CgED7=pW^j0RBMrzg^mK6y;kcfhaDXYo*_ru3 zPk=&$fk^8G$z#U?+&Z*d4oc-nH5}t8JbJPr@*u-jMlOc@Gdz9ix4eD>H8Xg+`njxg HN@xNA?`|}z literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0126.png b/assets/kenney/tiny-dungeon/Tiles/tile_0126.png new file mode 100644 index 0000000000000000000000000000000000000000..d28ba06e8ed521dd0feebf6e4ebc4417da02d755 GIT binary patch literal 171 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF!)A$S;_|;n|HeAjibEb06p_QfM%6in%Cx>{x)?LW`DzaZBPFj%j!wKiLp@kYOt$7sIXjf}NAMNL&YM OX7F_Nb6Mw<&;$VIvpLQH literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0127.png b/assets/kenney/tiny-dungeon/Tiles/tile_0127.png new file mode 100644 index 0000000000000000000000000000000000000000..20e0cc9de0e1905c279c39e285f8907d48c1982e GIT binary patch literal 171 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF>t literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0128.png b/assets/kenney/tiny-dungeon/Tiles/tile_0128.png new file mode 100644 index 0000000000000000000000000000000000000000..208da4d3739972c61397cd95c4dcbeb9a62db7dc GIT binary patch literal 171 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF3#axs;b}Ybcp+(EVxFvB7$27c;pKORc$gq`>i{aLM!OqEBB(4KB OGkCiCxvXEal|aXmR9A%TN8m4W%% zg$oQE$~Qy~aqyb8o@lk2y}&qR&Vn9?K#pe9Bc=@E${wQ2Ma~3u7&FAO@|$Tc(7XUN Ogu&C*&t;ucLK6VMxiA?3 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0130.png b/assets/kenney/tiny-dungeon/Tiles/tile_0130.png new file mode 100644 index 0000000000000000000000000000000000000000..2cf4d02cbc484588564ea94500ca5ec3fb2ddd25 GIT binary patch literal 185 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF;=Xla~AYC1adT+9uYmoQQGL$dO$*NodMgGt_uR!8A7}j b&oMAeY805Que(4FXdr{9tDnm{r-UW|YFapZ literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-dungeon/Tiles/tile_0131.png b/assets/kenney/tiny-dungeon/Tiles/tile_0131.png new file mode 100644 index 0000000000000000000000000000000000000000..ca4935b15f54a89d56a4d80d34d99aace21eb480 GIT binary patch literal 181 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 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Sample.png b/assets/kenney/tiny-town/Sample.png new file mode 100644 index 0000000000000000000000000000000000000000..10e4a71b5df4cf3164fd8d65e47d8f7e4170bd38 GIT binary patch literal 112122 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 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0000.png b/assets/kenney/tiny-town/Tiles/tile_0000.png new file mode 100644 index 0000000000000000000000000000000000000000..e743c54239ad02d5d34f9b8ce3c98d5b9e4c8feb GIT binary patch literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|WIbIRLo9le vb1bL*oZrZFz@_t9AhR2!lvI6;>0X`wF z-8X7emxi?*%dGRu=L8BGdAc};a9mH0U}fRqo|SOqQl>*vs8|Ps=bET#tSVuLc6uCX oQfr&3kaTm^(#sA>kqMj(F(DdjlViLEfw~zyUHx3vIVCg!00E~dC;$Ke literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0002.png b/assets/kenney/tiny-town/Tiles/tile_0002.png new file mode 100644 index 0000000000000000000000000000000000000000..8f24c62e833011bf2dc2e2025dc636f6c10a54b5 GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF&`~?G-pTOq-KFjO^ zKVNQc(cZ$``%ai~YT5#WSJ%T!8!lvI6-$0X`wF zK>Bf;#@~Ix_G*T<3O>O=K4VFcUoeBivm0qZj+3X0V+hCf z-`n(rgnwJ*JnlsCr^zNH)J^483UlWCH~pr(#E!lvI6-$0X`wF zK-zu2SIezhDN3XE)M-97j(V#}JO|$q5N|2Y}!|qsNW^j6!AA z4M+C><>5KA{~B{=w8Eq3znFQ>tPgAM$kFKjfAtkV&!5#{e;EZ$3$C#?c)I$ztaD0e0sv!lvI6-$0X`wF zK-zu2SIezhDN3XE)M-oN!MU#}JO|vd32QHW)CtUYu><;QmU4 zmvfn1+Y31fk*0JjCY^%+LKzQyG6-PpTUe_w!F6W6oEXrL7gp00i_>zopr01hlZ8~^|S literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0006.png b/assets/kenney/tiny-town/Tiles/tile_0006.png new file mode 100644 index 0000000000000000000000000000000000000000..20f607bde5f64c755f96ec56ab51fa8451558b49 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF9Luy!lvI6-$0X`wF zK-zu2SIezhDN3XE)M-9DPq0#}JO|$q5QfAL9LuyP67EK(ToVTi{HgXbKr|M2{0dNru_VYZn8D%MjWi&~+0(@_gyVYX>C?On3Oq~~A%md`;K~hS`>s5%d|g;1b9FEqwq3=U$$;8X9HLCvF2aQ#tRswwk>3Ce$DhP Wg)bqYD5M5x9D}E;pUXO@geCx#gE=Gs literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0010.png b/assets/kenney/tiny-town/Tiles/tile_0010.png new file mode 100644 index 0000000000000000000000000000000000000000..1aa04494bc9c6ae74d40b617ae5791c5120fa78e GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zK>Bf;#@~Ix_G*T<3O>O=K4VFcUoeBivm0qZj=rahV+hCfgTe~DWM4f@GUQJ literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0011.png b/assets/kenney/tiny-town/Tiles/tile_0011.png new file mode 100644 index 0000000000000000000000000000000000000000..b1b7842312500eb5442775c32b580558f763cba7 GIT binary patch literal 185 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF|M2{0dNru_VYZn8D%MjWi&~!_&nvgyXvFnTvu46gZdz+Fr1{ zVrgUCq5S)Ni0{fzU-_JR!VYWv*ni0N?t|8s>CRehI|bx}L^E2nW(i1hhQ{=~x$&}H c_Vwks{@MI5^QYR&0L^6ZboFyt=akR{0CrM7{{R30 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0012.png b/assets/kenney/tiny-town/Tiles/tile_0012.png new file mode 100644 index 0000000000000000000000000000000000000000..c664900e1e03a95325eb272b10ff5a5e61b1468f GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFnri(?4K^<;xKCbpEeiIX->6q=B@|ki*nDCH^jpvw~K^x~B#U{l^2bdBy4ojTtQ?l6VEWvQDQ07DEQ=4+2K@6U*elF{r G5}E*4p*D>G literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0013.png b/assets/kenney/tiny-town/Tiles/tile_0013.png new file mode 100644 index 0000000000000000000000000000000000000000..47bec7894f1a6e86d1c0edae8bbc4f972af6a894 GIT binary patch literal 153 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFbni(?4K^<;xKCbs0{R1Rm)n~|QLH$6HJ9`!tV x^r+|2)`P5E4m|GS?Cydc9m+k7Qx~x@GkBks_dECb_j#ZJ44$rjF6*2UngC0-G710y literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0014.png b/assets/kenney/tiny-town/Tiles/tile_0014.png new file mode 100644 index 0000000000000000000000000000000000000000..20737fcec3cef4015845b523141baa9d1491da26 GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFnri(?4K^<;xKCN>La&zl~el1B;(g9;0oHc80D zHXPtoVPY$2GwONBlWJkLxYJ_80ZBK3w#6Nses3Mv7HgQu&X%Q~lo FCIEsFGQ$7> literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0015.png b/assets/kenney/tiny-town/Tiles/tile_0015.png new file mode 100644 index 0000000000000000000000000000000000000000..d6302ed38578d74750a6649fbee9a74939a4d561 GIT binary patch literal 193 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFoHHmiGc#lC-od~a!ONyBa)d$ZgaB7cYnzb)Lo1W3Ba=he g1g#mz4mB_^7)nVh-xh0}4m6j+)78&qol`;+0Oz?fvj6}9 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0017.png b/assets/kenney/tiny-town/Tiles/tile_0017.png new file mode 100644 index 0000000000000000000000000000000000000000..4889f5b49315ad1241238ac57e1580c06a0424bf GIT binary patch literal 177 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zK)U5vru%#^do{x)N=9pde8!R>zhDN3XE)M-9A{4##}JO|$q5b2|Lh$O{j;C&L%P19 z@nQCt|NK1n!~Xw2{NeT2>s4+4*Uvv@d}Du|>HNl@UtfP!cx2!4gIR@7;Y9Luy9LuybP0l+XkKP`W=@ literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0020.png b/assets/kenney/tiny-town/Tiles/tile_0020.png new file mode 100644 index 0000000000000000000000000000000000000000..33d8690520349a9db20639d3b40aff8e193c86ba GIT binary patch literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFgnPb!f`#hAhCf-oL$42Rc%R2 zg2U6EkOe%d5{D(0-HMPr70_hdlNfaDMV5e)T0k4e6)uK^SsV{PT{E@<8o=P`>gTe~ HDWM4fl@Tx* literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0021.png b/assets/kenney/tiny-town/Tiles/tile_0021.png new file mode 100644 index 0000000000000000000000000000000000000000..f39998d9d5415794e49d5b61d96e20a1cc0355c7 GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF|M2{0dNru_VYZn8D%MjWi&~$kW9!gyVX0LIZ=i##yH19TtZr zju}Ww9G0B>kSSe5`>=$8psIy4r`pmMy+=z}HXjmX;MU@>o~teK9jKeZ)78&qol`;+ E05^awod5s; literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0022.png b/assets/kenney/tiny-town/Tiles/tile_0022.png new file mode 100644 index 0000000000000000000000000000000000000000..e7e722a0c21105aaf68c5f99134cb5eb85326b21 GIT binary patch literal 200 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF|M2{0dNru_VYZn8D%MjWi%9+|$J|gyXvJxs9R+6nLB+MI{?K zd4v`C1vY$}uW4oySbDX->B>n>N25zZdZ#rVZu%H(JnMFF>#Ri|n9escxVoFJ`s!@9 r$u&edy6l2})0aaWe)rqT^4IXI{+IZvWXU85w1UCY)z4*}Q$iB}G_64y literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0023.png b/assets/kenney/tiny-town/Tiles/tile_0023.png new file mode 100644 index 0000000000000000000000000000000000000000..14ba8d16985414727a86b3c97fd1639e5002d3de GIT binary patch literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFgMDxk@@Co$;Qi!1>pwSYE`D_jf-vp61px@K$zG=Ra=)z4*} HQ$iB}y|plS literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0024.png b/assets/kenney/tiny-town/Tiles/tile_0024.png new file mode 100644 index 0000000000000000000000000000000000000000..7fec97cbc101e68a31f213a472c968c9bd4dc8ea GIT binary patch literal 135 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zsY}DoH-)qu%Y3yor)_3W3s79m)5S4_<9c$$-~a#X*;qDmxU69o)D{r>9yq0;GxYmI fuXTqx6~r0%-daAHBVlL*)WP8C>gTe~DWM4fLOv+H literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0025.png b/assets/kenney/tiny-town/Tiles/tile_0025.png new file mode 100644 index 0000000000000000000000000000000000000000..6e59a442db93c1e92ae71baa4700f72b4461d7b4 GIT binary patch literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|WIbIRLo9le vYqpv^w`XQ;=oC7;n5{?3AnQPa5d%Z$2WF|S59Vk96*73b`njxgN@xNAQP~<; literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0026.png b/assets/kenney/tiny-town/Tiles/tile_0026.png new file mode 100644 index 0000000000000000000000000000000000000000..36b21a01c9a8d810a90d69f16cda30007034f421 GIT binary patch literal 140 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFYm!fHCisQ2tXR5X+r&OihXl4?v#JlU?%_~qImQ0p iy!^<)y29MAj~IiC1_OfJ10LoBHdai+ zGyE>Aa?tHe&t`mYZ_u#o*?}A43KkEX+%9*o i-+71sT6ghjar0=An znJ|m@ga-rnlD4+S)=MtVOo}}hE(C1YWHLPv|{ZkQ9~OOgIh8G VDW;CURY3C?JYD@<);T3K0RZ)XHlhFk literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0031.png b/assets/kenney/tiny-town/Tiles/tile_0031.png new file mode 100644 index 0000000000000000000000000000000000000000..f857d7215445b6fdef52acd2282c89d4063201c7 GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFA{Y{UMWepG(k(9&(TYl6@Y5kgTe~DWM4fVT3r) literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0033.png b/assets/kenney/tiny-town/Tiles/tile_0033.png new file mode 100644 index 0000000000000000000000000000000000000000..19423730d04f5f8c13a2b173785ab77c88045538 GIT binary patch literal 181 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFnY%5TRu_VYZn8D%MjWi%f$J50zgyVX0f^9-0+10H wRMcqDz`%a^$kC&cM-t4;M9j<*7FaPbybj=ae(!)66a<(L>Njzv zXjKF@*oOT#{iyu7p{3hw*94&*B8q|u3%f%ZPsyL*|Et=*aQREKLq9h*bK4~7RD}8Z XPvEcfQoUdWG>^g4)z4*}Q$iB}kGVN7 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0036.png b/assets/kenney/tiny-town/Tiles/tile_0036.png new file mode 100644 index 0000000000000000000000000000000000000000..483b603f589640a686303f36b4f8acd64fb630c4 GIT binary patch literal 154 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFCYLlrr;laSY+Oo@`)N$jHpb(kywbpv{m+#&to~10Hoz ylUOysfVPd?Y|LvsSWhr)n&a!BB+zh@fnm}K*=279LOOsZFnGH9xvX!lvI6-$0X`wF z|4z<1-xShvEc4aUoOSI6j6iW!PZ!4!j_b)k_*r<42(~Xga)1AI#iak&{@*^o;nmeu fp**X@961^G*;}1Y;OyNG)WG2B>gTe~DWM4fuW&4w literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0038.png b/assets/kenney/tiny-town/Tiles/tile_0038.png new file mode 100644 index 0000000000000000000000000000000000000000..8b786b641a2c1917b5b5240b7e7e18ea129c6bcf GIT binary patch literal 149 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFDfi(?4K_2dFZ=JaGXlQzYkM5aWGl^lm9B)Vh` swn{4-&QUOO5KI>q$UT$5!#ab9;fcLm!^0O+9ze|up00i_>zopr0LhFiw*UYD literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0039.png b/assets/kenney/tiny-town/Tiles/tile_0039.png new file mode 100644 index 0000000000000000000000000000000000000000..ba565dae10b923fb45856d5a0e72abd3821ac8ee GIT binary patch literal 129 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zsY}DoH-)qu%Y3yor)_3W3s79a)5S4_<9c$$-~a#X+d>tbxLss+@T>f5j);GFq+W=F ZA>YgP!ifj}J^p-|_s^yqq^76wmOKbLh*2~7YhC@K;F literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0041.png b/assets/kenney/tiny-town/Tiles/tile_0041.png new file mode 100644 index 0000000000000000000000000000000000000000..f57be4232b7108b0f719a3d8e2535637c85bcedb GIT binary patch literal 126 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zsY}DoH-)qu%Y3yor)_3W3s79v)5S4_<9hNBeij}TfsX}DNB-`UIugaIw8i0wHp7vv VHqS)MbwCOkJYD@<);T3K0RXVqB+dW; literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0042.png b/assets/kenney/tiny-town/Tiles/tile_0042.png new file mode 100644 index 0000000000000000000000000000000000000000..4e06403d2708b4813fc952feab168c728280fe34 GIT binary patch literal 137 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFv=d_2B?9-)78&qol`;+00!wO@&Et; literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0043.png b/assets/kenney/tiny-town/Tiles/tile_0043.png new file mode 100644 index 0000000000000000000000000000000000000000..cf9b5629a28b24ae95a65eb2a54c264f092c7065 GIT binary patch literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6;>0X`wF zsY}BSoW9d?EOU0!;Yy&Oho_5U2*>s02v!!J)oG0#Qztq!87GMzHad4gr!7?5VzR`v zWo~PkgeC?GBsFSHm@#u}Q+Hx&(<`7PcSxg^kVr$zH6sN^76vX+`HfGNHTD6`WbkzL Kb6Mw<&;$UuM>2*0 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0044.png b/assets/kenney/tiny-town/Tiles/tile_0044.png new file mode 100644 index 0000000000000000000000000000000000000000..4a0799d315f6e618b1f3d6c7daee38a66f849d62 GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFXvKJ`CSQ6wH%;50sMjDV~?CIhd!f`!0;Q&)aOpMF{9&v>R zgPvYNo(&RB3zsa($>}*{U=|V-afVmqDL&RGcO*l^+NHb+9{3ftB TUo1imXc&X1tDnm{r-UW|Zdx(G literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0046.png b/assets/kenney/tiny-town/Tiles/tile_0046.png new file mode 100644 index 0000000000000000000000000000000000000000..1ff37186dbdd19806031397bdc7f8b2ebcf6fc2e GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFXvKJ`CSQ6wH%;50sMjDV~?CIhd!f`!0;Q&)aOpMF{9&v>R zgPz`4g&LE#jT!lvI6-$0X`wF zKzeVE*Q=#D_G*S2O6R5m`HUq&e!&b5&u*jvIZB=`jv*Y^lM@^me%m`d`d_c`G252w lqp6%*&Fuc>4Y!#U8U9p@?Aja422{+z;OXk;vd$@?2>^q?C@cT~ literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0048.png b/assets/kenney/tiny-town/Tiles/tile_0048.png new file mode 100644 index 0000000000000000000000000000000000000000..3d500133b9d801695ef5fca76f77a236facea0d4 GIT binary patch literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF z2TtGVp1s9h%`hsnL$&lz>% literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0049.png b/assets/kenney/tiny-town/Tiles/tile_0049.png new file mode 100644 index 0000000000000000000000000000000000000000..fbe1d9f74be050e526b2de28ee76bd8af0f7d1a9 GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF z_G*R)PT%RCy(KEM!~Ri(3Q*j^)5S4_<9c#JLvw&aLIf)d&;Q1T#H*|C?ruD??>^7W z?W@X-WB&j8Zte2u?(VCrCGNdv7J7eA?|jORc=>wSh0F}=EVOM|OD_2V&0_F$^>bP0 Hl+XkKw{tgr literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0050.png b/assets/kenney/tiny-town/Tiles/tile_0050.png new file mode 100644 index 0000000000000000000000000000000000000000..c17255cafc37b9484eb8e8064874c828aa71eacc GIT binary patch literal 171 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF z2TtFyS2OIMy(KEMLuB!lvI6-$0X`wF z2TtGVp1mb1v%_A^(C6xROQ5)$r;B3<$MxhN{46{POgxAF|KERV!@vLk<9UAa@Z6X9 zFVdQ&MBb@0FT!+NdN!< literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0052.png b/assets/kenney/tiny-town/Tiles/tile_0052.png new file mode 100644 index 0000000000000000000000000000000000000000..f94e72d7979b58daad8cbf6de9df13dfff813bda GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF}`73MEx01*4NX;F@)o~Z`VQ20|q?ItVfwkTKxnJ?j2y3 zX!#z$lxexicY))IPuTX`Fn^MpV5<--EvTGx@>iGVs<#%CzZ8Ub>Za_B^*$;U`}}69 ap#Hke@;NMPLKgxJX7F_Nb6Mw<&;$TsMm`h( literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0053.png b/assets/kenney/tiny-town/Tiles/tile_0053.png new file mode 100644 index 0000000000000000000000000000000000000000..ce3488793be62e6bf9b1f66fa62588061287b084 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF}^^wQ*aSb*4xv?F@)oK>Y0PQ2Mjoz1J_>=U1i{C-f@QM z#GCzIolTdV@1Jyve~@YMILl&FqsZPj3rl(=x0G_8wpM=I9r{9L)oaC2TeVfuTmRbc YKXFaoTfv{F6=*Djr>mdKI;Vst0PcE0U;qFB literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0054.png b/assets/kenney/tiny-town/Tiles/tile_0054.png new file mode 100644 index 0000000000000000000000000000000000000000..d04ac27fedd9c6585584d2bbfa2ef29dbff97b95 GIT binary patch literal 181 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF}|R?w|yH>*3Z+$F@)oKXwN~;0|q?Id!52FPB4kyJ0N@` z}_hVW;nf<_aIO~kf)1d2*-8XE=R!w1{^Fu6%^SnX=E&J zxOat-&+5l?0R^9LTg|tpu*z0)9TNY|{<3b$tfPr%Q!lvI6-$0X`wF zKzeVE*Q=#D_G*S2O6R5m`HUq&e!&b5&u*jvIVzqmjv*Y^lM{YyZEs}sdc!Uh|JrfQ nSB)drDkj+ecfp#W!UHc*tYB*-tA!Qt7BG$1F@)5S4_)c$l zthA4GG4wE&!lvI6-$0X`wF zKzeVE*Q=#D_G*S2O6R5m`HUq&e!&b5&u*jvIjWv6jv*Y^lM^;XpFhB$_^+{J|3`;M o*Q-PxW!v=p*e1vRkw1%zp=+mjl-#<8E}#YmPgg&ebxsLQ08>*dY5)KL literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0059.png b/assets/kenney/tiny-town/Tiles/tile_0059.png new file mode 100644 index 0000000000000000000000000000000000000000..b86df4b484d52545b92160093b7da769d48a9968 GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zKzeVE*Q=#D_G*S2O6R5m`HUq&e!&b5&u*jvIm(_cjv*Y^lM^=FK74>d@!wl^q5anu n3&cN8JhJ_#1;+-n8JY|;62#uWeCM(TsGPym)z4*}Q$iB}2n#F5 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0060.png b/assets/kenney/tiny-town/Tiles/tile_0060.png new file mode 100644 index 0000000000000000000000000000000000000000..f8e8441efeb306c0b9d9a8b34f66bce6e8c43c9a GIT binary patch literal 177 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFEG+?C#_^{Bs^9BL?+H;T^8-lc3p0c&PvD12A%48+t}@PHedc3+-GaC?k4xw X8HzXgck^)qO=a+O^>bP0l+XkKN8UVY literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0061.png b/assets/kenney/tiny-town/Tiles/tile_0061.png new file mode 100644 index 0000000000000000000000000000000000000000..4b014cf6faf461585b3f7d168a31285c766d2f3e GIT binary patch literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zW!7c~PT%RCy(KEMLv)(^2cWpCr;B3<$MxihuUYr=+s;H^-7UGU{_pR(5A6jE_Ec}L z5|zyJ*EHv literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0062.png b/assets/kenney/tiny-town/Tiles/tile_0062.png new file mode 100644 index 0000000000000000000000000000000000000000..1dc3f1a4a32eb6d354d5b4b1e13384bb510a183e GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFp#6iJk10I))zU++)8SgY1 z@G9(PRK9C_<90o#;Lqje@=NS*<}T`sPC3`P+hpQlt}{<|9O1dwqE&h5$&zDEJnJ`J z@Y~d(wPlD7?2un`DL8gg& z|7)>M`uFz6&6j@$_t{#kyUG1^ XhT={B-F%!tQyDy6{an^LB{Ts5J(@f* literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0065.png b/assets/kenney/tiny-town/Tiles/tile_0065.png new file mode 100644 index 0000000000000000000000000000000000000000..ed6a0fa979d20cba26b163e2a2660484d5685864 GIT binary patch literal 166 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zQJEco_Vj;hNjmIp`ttoVkUCdS7sn8e>&X#cv+n1&or%7>TXJ3f-`{f|+6x%$soq{C zdiZy(!=t;mpU&j@{`&EHXO(~ZZ|#-#U?}~={_+R^^^IH{5)KRu`dbXo>Puhy3p9|y M)78&qol`;+0Kd#Xt^fc4 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0066.png b/assets/kenney/tiny-town/Tiles/tile_0066.png new file mode 100644 index 0000000000000000000000000000000000000000..ee9ef048267321a8367932719ff460c71aa56b8c GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF!YSbmx5*bJ_7!Xo=jnJ6_HX2P^`nMg$v)vwv1*4!U=)P4Ber(~tU# dpO?LzX|KOoN&B2-DLc?`22WQ%mvv4FO#p9vJ{AA~ literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0067.png b/assets/kenney/tiny-town/Tiles/tile_0067.png new file mode 100644 index 0000000000000000000000000000000000000000..d1ac6e7b1a88fcf43ed3618e4cb9ad729ebd4cb7 GIT binary patch literal 216 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF(^(=jq}Y!f{>p#6iJk10I))zU++)8SgY1 z@G9(PRK9C_<90o#;Lqje@=NS*<}T`sPC3`P+hpQlt}{<|9O1dwqE&h5$&zDEJnJ`J z@Y~d(wPU&v+k{v#iNrZ9NA L`njxgN@xNAF5)ld literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0070.png b/assets/kenney/tiny-town/Tiles/tile_0070.png new file mode 100644 index 0000000000000000000000000000000000000000..e9aafdfd627b4903b0e633f19ed9d5c073b11d16 GIT binary patch literal 165 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF!lvI6-$0X`wF zK>F3voV__-_G*UhP9LTN`HUq&e!&b5&u*jvIkKKEjv*Y^lM^!lvI6-$0X`wF zW!7f)YKE_t=IqV!+A}H54=AqT>Eal|aXq=?*8l(Z&QomX+~8M#^YdZS{%_8lzxlrf iYz$u==Ey0smtpEUEv<7a4$lGVVeoYIb6Mw<&;$UXa4ZA> literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0073.png b/assets/kenney/tiny-town/Tiles/tile_0073.png new file mode 100644 index 0000000000000000000000000000000000000000..d3704362b1bca54c16ad7fdb3318fcff4f35caf1 GIT binary patch literal 129 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6;>0X`wF zW!7e|mgelu@%sOe7o=9%)5S4_<9c!gD+^CTQlnT$Kto}8>p@Pn9TIamSeZB)wHO&* Xd{@m@SKiP8RLgTe~DWM4fVc8*R literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0074.png b/assets/kenney/tiny-town/Tiles/tile_0074.png new file mode 100644 index 0000000000000000000000000000000000000000..df9febc72071ae17b3125938f15109dbb2343b08 GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zKzeVEm%WzhDN3XE)M-99>Tr#}JO|$sDXqZ9o41-*0r~|NsBf xAKqUT`dhMYZPeCz55<|816@Rz4+pU@GEC=@D{-;%^Z;sP@O1TaS?83{1OUtyEsFpE literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0075.png b/assets/kenney/tiny-town/Tiles/tile_0075.png new file mode 100644 index 0000000000000000000000000000000000000000..ff1c20525f47bd063eeacbcce3d28c1638e8ed13 GIT binary patch literal 143 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zW!7f)YKE_t=IqV!+A}H54=AqZ>Eal|aXtCR|Nr-c+W!Clf1u;){{$9epEv!s9lsCq ox!iC#8n!lyS9QV{rd}on8zU1Y#*+*5fjSvHUHx3vIVCg!01139SpWb4 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0076.png b/assets/kenney/tiny-town/Tiles/tile_0076.png new file mode 100644 index 0000000000000000000000000000000000000000..1262306e567f1d31bb14d3e8213d7cb91e3c4593 GIT binary patch literal 137 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zQJEd~YK8|+-|3#cWv%S~zd&&fPZ!4!j_b)CxBmaPcb;N9=LWy}o1YJp_J4Ec{LTL@ iU}N~|Fh@?2y$n;=X=$BXad-|;4}+(xpUXO@geCwQb1lCB literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0077.png b/assets/kenney/tiny-town/Tiles/tile_0077.png new file mode 100644 index 0000000000000000000000000000000000000000..4a35d9b7980d74d58c15f88c1a0316f7e106c14e GIT binary patch literal 129 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6;>0X`wF zQJEbFPT%RCy~V*qCmblK?CIhd!f`!0f|Z3QA*oTUBcP!$y!9Zb+75|19IQ+njarNh YFTSg0t1EBl04itjboFyt=akR{0Ce;rrvLx| literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0078.png b/assets/kenney/tiny-town/Tiles/tile_0078.png new file mode 100644 index 0000000000000000000000000000000000000000..2fa0920d257514167df7cb7e00845b7b51bc6e83 GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zK)QSO7JD_r1E=q7IzGn;$Y(4G@(X5gcy=QV$kFw5aSY+Op3K3@)b`{5|NTZ+{{R0! x{o(ypp}!^T)<$ie_fVXfInYIf`EU>mBg1qaxe^yEPY<9*22WQ%mvv4FO#ogXFE;=H literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0079.png b/assets/kenney/tiny-town/Tiles/tile_0079.png new file mode 100644 index 0000000000000000000000000000000000000000..dbbb00d50fe2955eb9430ae80a3dc14a704a834f GIT binary patch literal 143 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zQJEd~YK8|+-|3#cWv%S~zd&(4PZ!4!j_b)k{{O!p)b{`X{{tOY|0l2*`@HG5?f89= o&*g^0(Xh2qys8tvF!eGq*ch2GF`itY57f!v>FVdQ&MBb@0F2Tw6aWAK literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0080.png b/assets/kenney/tiny-town/Tiles/tile_0080.png new file mode 100644 index 0000000000000000000000000000000000000000..30f1b3a336c275c3e5b200eaf76a36ad27d52176 GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFH>_hSigKH?Ch-9tYIQ;OXk;vd$@?2>@Ia BEp`9^ literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0081.png b/assets/kenney/tiny-town/Tiles/tile_0081.png new file mode 100644 index 0000000000000000000000000000000000000000..60fd8ab8a33b9f3a06a145a4c30c80c5eeaf55d2 GIT binary patch literal 120 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|j67W&Lo9le z|NQ@N&#ch#>1{l~a>T$yM8wQdR8YiCw6L&HgmEUb$<3QANu1rr e0Zgroj0`g81>dv8svZQI%i!ti=d#Wzp$PylkTPBX literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0084.png b/assets/kenney/tiny-town/Tiles/tile_0084.png new file mode 100644 index 0000000000000000000000000000000000000000..a6e113ecc836efd4d419f81de7627a200b7c76fb GIT binary patch literal 170 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF+I>`7{YNqnWL4dEkN9WBbB4kAV$(@j-!y8 zL)&UYftCgdw^MGX1lqC$qz(s|1W0H%vo5;Z*vOi+fcX&Dj->|a3=A{a756UD?WhDA O$KdJe=d#Wzp$PzM5;C*^ literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0085.png b/assets/kenney/tiny-town/Tiles/tile_0085.png new file mode 100644 index 0000000000000000000000000000000000000000..110d522e89067a49d4ab7dae07345780c66da70b GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF(I2 zM8?KY4t44$rjF6*2U FngGz#FO2{I literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0086.png b/assets/kenney/tiny-town/Tiles/tile_0086.png new file mode 100644 index 0000000000000000000000000000000000000000..65e9eced3f360f8592f216576787cefe6a4816e7 GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFo(4H60jTa08_rygiH7|3xh zfNf_HNG4}uf literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0087.png b/assets/kenney/tiny-town/Tiles/tile_0087.png new file mode 100644 index 0000000000000000000000000000000000000000..5944e65314ffb4ff8186e14838ad0045256983d9 GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFzopr E04?|~@c;k- literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0088.png b/assets/kenney/tiny-town/Tiles/tile_0088.png new file mode 100644 index 0000000000000000000000000000000000000000..fc2d67123dec365b62f7e0933712c548e71bf3b4 GIT binary patch literal 167 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF{VoMe`Fi10KG?*jlBQv$Zf#pPj z5DSy2fOA7&gW#crActfQX-(;*)C~?>tPM6e@RT@2Fm4xl#>3FfCmyij(o7DZaSWcW KelF{r5}E)npf2(N literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0089.png b/assets/kenney/tiny-town/Tiles/tile_0089.png new file mode 100644 index 0000000000000000000000000000000000000000..8807a4bb17ec0c000480cb2253240af22134e048 GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFMKA literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0090.png b/assets/kenney/tiny-town/Tiles/tile_0090.png new file mode 100644 index 0000000000000000000000000000000000000000..902e62806b54cafb341668ad9085cc410a405d2c GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFQ0@>ED7=pW^j0RBMr#W^>lFz;kcfhut2V$u<@e6wC?W7 zoE=9WJzA2I^XSn5h9y&b8gbP0l+XkKdr~da literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0093.png b/assets/kenney/tiny-town/Tiles/tile_0093.png new file mode 100644 index 0000000000000000000000000000000000000000..18dd43692d6cae02a52939cb232cfb33601c8a83 GIT binary patch literal 162 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zK>Bf;#@~Ix_G*T<3O>O=K4VFcUoeBivm0qZj)|v>V+hCfZA!u6{1-oD!M< DH}fpw literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0094.png b/assets/kenney/tiny-town/Tiles/tile_0094.png new file mode 100644 index 0000000000000000000000000000000000000000..6906b6ea03658cceb69d963ba2ab7e98bb2617d3 GIT binary patch literal 185 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zK>F{#;Kywm_G*S-udSN_xjxYAl$+IBffD6V_KGeab%5GWzhad4W(Gz~VR knYuRvZtxs3@Mbe&C}5JDv~fnoC!o0up00i_>zopr03UQcV*mgE literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0096.png b/assets/kenney/tiny-town/Tiles/tile_0096.png new file mode 100644 index 0000000000000000000000000000000000000000..32d667f8c7b1f91ba7a1e9c138e87dcbaac7d4ee GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFJP%Nau_VYZn8D%MjWi&~$J50zgyXvJsf(Nq4m`{k8iemW zWSW+DL2p6Y|CxJYG-v#=xx^HB@M1?zx!@lE(ucFO4rz5bP0l+XkK7GplM literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0097.png b/assets/kenney/tiny-town/Tiles/tile_0097.png new file mode 100644 index 0000000000000000000000000000000000000000..08636d5b93ef71a354985e28772f86eed6d93424 GIT binary patch literal 139 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zQJEd~YKGmjw;VWqr(3Q$3n;GT>Eal|aXp!Xm5I%uP?kf2kD1X~SioQn6BEZrd5(r7 i`|m0w+4pqMWnlQT-*`VOFAqOZ7lWs(pUXO@geCxdoFfGQ literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0098.png b/assets/kenney/tiny-town/Tiles/tile_0098.png new file mode 100644 index 0000000000000000000000000000000000000000..17799e02c4125376f610dd3821bf214b8d553832 GIT binary patch literal 181 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFJP%Nau_VYZn8D%MjWi&~#nZ(xgyVX$K^p@bo5taWgEv`t zdL?CC9WET5;TXul(#WIA(O}5ZD;eW(;3jMD!zXK4(kymbEM6VxWH2QmsL3E!?-+y3 X1ZnY{rqlO;<}rA>`njxgN@xNAmVPy0 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0099.png b/assets/kenney/tiny-town/Tiles/tile_0099.png new file mode 100644 index 0000000000000000000000000000000000000000..eafb9895b71d05782a7d7d31e002117633c520ee GIT binary patch literal 171 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFs0gu+G!HgOB*lSe&S zIU0E!6!lvI6-$0X`wF zQJEd~YK8|+-|3#cWv%S~zd&(iPZ!4!j_b)BtW0bMhP)gSvl<#68VDHtVQ1pl$i*>% bV^0^OgpJl-52wZspmGLJS3j3^P6s0f<^{*HjTrrjz>8; zVyDDNh_p5Y2%InwVRLd!7H3Q5XfR}nm6+n-;L6#|7{YAmH$jBCHboFyt=akR{0HvreZvX%Q literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0103.png b/assets/kenney/tiny-town/Tiles/tile_0103.png new file mode 100644 index 0000000000000000000000000000000000000000..46653e0d2b42bc76998f91509d058a0d869ebb59 GIT binary patch literal 196 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFd6`fKy{2IL4Lsu4$p3+ z0XaFIE{-7_*OPC^S{A2eWZcMOQ%H`|YBAI;j?(H7oMu`4Y>SD4a`Ce-r)FMm=$W}W zY;BaK@QE23OO`Cr;7plPQBtyHhqHulfSa((kv)qRFWxJ0VnbA1T-;WPBN41D8a=TJ k$6np#xubCH)m>?ZFA;8f;UA3W0_|n+boFyt=akR{0Hxws>;M1& literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0105.png b/assets/kenney/tiny-town/Tiles/tile_0105.png new file mode 100644 index 0000000000000000000000000000000000000000..5e1d449e30d7608fbf9a7105ad6a8225e9f8278f GIT binary patch literal 198 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFwKOLvp~ha#Q03*f7eG_y7O=Kkq;(6kEuuJFaKiAan|6_j9!CVPku07V|SM<%}o$(RKB<9-Hm{& q?bQ=_cIS95FRw3Te;?5Il3$2leA|jomCJ#qGkCiCxvXX=(Vn-Ckb&eNP6p0G2In6ABVFc3J&XTrd6%5RTHn;OSoXYoe(8Yv t>gI&Ip{8lv*VA~ES8!_X`PHk(sDHagKFf7#cq7mT22WQ%mvv4FO#p&ML`MJs literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0108.png b/assets/kenney/tiny-town/Tiles/tile_0108.png new file mode 100644 index 0000000000000000000000000000000000000000..f1d4db22366a2449c1c03e6cb3f8b6e20bd45da1 GIT binary patch literal 122 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF z-LtnuWp>!B86G%&hu@?52~b?p)5S4_<9c$${{R2$+gKHnG&>^r)lUdBGn70qi``)` R{~1sbgQu&X%Q~loCIIqGB9s6C literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0109.png b/assets/kenney/tiny-town/Tiles/tile_0109.png new file mode 100644 index 0000000000000000000000000000000000000000..2c97ef129a3e879558f60db80466168ec32286f8 GIT binary patch literal 99 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|WIbIRLo9le uZ3=#!t7qe45LTV#&MRS>aHZj33IhXo40GG$>;v^cg$$mqelF{r5}E)nZy6&1 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0110.png b/assets/kenney/tiny-town/Tiles/tile_0110.png new file mode 100644 index 0000000000000000000000000000000000000000..638bdc49fb86b8dc1072506a43b06d59bb6f52b9 GIT binary patch literal 121 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF z-LtnuWp>!B86G%&hu@?52~b?Z)5S4_<9hOs|Nrmnvnd>8RazvG5L0xN;Y)|5;_Pec Qp+GeZp00i_>zopr0PR>K0{{R3 literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0111.png b/assets/kenney/tiny-town/Tiles/tile_0111.png new file mode 100644 index 0000000000000000000000000000000000000000..d1883756a39c285c1d533736c34078aedecd03b2 GIT binary patch literal 203 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFF1ZtqQ%Y8IGiH4?*~4CBFULJ0OJuQsslVD5 vzI(r%-=CPR8?^8C=7=vfM0lIx6hZrgN!bPVeOvId1C|4?Skt)9udGw(-jJi#>{8 v?(*1fH>^y(`)l?hqb>7I?Pb^=cL(Y}Stn_`I5Y1n&=v+yS3j3^P6gO*e$L5#8AwCvpj6rS#buk-ak8IgWGgDAsvkwkGjPhsL3; sdi(bNU2tZdd`MnLRg$~S`qrO}MinB-udg#r1X{u1>FVdQ&MBb@0GBaCivR!s literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0115.png b/assets/kenney/tiny-town/Tiles/tile_0115.png new file mode 100644 index 0000000000000000000000000000000000000000..0325c94481377364731eb01b686c8e5b60c87662 GIT binary patch literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF2Pn!|666=m;PC858j$1W>Eal|aXmR9A%TN8HGv^m z;lP0dQc_ZnfcSubRL+`5DLGQ71hRONB$_1_HZEGIz~;g$#JocPh$%ykKqk)w-+!lvI6-$0X`wF zK)QSOmIJ5n*sB?8F6{aP!lvI6-$0X`wF zKzeVE*MZY_?9~jnrsfv|`HUq&e!&b5&u*jvIi8*_jv*Y^lM@mi{6Bx-KmxzgzqRZ_ z`yGzND;)e&Yaj6GpFG>M|6k=L-u(ZUnDAr&ALf9AZl1t_? cu3%yaJ|%tg^~1j$KtmZkUHx3vIVCg!08_R?82|tP literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0120.png b/assets/kenney/tiny-town/Tiles/tile_0120.png new file mode 100644 index 0000000000000000000000000000000000000000..9991c97809e35b410eaf7d006b61a9a64c5c8997 GIT binary patch literal 158 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zQJEdxv$xo*86G%&XV-!A;y`g*PZ!4!j_b)0`~Uy1Z(FL6#MlwRuRh_(w*UXRMOL?W zu8rE-mH7Ad_4Sh1~S{;}eFVdQ&MBb@ E0B5l_k^lez literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0121.png b/assets/kenney/tiny-town/Tiles/tile_0121.png new file mode 100644 index 0000000000000000000000000000000000000000..9ad5ce62e53c09017f07ceb4d327d8bfe8035980 GIT binary patch literal 141 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zQJEd~YKGmjw;VWqr(3Q$3n;GR>Eal|aXtA5KMT)|j{6DMsue!|vhQK=Zee0PT&j>@ l!NbDi>u_KL7smk>hIn7IjVJ2&{RZk|@O1TaS?83{1OU%*DUJXD literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0122.png b/assets/kenney/tiny-town/Tiles/tile_0122.png new file mode 100644 index 0000000000000000000000000000000000000000..ed2d0f54c1245e6ed3bd58be51890a899bf1a95c GIT binary patch literal 163 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6-$0X`wF zQJEdxv$xo*86G%&XV-!A;y`gHPZ!4!j_b)k{_lS$e)#|Y|BD=0#3yw8W>wsGy!lAd z>xQIyMXv>~!q!F|J^JC-*Vpkp?fmlpjy`ztLgJ`^loXfR9)>-AI@9i5cFqEt#^CAd K=d#Wzp$PzBYdt6c literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0123.png b/assets/kenney/tiny-town/Tiles/tile_0123.png new file mode 100644 index 0000000000000000000000000000000000000000..3958c4bff824de46ee4d1342c0de73335406652a GIT binary patch literal 145 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFR=M0V|2$-?&Z)8}m&fA*(on<3XF@vY8pUXO@geCy=M<(0= literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0125.png b/assets/kenney/tiny-town/Tiles/tile_0125.png new file mode 100644 index 0000000000000000000000000000000000000000..c13e66b7f53f0a363d4469b6d2b18df5127967d5 GIT binary patch literal 186 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFb_r9Waxb@dLAJI+i f3Fn_gJ~+&_#X(}*w*J^OpbZS3u6{1-oD!M<=Z8RJ literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0126.png b/assets/kenney/tiny-town/Tiles/tile_0126.png new file mode 100644 index 0000000000000000000000000000000000000000..50b6aca8102b990c285160678b0487f1a6239850 GIT binary patch literal 140 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!93?!50ihlx9Ea{HEjtmSN`?>!lvI6;>0X`wF z2TtD!N~r0cy~WD^WCl=B&(p;*gyVWL2P;!ssJHXt1xGf8Zk9NZG-vfRLxVLepA=al kbWC~@wI)QEiY~WeSmP#lci!);4?vv^p00i_>zopr0K`iw7XSbN literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0127.png b/assets/kenney/tiny-town/Tiles/tile_0127.png new file mode 100644 index 0000000000000000000000000000000000000000..1408cfe8c32d144858b2ae1822cd0f93506aafa7 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFmj zW?)p9JB?w<%}YJOhaGyhq=;)AKH?h4b1Hz>Io)AtLf6AvjciVmIR?IOiX|L) r*bELIWj$4(?gTe~DWM4f1am?I literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0129.png b/assets/kenney/tiny-town/Tiles/tile_0129.png new file mode 100644 index 0000000000000000000000000000000000000000..3c02b6a7c5cf59bfffa4088cc17706f427adbe61 GIT binary patch literal 200 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFwK$96fUHx3vIVCg!0OmqO3jhEB literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0130.png b/assets/kenney/tiny-town/Tiles/tile_0130.png new file mode 100644 index 0000000000000000000000000000000000000000..4b99555995c9e7d82966c353bd5ae51ea3584c97 GIT binary patch literal 206 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF!E!Ic^ec2 zSiZY5mL>4IXgf#+R8D5NUC;S$)`x_+$tP8-9Tu!$_`%$|<85H)*@r3>`xbfjsV{xK yEoIaCpc9EN?asMKcuvtOjBF8Gf9~SXW9*WR>Qk?m?2rdq!QkoY=d#Wzp$PzrEl0xu literal 0 HcmV?d00001 diff --git a/assets/kenney/tiny-town/Tiles/tile_0131.png b/assets/kenney/tiny-town/Tiles/tile_0131.png new file mode 100644 index 0000000000000000000000000000000000000000..b1c9c4560ba3f949d1c4887d84968bb54976cea6 GIT binary patch literal 220 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPF&}7Gcgih{_vU!ns~P@E7e4}&W-JNv3ubV5b|VeQiT8AI4B@z* zobccULlYYtTN|H20s~iz7FR1%t5uXElb|e*tl(3J3tTBJ)0Zw?I=xBa;iiG4JxU_Z(DLo!bZ rXb=>%F#qTZ7Mc7ZYuchYZdX5ZGVXg`@?B3$4J7U9>gTe~DWM4fTH!Iz literal 0 HcmV?d00001 diff --git a/build-cli.sh b/build-cli.sh new file mode 100755 index 00000000..cad36c76 --- /dev/null +++ b/build-cli.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# build-cli.sh — build the self-hosted Ludic front-end binaries. +# +# Both `ludicc` and `ludic` are the SAME native binary, compiled from the Ludic +# compiler's own IR seed (selfhost/ludicc.seed.ll) with clang alone — no C +# compiler. The binary is multi-call: it looks at argv[0], so invoked as +# `ludicc` it compiles, and invoked as `ludic` it compiles and runs. +# +# ./build-cli.sh +# ./ludicc examples/snake.ludic -o build/snake # compile +# ./ludic examples/snake.ludic # compile + play +# +# The binaries locate the runtime (runtime/native/cocoa.ll) via $LUDIC_HOME, +# defaulting to the directory they sit in — so keep them at the repo root, or +# set LUDIC_HOME and put them on your PATH. +set -eu +cd "$(dirname "$0")" +CC="${LUDIC_CC:-clang}" +mkdir -p build + +echo "cc: selfhost/ludicc.seed.ll -> ludicc/ludic (from the IR seed, no C compiler)" +$CC selfhost/ludicc.seed.ll -o build/ludicc +cp build/ludicc ludicc +cp build/ludicc ludic +chmod +x ludicc ludic +echo "done. built ./ludicc and ./ludic" diff --git a/build.sh b/build.sh new file mode 100755 index 00000000..9cc303ec --- /dev/null +++ b/build.sh @@ -0,0 +1,52 @@ +#!/bin/bash +# build.sh — compile a Ludic program with the self-hosted Ludic compiler. +# +# The compiler is written in Ludic (selfhost/*.ludic). It is built from the +# checked-in LLVM-IR seed (selfhost/ludicc.seed.ll) with clang alone — no C +# compiler is involved anywhere. clang then assembles the emitted IR and links +# it; a windowed build also links the hand-written platform layer (cocoa.ll). +# +# ./build.sh examples/snake.ludic # windowed native app +# ./build.sh examples/snake.ludic --headless # headless (renders out.ppm) +set -u +cd "$(dirname "$0")" +CC="${LUDIC_CC:-clang}" +mkdir -p build + +# the compiler itself: assembled from the IR seed (C-free) +if [ ! -x build/ludicc ] || [ selfhost/ludicc.seed.ll -nt build/ludicc ]; then + echo "cc: selfhost/ludicc.seed.ll -> build/ludicc (from the IR seed, no C compiler)" + $CC selfhost/ludicc.seed.ll -o build/ludicc || exit 1 +fi + +SRC=""; MODE=windowed; SAVE=0 +for a in "$@"; do + case "$a" in + --headless) MODE=headless ;; + --windowed) MODE=windowed ;; + --save-temps) SAVE=1 ;; + -*) ;; + *) SRC="$a" ;; + esac +done +[ -n "$SRC" ] || { echo "usage: ./build.sh [--headless]"; exit 1; } +NAME="$(basename "${SRC%.ludic}")" + +case "$MODE" in + windowed) + OUT="build/$NAME" + echo "ludicc: $SRC -> $OUT (Ludic-written compiler -> LLVM IR -> windowed binary)" + build/ludicc --windowed "$SRC" > "$OUT.ll" || exit 1 + $CC -O2 "$OUT.ll" runtime/native/cocoa.ll -framework Cocoa -Wl,-rpath,@loader_path -o "$OUT" || exit 1 + [ "$SAVE" = 1 ] || rm -f "$OUT.ll" + echo "done. run: ./$OUT (from the repo root, so assets/ resolves)" + ;; + headless) + OUT="build/${NAME}_headless" + echo "ludicc: $SRC -> $OUT (renders the last frame to out.ppm)" + build/ludicc --headless "$SRC" > "$OUT.ll" || exit 1 + $CC -O2 "$OUT.ll" -o "$OUT" || exit 1 + [ "$SAVE" = 1 ] || rm -f "$OUT.ll" + echo "done. run: printf 'ddss' | ./$OUT && open out.ppm" + ;; +esac diff --git a/examples/chronorift.ludic b/examples/chronorift.ludic new file mode 100644 index 00000000..2f6fd3b7 --- /dev/null +++ b/examples/chronorift.ludic @@ -0,0 +1,16 @@ +# ============================================================================ +# chronorift.ludic — a 2D windowed co-op JRPG written in Ludic (CC0 Kenney art) +# Overworld + dungeon + random encounters + co-op turn battle + boss + save. +# Compiles to a native macOS app: ludicc -> LLVM IR -> native binary. No C. +# +# This entry file is deliberately thin: the game is split across modules under +# chronorift/, pulled in with `import`. Paths resolve relative to this file, and +# each import is include-guarded so re-imports are free. +# ============================================================================ +game ChronoRift { + import "chronorift/world.ludic" # components, entity archetypes, constants + import "chronorift/rules.ludic" # pure rules + map data (functions) + import "chronorift/overworld.ludic" # boot, movement, encounters, shop + import "chronorift/combat.ludic" # co-op turn battle state machine + import "chronorift/draw.ludic" # the Render system +} diff --git a/examples/chronorift/combat.ludic b/examples/chronorift/combat.ludic new file mode 100644 index 00000000..2cd46165 --- /dev/null +++ b/examples/chronorift/combat.ludic @@ -0,0 +1,167 @@ +# combat.ludic — the co-op turn-based battle state machine. + +# The battle is a state machine over R_PHASE. `machine` dispatches on the +# register and `become` transitions to a named state — no more `if ph == N` +# ladders. Knight turn (0,1), Mage turn (2,3), Enemy turn (4). +system Battle phase Update { + if reg(R_MODE) == 1 { + let k = key() + for (e) in query [Stats, {Enemy}] { + machine R_PHASE { + + state KnightMenu = 0 { + for (st, pt) in query [Stats, Party] { + if pt.slot == 0 { + if st.hp <= 0 { + become MageMenu + setreg(R_CUR, 0) + } else { + if k == 'w' { setreg(R_CUR, max(0, reg(R_CUR) - 1)) } + if k == 's' { setreg(R_CUR, min(3, reg(R_CUR) + 1)) } + if is_confirm(k) { + match reg(R_CUR) { + 0 => { + let d = max(1, st.atk - e.def + rng_range(0, 4)) + e.hp = e.hp - d + setreg(R_PDMG, d) + } + 1 => { st.guard = 1 setreg(R_PDMG, 0) } + 2 => { + if reg(R_POTION) > 0 { + setreg(R_POTION, reg(R_POTION) - 1) + st.hp = min(st.maxhp, st.hp + 24) + setreg(R_PDMG, 24) + } else { setreg(R_PDMG, 0) } + } + 3 => { + if rng_chance(50) { e.hp = 0 setreg(R_MODE, 0) } + else { setreg(R_PDMG, 0) } + } + } + become KnightResolve + setreg(R_CUR, 0) + } + } + } + } + } + + state KnightResolve = 1 { + if k != 0 { + if e.hp <= 0 { + grant_xp(e.xp) + setreg(R_GOLD, reg(R_GOLD) + e.xp) + if reg(R_ETYPE) == 2 { setreg(R_BOSS, 1) setreg(R_MODE, 3) setreg(R_ACK, 0) } + else { setreg(R_MODE, 0) } + become KnightMenu + } else { + become MageMenu + setreg(R_CUR, 0) + } + } + } + + state MageMenu = 2 { + for (st, pt) in query [Stats, Party] { + if pt.slot == 1 { + if st.hp <= 0 { + become EnemyTurn + } else { + if k == 'i' { setreg(R_CUR, max(0, reg(R_CUR) - 1)) } + if k == 'k' { setreg(R_CUR, min(2, reg(R_CUR) + 1)) } + if k == 'j' { + match reg(R_CUR) { + 0 => { + let d = max(1, st.atk + 5 - e.def + rng_range(0, 5)) + e.hp = e.hp - d + setreg(R_PDMG, d) + } + 1 => { + if st.mp >= 4 { + st.mp = st.mp - 4 + for (t2, p2) in query [Stats, Party] { + if p2.slot == 0 { t2.hp = min(t2.maxhp, t2.hp + 16) } + } + setreg(R_PDMG, 16) + } else { setreg(R_PDMG, 0) } + } + 2 => { st.guard = 1 setreg(R_PDMG, 0) } + } + become MageResolve + setreg(R_CUR, 0) + } + } + } + } + } + + state MageResolve = 3 { + if k != 0 { + if e.hp <= 0 { + grant_xp(e.xp) + setreg(R_GOLD, reg(R_GOLD) + e.xp) + if reg(R_ETYPE) == 2 { setreg(R_BOSS, 1) setreg(R_MODE, 3) setreg(R_ACK, 0) } + else { setreg(R_MODE, 0) } + become KnightMenu + } else { + become EnemyTurn + } + } + } + + state EnemyTurn = 4 { + if k != 0 { + let done = 0 + for (t3) in query [Stats, {Party}] { + if done == 0 { + if t3.hp > 0 { + let ed = max(1, e.atk - t3.def + rng_range(0, 4)) + if t3.guard == 1 { ed = ed / 2 t3.guard = 0 } + t3.hp = t3.hp - ed + setreg(R_EDMG, ed) + done = 1 + } + } + } + let alive = 0 + for (t4) in query [Stats, {Party}] { + if t4.hp > 0 { alive = alive + 1 } + } + if alive == 0 { setreg(R_MODE, 2) setreg(R_ACK, 0) } + else { + become KnightMenu + setreg(R_CUR, 0) + } + } + } + } + } + } +} + +system CleanBattle phase LateUpdate { + if reg(R_MODE) != 1 { + for (e) in query [Stats, {Enemy}] { + despawn self() + } + } +} + +system Meta phase Update { + let k = key() + if reg(R_MODE) == 2 { + if k == 0 { setreg(R_ACK, 1) } + if k != 0 { + if reg(R_ACK) == 1 { + for (h) in query [Stats, {Party}] { h.hp = h.maxhp } + setreg(R_MODE, 0) + } + } + } + if reg(R_MODE) == 3 { + if k == 0 { setreg(R_ACK, 1) } + if k != 0 { + if reg(R_ACK) == 1 { setreg(R_MODE, 0) } + } + } +} diff --git a/examples/chronorift/draw.ludic b/examples/chronorift/draw.ludic new file mode 100644 index 00000000..13259b71 --- /dev/null +++ b/examples/chronorift/draw.ludic @@ -0,0 +1,138 @@ +# draw.ludic — the Render system (overworld, battle, and overlay screens). + +system Draw phase Render { + let m = reg(R_MODE) + clear(0x101018) + + if m == 0 { + let cx = 0 + let cy = 0 + for (p) in query [Pos, {Player}] { + cx = clamp(p.x * 16 - 152, 0, MW * 16 - 320) + cy = clamp(p.y * 16 - 112, 0, MH * 16 - 240) + } + let tx0 = cx / 16 + let ty0 = cy / 16 + for ty in ty0 .. ty0 + 16 { + for tx in tx0 .. tx0 + 21 { + let c = tile(tx, ty) + let sx = tx * 16 - cx + let sy = ty * 16 - cy + let base = SPR_GRASS + match c { + 'r' => base = SPR_PATH + ',', 'S', 'B' => base = SPR_FLOOR + '=' => base = SPR_WALL + } + draw_sprite(base, sx, sy) + if c == 'T' { draw_sprite(SPR_TREE, sx, sy) } + if c == '#' { draw_sprite(SPR_TREE, sx, sy) } + if c == 'H' { draw_sprite(SPR_HOUSE, sx, sy) } + if c == 'D' { draw_sprite(SPR_DOOR, sx, sy) } + if c == 'S' { draw_sprite(SPR_DOOR, sx, sy) } + if c == 'B' { + if reg(R_BOSS) == 0 { draw_sprite(SPR_BOSS, sx, sy) } + } + } + } + for (p, a) in query [Pos, Actor] { + draw_sprite(a.kind, p.x * 16 - cx, p.y * 16 - cy) + } + for (h, pp) in query [Stats, Party] { + if pp.slot == 0 { + fill_rect(4, 4, 96, 38, 0x0c0c16) + frame_rect(4, 4, 96, 38, 0x3a3a55) + text(8, 8, "LV", 0xffe08a, 1) + text_int(24, 8, h.lvl, 0xffffff, 1) + text(8, 18, "HP", 0x88ff88, 1) + text_int(24, 18, h.hp, 0xffffff, 1) + text(8, 28, "G", 0xffd24a, 1) + text_int(18, 28, reg(R_GOLD), 0xffffff, 1) + text(54, 28, "PO", 0x88ffcc, 1) + text_int(72, 28, reg(R_POTION), 0xffffff, 1) + } + } + } + + if m == 1 { + fill_rect(0, 0, 320, 176, 0x241a2e) + for (e, a) in query [Stats, Actor, {Enemy}] { + let bs = 5 + if reg(R_ETYPE) == 2 { bs = 7 } + draw_sprite_scaled(a.kind, 160 - bs * 8, 44, bs) + text(100, 20, enemy_name(reg(R_ETYPE)), 0xffffff, 1) + fill_rect(100, 30, 120, 8, 0x401018) + fill_rect(100, 30, e.hp * 120 / e.maxhp, 8, 0xe04040) + } + let ph = reg(R_PHASE) + let act = 0 + if ph >= 2 { act = 1 } + if ph >= 4 { act = 2 } + fill_rect(0, 176, 320, 64, 0x0c0c16) + frame_rect(0, 176, 320, 64, 0x3a3a55) + for (st, pt) in query [Stats, Party] { + let hx = 6 + pt.slot * 92 + let spr = 5 + if pt.slot == 1 { spr = 9 } + if pt.slot == act { frame_rect(hx - 2, 180, 88, 44, 0xffff00) } + draw_sprite_scaled(spr, hx, 184, 2) + if pt.slot == 0 { text(hx + 36, 182, "KNIGHT", 0xffe08a, 1) } + if pt.slot == 1 { text(hx + 36, 182, "MAGE", 0xc9a0ff, 1) } + text(hx + 36, 195, "HP", 0x88ff88, 1) + text_int(hx + 56, 195, st.hp, 0xffffff, 1) + text(hx + 36, 207, "MP", 0x88aaff, 1) + text_int(hx + 56, 207, st.mp, 0xffffff, 1) + } + let cur = reg(R_CUR) + if ph == 0 or ph == 1 { + text(206, 181, "P1 KNIGHT", 0xffe08a, 1) + text(214, 192, "ATTACK", 0xffffff, 1) + text(214, 203, "DEFEND", 0xffffff, 1) + text(214, 214, "ITEM", 0xffffff, 1) + text(256, 214, "x", 0x777777, 1) + text_int(264, 214, reg(R_POTION), 0xffd24a, 1) + text(214, 225, "RUN", 0xffffff, 1) + if ph == 0 { text(204, 192 + cur * 11, ">", 0xffff00, 1) } + } + if ph == 2 or ph == 3 { + text(206, 182, "P2 MAGE", 0xc9a0ff, 1) + text(214, 196, "ATTACK", 0xffffff, 1) + text(214, 208, "HEAL", 0xffffff, 1) + text(214, 220, "DEFEND", 0xffffff, 1) + if ph == 2 { text(204, 196 + cur * 12, ">", 0xffff00, 1) } + } + if ph == 4 { text(206, 200, "ENEMY TURN", 0xff8888, 1) } + if ph == 1 or ph == 3 { + text(6, 232, "DMG", 0xffff88, 1) + text_int(34, 232, reg(R_PDMG), 0xffffff, 1) + } + if ph == 4 { + text(6, 232, "FOE HITS", 0xff8888, 1) + text_int(66, 232, reg(R_EDMG), 0xffffff, 1) + } + } + + if m == 2 { + text(112, 104, "YOU FELL", 0xff5555, 2) + text(84, 140, "PRESS ANY KEY", 0xffffff, 1) + } + if m == 3 { + text(60, 96, "THE RIFT IS SEALED", 0x88ffcc, 2) + text(96, 132, "VICTORY!", 0xffe060, 3) + text(84, 170, "PRESS ANY KEY", 0xffffff, 1) + } + if m == 4 { + fill_rect(60, 60, 200, 120, 0x141422) + frame_rect(60, 60, 200, 120, 0x6a6a95) + text(96, 72, "ITEM SHOP", 0xffe060, 2) + text(80, 104, "BUY POTION", 0xffffff, 1) + text(180, 104, "10 G", 0xffd24a, 1) + text(80, 122, "LEAVE", 0xffffff, 1) + text(70, 104 + reg(R_CUR) * 18, ">", 0xffff00, 1) + text(80, 150, "GOLD", 0xffd24a, 1) + text_int(120, 150, reg(R_GOLD), 0xffffff, 1) + text(160, 150, "POTIONS", 0x88ffcc, 1) + text_int(226, 150, reg(R_POTION), 0xffffff, 1) + } + present() +} diff --git a/examples/chronorift/overworld.ludic b/examples/chronorift/overworld.ludic new file mode 100644 index 00000000..3ce11c01 --- /dev/null +++ b/examples/chronorift/overworld.ludic @@ -0,0 +1,140 @@ +# overworld.ludic — boot, movement/encounter input, and the shop system. + +system Boot phase Start { + load_png("assets/kenney/tiny-town/Tiles/tile_0000.png") # 0 grass + load_png("assets/kenney/tiny-town/Tiles/tile_0004.png") # 1 tree + load_png("assets/kenney/tiny-town/Tiles/tile_0025.png") # 2 path + load_png("assets/kenney/tiny-town/Tiles/tile_0073.png") # 3 house + load_png("assets/kenney/tiny-town/Tiles/tile_0112.png") # 4 arch + load_png("assets/kenney/tiny-dungeon/Tiles/tile_0096.png") # 5 hero + load_png("assets/kenney/tiny-dungeon/Tiles/tile_0108.png") # 6 slime + load_png("assets/kenney/tiny-dungeon/Tiles/tile_0120.png") # 7 skeleton + load_png("assets/kenney/tiny-dungeon/Tiles/tile_0110.png") # 8 boss + load_png("assets/kenney/tiny-dungeon/Tiles/tile_0084.png") # 9 mage + load_png("assets/kenney/tiny-dungeon/Tiles/tile_0048.png") # 10 floor + load_png("assets/kenney/tiny-dungeon/Tiles/tile_0026.png") # 11 wall + + build_field(0) + spawn Player { + Pos = { x = 11, y = 15 } + Actor = { kind = 5 } + Party = { slot = 0 } + Stats = { hp = 40, maxhp = 40, mp = 8, maxmp = 8, atk = 12, def = 6, lvl = 1, xp = 0, guard = 0 } + } + spawn Ally { + Party = { slot = 1 } + Stats = { hp = 26, maxhp = 26, mp = 16, maxmp = 16, atk = 8, def = 4, lvl = 1, xp = 0, guard = 0 } + } + setreg(R_MODE, 0) + setreg(R_ENC, 4) + setreg(R_MAP, 0) + setreg(R_BOSS, 0) + setreg(R_GOLD, 20) + setreg(R_POTION, 2) +} + +system Control phase Input { + if reg(R_MODE) == 0 { + for (p) in query [Pos, {Player}] { + let k = key() + let nx = p.x + let ny = p.y + if k == 'w' { ny = p.y - 1 } + if k == 's' { ny = p.y + 1 } + if k == 'a' { nx = p.x - 1 } + if k == 'd' { nx = p.x + 1 } + let moved = 0 + if walkable(nx, ny) { + if nx != p.x or ny != p.y { + p.x = nx + p.y = ny + moved = 1 + } + } + if moved == 1 { + let tc = tile(p.x, p.y) + if tc == 'D' { + build_dungeon(0) + p.x = 3 + p.y = 2 + setreg(R_MAP, 1) + } + if tc == 'S' { + build_field(0) + p.x = 36 + p.y = 3 + setreg(R_MAP, 0) + } + if tc == 'B' { + if reg(R_BOSS) == 0 { + setreg(R_ETYPE, 2) + spawn Enemy { + Actor = { kind = 8 } + Stats = { hp = 120, maxhp = 120, mp = 0, maxmp = 0, atk = 18, def = 10, lvl = 5, xp = 300, guard = 0 } + } + setreg(R_MODE, 1) + setreg(R_PHASE, 0) + setreg(R_CUR, 0) + } + } + if tc == 'h' { + setreg(R_MODE, 4) + setreg(R_CUR, 0) + } + if tc != 'D' { + if tc != 'S' { + if tc != 'B' { + if tc != 'h' { + setreg(R_ENC, reg(R_ENC) - 1) + if reg(R_ENC) <= 0 { + setreg(R_ENC, rng_range(4, 9)) + let et = 0 + if reg(R_MAP) == 1 { et = 1 } + if reg(R_MAP) == 0 { + if rng_chance(40) { et = 1 } + } + setreg(R_ETYPE, et) + if et == 0 { + spawn Enemy { + Actor = { kind = 6 } + Stats = { hp = 18, maxhp = 18, mp = 0, maxmp = 0, atk = 8, def = 2, lvl = 1, xp = 7, guard = 0 } + } + } + if et == 1 { + spawn Enemy { + Actor = { kind = 7 } + Stats = { hp = 30, maxhp = 30, mp = 0, maxmp = 0, atk = 11, def = 5, lvl = 1, xp = 15, guard = 0 } + } + } + setreg(R_MODE, 1) + setreg(R_PHASE, 0) + setreg(R_CUR, 0) + } + } + } + } + } + } + if k == 'k' { save() } + if k == 'l' { if load() { } } + } + } +} + +# shop (at the house 'h' tile): buy potions with gold +system Shop phase Update { + if reg(R_MODE) == 4 { + let k = key() + if k == 'w' { setreg(R_CUR, max(0, reg(R_CUR) - 1)) } + if k == 's' { setreg(R_CUR, min(1, reg(R_CUR) + 1)) } + if is_confirm(k) { + if reg(R_CUR) == 0 { + if reg(R_GOLD) >= 10 { + setreg(R_GOLD, reg(R_GOLD) - 10) + setreg(R_POTION, reg(R_POTION) + 1) + } + } + if reg(R_CUR) == 1 { setreg(R_MODE, 0) } + } + } +} diff --git a/examples/chronorift/rules.ludic b/examples/chronorift/rules.ludic new file mode 100644 index 00000000..12d77dc8 --- /dev/null +++ b/examples/chronorift/rules.ludic @@ -0,0 +1,86 @@ +# rules.ludic — pure game rules & map data (functions only, no systems). + +fn tile_sprite(c: int) -> int { + match c { + 'T', '#' => return SPR_TREE + 'H' => return SPR_HOUSE + 'D' => return SPR_DOOR + 'r', 'h' => return SPR_PATH + ',', 'S', 'B' => return SPR_FLOOR + '=' => return SPR_WALL + } + return SPR_GRASS +} +fn walkable(x: int, y: int) -> bool { + let c = tile(x, y) + return c == '.' or c == 'D' or c == 'r' or c == ',' or c == 'S' or c == 'B' or c == 'h' +} +fn is_confirm(k: int) -> bool { return k == 32 or k == 10 or k == 13 } +fn enemy_name(et: int) -> str { + if et == 0 { return "SLIME" } + if et == 1 { return "SKELETON" } + return "RIFT WARDEN" +} + +fn build_field(x: int) -> int { + map_size(40, 18) + map_row(0, "########################################") + map_row(1, "#......................................#") + map_row(2, "#...TT.........................TT.....D#") + map_row(3, "#..TT.......................TT.........#") + map_row(4, "#..T.........................T.........#") + map_row(5, "#....................................T.#") + map_row(6, "#.....TT....................TT.......T.#") + map_row(7, "#....TT.....................T..........#") + map_row(8, "#...........rrrrrrrr........HH.........#") + map_row(9, "#..........r........r.......HH.........#") + map_row(10, "#......TT...r........rrrrrrrrhr......T.#") + map_row(11, "#.....TT...r.................r.......T.#") + map_row(12, "#..........r.......TT.......r..........#") + map_row(13, "#..........rrrrrrrrrrrrrrrrr.........T.#") + map_row(14, "#.........TT.........................T.#") + map_row(15, "#........TT..........................T.#") + map_row(16, "#....................................T.#") + map_row(17, "########################################") + return 0 +} +fn build_dungeon(x: int) -> int { + map_size(40, 18) + map_row(0, "========================================") + map_row(1, "=,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,=") + map_row(2, "=,S,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,=") + map_row(3, "=,,,,,====,,,,,,,,,,,,,,,====,,,,,,,,,,=") + map_row(4, "=,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,=") + map_row(5, "=,,,,,,,,,,,,,====,,,,,,,,,,,,,,,,,,,,,=") + map_row(6, "=,,,,,,,,,,,,,,,,,,,,,,,,,,,,,====,,,,,=") + map_row(7, "=,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,=") + map_row(8, "=,,,====,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,=") + map_row(9, "=,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,=") + map_row(10, "=,,,,,,,,,,,,,,,,,,====,,,,,,,,,,,,,,,,=") + map_row(11, "=,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,=") + map_row(12, "=,,,,,,,,,,,,,,,,,,,,,,,,,,,====,,,,,,,=") + map_row(13, "=,,,,,,,,,====,,,,,,,,,,,,,,,,,,,,,,,,,=") + map_row(14, "=,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,=") + map_row(15, "=,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,B,,=") + map_row(16, "=,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,=") + map_row(17, "========================================") + return 0 +} + +fn grant_xp(amount: int) -> int { + for (t) in query [Stats, {Party}] { + if t.hp > 0 { + t.xp = t.xp + amount + while t.xp >= t.lvl * 20 { + t.xp = t.xp - t.lvl * 20 + t.lvl = t.lvl + 1 + t.maxhp = t.maxhp + 8 + t.hp = t.maxhp + t.maxmp = t.maxmp + 2 + t.atk = t.atk + 2 + t.def = t.def + 1 + } + } + } + return 0 +} diff --git a/examples/chronorift/world.ludic b/examples/chronorift/world.ludic new file mode 100644 index 00000000..457d87ee --- /dev/null +++ b/examples/chronorift/world.ludic @@ -0,0 +1,43 @@ +# world.ludic — the data model: components, entity archetypes, constants. +# Imported by examples/chronorift.ludic. No `game` wrapper (this is a fragment). + +component Pos { x: int = 0, y: int = 0 } +component Actor { kind: int = 0 } +component Stats { hp: int = 1, maxhp: int = 1, mp: int = 0, maxmp: int = 0, + atk: int = 1, def: int = 0, lvl: int = 1, xp: int = 0, guard: int = 0 } +component Party { slot: int = 0 } + +# Entity KINDS. Identity is stored as one integer per entity (L_kind), not as +# an empty marker component. Query membership with {Player} / {Enemy}. +archetype Player { Pos, Actor, Party, Stats } # the controllable knight +archetype Ally { Party, Stats } # backline mage (no overworld body) +archetype Enemy { Actor, Stats } # battle foe + +const MW: int = 40 +const MH: int = 18 + +const SPR_GRASS: int = 0 +const SPR_TREE: int = 1 +const SPR_PATH: int = 2 +const SPR_HOUSE: int = 3 +const SPR_DOOR: int = 4 +const SPR_HERO: int = 5 +const SPR_SLIME: int = 6 +const SPR_SKEL: int = 7 +const SPR_BOSS: int = 8 +const SPR_MAGE: int = 9 +const SPR_FLOOR: int = 10 +const SPR_WALL: int = 11 + +const R_MODE: int = 0 # 0 field, 1 battle, 2 gameover, 3 victory +const R_PHASE: int = 1 +const R_CUR: int = 2 +const R_ENC: int = 3 +const R_ETYPE: int = 4 # 0 slime, 1 skeleton, 2 boss +const R_PDMG: int = 5 +const R_EDMG: int = 6 +const R_GOLD: int = 7 +const R_MAP: int = 8 # 0 overworld, 1 dungeon +const R_BOSS: int = 9 # boss defeated flag +const R_ACK: int = 10 # debounce for end screens +const R_POTION: int = 11 # potions in inventory diff --git a/examples/hello.ludic b/examples/hello.ludic new file mode 100644 index 00000000..0b4d1780 --- /dev/null +++ b/examples/hello.ludic @@ -0,0 +1,34 @@ +# hello.ludic — smallest program that exercises the ECS pipeline +game Hello { + + component Pos { x: int = 0, y: int = 0 } + component Vel { dx: int = 0, dy: int = 0 } + + system Boot phase Start { + spawn Mob { + Pos = { x = 3, y = 4 } + Vel = { dx = 1, dy = 0 } + } + spawn Mob { + Pos = { x = 10, y = 2 } + Vel = { dx = 0, dy = 1 } + } + } + + # a system can declare the entities it operates on: the body then runs once + # per match, with the components bound and self() giving that entity. + system Move phase FixedUpdate + query (p, v) [Pos, Vel] + { + p.x = p.x + v.dx + p.y = p.y + v.dy + } + + system Report phase Update { + for (p) in query [Pos] { + print_int(p.x) + print_int(p.y) + } + quit() + } +} diff --git a/examples/lib/arena.ludic b/examples/lib/arena.ludic new file mode 100644 index 00000000..35bdf6ae --- /dev/null +++ b/examples/lib/arena.ludic @@ -0,0 +1,34 @@ +# ============================================================================ +# arena.ludic — a game that links the Ludic shared library next to it. +# +# ludicc examples/lib/combat.ludic --shared -o build/libcombat.dylib +# ludicc examples/lib/arena.ludic -o build/arena -Lbuild -lcombat +# +# `extern fn` binds a name to a symbol resolved at link time. The library the +# symbols come from happens to be written in Ludic, but nothing here depends on +# that: the same declaration binds a C, Rust or Zig library just as well. This +# is how Ludic reaches the outside world without a C shim. +# ============================================================================ +game Arena { + + extern fn damage(attack: int, armour: int, roll: int) -> int = "damage" + extern fn hits_to_kill(hp: int, attack: int, armour: int) -> int = "hits_to_kill" + extern fn xp_for(level: int, kills: int) -> int = "xp_for" + + component Fighter { hp: int = 30, attack: int = 9, armour: int = 2 } + + system Boot phase Start { + spawn Hero { Fighter = { hp = 40, attack = 12, armour = 3 } } + spawn Orc { Fighter = { hp = 24, attack = 7, armour = 1 } } + } + + system Fight phase Update { + for (f) in query [Fighter] { + print_int(damage(f.attack, f.armour, 0)) + print_int(damage(f.attack, f.armour, 20)) + print_int(hits_to_kill(f.hp, f.attack, f.armour)) + } + print_int(xp_for(3, 4)) + quit() + } +} diff --git a/examples/lib/combat.ludic b/examples/lib/combat.ludic new file mode 100644 index 00000000..794f72d5 --- /dev/null +++ b/examples/lib/combat.ludic @@ -0,0 +1,46 @@ +# ============================================================================ +# combat.ludic — a Ludic *library*, not a game. +# +# `module` instead of `game` means: no entry point, no frame loop. ludicc +# compiles this to a real shared object — +# +# ludicc examples/lib/combat.ludic --shared -o build/libcombat.dylib +# +# — whose `export fn`s are ordinary C-ABI symbols. Anything that can call a +# .dylib/.so/.dll can call these: another Ludic program via `extern fn`, a game +# engine, a test harness, a scripting host. Non-exported functions stay private +# to the library. +# ============================================================================ +module Combat { + + const CRIT_MULT: int = 2 + + # damage after armour, with a crit multiplier applied on an exact roll + export fn damage(attack: int, armour: int, roll: int) -> int { + let raw = attack - armour + if raw < 1 { raw = 1 } + if roll == 20 { raw = raw * CRIT_MULT } + return raw + } + + # how many hits to drop a target — the loop is here so the caller cannot + # accidentally disagree with `damage` about rounding + export fn hits_to_kill(hp: int, attack: int, armour: int) -> int { + let left = hp + let n = 0 + while left > 0 { + left = left - damage(attack, armour, 0) + n = n + 1 + } + return n + } + + export fn xp_for(level: int, kills: int) -> int { + return curve(level) * kills + } + + # private: not exported, so it is not a symbol in the library + fn curve(level: int) -> int { + return 10 + level * level * 3 + } +} diff --git a/examples/menu.ludic b/examples/menu.ludic new file mode 100644 index 00000000..2bb9861e --- /dev/null +++ b/examples/menu.ludic @@ -0,0 +1,41 @@ +# menu.ludic — a retained-UI title screen. The UI is declared as DATA (the `ui` +# block); the engine lays it out (stacked panel, padding/gap/alignment), draws +# it (background, TrueType labels, focusable buttons), and routes keyboard focus +# and activation. The game only loads a font, opens the UI, and reads clicks. +game Menu { + + const R_FONT: int = 0 + const R_MSG: int = 1 + + ui MainMenu { + panel id=Root w=288 pad=16 gap=6 bg=0x1a1a2c border=0x4a4a72 skin="assets/ui/panel.png" inset=10 align=center { + label text="CHRONO RIFT" font=reg(R_FONT) size=26 fg=0xffe060 align=center + label text="a Ludic retained-UI demo" font=reg(R_FONT) size=14 fg=0x9aa0c8 align=center + spacer h=4 + button id=NewGame text="New Game" font=reg(R_FONT) size=16 w=236 + button id=Continue text="Continue" font=reg(R_FONT) size=16 w=236 + button id=Options text="Options" font=reg(R_FONT) size=16 w=236 + button id=Quit text="Quit" font=reg(R_FONT) size=16 w=236 + } + } + + system Boot phase Start { + setreg(R_FONT, font_load("/System/Library/Fonts/Supplemental/Arial.ttf")) + ui_build() + ui_open(UI_MainMenu) + } + + system Nav phase Update { + ui_tick(key()) + if ui_clicked(UI_NewGame) { ui_set_text(UI_NewGame, "Starting...") } + if ui_clicked(UI_Continue) { ui_set_text(UI_Continue, "No save") } + if ui_clicked(UI_Options) { ui_set_text(UI_Options, "Soon (TM)") } + if ui_clicked(UI_Quit) { quit() } + } + + system Draw phase Render { + clear(0x0e0e16) + ui_render() + present() + } +} diff --git a/examples/qdecl.ludic b/examples/qdecl.ludic new file mode 100644 index 00000000..5c63a879 --- /dev/null +++ b/examples/qdecl.ludic @@ -0,0 +1,37 @@ +# ============================================================================ +# qdecl.ludic — a system whose query lives in its signature. +# +# system CleanBattle phase LateUpdate +# query (b, p) [Battle, Pos, {Foe}] where b.hp <= 0 +# { … } +# +# is the same thing as writing `for (b, p) in query [...] where ... { … }` around +# the whole body — the loop header just moves into the declaration. The body runs +# once per matching entity, and self() is that entity. +# ============================================================================ +game QueryDecl { + component Battle { hp: int = 0, side: int = 0 } + component Pos { x: int = 0, y: int = 0 } + archetype Foe { Battle, Pos } + + system Seed phase Start { + spawn Foe { Battle = { hp = 3, side = 1 } } + spawn Foe { Battle = { hp = 0, side = 1 } } + spawn Foe { Battle = { hp = -2, side = 0 } } + } + + system CleanBattle phase LateUpdate + query (b, p) [Battle, Pos, {Foe}] where b.hp <= 0 and b.side == 1 + { + print_int(p.x) + despawn self() + } + + system Census phase Render + query (b) [Battle] + { + print_int(b.hp) + } + + system Bye phase Render { quit() } +} diff --git a/examples/scenes.ludic b/examples/scenes.ludic new file mode 100644 index 00000000..b3600e7b --- /dev/null +++ b/examples/scenes.ludic @@ -0,0 +1,38 @@ +# ⚠� NOT YET IMPLEMENTED by the self-hosted compiler. `scene` / `layer` / +# `on enter` / `on exit` have no parser support today, so this file does NOT +# compile with build/ludicc — it is a design sketch of the intended syntax (see +# LANGUAGE.md §"Scenes & layers"). It is deliberately excluded from test.sh. +# Games that need scene-like states use a mode register + `machine` today, as +# examples/chronorift does. +game SceneDemo { + const R_N: int = 0 + + system Boot phase Start { setreg(R_N, 0) print_int(1000) } + + scene Title start { + on enter { print_int(1) } + on exit { print_int(2) } + layer Main { + system Tick phase Update { + setreg(R_N, reg(R_N) + 1) + print_int(100 + reg(R_N)) + if reg(R_N) >= 2 { enter Play } + } + } + } + + scene Play { + on enter { print_int(3) setreg(R_N, 0) } + on exit { print_int(4) } + layer World { + system Step phase Update { + setreg(R_N, reg(R_N) + 1) + print_int(200 + reg(R_N)) + if reg(R_N) >= 2 { quit() } + } + } + layer Hud { + system Draw phase Render { print_int(900) } + } + } +} diff --git a/examples/snake.ludic b/examples/snake.ludic new file mode 100644 index 00000000..857dbe4e --- /dev/null +++ b/examples/snake.ludic @@ -0,0 +1,136 @@ +# ============================================================================ +# snake.ludic — a second, unrelated game in Ludic, to prove the language is +# general: compiled by the SAME unmodified ludicc + runtime as the JRPG. +# No sprites/assets — pure primitives. Build: ./build.sh examples/snake.ludic +# ============================================================================ +game Snake { + + component Pos { x: int = 0, y: int = 0 } + component Seg { order: int = 0 } + + const GW: int = 20 + const GH: int = 15 + const TS: int = 16 + + const R_DIR: int = 0 # 0 up 1 down 2 left 3 right + const R_LEN: int = 1 + const R_TICK: int = 2 + const R_FX: int = 3 + const R_FY: int = 4 + const R_MODE: int = 5 # 0 play 1 gameover + const R_SCORE: int = 6 + const R_ATE: int = 7 + const R_TX: int = 8 + const R_TY: int = 9 + const R_ACK: int = 10 + + fn reset(x: int) -> int { + for (p, s) in query [Pos, Seg] { despawn self() } + spawn S0 { Seg = { order = 0 } Pos = { x = 10, y = 7 } } + spawn S1 { Seg = { order = 1 } Pos = { x = 9, y = 7 } } + spawn S2 { Seg = { order = 2 } Pos = { x = 8, y = 7 } } + setreg(R_DIR, 3) + setreg(R_LEN, 3) + setreg(R_TICK, 0) + setreg(R_MODE, 0) + setreg(R_SCORE, 0) + setreg(R_FX, 14) + setreg(R_FY, 7) + return 0 + } + + system Boot phase Start { reset(0) } + + system Input phase Input { + let k = key() + if reg(R_MODE) == 0 { + if k == 'w' { if reg(R_DIR) != 1 { setreg(R_DIR, 0) } } + if k == 's' { if reg(R_DIR) != 0 { setreg(R_DIR, 1) } } + if k == 'a' { if reg(R_DIR) != 3 { setreg(R_DIR, 2) } } + if k == 'd' { if reg(R_DIR) != 2 { setreg(R_DIR, 3) } } + } + if reg(R_MODE) == 1 { + if k == 0 { setreg(R_ACK, 1) } + if k != 0 { if reg(R_ACK) == 1 { reset(0) } } + } + } + + system Move phase Update { + if reg(R_MODE) == 0 { + setreg(R_TICK, reg(R_TICK) + 1) + if reg(R_TICK) >= 6 { + setreg(R_TICK, 0) + let len = reg(R_LEN) + for (pt, stg) in query [Pos, Seg] { + if stg.order == len - 1 { setreg(R_TX, pt.x) setreg(R_TY, pt.y) } + } + for step in 0 .. len { + let i = len - 1 - step + if i >= 1 { + for (pa, sa) in query [Pos, Seg] { + if sa.order == i { + for (pb, sb) in query [Pos, Seg] { + if sb.order == i - 1 { pa.x = pb.x pa.y = pb.y } + } + } + } + } + } + setreg(R_ATE, 0) + for (ph, sh) in query [Pos, Seg] { + if sh.order == 0 { + if reg(R_DIR) == 0 { ph.y = ph.y - 1 } + if reg(R_DIR) == 1 { ph.y = ph.y + 1 } + if reg(R_DIR) == 2 { ph.x = ph.x - 1 } + if reg(R_DIR) == 3 { ph.x = ph.x + 1 } + if ph.x < 0 { setreg(R_MODE, 1) } + if ph.x >= GW { setreg(R_MODE, 1) } + if ph.y < 0 { setreg(R_MODE, 1) } + if ph.y >= GH { setreg(R_MODE, 1) } + if ph.x == reg(R_FX) { if ph.y == reg(R_FY) { setreg(R_ATE, 1) } } + } + } + for (ph, sh) in query [Pos, Seg] { + if sh.order == 0 { + for (pb, sb) in query [Pos, Seg] { + if sb.order > 0 { + if pb.x == ph.x { if pb.y == ph.y { setreg(R_MODE, 1) } } + } + } + } + } + if reg(R_ATE) == 1 { + setreg(R_SCORE, reg(R_SCORE) + 1) + spawn Body { Seg = { order = len } Pos = { x = reg(R_TX), y = reg(R_TY) } } + setreg(R_LEN, len + 1) + setreg(R_FX, rng_range(0, GW - 1)) + setreg(R_FY, rng_range(0, GH - 1)) + } + } + } + } + + system Draw phase Render { + clear(0x0d1020) + for gy in 0 .. GH { + for gx in 0 .. GW { + let col = 0x141a2e + if (gx + gy) % 2 == 0 { col = 0x10162a } + fill_rect(gx * TS, gy * TS, TS, TS, col) + } + } + fill_rect(reg(R_FX) * TS + 3, reg(R_FY) * TS + 3, TS - 6, TS - 6, 0xe0405a) + for (p, s) in query [Pos, Seg] { + let col = 0x40c060 + if s.order == 0 { col = 0x9dffb0 } + fill_rect(p.x * TS + 1, p.y * TS + 1, TS - 2, TS - 2, col) + } + text(6, 4, "SCORE", 0xffffff, 1) + text_int(52, 4, reg(R_SCORE), 0xffe060, 1) + if reg(R_MODE) == 1 { + text(112, 104, "GAME OVER", 0xff5555, 2) + text(84, 140, "PRESS ANY KEY", 0xffffff, 1) + } + present() + } +} diff --git a/runtime/native/cocoa.ll b/runtime/native/cocoa.ll new file mode 100644 index 00000000..b092b940 --- /dev/null +++ b/runtime/native/cocoa.ll @@ -0,0 +1,327 @@ +; ============================================================================ +; cocoa.ll — the macOS window, written in LLVM IR. +; +; This is what replaced plat_cocoa.m. There is no Objective-C source and no C +; source in a Ludic build: the window is opened by talking to the Objective-C +; runtime through its C ABI (objc_getClass / sel_registerName / objc_msgSend) +; and to Quartz through CoreGraphics, exactly as a compiled .m file would, only +; written at the level ludicc itself emits. ludicc splices this module in when +; it links a windowed macOS binary. +; +; The one piece that genuinely needs a class is the view: AppKit paints through +; -drawRect:, so a class is built at runtime with objc_allocateClassPair and +; @ludic_drawRect is installed as its IMP. On arm64 the unused NSRect argument +; simply stays in registers we never read, so the IMP needs no struct in its +; signature. +; +; Exposed to Ludic (through the win_* intrinsics): +; win_open(w, h, scale, title) win_poll() -> key win_present(fb, w, h) +; win_running() -> bool win_close() +; ============================================================================ + +%CGRect = type { double, double, double, double } + +declare ptr @objc_getClass(ptr) +declare ptr @sel_registerName(ptr) +declare ptr @objc_msgSend(ptr, ptr, ...) +declare ptr @objc_allocateClassPair(ptr, ptr, i64) +declare void @objc_registerClassPair(ptr) +declare i8 @class_addMethod(ptr, ptr, ptr, ptr) +declare ptr @CGColorSpaceCreateDeviceRGB() +declare ptr @CGBitmapContextCreate(ptr, i64, i64, i64, i64, ptr, i32) +declare ptr @CGBitmapContextCreateImage(ptr) +declare void @CGContextDrawImage(ptr, %CGRect, ptr) +declare void @CGContextSetInterpolationQuality(ptr, i32) +declare void @CGContextTranslateCTM(ptr, double, double) +declare void @CGContextScaleCTM(ptr, double, double) +declare void @CGContextSaveGState(ptr) +declare void @CGContextRestoreGState(ptr) +declare void @CGImageRelease(ptr) +declare void @CGContextRelease(ptr) +declare void @CGColorSpaceRelease(ptr) +declare i32 @usleep(i32) + +@.c_app = private unnamed_addr constant [14 x i8] c"NSApplication\00" +@.c_win = private unnamed_addr constant [9 x i8] c"NSWindow\00" +@.c_str = private unnamed_addr constant [9 x i8] c"NSString\00" +@.c_date = private unnamed_addr constant [7 x i8] c"NSDate\00" +@.c_view = private unnamed_addr constant [7 x i8] c"NSView\00" +@.c_gctx = private unnamed_addr constant [18 x i8] c"NSGraphicsContext\00" +@.c_ludic = private unnamed_addr constant [10 x i8] c"LudicView\00" + +@.s_shared = private unnamed_addr constant [18 x i8] c"sharedApplication\00" +@.s_policy = private unnamed_addr constant [21 x i8] c"setActivationPolicy:\00" +@.s_alloc = private unnamed_addr constant [6 x i8] c"alloc\00" +@.s_initw = private unnamed_addr constant [45 x i8] c"initWithContentRect:styleMask:backing:defer:\00" +@.s_initf = private unnamed_addr constant [15 x i8] c"initWithFrame:\00" +@.s_title = private unnamed_addr constant [10 x i8] c"setTitle:\00" +@.s_utf8 = private unnamed_addr constant [22 x i8] c"stringWithUTF8String:\00" +@.s_setcv = private unnamed_addr constant [16 x i8] c"setContentView:\00" +@.s_center = private unnamed_addr constant [7 x i8] c"center\00" +@.s_mkey = private unnamed_addr constant [22 x i8] c"makeKeyAndOrderFront:\00" +@.s_mfirst = private unnamed_addr constant [20 x i8] c"makeFirstResponder:\00" +@.s_act = private unnamed_addr constant [27 x i8] c"activateIgnoringOtherApps:\00" +@.s_next = private unnamed_addr constant [48 x i8] c"nextEventMatchingMask:untilDate:inMode:dequeue:\00" +@.s_send = private unnamed_addr constant [11 x i8] c"sendEvent:\00" +@.s_dpast = private unnamed_addr constant [12 x i8] c"distantPast\00" +@.s_type = private unnamed_addr constant [5 x i8] c"type\00" +@.s_keycd = private unnamed_addr constant [8 x i8] c"keyCode\00" +@.s_chars = private unnamed_addr constant [28 x i8] c"charactersIgnoringModifiers\00" +@.s_length = private unnamed_addr constant [7 x i8] c"length\00" +@.s_charat = private unnamed_addr constant [18 x i8] c"characterAtIndex:\00" +@.s_disp = private unnamed_addr constant [8 x i8] c"display\00" +@.s_visib = private unnamed_addr constant [10 x i8] c"isVisible\00" +@.s_curctx = private unnamed_addr constant [15 x i8] c"currentContext\00" +@.s_cgctx = private unnamed_addr constant [10 x i8] c"CGContext\00" +@.s_drawr = private unnamed_addr constant [10 x i8] c"drawRect:\00" +@.s_afr = private unnamed_addr constant [23 x i8] c"acceptsFirstResponder\00\00" +@.mode = private unnamed_addr constant [22 x i8] c"kCFRunLoopDefaultMode\00" +@.enc_draw = private unnamed_addr constant [36 x i8] c"v@:{CGRect={CGPoint=dd}{CGSize=dd}}\00" +@.enc_bool = private unnamed_addr constant [4 x i8] c"c@:\00" + +@W_app = internal global ptr null +@W_win = internal global ptr null +@W_view = internal global ptr null +@W_fb = internal global ptr null +@W_fbw = internal global i32 320 +@W_fbh = internal global i32 240 +@W_scale = internal global i32 3 +@W_key = internal global i32 0 +@W_running = internal global i32 1 + +; -drawRect: — blit the framebuffer into the view. +; The NSRect argument is ignored, so it never appears in this signature. +define internal void @ludic_drawRect(ptr %self, ptr %sel) { +entry: + %fb = load ptr, ptr @W_fb + %null = icmp eq ptr %fb, null + br i1 %null, label %out, label %draw +draw: + %w32 = load i32, ptr @W_fbw + %h32 = load i32, ptr @W_fbh + %sc32 = load i32, ptr @W_scale + %w = sext i32 %w32 to i64 + %h = sext i32 %h32 to i64 + %stride = mul i64 %w, 4 + + %cs = call ptr @CGColorSpaceCreateDeviceRGB() + ; kCGImageAlphaNoneSkipFirst (6) | kCGBitmapByteOrder32Little (8192) + %bmp = call ptr @CGBitmapContextCreate(ptr %fb, i64 %w, i64 %h, i64 8, i64 %stride, ptr %cs, i32 8198) + %img = call ptr @CGBitmapContextCreateImage(ptr %bmp) + + %gcls = call ptr @objc_getClass(ptr @.c_gctx) + %sel_cur = call ptr @sel_registerName(ptr @.s_curctx) + %gctx = call ptr @objc_msgSend(ptr %gcls, ptr %sel_cur) + %sel_cg = call ptr @sel_registerName(ptr @.s_cgctx) + %ctx = call ptr @objc_msgSend(ptr %gctx, ptr %sel_cg) + + call void @CGContextSetInterpolationQuality(ptr %ctx, i32 1) ; kCGInterpolationNone + %scd = sitofp i32 %sc32 to double + %wd = sitofp i32 %w32 to double + %hd = sitofp i32 %h32 to double + %dw = fmul double %wd, %scd + %dh = fmul double %hd, %scd + + ; The framebuffer's row 0 is the top row, and a CGImage built over it carries + ; that orientation, so drawing it into the view's context lands right-side-up + ; with no CTM flip. (Adding one here mirrors the game vertically — verified by + ; drawing four different corners and looking at the window.) + %r0 = insertvalue %CGRect undef, double 0.0, 0 + %r1 = insertvalue %CGRect %r0, double 0.0, 1 + %r2 = insertvalue %CGRect %r1, double %dw, 2 + %r3 = insertvalue %CGRect %r2, double %dh, 3 + call void @CGContextDrawImage(ptr %ctx, %CGRect %r3, ptr %img) + + call void @CGImageRelease(ptr %img) + call void @CGContextRelease(ptr %bmp) + call void @CGColorSpaceRelease(ptr %cs) + br label %out +out: + ret void +} + +; -acceptsFirstResponder — so the view receives key events +define internal i8 @ludic_yes(ptr %self, ptr %sel) { +entry: + ret i8 1 +} + +define void @win_open(i32 %w, i32 %h, i32 %scale, ptr %title) { +entry: + store i32 %w, ptr @W_fbw + store i32 %h, ptr @W_fbh + store i32 %scale, ptr @W_scale + + %appcls = call ptr @objc_getClass(ptr @.c_app) + %sel_sh = call ptr @sel_registerName(ptr @.s_shared) + %app = call ptr @objc_msgSend(ptr %appcls, ptr %sel_sh) + store ptr %app, ptr @W_app + %sel_pol = call ptr @sel_registerName(ptr @.s_policy) + %a1 = call ptr (ptr, ptr, i64) @objc_msgSend(ptr %app, ptr %sel_pol, i64 0) + + ; build the view class once: NSView + drawRect: + acceptsFirstResponder + %viewsuper = call ptr @objc_getClass(ptr @.c_view) + %cls = call ptr @objc_allocateClassPair(ptr %viewsuper, ptr @.c_ludic, i64 0) + %sel_draw = call ptr @sel_registerName(ptr @.s_drawr) + %m1 = call i8 @class_addMethod(ptr %cls, ptr %sel_draw, ptr @ludic_drawRect, ptr @.enc_draw) + %sel_afr = call ptr @sel_registerName(ptr @.s_afr) + %m2 = call i8 @class_addMethod(ptr %cls, ptr %sel_afr, ptr @ludic_yes, ptr @.enc_bool) + call void @objc_registerClassPair(ptr %cls) + + %wd = sitofp i32 %w to double + %hd = sitofp i32 %h to double + %scd = sitofp i32 %scale to double + %pw = fmul double %wd, %scd + %ph = fmul double %hd, %scd + %r0 = insertvalue %CGRect undef, double 0.0, 0 + %r1 = insertvalue %CGRect %r0, double 0.0, 1 + %r2 = insertvalue %CGRect %r1, double %pw, 2 + %rect = insertvalue %CGRect %r2, double %ph, 3 + + %wincls = call ptr @objc_getClass(ptr @.c_win) + %sel_alloc = call ptr @sel_registerName(ptr @.s_alloc) + %w0 = call ptr @objc_msgSend(ptr %wincls, ptr %sel_alloc) + %sel_initw = call ptr @sel_registerName(ptr @.s_initw) + ; NSWindowStyleMaskTitled|Closable = 3, NSBackingStoreBuffered = 2 + %win = call ptr (ptr, ptr, %CGRect, i64, i64, i8) @objc_msgSend(ptr %w0, ptr %sel_initw, %CGRect %rect, i64 3, i64 2, i8 0) + store ptr %win, ptr @W_win + + %strcls = call ptr @objc_getClass(ptr @.c_str) + %sel_utf8 = call ptr @sel_registerName(ptr @.s_utf8) + %nstitle = call ptr (ptr, ptr, ptr) @objc_msgSend(ptr %strcls, ptr %sel_utf8, ptr %title) + %sel_title = call ptr @sel_registerName(ptr @.s_title) + %a2 = call ptr (ptr, ptr, ptr) @objc_msgSend(ptr %win, ptr %sel_title, ptr %nstitle) + + %v0 = call ptr @objc_msgSend(ptr %cls, ptr %sel_alloc) + %sel_initf = call ptr @sel_registerName(ptr @.s_initf) + %view = call ptr (ptr, ptr, %CGRect) @objc_msgSend(ptr %v0, ptr %sel_initf, %CGRect %rect) + store ptr %view, ptr @W_view + %sel_setcv = call ptr @sel_registerName(ptr @.s_setcv) + %a3 = call ptr (ptr, ptr, ptr) @objc_msgSend(ptr %win, ptr %sel_setcv, ptr %view) + %sel_center = call ptr @sel_registerName(ptr @.s_center) + %a4 = call ptr @objc_msgSend(ptr %win, ptr %sel_center) + %sel_mkey = call ptr @sel_registerName(ptr @.s_mkey) + %a5 = call ptr (ptr, ptr, ptr) @objc_msgSend(ptr %win, ptr %sel_mkey, ptr null) + %sel_mfirst = call ptr @sel_registerName(ptr @.s_mfirst) + %a6 = call ptr (ptr, ptr, ptr) @objc_msgSend(ptr %win, ptr %sel_mfirst, ptr %view) + %sel_act = call ptr @sel_registerName(ptr @.s_act) + %a7 = call ptr (ptr, ptr, i8) @objc_msgSend(ptr %app, ptr %sel_act, i8 1) + ret void +} + +; Drain the event queue, remembering the last key pressed. Arrow keys map onto +; WASD and escape onto 'q', matching what the C backend did. +define i32 @win_poll() { +entry: + store i32 0, ptr @W_key + %app = load ptr, ptr @W_app + %none = icmp eq ptr %app, null + br i1 %none, label %done, label %setup +setup: + %sel_next = call ptr @sel_registerName(ptr @.s_next) + %sel_send = call ptr @sel_registerName(ptr @.s_send) + %sel_dp = call ptr @sel_registerName(ptr @.s_dpast) + %sel_type = call ptr @sel_registerName(ptr @.s_type) + %sel_kc = call ptr @sel_registerName(ptr @.s_keycd) + %sel_ch = call ptr @sel_registerName(ptr @.s_chars) + %sel_len = call ptr @sel_registerName(ptr @.s_length) + %sel_cat = call ptr @sel_registerName(ptr @.s_charat) + %sel_utf8 = call ptr @sel_registerName(ptr @.s_utf8) + %datecls = call ptr @objc_getClass(ptr @.c_date) + %strcls = call ptr @objc_getClass(ptr @.c_str) + %mode = call ptr (ptr, ptr, ptr) @objc_msgSend(ptr %strcls, ptr %sel_utf8, ptr @.mode) + br label %pump +pump: + %date = call ptr @objc_msgSend(ptr %datecls, ptr %sel_dp) + %ev = call ptr (ptr, ptr, i64, ptr, ptr, i8) @objc_msgSend(ptr %app, ptr %sel_next, i64 -1, ptr %date, ptr %mode, i8 1) + %got = icmp ne ptr %ev, null + br i1 %got, label %handle, label %finish +handle: + %ty = call i64 (ptr, ptr) @objc_msgSend(ptr %ev, ptr %sel_type) + %iskey = icmp eq i64 %ty, 10 ; NSEventTypeKeyDown + br i1 %iskey, label %key, label %forward +key: + %kc = call i16 (ptr, ptr) @objc_msgSend(ptr %ev, ptr %sel_kc) + %kc32 = zext i16 %kc to i32 + switch i32 %kc32, label %fromchars [ + i32 126, label %k_w + i32 125, label %k_s + i32 123, label %k_a + i32 124, label %k_d + i32 49, label %k_space + i32 36, label %k_ret + i32 53, label %k_esc + ] +k_w: store i32 119, ptr @W_key br label %forward +k_s: store i32 115, ptr @W_key br label %forward +k_a: store i32 97, ptr @W_key br label %forward +k_d: store i32 100, ptr @W_key br label %forward +k_space: store i32 32, ptr @W_key br label %forward +k_ret: store i32 10, ptr @W_key br label %forward +k_esc: + store i32 113, ptr @W_key + store i32 0, ptr @W_running + br label %forward +fromchars: + %chars = call ptr (ptr, ptr) @objc_msgSend(ptr %ev, ptr %sel_ch) + %clen = call i64 (ptr, ptr) @objc_msgSend(ptr %chars, ptr %sel_len) + %hasch = icmp sgt i64 %clen, 0 + br i1 %hasch, label %takechar, label %forward +takechar: + %ch = call i16 (ptr, ptr, i64) @objc_msgSend(ptr %chars, ptr %sel_cat, i64 0) + %ch32 = zext i16 %ch to i32 + store i32 %ch32, ptr @W_key + %isq = icmp eq i32 %ch32, 113 + br i1 %isq, label %quit, label %forward +quit: + store i32 0, ptr @W_running + br label %forward +forward: + %fwd = call ptr (ptr, ptr, ptr) @objc_msgSend(ptr %app, ptr %sel_send, ptr %ev) + br label %pump +finish: + ; a closed window ends the run + %win = load ptr, ptr @W_win + %hw = icmp ne ptr %win, null + br i1 %hw, label %checkvis, label %done +checkvis: + %sel_vis = call ptr @sel_registerName(ptr @.s_visib) + %vis = call i8 (ptr, ptr) @objc_msgSend(ptr %win, ptr %sel_vis) + %gone = icmp eq i8 %vis, 0 + br i1 %gone, label %closed, label %done +closed: + store i32 0, ptr @W_running + br label %done +done: + %k = load i32, ptr @W_key + ret i32 %k +} + +define void @win_present(ptr %fb, i32 %w, i32 %h) { +entry: + store ptr %fb, ptr @W_fb + store i32 %w, ptr @W_fbw + store i32 %h, ptr @W_fbh + %view = load ptr, ptr @W_view + %none = icmp eq ptr %view, null + br i1 %none, label %out, label %show +show: + %sel_disp = call ptr @sel_registerName(ptr @.s_disp) + %d = call ptr @objc_msgSend(ptr %view, ptr %sel_disp) + %u = call i32 @usleep(i32 16000) ; ~60 fps + br label %out +out: + ret void +} + +define i32 @win_running() { +entry: + %r = load i32, ptr @W_running + ret i32 %r +} + +define void @win_close() { +entry: + store i32 0, ptr @W_running + ret void +} diff --git a/runtime/native/core.ludic b/runtime/native/core.ludic new file mode 100644 index 00000000..b6f89c1f --- /dev/null +++ b/runtime/native/core.ludic @@ -0,0 +1,394 @@ +# ============================================================================ +# runtime/native/core.ludic — the Ludic runtime, written in Ludic. +# +# This is what the native backend links instead of a C runtime. Everything a +# game touches through a builtin — the framebuffer, rectangles, text, the +# registers, the RNG, input, the frame dump — is implemented right here in +# Ludic and compiled to machine code by ludicc like any other Ludic source. +# +# Underneath it there is exactly one layer, and it is not C: the compiler +# intrinsics (mem_alloc, peek8/poke8, peek32/poke32, file_open/file_write, +# read_byte, …) lower to direct calls into the platform's C ABI — malloc, +# fwrite, getchar. That ABI is the operating system's interface, the same floor +# Rust and Swift stand on. No C source is compiled at any point in the build. +# +# A builtin `clear(c)` in a game resolves to `rt_clear(c)` here; that is the +# whole protocol. Swap this file and you have swapped the runtime. +# +# This file is a fragment: ludicc splices it into every native build. It is not +# a `game`/`module` block of its own. +# ============================================================================ + +# ---- state ---------------------------------------------------------------- +var rt_fb: ptr = ptr_null() # framebuffer, one i32 (0x00RRGGBB) per pixel +var rt_fbw: int = 320 +var rt_fbh: int = 240 +var rt_regs: ptr = ptr_null() # the 64 general-purpose game registers +var rt_rng: int = 305419896 # xorshift32 state +var rt_alive: int = 1 # platform still running? + +# 5x7 glyphs for ASCII 32..90, 7 rows per glyph, each row a 5-bit mask stored +# biased by '0' so the whole font is one printable string literal. +fn rt_font() -> str { + return "00000004444404000000000000000000000IJ4:FC000000000000000000000000000000E>O>E0044O4400000448000O000000004012448@@>ACEIA>4<4444>>A168@ON11>11N26:BO22O@N11A>>@@NAA>O124888>AA>AA>>AA?11>04004000000000024842000O0O000842480>A164040000000>AAOAAANAANAAN>A@@@A>LBAAABLO@@L@@OO@@L@@@>A@GAA>AAAOAAA>44444>7222BBAAAAA>NAAN@@@>AAAEB=NAANDBA>A@>1A>O444444AAAAAA>AAAAA:4AAAEEKAAA:4:AAAA:4444O1248@O" +} + +fn rt_init() -> void { + rt_fb = mem_alloc(320 * 240 * 4) + rt_regs = mem_alloc(64 * 4) + mem_set(rt_regs, 0, 64 * 4) + rt_map = mem_alloc(96 * 64) + mem_set(rt_map, 32, 96 * 64) + rt_statusbuf = mem_alloc(96) + poke8(rt_statusbuf, 0, 0) + rt_image_init() + rt_tt_init() + rt_ui_init() + rt_clear(0) + if is_windowed() { + win_open(rt_fbw, rt_fbh, 3, game_title()) + } +} + +fn rt_shutdown() -> void { + if is_windowed() { + win_close() + return + } + rt_dump_ppm("out.ppm") +} + +# ---- framebuffer ---------------------------------------------------------- +fn rt_clear(c: int) -> void { + let n = rt_fbw * rt_fbh + for i in 0 .. n { + poke32(rt_fb, i, c) + } +} + +fn rt_put_px(x: int, y: int, c: int) -> void { + if x < 0 { return } + if y < 0 { return } + if x >= rt_fbw { return } + if y >= rt_fbh { return } + poke32(rt_fb, y * rt_fbw + x, c) +} + +fn rt_fill_rect(x: int, y: int, w: int, h: int, c: int) -> void { + let x0 = max(0, x) + let y0 = max(0, y) + let x1 = min(rt_fbw, x + w) + let y1 = min(rt_fbh, y + h) + let j = y0 + while j < y1 { + let row = j * rt_fbw + let i = x0 + while i < x1 { + poke32(rt_fb, row + i, c) + i = i + 1 + } + j = j + 1 + } +} + +fn rt_frame_rect(x: int, y: int, w: int, h: int, c: int) -> void { + rt_fill_rect(x, y, w, 1, c) + rt_fill_rect(x, y + h - 1, w, 1, c) + rt_fill_rect(x, y, 1, h, c) + rt_fill_rect(x + w - 1, y, 1, h, c) +} + +# Windowed: hand the framebuffer to the platform layer, which blits it into +# the view. Headless: nothing to do until shutdown writes the last frame out. +fn rt_present() -> void { + if is_windowed() { + win_present(rt_fb, rt_fbw, rt_fbh) + } +} + +# ---- text ----------------------------------------------------------------- +fn rt_glyph(x: int, y: int, ch: int, colour: int, sc: int) -> void { + let c = ch + if c >= 97 { + if c <= 122 { c = c - 32 } + } + if c < 32 { return } + if c > 90 { return } + let base = (c - 32) * 7 + let font = rt_font() + for row in 0 .. 7 { + let bits = peek8(font, base + row) - 48 + let b = bits + for cc in 0 .. 5 { + let on = b / 16 + if on == 1 { + rt_fill_rect(x + cc * sc, y + row * sc, sc, sc, colour) + } + b = (b - on * 16) * 2 + } + } +} + +fn rt_text(x: int, y: int, s: str, colour: int, sc: int) -> void { + let i = 0 + let cx = x + let ch = peek8(s, 0) + while ch != 0 { + rt_glyph(cx, y, ch, colour, sc) + cx = cx + 6 * sc + i = i + 1 + ch = peek8(s, i) + } +} + +fn rt_text_int(x: int, y: int, n: int, colour: int, sc: int) -> void { + if n == 0 { + rt_glyph(x, y, 48, colour, sc) + return + } + let v = n + let cx = x + if v < 0 { + rt_glyph(cx, y, 45, colour, sc) + cx = cx + 6 * sc + v = 0 - v + } + let digits = 0 + let t = v + while t > 0 { + digits = digits + 1 + t = t / 10 + } + let p = digits + while p > 0 { + let div = 1 + for k in 1 .. p { + div = div * 10 + } + rt_glyph(cx, y, 48 + (v / div) % 10, colour, sc) + cx = cx + 6 * sc + p = p - 1 + } +} + +# ---- registers ------------------------------------------------------------ +fn rt_reg(i: int) -> int { + if i < 0 { return 0 } + if i >= 64 { return 0 } + return peek32(rt_regs, i) +} + +fn rt_setreg(i: int, v: int) -> void { + if i < 0 { return } + if i >= 64 { return } + poke32(rt_regs, i, v) +} + +# ---- rng (xorshift32) ----------------------------------------------------- +fn rt_seed(s: int) -> void { + if s == 0 { + rt_rng = 305419896 + return + } + rt_rng = s +} + +# xorshift32 (Marsaglia). Runs on the raw 32-bit pattern, so the sign bit is +# masked off only when a caller asks for a number. +fn rt_next_rand() -> int { + let x = rt_rng + x = bxor(x, shl(x, 13)) + x = bxor(x, shr(x, 17)) + x = bxor(x, shl(x, 5)) + rt_rng = x + return band(x, 2147483647) +} + +fn rt_rng_range(lo: int, hi: int) -> int { + if hi <= lo { return lo } + return lo + rt_next_rand() % (hi - lo + 1) +} + +fn rt_rng_chance(pct: int) -> bool { + return rt_next_rand() % 100 < pct +} + +# ---- platform: input ------------------------------------------------------ +fn rt_poll() -> int { + if is_windowed() { + return win_poll() + } + let c = read_byte() + if c < 0 { + rt_alive = 0 + return 0 + } + if c == 113 { # 'q' quits, as in the headless C platform + rt_alive = 0 + } + return c +} + +fn rt_running() -> bool { + if is_windowed() { + return win_running() + } + return rt_alive +} + +# ---- writing the frame out ------------------------------------------------ +fn rt_put_str(buf: ptr, at: int, s: str) -> int { + let i = 0 + let n = at + let ch = peek8(s, 0) + while ch != 0 { + poke8(buf, n, ch) + n = n + 1 + i = i + 1 + ch = peek8(s, i) + } + return n +} + +fn rt_put_int(buf: ptr, at: int, v: int) -> int { + if v == 0 { + poke8(buf, at, 48) + return at + 1 + } + let digits = 0 + let t = v + while t > 0 { + digits = digits + 1 + t = t / 10 + } + let n = at + let p = digits + while p > 0 { + let div = 1 + for k in 1 .. p { + div = div * 10 + } + poke8(buf, n, 48 + (v / div) % 10) + n = n + 1 + p = p - 1 + } + return n +} + +fn rt_dump_ppm(path: str) -> void { + let f = file_open(path, "wb") + if ptr_is_null(f) { return } + + let hdr = mem_alloc(64) + let n = rt_put_str(hdr, 0, "P6\n") + n = rt_put_int(hdr, n, rt_fbw) + n = rt_put_str(hdr, n, " ") + n = rt_put_int(hdr, n, rt_fbh) + n = rt_put_str(hdr, n, "\n255\n") + file_write(f, hdr, n) + + let px = rt_fbw * rt_fbh + let buf = mem_alloc(px * 3) + for i in 0 .. px { + let c = peek32(rt_fb, i) + poke8(buf, i * 3, (c / 65536) % 256) + poke8(buf, i * 3 + 1, (c / 256) % 256) + poke8(buf, i * 3 + 2, c % 256) + } + file_write(f, buf, px * 3) + file_close(f) + mem_free(buf) + mem_free(hdr) +} + +import "inflate.ludic" +import "image.ludic" +import "truetype.ludic" +import "ui.ludic" + +# ---- tilemap -------------------------------------------------------------- +# A character grid the game paints with map_row() and reads with tile(). Stored +# as one byte per cell in a flat buffer; out-of-bounds reads answer '#' so a +# caller can treat the edge of the world as wall without special-casing it. +var rt_map: ptr = ptr_null() +var rt_mapw: int = 0 +var rt_maph: int = 0 + +fn rt_map_size(w: int, h: int) -> void { + rt_mapw = clamp(w, 0, 96) + rt_maph = clamp(h, 0, 64) + mem_set(rt_map, 32, 96 * 64) +} + +fn rt_map_row(y: int, s: str) -> void { + if y < 0 { return } + if y >= 64 { return } + let x = 0 + let ch = peek8(s, 0) + while ch != 0 { + if x >= 96 { return } + poke8(rt_map, y * 96 + x, ch) + x = x + 1 + ch = peek8(s, x) + } +} + +fn rt_tile(x: int, y: int) -> int { + if x < 0 { return 35 } + if y < 0 { return 35 } + if x >= rt_mapw { return 35 } + if y >= rt_maph { return 35 } + return peek8(rt_map, y * 96 + x) +} + +# ---- status line ---------------------------------------------------------- +# One persistent string of feedback/dialogue, copied into runtime-owned memory +# so it survives whatever the caller does with the original. +var rt_statusbuf: ptr = ptr_null() + +fn rt_status(s: str) -> void { + let i = 0 + let ch = peek8(s, 0) + while ch != 0 { + if i >= 95 { ch = 0 } + if ch != 0 { + poke8(rt_statusbuf, i, ch) + i = i + 1 + ch = peek8(s, i) + } + } + poke8(rt_statusbuf, i, 0) +} + +fn rt_status_text() -> ptr { + return rt_statusbuf +} + +# ---- snapshot: the runtime serialises its own half ------------------------ +# The compiler writes the ECS (entities, components, archetype kinds) because +# only it knows their shape. Everything below belongs to the runtime, so the +# runtime writes it — same order both ways. +fn rt_save_state(f: ptr) -> void { + let w = mem_alloc(16) + poke32(w, 0, rt_rng) + poke32(w, 1, rt_mapw) + poke32(w, 2, rt_maph) + poke32(w, 3, rt_alive) + file_write(f, w, 16) + file_write(f, rt_regs, 64 * 4) + file_write(f, rt_map, 96 * 64) + file_write(f, rt_statusbuf, 96) + mem_free(w) +} + +fn rt_load_state(f: ptr) -> void { + let w = mem_alloc(16) + file_read(f, w, 16) + rt_rng = peek32(w, 0) + rt_mapw = peek32(w, 1) + rt_maph = peek32(w, 2) + file_read(f, rt_regs, 64 * 4) + file_read(f, rt_map, 96 * 64) + file_read(f, rt_statusbuf, 96) + mem_free(w) +} diff --git a/runtime/native/image.ludic b/runtime/native/image.ludic new file mode 100644 index 00000000..15d23cd9 --- /dev/null +++ b/runtime/native/image.ludic @@ -0,0 +1,436 @@ +# ============================================================================ +# image.ludic — PNG decoding, images and sprites, written in Ludic. +# +# Replaces the C runtime's image half. Reads a real .png off disk, inflates the +# IDAT stream with the Ludic DEFLATE decoder next door, reverses the per-scanline +# filters, and expands whatever colour type the file uses into 0xAARRGGBB. +# +# Supported: 8/4/2/1-bit greyscale, 8-bit truecolour, indexed with PLTE/tRNS, +# greyscale+alpha and RGBA — the same set the C runtime handled. +# ============================================================================ + +const IMG_MAX: int = 32 +const SPR_MAX: int = 160 +const SPR_SZ: int = 16 + +var img_px: ptr = ptr_null() # IMG_MAX pointers to RGBA buffers +var img_w: ptr = ptr_null() +var img_h: ptr = ptr_null() +var img_n: int = 0 + +var spr_px: ptr = ptr_null() # SPR_MAX * 16 * 16 RGBA pixels, one block +var spr_n: int = 0 + +fn rt_image_init() -> void { + img_px = mem_alloc(IMG_MAX * 8) + img_w = mem_alloc(IMG_MAX * 4) + img_h = mem_alloc(IMG_MAX * 4) + spr_px = mem_alloc(SPR_MAX * SPR_SZ * SPR_SZ * 4) + mem_set(spr_px, 0, SPR_MAX * SPR_SZ * SPR_SZ * 4) +} + +# ---- decoding ------------------------------------------------------------- +fn png_be32(b: ptr, at: int) -> int { + return bor(bor(shl(peek8(b, at), 24), shl(peek8(b, at + 1), 16)), + bor(shl(peek8(b, at + 2), 8), peek8(b, at + 3))) +} + +fn png_tag(b: ptr, at: int, a: int, c: int, d: int, e: int) -> bool { + if peek8(b, at) != a { return false } + if peek8(b, at + 1) != c { return false } + if peek8(b, at + 2) != d { return false } + if peek8(b, at + 3) != e { return false } + return true +} + +fn rt_read_file(path: str) -> ptr { + let f = file_open(path, "rb") + if ptr_is_null(f) { return ptr_null() } + file_seek(f, 0, 2) + let n = file_tell(f) + file_seek(f, 0, 0) + if n <= 0 { file_close(f) return ptr_null() } + let buf = mem_alloc(n + 8) + file_read(f, buf, n) + file_close(f) + rt_file_len = n + return buf +} +var rt_file_len: int = 0 + +# decoded image is left in these; -1 width means failure +var png_w: int = 0 +var png_h: int = 0 +var png_px: ptr = ptr_null() + +fn rt_decode_png(path: str) -> bool { + png_w = 0 + png_h = 0 + png_px = ptr_null() + let d = rt_read_file(path) + if ptr_is_null(d) { return false } + let size = rt_file_len + if size < 8 { mem_free(d) return false } + if peek8(d, 0) != 137 { mem_free(d) return false } + if peek8(d, 1) != 80 { mem_free(d) return false } + + let w = 0 + let h = 0 + let bd = 0 + let ct = 0 + let plte = mem_alloc(768) + let trns = mem_alloc(256) + let ntrns = 0 + let idat = mem_alloc(size) + let idlen = 0 + let i = 8 + let done = 0 + + while done == 0 { + if i + 8 > size { done = 1 } + if done == 0 { + let ln = png_be32(d, i) + let typ = i + 4 + let body = i + 8 + if ln < 0 { done = 1 } + if body + ln > size { done = 1 } + if done == 0 { + if png_tag(d, typ, 73, 72, 68, 82) { # IHDR + w = png_be32(d, body) + h = png_be32(d, body + 4) + bd = peek8(d, body + 8) + ct = peek8(d, body + 9) + } + if png_tag(d, typ, 80, 76, 84, 69) { # PLTE + let m = min(ln, 768) + for k in 0 .. m { poke8(plte, k, peek8(d, body + k)) } + } + if png_tag(d, typ, 116, 82, 78, 83) { # tRNS + ntrns = min(ln, 256) + for k in 0 .. ntrns { poke8(trns, k, peek8(d, body + k)) } + } + if png_tag(d, typ, 73, 68, 65, 84) { # IDAT + for k in 0 .. ln { poke8(idat, idlen + k, peek8(d, body + k)) } + idlen = idlen + ln + } + if png_tag(d, typ, 73, 69, 78, 68) { done = 1 } # IEND + i = i + 12 + ln + } + } + } + + if w <= 0 { mem_free(d) return false } + if h <= 0 { mem_free(d) return false } + + let channels = 1 + if ct == 2 { channels = 3 } + if ct == 6 { channels = 4 } + if ct == 4 { channels = 2 } + let bppbits = bd * channels + let fbpp = (bppbits + 7) / 8 + if fbpp < 1 { fbpp = 1 } + let stride = (w * bppbits + 7) / 8 + let rawlen = h * (stride + 1) + let raw = mem_alloc(rawlen + 8) + if z_uncompress(idat, idlen, raw, rawlen) < 0 { + mem_free(d) mem_free(raw) mem_free(idat) + return false + } + + # reverse the per-scanline filters, in place + for y in 0 .. h { + let line = y * (stride + 1) + let ft = peek8(raw, line) + let cur = line + 1 + let prev = cur - (stride + 1) + for x in 0 .. stride { + let a = 0 + let b = 0 + let c = 0 + if x >= fbpp { a = peek8(raw, cur + x - fbpp) } + if y > 0 { b = peek8(raw, prev + x) } + if x >= fbpp { if y > 0 { c = peek8(raw, prev + x - fbpp) } } + let v = peek8(raw, cur + x) + if ft == 1 { v = v + a } + if ft == 2 { v = v + b } + if ft == 3 { v = v + (a + b) / 2 } + if ft == 4 { + let p = a + b - c + let pa = abs(p - a) + let pb = abs(p - b) + let pc = abs(p - c) + let pick = c + if pb <= pc { pick = b } + if pa <= pb { if pa <= pc { pick = a } } + v = v + pick + } + poke8(raw, cur + x, band(v, 255)) + } + } + + # expand to 0xAARRGGBB + let out = mem_alloc(w * h * 4) + let maxv = shl(1, bd) - 1 + for y in 0 .. h { + let row = y * (stride + 1) + 1 + for x in 0 .. w { + let R = 0 + let G = 0 + let B = 0 + let A = 255 + if ct == 6 { + R = peek8(raw, row + x * 4) + G = peek8(raw, row + x * 4 + 1) + B = peek8(raw, row + x * 4 + 2) + A = peek8(raw, row + x * 4 + 3) + } + if ct == 2 { + R = peek8(raw, row + x * 3) + G = peek8(raw, row + x * 3 + 1) + B = peek8(raw, row + x * 3 + 2) + } + if ct == 4 { + R = peek8(raw, row + x * 2) + G = R + B = R + A = peek8(raw, row + x * 2 + 1) + } + if ct == 3 { + let bp = x * bd + let idx = band(shr(peek8(raw, row + bp / 8), 8 - bd - bp % 8), maxv) + R = peek8(plte, idx * 3) + G = peek8(plte, idx * 3 + 1) + B = peek8(plte, idx * 3 + 2) + if idx < ntrns { A = peek8(trns, idx) } + } + if ct == 0 { + let bp = x * bd + let s = band(shr(peek8(raw, row + bp / 8), 8 - bd - bp % 8), maxv) + let g = s + if bd != 8 { g = s * 255 / maxv } + R = g + G = g + B = g + } + poke32(out, y * w + x, bor(bor(shl(A, 24), shl(R, 16)), bor(shl(G, 8), B))) + } + } + + mem_free(d) + mem_free(idat) + mem_free(raw) + mem_free(plte) + mem_free(trns) + png_w = w + png_h = h + png_px = out + return true +} + +# ---- images --------------------------------------------------------------- +fn rt_image_load(path: str) -> int { + if img_n >= IMG_MAX { return 0 - 1 } + if rt_decode_png(path) == false { return 0 - 1 } + let id = img_n + img_n = img_n + 1 + pokep(img_px, id, png_px) + poke32(img_w, id, png_w) + poke32(img_h, id, png_h) + return id +} + +fn rt_blend_px(x: int, y: int, argb: int) -> void { + let a = band(shr(argb, 24), 255) + if a == 0 { return } + if x < 0 { return } + if y < 0 { return } + if x >= rt_fbw { return } + if y >= rt_fbh { return } + let r = band(shr(argb, 16), 255) + let g = band(shr(argb, 8), 255) + let b = band(argb, 255) + if a != 255 { + let dst = peek32(rt_fb, y * rt_fbw + x) + let dr = band(shr(dst, 16), 255) + let dg = band(shr(dst, 8), 255) + let db = band(dst, 255) + r = (r * a + dr * (255 - a)) / 255 + g = (g * a + dg * (255 - a)) / 255 + b = (b * a + db * (255 - a)) / 255 + } + poke32(rt_fb, y * rt_fbw + x, bor(bor(shl(r, 16), shl(g, 8)), b)) +} + +fn rt_draw_image(id: int, dx: int, dy: int) -> void { + if id < 0 { return } + if id >= img_n { return } + let w = peek32(img_w, id) + let h = peek32(img_h, id) + let s = peekp(img_px, id) + for y in 0 .. h { + for x in 0 .. w { + rt_blend_px(dx + x, dy + y, peek32(s, y * w + x)) + } + } +} + +fn rt_draw_image_scaled(id: int, dx: int, dy: int, dw: int, dh: int) -> void { + if id < 0 { return } + if id >= img_n { return } + if dw <= 0 { return } + if dh <= 0 { return } + let w = peek32(img_w, id) + let h = peek32(img_h, id) + let s = peekp(img_px, id) + for y in 0 .. dh { + for x in 0 .. dw { + rt_blend_px(dx + x, dy + y, peek32(s, (y * h / dh) * w + x * w / dw)) + } + } +} + +# map one destination axis onto the source for a 9-slice: the two insets are +# copied 1:1 and only the middle stretches +fn rt_9map(d: int, dsz: int, ssz: int, inset: int) -> int { + if inset * 2 >= dsz { return d * ssz / max(dsz, 1) } + if inset * 2 >= ssz { return d * ssz / max(dsz, 1) } + if d < inset { return d } + if d >= dsz - inset { return ssz - (dsz - d) } + return inset + (d - inset) * (ssz - 2 * inset) / (dsz - 2 * inset) +} + +fn rt_draw_9slice(id: int, dx: int, dy: int, dw: int, dh: int, inset: int) -> void { + if id < 0 { return } + if id >= img_n { return } + if dw <= 0 { return } + if dh <= 0 { return } + let w = peek32(img_w, id) + let h = peek32(img_h, id) + let s = peekp(img_px, id) + for y in 0 .. dh { + let sy = rt_9map(y, dh, h, inset) + for x in 0 .. dw { + rt_blend_px(dx + x, dy + y, peek32(s, sy * w + rt_9map(x, dw, w, inset))) + } + } +} + +# ---- sprites (16x16 art) -------------------------------------------------- +fn rt_load_png(path: str) -> int { + if spr_n >= SPR_MAX { return 0 - 1 } + if rt_decode_png(path) == false { return 0 - 1 } + let id = spr_n + spr_n = spr_n + 1 + let base = id * SPR_SZ * SPR_SZ + for y in 0 .. SPR_SZ { + for x in 0 .. SPR_SZ { + let px = 0 + if x < png_w { + if y < png_h { + let c = peek32(png_px, y * png_w + x) + if band(shr(c, 24), 255) >= 128 { px = bor(shl(255, 24), band(c, 16777215)) } + } + } + poke32(spr_px, base + y * SPR_SZ + x, px) + } + } + mem_free(png_px) + png_px = ptr_null() + return id +} + +fn rt_draw_sprite(id: int, px: int, py: int) -> void { + if id < 0 { return } + if id >= spr_n { return } + let base = id * SPR_SZ * SPR_SZ + for y in 0 .. SPR_SZ { + for x in 0 .. SPR_SZ { + let p = peek32(spr_px, base + y * SPR_SZ + x) + if band(shr(p, 24), 255) != 0 { + rt_put_px(px + x, py + y, band(p, 16777215)) + } + } + } +} + +fn rt_draw_sprite_scaled(id: int, px: int, py: int, sc: int) -> void { + if id < 0 { return } + if id >= spr_n { return } + if sc < 1 { return } + let base = id * SPR_SZ * SPR_SZ + for y in 0 .. SPR_SZ { + for x in 0 .. SPR_SZ { + let p = peek32(spr_px, base + y * SPR_SZ + x) + if band(shr(p, 24), 255) != 0 { + rt_fill_rect(px + x * sc, py + y * sc, sc, sc, band(p, 16777215)) + } + } + } +} + +# ---- .lspr sprite sheets (palette + ASCII rows) --------------------------- +fn rt_hexval(c: int) -> int { + if c >= 48 { if c <= 57 { return c - 48 } } + if c >= 97 { if c <= 102 { return c - 87 } } + if c >= 65 { if c <= 70 { return c - 55 } } + return 0 - 1 +} + +fn rt_load_sprites(path: str) -> void { + let d = rt_read_file(path) + if ptr_is_null(d) { spr_n = 0 return } + let size = rt_file_len + let pal = mem_alloc(128 * 4) + mem_set(pal, 0, 128 * 4) + let cur = 0 - 1 + let row = 0 + let i = 0 + while i < size { + let start = i + let len = 0 + let j = start + while j < size { + let ch = peek8(d, j) + if ch == 10 { j = size } else { len = len + 1 j = j + 1 } + } + let c0 = peek8(d, start) + if c0 == 112 { # 'p' — "pal " + let ch = peek8(d, start + 4) + let v = 0 + for k in 0 .. 6 { + let hv = rt_hexval(peek8(d, start + 6 + k)) + if hv >= 0 { v = v * 16 + hv } + } + if ch < 128 { poke32(pal, ch, bor(shl(255, 24), v)) } + } + if c0 == 115 { # 's' — "spr" starts a new sprite + cur = 0 - 1 + if spr_n < SPR_MAX { + cur = spr_n + spr_n = spr_n + 1 + mem_set(ptr_add(spr_px, cur * SPR_SZ * SPR_SZ * 4), 0, SPR_SZ * SPR_SZ * 4) + } + row = 0 + } + if c0 != 112 { + if c0 != 115 { + if c0 != 35 { # '#' comment + if cur >= 0 { + if row < SPR_SZ { + for x in 0 .. SPR_SZ { + if x < len { + poke32(spr_px, cur * SPR_SZ * SPR_SZ + row * SPR_SZ + x, + peek32(pal, band(peek8(d, start + x), 127))) + } + } + row = row + 1 + } + } + } + } + } + i = start + len + 1 + } + mem_free(pal) + mem_free(d) +} diff --git a/runtime/native/inflate.ludic b/runtime/native/inflate.ludic new file mode 100644 index 00000000..8a6108fa --- /dev/null +++ b/runtime/native/inflate.ludic @@ -0,0 +1,276 @@ +# ============================================================================ +# inflate.ludic — DEFLATE decompression (RFC 1951), written in Ludic. +# +# PNG stores its pixels zlib-compressed, so decoding one means implementing +# inflate. The C runtime linked zlib for this. We don't: zlib is not present by +# default on every target Ludic compiles for (Windows especially), and shipping +# a dependency to read a sprite is a poor trade when the algorithm is this +# small. So it lives here, in the language. +# +# The decoder is the canonical-Huffman formulation from Mark Adler's `puff`: +# a symbol table plus per-length counts, walked one bit at a time. Slower than +# a lookup-table decoder, and entirely fast enough to load sprites at startup. +# ============================================================================ + +# ---- bit reader (DEFLATE packs bits least-significant-first) --------------- +var z_src: ptr = ptr_null() +var z_len: int = 0 +var z_pos: int = 0 +var z_bitbuf: int = 0 +var z_bitcnt: int = 0 +var z_err: int = 0 + +fn z_start(src: ptr, len: int) -> void { + z_src = src + z_len = len + z_pos = 0 + z_bitbuf = 0 + z_bitcnt = 0 + z_err = 0 +} + +fn z_bits(need: int) -> int { + let val = z_bitbuf + while z_bitcnt < need { + if z_pos >= z_len { + z_err = 1 + return 0 + } + val = bor(val, shl(peek8(z_src, z_pos), z_bitcnt)) + z_pos = z_pos + 1 + z_bitcnt = z_bitcnt + 8 + } + z_bitbuf = shr(val, need) + z_bitcnt = z_bitcnt - need + return band(val, shl(1, need) - 1) +} + +# ---- Huffman tables ------------------------------------------------------- +# A table is a single buffer: 16 length-counts followed by the symbols in +# canonical order. One allocation, no structs. +fn z_table_new(nsym: int) -> ptr { + return mem_alloc((16 + nsym) * 4) +} + +# lengths[i] = code length of symbol i (0 = symbol unused) +fn z_table_build(table: ptr, lengths: ptr, n: int) -> void { + for i in 0 .. 16 { + poke32(table, i, 0) + } + for s in 0 .. n { + let l = peek32(lengths, s) + poke32(table, l, peek32(table, l) + 1) + } + poke32(table, 0, 0) # length 0 means "not present" + # offset of each length's first symbol + let offs = mem_alloc(16 * 4) + poke32(offs, 1, 0) + for l in 1 .. 15 { + poke32(offs, l + 1, peek32(offs, l) + peek32(table, l)) + } + for s in 0 .. n { + let l = peek32(lengths, s) + if l != 0 { + poke32(table, 16 + peek32(offs, l), s) + poke32(offs, l, peek32(offs, l) + 1) + } + } + mem_free(offs) +} + +fn z_decode(table: ptr) -> int { + let code = 0 + let first = 0 + let index = 0 + for len in 1 .. 16 { + code = bor(code, z_bits(1)) + let count = peek32(table, len) + if code - first < count { + return peek32(table, 16 + index + (code - first)) + } + index = index + count + first = shl(first + count, 1) + code = shl(code, 1) + } + z_err = 1 + return -1 +} + +# ---- length / distance code tables (RFC 1951 section 3.2.5) --------------- +fn z_len_base(sym: int) -> int { + if sym < 8 { return 3 + sym } + if sym == 28 { return 258 } + let extra = (sym - 4) / 4 + let group = shl(1, extra) + return 3 + shl(group - 1, 2) + 4 + (sym - 4 - extra * 4) * group +} + +fn z_len_extra(sym: int) -> int { + if sym < 8 { return 0 } + if sym == 28 { return 0 } + return (sym - 4) / 4 +} + +fn z_dist_base(sym: int) -> int { + if sym < 4 { return 1 + sym } + let extra = (sym - 2) / 2 + let group = shl(1, extra) + return 1 + shl(group, 1) + (sym - 2 - extra * 2) * group +} + +fn z_dist_extra(sym: int) -> int { + if sym < 4 { return 0 } + return (sym - 2) / 2 +} + +# ---- block decoders ------------------------------------------------------- +# `out` is the destination window; returns the new write position, or -1. +fn z_stored(out: ptr, at: int, cap: int) -> int { + z_bitbuf = 0 + z_bitcnt = 0 # stored blocks are byte-aligned + if z_pos + 4 > z_len { return -1 } + let n = peek8(z_src, z_pos) + shl(peek8(z_src, z_pos + 1), 8) + z_pos = z_pos + 4 # LEN then its one's complement + let w = at + for i in 0 .. n { + if z_pos >= z_len { return -1 } + if w >= cap { return -1 } + poke8(out, w, peek8(z_src, z_pos)) + w = w + 1 + z_pos = z_pos + 1 + } + return w +} + +fn z_codes(out: ptr, at: int, cap: int, lit: ptr, dist: ptr) -> int { + let w = at + let sym = z_decode(lit) + while sym != 256 { + if z_err != 0 { return -1 } + if sym < 0 { return -1 } + if sym < 256 { + if w >= cap { return -1 } + poke8(out, w, sym) + w = w + 1 + } + if sym > 256 { + let s = sym - 257 + if s >= 29 { return -1 } + let length = z_len_base(s) + z_bits(z_len_extra(s)) + let d = z_decode(dist) + if d < 0 { return -1 } + let distance = z_dist_base(d) + z_bits(z_dist_extra(d)) + if distance > w { return -1 } + for k in 0 .. length { + if w >= cap { return -1 } + poke8(out, w, peek8(out, w - distance)) + w = w + 1 + } + } + sym = z_decode(lit) + } + return w +} + +fn z_fixed_tables(lit: ptr, dist: ptr) -> void { + let lengths = mem_alloc(288 * 4) + for i in 0 .. 144 { poke32(lengths, i, 8) } + for i in 144 .. 256 { poke32(lengths, i, 9) } + for i in 256 .. 280 { poke32(lengths, i, 7) } + for i in 280 .. 288 { poke32(lengths, i, 8) } + z_table_build(lit, lengths, 288) + for i in 0 .. 30 { poke32(lengths, i, 5) } + z_table_build(dist, lengths, 30) + mem_free(lengths) +} + +fn z_dynamic_tables(lit: ptr, dist: ptr) -> int { + let nlen = z_bits(5) + 257 + let ndist = z_bits(5) + 1 + let ncode = z_bits(4) + 4 + if nlen > 286 { return 0 } + if ndist > 30 { return 0 } + + let lengths = mem_alloc(320 * 4) + for i in 0 .. 19 { poke32(lengths, i, 0) } + # the code-length alphabet is transmitted in this fixed permutation + # 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 — biased by '0' so it is one literal + let order = "@AB08796:5;4<3=2>1?" + for i in 0 .. ncode { + poke32(lengths, peek8(order, i) - 48, z_bits(3)) + } + let clen = z_table_new(19) + z_table_build(clen, lengths, 19) + + let n = 0 + while n < nlen + ndist { + let sym = z_decode(clen) + if sym < 0 { return 0 } + if sym < 16 { + poke32(lengths, n, sym) + n = n + 1 + } + if sym >= 16 { + let prev = 0 + let rep = 0 + if sym == 16 { + if n == 0 { return 0 } + prev = peek32(lengths, n - 1) + rep = 3 + z_bits(2) + } + if sym == 17 { rep = 3 + z_bits(3) } + if sym == 18 { rep = 11 + z_bits(7) } + for k in 0 .. rep { + if n < 320 { + poke32(lengths, n, prev) + n = n + 1 + } + } + } + } + z_table_build(lit, lengths, nlen) + # the distance lengths follow the literal ones in the same buffer + let dl = mem_alloc(32 * 4) + for i in 0 .. ndist { poke32(dl, i, peek32(lengths, nlen + i)) } + z_table_build(dist, dl, ndist) + mem_free(dl) + mem_free(lengths) + mem_free(clen) + return 1 +} + +# Inflate a raw DEFLATE stream. Returns bytes written, or -1. +fn z_inflate(src: ptr, len: int, out: ptr, cap: int) -> int { + z_start(src, len) + let lit = z_table_new(288) + let dist = z_table_new(30) + let w = 0 + let final = 0 + while final == 0 { + final = z_bits(1) + let btype = z_bits(2) + if z_err != 0 { return -1 } + if btype == 0 { w = z_stored(out, w, cap) } + if btype == 1 { + z_fixed_tables(lit, dist) + w = z_codes(out, w, cap, lit, dist) + } + if btype == 2 { + if z_dynamic_tables(lit, dist) == 0 { return -1 } + w = z_codes(out, w, cap, lit, dist) + } + if btype == 3 { return -1 } + if w < 0 { return -1 } + } + mem_free(lit) + mem_free(dist) + return w +} + +# zlib wrapper (RFC 1950): two header bytes, then DEFLATE, then Adler-32. +fn z_uncompress(src: ptr, len: int, out: ptr, cap: int) -> int { + if len < 2 { return -1 } + let cmf = peek8(src, 0) + if band(cmf, 15) != 8 { return -1 } + return z_inflate(ptr_add(src, 2), len - 2, out, cap) +} diff --git a/runtime/native/truetype.ludic b/runtime/native/truetype.ludic new file mode 100644 index 00000000..3d29f2c6 --- /dev/null +++ b/runtime/native/truetype.ludic @@ -0,0 +1,428 @@ +# ============================================================================ +# truetype.ludic — a TrueType font loader and glyph rasterizer, in Ludic. +# +# Parses the sfnt container, maps codepoints through cmap (formats 0/4/6/12), +# decodes simple and composite `glyf` outlines, flattens the quadratic Béziers, +# and fills them with the nonzero winding rule at 4x4 supersampling to get an +# 8-bit coverage mask. Then a glyph cache and a UTF-8 text layer on top. +# +# The C original used floats. Ludic has Q16.16 `fixed`, which is enough: at 16 +# fractional bits a glyph coordinate is exact to 1/65536 of a pixel, far below +# the 1/4-pixel supersample grid the rasterizer actually quantises to. +# ============================================================================ + +const TT_MAX: int = 8 # fonts loaded at once +const TT_SS: int = 4 # supersample factor per axis +const TT_PTS: int = 4096 # points in one outline +const TT_EDGES: int = 16384 # line segments in one glyph +const TT_GC: int = 512 # glyph cache entries + +# ---- per-font tables (parallel arrays; index = font id) ------------------- +var tt_data: ptr = ptr_null() +var tt_size: ptr = ptr_null() +var tt_upem: ptr = ptr_null() +var tt_nglyf: ptr = ptr_null() +var tt_locfm: ptr = ptr_null() +var tt_nhm: ptr = ptr_null() +var tt_asc: ptr = ptr_null() +var tt_desc: ptr = ptr_null() +var tt_gap: ptr = ptr_null() +var tt_glyf: ptr = ptr_null() +var tt_loca: ptr = ptr_null() +var tt_hmtx: ptr = ptr_null() +var tt_cmap: ptr = ptr_null() +var tt_cfmt: ptr = ptr_null() +var tt_n: int = 0 + +# ---- outline + edge scratch (reused for every glyph) ---------------------- +var ol_x: ptr = ptr_null() +var ol_y: ptr = ptr_null() +var ol_on: ptr = ptr_null() +var ol_ends: ptr = ptr_null() +var ol_n: int = 0 +var ol_ne: int = 0 + +var ed_x0: ptr = ptr_null() +var ed_y0: ptr = ptr_null() +var ed_x1: ptr = ptr_null() +var ed_y1: ptr = ptr_null() +var ed_n: int = 0 + +var sc_x: ptr = ptr_null() # scanline crossings +var sc_d: ptr = ptr_null() + +# ---- glyph cache ---------------------------------------------------------- +var gc_used: ptr = ptr_null() +var gc_font: ptr = ptr_null() +var gc_cp: ptr = ptr_null() +var gc_px: ptr = ptr_null() +var gc_w: ptr = ptr_null() +var gc_h: ptr = ptr_null() +var gc_ox: ptr = ptr_null() +var gc_oy: ptr = ptr_null() +var gc_adv: ptr = ptr_null() +var gc_bmp: ptr = ptr_null() + +fn rt_tt_init() -> void { + tt_data = mem_alloc(TT_MAX * 8) + tt_size = mem_alloc(TT_MAX * 4) + tt_upem = mem_alloc(TT_MAX * 4) + tt_nglyf = mem_alloc(TT_MAX * 4) + tt_locfm = mem_alloc(TT_MAX * 4) + tt_nhm = mem_alloc(TT_MAX * 4) + tt_asc = mem_alloc(TT_MAX * 4) + tt_desc = mem_alloc(TT_MAX * 4) + tt_gap = mem_alloc(TT_MAX * 4) + tt_glyf = mem_alloc(TT_MAX * 4) + tt_loca = mem_alloc(TT_MAX * 4) + tt_hmtx = mem_alloc(TT_MAX * 4) + tt_cmap = mem_alloc(TT_MAX * 4) + tt_cfmt = mem_alloc(TT_MAX * 4) + + ol_x = mem_alloc(TT_PTS * 4) + ol_y = mem_alloc(TT_PTS * 4) + ol_on = mem_alloc(TT_PTS * 4) + ol_ends = mem_alloc(256 * 4) + + ed_x0 = mem_alloc(TT_EDGES * 4) + ed_y0 = mem_alloc(TT_EDGES * 4) + ed_x1 = mem_alloc(TT_EDGES * 4) + ed_y1 = mem_alloc(TT_EDGES * 4) + sc_x = mem_alloc(TT_EDGES * 4) + sc_d = mem_alloc(TT_EDGES * 4) + + gc_used = mem_alloc(TT_GC * 4) + gc_font = mem_alloc(TT_GC * 4) + gc_cp = mem_alloc(TT_GC * 4) + gc_px = mem_alloc(TT_GC * 4) + gc_w = mem_alloc(TT_GC * 4) + gc_h = mem_alloc(TT_GC * 4) + gc_ox = mem_alloc(TT_GC * 4) + gc_oy = mem_alloc(TT_GC * 4) + gc_adv = mem_alloc(TT_GC * 4) + gc_bmp = mem_alloc(TT_GC * 8) + mem_set(gc_used, 0, TT_GC * 4) +} + +# ---- big-endian readers --------------------------------------------------- +fn tt_u16(d: ptr, at: int) -> int { + return bor(shl(peek8(d, at), 8), peek8(d, at + 1)) +} +fn tt_i16(d: ptr, at: int) -> int { + let v = tt_u16(d, at) + if v >= 32768 { return v - 65536 } + return v +} +fn tt_u32(d: ptr, at: int) -> int { + return bor(bor(shl(peek8(d, at), 24), shl(peek8(d, at + 1), 16)), + bor(shl(peek8(d, at + 2), 8), peek8(d, at + 3))) +} +fn tt_i8(d: ptr, at: int) -> int { + let v = peek8(d, at) + if v >= 128 { return v - 256 } + return v +} + +fn tt_find_table(d: ptr, base: int, a: int, b: int, c: int, e: int) -> int { + let n = tt_u16(d, base + 4) + for i in 0 .. n { + let rec = base + 12 + i * 16 + if peek8(d, rec) == a { + if peek8(d, rec + 1) == b { + if peek8(d, rec + 2) == c { + if peek8(d, rec + 3) == e { return tt_u32(d, rec + 8) } + } + } + } + } + return 0 - 1 +} + +# pick the most capable Unicode subtable, as the C loader did +fn tt_pick_cmap(id: int, d: ptr, co: int) -> void { + poke32(tt_cmap, id, 0 - 1) + poke32(tt_cfmt, id, 0) + if co < 0 { return } + let n = tt_u16(d, co + 2) + let best = 0 - 1 + let bestscore = 0 - 1 + for i in 0 .. n { + let rec = co + 4 + i * 8 + let plat = tt_u16(d, rec) + let enc = tt_u16(d, rec + 2) + let off = tt_u32(d, rec + 4) + let score = 0 - 1 + if plat == 0 { score = 2 } + if plat == 0 { if enc == 4 { score = 4 } } + if plat == 0 { if enc == 6 { score = 4 } } + if plat == 3 { if enc == 1 { score = 3 } } + if plat == 3 { if enc == 10 { score = 5 } } + if score > bestscore { + bestscore = score + best = co + off + } + } + if best < 0 { return } + poke32(tt_cmap, id, best) + poke32(tt_cfmt, id, tt_u16(d, best)) +} + +fn rt_font_load(path: str) -> int { + if tt_n >= TT_MAX { return 0 - 1 } + let d = rt_read_file(path) + if ptr_is_null(d) { return 0 - 1 } + let size = rt_file_len + let base = 0 + # a .ttc collection points at its first font + if size >= 16 { + if peek8(d, 0) == 116 { if peek8(d, 1) == 116 { if peek8(d, 2) == 99 { if peek8(d, 3) == 102 { + base = tt_u32(d, 12) + } } } } + } + let head = tt_find_table(d, base, 104, 101, 97, 100) + let maxp = tt_find_table(d, base, 109, 97, 120, 112) + let hhea = tt_find_table(d, base, 104, 104, 101, 97) + let loca = tt_find_table(d, base, 108, 111, 99, 97) + let glyf = tt_find_table(d, base, 103, 108, 121, 102) + let hmtx = tt_find_table(d, base, 104, 109, 116, 120) + if head < 0 { return 0 - 1 } + if maxp < 0 { return 0 - 1 } + if hhea < 0 { return 0 - 1 } + if loca < 0 { return 0 - 1 } + if glyf < 0 { return 0 - 1 } + if hmtx < 0 { return 0 - 1 } + + let id = tt_n + tt_n = tt_n + 1 + pokep(tt_data, id, d) + poke32(tt_size, id, size) + let upem = tt_u16(d, head + 18) + if upem <= 0 { upem = 1000 } + poke32(tt_upem, id, upem) + poke32(tt_locfm, id, tt_i16(d, head + 50)) + poke32(tt_nglyf, id, tt_u16(d, maxp + 4)) + poke32(tt_asc, id, tt_i16(d, hhea + 4)) + poke32(tt_desc, id, tt_i16(d, hhea + 6)) + poke32(tt_gap, id, tt_i16(d, hhea + 8)) + poke32(tt_nhm, id, tt_u16(d, hhea + 34)) + poke32(tt_glyf, id, glyf) + poke32(tt_loca, id, loca) + poke32(tt_hmtx, id, hmtx) + tt_pick_cmap(id, d, tt_find_table(d, base, 99, 109, 97, 112)) + return id +} + +# ---- codepoint -> glyph id ------------------------------------------------ +fn tt_glyph_index(id: int, cp: int) -> int { + let d = peekp(tt_data, id) + let s = peek32(tt_cmap, id) + if s < 0 { return 0 } + let fmt = peek32(tt_cfmt, id) + + if fmt == 4 { + if cp > 65535 { return 0 } + let segX2 = tt_u16(d, s + 6) + let segc = segX2 / 2 + let endp = s + 14 + let startp = endp + segX2 + 2 + let deltap = startp + segX2 + let rangep = deltap + segX2 + for i in 0 .. segc { + if cp <= tt_u16(d, endp + i * 2) { + let st = tt_u16(d, startp + i * 2) + if cp < st { return 0 } + let ro = tt_u16(d, rangep + i * 2) + if ro == 0 { return band(cp + tt_i16(d, deltap + i * 2), 65535) } + let g = tt_u16(d, rangep + i * 2 + ro + (cp - st) * 2) + if g == 0 { return 0 } + return band(g + tt_i16(d, deltap + i * 2), 65535) + } + } + return 0 + } + if fmt == 12 { + let ng = tt_u32(d, s + 12) + for i in 0 .. ng { + let g = s + 16 + i * 12 + if cp >= tt_u32(d, g) { + if cp <= tt_u32(d, g + 4) { return tt_u32(d, g + 8) + (cp - tt_u32(d, g)) } + } + } + return 0 + } + if fmt == 6 { + let first = tt_u16(d, s + 6) + let cnt = tt_u16(d, s + 8) + if cp >= first { if cp < first + cnt { return tt_u16(d, s + 10 + (cp - first) * 2) } } + return 0 + } + if fmt == 0 { + if cp < 256 { return peek8(d, s + 6 + cp) } + } + return 0 +} + +fn tt_advance(id: int, gid: int) -> int { + let d = peekp(tt_data, id) + let hmtx = peek32(tt_hmtx, id) + let n = peek32(tt_nhm, id) + if gid < n { return tt_u16(d, hmtx + gid * 4) } + return tt_u16(d, hmtx + (n - 1) * 4) +} + +# ---- outline extraction --------------------------------------------------- +fn ol_pt(x: fixed, y: fixed, on: int) -> void { + if ol_n >= TT_PTS { return } + pokef(ol_x, ol_n, x) + pokef(ol_y, ol_n, y) + poke32(ol_on, ol_n, on) + ol_n = ol_n + 1 +} + +fn tt_glyph_start(id: int, gid: int) -> int { + let d = peekp(tt_data, id) + let loca = peek32(tt_loca, id) + if peek32(tt_locfm, id) == 0 { return tt_u16(d, loca + gid * 2) * 2 } + return tt_u32(d, loca + gid * 4) +} +fn tt_glyph_end(id: int, gid: int) -> int { + let d = peekp(tt_data, id) + let loca = peek32(tt_loca, id) + if peek32(tt_locfm, id) == 0 { return tt_u16(d, loca + (gid + 1) * 2) * 2 } + return tt_u32(d, loca + (gid + 1) * 4) +} + +# Append glyph `gid`, transformed by [a b c e] + (dx,dy), to the outline. +fn tt_load_outline(id: int, gid: int, a: fixed, b: fixed, c: fixed, e: fixed, dx: fixed, dy: fixed, depth: int) -> void { + if gid < 0 { return } + if gid >= peek32(tt_nglyf, id) { return } + if depth > 5 { return } + let goff = tt_glyph_start(id, gid) + let gend = tt_glyph_end(id, gid) + if goff >= gend { return } + let d = peekp(tt_data, id) + let g = peek32(tt_glyf, id) + goff + let nc = tt_i16(d, g) + + if nc >= 0 { + let endpts = g + 10 + let npts = 0 + if nc > 0 { npts = tt_u16(d, endpts + (nc - 1) * 2) + 1 } + let p = endpts + nc * 2 + p = p + 2 + tt_u16(d, p) # skip instructions + + let flags = mem_alloc(npts + 8) + let i = 0 + while i < npts { + let fl = peek8(d, p) + p = p + 1 + poke8(flags, i, fl) + i = i + 1 + if band(fl, 8) != 0 { # REPEAT + let r = peek8(d, p) + p = p + 1 + while r > 0 { + if i < npts { poke8(flags, i, fl) i = i + 1 } + r = r - 1 + } + } + } + + let xs = mem_alloc((npts + 1) * 4) + let ys = mem_alloc((npts + 1) * 4) + let xv = 0 + for k in 0 .. npts { + let fl = peek8(flags, k) + if band(fl, 2) != 0 { + let dxv = peek8(d, p) + p = p + 1 + if band(fl, 16) != 0 { xv = xv + dxv } else { xv = xv - dxv } + } else { + if band(fl, 16) == 0 { xv = xv + tt_i16(d, p) p = p + 2 } + } + poke32(xs, k, xv) + } + let yv = 0 + for k in 0 .. npts { + let fl = peek8(flags, k) + if band(fl, 4) != 0 { + let dyv = peek8(d, p) + p = p + 1 + if band(fl, 32) != 0 { yv = yv + dyv } else { yv = yv - dyv } + } else { + if band(fl, 32) == 0 { yv = yv + tt_i16(d, p) p = p + 2 } + } + poke32(ys, k, yv) + } + + let start = 0 + for ci in 0 .. nc { + let last = tt_u16(d, endpts + ci * 2) + for k in start .. last + 1 { + let X = fx(peek32(xs, k)) + let Y = fx(peek32(ys, k)) + ol_pt(a * X + c * Y + dx, b * X + e * Y + dy, band(peek8(flags, k), 1)) + } + if ol_ne < 256 { + poke32(ol_ends, ol_ne, ol_n) + ol_ne = ol_ne + 1 + } + start = last + 1 + } + mem_free(flags) + mem_free(xs) + mem_free(ys) + } else { + # composite glyph: components, each with its own placement and transform + let p = g + 10 + let more = 1 + while more == 1 { + let flags = tt_u16(d, p) + let cgid = tt_u16(d, p + 2) + p = p + 4 + let arg1 = 0 + let arg2 = 0 + if band(flags, 1) != 0 { + arg1 = tt_i16(d, p) + arg2 = tt_i16(d, p + 2) + p = p + 4 + } else { + arg1 = tt_i8(d, p) + arg2 = tt_i8(d, p + 1) + p = p + 2 + } + let ca = 1.0 + let cb = 0.0 + let cc = 0.0 + let ce = 1.0 + if band(flags, 8) != 0 { + ca = as_fixed(shl(tt_i16(d, p), 2)) # F2Dot14 -> Q16.16 + ce = ca + p = p + 2 + } + if band(flags, 64) != 0 { + ca = as_fixed(shl(tt_i16(d, p), 2)) + ce = as_fixed(shl(tt_i16(d, p + 2), 2)) + p = p + 4 + } + if band(flags, 128) != 0 { + ca = as_fixed(shl(tt_i16(d, p), 2)) + cb = as_fixed(shl(tt_i16(d, p + 2), 2)) + cc = as_fixed(shl(tt_i16(d, p + 4), 2)) + ce = as_fixed(shl(tt_i16(d, p + 6), 2)) + p = p + 8 + } + let odx = dx + let ody = dy + if band(flags, 2) != 0 { + odx = a * fx(arg1) + c * fx(arg2) + dx + ody = b * fx(arg1) + e * fx(arg2) + dy + } + tt_load_outline(id, cgid, a * ca + c * cb, b * ca + e * cb, a * cc + c * ce, b * cc + e * ce, odx, ody, depth + 1) + more = 0 + if band(flags, 32) != 0 { more = 1 } + } + } +} + +import "truetype_raster.ludic" diff --git a/runtime/native/truetype_raster.ludic b/runtime/native/truetype_raster.ludic new file mode 100644 index 00000000..25c10363 --- /dev/null +++ b/runtime/native/truetype_raster.ludic @@ -0,0 +1,380 @@ +# truetype_raster.ludic — glyph rasterization, the glyph cache, UTF-8 decoding +# and text drawing. Split out of truetype.ludic (the sfnt/cmap/outline half). + +# ---- rasterization -------------------------------------------------------- +fn ed_add(x0: fixed, y0: fixed, x1: fixed, y1: fixed) -> void { + if ed_n >= TT_EDGES { return } + pokef(ed_x0, ed_n, x0) + pokef(ed_y0, ed_n, y0) + pokef(ed_x1, ed_n, x1) + pokef(ed_y1, ed_n, y1) + ed_n = ed_n + 1 +} + +fn tt_isqrt(v: int) -> int { + if v <= 0 { return 0 } + let r = 0 + let b = 32768 + while b > 0 { + let t = r + b + if t * t <= v { r = t } + b = b / 2 + } + return r +} + +# flatten one quadratic Bézier into line segments, subdivided by chord length +fn ed_quad(x0: fixed, y0: fixed, cx: fixed, cy: fixed, x1: fixed, y1: fixed) -> void { + let dx = flr(x1) - flr(x0) + let dy = flr(y1) - flr(y0) + let n = tt_isqrt(dx * dx + dy * dy) / 3 + if n < 2 { n = 2 } + if n > 24 { n = 24 } + let px = x0 + let py = y0 + for i in 1 .. n + 1 { + let t = fx(i) / n + let u = 1.0 - t + let qx = u * u * x0 + 2.0 * u * t * cx + t * t * x1 + let qy = u * u * y0 + 2.0 * u * t * cy + t * t * y1 + ed_add(px, py, qx, qy) + px = qx + py = qy + } +} + +# Rasterize a glyph at `px` pixels. Coverage lands in a fresh buffer; the +# geometry is left in gr_* for the caller. +var gr_w: int = 0 +var gr_h: int = 0 +var gr_ox: int = 0 +var gr_oy: int = 0 +var gr_adv: int = 0 + +fn tt_raster(id: int, gid: int, px: int) -> ptr { + let upem = peek32(tt_upem, id) + let scale = fx(px) / upem + gr_adv = flr(fx(tt_advance(id, gid)) * scale + 0.5) + gr_w = 0 + gr_h = 0 + ol_n = 0 + ol_ne = 0 + ed_n = 0 + tt_load_outline(id, gid, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0) + if ol_n == 0 { return ptr_null() } + + let minx = 999999.0 + let miny = 999999.0 + let maxx = 0.0 - 999999.0 + let maxy = 0.0 - 999999.0 + for i in 0 .. ol_n { + let X = peekf(ol_x, i) * scale + let Y = peekf(ol_y, i) * scale + if X < minx { minx = X } + if X > maxx { maxx = X } + if Y < miny { miny = Y } + if Y > maxy { maxy = Y } + } + let x0 = flr(minx) + let y0 = flr(miny) + let x1 = flr(maxx) + 1 + let y1 = flr(maxy) + 1 + if maxx == fx(flr(maxx)) { x1 = flr(maxx) } + if maxy == fx(flr(maxy)) { y1 = flr(maxy) } + let W = x1 - x0 + let H = y1 - y0 + if W <= 0 { return ptr_null() } + if H <= 0 { return ptr_null() } + if W > 1024 { return ptr_null() } + if H > 1024 { return ptr_null() } + gr_w = W + gr_h = H + gr_ox = x0 + gr_oy = y1 + + # build edges in supersample space (y grows downward) + let start = 0 + for ci in 0 .. ol_ne { + let end = peek32(ol_ends, ci) + let cnt = end - start + if cnt >= 2 { + let first_on = 0 - 1 + for i in 0 .. cnt { + if first_on < 0 { if peek32(ol_on, start + i) == 1 { first_on = i } } + } + let sx = 0.0 + let sy = 0.0 + if first_on < 0 { + # all off-curve: start at the midpoint of the first and last point + let mx = (peekf(ol_x, start) + peekf(ol_x, start + cnt - 1)) / 2 + let my = (peekf(ol_y, start) + peekf(ol_y, start + cnt - 1)) / 2 + sx = (mx * scale - fx(x0)) * TT_SS + sy = (fx(y1) - my * scale) * TT_SS + first_on = 0 + } else { + sx = (peekf(ol_x, start + first_on) * scale - fx(x0)) * TT_SS + sy = (fx(y1) - peekf(ol_y, start + first_on) * scale) * TT_SS + } + let curx = sx + let cury = sy + let step = 0 + while step < cnt { + let i = (first_on + 1 + step) % cnt + let ix = (peekf(ol_x, start + i) * scale - fx(x0)) * TT_SS + let iy = (fx(y1) - peekf(ol_y, start + i) * scale) * TT_SS + if peek32(ol_on, start + i) == 1 { + ed_add(curx, cury, ix, iy) + curx = ix + cury = iy + } else { + let j = (i + 1) % cnt + let jx = (peekf(ol_x, start + j) * scale - fx(x0)) * TT_SS + let jy = (fx(y1) - peekf(ol_y, start + j) * scale) * TT_SS + let ex = jx + let ey = jy + if peek32(ol_on, start + j) == 1 { + step = step + 1 + } else { + ex = (ix + jx) / 2 # implied on-curve midpoint + ey = (iy + jy) / 2 + } + ed_quad(curx, cury, ix, iy, ex, ey) + curx = ex + cury = ey + } + step = step + 1 + } + ed_add(curx, cury, sx, sy) + } + start = end + } + + let SW = W * TT_SS + let SH = H * TT_SS + let cover = mem_alloc(W * H) + mem_set(cover, 0, W * H) + let unit = 255 / (TT_SS * TT_SS) + + for sy in 0 .. SH { + let yc = fx(sy) + 0.5 + let m = 0 + for i in 0 .. ed_n { + let ya = peekf(ed_y0, i) + let yb = peekf(ed_y1, i) + let hit = 0 + if ya <= yc { if yb > yc { hit = 1 } } + if yb <= yc { if ya > yc { hit = 1 } } + if hit == 1 { + let t = (yc - ya) / (yb - ya) + pokef(sc_x, m, peekf(ed_x0, i) + t * (peekf(ed_x1, i) - peekf(ed_x0, i))) + if yb > ya { poke32(sc_d, m, 1) } else { poke32(sc_d, m, 0 - 1) } + m = m + 1 + } + } + # insertion sort the crossings by x + for i in 1 .. m { + let kx = peekf(sc_x, i) + let kd = peek32(sc_d, i) + let j = i - 1 + let placed = 0 + while j >= 0 { + if peekf(sc_x, j) > kx { + pokef(sc_x, j + 1, peekf(sc_x, j)) + poke32(sc_d, j + 1, peek32(sc_d, j)) + j = j - 1 + } else { + pokef(sc_x, j + 1, kx) + poke32(sc_d, j + 1, kd) + placed = 1 + j = 0 - 1 + } + } + if placed == 0 { + pokef(sc_x, 0, kx) + poke32(sc_d, 0, kd) + } + } + let wind = 0 + let oy = sy / TT_SS + for i in 0 .. m - 1 { + wind = wind + peek32(sc_d, i) + if wind != 0 { + let xa = peekf(sc_x, i) + let xb = peekf(sc_x, i + 1) + if xa < 0.0 { xa = 0.0 } + if xb > fx(SW) { xb = fx(SW) } + if xb > xa { + let ixa = flr(xa) + let ixb = flr(xb) + 1 + for sx in ixa .. ixb { + let cxl = xa + let cxr = xb + if fx(sx) > cxl { cxl = fx(sx) } + if fx(sx + 1) < cxr { cxr = fx(sx + 1) } + let cvr = cxr - cxl + if cvr > 0.0 { + let oxp = sx / TT_SS + if oxp >= 0 { if oxp < W { if oy >= 0 { if oy < H { + let v = peek8(cover, oy * W + oxp) + flr(cvr * unit) + if v > 255 { v = 255 } + poke8(cover, oy * W + oxp, v) + } } } } + } + } + } + } + } + } + return cover +} + +# ---- glyph cache ---------------------------------------------------------- +# Rasterizing is far too slow to repeat per frame, so a coverage mask is kept +# per (font, codepoint, size). Open addressing, 8 probes, evict on miss. +fn gc_hash(font: int, cp: int, px: int) -> int { + return band(bxor(bxor(cp * 2654435761, shl(font, 20)), shl(px, 8)), TT_GC - 1) +} + +fn tt_glyph_get(font: int, cp: int, px: int) -> int { + let h = gc_hash(font, cp, px) + for k in 0 .. 8 { + let s = band(h + k, TT_GC - 1) + if peek32(gc_used, s) == 1 { + if peek32(gc_font, s) == font { + if peek32(gc_cp, s) == cp { + if peek32(gc_px, s) == px { return s } + } + } + } + } + let s = h + if peek32(gc_used, s) == 1 { + let old = peekp(gc_bmp, s) + if ptr_is_null(old) == false { mem_free(old) } + } + let bmp = tt_raster(font, tt_glyph_index(font, cp), px) + pokep(gc_bmp, s, bmp) + poke32(gc_used, s, 1) + poke32(gc_font, s, font) + poke32(gc_cp, s, cp) + poke32(gc_px, s, px) + poke32(gc_w, s, gr_w) + poke32(gc_h, s, gr_h) + poke32(gc_ox, s, gr_ox) + poke32(gc_oy, s, gr_oy) + poke32(gc_adv, s, gr_adv) + return s +} + +# ---- UTF-8 ---------------------------------------------------------------- +var u8_next: int = 0 # byte index just past the codepoint last decoded + +fn tt_utf8(s: str, at: int) -> int { + let c = peek8(s, at) + let extra = 0 - 1 + if c < 128 { extra = 0 } + if shr(c, 5) == 6 { extra = 1 } + if shr(c, 4) == 14 { extra = 2 } + if shr(c, 3) == 30 { extra = 3 } + if extra < 0 { + u8_next = at + 1 + return 65533 + } + if extra == 0 { + u8_next = at + 1 + return c + } + let cp = band(c, shr(63, extra)) + for i in 0 .. extra { + let b = peek8(s, at + 1 + i) + if band(b, 192) != 128 { + u8_next = at + 1 + i + return 65533 + } + cp = bor(shl(cp, 6), band(b, 63)) + } + u8_next = at + 1 + extra + return cp +} + +# ---- drawing -------------------------------------------------------------- +fn tt_blit(bmp: ptr, w: int, h: int, dx: int, dy: int, colour: int) -> void { + if ptr_is_null(bmp) { return } + let cr = band(shr(colour, 16), 255) + let cg = band(shr(colour, 8), 255) + let cb = band(colour, 255) + for y in 0 .. h { + let py = dy + y + if py >= 0 { + if py < rt_fbh { + for x in 0 .. w { + let a = peek8(bmp, y * w + x) + if a != 0 { + let pxx = dx + x + if pxx >= 0 { + if pxx < rt_fbw { + let d = peek32(rt_fb, py * rt_fbw + pxx) + let rr = (cr * a + band(shr(d, 16), 255) * (255 - a)) / 255 + let rg = (cg * a + band(shr(d, 8), 255) * (255 - a)) / 255 + let rb = (cb * a + band(d, 255) * (255 - a)) / 255 + poke32(rt_fb, py * rt_fbw + pxx, bor(bor(shl(rr, 16), shl(rg, 8)), rb)) + } + } + } + } + } + } + } +} + +fn rt_text_ttf(font: int, x: int, y: int, s: str, colour: int, px: int) -> void { + if font < 0 { return } + if font >= tt_n { return } + if px <= 0 { return } + let upem = peek32(tt_upem, font) + let scale = fx(px) / upem + let baseline = y + flr(fx(peek32(tt_asc, font)) * scale + 0.5) + let lineh = flr(fx(peek32(tt_asc, font) - peek32(tt_desc, font) + peek32(tt_gap, font)) * scale + 0.5) + let penx = x + let i = 0 + while peek8(s, i) != 0 { + let cp = tt_utf8(s, i) + i = u8_next + if cp == 10 { + penx = x + baseline = baseline + lineh + } else { + let g = tt_glyph_get(font, cp, px) + tt_blit(peekp(gc_bmp, g), peek32(gc_w, g), peek32(gc_h, g), penx + peek32(gc_ox, g), baseline - peek32(gc_oy, g), colour) + penx = penx + peek32(gc_adv, g) + } + } +} + +fn rt_text_w(font: int, s: str, px: int) -> int { + if font < 0 { return 0 } + if font >= tt_n { return 0 } + if px <= 0 { return 0 } + let w = 0 + let best = 0 + let i = 0 + while peek8(s, i) != 0 { + let cp = tt_utf8(s, i) + i = u8_next + if cp == 10 { + if w > best { best = w } + w = 0 + } else { + w = w + peek32(gc_adv, tt_glyph_get(font, cp, px)) + } + } + if w > best { best = w } + return best +} + +fn rt_text_h(font: int, px: int) -> int { + if font < 0 { return 0 } + if font >= tt_n { return 0 } + let scale = fx(px) / peek32(tt_upem, font) + return flr(fx(peek32(tt_asc, font) - peek32(tt_desc, font) + peek32(tt_gap, font)) * scale + 0.5) +} diff --git a/runtime/native/ui.ludic b/runtime/native/ui.ludic new file mode 100644 index 00000000..0d2bef01 --- /dev/null +++ b/runtime/native/ui.ludic @@ -0,0 +1,312 @@ +# ============================================================================ +# ui.ludic — the retained UI engine, written in Ludic. +# +# A `ui Name { … }` block in a game is DATA: the compiler flattens the widget +# tree and emits a build function that calls rt_ui_set() for each property. +# Everything after that — measure/arrange layout, 9-slice skins, text, keyboard +# focus and activation — is this file. +# +# Widgets are parallel arrays rather than a struct per widget, because Ludic +# has components for per-entity data and raw memory for everything else, and a +# widget is not an entity. +# ============================================================================ + +const UI_MAX: int = 256 + +# widget types, matching the compiler's flattener +const WT_PANEL: int = 0 +const WT_COL: int = 1 +const WT_ROW: int = 2 +const WT_LABEL: int = 3 +const WT_BUTTON: int = 4 +const WT_IMAGE: int = 5 +const WT_SPACER: int = 6 + +# property keys — the private protocol between ludicc and this runtime +const K_TYPE: int = 0 +const K_PARENT: int = 1 +const K_W: int = 2 +const K_H: int = 3 +const K_X: int = 4 +const K_Y: int = 5 +const K_HASPOS: int = 6 +const K_PAD: int = 7 +const K_GAP: int = 8 +const K_BG: int = 9 +const K_FG: int = 10 +const K_BORDER: int = 11 +const K_ALIGN: int = 12 +const K_GROW: int = 13 +const K_FONT: int = 14 +const K_SIZE: int = 15 +const K_SKININSET: int = 16 +const K_FOCUSABLE: int = 17 +const K_VISIBLE: int = 18 +const K_IMG: int = 19 +const K_SKIN: int = 20 + +var ui_type: ptr = ptr_null() +var ui_parent: ptr = ptr_null() +var ui_w: ptr = ptr_null() +var ui_h: ptr = ptr_null() +var ui_x: ptr = ptr_null() +var ui_y: ptr = ptr_null() +var ui_haspos: ptr = ptr_null() +var ui_pad: ptr = ptr_null() +var ui_gap: ptr = ptr_null() +var ui_bg: ptr = ptr_null() +var ui_fg: ptr = ptr_null() +var ui_border: ptr = ptr_null() +var ui_align: ptr = ptr_null() +var ui_grow: ptr = ptr_null() +var ui_font: ptr = ptr_null() +var ui_size: ptr = ptr_null() +var ui_skin: ptr = ptr_null() +var ui_inset: ptr = ptr_null() +var ui_img: ptr = ptr_null() +var ui_focusable: ptr = ptr_null() +var ui_rx: ptr = ptr_null() +var ui_ry: ptr = ptr_null() +var ui_rw: ptr = ptr_null() +var ui_rh: ptr = ptr_null() +var ui_visible: ptr = ptr_null() +var ui_fired: ptr = ptr_null() +var ui_hasdyn: ptr = ptr_null() +var ui_dyn: ptr = ptr_null() # UI_MAX * 96 bytes +var ui_text: ptr = ptr_null() # UI_MAX static string pointers + +var ui_n: int = 0 +var ui_active: int = -1 +var ui_focus: int = -1 + +fn rt_ui_init() -> void { + ui_type = mem_alloc(UI_MAX * 4) + ui_parent = mem_alloc(UI_MAX * 4) + ui_w = mem_alloc(UI_MAX * 4) + ui_h = mem_alloc(UI_MAX * 4) + ui_x = mem_alloc(UI_MAX * 4) + ui_y = mem_alloc(UI_MAX * 4) + ui_haspos = mem_alloc(UI_MAX * 4) + ui_pad = mem_alloc(UI_MAX * 4) + ui_gap = mem_alloc(UI_MAX * 4) + ui_bg = mem_alloc(UI_MAX * 4) + ui_fg = mem_alloc(UI_MAX * 4) + ui_border = mem_alloc(UI_MAX * 4) + ui_align = mem_alloc(UI_MAX * 4) + ui_grow = mem_alloc(UI_MAX * 4) + ui_font = mem_alloc(UI_MAX * 4) + ui_size = mem_alloc(UI_MAX * 4) + ui_skin = mem_alloc(UI_MAX * 4) + ui_inset = mem_alloc(UI_MAX * 4) + ui_img = mem_alloc(UI_MAX * 4) + ui_focusable = mem_alloc(UI_MAX * 4) + ui_rx = mem_alloc(UI_MAX * 4) + ui_ry = mem_alloc(UI_MAX * 4) + ui_rw = mem_alloc(UI_MAX * 4) + ui_rh = mem_alloc(UI_MAX * 4) + ui_visible = mem_alloc(UI_MAX * 4) + ui_fired = mem_alloc(UI_MAX * 4) + ui_hasdyn = mem_alloc(UI_MAX * 4) + ui_dyn = mem_alloc(UI_MAX * 96) + ui_text = mem_alloc(UI_MAX * 8) +} + +# ---- build-time interface (called by compiler-emitted code) --------------- +fn rt_ui_reset(n: int) -> void { + ui_n = n + for i in 0 .. n { + poke32(ui_type, i, 0) + poke32(ui_parent, i, 0 - 1) + poke32(ui_w, i, 0) + poke32(ui_h, i, 0) + poke32(ui_x, i, 0) + poke32(ui_y, i, 0) + poke32(ui_haspos, i, 0) + poke32(ui_pad, i, 0) + poke32(ui_gap, i, 0) + poke32(ui_bg, i, 0 - 1) + poke32(ui_fg, i, 0 - 1) + poke32(ui_border, i, 0 - 1) + poke32(ui_align, i, 0 - 1) + poke32(ui_grow, i, 0) + poke32(ui_font, i, 0 - 1) + poke32(ui_size, i, 8) + poke32(ui_skin, i, 0 - 1) + poke32(ui_inset, i, 6) + poke32(ui_img, i, 0 - 1) + poke32(ui_focusable, i, 0) + poke32(ui_visible, i, 1) + poke32(ui_fired, i, 0) + poke32(ui_hasdyn, i, 0) + pokep(ui_text, i, ptr_null()) + } +} + +fn rt_ui_set(i: int, k: int, v: int) -> void { + if i < 0 { return } + if i >= UI_MAX { return } + if k == K_TYPE { poke32(ui_type, i, v) } + if k == K_PARENT { poke32(ui_parent, i, v) } + if k == K_W { poke32(ui_w, i, v) } + if k == K_H { poke32(ui_h, i, v) } + if k == K_X { poke32(ui_x, i, v) } + if k == K_Y { poke32(ui_y, i, v) } + if k == K_HASPOS { poke32(ui_haspos, i, v) } + if k == K_PAD { poke32(ui_pad, i, v) } + if k == K_GAP { poke32(ui_gap, i, v) } + if k == K_BG { poke32(ui_bg, i, v) } + if k == K_FG { poke32(ui_fg, i, v) } + if k == K_BORDER { poke32(ui_border, i, v) } + if k == K_ALIGN { poke32(ui_align, i, v) } + if k == K_GROW { poke32(ui_grow, i, v) } + if k == K_FONT { poke32(ui_font, i, v) } + if k == K_SIZE { poke32(ui_size, i, v) } + if k == K_SKININSET { poke32(ui_inset, i, v) } + if k == K_FOCUSABLE { poke32(ui_focusable, i, v) } + if k == K_VISIBLE { poke32(ui_visible, i, v) } + if k == K_IMG { poke32(ui_img, i, v) } + if k == K_SKIN { poke32(ui_skin, i, v) } +} + +fn rt_ui_static_text(i: int, s: str) -> void { + if i < 0 { return } + if i >= UI_MAX { return } + pokep(ui_text, i, s) +} + +# ---- text helpers: TrueType when a font is loaded, bitmap otherwise ------- +fn ui_str(i: int) -> ptr { + if peek32(ui_hasdyn, i) == 1 { return ptr_add(ui_dyn, i * 96) } + let t = peekp(ui_text, i) + if ptr_is_null(t) { return ptr_add(ui_dyn, i * 96) } + return t +} + +fn ui_draw_text(font: int, x: int, y: int, s: ptr, colour: int, size: int) -> void { + if font >= 0 { + if font < tt_n { + rt_text_ttf(font, x, y, s, colour, size) + return + } + } + rt_text(x, y, s, colour, max(size / 8, 1)) +} + +fn ui_tw(font: int, s: ptr, size: int) -> int { + if font >= 0 { + if font < tt_n { return rt_text_w(font, s, size) } + } + let n = 0 + while peek8(s, n) != 0 { n = n + 1 } + return n * 6 * max(size / 8, 1) +} + +fn ui_th(font: int, size: int) -> int { + if font >= 0 { + if font < tt_n { return rt_text_h(font, size) } + } + return 7 * max(size / 8, 1) +} + +fn ui_is_container(t: int) -> bool { + if t == WT_PANEL { return true } + if t == WT_COL { return true } + if t == WT_ROW { return true } + return false +} +fn ui_dir(t: int) -> int { + if t == WT_ROW { return 0 } + return 1 +} +fn ui_under(i: int, root: int) -> bool { + let k = i + while k >= 0 { + if k == root { return true } + k = peek32(ui_parent, k) + } + return false +} + +# ---- measure: content sizes, children before parents ---------------------- +fn ui_measure() -> void { + let i = ui_n - 1 + while i >= 0 { + if peek32(ui_visible, i) == 0 { + poke32(ui_rw, i, 0) + poke32(ui_rh, i, 0) + } else { + let t = peek32(ui_type, i) + let pad = peek32(ui_pad, i) + let cw = 0 + let ch = 0 + if t == WT_LABEL { cw = 0 - 1 } + if t == WT_BUTTON { cw = 0 - 1 } + if cw == 0 - 1 { + let s = ui_str(i) + cw = ui_tw(peek32(ui_font, i), s, peek32(ui_size, i)) + 2 * pad + ch = ui_th(peek32(ui_font, i), peek32(ui_size, i)) + 2 * pad + if t == WT_BUTTON { + cw = cw + 10 + ch = ch + 6 + } + } else { + if t == WT_IMAGE { + let im = peek32(ui_img, i) + if im >= 0 { + cw = peek32(img_w, im) + ch = peek32(img_h, im) + } + } else { + if t == WT_SPACER { + cw = peek32(ui_w, i) + ch = peek32(ui_h, i) + } else { + let dir = ui_dir(t) + let mainsz = 0 + let cross = 0 + let nc = 0 + for c in 0 .. ui_n { + if peek32(ui_parent, c) == i { + if peek32(ui_visible, c) == 1 { + if dir == 1 { + mainsz = mainsz + peek32(ui_rh, c) + cross = max(cross, peek32(ui_rw, c)) + } else { + mainsz = mainsz + peek32(ui_rw, c) + cross = max(cross, peek32(ui_rh, c)) + } + nc = nc + 1 + } + } + } + if nc > 1 { mainsz = mainsz + peek32(ui_gap, i) * (nc - 1) } + mainsz = mainsz + 2 * pad + cross = cross + 2 * pad + if dir == 1 { + cw = cross + ch = mainsz + } else { + cw = mainsz + ch = cross + } + } + } + } + let rw = peek32(ui_w, i) + let rh = peek32(ui_h, i) + if rw == 0 { rw = cw } + if rh == 0 { rh = ch } + poke32(ui_rw, i, rw) + poke32(ui_rh, i, rh) + } + i = i - 1 + } +} + +fn ui_eff_align(child: int, parent: int) -> int { + if peek32(ui_align, child) >= 0 { return peek32(ui_align, child) } + if peek32(ui_align, parent) >= 0 { return peek32(ui_align, parent) } + return 0 +} + +import "ui_draw.ludic" diff --git a/runtime/native/ui_draw.ludic b/runtime/native/ui_draw.ludic new file mode 100644 index 00000000..a7032264 --- /dev/null +++ b/runtime/native/ui_draw.ludic @@ -0,0 +1,283 @@ +# ui_draw.ludic — layout arrange, drawing, focus/activation and the game-facing +# accessors. Split out of ui.ludic (the storage/build/measure half). + +# ---- arrange: rects, parents before children ------------------------------ +fn ui_arrange(i: int, x: int, y: int) -> void { + poke32(ui_rx, i, x) + poke32(ui_ry, i, y) + let t = peek32(ui_type, i) + if ui_is_container(t) == false { return } + let dir = ui_dir(t) + let pad = peek32(ui_pad, i) + let gap = peek32(ui_gap, i) + let innerw = peek32(ui_rw, i) - 2 * pad + let innerh = peek32(ui_rh, i) - 2 * pad + let total = 0 + let ng = 0 + let grows = 0 + for c in 0 .. ui_n { + if peek32(ui_parent, c) == i { + if peek32(ui_visible, c) == 1 { + if dir == 1 { total = total + peek32(ui_rh, c) } else { total = total + peek32(ui_rw, c) } + ng = ng + 1 + grows = grows + peek32(ui_grow, c) + } + } + } + if ng > 1 { total = total + gap * (ng - 1) } + let avail = innerw + if dir == 1 { avail = innerh } + let extra = max(avail - total, 0) + let cx = x + pad + let cy = y + pad + for c in 0 .. ui_n { + if peek32(ui_parent, c) == i { + if peek32(ui_visible, c) == 1 { + let kw = peek32(ui_rw, c) + let kh = peek32(ui_rh, c) + if peek32(ui_grow, c) != 0 { + if grows > 0 { + if dir == 1 { kh = kh + extra / grows } else { kw = kw + extra / grows } + } + } + let al = ui_eff_align(c, i) + poke32(ui_rw, c, kw) + poke32(ui_rh, c, kh) + if dir == 1 { + let ax = x + pad + if al == 1 { ax = x + pad + (innerw - kw) / 2 } + if al == 2 { ax = x + pad + (innerw - kw) } + ui_arrange(c, ax, cy) + cy = cy + kh + gap + } else { + let ay = y + pad + if al == 1 { ay = y + pad + (innerh - kh) / 2 } + if al == 2 { ay = y + pad + (innerh - kh) } + ui_arrange(c, cx, ay) + cx = cx + kw + gap + } + } + } + } +} + +fn ui_layout() -> void { + if ui_active < 0 { return } + ui_measure() + let px = (rt_fbw - peek32(ui_rw, ui_active)) / 2 + let py = (rt_fbh - peek32(ui_rh, ui_active)) / 2 + if peek32(ui_haspos, ui_active) == 1 { + px = peek32(ui_x, ui_active) + py = peek32(ui_y, ui_active) + } + ui_arrange(ui_active, px, py) +} + +# ---- drawing -------------------------------------------------------------- +fn ui_lighten(c: int) -> int { + let r = band(shr(c, 16), 255) + let g = band(shr(c, 8), 255) + let b = band(c, 255) + r = r + (255 - r) * 4 / 10 + g = g + (255 - g) * 4 / 10 + b = b + (255 - b) * 4 / 10 + return bor(bor(shl(r, 16), shl(g, 8)), b) +} + +fn ui_draw_node(i: int) -> void { + if peek32(ui_visible, i) == 0 { return } + let t = peek32(ui_type, i) + let rx = peek32(ui_rx, i) + let ry = peek32(ui_ry, i) + let rw = peek32(ui_rw, i) + let rh = peek32(ui_rh, i) + let skin = peek32(ui_skin, i) + let focused = 0 + if i == ui_focus { focused = 1 } + + if t == WT_PANEL { + if skin >= 0 { + rt_draw_9slice(skin, rx, ry, rw, rh, peek32(ui_inset, i)) + } else { + if peek32(ui_bg, i) >= 0 { rt_fill_rect(rx, ry, rw, rh, peek32(ui_bg, i)) } + if peek32(ui_border, i) >= 0 { rt_frame_rect(rx, ry, rw, rh, peek32(ui_border, i)) } + } + } + if t == WT_BUTTON { + let bg = peek32(ui_bg, i) + if bg < 0 { bg = 0x2a2a3a } + if focused == 1 { bg = ui_lighten(bg) } + if skin >= 0 { + rt_draw_9slice(skin, rx, ry, rw, rh, peek32(ui_inset, i)) + } else { + rt_fill_rect(rx, ry, rw, rh, bg) + } + let bc = peek32(ui_border, i) + if bc < 0 { bc = 0x555577 } + if focused == 1 { bc = 0xffff00 } + rt_frame_rect(rx, ry, rw, rh, bc) + let s = ui_str(i) + let fg = peek32(ui_fg, i) + if fg < 0 { fg = 0xffffff } + let font = peek32(ui_font, i) + let size = peek32(ui_size, i) + ui_draw_text(font, rx + (rw - ui_tw(font, s, size)) / 2, ry + (rh - ui_th(font, size)) / 2, s, fg, size) + } + if t == WT_LABEL { + let s = ui_str(i) + let fg = peek32(ui_fg, i) + if fg < 0 { fg = 0xffffff } + let font = peek32(ui_font, i) + let size = peek32(ui_size, i) + let pad = peek32(ui_pad, i) + let tw = ui_tw(font, s, size) + let tx = rx + pad + let al = peek32(ui_align, i) + if al == 1 { tx = rx + (rw - tw) / 2 } + if al == 2 { tx = rx + rw - pad - tw } + ui_draw_text(font, tx, ry + pad, s, fg, size) + } + if t == WT_IMAGE { + if peek32(ui_img, i) >= 0 { rt_draw_image_scaled(peek32(ui_img, i), rx, ry, rw, rh) } + } + for c in 0 .. ui_n { + if peek32(ui_parent, c) == i { ui_draw_node(c) } + } +} + +# ---- focus and activation ------------------------------------------------- +var ui_fl: ptr = ptr_null() + +fn ui_focusables() -> int { + if ptr_is_null(ui_fl) { ui_fl = mem_alloc(UI_MAX * 4) } + let n = 0 + for i in 0 .. ui_n { + if peek32(ui_focusable, i) == 1 { + if peek32(ui_visible, i) == 1 { + if ui_under(i, ui_active) { + poke32(ui_fl, n, i) + n = n + 1 + } + } + } + } + return n +} + +fn rt_ui_open(root: int) -> void { + ui_active = root + let n = ui_focusables() + ui_focus = 0 - 1 + if n > 0 { ui_focus = peek32(ui_fl, 0) } +} + +fn rt_ui_tick(k: int) -> void { + if ui_active < 0 { return } + for i in 0 .. ui_n { poke32(ui_fired, i, 0) } + ui_layout() + let n = ui_focusables() + if n == 0 { + ui_focus = 0 - 1 + return + } + let cur = 0 - 1 + for i in 0 .. n { + if peek32(ui_fl, i) == ui_focus { cur = i } + } + if cur < 0 { + cur = 0 + ui_focus = peek32(ui_fl, 0) + } + if k == 119 { # 'w' + cur = (cur - 1 + n) % n + ui_focus = peek32(ui_fl, cur) + } + if k == 115 { # 's' + cur = (cur + 1) % n + ui_focus = peek32(ui_fl, cur) + } + if k == 32 { poke32(ui_fired, ui_focus, 1) } + if k == 10 { poke32(ui_fired, ui_focus, 1) } + if k == 13 { poke32(ui_fired, ui_focus, 1) } +} + +fn rt_ui_render() -> void { + if ui_active < 0 { return } + ui_layout() + ui_draw_node(ui_active) +} + +# ---- game-facing accessors ------------------------------------------------ +fn rt_ui_clicked(id: int) -> bool { + if id < 0 { return false } + if id >= ui_n { return false } + return peek32(ui_fired, id) == 1 +} + +fn rt_ui_set_text(id: int, s: str) -> void { + if id < 0 { return } + if id >= ui_n { return } + let base = id * 96 + let i = 0 + let ch = peek8(s, 0) + while ch != 0 { + if i >= 95 { ch = 0 } + if ch != 0 { + poke8(ui_dyn, base + i, ch) + i = i + 1 + ch = peek8(s, i) + } + } + poke8(ui_dyn, base + i, 0) + poke32(ui_hasdyn, id, 1) +} + +fn rt_ui_set_int(id: int, n: int) -> void { + if id < 0 { return } + if id >= ui_n { return } + let base = id * 96 + let at = 0 + let v = n + if v < 0 { + poke8(ui_dyn, base, 45) + at = 1 + v = 0 - v + } + if v == 0 { + poke8(ui_dyn, base + at, 48) + at = at + 1 + } else { + let digits = 0 + let t = v + while t > 0 { + digits = digits + 1 + t = t / 10 + } + let p = digits + while p > 0 { + let div = 1 + for k in 1 .. p { div = div * 10 } + poke8(ui_dyn, base + at, 48 + (v / div) % 10) + at = at + 1 + p = p - 1 + } + } + poke8(ui_dyn, base + at, 0) + poke32(ui_hasdyn, id, 1) +} + +fn rt_ui_focus(id: int) -> void { + if id < 0 { return } + if id >= ui_n { return } + ui_focus = id +} + +fn rt_ui_focused() -> int { + return ui_focus +} + +fn rt_ui_visible(id: int, v: int) -> void { + if id < 0 { return } + if id >= ui_n { return } + poke32(ui_visible, id, v) +} diff --git a/runtime/web/imports.txt b/runtime/web/imports.txt new file mode 100644 index 00000000..9f62a281 --- /dev/null +++ b/runtime/web/imports.txt @@ -0,0 +1,32 @@ +# runtime/web/imports.txt — every symbol a web build may leave undefined. +# +# ludicc passes this to wasm-ld as --allow-undefined-file, so these become the +# module's wasm imports and *anything else* undefined is a link error at build +# time rather than a LinkError in the browser. That matters because LLVM invents +# libcalls (calloc, bcmp, memmove) that ludicc never emitted: without this list +# they would silently become imports nobody implements. +# +# runtime/web/platform.js supplies all of them. + +# the window — the same five-function protocol runtime/native/cocoa.ll implements +win_open +win_poll +win_present +win_running +win_close + +# files: a preloaded image of the game's assets, plus localStorage for saves +web_fopen +web_fread +web_fwrite +web_fclose +web_fseek +web_ftell + +# stdin, stdout, the clock, and giving up +web_getchar +web_putchar +web_print_str +web_print_int +web_time +web_exit diff --git a/runtime/web/index.html b/runtime/web/index.html new file mode 100644 index 00000000..68007292 --- /dev/null +++ b/runtime/web/index.html @@ -0,0 +1,106 @@ + + + + + + +{{TITLE}} + + + + +

{{TITLE}}

+ +

loading…

+ +
+ + + + + + + + + +
+ + + + diff --git a/runtime/web/platform.js b/runtime/web/platform.js new file mode 100644 index 00000000..d531d89f --- /dev/null +++ b/runtime/web/platform.js @@ -0,0 +1,357 @@ +// ============================================================================ +// runtime/web/platform.js — the web's window, keyboard and filesystem. +// +// This file is the browser's answer to runtime/native/cocoa.ll, and it has the +// same job and the same size: implement the five-function platform protocol +// +// win_open(w, h, scale, title) win_poll() -> key win_present(fb, w, h) +// win_running() -> bool win_close() +// +// plus the handful of host services wasm has no OS to ask for — files, the +// clock, stdout. Nothing else. The game, the ECS, the framebuffer, the PNG +// decoder, the TrueType rasteriser and the UI are all compiled Ludic running +// inside the wasm module; no game logic passes through this file, and none of +// it is interpreted. +// +// const game = await LudicWeb.start({ wasm: 'chronorift.wasm', +// canvas: document.querySelector('canvas'), +// manifest: 'assets.json' }) +// ============================================================================ + +export const LudicWeb = { start }; + +// --------------------------------------------------------------------------- +// Keyboard. win_poll() reports the last key pressed since the previous frame, +// as a character code, or 0 for none — exactly what cocoa.ll reports. Arrow +// keys fold onto WASD and Escape onto 'q', so a game written for the native +// build needs no web-specific input handling. +// --------------------------------------------------------------------------- +const KEY_ALIASES = { + ArrowUp: 'w', ArrowLeft: 'a', ArrowDown: 's', ArrowRight: 'd', + Escape: 'q', Enter: '\r', Backspace: '\b', Tab: '\t', +}; + +function keyCode(ev) { + const alias = KEY_ALIASES[ev.key]; + if (alias) return alias.charCodeAt(0); + if (ev.key.length === 1) return ev.key.charCodeAt(0); + return 0; +} + +// --------------------------------------------------------------------------- +// A read-only image of the game's files, plus a writable overlay in +// localStorage for save games. +// +// The Ludic runtime opens assets with file_open()/file_read(), which on a +// native build is fopen/fread. The browser has no synchronous file access, so +// every file the game can open is fetched up front (see the manifest ludicc +// emits beside the .wasm) and served out of memory. Saves go the other way: +// file_open("game.sav","wb") buffers, and fclose commits to localStorage, so +// save/load survives a page reload. +// --------------------------------------------------------------------------- +export class Files { + constructor(preloaded, storageKey) { + this.assets = preloaded; // Map + this.storageKey = storageKey; + this.open = new Map(); // handle -> {data, pos, path, write} + this.next = 1; // 0 is NULL to the Ludic side + } + + saved(path) { + try { + const raw = localStorage.getItem(this.storageKey + path); + if (raw === null) return null; + const bytes = new Uint8Array(raw.length); + for (let i = 0; i < raw.length; i++) bytes[i] = raw.charCodeAt(i) & 0xff; + return bytes; + } catch { return null; } + } + + commit(path, data) { + try { + let raw = ''; + for (let i = 0; i < data.length; i += 0x8000) + raw += String.fromCharCode.apply(null, data.subarray(i, i + 0x8000)); + localStorage.setItem(this.storageKey + path, raw); + } catch (e) { + console.warn('ludic: could not persist', path, e); + } + } + + fopen(path, mode) { + const writing = mode.includes('w') || mode.includes('a'); + if (writing) { + const h = this.next++; + this.open.set(h, { path, pos: 0, write: true, chunks: [], size: 0 }); + return h; + } + // Reads prefer a save the player has made over the shipped asset. + const data = this.saved(path) || this.assets.get(path) || + this.assets.get(path.replace(/^\.\//, '')); + if (!data) return 0; // NULL: the game handles it + const h = this.next++; + this.open.set(h, { path, pos: 0, write: false, data }); + return h; + } + + fread(h, dst, want) { + const f = this.open.get(h); + if (!f || f.write) return 0; + const n = Math.max(0, Math.min(want, f.data.length - f.pos)); + dst.set(f.data.subarray(f.pos, f.pos + n)); + f.pos += n; + return n; + } + + fwrite(h, src, n) { + const f = this.open.get(h); + if (!f || !f.write) return 0; + f.chunks.push(src.slice(0, n)); // copy: wasm memory is reused + f.size += n; + f.pos += n; + return n; + } + + fclose(h) { + const f = this.open.get(h); + if (!f) return; + if (f.write) { + const all = new Uint8Array(f.size); + let at = 0; + for (const c of f.chunks) { all.set(c, at); at += c.length; } + this.commit(f.path, all); + } + this.open.delete(h); + } + + fseek(h, off, whence) { + const f = this.open.get(h); + if (!f) return -1; + const end = f.write ? f.size : f.data.length; + const base = whence === 1 ? f.pos : whence === 2 ? end : 0; + f.pos = Math.max(0, Math.min(end, base + off)); + return 0; + } + + ftell(h) { + const f = this.open.get(h); + return f ? f.pos : -1; + } +} + +// --------------------------------------------------------------------------- +// The canvas. win_present() hands over a pointer to the framebuffer — one +// 0x00RRGGBB word per pixel — which is transcoded into the RGBA byte order +// ImageData wants and blitted at the requested integer scale. +// --------------------------------------------------------------------------- +class Screen { + constructor(canvas) { + this.canvas = canvas; + this.ctx = null; + this.image = null; + this.w = 0; this.h = 0; + } + + open(w, h, scale, title) { + this.w = w; this.h = h; + this.canvas.width = w; + this.canvas.height = h; + // The backing store stays at the framebuffer's own resolution and CSS does + // the scaling, so a 320x240 game stays crisp on a HiDPI display. + // + // How big to draw it is the page's decision, not the platform layer's: a 3x + // 320x240 window is 720px tall and does not fit a laptop viewport once there + // is a title above it. So this publishes the framebuffer's dimensions and + // the scale the game asked for, and leaves the fitting to CSS — see the + // width rule in runtime/web/index.html. + const css = this.canvas.style; + css.setProperty('--ludic-w', String(w)); + css.setProperty('--ludic-h', String(h)); + css.setProperty('--ludic-scale', String(scale)); + css.aspectRatio = w + ' / ' + h; + css.height = 'auto'; + css.imageRendering = 'pixelated'; + this.ctx = this.canvas.getContext('2d', { alpha: false }); + this.ctx.imageSmoothingEnabled = false; + this.image = this.ctx.createImageData(w, h); + this.rgba = new Uint32Array(this.image.data.buffer); + if (title) document.title = title; + } + + present(words, w, h) { + if (!this.ctx) return; + if (w !== this.w || h !== this.h) this.open(w, h, 1, null); + const dst = this.rgba; + // Little-endian ImageData is 0xAABBGGRR; the framebuffer is 0x00RRGGBB. + for (let i = 0, n = w * h; i < n; i++) { + const c = words[i]; + dst[i] = 0xff000000 | ((c & 0xff) << 16) | (c & 0xff00) | ((c >>> 16) & 0xff); + } + this.ctx.putImageData(this.image, 0, 0); + } +} + +// --------------------------------------------------------------------------- +// Host — the memory views and the services wasm has no OS to ask for. +// +// A wasm module's linear memory is detached and replaced every time it grows, +// so every view has to be re-derived rather than cached across a call. Beyond +// that this is just the non-window half of the platform: files, stdin, stdout +// and the clock. The browser and Node need exactly the same set, so the Node +// test runner (tools/ludic-web/run.mjs) builds on this class too, and only the +// five win_* functions differ between the two hosts. +// --------------------------------------------------------------------------- +export class Host { + constructor({ files, stdin = '', log = console.log } = {}) { + this.files = files; + this.stdin = stdin; + this.stdinAt = 0; + this.log = log; + this.line = ''; + this.memory = null; + this.buffer = null; + this.running = 1; + this.exitCode = null; + } + + bind(memory) { this.memory = memory; this.sync(); } + + sync() { + if (this.memory.buffer !== this.buffer) { + this.buffer = this.memory.buffer; + this.u8 = new Uint8Array(this.buffer); + this.u32 = new Uint32Array(this.buffer); + } + } + + cstr(p) { + this.sync(); + let end = p; + while (this.u8[end] !== 0) end++; + return new TextDecoder().decode(this.u8.subarray(p, end)); + } + + flush() { if (this.line) { this.log(this.line); this.line = ''; } } + + imports() { + const fs = this.files; + return { + web_fopen: (path, mode) => fs.fopen(this.cstr(path), this.cstr(mode)), + web_fread: (h, dst, n) => { this.sync(); return fs.fread(h, this.u8.subarray(dst, dst + n), n); }, + web_fwrite: (h, src, n) => { this.sync(); return fs.fwrite(h, this.u8.subarray(src, src + n), n); }, + web_fclose: (h) => fs.fclose(h), + web_fseek: (h, off, whence) => fs.fseek(h, off, whence), + web_ftell: (h) => fs.ftell(h), + + web_getchar: () => (this.stdinAt < this.stdin.length ? this.stdin.charCodeAt(this.stdinAt++) : -1), + web_putchar: (c) => { if (c === 10) this.flush(); else this.line += String.fromCharCode(c); }, + web_print_str: (p) => { this.line += this.cstr(p); }, + // print_int(n) is printf("%d\n", n) natively, newline included. + web_print_int: (n) => { this.line += String(n); this.flush(); }, + web_time: () => Math.floor(Date.now() / 1000), + web_exit: (code) => { + this.running = 0; this.exitCode = code; this.flush(); + throw new ExitSignal(code); + }, + }; + } +} + +// --------------------------------------------------------------------------- +// start() — fetch the module and its assets, wire the imports, run the loop. +// +// The native entry point is `while (alive) frame();`. A browser tab cannot be +// held that way, so a web build exports the loop's parts instead — +// ludic_boot / ludic_frame / ludic_alive / ludic_teardown — and this drives +// them from requestAnimationFrame. The systems that run per frame, and their +// order, are identical; only who owns the loop changes. +// --------------------------------------------------------------------------- +async function start({ wasm, canvas, manifest = null, files = {}, onExit = null, + stdin = '', storageKey = 'ludic:' } = {}) { + const assets = new Map(); + for (const [path, bytes] of Object.entries(files)) assets.set(path, bytes); + + if (manifest) { + const list = await (await fetch(manifest)).json(); + await Promise.all(list.map(async (path) => { + const res = await fetch(path); + if (!res.ok) { console.warn('ludic: missing asset', path); return; } + assets.set(path, new Uint8Array(await res.arrayBuffer())); + })); + } + + const host = new Host({ files: new Files(assets, storageKey) }); + const screen = new Screen(canvas); + let pendingKey = 0; + + const env = { + ...host.imports(), + // The window, which is the only part of the platform the browser and the + // test runner do not share. + win_open: (w, h, scale, title) => screen.open(w, h, scale || 1, host.cstr(title)), + win_poll: () => { const k = pendingKey; pendingKey = 0; return k; }, + win_present: (fb, w, h) => { + host.sync(); + screen.present(host.u32.subarray(fb >>> 2, (fb >>> 2) + w * h), w, h); + }, + win_running: () => host.running, + win_close: () => { host.running = 0; }, + }; + + const { instance } = await WebAssembly.instantiateStreaming(fetch(wasm), { env }); + host.bind(instance.exports.memory); + + const { ludic_boot, ludic_frame, ludic_alive, ludic_teardown } = instance.exports; + + const onKey = (ev) => { + const k = keyCode(ev); + if (k) { pendingKey = k; ev.preventDefault(); } + }; + window.addEventListener('keydown', onKey); + + const game = { + instance, + exports: instance.exports, + // Lets a page wire on-screen buttons for touch devices: game.press('w'). + press: (k) => { pendingKey = typeof k === 'string' ? k.charCodeAt(0) : k; }, + stop: () => { host.running = 0; }, + }; + + let stopped = false; + const finish = () => { + if (stopped) return; + stopped = true; + window.removeEventListener('keydown', onKey); + try { ludic_teardown(); } catch (e) { if (!(e instanceof ExitSignal)) throw e; } + host.flush(); + if (onExit) onExit(host.exitCode ?? 0); + }; + + const step = () => { + if (stopped) return; + try { + if (!host.running || !ludic_alive()) return finish(); + ludic_frame(); + } catch (e) { + if (e instanceof ExitSignal) return finish(); + stopped = true; + window.removeEventListener('keydown', onKey); + throw e; + } + requestAnimationFrame(step); + }; + + try { ludic_boot(); } catch (e) { + if (!(e instanceof ExitSignal)) throw e; + finish(); + return game; + } + requestAnimationFrame(step); + return game; +} + +// os_exit() has to unwind the wasm frame it was called from; there is no +// process to terminate, so it throws and the loop treats it as the end. +export class ExitSignal extends Error { + constructor(code) { super('ludic: exit(' + code + ')'); this.code = code; } +} diff --git a/runtime/web/wasm.ll b/runtime/web/wasm.ll new file mode 100644 index 00000000..80a7c295 --- /dev/null +++ b/runtime/web/wasm.ll @@ -0,0 +1,369 @@ +; ============================================================================ +; runtime/web/wasm.ll — the web platform layer, written in LLVM IR. +; +; This is to the browser what runtime/native/cocoa.ll is to macOS: the one +; per-platform file, hand-written in the same IR ludicc emits, assembled by the +; same toolchain and handed to the same linker. No C is compiled here either. +; +; It exists because wasm32-unknown-unknown has no libc. The Ludic runtime +; (runtime/native/*.ludic) stands on a floor of ~15 platform calls — malloc, +; memcpy, fopen, getchar — and on a native target those are the OS's. On the +; web there is no OS underneath, so this file *is* the floor: +; +; * the allocator is implemented here, over wasm linear memory; +; * memcpy/memset/strlen are implemented here; +; * everything genuinely external — files, stdin, stdout, the clock, and the +; five win_* window functions — is a wasm import, resolved by +; runtime/web/platform.js. +; +; Nothing above this file changes for the web. core.ludic, image.ludic, +; truetype.ludic and ui.ludic compile to wasm unmodified. +; ============================================================================ + +target triple = "wasm32-unknown-unknown" + +declare i32 @llvm.wasm.memory.size.i32(i32) +declare i32 @llvm.wasm.memory.grow.i32(i32, i32) +declare void @llvm.memcpy.p0.p0.i32(ptr, ptr, i32, i1) +declare void @llvm.memmove.p0.p0.i32(ptr, ptr, i32, i1) +declare void @llvm.memset.p0.i32(ptr, i8, i32, i1) + +; wasm-ld places this symbol immediately after the static data segments; its +; *address* is where our heap may begin. +@__heap_base = external global i8 + +; --------------------------------------------------------------------------- +; The allocator. +; +; A first-fit free list over linear memory, growing the wasm memory with +; memory.grow when it runs out. Every block carries an 8-byte header +; [i32 payload_size][i32 next_free] and the pointer handed out is header+8, so +; free() is O(1) and malloc() reuses blocks of a size it has seen before — +; which is the shape of the load the PNG decoder actually makes (a dozen tiles +; of identical dimensions, each decode allocating and releasing the same three +; buffers). Blocks are split when the fit is loose; adjacent free blocks are +; not coalesced, which costs some fragmentation and buys a lot of simplicity. +; --------------------------------------------------------------------------- + +@ludic_brk = internal global i32 0 ; bump pointer; 0 until first use +@ludic_free = internal global i32 0 ; head of the free list, 0 = empty + +define ptr @malloc(i32 %n0) { +entry: + %small = icmp slt i32 %n0, 1 + %n1 = select i1 %small, i32 1, i32 %n0 + %pad = add i32 %n1, 7 + %n = and i32 %pad, -8 ; 8-byte aligned payloads + %head = load i32, ptr @ludic_free + br label %scan + +scan: ; walk the free list, first fit + %cur = phi i32 [ %head, %entry ], [ %nxt, %scan.next ] + %prev = phi i32 [ 0, %entry ], [ %cur, %scan.next ] + %end = icmp eq i32 %cur, 0 + br i1 %end, label %bump, label %check + +check: + %cp = inttoptr i32 %cur to ptr + %sz = load i32, ptr %cp + %nxtp = getelementptr i8, ptr %cp, i32 4 + %nxt = load i32, ptr %nxtp + %fits = icmp sge i32 %sz, %n + br i1 %fits, label %take, label %scan.next + +scan.next: + br label %scan + +take: ; unlink %cur from the free list + %first = icmp eq i32 %prev, 0 + br i1 %first, label %unlink.head, label %unlink.mid +unlink.head: + store i32 %nxt, ptr @ludic_free + br label %split +unlink.mid: + %pp = inttoptr i32 %prev to ptr + %pnp = getelementptr i8, ptr %pp, i32 4 + store i32 %nxt, ptr %pnp + br label %split + +split: ; give the tail back if it is worth it + %floor = add i32 %n, 40 + %loose = icmp sge i32 %sz, %floor + br i1 %loose, label %do.split, label %take.done +do.split: + store i32 %n, ptr %cp + %tail = sub i32 %sz, %n + %tailsz = sub i32 %tail, 8 + %tailat0 = add i32 %cur, 8 + %tailat = add i32 %tailat0, %n + %tp = inttoptr i32 %tailat to ptr + store i32 %tailsz, ptr %tp + %tnp = getelementptr i8, ptr %tp, i32 4 + %fh = load i32, ptr @ludic_free + store i32 %fh, ptr %tnp + store i32 %tailat, ptr @ludic_free + br label %take.done +take.done: + %reuse = getelementptr i8, ptr %cp, i32 8 + ret ptr %reuse + +bump: ; nothing reusable: take fresh memory + %b0 = load i32, ptr @ludic_brk + %new = icmp eq i32 %b0, 0 + br i1 %new, label %brk.init, label %brk.have +brk.init: + %hb = ptrtoint ptr @__heap_base to i32 + %hb7 = add i32 %hb, 7 + %hba = and i32 %hb7, -8 + br label %brk.have +brk.have: + %brk = phi i32 [ %b0, %bump ], [ %hba, %brk.init ] + %hdr = add i32 %brk, 8 + %need = add i32 %hdr, %n + %pages = call i32 @llvm.wasm.memory.size.i32(i32 0) + %have = shl i32 %pages, 16 + %short = icmp ugt i32 %need, %have + br i1 %short, label %grow, label %carve +grow: + %deficit = sub i32 %need, %have + %round = add i32 %deficit, 65535 + %want = lshr i32 %round, 16 + %got = call i32 @llvm.wasm.memory.grow.i32(i32 0, i32 %want) + %oom = icmp eq i32 %got, -1 + br i1 %oom, label %fail, label %carve +fail: + ret ptr null +carve: + %hp = inttoptr i32 %brk to ptr + store i32 %n, ptr %hp + store i32 %need, ptr @ludic_brk + %up = inttoptr i32 %hdr to ptr + ret ptr %up +} + +define void @free(ptr %p) { +entry: + %nil = icmp eq ptr %p, null + br i1 %nil, label %out, label %push +push: + %pi = ptrtoint ptr %p to i32 + %hi = sub i32 %pi, 8 + %hp = inttoptr i32 %hi to ptr + %np = getelementptr i8, ptr %hp, i32 4 + %fh = load i32, ptr @ludic_free + store i32 %fh, ptr %np + store i32 %hi, ptr @ludic_free + br label %out +out: + ret void +} + +; calloc and realloc are here because LLVM *invents* calls to them. It +; recognises the allocator by name, so an -O2 pass rewrites the +; mem_alloc()+mem_set(0) that core.ludic's rt_init does into a single calloc. +; The platform layer therefore has to be a complete enough libc for whatever the +; optimiser lowers to, not just for what ludicc emits. +define ptr @calloc(i32 %count, i32 %size) { +entry: + %n = mul i32 %count, %size + %p = call ptr @malloc(i32 %n) + %nil = icmp eq ptr %p, null + br i1 %nil, label %out, label %zero +zero: + call void @llvm.memset.p0.i32(ptr %p, i8 0, i32 %n, i1 false) + br label %out +out: + ret ptr %p +} + +; the block header carries its own size, so realloc can grow in place +define ptr @realloc(ptr %p, i32 %n) { +entry: + %nil = icmp eq ptr %p, null + br i1 %nil, label %fresh, label %known +fresh: + %f = call ptr @malloc(i32 %n) + ret ptr %f +known: + %pi = ptrtoint ptr %p to i32 + %hi = sub i32 %pi, 8 + %hp = inttoptr i32 %hi to ptr + %old = load i32, ptr %hp + %big = icmp sge i32 %old, %n + br i1 %big, label %keep, label %move +keep: + ret ptr %p +move: + %new = call ptr @malloc(i32 %n) + %bad = icmp eq ptr %new, null + br i1 %bad, label %fail, label %shift +fail: + ret ptr null +shift: + call void @llvm.memcpy.p0.p0.i32(ptr %new, ptr %p, i32 %old, i1 false) + call void @free(ptr %p) + ret ptr %new +} + +; --------------------------------------------------------------------------- +; Bulk memory and strings. +; +; size_t is 32-bit on wasm32, which is the signature ludicc emits for this +; target and the one LLVM canonicalises these names to. They use the wasm +; bulk-memory instructions (memory.copy / memory.fill) rather than a byte loop. +; --------------------------------------------------------------------------- + +define ptr @memcpy(ptr %d, ptr %s, i32 %n) { + call void @llvm.memcpy.p0.p0.i32(ptr %d, ptr %s, i32 %n, i1 false) + ret ptr %d +} + +define ptr @memset(ptr %d, i32 %c, i32 %n) { + %b = trunc i32 %c to i8 + call void @llvm.memset.p0.i32(ptr %d, i8 %b, i32 %n, i1 false) + ret ptr %d +} + +define ptr @memmove(ptr %d, ptr %s, i32 %n) { + call void @llvm.memmove.p0.p0.i32(ptr %d, ptr %s, i32 %n, i1 false) + ret ptr %d +} + +define i32 @memcmp(ptr %a, ptr %b, i32 %n) { +entry: + br label %loop +loop: + %i = phi i32 [ 0, %entry ], [ %i1, %step ] + %done = icmp uge i32 %i, %n + br i1 %done, label %same, label %test +test: + %ap = getelementptr i8, ptr %a, i32 %i + %bp = getelementptr i8, ptr %b, i32 %i + %av = load i8, ptr %ap + %bv = load i8, ptr %bp + %eq = icmp eq i8 %av, %bv + br i1 %eq, label %step, label %differ +step: + %i1 = add i32 %i, 1 + br label %loop +differ: + %az = zext i8 %av to i32 + %bz = zext i8 %bv to i32 + %r = sub i32 %az, %bz + ret i32 %r +same: + ret i32 0 +} + +; LLVM emits bcmp for comparisons whose result is only tested against zero. +define i32 @bcmp(ptr %a, ptr %b, i32 %n) { + %r = call i32 @memcmp(ptr %a, ptr %b, i32 %n) + ret i32 %r +} + +define i32 @strlen(ptr %s) { +entry: + br label %loop +loop: + %i = phi i32 [ 0, %entry ], [ %i1, %step ] + %cp = getelementptr i8, ptr %s, i32 %i + %c = load i8, ptr %cp + %z = icmp eq i8 %c, 0 + br i1 %z, label %out, label %step +step: + %i1 = add i32 %i, 1 + br label %loop +out: + ret i32 %i +} + +; --------------------------------------------------------------------------- +; Everything genuinely outside the module. +; +; These are wasm imports: platform.js supplies them, exactly as Cocoa supplies +; objc_msgSend to cocoa.ll. Files are served from a preloaded read-only image of +; the game's assets; the save file is backed by localStorage. +; --------------------------------------------------------------------------- + +declare i32 @web_fopen(ptr, ptr) ; -> handle, 0 on failure +declare i32 @web_fread(i32, ptr, i32) +declare i32 @web_fwrite(i32, ptr, i32) +declare void @web_fclose(i32) +declare i32 @web_fseek(i32, i32, i32) +declare i32 @web_ftell(i32) +declare i32 @web_time() +declare void @web_exit(i32) + +; A file handle is an opaque `ptr` to the Ludic runtime, and a small integer to +; JS. Handle 0 doubles as libc's NULL, so `file_open` failure checks work +; unchanged. +define ptr @fopen(ptr %path, ptr %mode) { + %h = call i32 @web_fopen(ptr %path, ptr %mode) + %p = inttoptr i32 %h to ptr + ret ptr %p +} + +define i32 @fread(ptr %buf, i32 %size, i32 %count, ptr %f) { + %bytes = mul i32 %size, %count + %h = ptrtoint ptr %f to i32 + %got = call i32 @web_fread(i32 %h, ptr %buf, i32 %bytes) + ret i32 %got +} + +define i32 @fwrite(ptr %buf, i32 %size, i32 %count, ptr %f) { + %bytes = mul i32 %size, %count + %h = ptrtoint ptr %f to i32 + %put = call i32 @web_fwrite(i32 %h, ptr %buf, i32 %bytes) + ret i32 %put +} + +define i32 @fclose(ptr %f) { + %h = ptrtoint ptr %f to i32 + call void @web_fclose(i32 %h) + ret i32 0 +} + +define i32 @fseek(ptr %f, i32 %off, i32 %whence) { + %h = ptrtoint ptr %f to i32 + %r = call i32 @web_fseek(i32 %h, i32 %off, i32 %whence) + ret i32 %r +} + +define i32 @ftell(ptr %f) { + %h = ptrtoint ptr %f to i32 + %r = call i32 @web_ftell(i32 %h) + ret i32 %r +} + +define i64 @time(ptr %slot) { + %s = call i32 @web_time() + %r = sext i32 %s to i64 + ret i64 %r +} + +define void @exit(i32 %code) noreturn { + call void @web_exit(i32 %code) + unreachable +} + +; stdin/stdout. A windowed web build never reads stdin — rt_poll() goes through +; win_poll() — but the intrinsic still has to resolve, and the headless path +; (used by the test suite under Node) genuinely uses both. +declare i32 @web_getchar() +declare void @web_putchar(i32) + +define i32 @getchar() { + %c = call i32 @web_getchar() + ret i32 %c +} + +define i32 @putchar(i32 %c) { + call void @web_putchar(i32 %c) + ret i32 %c +} + +; `print_str` is the one intrinsic ludicc lowers differently for the web: on a +; native target it goes through variadic printf("%s"), which wasm's strict +; signature checking makes awkward, so the web backend emits a direct call to +; @web_print_str instead. It is a pure import — platform.js defines it — and so +; needs no adapter here. diff --git a/selfhost/ast.ludic b/selfhost/ast.ludic new file mode 100644 index 00000000..dae73540 --- /dev/null +++ b/selfhost/ast.ludic @@ -0,0 +1,68 @@ +# ast.ludic — the node kinds and the single Node shape they share, plus the +# declaration tables the emitter reads. Mirrors compiler/front/ast.h + sem/. + +# declarations +const N_STRUCT: int = 0 +const N_FIELD: int = 1 +const N_VAR: int = 2 +const N_CONST: int = 3 +const N_FN: int = 4 +const N_PARAM: int = 5 +const N_MAIN: int = 6 +const N_BLOCK: int = 7 +const N_COMP: int = 8 +const N_SYS: int = 9 +const N_ARCH: int = 10 +const N_EXTERN: int = 11 +const N_UI: int = 12 +# statements +const S_LET: int = 10 +const S_ASSIGN: int = 11 +const S_IF: int = 12 +const S_WHILE: int = 13 +const S_FOR: int = 14 +const S_RETURN: int = 15 +const S_EXPR: int = 16 +const S_BREAK: int = 17 +const S_CONTINUE: int = 18 +const S_MATCH: int = 19 +const S_MARM: int = 20 +const S_QUERY: int = 21 +const S_SPAWN: int = 22 +const S_DESPAWN: int = 23 +const S_MACHINE: int = 24 +const S_STATE: int = 25 +const S_BECOME: int = 26 +# expressions +const E_INT: int = 30 +const E_STR: int = 31 +const E_BOOL: int = 32 +const E_ID: int = 33 +const E_CALL: int = 34 +const E_MEMBER: int = 35 +const E_INDEX: int = 36 +const E_BIN: int = 37 +const E_UN: int = 38 +const E_NEW: int = 39 +const E_FLOAT: int = 40 +const E_REC: int = 41 +const E_FINIT: int = 42 + +struct Node { + kind: int = 0 + s: ptr = ptr_null() # name / operator / string / type-of-new + ival: int = 0 # int literal, bool, flags + ty: ptr = ptr_null() # declared type (let/param/field/fn/var/const) + a: Node # fixed children (meaning per kind) + b: Node + c: Node + kids: []Node # variadic children + line: int = 0 +} + +fn node(kind: int) -> Node { + let n = new Node + n.kind = kind + n.kids = new []Node + return n +} diff --git a/selfhost/bootstrap-cfree.sh b/selfhost/bootstrap-cfree.sh new file mode 100755 index 00000000..45ed1077 --- /dev/null +++ b/selfhost/bootstrap-cfree.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# bootstrap-cfree.sh — rebuild the self-hosted compiler with NO C compiler. +# +# The C `ludicc` is retired to a one-time seed: selfhost/ludicc.seed.ll is the +# self-host compiler's own LLVM IR, a proven fixed point. From it plus clang +# (an IR assembler, the same floor Rust and Swift stand on) the compiler +# rebuilds itself and reproduces its own IR — the C source is never invoked. +# +# seed.ll --clang--> sh_seed +# sh_seed compiles selfhost.ludic -> out.ll +# assert out.ll == seed.ll (the seed is a true fixed point) +set -u +cd "$(dirname "$0")/.." +CC="${LUDIC_CC:-clang}" +B=build/cfree +mkdir -p "$B" + +# assemble the compiler straight from the checked-in seed — no C involved +$CC selfhost/ludicc.seed.ll -o "$B/sh_seed" 2>/dev/null || { echo "FAIL: assemble seed"; exit 1; } +echo " seed.ll --clang--> sh_seed (no C compiler used)" + +# regenerate the concatenated source the same way build.sh does (pure shell) +FRAGS="selfhost/str.ludic selfhost/buf.ludic selfhost/io.ludic selfhost/ast.ludic +selfhost/lex.ludic selfhost/parse.ludic selfhost/parse_game.ludic selfhost/emit_core.ludic selfhost/emit_head.ludic +selfhost/emit_addr.ludic selfhost/emit_intrin.ludic selfhost/emit_intrin2.ludic selfhost/emit_math.ludic selfhost/emit_new.ludic +selfhost/emit_expr.ludic selfhost/emit_stmt.ludic selfhost/emit_ecs.ludic selfhost/emit_query.ludic selfhost/emit_spawn.ludic selfhost/emit_game.ludic selfhost/emit_machine.ludic selfhost/emit_save.ludic selfhost/emit_ui.ludic selfhost/emit_decl.ludic selfhost/main.ludic" +{ echo "game SelfHost {"; for f in $FRAGS; do cat "$f"; echo; done; echo "}"; } > "$B/selfhost.ludic" + +# the seed-built compiler compiles its own source +"$B/sh_seed" "$B/selfhost.ludic" > "$B/out.ll" 2>/dev/null || { echo "FAIL: seed compiler self-compile"; exit 1; } +echo " sh_seed compiles selfhost.ludic -> out.ll ($(wc -l < "$B/out.ll" | tr -d ' ') lines)" + +if cmp -s "$B/out.ll" selfhost/ludicc.seed.ll; then + echo " ✅ out.ll == seed.ll — the compiler rebuilds itself with no C compiler" + exit 0 +else + echo " â�Œ out.ll != seed.ll (seed is stale — regenerate with ./selfhost/reseed.sh)" + diff "$B/out.ll" selfhost/ludicc.seed.ll | head + exit 1 +fi diff --git a/selfhost/bootstrap.sh b/selfhost/bootstrap.sh new file mode 100755 index 00000000..68658094 --- /dev/null +++ b/selfhost/bootstrap.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# bootstrap.sh — the self-hosting proof. +# +# stage0: the C compiler (build/ludicc) compiles the self-host source -> gen1 +# stage1: gen1 compiles the self-host source -> gen2 +# stage2: gen2 compiles the self-host source -> gen3 +# assert: gen2.ll == gen3.ll (the compiler reproduces itself exactly) +# +# gen1 is built by a *different* compiler (the C one), so its IR legitimately +# differs; gen2 == gen3 is the fixpoint that proves independence. +set -u +cd "$(dirname "$0")/.." +CC="${LUDIC_CC:-clang}" +B=build/boot +mkdir -p "$B" +say() { printf " %s\n" "$1"; } + +# stage 0: C compiler builds the self-host compiler (also writes build/selfhost.ludic) +./selfhost/build.sh build/ludicc "$B/gen1" >/dev/null 2>&1 || { echo "FAIL: stage0 build"; exit 1; } +say "stage0: C ludicc -> gen1 (self-host compiler)" + +# stage 1: gen1 compiles the self-host source to IR, assemble -> gen2 +"$B/gen1" build/selfhost.ludic > "$B/gen2.ll" 2>/dev/null || { echo "FAIL: gen1 self-compile"; exit 1; } +$CC "$B/gen2.ll" -o "$B/gen2" 2>/dev/null || { echo "FAIL: gen2 assemble"; exit 1; } +say "stage1: gen1 -> gen2.ll ($(wc -l < "$B/gen2.ll" | tr -d ' ') lines) -> gen2" + +# stage 2: gen2 compiles the self-host source to IR -> gen3 +"$B/gen2" build/selfhost.ludic > "$B/gen3.ll" 2>/dev/null || { echo "FAIL: gen2 self-compile"; exit 1; } +say "stage2: gen2 -> gen3.ll ($(wc -l < "$B/gen3.ll" | tr -d ' ') lines)" + +# the fixpoint +if cmp -s "$B/gen2.ll" "$B/gen3.ll"; then + rm -f build/selfhost.ludic + echo " ✅ FIXPOINT: gen2.ll == gen3.ll — the self-hosted compiler reproduces itself" + exit 0 +else + echo " â�Œ gen2.ll != gen3.ll" + diff "$B/gen2.ll" "$B/gen3.ll" | head + exit 1 +fi diff --git a/selfhost/buf.ludic b/selfhost/buf.ludic new file mode 100644 index 00000000..0d668a4e --- /dev/null +++ b/selfhost/buf.ludic @@ -0,0 +1,29 @@ +# buf.ludic — a growable byte buffer for building IR text. The emitter writes +# module-level material (types, globals, string constants) into one buffer and +# function bodies into another, then prints them in order. + +struct Buf { data: ptr = ptr_null(), len: int = 0, cap: int = 0 } + +fn buf_new() -> Buf { + let b = new Buf + b.cap = 256 + b.data = mem_alloc(b.cap) + b.len = 0 + return b +} +fn buf_ensure(b: Buf, extra: int) -> void { + if b.len + extra + 1 <= b.cap { return } + while b.len + extra + 1 > b.cap { b.cap = b.cap * 2 } + b.data = mem_realloc(b.data, b.cap) +} +fn buf_putc(b: Buf, c: int) -> void { + buf_ensure(b, 1) + poke8(b.data, b.len, c) + b.len = b.len + 1 +} +fn buf_puts(b: Buf, s: ptr) -> void { + let i = 0 + while peek8(s, i) != 0 { buf_putc(b, peek8(s, i)) i = i + 1 } +} +fn buf_puti(b: Buf, n: int) -> void { buf_puts(b, itoa(n)) } +fn buf_str(b: Buf) -> ptr { poke8(b.data, b.len, 0) return b.data } diff --git a/selfhost/build.sh b/selfhost/build.sh new file mode 100755 index 00000000..b2050eb5 --- /dev/null +++ b/selfhost/build.sh @@ -0,0 +1,39 @@ +#!/bin/bash +# build.sh — assemble the self-host compiler from its fragments and compile it +# with the given ludicc (default: the C build/ludicc). +# ./selfhost/build.sh [ludicc] [outbin] +set -u +cd "$(dirname "$0")/.." +LC="${1:-build/ludicc}" +OUT="${2:-build/selfhost}" +mkdir -p build +FRAGS="selfhost/str.ludic +selfhost/buf.ludic +selfhost/io.ludic +selfhost/ast.ludic +selfhost/lex.ludic +selfhost/parse.ludic +selfhost/parse_game.ludic +selfhost/emit_core.ludic +selfhost/emit_head.ludic +selfhost/emit_addr.ludic +selfhost/emit_intrin.ludic +selfhost/emit_intrin2.ludic +selfhost/emit_math.ludic +selfhost/emit_new.ludic +selfhost/emit_expr.ludic +selfhost/emit_stmt.ludic +selfhost/emit_ecs.ludic +selfhost/emit_query.ludic +selfhost/emit_spawn.ludic +selfhost/emit_game.ludic +selfhost/emit_machine.ludic +selfhost/emit_save.ludic +selfhost/emit_ui.ludic +selfhost/emit_decl.ludic +selfhost/main.ludic" +SRC=build/selfhost.ludic +{ echo "game SelfHost {"; for f in $FRAGS; do cat "$f"; echo; done; echo "}"; } > "$SRC" +# the compiler emits IR to stdout; clang assembles and links it +"$LC" "$SRC" > "$OUT.ll" 2>/dev/null && ${LUDIC_CC:-clang} "$OUT.ll" -o "$OUT" 2>/dev/null +rc=$?; rm -f "$OUT.ll"; [ $rc -eq 0 ] diff --git a/selfhost/compile.sh b/selfhost/compile.sh new file mode 100755 index 00000000..cd7b0e90 --- /dev/null +++ b/selfhost/compile.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# compile.sh — compile a .ludic file with the self-hosted compiler and link it. +# ./selfhost/compile.sh +set -eu +cd "$(dirname "$0")/.." +SH="$1"; IN="$2"; OUT="$3" +"$SH" "$IN" > "$OUT.ll" +clang "$OUT.ll" -o "$OUT" diff --git a/selfhost/emit_addr.ludic b/selfhost/emit_addr.ludic new file mode 100644 index 00000000..d9d523bc --- /dev/null +++ b/selfhost/emit_addr.ludic @@ -0,0 +1,38 @@ +# emit_addr.ludic — addresses of lvalues (struct fields and slice elements), +# shared by expression loads and assignment stores. Each returns the address +# register; the element/field type is written into g_addr_ty. + +var g_addr_ty: ptr # out-param: the type at the computed address + +# address of `base.field` +fn emit_member_addr(e: Node) -> ptr { + let base = emit_expr(e.a) + let s = layout_node(base.ty) + if ptr_is_null(s) { perr(sconcat("member access on non-aggregate ", base.ty)) } + let fidx = field_index(s, e.s) + if fidx < 0 { perr(sconcat("no such field ", e.s)) } + g_addr_ty = field_type(s, e.s) + let r = nreg() + emit(" ") emit(r) emit(" = getelementptr inbounds ") emit(layout_ty(base.ty)) + emit(", ptr ") emit(base.code) emit(", i32 0, i32 ") emit(itoa(fidx)) emit("\n") + return r +} + +# address of `base[index]` (slices only in this subset) +fn emit_index_addr(e: Node) -> ptr { + let base = emit_expr(e.a) + if not is_slice_ty(base.ty) { perr("indexing a non-slice") } + let el = slice_elem(base.ty) + g_addr_ty = el + # load the data pointer from the slice header (field 0) + let dp = nreg() + emit(" ") emit(dp) emit(" = getelementptr inbounds %LSlice, ptr ") + emit(base.code) emit(", i32 0, i32 0\n") + let data = nreg() + emit(" ") emit(data) emit(" = load ptr, ptr ") emit(dp) emit("\n") + let ix = emit_expr(e.b) + let r = nreg() + emit(" ") emit(r) emit(" = getelementptr inbounds ") emit(llty(el)) + emit(", ptr ") emit(data) emit(", i32 ") emit(ix.code) emit("\n") + return r +} diff --git a/selfhost/emit_core.ludic b/selfhost/emit_core.ludic new file mode 100644 index 00000000..dbdcf2c1 --- /dev/null +++ b/selfhost/emit_core.ludic @@ -0,0 +1,139 @@ +# emit_core.ludic — emitter state, type mapping, struct/slice helpers, and the +# module header. Mirrors the pieces of compiler/back/ that this subset needs. +# structs and slices are references, so every non-scalar type lowers to `ptr`. + +struct Val { code: ptr = ptr_null(), ty: ptr = ptr_null() } +fn val(code: ptr, ty: ptr) -> Val { let v = new Val v.code = code v.ty = ty return v } + +var head: Buf # module-level: types, globals, string constants +var code: Buf # function bodies +var falloc: Buf # entry-block allocas for the current function +var ll_t: int = 0 # temp register counter (reset per function) +var ll_lbl: int = 0 # label counter +var ll_str: int = 0 # string-constant counter + +# local environment (parallel slices), reset per function +var loc_name: []ptr +var loc_reg: []ptr +var loc_ty: []ptr +var nloc: int = 0 + +# loop targets for break/continue (innermost last) +var brk_lbl: []ptr +var cnt_lbl: []ptr +var nloop: int = 0 + +var ret_ty: ptr # current function's return type +var g_term: bool = false # did the current block end in a terminator? +var self_stk: []ptr # entity-index slot (ip) per enclosing query, for self() +var nself: int = 0 +var mach_stk: []Node # enclosing `machine` nodes, so `become` finds its register +var nmach: int = 0 + +fn emit(s: ptr) -> void { buf_puts(code, s) } +fn emith(s: ptr) -> void { buf_puts(head, s) } + +# stack slots MUST live in the entry block (an alloca in a loop walks the stack +# off its end), so they go into a per-function buffer spliced in at entry. +fn emit_alloca(llt: ptr) -> ptr { + let r = sconcat("%t", itoa(ll_t)) ll_t = ll_t + 1 + buf_puts(falloc, " ") buf_puts(falloc, r) buf_puts(falloc, " = alloca ") buf_puts(falloc, llt) buf_puts(falloc, "\n") + return r +} + +# "%t" fresh register +fn sconcat(a: ptr, b: ptr) -> ptr { + let la = slen(a) let lb = slen(b) + let out = mem_alloc(la + lb + 1) + let i = 0 + while i < la { poke8(out, i, peek8(a, i)) i = i + 1 } + let j = 0 + while j < lb { poke8(out, la + j, peek8(b, j)) j = j + 1 } + poke8(out, la + lb, 0) + return out +} +fn nreg() -> ptr { let r = sconcat("%t", itoa(ll_t)) ll_t = ll_t + 1 return r } +fn lbl(pfx: ptr) -> ptr { let r = sconcat(pfx, itoa(ll_lbl)) ll_lbl = ll_lbl + 1 return r } + +# Ludic type -> LLVM type. int/bool are i32; everything else (ptr/str/struct/ +# slice) is a pointer; void is void. +fn llty(t: ptr) -> ptr { + if streq(t, "int") or streq(t, "bool") or streq(t, "fixed") { return "i32" } + if streq(t, "void") { return "void" } + return "ptr" +} + +fn is_slice_ty(t: ptr) -> bool { return peek8(t, 0) == 91 and peek8(t, 1) == 93 } # "[]" +fn slice_elem(t: ptr) -> ptr { return substr(t, 2, slen(t) - 2) } + +fn find_struct(name: ptr) -> Node { + let i = 0 + while i < len(prog) { + let d = prog[i] + if d.kind == N_STRUCT and streq(d.s, name) { return d } + i = i + 1 + } + return ptr_null() +} +fn is_struct_ty(t: ptr) -> bool { return not ptr_is_null(find_struct(t)) } + +fn find_arch(name: ptr) -> Node { + let i = 0 + while i < len(prog) { let d = prog[i] if d.kind == N_ARCH and streq(d.s, name) { return d } i = i + 1 } + return ptr_null() +} +fn find_comp(name: ptr) -> Node { + let i = 0 + while i < len(prog) { let d = prog[i] if d.kind == N_COMP and streq(d.s, name) { return d } i = i + 1 } + return ptr_null() +} +# a struct or a component — both have %Str_/%Cmp_ layouts with named fields +fn layout_node(name: ptr) -> Node { + let s = find_struct(name) if not ptr_is_null(s) { return s } + return find_comp(name) +} +fn layout_ty(name: ptr) -> ptr { + if not ptr_is_null(find_struct(name)) { return sconcat("%Str_", name) } + return sconcat("%Cmp_", name) +} + +fn field_index(s: Node, fname: ptr) -> int { + let i = 0 + while i < len(s.kids) { if streq(s.kids[i].s, fname) { return i } i = i + 1 } + return 0 - 1 +} +fn field_type(s: Node, fname: ptr) -> ptr { + let i = 0 + while i < len(s.kids) { if streq(s.kids[i].s, fname) { return s.kids[i].ty } i = i + 1 } + return "int" +} + +# find a global var/const by name +fn find_global(name: ptr) -> Node { + let i = 0 + while i < len(prog) { + let d = prog[i] + if d.kind == N_VAR and streq(d.s, name) { return d } + if d.kind == N_CONST and streq(d.s, name) { return d } + i = i + 1 + } + return ptr_null() +} +fn find_fn(name: ptr) -> Node { + let i = 0 + while i < len(prog) { let d = prog[i] if d.kind == N_FN and streq(d.s, name) { return d } i = i + 1 } + return ptr_null() +} + +# local variable environment +fn loc_reset() -> void { nloc = 0 } +fn loc_push(name: ptr, r: ptr, ty: ptr) -> void { + if nloc < len(loc_name) { loc_name[nloc] = name loc_reg[nloc] = r loc_ty[nloc] = ty } + else { push(loc_name, name) push(loc_reg, r) push(loc_ty, ty) } + nloc = nloc + 1 +} +fn loc_find(name: ptr) -> int { + let i = nloc - 1 + while i >= 0 { if streq(loc_name[i], name) { return i } i = i - 1 } + return 0 - 1 +} diff --git a/selfhost/emit_decl.ludic b/selfhost/emit_decl.ludic new file mode 100644 index 00000000..62175705 --- /dev/null +++ b/selfhost/emit_decl.ludic @@ -0,0 +1,104 @@ +# emit_decl.ludic — functions, main, and the whole-program driver. A function's +# body is built into a scratch buffer so entry-block allocas can be spliced in +# ahead of it (see emit_alloca). Returns go through a %retval slot + `ret` label. + +fn emit_params_sig(d: Node) -> void { + let i = 0 + while i < len(d.kids) { + if i > 0 { emit(", ") } + emit(llty(d.kids[i].ty)) emit(" %arg_") emit(d.kids[i].s) + i = i + 1 + } +} + +fn emit_fn(d: Node) -> void { + ll_t = 0 ll_lbl = 0 g_term = false loc_reset() nloop = 0 + ret_ty = d.ty + let fbody = buf_new() + falloc = buf_new() + let saved = code + code = fbody + let rl = llty(ret_ty) + if not streq(rl, "void") { buf_puts(falloc, " %retval = alloca ") buf_puts(falloc, rl) buf_puts(falloc, "\n") } + # params: store each incoming argument into a stack slot + let i = 0 + while i < len(d.kids) { + let p = d.kids[i] + let slot = emit_alloca(llty(p.ty)) + emit(" store ") emit(llty(p.ty)) emit(" %arg_") emit(p.s) emit(", ptr ") emit(slot) emit("\n") + loc_push(p.s, slot, p.ty) + i = i + 1 + } + emit_block(d.a) + if not g_term { emit(" br label %ret\n") } + emit("ret:\n") + if streq(rl, "void") { emit(" ret void\n") } + else { let r = emit_bind(sconcat("load ", sconcat(rl, ", ptr %retval"))) emit(" ret ") emit(rl) emit(" ") emit(r) emit("\n") } + code = saved + emit("define ") emit(rl) emit(" @fn_") emit(d.s) emit("(") emit_params_sig(d) emit(") {\nentry:\n") + emit(buf_str(falloc)) + emit(buf_str(fbody)) + emit("}\n\n") +} + +fn emit_main(d: Node) -> void { + ll_t = 0 ll_lbl = 0 g_term = false loc_reset() nloop = 0 + ret_ty = "int" + let fbody = buf_new() + falloc = buf_new() + let saved = code + code = fbody + buf_puts(falloc, " %retval = alloca i32\n") + emit(" store i32 %argc, ptr @L_argc\n") + emit(" store ptr %argv, ptr @L_argv\n") + emit(" store i32 0, ptr %retval\n") + emit_block(d.a) + if not g_term { emit(" br label %ret\n") } + emit("ret:\n") + let r = emit_bind("load i32, ptr %retval") + emit(" ret i32 ") emit(r) emit("\n") + code = saved + emit("define i32 @main(i32 %argc, ptr %argv) {\nentry:\n") + emit(buf_str(falloc)) + emit(buf_str(fbody)) + emit("}\n") +} + +fn emit_program() -> void { + head = buf_new() + code = buf_new() + loc_name = new []ptr loc_reg = new []ptr loc_ty = new []ptr + brk_lbl = new []ptr cnt_lbl = new []ptr + self_stk = new []ptr + mach_stk = new []Node + emit_header() + if has_ecs() { emit_ecs_storage() } + let i = 0 + while i < len(prog) { if prog[i].kind == N_FN { emit_fn(prog[i]) } i = i + 1 } + if has_ecs() { emit_ecs_allocator() emit_snapshot() } + if has_ui() { emit_ui_build() } + if has_systems() { emit_game_main() } + else { + i = 0 + while i < len(prog) { if prog[i].kind == N_MAIN { emit_main(prog[i]) } i = i + 1 } + } +} + +# Flush the emitted IR. With a null path it goes to stdout (the pipe the shell +# drivers read); with a path it is written to that file so ludicc can hand it to +# clang itself. +fn ir_flush(path: ptr) -> bool { + let h = buf_str(head) + let c = buf_str(code) + if ptr_is_null(path) { + print_str(h) + print_str(c) + return true + } + let f = file_open(path, "wb") + if ptr_is_null(f) { return false } + file_write(f, h, slen(h)) + file_write(f, c, slen(c)) + file_close(f) + return true +} diff --git a/selfhost/emit_ecs.ludic b/selfhost/emit_ecs.ludic new file mode 100644 index 00000000..720ab12d --- /dev/null +++ b/selfhost/emit_ecs.ludic @@ -0,0 +1,92 @@ +# emit_ecs.ludic — ECS storage and the entity allocator. For each component: +# a %Cmp_ layout, a dense @S_ store, and an @H_ "has this component" array. +# Entities are integer handles; L_alloc reuses freed slots. Mirrors the ECS +# parts of compiler/back/ir_decl.c. + +const MAX_ENT: int = 1024 + +fn has_ecs() -> bool { + let i = 0 + while i < len(prog) { let k = prog[i].kind if k == N_COMP or k == N_SYS { return true } i = i + 1 } + return false +} +fn has_systems() -> bool { + let i = 0 + while i < len(prog) { if prog[i].kind == N_SYS { return true } i = i + 1 } + return false +} + +fn emit_ecs_storage() -> void { + emith("@L_running = internal global i32 1\n") + emith("@L_key = internal global i32 0\n") + emith("@L_entc = internal global i32 0\n") + let me = itoa(MAX_ENT) + emith(sconcat("@L_alive = internal global [", sconcat(me, " x i32] zeroinitializer\n"))) + emith(sconcat("@L_kind = internal global [", sconcat(me, " x i32] zeroinitializer\n"))) + emith(sconcat("@L_freelist = internal global [", sconcat(me, " x i32] zeroinitializer\n"))) + emith("@L_freen = internal global i32 0\n") + let i = 0 + while i < len(prog) { + let c = prog[i] + if c.kind == N_COMP { + emith(sconcat("%Cmp_", sconcat(c.s, " = type { "))) + if len(c.kids) == 0 { emith("i32") } + let f = 0 + while f < len(c.kids) { if f > 0 { emith(", ") } emith(llty(c.kids[f].ty)) f = f + 1 } + emith(" }\n") + emith(sconcat("@S_", sconcat(c.s, sconcat(" = internal global [", sconcat(me, sconcat(" x %Cmp_", sconcat(c.s, "] zeroinitializer\n"))))))) + emith(sconcat("@H_", sconcat(c.s, sconcat(" = internal global [", sconcat(me, " x i8] zeroinitializer\n"))))) + } + i = i + 1 + } +} + +# L_reset(e): clear every has-flag and the archetype kind for entity e +fn emit_ecs_allocator() -> void { + let me = itoa(MAX_ENT) + emit("define void @L_reset(i32 %e) {\nentry:\n") + let i = 0 + while i < len(prog) { + if prog[i].kind == N_COMP { + let hn = sconcat("%h", itoa(i)) + emit(" ") emit(hn) emit(" = getelementptr inbounds [") emit(me) emit(" x i8], ptr @H_") emit(prog[i].s) emit(", i32 0, i32 %e\n") + emit(" store i8 0, ptr ") emit(hn) emit("\n") + } + i = i + 1 + } + emit(" %k = getelementptr inbounds [") emit(me) emit(" x i32], ptr @L_kind, i32 0, i32 %e\n") + emit(" store i32 0, ptr %k\n ret void\n}\n\n") + + emit("define i32 @L_alloc() {\nentry:\n") + emit(" %fn = load i32, ptr @L_freen\n") + emit(" %has = icmp sgt i32 %fn, 0\n") + emit(" br i1 %has, label %reuse, label %fresh\n") + emit("reuse:\n") + emit(" %fn1 = sub i32 %fn, 1\n") + emit(" store i32 %fn1, ptr @L_freen\n") + emit(" %fp = getelementptr inbounds [") emit(me) emit(" x i32], ptr @L_freelist, i32 0, i32 %fn1\n") + emit(" %re = load i32, ptr %fp\n") + emit(" br label %done\n") + emit("fresh:\n") + emit(" %ec = load i32, ptr @L_entc\n") + emit(" %ec1 = add i32 %ec, 1\n") + emit(" store i32 %ec1, ptr @L_entc\n") + emit(" br label %done\n") + emit("done:\n") + emit(" %e = phi i32 [ %re, %reuse ], [ %ec, %fresh ]\n") + emit(" call void @L_reset(i32 %e)\n") + emit(" %ap = getelementptr inbounds [") emit(me) emit(" x i32], ptr @L_alive, i32 0, i32 %e\n") + emit(" store i32 1, ptr %ap\n") + emit(" ret i32 %e\n}\n\n") + + emit("define void @L_free_entity(i32 %e) {\nentry:\n") + emit(" %ap = getelementptr inbounds [") emit(me) emit(" x i32], ptr @L_alive, i32 0, i32 %e\n") + emit(" store i32 0, ptr %ap\n") + emit(" call void @L_reset(i32 %e)\n") + emit(" %fn = load i32, ptr @L_freen\n") + emit(" %fp = getelementptr inbounds [") emit(me) emit(" x i32], ptr @L_freelist, i32 0, i32 %fn\n") + emit(" store i32 %e, ptr %fp\n") + emit(" %fn1 = add i32 %fn, 1\n") + emit(" store i32 %fn1, ptr @L_freen\n") + emit(" ret void\n}\n\n") +} diff --git a/selfhost/emit_expr.ludic b/selfhost/emit_expr.ludic new file mode 100644 index 00000000..331abc86 --- /dev/null +++ b/selfhost/emit_expr.ludic @@ -0,0 +1,168 @@ +# emit_expr.ludic — lower an expression to IR, returning its register and type. + +fn emit_load_at(addr: ptr, ty: ptr) -> Val { + let r = emit_bind(sconcat("load ", sconcat(llty(ty), sconcat(", ptr ", addr)))) + return val(r, ty) +} + +# short-circuit `and`/`or`: seed a slot with (left!=0), branch to decide whether +# to overwrite with (right!=0). +fn emit_logic(e: Node) -> Val { + let slot = emit_alloca("i32") + let la = emit_expr(e.a) + let lc = emit_bind(sconcat("icmp ne i32 ", sconcat(la.code, ", 0"))) + let lz = emit_bind(sconcat("zext i1 ", sconcat(lc, " to i32"))) + emit(" store i32 ") emit(lz) emit(", ptr ") emit(slot) emit("\n") + let ev = lbl("sc") let done = lbl("scend") + if streq(e.s, "and") { emit(" br i1 ") emit(lc) emit(", label %") emit(ev) emit(", label %") emit(done) emit("\n") } + else { emit(" br i1 ") emit(lc) emit(", label %") emit(done) emit(", label %") emit(ev) emit("\n") } + emit(ev) emit(":\n") + let rb = emit_expr(e.b) + let rc = emit_bind(sconcat("icmp ne i32 ", sconcat(rb.code, ", 0"))) + let rz = emit_bind(sconcat("zext i1 ", sconcat(rc, " to i32"))) + emit(" store i32 ") emit(rz) emit(", ptr ") emit(slot) emit("\n") + emit(" br label %") emit(done) emit("\n") + emit(done) emit(":\n") + return val(emit_bind(sconcat("load i32, ptr ", slot)), "bool") +} + +fn cmp_code(op: ptr) -> ptr { + if streq(op, "<") { return "slt" } + if streq(op, "<=") { return "sle" } + if streq(op, ">") { return "sgt" } + if streq(op, ">=") { return "sge" } + if streq(op, "==") { return "eq" } + return "ne" +} +fn is_cmp(op: ptr) -> bool { + return streq(op,"<") or streq(op,"<=") or streq(op,">") or streq(op,">=") or streq(op,"==") or streq(op,"!=") +} +fn arith_code(op: ptr) -> ptr { + if streq(op, "+") { return "add" } + if streq(op, "-") { return "sub" } + if streq(op, "*") { return "mul" } + if streq(op, "/") { return "sdiv" } + return "srem" +} + +# widen an int value to Q16.16 by shifting left 16 (a fixed value passes through) +fn to_fixed(v: Val) -> ptr { + if streq(v.ty, "fixed") { return v.code } + return emit_bind(sconcat("shl i32 ", sconcat(v.code, ", 16"))) +} + +fn emit_bin(e: Node) -> Val { + if streq(e.s, "and") or streq(e.s, "or") { return emit_logic(e) } + let a = emit_expr(e.a) + let b = emit_expr(e.b) + let fx = streq(a.ty, "fixed") or streq(b.ty, "fixed") + if is_cmp(e.s) { + let ac = a.code let bc = b.code + if fx { ac = to_fixed(a) bc = to_fixed(b) } + let c = emit_bind(sconcat("icmp ", sconcat(cmp_code(e.s), sconcat(" i32 ", sconcat(ac, sconcat(", ", bc)))))) + return val(emit_bind(sconcat("zext i1 ", sconcat(c, " to i32"))), "bool") + } + if fx { + let af = to_fixed(a) let bf = to_fixed(b) + if streq(e.s, "*") { + let a64 = emit_bind(sconcat("sext i32 ", sconcat(af, " to i64"))) + let b64 = emit_bind(sconcat("sext i32 ", sconcat(bf, " to i64"))) + let m = emit_bind(sconcat("mul i64 ", sconcat(a64, sconcat(", ", b64)))) + let sh = emit_bind(sconcat("ashr i64 ", sconcat(m, ", 16"))) + return val(emit_bind(sconcat("trunc i64 ", sconcat(sh, " to i32"))), "fixed") + } + if streq(e.s, "/") { + let a64 = emit_bind(sconcat("sext i32 ", sconcat(af, " to i64"))) + let ash = emit_bind(sconcat("shl i64 ", sconcat(a64, ", 16"))) + let b64 = emit_bind(sconcat("sext i32 ", sconcat(bf, " to i64"))) + let dv = emit_bind(sconcat("sdiv i64 ", sconcat(ash, sconcat(", ", b64)))) + return val(emit_bind(sconcat("trunc i64 ", sconcat(dv, " to i32"))), "fixed") + } + let r = emit_bind(sconcat(arith_code(e.s), sconcat(" i32 ", sconcat(af, sconcat(", ", bf))))) + return val(r, "fixed") + } + let r = emit_bind(sconcat(arith_code(e.s), sconcat(" i32 ", sconcat(a.code, sconcat(", ", b.code))))) + return val(r, "int") +} + +fn emit_call(e: Node) -> Val { + let name = e.a.s + if streq(name, "self") { if nself == 0 { return val("0", "entity") } return val(emit_bind(sconcat("load i32, ptr ", self_stk[nself - 1])), "entity") } + if streq(name, "key") { return val(emit_bind("load i32, ptr @L_key"), "int") } + if streq(name, "save") { emit(" call void @L_save()\n") return val("0", "void") } + if streq(name, "ui_build") { emit(" call void @ui_build()\n") return val("0", "void") } + if streq(name, "load") { return val(emit_bind("call i32 @L_load()"), "bool") } + if streq(name, "quit") { emit(" store i32 0, ptr @L_running\n") return val("0", "void") } + if streq(name, "len") { return emit_len(e) } + if streq(name, "push") { return emit_push(e) } + if streq(name, "fx") { let a = emit_expr(e.kids[0]) return val(emit_bind(sconcat("shl i32 ", sconcat(a.code, ", 16"))), "fixed") } + if streq(name, "flr") { let a = emit_expr(e.kids[0]) return val(emit_bind(sconcat("ashr i32 ", sconcat(a.code, ", 16"))), "int") } + if is_intrinsic(name) { return emit_intrinsic(name, e) } + if is_intrinsic2(name) { return emit_intrinsic2(name, e) } + if is_math_builtin(name) { return emit_math_builtin(name, e) } + let fn2 = find_fn(name) + let cname = name + if ptr_is_null(fn2) { + # a builtin like clear()/reg() is satisfied by its rt_ function + let rtname = sconcat("rt_", name) + fn2 = find_fn(rtname) + if ptr_is_null(fn2) { perr(sconcat("unknown function ", name)) } + cname = rtname + } + # evaluate args first (their IR is emitted before the call instruction) + let args = new []ptr + let atys = new []ptr + let i = 0 + while i < len(e.kids) { let v = emit_expr(e.kids[i]) push(args, v.code) push(atys, v.ty) i = i + 1 } + let rl = llty(fn2.ty) + emit(" ") + let rreg = "0" + if not streq(rl, "void") { rreg = nreg() emit(rreg) emit(" = ") } + emit("call ") emit(rl) emit(" @fn_") emit(cname) emit("(") + i = 0 + while i < len(args) { + if i > 0 { emit(", ") } + emit(llty(atys[i])) emit(" ") emit(args[i]) + i = i + 1 + } + emit(") +") + return val(rreg, fn2.ty) +} + +fn emit_expr(e: Node) -> Val { + if ptr_is_null(e) { return val("0", "int") } + if e.kind == E_INT { return val(itoa(e.ival), "int") } + if e.kind == E_FLOAT { return val(itoa(e.ival), "fixed") } + if e.kind == E_BOOL { return val(itoa(e.ival), "bool") } + if e.kind == E_STR { return val(emit_str_const(e.s), "str") } + if e.kind == E_NEW { + if is_slice_ty(e.s) { return emit_new_slice(e.s) } + return emit_new_struct(e.s) + } + if e.kind == E_ID { + let li = loc_find(e.s) + if li >= 0 { return emit_load_at(loc_reg[li], loc_ty[li]) } + let g = find_global(e.s) + if not ptr_is_null(g) { + if g.kind == N_CONST { return val(itoa(g.a.ival), "int") } + let r = emit_bind(sconcat("load ", sconcat(llty(g.ty), sconcat(", ptr @g_", e.s)))) + return val(r, g.ty) + } + # a UI_ that is not a const/var resolves to its widget index + if is_ui_ident(e.s) { return val(itoa(ui_index_of(e.s)), "int") } + perr(sconcat("unknown identifier ", e.s)) + } + if e.kind == E_MEMBER { let a = emit_member_addr(e) return emit_load_at(a, g_addr_ty) } + if e.kind == E_INDEX { let a = emit_index_addr(e) return emit_load_at(a, g_addr_ty) } + if e.kind == E_CALL { return emit_call(e) } + if e.kind == E_BIN { return emit_bin(e) } + if e.kind == E_UN { + let a = emit_expr(e.a) + if streq(e.s, "-") { return val(emit_bind(sconcat("sub i32 0, ", a.code)), "int") } + let c = emit_bind(sconcat("icmp eq i32 ", sconcat(a.code, ", 0"))) + return val(emit_bind(sconcat("zext i1 ", sconcat(c, " to i32"))), "bool") + } + perr("cannot emit expression") + return val("0", "int") +} diff --git a/selfhost/emit_game.ludic b/selfhost/emit_game.ludic new file mode 100644 index 00000000..15fed507 --- /dev/null +++ b/selfhost/emit_game.ludic @@ -0,0 +1,68 @@ +# emit_game.ludic — system functions and the frame loop. A system compiles to a +# void function; main() boots (Start systems), then runs the per-frame phases in +# order until the game stops. Runtime hooks (rt_init/poll/running/shutdown) are +# called only when the runtime defines them. + +fn emit_system_fn(sys: Node) -> void { + ll_t = 0 ll_lbl = 0 g_term = false loc_reset() nloop = 0 nself = 0 + ret_ty = "void" + let fbody = buf_new() + falloc = buf_new() + let saved = code + code = fbody + emit_block(sys.a) + if not g_term { emit(" br label %ret\n") } + emit("ret:\n ret void\n") + code = saved + emit("define void @sys_") emit(sys.s) emit("() {\nentry:\n") + emit(buf_str(falloc)) + emit(buf_str(fbody)) + emit("}\n\n") +} + +fn emit_calls_for_phase(phase: ptr) -> void { + let i = 0 + while i < len(prog) { + let d = prog[i] + if d.kind == N_SYS and streq(d.ty, phase) { emit(" call void @sys_") emit(d.s) emit("()\n") } + i = i + 1 + } +} + +fn emit_game_main() -> void { + # every system becomes a function first + let i = 0 + while i < len(prog) { if prog[i].kind == N_SYS { emit_system_fn(prog[i]) } i = i + 1 } + + emit("define i32 @main(i32 %argc, ptr %argv) {\nentry:\n") + emit(" store i32 %argc, ptr @L_argc\n") + emit(" store ptr %argv, ptr @L_argv\n") + if not ptr_is_null(find_fn("rt_init")) { emit(" call void @fn_rt_init()\n") } + emit_calls_for_phase("Start") + emit(" br label %loop\n") + emit("loop:\n") + let r = emit_bind("load i32, ptr @L_running") + let rc = emit_bind(sconcat("icmp ne i32 ", sconcat(r, ", 0"))) + if not ptr_is_null(find_fn("rt_running")) { + let pr = emit_bind("call i32 @fn_rt_running()") + let pc = emit_bind(sconcat("icmp ne i32 ", sconcat(pr, ", 0"))) + let go = emit_bind(sconcat("and i1 ", sconcat(rc, sconcat(", ", pc)))) + emit(" br i1 ") emit(go) emit(", label %body, label %done\n") + } else { + emit(" br i1 ") emit(rc) emit(", label %body, label %done\n") + } + emit("body:\n") + if not ptr_is_null(find_fn("rt_poll")) { + let k = emit_bind("call i32 @fn_rt_poll()") + emit(" store i32 ") emit(k) emit(", ptr @L_key\n") + } + emit_calls_for_phase("Input") + emit_calls_for_phase("FixedUpdate") + emit_calls_for_phase("Update") + emit_calls_for_phase("LateUpdate") + emit_calls_for_phase("Render") + emit(" br label %loop\n") + emit("done:\n") + if not ptr_is_null(find_fn("rt_shutdown")) { emit(" call void @fn_rt_shutdown()\n") } + emit(" ret i32 0\n}\n") +} diff --git a/selfhost/emit_head.ludic b/selfhost/emit_head.ludic new file mode 100644 index 00000000..0d33c28d --- /dev/null +++ b/selfhost/emit_head.ludic @@ -0,0 +1,108 @@ +# emit_head.ludic — string constants and the module header (libc declarations, +# the slice header type, struct layouts, globals, argv, format strings). + +fn hexdig(n: int) -> int { if n < 10 { return 48 + n } return 55 + n } # 0-9 A-F + +# emit `@.strN = ... c"escaped\00"` and return its name; % and non-print -> \XX +fn emit_str_const(s: ptr) -> ptr { + let name = sconcat("@.str", itoa(ll_str)) + ll_str = ll_str + 1 + let n = slen(s) + emith(name) emith(" = private unnamed_addr constant [") + emith(itoa(n + 1)) emith(" x i8] c\"") + let i = 0 + while i < n { + let c = peek8(s, i) + if c == 34 or c == 92 or c < 32 or c > 126 { + buf_putc(head, 92) # backslash + buf_putc(head, hexdig(c / 16)) + buf_putc(head, hexdig(c % 16)) + } else { buf_putc(head, c) } + i = i + 1 + } + emith("\\00\"\n") + return name +} + +# a fresh SSA register bound to a `getelementptr`, returned as its name +fn emit_gep_i8(base: ptr, idx: ptr) -> ptr { + let r = nreg() + emit(" ") emit(r) emit(" = getelementptr inbounds i8, ptr ") + emit(base) emit(", i32 ") emit(idx) emit("\n") + return r +} + +# the constant initializer for a global var: a literal, or 0/null +fn global_init(d: Node) -> ptr { + if ptr_is_null(d.a) { if streq(llty(d.ty), "ptr") { return "null" } return "0" } + let e = d.a + if e.kind == E_INT or e.kind == E_FLOAT or e.kind == E_BOOL { return itoa(e.ival) } + if e.kind == E_UN and streq(e.s, "-") and e.a.kind == E_INT { return sconcat("-", itoa(e.a.ival)) } + if streq(llty(d.ty), "ptr") { return "null" } + return "0" +} + +fn emit_header() -> void { + emith("; Ludic (self-hosted) -> LLVM IR\n") + emith("declare i32 @printf(ptr, ...)\n") + emith("declare ptr @malloc(i64)\n") + emith("declare ptr @realloc(ptr, i64)\n") + emith("declare void @free(ptr)\n") + emith("declare ptr @fopen(ptr, ptr)\n") + emith("declare i64 @fread(ptr, i64, i64, ptr)\n") + emith("declare i64 @fwrite(ptr, i64, i64, ptr)\n") + emith("declare i32 @fseek(ptr, i64, i32)\n") + emith("declare i64 @ftell(ptr)\n") + emith("declare i32 @fclose(ptr)\n") + emith("declare void @exit(i32)\n") + emith("declare i32 @system(ptr)\n") + emith("declare ptr @getenv(ptr)\n") + emith("declare ptr @memcpy(ptr, ptr, i64)\n") + emith("declare ptr @memset(ptr, i32, i64)\n") + emith("declare i64 @strlen(ptr)\n") + emith("declare i32 @getchar()\n") + emith("declare i32 @putchar(i32)\n") + emith("declare i64 @time(ptr)\n") + emith("declare void @win_open(i32, i32, i32, ptr)\n") + emith("declare i32 @win_poll()\n") + emith("declare void @win_present(ptr, i32, i32)\n") + emith("declare i32 @win_running()\n") + emith("declare void @win_close()\n") + emith("@__stderrp = external global ptr\n") + emith("@.fmt_str = private unnamed_addr constant [3 x i8] c\"%s\\00\"\n") + emith("@.fmt_int = private unnamed_addr constant [4 x i8] c\"%d\\0A\\00\"\n") + emith("@L_argc = internal global i32 0\n") + emith("@L_argv = internal global ptr null\n") + emith("@.gametitle = private unnamed_addr constant [") + emith(itoa(slen(g_game_name) + 1)) emith(" x i8] c\"") emith(g_game_name) emith("\\00\"\n") + emith("%LSlice = type { ptr, i32, i32 }\n") + # struct layouts + let i = 0 + while i < len(prog) { + let d = prog[i] + if d.kind == N_STRUCT { + emith("%Str_") emith(d.s) emith(" = type { ") + if len(d.kids) == 0 { emith("i32") } + let f = 0 + while f < len(d.kids) { + if f > 0 { emith(", ") } + emith(llty(d.kids[f].ty)) + f = f + 1 + } + emith(" }\n") + } + i = i + 1 + } + # globals (vars) — aggregates/pointers default to null, scalars to 0 + i = 0 + while i < len(prog) { + let d = prog[i] + if d.kind == N_VAR { + emith("@g_") emith(d.s) emith(" = internal global ") + emith(llty(d.ty)) emith(" ") + emith(global_init(d)) + emith("\n") + } + i = i + 1 + } +} diff --git a/selfhost/emit_intrin.ludic b/selfhost/emit_intrin.ludic new file mode 100644 index 00000000..13e530eb --- /dev/null +++ b/selfhost/emit_intrin.ludic @@ -0,0 +1,142 @@ +# emit_intrin.ludic — the low-level intrinsics the self-host source uses, each +# lowered to the same libc/inline IR the C backend emits. Returns a Val via +# g_intrin_val and sets g_intrin_ok when `name` was an intrinsic. + +var g_intrin_ok: bool = false + +# is `name` a low-level intrinsic? A pure name check, so it can gate dispatch +# without evaluating arguments (which could clobber shared state). +fn is_intrinsic(name: ptr) -> bool { + if streq(name,"ptr_null") or streq(name,"mem_alloc") or streq(name,"mem_realloc") { return true } + if streq(name,"peek8") or streq(name,"poke8") or streq(name,"ptr_is_null") { return true } + if streq(name,"file_open") or streq(name,"file_read") or streq(name,"file_write") { return true } + if streq(name,"file_seek") or streq(name,"file_tell") or streq(name,"file_close") { return true } + if streq(name,"print_str") or streq(name,"print_int") { return true } + if streq(name,"os_argc") or streq(name,"os_arg") or streq(name,"os_exit") or streq(name,"file_stderr") { return true } + if streq(name,"os_system") or streq(name,"os_getenv") { return true } + if streq(name,"shl") or streq(name,"shr") or streq(name,"band") or streq(name,"bor") or streq(name,"bxor") or streq(name,"bnot") { return true } + if streq(name,"peek32") or streq(name,"poke32") { return true } + return false +} +# emit " = \n" and return r +fn emit_bind(rest: ptr) -> ptr { let r = nreg() emit(" ") emit(r) emit(" = ") emit(rest) emit("\n") return r } + +fn arg_code(e: Node, i: int) -> ptr { let v = emit_expr(e.kids[i]) return v.code } + +fn emit_intrinsic(name: ptr, e: Node) -> Val { + g_intrin_ok = true + if streq(name, "ptr_null") { return val("null", "ptr") } + if streq(name, "mem_alloc") { + let n = arg_code(e, 0) + let w = emit_bind(sconcat("zext i32 ", sconcat(n, " to i64"))) + return val(emit_bind(sconcat("call ptr @malloc(i64 ", sconcat(w, ")"))), "ptr") + } + if streq(name, "mem_realloc") { + let p = arg_code(e, 0) let n = arg_code(e, 1) + let w = emit_bind(sconcat("zext i32 ", sconcat(n, " to i64"))) + return val(emit_bind(sconcat("call ptr @realloc(ptr ", sconcat(p, sconcat(", i64 ", sconcat(w, ")"))))), "ptr") + } + if streq(name, "peek8") { + let p = arg_code(e, 0) let i = arg_code(e, 1) + let a = emit_gep_i8(p, i) + let b = emit_bind(sconcat("load i8, ptr ", a)) + return val(emit_bind(sconcat("zext i8 ", sconcat(b, " to i32"))), "int") + } + if streq(name, "poke8") { + let p = arg_code(e, 0) let i = arg_code(e, 1) let v = arg_code(e, 2) + let a = emit_gep_i8(p, i) + let t = emit_bind(sconcat("trunc i32 ", sconcat(v, " to i8"))) + emit(" store i8 ") emit(t) emit(", ptr ") emit(a) emit("\n") + return val("0", "void") + } + if streq(name, "ptr_is_null") { + let p = arg_code(e, 0) + let c = emit_bind(sconcat("icmp eq ptr ", sconcat(p, ", null"))) + return val(emit_bind(sconcat("zext i1 ", sconcat(c, " to i32"))), "bool") + } + if streq(name, "file_open") { + let p = arg_code(e, 0) let m = arg_code(e, 1) + return val(emit_bind(sconcat("call ptr @fopen(ptr ", sconcat(p, sconcat(", ptr ", sconcat(m, ")"))))), "ptr") + } + if streq(name, "file_read") or streq(name, "file_write") { + let f = arg_code(e, 0) let b = arg_code(e, 1) let n = arg_code(e, 2) + let w = emit_bind(sconcat("zext i32 ", sconcat(n, " to i64"))) + let fn2 = "@fread" + if streq(name, "file_write") { fn2 = "@fwrite" } + let r = emit_bind(sconcat("call i64 ", sconcat(fn2, sconcat("(ptr ", sconcat(b, sconcat(", i64 1, i64 ", sconcat(w, sconcat(", ptr ", sconcat(f, ")"))))))))) + return val(emit_bind(sconcat("trunc i64 ", sconcat(r, " to i32"))), "int") + } + if streq(name, "file_seek") { + let f = arg_code(e, 0) let off = arg_code(e, 1) let wh = arg_code(e, 2) + let o = emit_bind(sconcat("sext i32 ", sconcat(off, " to i64"))) + return val(emit_bind(sconcat("call i32 @fseek(ptr ", sconcat(f, sconcat(", i64 ", sconcat(o, sconcat(", i32 ", sconcat(wh, ")"))))))), "int") + } + if streq(name, "file_tell") { + let f = arg_code(e, 0) + let r = emit_bind(sconcat("call i64 @ftell(ptr ", sconcat(f, ")"))) + return val(emit_bind(sconcat("trunc i64 ", sconcat(r, " to i32"))), "int") + } + if streq(name, "file_close") { + let f = arg_code(e, 0) + emit(" call i32 @fclose(ptr ") emit(f) emit(")\n") + return val("0", "void") + } + if streq(name, "print_str") { + let s = arg_code(e, 0) + emit(" call i32 (ptr, ...) @printf(ptr @.fmt_str, ptr ") emit(s) emit(")\n") + return val("0", "void") + } + if streq(name, "print_int") { + let n = arg_code(e, 0) + emit(" call i32 (ptr, ...) @printf(ptr @.fmt_int, i32 ") emit(n) emit(")\n") + return val("0", "void") + } + if streq(name, "os_argc") { return val(emit_bind("load i32, ptr @L_argc"), "int") } + if streq(name, "os_arg") { + let i = arg_code(e, 0) + let v = emit_bind("load ptr, ptr @L_argv") + let q = emit_bind(sconcat("getelementptr ptr, ptr ", sconcat(v, sconcat(", i32 ", i)))) + return val(emit_bind(sconcat("load ptr, ptr ", q)), "str") + } + if streq(name, "os_exit") { + let n = arg_code(e, 0) + emit(" call void @exit(i32 ") emit(n) emit(")\n") + emit(" unreachable\n") + g_term = true + return val("0", "void") + } + if streq(name, "file_stderr") { return val(emit_bind("load ptr, ptr @__stderrp"), "ptr") } + if streq(name, "os_system") { + let c = arg_code(e, 0) + return val(emit_bind(sconcat("call i32 @system(ptr ", sconcat(c, ")"))), "int") + } + if streq(name, "os_getenv") { + let n = arg_code(e, 0) + return val(emit_bind(sconcat("call ptr @getenv(ptr ", sconcat(n, ")"))), "str") + } + if streq(name, "bnot") { let a = arg_code(e, 0) return val(emit_bind(sconcat("xor i32 ", sconcat(a, ", -1"))), "int") } + if streq(name,"shl") or streq(name,"shr") or streq(name,"band") or streq(name,"bor") or streq(name,"bxor") { + let a = arg_code(e, 0) let b = arg_code(e, 1) + let opc = "shl" + if streq(name,"shr") { opc = "lshr" } + if streq(name,"band") { opc = "and" } + if streq(name,"bor") { opc = "or" } + if streq(name,"bxor") { opc = "xor" } + return val(emit_bind(sconcat(opc, sconcat(" i32 ", sconcat(a, sconcat(", ", b))))), "int") + } + if streq(name, "peek32") { + let p = arg_code(e, 0) let i = arg_code(e, 1) + let g = nreg() + emit(" ") emit(g) emit(" = getelementptr inbounds i32, ptr ") emit(p) emit(", i32 ") emit(i) emit("\n") + return val(emit_bind(sconcat("load i32, ptr ", g)), "int") + } + if streq(name, "poke32") { + let p = arg_code(e, 0) let i = arg_code(e, 1) let v = arg_code(e, 2) + let g = nreg() + emit(" ") emit(g) emit(" = getelementptr inbounds i32, ptr ") emit(p) emit(", i32 ") emit(i) emit("\n") + emit(" store i32 ") emit(v) emit(", ptr ") emit(g) emit("\n") + return val("0", "void") + } + g_intrin_ok = false + return val("0", "void") +} diff --git a/selfhost/emit_intrin2.ludic b/selfhost/emit_intrin2.ludic new file mode 100644 index 00000000..f1d6a636 --- /dev/null +++ b/selfhost/emit_intrin2.ludic @@ -0,0 +1,95 @@ +# emit_intrin2.ludic — the rest of the low-level intrinsics: raw memory, fixed +# memory access, pointer arithmetic, stdio, time, and the windowing hooks. +# Matches compiler/back/ir_intrin.c. Reached from emit_intrinsic's fall-through. + +var g_windowed: bool = false # headless by default (games read stdin / dump PPM) + +fn is_intrinsic2(name: ptr) -> bool { + if streq(name,"mem_free") or streq(name,"mem_copy") or streq(name,"mem_set") { return true } + if streq(name,"ptr_add") or streq(name,"read_byte") or streq(name,"write_byte") { return true } + if streq(name,"str_len") or streq(name,"os_time") { return true } + if streq(name,"peekf") or streq(name,"pokef") or streq(name,"as_fixed") or streq(name,"as_int") { return true } + if streq(name,"peekp") or streq(name,"pokep") { return true } + if streq(name,"is_windowed") or streq(name,"game_title") { return true } + if streq(name,"win_open") or streq(name,"win_poll") or streq(name,"win_present") { return true } + if streq(name,"win_running") or streq(name,"win_close") { return true } + return false +} + +fn emit_intrinsic2(name: ptr, e: Node) -> Val { + if streq(name, "mem_free") { + let p = arg_code(e, 0) emit(" call void @free(ptr ") emit(p) emit(")\n") return val("0", "void") + } + if streq(name, "mem_copy") { + let d = arg_code(e, 0) let s = arg_code(e, 1) let n = arg_code(e, 2) + let w = emit_bind(sconcat("zext i32 ", sconcat(n, " to i64"))) + emit(" call ptr @memcpy(ptr ") emit(d) emit(", ptr ") emit(s) emit(", i64 ") emit(w) emit(")\n") + return val("0", "void") + } + if streq(name, "mem_set") { + let p = arg_code(e, 0) let v = arg_code(e, 1) let n = arg_code(e, 2) + let w = emit_bind(sconcat("zext i32 ", sconcat(n, " to i64"))) + emit(" call ptr @memset(ptr ") emit(p) emit(", i32 ") emit(v) emit(", i64 ") emit(w) emit(")\n") + return val("0", "void") + } + if streq(name, "ptr_add") { + let p = arg_code(e, 0) let n = arg_code(e, 1) + let g = nreg() + emit(" ") emit(g) emit(" = getelementptr inbounds i8, ptr ") emit(p) emit(", i32 ") emit(n) emit("\n") + return val(g, "ptr") + } + if streq(name, "read_byte") { return val(emit_bind("call i32 @getchar()"), "int") } + if streq(name, "write_byte") { + let v = arg_code(e, 0) emit(" call i32 @putchar(i32 ") emit(v) emit(")\n") return val("0", "void") + } + if streq(name, "str_len") { + let s = arg_code(e, 0) + let r = emit_bind(sconcat("call i64 @strlen(ptr ", sconcat(s, ")"))) + return val(emit_bind(sconcat("trunc i64 ", sconcat(r, " to i32"))), "int") + } + if streq(name, "os_time") { + let r = emit_bind("call i64 @time(ptr null)") + return val(emit_bind(sconcat("trunc i64 ", sconcat(r, " to i32"))), "int") + } + if streq(name, "peekf") { + let p = arg_code(e, 0) let i = arg_code(e, 1) + let g = nreg() emit(" ") emit(g) emit(" = getelementptr inbounds i32, ptr ") emit(p) emit(", i32 ") emit(i) emit("\n") + return val(emit_bind(sconcat("load i32, ptr ", g)), "fixed") + } + if streq(name, "pokef") { + let p = arg_code(e, 0) let i = arg_code(e, 1) let v = arg_code(e, 2) + let g = nreg() emit(" ") emit(g) emit(" = getelementptr inbounds i32, ptr ") emit(p) emit(", i32 ") emit(i) emit("\n") + emit(" store i32 ") emit(v) emit(", ptr ") emit(g) emit("\n") + return val("0", "void") + } + if streq(name, "peekp") { + let p = arg_code(e, 0) let i = arg_code(e, 1) + let g = nreg() emit(" ") emit(g) emit(" = getelementptr inbounds ptr, ptr ") emit(p) emit(", i32 ") emit(i) emit("\n") + return val(emit_bind(sconcat("load ptr, ptr ", g)), "ptr") + } + if streq(name, "pokep") { + let p = arg_code(e, 0) let i = arg_code(e, 1) let v = arg_code(e, 2) + let g = nreg() emit(" ") emit(g) emit(" = getelementptr inbounds ptr, ptr ") emit(p) emit(", i32 ") emit(i) emit("\n") + emit(" store ptr ") emit(v) emit(", ptr ") emit(g) emit("\n") + return val("0", "void") + } + if streq(name, "as_fixed") { let a = emit_expr(e.kids[0]) return val(a.code, "fixed") } + if streq(name, "as_int") { let a = emit_expr(e.kids[0]) return val(a.code, "int") } + if streq(name, "is_windowed") { if g_windowed { return val("1", "bool") } return val("0", "bool") } + if streq(name, "game_title") { return val("@.gametitle", "str") } + # windowing hooks — declared external; only reached on the is_windowed() branch + if streq(name, "win_poll") { return val(emit_bind("call i32 @win_poll()"), "int") } + if streq(name, "win_running") { return val(emit_bind("call i32 @win_running()"), "bool") } + if streq(name, "win_open") { + let a = arg_code(e, 0) let b = arg_code(e, 1) let c = arg_code(e, 2) let d = arg_code(e, 3) + emit(" call void @win_open(i32 ") emit(a) emit(", i32 ") emit(b) emit(", i32 ") emit(c) emit(", ptr ") emit(d) emit(")\n") + return val("0", "void") + } + if streq(name, "win_present") { + let a = arg_code(e, 0) let b = arg_code(e, 1) let c = arg_code(e, 2) + emit(" call void @win_present(ptr ") emit(a) emit(", i32 ") emit(b) emit(", i32 ") emit(c) emit(")\n") + return val("0", "void") + } + if streq(name, "win_close") { emit(" call void @win_close()\n") return val("0", "void") } + return val("0", "void") +} diff --git a/selfhost/emit_machine.ludic b/selfhost/emit_machine.ludic new file mode 100644 index 00000000..85ab1e33 --- /dev/null +++ b/selfhost/emit_machine.ludic @@ -0,0 +1,39 @@ +# emit_machine.ludic — `machine { state Name = v { .. } }` dispatches on a +# register's value; `become Name` stores the target state's value back. Both are +# reg()/setreg() calls, resolved to the runtime like any other builtin. + +fn emit_machine(st: Node) -> void { + let regv = emit_expr(st.a) + let s = emit_bind(sconcat("call i32 @fn_rt_reg(i32 ", sconcat(regv.code, ")"))) + if nmach < len(mach_stk) { mach_stk[nmach] = st } else { push(mach_stk, st) } + nmach = nmach + 1 + let endl = lbl("smend") + let i = 0 + while i < len(st.kids) { + let state = st.kids[i] + let v = emit_expr(state.b) + let c = emit_bind(sconcat("icmp eq i32 ", sconcat(s, sconcat(", ", v.code)))) + let body = lbl("sbody") let nxt = lbl("sarm") + emit(" br i1 ") emit(c) emit(", label %") emit(body) emit(", label %") emit(nxt) emit("\n") + emit(body) emit(":\n") g_term = false + emit_block(state.a) + if not g_term { emit(" br label %") emit(endl) emit("\n") } + emit(nxt) emit(":\n") g_term = false + i = i + 1 + } + if not g_term { emit(" br label %") emit(endl) emit("\n") } + emit(endl) emit(":\n") g_term = false + nmach = nmach - 1 +} + +fn emit_become(st: Node) -> void { + if nmach == 0 { perr("'become' outside a machine") } + let m = mach_stk[nmach - 1] + let target: Node = ptr_null() + let i = 0 + while i < len(m.kids) { if streq(m.kids[i].s, st.s) { target = m.kids[i] } i = i + 1 } + if ptr_is_null(target) { perr(sconcat("become: no state ", st.s)) } + let regv = emit_expr(m.a) + let sv = emit_expr(target.b) + emit(" call void @fn_rt_setreg(i32 ") emit(regv.code) emit(", i32 ") emit(sv.code) emit(")\n") +} diff --git a/selfhost/emit_math.ludic b/selfhost/emit_math.ludic new file mode 100644 index 00000000..00462c0a --- /dev/null +++ b/selfhost/emit_math.ludic @@ -0,0 +1,29 @@ +# emit_math.ludic — the math builtins that lower to inline IR rather than a +# runtime call: min, max, abs, clamp. Everything else named like a builtin +# (clear, fill_rect, reg, ...) is resolved to its rt_ function by emit_call. + +fn is_math_builtin(name: ptr) -> bool { + return streq(name,"min") or streq(name,"max") or streq(name,"abs") or streq(name,"clamp") +} + +fn emit_math_builtin(name: ptr, e: Node) -> Val { + if streq(name, "abs") { + let a = emit_expr(e.kids[0]) + let c = emit_bind(sconcat("icmp slt i32 ", sconcat(a.code, ", 0"))) + let n = emit_bind(sconcat("sub i32 0, ", a.code)) + return val(emit_bind(sconcat("select i1 ", sconcat(c, sconcat(", i32 ", sconcat(n, sconcat(", i32 ", a.code)))))), "int") + } + if streq(name, "min") or streq(name, "max") { + let a = emit_expr(e.kids[0]) let b = emit_expr(e.kids[1]) + let op = "slt" + if streq(name, "max") { op = "sgt" } + let c = emit_bind(sconcat("icmp ", sconcat(op, sconcat(" i32 ", sconcat(a.code, sconcat(", ", b.code)))))) + return val(emit_bind(sconcat("select i1 ", sconcat(c, sconcat(", i32 ", sconcat(a.code, sconcat(", i32 ", b.code)))))), "int") + } + # clamp(v, lo, hi) = max(lo, min(v, hi)) + let v = emit_expr(e.kids[0]) let lo = emit_expr(e.kids[1]) let hi = emit_expr(e.kids[2]) + let c1 = emit_bind(sconcat("icmp slt i32 ", sconcat(v.code, sconcat(", ", hi.code)))) + let t = emit_bind(sconcat("select i1 ", sconcat(c1, sconcat(", i32 ", sconcat(v.code, sconcat(", i32 ", hi.code)))))) + let c2 = emit_bind(sconcat("icmp sgt i32 ", sconcat(lo.code, sconcat(", ", t)))) + return val(emit_bind(sconcat("select i1 ", sconcat(c2, sconcat(", i32 ", sconcat(lo.code, sconcat(", i32 ", t)))))), "int") +} diff --git a/selfhost/emit_new.ludic b/selfhost/emit_new.ludic new file mode 100644 index 00000000..7f139f19 --- /dev/null +++ b/selfhost/emit_new.ludic @@ -0,0 +1,88 @@ +# emit_new.ludic — heap construction and slice operations: `new S`, `new []T`, +# push(slice, v) and len(slice). Slices are a { data, len, cap } header the +# holder points at, so growth is visible to every holder. + +fn emit_sizeof(llt: ptr) -> ptr { + let p = emit_bind(sconcat("getelementptr ", sconcat(llt, ", ptr null, i32 1"))) + return emit_bind(sconcat("ptrtoint ptr ", sconcat(p, " to i64"))) +} + +fn emit_new_struct(name: ptr) -> Val { + let s = find_struct(name) + if ptr_is_null(s) { perr("unknown struct in new") } + let sz = emit_sizeof(sconcat("%Str_", name)) + let obj = emit_bind(sconcat("call ptr @malloc(i64 ", sconcat(sz, ")"))) + let f = 0 + while f < len(s.kids) { + let fd = s.kids[f] + let addr = nreg() + emit(" ") emit(addr) emit(" = getelementptr inbounds %Str_") emit(name) + emit(", ptr ") emit(obj) emit(", i32 0, i32 ") emit(itoa(f)) emit("\n") + let lt = llty(fd.ty) + let v = "0" + if streq(lt, "ptr") { v = "null" } + if not ptr_is_null(fd.a) { let dv = emit_expr(fd.a) v = dv.code } + emit(" store ") emit(lt) emit(" ") emit(v) emit(", ptr ") emit(addr) emit("\n") + f = f + 1 + } + return val(obj, name) +} + +fn emit_new_slice(ty: ptr) -> Val { + let sz = emit_sizeof("%LSlice") + let h = emit_bind(sconcat("call ptr @malloc(i64 ", sconcat(sz, ")"))) + let d0 = nreg() emit(" ") emit(d0) emit(" = getelementptr inbounds %LSlice, ptr ") emit(h) emit(", i32 0, i32 0\n") + emit(" store ptr null, ptr ") emit(d0) emit("\n") + let d1 = nreg() emit(" ") emit(d1) emit(" = getelementptr inbounds %LSlice, ptr ") emit(h) emit(", i32 0, i32 1\n") + emit(" store i32 0, ptr ") emit(d1) emit("\n") + let d2 = nreg() emit(" ") emit(d2) emit(" = getelementptr inbounds %LSlice, ptr ") emit(h) emit(", i32 0, i32 2\n") + emit(" store i32 0, ptr ") emit(d2) emit("\n") + return val(h, ty) +} + +fn slice_field(h: ptr, i: int) -> ptr { + let r = nreg() + emit(" ") emit(r) emit(" = getelementptr inbounds %LSlice, ptr ") emit(h) + emit(", i32 0, i32 ") emit(itoa(i)) emit("\n") + return r +} + +fn emit_len(e: Node) -> Val { + let s = emit_expr(e.kids[0]) + let lp = slice_field(s.code, 1) + return val(emit_bind(sconcat("load i32, ptr ", lp)), "int") +} + +fn emit_push(e: Node) -> Val { + let s = emit_expr(e.kids[0]) + let el = slice_elem(s.ty) + let elt = llty(el) + let h = s.code + let lp = slice_field(h, 1) let cp = slice_field(h, 2) let dp = slice_field(h, 0) + let l = emit_bind(sconcat("load i32, ptr ", lp)) + let c = emit_bind(sconcat("load i32, ptr ", cp)) + let full = emit_bind(sconcat("icmp sge i32 ", sconcat(l, sconcat(", ", c)))) + let grow = lbl("grow") let put = lbl("put") + emit(" br i1 ") emit(full) emit(", label %") emit(grow) emit(", label %") emit(put) emit("\n") + emit(grow) emit(":\n") + let dbl = emit_bind(sconcat("mul i32 ", sconcat(c, ", 2"))) + let isz = emit_bind(sconcat("icmp eq i32 ", sconcat(c, ", 0"))) + let nc = emit_bind(sconcat("select i1 ", sconcat(isz, sconcat(", i32 8, i32 ", dbl)))) + let esz = emit_sizeof(elt) + let ncw = emit_bind(sconcat("zext i32 ", sconcat(nc, " to i64"))) + let bytes = emit_bind(sconcat("mul i64 ", sconcat(ncw, sconcat(", ", esz)))) + let old = emit_bind(sconcat("load ptr, ptr ", dp)) + let nd = emit_bind(sconcat("call ptr @realloc(ptr ", sconcat(old, sconcat(", i64 ", sconcat(bytes, ")"))))) + emit(" store ptr ") emit(nd) emit(", ptr ") emit(dp) emit("\n") + emit(" store i32 ") emit(nc) emit(", ptr ") emit(cp) emit("\n") + emit(" br label %") emit(put) emit("\n") + emit(put) emit(":\n") + let v = emit_expr(e.kids[1]) + let data = emit_bind(sconcat("load ptr, ptr ", dp)) + let slot = nreg() + emit(" ") emit(slot) emit(" = getelementptr inbounds ") emit(elt) emit(", ptr ") emit(data) emit(", i32 ") emit(l) emit("\n") + emit(" store ") emit(elt) emit(" ") emit(v.code) emit(", ptr ") emit(slot) emit("\n") + let l1 = emit_bind(sconcat("add i32 ", sconcat(l, ", 1"))) + emit(" store i32 ") emit(l1) emit(", ptr ") emit(lp) emit("\n") + return val("0", "void") +} diff --git a/selfhost/emit_query.ludic b/selfhost/emit_query.ludic new file mode 100644 index 00000000..8a5931ff --- /dev/null +++ b/selfhost/emit_query.ludic @@ -0,0 +1,98 @@ +# emit_query.ludic — the ECS query loop. Iterates live entities, filters by the +# components/archetypes each carries, binds the requested components, and runs +# the body once per match. Mirrors ll_query in compiler/back/ir_ecs.c. + +fn find_arch_id(name: ptr) -> int { + let i = 0 let n = 1 + while i < len(prog) { if prog[i].kind == N_ARCH { if streq(prog[i].s, name) { return n } n = n + 1 } i = i + 1 } + return 0 +} + +fn emit_query(st: Node) -> void { + let me = itoa(MAX_ENT) + let ip = emit_alloca("i32") + store_at("i32", "0", ip) + if nself < len(self_stk) { self_stk[nself] = ip } else { push(self_stk, ip) } + nself = nself + 1 + + let cond = lbl("qcond") let body = lbl("qbody") let nxt = lbl("qnext") let endl = lbl("qend") + emit(" br label %") emit(cond) emit("\n") + emit(cond) emit(":\n") + let i0 = emit_bind(sconcat("load i32, ptr ", ip)) + let ec = emit_bind("load i32, ptr @L_entc") + let lt = emit_bind(sconcat("icmp slt i32 ", sconcat(i0, sconcat(", ", ec)))) + emit(" br i1 ") emit(lt) emit(", label %") emit(body) emit(", label %") emit(endl) emit("\n") + emit(body) emit(":\n") g_term = false + let i1 = emit_bind(sconcat("load i32, ptr ", ip)) + # alive? + let ap = nreg() emit(" ") emit(ap) emit(" = getelementptr inbounds [") emit(me) emit(" x i32], ptr @L_alive, i32 0, i32 ") emit(i1) emit("\n") + let al = emit_bind(sconcat("load i32, ptr ", ap)) + let alc = emit_bind(sconcat("icmp ne i32 ", sconcat(al, ", 0"))) + let ka = lbl("qa") + emit(" br i1 ") emit(alc) emit(", label %") emit(ka) emit(", label %") emit(nxt) emit("\n") + emit(ka) emit(":\n") + + let terms = st.c + # component / archetype filters + let t = 0 + while t < len(terms.kids) { + let tm = terms.kids[t] + let ak = find_arch_id(tm.s) + let ok = "0" + if ak > 0 { + let kp = nreg() emit(" ") emit(kp) emit(" = getelementptr inbounds [") emit(me) emit(" x i32], ptr @L_kind, i32 0, i32 ") emit(i1) emit("\n") + let kv = emit_bind(sconcat("load i32, ptr ", kp)) + ok = emit_bind(sconcat("icmp eq i32 ", sconcat(kv, sconcat(", ", itoa(ak))))) + } else { + let hp = nreg() emit(" ") emit(hp) emit(" = getelementptr inbounds [") emit(me) emit(" x i8], ptr @H_") emit(tm.s) emit(", i32 0, i32 ") emit(i1) emit("\n") + let hv = emit_bind(sconcat("load i8, ptr ", hp)) + ok = emit_bind(sconcat("icmp ne i8 ", sconcat(hv, ", 0"))) + } + let keep = lbl("qt") + emit(" br i1 ") emit(ok) emit(", label %") emit(keep) emit(", label %") emit(nxt) emit("\n") + emit(keep) emit(":\n") + t = t + 1 + } + + # bind the requested components to the loop variables, in order + let save = nloc + let vi = 0 + t = 0 + while t < len(terms.kids) { + let tm = terms.kids[t] + if tm.ival == 0 and find_arch_id(tm.s) == 0 { + if vi < len(st.kids) { + let slot = nreg() + emit(" ") emit(slot) emit(" = getelementptr inbounds [") emit(me) emit(" x %Cmp_") emit(tm.s) emit("], ptr @S_") emit(tm.s) emit(", i32 0, i32 ") emit(i1) emit("\n") + let vslot = emit_alloca("ptr") + emit(" store ptr ") emit(slot) emit(", ptr ") emit(vslot) emit("\n") + loc_push(st.kids[vi].s, vslot, tm.s) + vi = vi + 1 + } + } + t = t + 1 + } + + # optional where-clause + if not ptr_is_null(st.b) { + let w = emit_expr(st.b) + let wc = emit_bind(sconcat("icmp ne i32 ", sconcat(w.code, ", 0"))) + let kw = lbl("qw") + emit(" br i1 ") emit(wc) emit(", label %") emit(kw) emit(", label %") emit(nxt) emit("\n") + emit(kw) emit(":\n") + } + + loop_push(nxt, endl) + emit_block(st.a) + loop_pop() + nloc = save + if not g_term { emit(" br label %") emit(nxt) emit("\n") } + + emit(nxt) emit(":\n") + let i2 = emit_bind(sconcat("load i32, ptr ", ip)) + let i3 = emit_bind(sconcat("add i32 ", sconcat(i2, ", 1"))) + store_at("i32", i3, ip) + emit(" br label %") emit(cond) emit("\n") + emit(endl) emit(":\n") g_term = false + nself = nself - 1 +} diff --git a/selfhost/emit_save.ludic b/selfhost/emit_save.ludic new file mode 100644 index 00000000..7a170f85 --- /dev/null +++ b/selfhost/emit_save.ludic @@ -0,0 +1,61 @@ +# emit_save.ludic — save() / load() snapshot of the whole ECS world. The +# compiler writes the entity/component half itself (it knows the shape) and +# hands the open file to rt_save_state/rt_load_state for the runtime's own +# state. Mirrors compiler/back/ir_save.c. save()->@L_save, load()->@L_load. + +var g_iok: int = 0 + +fn emit_io(fn2: ptr, p: ptr, bytes: ptr) -> void { + let r = sconcat("%io", itoa(g_iok)) g_iok = g_iok + 1 + emit(" ") emit(r) emit(" = call i64 @") emit(fn2) emit("(ptr ") emit(p) emit(", i64 1, i64 ") emit(bytes) emit(", ptr %f)\n") +} + +fn emit_snapshot_blocks(fn2: ptr) -> void { + g_iok = 0 + let me = itoa(MAX_ENT) + emit_io(fn2, "@L_entc", "4") + emit_io(fn2, "@L_freen", "4") + emit(" %nalive = mul i64 ") emit(me) emit(", 4\n") + emit_io(fn2, "@L_alive", "%nalive") + emit_io(fn2, "@L_freelist", "%nalive") + emit_io(fn2, "@L_kind", "%nalive") + let i = 0 + while i < len(prog) { if prog[i].kind == N_VAR { emit_io(fn2, sconcat("@g_", prog[i].s), "4") } i = i + 1 } + let ci = 0 + i = 0 + while i < len(prog) { + if prog[i].kind == N_COMP { + let c = prog[i].s + let csz = sconcat("%csz", itoa(ci)) + emit(" ") emit(csz) emit(" = ptrtoint ptr getelementptr (%Cmp_") emit(c) emit(", ptr null, i32 ") emit(me) emit(") to i64\n") + emit_io(fn2, sconcat("@S_", c), csz) + emit_io(fn2, sconcat("@H_", c), me) + ci = ci + 1 + } + i = i + 1 + } +} + +fn emit_snapshot() -> void { + emith("@.sav_path = private unnamed_addr constant [10 x i8] c\"ludic.sav\\00\"\n") + emith("@.sav_wb = private unnamed_addr constant [3 x i8] c\"wb\\00\"\n") + emith("@.sav_rb = private unnamed_addr constant [3 x i8] c\"rb\\00\"\n") + let has_save = not ptr_is_null(find_fn("rt_save_state")) + let has_load = not ptr_is_null(find_fn("rt_load_state")) + + emit("define void @L_save() {\nentry:\n") + emit(" %f = call ptr @fopen(ptr @.sav_path, ptr @.sav_wb)\n") + emit(" %bad = icmp eq ptr %f, null\n") + emit(" br i1 %bad, label %out, label %go\ngo:\n") + emit_snapshot_blocks("fwrite") + if has_save { emit(" call void @fn_rt_save_state(ptr %f)\n") } + emit(" %c = call i32 @fclose(ptr %f)\n br label %out\nout:\n ret void\n}\n\n") + + emit("define i32 @L_load() {\nentry:\n") + emit(" %f = call ptr @fopen(ptr @.sav_path, ptr @.sav_rb)\n") + emit(" %bad = icmp eq ptr %f, null\n") + emit(" br i1 %bad, label %miss, label %go\nmiss:\n ret i32 0\ngo:\n") + emit_snapshot_blocks("fread") + if has_load { emit(" call void @fn_rt_load_state(ptr %f)\n") } + emit(" %c = call i32 @fclose(ptr %f)\n ret i32 1\n}\n\n") +} diff --git a/selfhost/emit_spawn.ludic b/selfhost/emit_spawn.ludic new file mode 100644 index 00000000..a418bcba --- /dev/null +++ b/selfhost/emit_spawn.ludic @@ -0,0 +1,68 @@ +# emit_spawn.ludic — spawn / despawn / self(), and seeding a component's fields +# from its declared defaults plus any per-spawn overrides. + +fn emit_init_component(e: ptr, comp: ptr, rec: Node) -> void { + let me = itoa(MAX_ENT) + let c = find_comp(comp) + if ptr_is_null(c) { perr(sconcat("spawn: unknown component ", comp)) } + let hp = nreg() emit(" ") emit(hp) emit(" = getelementptr inbounds [") emit(me) emit(" x i8], ptr @H_") emit(comp) emit(", i32 0, i32 ") emit(e) emit("\n") + emit(" store i8 1, ptr ") emit(hp) emit("\n") + let slot = nreg() + emit(" ") emit(slot) emit(" = getelementptr inbounds [") emit(me) emit(" x %Cmp_") emit(comp) emit("], ptr @S_") emit(comp) emit(", i32 0, i32 ") emit(e) emit("\n") + # defaults + let f = 0 + while f < len(c.kids) { + let fd = c.kids[f] + let addr = nreg() + emit(" ") emit(addr) emit(" = getelementptr inbounds %Cmp_") emit(comp) emit(", ptr ") emit(slot) emit(", i32 0, i32 ") emit(itoa(f)) emit("\n") + let lt = llty(fd.ty) + let v = "0" + if streq(lt, "ptr") { v = "null" } + if not ptr_is_null(fd.a) { let dv = emit_expr(fd.a) v = dv.code } + emit(" store ") emit(lt) emit(" ") emit(v) emit(", ptr ") emit(addr) emit("\n") + f = f + 1 + } + # per-spawn overrides + if not ptr_is_null(rec) { + let j = 0 + while j < len(rec.kids) { + let fi = rec.kids[j] + let fidx = field_index(c, fi.s) + if fidx >= 0 { + let addr = nreg() + emit(" ") emit(addr) emit(" = getelementptr inbounds %Cmp_") emit(comp) emit(", ptr ") emit(slot) emit(", i32 0, i32 ") emit(itoa(fidx)) emit("\n") + let dv = emit_expr(fi.a) + emit(" store ") emit(llty(field_type(c, fi.s))) emit(" ") emit(dv.code) emit(", ptr ") emit(addr) emit("\n") + } + j = j + 1 + } + } +} + +fn emit_spawn(st: Node) -> void { + let e = emit_bind("call i32 @L_alloc()") + let ak = find_arch_id(st.s) + if ak > 0 { + let me = itoa(MAX_ENT) + let kp = nreg() emit(" ") emit(kp) emit(" = getelementptr inbounds [") emit(me) emit(" x i32], ptr @L_kind, i32 0, i32 ") emit(e) emit("\n") + emit(" store i32 ") emit(itoa(ak)) emit(", ptr ") emit(kp) emit("\n") + let arch = find_arch(st.s) + let c = 0 + while c < len(arch.kids) { + let cn = arch.kids[c].s + let rec = ptr_null() + let i = 0 + while i < len(st.kids) { if streq(st.kids[i].s, cn) { rec = st.kids[i].a } i = i + 1 } + emit_init_component(e, cn, rec) + c = c + 1 + } + } else { + let i = 0 + while i < len(st.kids) { emit_init_component(e, st.kids[i].s, st.kids[i].a) i = i + 1 } + } +} + +fn emit_despawn(st: Node) -> void { + let v = emit_expr(st.a) + emit(" call void @L_free_entity(i32 ") emit(v.code) emit(")\n") +} diff --git a/selfhost/emit_stmt.ludic b/selfhost/emit_stmt.ludic new file mode 100644 index 00000000..4643e01b --- /dev/null +++ b/selfhost/emit_stmt.ludic @@ -0,0 +1,193 @@ +# emit_stmt.ludic — lower statements. Terminators set g_term so the rest of a +# block is skipped until a new basic block opens. + +fn emit_block(b: Node) -> void { + let i = 0 + while i < len(b.kids) { + if g_term { return } + emit_stmt(b.kids[i]) + i = i + 1 + } +} + +# store `val` (llvm type `lt`) into address `addr` +fn store_at(lt: ptr, v: ptr, addr: ptr) -> void { + emit(" store ") emit(lt) emit(" ") emit(v) emit(", ptr ") emit(addr) emit("\n") +} + +fn emit_assign(st: Node) -> void { + # resolve the target's address and type + let t = st.a + let addr = "0" + let ty = "int" + if t.kind == E_ID { + let li = loc_find(t.s) + if li >= 0 { addr = loc_reg[li] ty = loc_ty[li] } + else { + let g = find_global(t.s) + if ptr_is_null(g) { perr(sconcat("assign to unknown ", t.s)) } + addr = sconcat("@g_", t.s) ty = g.ty + } + } else { + if t.kind == E_MEMBER { addr = emit_member_addr(t) ty = g_addr_ty } + else { if t.kind == E_INDEX { addr = emit_index_addr(t) ty = g_addr_ty } + else { perr("bad assignment target") } } + } + let lt = llty(ty) + let rv = emit_expr(st.b) + let v = rv.code + if not streq(st.s, "=") { + let cur = emit_bind(sconcat("load ", sconcat(lt, sconcat(", ptr ", addr)))) + let opc = "add" + if streq(st.s, "-=") { opc = "sub" } + if streq(st.s, "*=") { opc = "mul" } + if streq(st.s, "/=") { opc = "sdiv" } + v = emit_bind(sconcat(opc, sconcat(" i32 ", sconcat(cur, sconcat(", ", v))))) + } + store_at(lt, v, addr) +} + +fn emit_if(st: Node) -> void { + let c = emit_expr(st.a) + let cc = emit_bind(sconcat("icmp ne i32 ", sconcat(c.code, ", 0"))) + let has_else = not ptr_is_null(st.c) + let tl = lbl("then") let el = lbl("else") let en = lbl("ifend") + if has_else { emit(" br i1 ") emit(cc) emit(", label %") emit(tl) emit(", label %") emit(el) emit("\n") } + else { emit(" br i1 ") emit(cc) emit(", label %") emit(tl) emit(", label %") emit(en) emit("\n") } + emit(tl) emit(":\n") g_term = false + emit_block(st.b) + if not g_term { emit(" br label %") emit(en) emit("\n") } + if has_else { + emit(el) emit(":\n") g_term = false + # else is either a block or a nested if-statement + if st.c.kind == S_IF { emit_stmt(st.c) } else { emit_block(st.c) } + if not g_term { emit(" br label %") emit(en) emit("\n") } + } + emit(en) emit(":\n") g_term = false +} + +fn emit_while(st: Node) -> void { + let cl = lbl("wcond") let bl = lbl("wbody") let en = lbl("wend") + emit(" br label %") emit(cl) emit("\n") + emit(cl) emit(":\n") + let c = emit_expr(st.a) + let cc = emit_bind(sconcat("icmp ne i32 ", sconcat(c.code, ", 0"))) + emit(" br i1 ") emit(cc) emit(", label %") emit(bl) emit(", label %") emit(en) emit("\n") + emit(bl) emit(":\n") g_term = false + loop_push(cl, en) + emit_block(st.b) + loop_pop() + if not g_term { emit(" br label %") emit(cl) emit("\n") } + emit(en) emit(":\n") g_term = false +} + +fn emit_for(st: Node) -> void { + let slot = emit_alloca("i32") + let lo = emit_expr(st.a) + store_at("i32", lo.code, slot) + loc_push(st.s, slot, "int") + let cl = lbl("fcond") let bl = lbl("fbody") let ct = lbl("fcont") let en = lbl("fend") + emit(" br label %") emit(cl) emit("\n") + emit(cl) emit(":\n") + let iv = emit_bind(sconcat("load i32, ptr ", slot)) + let hi = emit_expr(st.b) + let cc = emit_bind(sconcat("icmp slt i32 ", sconcat(iv, sconcat(", ", hi.code)))) + emit(" br i1 ") emit(cc) emit(", label %") emit(bl) emit(", label %") emit(en) emit("\n") + emit(bl) emit(":\n") g_term = false + loop_push(ct, en) + emit_block(st.c) + loop_pop() + if not g_term { emit(" br label %") emit(ct) emit("\n") } + emit(ct) emit(":\n") + let i2 = emit_bind(sconcat("load i32, ptr ", slot)) + let i3 = emit_bind(sconcat("add i32 ", sconcat(i2, ", 1"))) + store_at("i32", i3, slot) + emit(" br label %") emit(cl) emit("\n") + emit(en) emit(":\n") g_term = false +} + +fn emit_return(st: Node) -> void { + if not ptr_is_null(st.a) { + let v = emit_expr(st.a) + store_at(llty(ret_ty), v.code, "%retval") + } + emit(" br label %ret\n") + g_term = true +} + +fn arm_is_default(arm: Node) -> bool { + let p = 0 + while p < len(arm.kids) { if arm.kids[p].kind == E_ID and streq(arm.kids[p].s, "_") { return true } p = p + 1 } + return false +} + +fn emit_match(st: Node) -> void { + let sv = emit_expr(st.a) + let endl = lbl("mend") + let deflt: Node = ptr_null() + let i = 0 + while i < len(st.kids) { + let arm = st.kids[i] + if arm_is_default(arm) { deflt = arm } + else { + let acc = "0" + let first = true + let p = 0 + while p < len(arm.kids) { + let pv = emit_expr(arm.kids[p]) + let c = emit_bind(sconcat("icmp eq i32 ", sconcat(sv.code, sconcat(", ", pv.code)))) + if first { acc = c first = false } + else { acc = emit_bind(sconcat("or i1 ", sconcat(acc, sconcat(", ", c)))) } + p = p + 1 + } + let bodyl = lbl("mbody") let nextl = lbl("marm") + emit(" br i1 ") emit(acc) emit(", label %") emit(bodyl) emit(", label %") emit(nextl) emit("\n") + emit(bodyl) emit(":\n") g_term = false + emit_block(arm.a) + if not g_term { emit(" br label %") emit(endl) emit("\n") } + emit(nextl) emit(":\n") g_term = false + } + i = i + 1 + } + if not ptr_is_null(deflt) { emit_block(deflt.a) } + if not g_term { emit(" br label %") emit(endl) emit("\n") } + emit(endl) emit(":\n") g_term = false +} + +fn emit_stmt(st: Node) -> void { + if st.kind == S_LET { + let ty = st.ty + if ptr_is_null(ty) { let v0 = emit_expr(st.a) ty = v0.ty + let slot = emit_alloca(llty(ty)) store_at(llty(ty), v0.code, slot) loc_push(st.s, slot, ty) return } + let slot = emit_alloca(llty(ty)) + if ptr_is_null(st.a) { + let z = "0" + if streq(llty(ty), "ptr") { z = "null" } + store_at(llty(ty), z, slot) + } else { let v = emit_expr(st.a) store_at(llty(ty), v.code, slot) } + loc_push(st.s, slot, ty) + return + } + if st.kind == S_ASSIGN { emit_assign(st) return } + if st.kind == S_IF { emit_if(st) return } + if st.kind == S_WHILE { emit_while(st) return } + if st.kind == S_FOR { emit_for(st) return } + if st.kind == S_RETURN { emit_return(st) return } + if st.kind == S_BREAK { emit(" br label %") emit(brk_lbl[nloop - 1]) emit("\n") g_term = true return } + if st.kind == S_CONTINUE { emit(" br label %") emit(cnt_lbl[nloop - 1]) emit("\n") g_term = true return } + if st.kind == S_MATCH { emit_match(st) return } + if st.kind == S_QUERY { emit_query(st) return } + if st.kind == S_SPAWN { emit_spawn(st) return } + if st.kind == S_DESPAWN { emit_despawn(st) return } + if st.kind == S_MACHINE { emit_machine(st) return } + if st.kind == S_BECOME { emit_become(st) return } + if st.kind == S_EXPR { let v = emit_expr(st.a) return } + perr("cannot emit statement") +} + +fn loop_push(cont: ptr, brk: ptr) -> void { + if nloop < len(cnt_lbl) { cnt_lbl[nloop] = cont brk_lbl[nloop] = brk } + else { push(cnt_lbl, cont) push(brk_lbl, brk) } + nloop = nloop + 1 +} +fn loop_pop() -> void { nloop = nloop - 1 } diff --git a/selfhost/emit_ui.ludic b/selfhost/emit_ui.ludic new file mode 100644 index 00000000..ef2c5841 --- /dev/null +++ b/selfhost/emit_ui.ludic @@ -0,0 +1,125 @@ +# emit_ui.ludic — a `ui` block is data: the compiler flattens the widget tree +# and emits @ui_build(), which hands every property to the Ludic UI runtime via +# rt_ui_set(index, key, value). Mirrors compiler/back/ir_ui.c. Layout/drawing/ +# focus all live in runtime/native/ui.ludic. + +var uiw: []Node # flattened widgets, pre-order +var uiw_parent: []int +var ui_roots: []int # first-widget index of each ui block + +fn ui_wtype(w: Node) -> int { + let s = w.s + if streq(s, "panel") { return 0 } if streq(s, "col") { return 1 } if streq(s, "row") { return 2 } + if streq(s, "label") { return 3 } if streq(s, "button") { return 4 } + if streq(s, "image") { return 5 } if streq(s, "spacer") { return 6 } + return 0 +} +fn ui_prop(w: Node, key: ptr) -> Node { + let i = 0 + while i < len(w.b.kids) { if streq(w.b.kids[i].s, key) { return w.b.kids[i].a } i = i + 1 } + return ptr_null() +} +fn ui_flatten(w: Node, parent: int) -> void { + let idx = len(uiw) + push(uiw, w) push(uiw_parent, parent) + let i = 0 + while i < len(w.kids) { ui_flatten(w.kids[i], idx) i = i + 1 } +} +fn ui_flatten_all() -> void { + uiw = new []Node uiw_parent = new []int ui_roots = new []int + let i = 0 + while i < len(prog) { + if prog[i].kind == N_UI and prog[i].ival == 1 { push(ui_roots, len(uiw)) ui_flatten(prog[i].a, 0 - 1) } + i = i + 1 + } +} +fn has_ui() -> bool { + let i = 0 + while i < len(prog) { if prog[i].kind == N_UI and prog[i].ival == 1 { return true } i = i + 1 } + return false +} + +# index of a UI_: a ui block's root, or a widget's id= +fn ui_index_of(nm: ptr) -> int { + let s = substr(nm, 3, slen(nm) - 3) # strip "UI_" + let u = 0 let bi = 0 + let i = 0 + while i < len(prog) { + if prog[i].kind == N_UI and prog[i].ival == 1 { if streq(prog[i].s, s) { return ui_roots[bi] } bi = bi + 1 } + i = i + 1 + } + i = 0 + while i < len(uiw) { + let idp = ui_prop(uiw[i], "id") + if not ptr_is_null(idp) { if idp.kind == E_ID and streq(idp.s, s) { return i } } + i = i + 1 + } + return 0 +} +fn is_ui_ident(nm: ptr) -> bool { + return slen(nm) > 3 and peek8(nm, 0) == 85 and peek8(nm, 1) == 73 and peek8(nm, 2) == 95 # "UI_" +} + +fn ll_ui_set(idx: int, key: int, val: ptr) -> void { + emit(" call void @fn_rt_ui_set(i32 ") emit(itoa(idx)) emit(", i32 ") emit(itoa(key)) emit(", i32 ") emit(val) emit(")\n") +} +fn ui_prop_key(k: ptr) -> int { + if streq(k,"w") { return 2 } if streq(k,"h") { return 3 } if streq(k,"x") { return 4 } if streq(k,"y") { return 5 } + if streq(k,"pad") { return 7 } if streq(k,"gap") { return 8 } if streq(k,"bg") { return 9 } if streq(k,"fg") { return 10 } + if streq(k,"border") { return 11 } if streq(k,"grow") { return 13 } if streq(k,"font") { return 14 } if streq(k,"size") { return 15 } + if streq(k,"inset") { return 16 } if streq(k,"focus") { return 17 } + return 0 - 1 +} + +fn emit_ui_build() -> void { + ui_flatten_all() + ll_t = 0 ll_lbl = 0 g_term = false loc_reset() nloop = 0 + let fbody = buf_new() + falloc = buf_new() + let saved = code + code = fbody + emit(" call void @fn_rt_ui_reset(i32 ") emit(itoa(len(uiw))) emit(")\n") + let i = 0 + while i < len(uiw) { + let w = uiw[i] + let t = ui_wtype(w) + ll_ui_set(i, 0, itoa(t)) + ll_ui_set(i, 1, itoa(uiw_parent[i])) + if t == 4 { ll_ui_set(i, 17, "1") } + let p = 0 + while p < len(w.b.kids) { + let pr = w.b.kids[p] + let k = pr.s + let v = pr.a + if streq(k, "id") { p = p + 1 continue } + if streq(k, "text") { + let sv = emit_expr(v) + emit(" call void @fn_rt_ui_static_text(i32 ") emit(itoa(i)) emit(", ptr ") emit(sv.code) emit(")\n") + } else { if streq(k, "skin") or streq(k, "image") { + let sv = emit_expr(v) + let r = emit_bind(sconcat("call i32 @fn_rt_image_load(ptr ", sconcat(sv.code, ")"))) + if streq(k, "skin") { ll_ui_set(i, 20, r) } else { ll_ui_set(i, 19, r) } + } else { if streq(k, "align") { + if v.kind == E_ID { + let a = 0 + if streq(v.s, "center") { a = 1 } if streq(v.s, "end") { a = 2 } + ll_ui_set(i, 12, itoa(a)) + } else { let vv = emit_expr(v) ll_ui_set(i, 12, vv.code) } + } else { + let key = ui_prop_key(k) + if key >= 0 { + let vv = emit_expr(v) + ll_ui_set(i, key, vv.code) + if key == 4 or key == 5 { ll_ui_set(i, 6, "1") } + } + } } } + p = p + 1 + } + i = i + 1 + } + code = saved + emit("define void @ui_build() {\nentry:\n") + emit(buf_str(falloc)) + emit(buf_str(fbody)) + emit(" ret void\n}\n\n") +} diff --git a/selfhost/game-build.sh b/selfhost/game-build.sh new file mode 100755 index 00000000..fc321288 --- /dev/null +++ b/selfhost/game-build.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# game-build.sh — compile a Ludic GAME with the self-hosted compiler. The +# compiler resolves the game's own `import`s and auto-splices the Ludic runtime +# (runtime/native/core.ludic + its imports), exactly as the C compiler does. +# Headless only for now (renders to out.ppm). Run from the repo root. +# ./selfhost/game-build.sh +set -u +cd "$(dirname "$0")/.." +SH="$1"; GAME="$2"; OUT="$3" +CC="${LUDIC_CC:-clang}" +ERR="$(mktemp)" +"$SH" "$GAME" > "$OUT.ll" 2>"$ERR" || { echo "self-host failed:"; head -5 "$ERR"; rm -f "$ERR"; exit 1; } +# -O2 removes the dead windowing branches (is_windowed()==0) so win_* need no defs +$CC -O2 "$OUT.ll" -o "$OUT" 2>"$ERR" || { echo "link failed:"; grep -i error "$ERR" | head -5; rm -f "$ERR"; exit 1; } +rm -f "$ERR" "$OUT.ll" # keep only the binary +echo "built $OUT" diff --git a/selfhost/golden/chronorift.ppm b/selfhost/golden/chronorift.ppm new file mode 100644 index 00000000..0a242d95 --- /dev/null +++ b/selfhost/golden/chronorift.ppm @@ -0,0 +1,4 @@ +P6 +320 240 +255 +$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.ÿÿÿÿÿÿÿÿÿ$.$.ÿÿÿ$.$.$.$.$.$.ÿÿÿÿÿÿÿÿÿ$.$.ÿÿÿ$.$.$.ÿÿÿ$.ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.ÿÿÿ$.$.$.ÿÿÿ$.ÿÿÿ$.$.$.$.$.$.$.ÿÿÿ$.$.$.ÿÿÿÿÿÿ$.ÿÿÿÿÿÿ$.ÿÿÿ$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.ÿÿÿ$.$.$.$.$.ÿÿÿ$.$.$.$.$.$.$.ÿÿÿ$.$.$.ÿÿÿ$.ÿÿÿ$.ÿÿÿ$.ÿÿÿ$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.ÿÿÿÿÿÿÿÿÿ$.$.ÿÿÿ$.$.$.$.$.$.$.ÿÿÿ$.$.$.ÿÿÿ$.ÿÿÿ$.ÿÿÿ$.ÿÿÿÿÿÿÿÿÿ$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.ÿÿÿ$.ÿÿÿ$.$.$.$.$.$.$.ÿÿÿ$.$.$.ÿÿÿ$.$.$.ÿÿÿ$.ÿÿÿ$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.ÿÿÿ$.$.$.ÿÿÿ$.ÿÿÿ$.$.$.$.$.$.$.ÿÿÿ$.$.$.ÿÿÿ$.$.$.ÿÿÿ$.ÿÿÿ$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.ÿÿÿÿÿÿÿÿÿ$.$.ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ$.$.ÿÿÿÿÿÿÿÿÿ$.$.ÿÿÿ$.$.$.ÿÿÿ$.ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@à@@$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1iÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔ?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1iÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔ?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1iÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔ?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1iÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔ?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1iÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔ?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³iÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³iÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³iÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³iÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³iÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔiÿÔCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•j?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•j?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•j?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•j?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•j?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•j?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•j?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•j?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•j?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•j?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³%•j%•j%•j%•j%•jCá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³Cá³?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U                                                                                                                                                                                                                                                                                                                              ::U::U                                                                                                                                                                                                                                                                                                                              ::U::U                                                                                                                                                                                                                                                                                                                              ::U::U   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                                                                                                   ::U::U   ÿÿ                                                                                      ÿÿ                                                                                                                  ÿàŠÿàŠÿàŠÿàŠ    ÿàŠ         ÿàŠ   ÿàŠ ÿàŠ   ÿàŠ  ÿàŠÿàŠÿàŠ   ÿàŠÿàŠÿàŠ  ÿàŠ   ÿàŠ ÿàŠÿàŠÿàŠÿàŠÿàŠ                                                            ::U::U   ÿÿ                                     ÿàŠ   ÿàŠ ÿàŠ   ÿàŠ  ÿàŠÿàŠÿàŠ   ÿàŠÿàŠÿàŠ  ÿàŠ   ÿàŠ ÿàŠÿàŠÿàŠÿàŠÿàŠ              ÿÿ                                          É ÿ   É ÿ  É ÿÉ ÿÉ ÿ   É ÿÉ ÿÉ ÿ  É ÿÉ ÿÉ ÿÉ ÿÉ ÿ                                                 ÿàŠ   ÿàŠ  ÿàŠÿàŠ         ÿàŠ  ÿàŠ  ÿàŠÿàŠ  ÿàŠ   ÿàŠ   ÿàŠ   ÿàŠ ÿàŠ   ÿàŠ   ÿàŠ                                                              ::U::U   ÿÿ                                     ÿàŠ  ÿàŠ  ÿàŠÿàŠ  ÿàŠ   ÿàŠ   ÿàŠ   ÿàŠ ÿàŠ   ÿàŠ   ÿàŠ                ÿÿ                                          É ÿÉ ÿ É ÿÉ ÿ É ÿ   É ÿ É ÿ   É ÿ É ÿ                                                     ÿàŠ   ÿàŠ   ÿàŠ         ÿàŠ ÿàŠ   ÿàŠ ÿàŠ ÿàŠ   ÿàŠ   ÿàŠ     ÿàŠ   ÿàŠ   ÿàŠ                                                              ::U::U   ÿÿ                                     ÿàŠ ÿàŠ   ÿàŠ ÿàŠ ÿàŠ   ÿàŠ   ÿàŠ     ÿàŠ   ÿàŠ   ÿàŠ                ÿÿ            ?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1                  É ÿ É ÿ É ÿ É ÿ   É ÿ É ÿ     É ÿ                                                     ÿàŠÿàŠÿàŠÿàŠ    ÿàŠ         ÿàŠÿàŠ    ÿàŠ ÿàŠ ÿàŠ   ÿàŠ   ÿàŠ ÿàŠÿàŠÿàŠ ÿàŠÿàŠÿàŠÿàŠÿàŠ   ÿàŠ                                                              ::U::U   ÿÿ                                     ÿàŠÿàŠ    ÿàŠ ÿàŠ ÿàŠ   ÿàŠ   ÿàŠ ÿàŠÿàŠÿàŠ ÿàŠÿàŠÿàŠÿàŠÿàŠ   ÿàŠ                ÿÿ            ?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1                  É ÿ É ÿ É ÿ É ÿÉ ÿÉ ÿÉ ÿÉ ÿ É ÿ É ÿÉ ÿÉ ÿ É ÿÉ ÿÉ ÿ                                                   ÿàŠ       ÿàŠ         ÿàŠ ÿàŠ   ÿàŠ  ÿàŠÿàŠ   ÿàŠ   ÿàŠ   ÿàŠ ÿàŠ   ÿàŠ   ÿàŠ                                                              ::U::U   ÿÿ             ?&1?&1?&1?&1?&1?&1?&1?&1                ÿàŠ ÿàŠ   ÿàŠ  ÿàŠÿàŠ   ÿàŠ   ÿàŠ   ÿàŠ ÿàŠ   ÿàŠ   ÿàŠ                ÿÿ          ?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1              É ÿ   É ÿ É ÿ   É ÿ É ÿ   É ÿ É ÿ                                                     ÿàŠ       ÿàŠ         ÿàŠ  ÿàŠ  ÿàŠ   ÿàŠ   ÿàŠ   ÿàŠ   ÿàŠ ÿàŠ   ÿàŠ   ÿàŠ                                                              ::U::U   ÿÿ             ?&1?&1?&1?&1?&1?&1?&1?&1                ÿàŠ  ÿàŠ  ÿàŠ   ÿàŠ   ÿàŠ   ÿàŠ   ÿàŠ ÿàŠ   ÿàŠ   ÿàŠ                ÿÿ          ?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1              É ÿ   É ÿ É ÿ   É ÿ É ÿ   É ÿ É ÿ                                                     ÿàŠ      ÿàŠÿàŠÿàŠ        ÿàŠ   ÿàŠ ÿàŠ   ÿàŠ  ÿàŠÿàŠÿàŠ   ÿàŠÿàŠÿàŠ  ÿàŠ   ÿàŠ   ÿàŠ                                                              ::U::U   ÿÿ         ?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1            ÿàŠ   ÿàŠ ÿàŠ   ÿàŠ  ÿàŠÿàŠÿàŠ   ÿàŠÿàŠÿàŠ  ÿàŠ   ÿàŠ   ÿàŠ                ÿÿ        ?&1?&1?&1?&1?&1?&1›L£›L£›L£›L£›L£›L£›L£›L£?&1?&1?&1?&1?&1?&1?&1?&1            É ÿ   É ÿ É ÿ   É ÿ  É ÿÉ ÿÉ ÿ  É ÿÉ ÿÉ ÿÉ ÿÉ ÿ                                                                                                                                                                  ::U::U   ÿÿ         ?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1                                                             ÿÿ        ?&1?&1?&1?&1?&1?&1›L£›L£›L£›L£›L£›L£›L£›L£?&1?&1?&1?&1?&1?&1?&1?&1                                                                                                                                                                                                     ::U::U   ÿÿ       ?&1?&1?&1?&1?&1?&1?&1?&1ÀËÜÀËÜÀËÜÀËÜ?&1?&1?&1?&1?&1?&1?&1?&1                                                           ÿÿ        ?&1?&1?&1?&1›L£›L£?&1?&1›L£›L£›L£›L£›L£›L£›L£›L£›L£›L£?&1?&1?&1?&1?&1?&1?&1?&1                                                                                                                                                                                                 ::U::U   ÿÿ       ?&1?&1?&1?&1?&1?&1?&1?&1ÀËÜÀËÜÀËÜÀËÜ?&1?&1?&1?&1?&1?&1?&1?&1                                                           ÿÿ        ?&1?&1?&1?&1›L£›L£?&1?&1›L£›L£›L£›L£›L£›L£›L£›L£›L£›L£?&1?&1?&1?&1?&1?&1?&1?&1                                                                                                                                                                                                 ::U::U   ÿÿ     ?&1?&1?&1?&1?&1?&1‹›´‹›´ÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜ‹›´‹›´?&1?&1?&1?&1?&1?&1                                                         ÿÿ        ?&1?&1?&1?&1?&1?&1?&1?&1›L£›L£›L£›L£›L£›L£›L£›L£›L£›L£›L£›L£?&1?&1?&1?&1?&1?&1?&1?&1                                                                                       ÿÿÿÿÿÿÿÿÿ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  ÿÿÿÿÿÿÿÿÿ   ÿÿÿÿÿÿÿÿÿ  ÿÿÿ   ÿÿÿ                                                                      ::U::U   ÿÿ     ?&1?&1?&1?&1?&1?&1‹›´‹›´ÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜ‹›´‹›´?&1?&1?&1?&1?&1?&1                                                         ÿÿ        ?&1?&1?&1?&1?&1?&1?&1?&1›L£›L£›L£›L£›L£›L£›L£›L£›L£›L£›L£›L£?&1?&1?&1?&1?&1?&1?&1?&1                                                                                      ÿÿÿ   ÿÿÿ   ÿÿÿ     ÿÿÿ   ÿÿÿ   ÿÿÿ ÿÿÿ   ÿÿÿ ÿÿÿ  ÿÿÿ                                                                       ::U::U   ÿÿ     ?&1?&1?&1?&1R`|R`|‹›´‹›´ÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜ‹›´‹›´R`|R`|?&1?&1?&1?&1                                                         ÿÿ        ?&1?&1?&1?&1›L£›L£ÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvЛL£›L£?&1?&1?&1?&1                                                                                      ÿÿÿ   ÿÿÿ   ÿÿÿ     ÿÿÿ   ÿÿÿ   ÿÿÿ ÿÿÿ     ÿÿÿ ÿÿÿ                                                                        ::U::U   ÿÿ     ?&1?&1?&1?&1R`|R`|‹›´‹›´ÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜ‹›´‹›´R`|R`|?&1?&1?&1?&1        ˆÿˆ   ˆÿˆ ˆÿˆˆÿˆˆÿˆˆÿˆ             ÿÿÿ   ÿÿÿÿÿÿÿÿÿ                   ÿÿ        ?&1?&1?&1?&1›L£›L£ÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvÐÑvЛL£›L£?&1?&1?&1?&1      ˆÿˆ   ˆÿˆ ˆÿˆˆÿˆˆÿˆˆÿˆ           ÿÿÿÿÿÿÿÿÿ   ÿÿÿÿÿÿÿÿÿ                                                  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ   ÿÿÿ     ÿÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿ     ÿÿÿÿÿÿ                                                                         ::U::U   ÿÿ     ?&1?&1?&1?&1‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´?&1?&1?&1?&1        ˆÿˆ   ˆÿˆ ˆÿˆ   ˆÿˆ           ÿÿÿÿÿÿ  ÿÿÿ   ÿÿÿ                  ÿÿ        ?&1?&1?&1?&1ÑvÐÑvЛL£›L£?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1›L£›L£ÑvÐÑvÐ?&1?&1?&1?&1      ˆÿˆ   ˆÿˆ ˆÿˆ   ˆÿˆ         ÿÿÿ   ÿÿÿ ÿÿÿ                                                     ÿÿÿ   ÿÿÿ   ÿÿÿ     ÿÿÿ   ÿÿÿ   ÿÿÿ ÿÿÿ     ÿÿÿ ÿÿÿ                                                                        ::U::U   ÿÿ     ?&1?&1?&1?&1‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´?&1?&1?&1?&1        ˆÿˆ   ˆÿˆ ˆÿˆ   ˆÿˆ          ÿÿÿ ÿÿÿ  ÿÿÿ  ÿÿÿÿÿÿ                  ÿÿ        ?&1?&1?&1?&1ÑvÐÑvЛL£›L£?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1›L£›L£ÑvÐÑvÐ?&1?&1?&1?&1      ˆÿˆ   ˆÿˆ ˆÿˆ   ˆÿˆ             ÿÿÿ ÿÿÿ                                                     ÿÿÿ   ÿÿÿ   ÿÿÿ     ÿÿÿ   ÿÿÿ   ÿÿÿ ÿÿÿ   ÿÿÿ ÿÿÿ  ÿÿÿ                                                                       ::U::U   ÿÿ     ?&1?&1?&1?&1‹›´‹›´‹›´‹›´?&1?&1‹›´‹›´?&1?&1‹›´‹›´?&1?&1‹›´‹›´?&1?&1?&1?&1        ˆÿˆˆÿˆˆÿˆˆÿˆˆÿˆ ˆÿˆˆÿˆˆÿˆˆÿˆ          ÿÿÿ  ÿÿÿ  ÿÿÿ ÿÿÿ ÿÿÿ                  ÿÿ        ?&1?&1?&1?&1›L£›L£‹›´‹›´÷‚÷‚÷‚÷‚÷‚÷‚÷‚÷‚÷‚÷‚÷‚÷‚‹›´‹›´›L£›L£?&1?&1?&1?&1      ˆÿˆˆÿˆˆÿˆˆÿˆˆÿˆ ˆÿˆˆÿˆˆÿˆˆÿˆ            ÿÿÿÿÿÿ  ÿÿÿÿÿÿÿÿÿÿÿÿ                                                  ÿÿÿ   ÿÿÿ   ÿÿÿ     ÿÿÿ   ÿÿÿ   ÿÿÿ  ÿÿÿÿÿÿÿÿÿ  ÿÿÿ   ÿÿÿ                                                                      ::U::U   ÿÿ     ?&1?&1?&1?&1‹›´‹›´‹›´‹›´?&1?&1‹›´‹›´?&1?&1‹›´‹›´?&1?&1‹›´‹›´?&1?&1?&1?&1        ˆÿˆ   ˆÿˆ ˆÿˆ             ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿ  ÿÿÿ                  ÿÿ        ?&1?&1?&1?&1›L£›L£‹›´‹›´÷‚÷‚÷‚÷‚÷‚÷‚÷‚÷‚÷‚÷‚÷‚÷‚‹›´‹›´›L£›L£?&1?&1?&1?&1      ˆÿˆ   ˆÿˆ ˆÿˆ              ÿÿÿ    ÿÿÿ   ÿÿÿ                                                                                                                                                          ::U::U   ÿÿ     ?&1?&1?&1?&1‹›´‹›´‹›´‹›´?&1?&1‹›´‹›´?&1?&1‹›´‹›´?&1?&1‹›´‹›´?&1?&1?&1?&1        ˆÿˆ   ˆÿˆ ˆÿˆ                ÿÿÿ  ÿÿÿ   ÿÿÿ                  ÿÿ        ?&1?&1?&1?&1?&1?&1‹›´‹›´÷‚÷‚&+D&+D&+D&+D÷‚÷‚&+D&+D&+D&+D÷‚÷‚?&1?&1?&1?&1?&1?&1      ˆÿˆ   ˆÿˆ ˆÿˆ             ÿÿÿ     ÿÿÿ   ÿÿÿ                                                                                                                                                          ::U::U   ÿÿ     ?&1?&1?&1?&1‹›´‹›´‹›´‹›´?&1?&1‹›´‹›´?&1?&1‹›´‹›´?&1?&1‹›´‹›´?&1?&1?&1?&1        ˆÿˆ   ˆÿˆ ˆÿˆ                ÿÿÿ   ÿÿÿÿÿÿÿÿÿ                   ÿÿ        ?&1?&1?&1?&1?&1?&1‹›´‹›´÷‚÷‚&+D&+D&+D&+D÷‚÷‚&+D&+D&+D&+D÷‚÷‚?&1?&1?&1?&1?&1?&1      ˆÿˆ   ˆÿˆ ˆÿˆ             ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  ÿÿÿÿÿÿÿÿÿ                                                                                                                                                           ::U::U   ÿÿ     ?&1?&1?&1?&1‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´?&1?&1?&1?&1                                                         ÿÿ        ?&1?&1?&1?&1?&1?&1?&1?&1÷‚÷‚÷‚÷‚ÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜ÷‚÷‚?&1?&1?&1?&1?&1?&1                                                                                                                                                                                                 ::U::U   ÿÿ     ?&1?&1?&1?&1‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´‹›´?&1?&1?&1?&1                                                         ÿÿ        ?&1?&1?&1?&1?&1?&1?&1?&1÷‚÷‚÷‚÷‚ÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜ÷‚÷‚?&1?&1?&1?&1?&1?&1                                                                                        ÿÿÿÿÿÿÿÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿ   ÿÿÿ ÿÿÿÿÿÿÿÿÿ                                                                        ::U::U   ÿÿ   ?&1?&1?&1?&1ÀËÜÀËÜÀËÜÀËÜ?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1ÀËÜÀËÜÀËÜÀËÜ?&1?&1?&1?&1                                                       ÿÿ      ?&1?&1?&1?&1?&1?&1?&1?&1›L£›L£÷‚÷‚‹›´‹›´÷‚÷‚÷‚÷‚÷‚÷‚‹›´‹›´›L£›L£?&1?&1?&1?&1?&1?&1                                                                                      ÿÿÿ  ÿÿÿ  ÿÿÿ     ÿÿÿ     ÿÿÿ     ÿÿÿÿÿÿ  ÿÿÿ ÿÿÿ  ÿÿÿ                                                                       ::U::U   ÿÿ   ?&1?&1?&1?&1ÀËÜÀËÜÀËÜÀËÜ?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1ÀËÜÀËÜÀËÜÀËÜ?&1?&1?&1?&1                                                       ÿÿ      ?&1?&1?&1?&1?&1?&1?&1?&1›L£›L£÷‚÷‚‹›´‹›´÷‚÷‚÷‚÷‚÷‚÷‚‹›´‹›´›L£›L£?&1?&1?&1?&1?&1?&1                                                                                      ÿÿÿ   ÿÿÿ ÿÿÿ     ÿÿÿ     ÿÿÿ     ÿÿÿ ÿÿÿ ÿÿÿ ÿÿÿ   ÿÿÿ                                                                      ::U::U   ÿÿ ?&1?&1?&1?&1?&1?&1ÀËÜÀËÜÀËÜÀËÜ‹›´‹›´ÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜ‹›´‹›´ÀËÜÀËÜÀËÜÀËÜ?&1?&1?&1?&1?&1?&1                                                     ÿÿ      ?&1?&1?&1?&1÷‚÷‚÷‚÷‚›L£›L£›L£›L£ÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜ›L£›L£÷‚÷‚÷‚÷‚?&1?&1?&1?&1                                                                                    ÿÿÿ   ÿÿÿ ÿÿÿÿÿÿÿÿÿ   ÿÿÿÿÿÿÿÿÿ   ÿÿÿÿÿÿÿÿÿ   ÿÿÿ ÿÿÿ ÿÿÿ ÿÿÿ   ÿÿÿ                                                                      ::U::U   ÿÿ ?&1?&1?&1?&1?&1?&1ÀËÜÀËÜÀËÜÀËÜ‹›´‹›´ÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜ‹›´‹›´ÀËÜÀËÜÀËÜÀËÜ?&1?&1?&1?&1?&1?&1    ˆªÿ   ˆªÿ ˆªÿˆªÿˆªÿˆªÿ           ÿÿÿÿÿÿÿÿÿ                         ÿÿ      ?&1?&1?&1?&1÷‚÷‚÷‚÷‚›L£›L£›L£›L£ÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜ›L£›L£÷‚÷‚÷‚÷‚?&1?&1?&1?&1    ˆªÿ   ˆªÿ ˆªÿˆªÿˆªÿˆªÿ            ÿÿÿ    ÿÿÿÿÿÿÿÿÿ                                                  ÿÿÿ   ÿÿÿ ÿÿÿ     ÿÿÿ     ÿÿÿ     ÿÿÿ  ÿÿÿÿÿÿ ÿÿÿ   ÿÿÿ                                                                      ::U::U   ÿÿ ?&1?&1?&1?&1R`|R`|R`|R`|‹›´‹›´‹›´‹›´ÀËÜÀËÜR`|R`|R`|R`|ÀËÜÀËÜ‹›´‹›´‹›´‹›´R`|R`|R`|R`|?&1?&1?&1?&1    ˆªÿˆªÿ ˆªÿˆªÿ ˆªÿ   ˆªÿ         ÿÿÿ   ÿÿÿ                        ÿÿ      ?&1?&1?&1?&1÷‚÷‚÷‚÷‚›L£›L£›L£›L£ÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜ›L£›L£÷‚÷‚÷‚÷‚?&1?&1?&1?&1    ˆªÿˆªÿ ˆªÿˆªÿ ˆªÿ   ˆªÿ          ÿÿÿÿÿÿ   ÿÿÿ                                                     ÿÿÿ  ÿÿÿ  ÿÿÿ     ÿÿÿ     ÿÿÿ     ÿÿÿ   ÿÿÿ ÿÿÿ  ÿÿÿ                                                                       ::U::U   ÿÿ ?&1?&1?&1?&1R`|R`|R`|R`|‹›´‹›´‹›´‹›´ÀËÜÀËÜR`|R`|R`|R`|ÀËÜÀËÜ‹›´‹›´‹›´‹›´R`|R`|R`|R`|?&1?&1?&1?&1    ˆªÿ ˆªÿ ˆªÿ ˆªÿ   ˆªÿ         ÿÿÿ   ÿÿÿ                        ÿÿ      ?&1?&1?&1?&1÷‚÷‚÷‚÷‚›L£›L£›L£›L£ÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜ›L£›L£÷‚÷‚÷‚÷‚?&1?&1?&1?&1    ˆªÿ ˆªÿ ˆªÿ ˆªÿ   ˆªÿ           ÿÿÿ   ÿÿÿ                                                     ÿÿÿÿÿÿÿÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿ     ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿ   ÿÿÿ ÿÿÿÿÿÿÿÿÿ                                                                        ::U::U   ÿÿ ?&1?&1?&1?&1R`|R`|R`|R`|?&1?&1½lJ½lJ½lJ½lJ½lJ½lJ½lJ½lJ½lJ½lJ½lJ½lJ?&1?&1R`|R`|R`|R`|?&1?&1?&1?&1    ˆªÿ ˆªÿ ˆªÿ ˆªÿˆªÿˆªÿˆªÿ           ÿÿÿÿÿÿÿÿÿ                         ÿÿ      ?&1?&1?&1?&1›L£›L£›L£›L£?&1?&1½lJ½lJÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜ?&1?&1›L£›L£›L£›L£?&1?&1?&1?&1    ˆªÿ ˆªÿ ˆªÿ ˆªÿˆªÿˆªÿˆªÿ            ÿÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                           ::U::U   ÿÿ ?&1?&1?&1?&1R`|R`|R`|R`|?&1?&1½lJ½lJ½lJ½lJ½lJ½lJ½lJ½lJ½lJ½lJ½lJ½lJ?&1?&1R`|R`|R`|R`|?&1?&1?&1?&1    ˆªÿ   ˆªÿ ˆªÿ             ÿÿÿ   ÿÿÿ                        ÿÿ      ?&1?&1?&1?&1›L£›L£›L£›L£?&1?&1½lJ½lJÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜ?&1?&1›L£›L£›L£›L£?&1?&1?&1?&1    ˆªÿ   ˆªÿ ˆªÿ               ÿÿÿ   ÿÿÿ   ÿÿÿ                                                                                                                                                          ::U::U   ÿÿ ?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1R`|R`|R`|R`|?&1?&1?&1?&1R`|R`|R`|R`|?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1    ˆªÿ   ˆªÿ ˆªÿ             ÿÿÿ   ÿÿÿ                        ÿÿ      ?&1?&1?&1?&1›L£›L£›L£›L£?&1?&1›L£›L£›L£›L£ÀËÜÀËÜÀËÜÀËܪ·Ìª·Ì›L£›L£?&1?&1›L£›L£›L£›L£?&1?&1?&1?&1    ˆªÿ   ˆªÿ ˆªÿ               ÿÿÿ   ÿÿÿ   ÿÿÿ                                                                                                                                                          ::U::U   ÿÿ ?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1R`|R`|R`|R`|?&1?&1?&1?&1R`|R`|R`|R`|?&1?&1?&1?&1?&1?&1?&1?&1?&1?&1    ˆªÿ   ˆªÿ ˆªÿ              ÿÿÿÿÿÿÿÿÿ                         ÿÿ      ?&1?&1?&1?&1›L£›L£›L£›L£?&1?&1›L£›L£›L£›L£ÀËÜÀËÜÀËÜÀËܪ·Ìª·Ì›L£›L£?&1?&1›L£›L£›L£›L£?&1?&1?&1?&1    ˆªÿ   ˆªÿ ˆªÿ              ÿÿÿÿÿÿÿÿÿ   ÿÿÿÿÿÿÿÿÿ                                                                                                                                                           ::U::U   ÿÿ   ?&1?&1?&1?&1?&1?&1?&1?&1ÀËÜÀËÜÀËÜÀËÜ?&1?&1?&1?&1ÀËÜÀËÜÀËÜÀËÜ?&1?&1?&1?&1?&1?&1?&1?&1                                                       ÿÿ        ?&1?&1?&1?&1?&1?&1›L£›L£›L£›L£ÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜ›L£›L£›L£›L£?&1?&1?&1?&1?&1?&1?&1?&1                                                                                       ÿÿÿÿÿÿÿÿÿ  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿ   ÿÿÿ                   www   www    ÿÒJÿÒJÿÒJ                                                   ::U::U   ÿÿ   ?&1?&1?&1?&1?&1?&1?&1?&1ÀËÜÀËÜÀËÜÀËÜ?&1?&1?&1?&1ÀËÜÀËÜÀËÜÀËÜ?&1?&1?&1?&1?&1?&1?&1?&1                                                       ÿÿ        ?&1?&1?&1?&1?&1?&1›L£›L£›L£›L£ÀËÜÀËÜÀËÜÀËÜÀËÜÀËÜ›L£›L£›L£›L£?&1?&1?&1?&1?&1?&1?&1?&1                                                                             ÿÿ          ÿÿÿ     ÿÿÿ   ÿÿÿ     ÿÿÿÿÿÿ ÿÿÿÿÿÿ                   www   www   ÿÒJ   ÿÒJ                                                  ::U::U   ÿÿ                                                                                      ÿÿ                                                                                                                  ÿÿ         ÿÿÿ     ÿÿÿ   ÿÿÿ     ÿÿÿ ÿÿÿ ÿÿÿ                    www www        ÿÒJ                                                  ::U::U   ÿÿ                                                                                      ÿÿ                                                                                                                   ÿÿ        ÿÿÿ     ÿÿÿ   ÿÿÿÿÿÿÿÿÿ   ÿÿÿ ÿÿÿ ÿÿÿ                     www       ÿÒJÿÒJ                                                   ::U::U   ÿÿ                                                                                      ÿÿ                                                                                                                  ÿÿ         ÿÿÿ     ÿÿÿ   ÿÿÿ     ÿÿÿ   ÿÿÿ                    www www     ÿÒJ                                                     ::U::U   ÿÿ                                                                                      ÿÿ                                                                                                                 ÿÿ          ÿÿÿ     ÿÿÿ   ÿÿÿ     ÿÿÿ   ÿÿÿ                   www   www   ÿÒJ                                                      ::U::U   ÿÿ                                                                                      ÿÿ                                                                                                                           ÿÿÿÿÿÿÿÿÿ    ÿÿÿ   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿ   ÿÿÿ                   www   www   ÿÒJÿÒJÿÒJÿÒJÿÒJ                                                  ::U::U   ÿÿ                                                                                      ÿÿ                                                                                                                                                                                                                                   ::U::U   ÿÿ                                                                                      ÿÿ                                                                                                                                                                                                                                   ::U::U   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ                                                                                                                                                                                                                                   ::U::U                                                                                                                                                                                                                                                                                                                              ::U::U                                                                                                                                                                                                                     ÿÿÿÿÿÿÿÿÿÿÿÿ  ÿÿÿ   ÿÿÿ ÿÿÿ   ÿÿÿ                                                                                        ::U::U                                                                                                                                                                                                                     ÿÿÿ   ÿÿÿ ÿÿÿ   ÿÿÿ ÿÿÿÿÿÿ  ÿÿÿ                                                                                        ::U::U                                                                                                                                                                                                                     ÿÿÿ   ÿÿÿ ÿÿÿ   ÿÿÿ ÿÿÿ ÿÿÿ ÿÿÿ                                                                                        ::U::U                                                                                                                                                                                                                     ÿÿÿÿÿÿÿÿÿÿÿÿ  ÿÿÿ   ÿÿÿ ÿÿÿ ÿÿÿ ÿÿÿ                                                                                        ::U::U                                                                                                                                                                                                                     ÿÿÿ ÿÿÿ   ÿÿÿ   ÿÿÿ ÿÿÿ  ÿÿÿÿÿÿ                                                                                        ::U::U                                                                                                                                                                                                                     ÿÿÿ  ÿÿÿ  ÿÿÿ   ÿÿÿ ÿÿÿ   ÿÿÿ                                                                                        ::U::U                                                                                                                                                                                                                     ÿÿÿ   ÿÿÿ  ÿÿÿÿÿÿÿÿÿ  ÿÿÿ   ÿÿÿ                                                                                        ::U::U                                                                                                                                                                                                                                                                                                                              ::U::U                                                                                                                                                                                                                                                                                                                              ::U::U                                                                                                                                                                                                                                                                                                                              ::U::U                                                                                                                                                                                                                                                                                                                              ::U::U                                                                                                                                                                                                                                                                                                                              ::U::U                                                                                                                                                                                                                                                                                                                              ::U::U                                                                                                                                                                                                                                                                                                                              ::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U::U \ No newline at end of file diff --git a/selfhost/golden/menu.ppm b/selfhost/golden/menu.ppm new file mode 100644 index 00000000..4514adf2 --- /dev/null +++ b/selfhost/golden/menu.ppm @@ -0,0 +1,4 @@ +P6 +320 240 +255 +ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&IB2–…Fº¤NìÐ[ñÔ\¿¨P›‰GIB2&&&&&&&zm?ƒuAPH4&&&&&&&&&j^:ƒuA_U8&&&&~p?ƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuARJ5&&&&&&&&&&&HA2—†Fº¤NïÒ\ñÔ\ɱR¦“IcY9&&&&&&&&ƒuAƒuAf[:&&&&&&&&&dZ9ƒuA[R7&&&&&&&&HA2—†Fº¤NïÒ\ñÔ\ɱR¦“IcY9&&&&&&&&&&&&&&&~p?ƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuARJ5&&&&&&&TK5ƒuAvi>&&&&uh=ƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuA`V8&@:0ƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuA<7/&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&50-º¤NñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\«—K! (&&&&&ßÄXñÔ\Š{C&&&&&&&&&¾§OñÔ\¨”J&&&&æÊYñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ÔºU@;0&&&&&&&+(+´ŸMñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\Ò¹TJC2&&&&&&ñÔ\ñÔ\ðÓ\KD3&&&&&&&&³žMñÔ\ ŽH&&&&&&+(+´ŸMñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\Ò¹TJC2&&&&&&&&&&&&&æÊYñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ÔºU@;0&&&&&’�DñÔ\×½V&&&&ÔºUñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\«—K&j^:ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\bX9&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&A<0ãÈYñÔ\ðÓ\ ŽH]S7LE3LE3cY9·¢NñÔ\ñÔ\ìQ'&&&&ßÄXñÔ\Š{C&&&&&&&&&¾§OñÔ\¨”J&&&&æÊYñÔ\º¤NƒuAƒuAƒuAƒuAƒuAƒuAƒuAÅ®QñÔ\ñÔ\ÞÃW*'+&&&&&62.ÛÁWñÔ\ñÔ\¸£Nj^:LE3LE3YP6�‹GíÐ[ñÔ\îÑ[dZ9&&&&&ñÔ\ñÔ\ñÔ\Õ¼U(&&&&&&&³žMñÔ\ ŽH&&&&&62.ÛÁWñÔ\ñÔ\¸£Nj^:LE3LE3YP6�‹GíÐ[ñÔ\îÑ[dZ9&&&&&&&&&&&&æÊYñÔ\º¤NƒuAƒuAƒuAƒuAƒuAƒuAƒuAÅ®QñÔ\ñÔ\ÞÃW*'+&&&&’�DñÔ\×½V&&&&ÔºUñÔ\ìQƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuA`V8&@:0ƒuAƒuAƒuAƒuAƒuAŸŒHñÔ\ñÔ\™ˆFƒuAƒuAƒuAƒuAƒuA<7/&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&$*ÜÁWñÔ\ÛÁWA<0&&&&&&yl>ñÔ\ñÔ\�€D&&&&ßÄXñÔ\Š{C&&&&&&&&&¾§OñÔ\¨”J&&&&æÊYñÔ\ƒuA&&&&&&&&vi>ñÔ\ñÔ\ŠzB&&&& (ÔºUñÔ\åÉY[R7&&&&&&62.͵SñÔ\íÐ[G@2&&&&ñÔ\ñÔ\ñÔ\ñÔ\•„E&&&&&&&³žMñÔ\ ŽH&&&& (ÔºUñÔ\åÉY[R7&&&&&&62.͵SñÔ\íÐ[G@2&&&&&&&&&&&æÊYñÔ\ƒuA&&&&&&&&vi>ñÔ\ñÔ\ŠzB&&&&’�DñÔ\×½V&&&&ÔºUñÔ\•„E&&&&&&&&&&&&&&&&&LE3ñÔ\ñÔ\A<0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&•„EñÔ\ìÐ[@:0&&&&&&&&­™KñÔ\ëÏ[)&*&&&ßÄXñÔ\Š{C&&&&&&&&&¾§OñÔ\¨”J&&&&æÊYñÔ\ƒuA&&&&&&&&&ʲSñÔ\ǯR&&&&Œ|CñÔ\îÑ[JC3&&&&&&&&+(+ÜÁWñÔ\ʲR&&&&ñÔ\ñÔ\Ó¹UñÔ\ñÔ\LE3&&&&&&³žMñÔ\ ŽH&&&&Œ|CñÔ\îÑ[JC3&&&&&&&&+(+ÜÁWñÔ\ʲR&&&&&&&&&&&æÊYñÔ\ƒuA&&&&&&&&&ʲSñÔ\ǯR&&&&’�DñÔ\×½V&&&&ÔºUñÔ\•„E&&&&&&&&&&&&&&&&&LE3ñÔ\ñÔ\A<0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&! (éÍZñÔ\›‰G&&&&&&&&&A<0æÊY³žM;6/&&&ßÄXñÔ\Š{C&&&&&&&&&¾§OñÔ\¨”J&&&&æÊYñÔ\ƒuA&&&&&&&&&¥’IñÔ\Ù¿V&&& (æÊYñÔ\�‹G&&&&&&&&&&g\:ñÔ\ñÔ\UM5&&&ñÔ\ñÔ\g\:Ó¹UñÔ\Õ¼U(&&&&&³žMñÔ\ ŽH&&& (æÊYñÔ\�‹G&&&&&&&&&&g\:ñÔ\ñÔ\UM5&&&&&&&&&&æÊYñÔ\ƒuA&&&&&&&&&¥’IñÔ\Ù¿V&&&&’�DñÔ\×½V&&&&ÔºUñÔ\•„E&&&&&&&&&&&&&&&&&LE3ñÔ\ñÔ\A<0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&^T7ñÔ\ñÔ\MF3&&&&&&&&&&&&&&&&ßÄXñÔ\Š{C&&&&&&&&&¾§OñÔ\¨”J&&&&æÊYñÔ\ƒuA&&&&&&&&&ʲSñÔ\Å®Q&&&[R7ñÔ\ñÔ\JC2&&&&&&&&&&'äÉYñÔ\ŸŒH&&&ñÔ\ñÔ\_U8JC2ðÓ\ñÔ\•„E&&&&&³žMñÔ\ ŽH&&&[R7ñÔ\ñÔ\JC2&&&&&&&&&&'äÉYñÔ\ŸŒH&&&&&&&&&&æÊYñÔ\ƒuA&&&&&&&&&ʲSñÔ\Å®Q&&&&’�DñÔ\×½V&&&&ÔºUñÔ\•„E&&&&&&&&&&&&&&&&&LE3ñÔ\ñÔ\A<0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&‹|CñÔ\îÑ['&&&&&&&&&&&&&&&&ßÄXñÔ\Š{C&&&&&&&&&¾§OñÔ\¨”J&&&&æÊYñÔ\ƒuA&&&&&&&&yl>ñÔ\ñÔ\q@&&&Š{CñÔ\ëÏ['&&&&&&&&&&&­™KñÔ\зT&&&ñÔ\ñÔ\_U8&’�DñÔ\ñÔ\LE3&&&&³žMñÔ\ ŽH&&&Š{CñÔ\ëÏ['&&&&&&&&&&&­™KñÔ\зT&&&&&&&&&&æÊYñÔ\ƒuA&&&&&&&&yl>ñÔ\ñÔ\q@&&&&’�DñÔ\×½V&&&&ÔºUñÔ\•„E&&&&&&&&&&&&&&&&&LE3ñÔ\ñÔ\A<0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&¥’IñÔ\Ö½U&&&&&&&&&&&&&&&&&ßÄXñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\¨”J&&&&æÊYñÔ\º¤NƒuAƒuAƒuAƒuAƒuAƒuAƒuA˳SñÔ\ñÔ\ʲR(&&&¨”JñÔ\Ó¹U&&&&&&&&&&&&Œ|CñÔ\ìÐ[&&&ñÔ\ñÔ\_U8&(Ó¹UñÔ\Õ¼U (&&&³žMñÔ\ ŽH&&&¨”JñÔ\Ó¹U&&&&&&&&&&&&Œ|CñÔ\ìÐ[&&&&&&&&&&æÊYñÔ\º¤NƒuAƒuAƒuAƒuAƒuAƒuAƒuA˳SñÔ\ñÔ\ʲR(&&&&’�DñÔ\×½V&&&&ÔºUñÔ\ÚÀVº¤Nº¤Nº¤Nº¤Nº¤Nº¤Nº¤Nº¤NJC2&&&&&&&&LE3ñÔ\ñÔ\A<0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&­™KñÔ\Ì´S&&&&&&&&&&&&&&&&&ßÄXñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\¨”J&&&&æÊYñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\¢�I$")&&&&´ŸMñÔ\Å®Q&&&&&&&&&&&&€r@ñÔ\ñÔ\(&&ñÔ\ñÔ\_U8&&G@2ïÒ\ñÔ\™ˆF&&&³žMñÔ\ ŽH&&&´ŸMñÔ\Å®Q&&&&&&&&&&&&€r@ñÔ\ñÔ\(&&&&&&&&&æÊYñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\¢�I$")&&&&&’�DñÔ\×½V&&&&ÔºUñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ñÔ\[R7&&&&&&&&LE3ñÔ\ñÔ\A<0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&¦“IñÔ\ÔºU&&&&&&&&&&&&&&&&&ßÄXñÔ\¤‘ILE3LE3LE3LE3LE3LE3LE3LE3LE3ʲSñÔ\¨”J&&&&æÊYñÔ\Õ¼Uº¤Nº¤Nº¤NÀªPñÔ\ñÔ\éÌZyl>-*+&&&&&&²�LñÔ\ǯR&&&&&&&&&&&&„uAñÔ\ðÓ\'&&ñÔ\ñÔ\_U8&&&Ž~DñÔ\ñÔ\PH4&&³žMñÔ\ ŽH&&&²�LñÔ\ǯR&&&&&&&&&&&&„uAñÔ\ðÓ\'&&&&&&&&&æÊYñÔ\Õ¼Uº¤Nº¤Nº¤NÀªPñÔ\ñÔ\éÌZyl>-*+&&&&&&&’�DñÔ\×½V&&&&ÔºUñÔ\ìQƒuAƒuAƒuAƒuAƒuAƒuAƒuAƒuA84.&&&&&&&&LE3ñÔ\ñÔ\A<0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&Ž~DñÔ\èÌZ&&&&&&&&&&&&&&&&&ßÄXñÔ\Š{C&&&&&&&&&¾§OñÔ\¨”J&&&&æÊYñÔ\ƒuA&&&&50-ȰRñÔ\àÅXJC2&&&&&&œŠGñÔ\ÛÁW&&&&&&&&&&&&œŠGñÔ\ßÄX&&&ñÔ\ñÔ\_U8&&&'зTñÔ\×½V (&³žMñÔ\ ŽH&&&œŠGñÔ\ÛÁW&&&&&&&&&&&&œŠGñÔ\ßÄX&&&&&&&&&&æÊYñÔ\ƒuA&&&&50-ȰRñÔ\àÅXJC2&&&&&&&’�DñÔ\×½V&&&&ÔºUñÔ\•„E&&&&&&&&&&&&&&&&&LE3ñÔ\ñÔ\A<0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&f[:ñÔ\ñÔ\73.&&&&&&&&&&dZ9E?1&&&&ßÄXñÔ\Š{C&&&&&&&&&¾§OñÔ\¨”J&&&&æÊYñÔ\ƒuA&&&&&'%*Ô»UñÔ\çËZ=8/&&&&&pd<ñÔ\ñÔ\-*+&&&&&&&&&&&ɱRñÔ\µ M&&&ñÔ\ñÔ\_U8&&&&G@2ïÒ\ñÔ\™ˆF&³žMñÔ\ ŽH&&&pd<ñÔ\ñÔ\-*+&&&&&&&&&&&ɱRñÔ\µ M&&&&&&&&&&æÊYñÔ\ƒuA&&&&&'%*Ô»UñÔ\çËZ=8/&&&&&&’�DñÔ\×½V&&&&ÔºUñÔ\•„E&&&&&&&&&&&&&&&&&LE3ñÔ\ñÔ\A<0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&+(+ïÒ\ñÔ\{m?&&&&&&&&& (èÌZñÔ\žŒG&&&ßÄXñÔ\Š{C&&&&&&&&&¾§OñÔ\¨”J&&&&æÊYñÔ\ƒuA&&&&&&D>1íÐ[ñÔ\Ò¹T(&&&&0,,ðÓ\ñÔ\yl>&&&&&&&&&&:5/ñÔ\ñÔ\ui=&&&ñÔ\ñÔ\_U8&&&&&Ž~DñÔ\ñÔ\PH4³žMñÔ\ ŽH&&&0,,ðÓ\ñÔ\yl>&&&&&&&&&&:5/ñÔ\ñÔ\ui=&&&&&&&&&&æÊYñÔ\ƒuA&&&&&&D>1íÐ[ñÔ\Ò¹T(&&&&&’�DñÔ\×½V&&&&ÔºUñÔ\•„E&&&&&&&&&&&&&&&&&LE3ñÔ\ñÔ\A<0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&³žMñÔ\Ù¿V(&&&&&&&&wj>ñÔ\ñÔ\QI4&&&ßÄXñÔ\Š{C&&&&&&&&&¾§OñÔ\¨”J&&&&æÊYñÔ\ƒuA&&&&&&&‡xBñÔ\ñÔ\‘€D&&&&&¯›LñÔ\ßÄX(%*&&&&&&&&&±œLñÔ\èÌZ'%*&&&ñÔ\ñÔ\_U8&&&&&'зTñÔ\×½V¾§OñÔ\ ŽH&&&&¯›LñÔ\ßÄX(%*&&&&&&&&&±œLñÔ\èÌZ'%*&&&&&&&&&&æÊYñÔ\ƒuA&&&&&&&‡xBñÔ\ñÔ\‘€D&&&&&’�DñÔ\×½V&&&&ÔºUñÔ\•„E&&&&&&&&&&&&&&&&&LE3ñÔ\ñÔ\A<0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&HA2ñÔ\ñÔ\§“J&&&&&&&@:0èÌZñÔ\Å®Q&&&&ßÄXñÔ\Š{C&&&&&&&&&¾§OñÔ\¨”J&&&&æÊYñÔ\ƒuA&&&&&&&'ζSñÔ\ïÒ\C=1&&&&:5/êÎZñÔ\ÁªP"!)&&&&&&&Œ|CñÔ\ñÔ\q@&&&&ñÔ\ñÔ\_U8&&&&&&G@2ïÒ\ñÔ\ñÔ\ñÔ\ ŽH&&&&:5/êÎZñÔ\ÁªP"!)&&&&&&&Œ|CñÔ\ñÔ\q@&&&&&&&&&&&æÊYñÔ\ƒuA&&&&&&&'ζSñÔ\ïÒ\C=1&&&&’�DñÔ\×½V&&&&ÔºUñÔ\•„E&&&&&&&&&&&&&&&&&LE3ñÔ\ñÔ\A<0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&�€DñÔ\ñÔ\ÁªPRJ5&&&(vi>æÊYñÔ\èÌZ=8/&&&&ßÄXñÔ\Š{C&&&&&&&&&¾§OñÔ\¨”J&&&&æÊYñÔ\ƒuA&&&&&&&&IB2ñÔ\ñÔ\ʲR'&&&&g\:ñÔ\ñÔ\×½VdZ9&&&&G@2¶¡NñÔ\ñÔ\³žM&&&&&ñÔ\ñÔ\_U8&&&&&&&Ž~DñÔ\ñÔ\ñÔ\ ŽH&&&&&g\:ñÔ\ñÔ\×½VdZ9&&&&G@2¶¡NñÔ\ñÔ\³žM&&&&&&&&&&&&æÊYñÔ\ƒuA&&&&&&&&IB2ñÔ\ñÔ\ʲR'&&&’�DñÔ\×½V&&&&ÔºUñÔ\•„E&&&&&&&&&&&&&&&&&LE3ñÔ\ñÔ\A<0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&–…FñÔ\ñÔ\ñÔ\éÌZº¤NÀªPñÔ\ñÔ\ñÔ\âÇXMF3&&&&&ßÄXñÔ\Š{C&&&&&&&&&¾§OñÔ\¨”J&&&&æÊYñÔ\ƒuA&&&&&&&&&™ˆFñÔ\ñÔ\q@&&&&&aW8åÉYñÔ\ñÔ\ñÔ\¿©Pº¤NåÉYñÔ\ñÔ\ñÔ\ŸŒH'&&&&&ñÔ\ñÔ\_U8&&&&&&&'зTñÔ\ñÔ\ ŽH&&&&&&aW8åÉYñÔ\ñÔ\ñÔ\¿©Pº¤NåÉYñÔ\ñÔ\ñÔ\ŸŒH'&&&&&&&&&&&&æÊYñÔ\ƒuA&&&&&&&&&™ˆFñÔ\ñÔ\q@&&&’�DñÔ\×½V&&&&ÔºUñÔ\•„E&&&&&&&&&&&&&&&&&LE3ñÔ\ñÔ\A<0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&TK5·¢NñÔ\ñÔ\ñÔ\ñÔ\ñÔ\èÌZšˆF+(+&&&&&&ßÄXñÔ\Š{C&&&&&&&&&¾§OñÔ\¨”J&&&&æÊYñÔ\ƒuA&&&&&&&&&"!)ÛÁWñÔ\êÎZ51-&&&&&+)+•„EáÆXñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ª–JKD3&&&&&&&ñÔ\ñÔ\_U8&&&&&&&&G@2îÑ[ñÔ\ ŽH&&&&&&&+)+•„EáÆXñÔ\ñÔ\ñÔ\ñÔ\ñÔ\ª–JKD3&&&&&&&&&&&&&&æÊYñÔ\ƒuA&&&&&&&&&"!)ÛÁWñÔ\êÎZ51-&&’�DñÔ\×½V&&&&ÔºUñÔ\•„E&&&&&&&&&&&&&&&&&LE3ñÔ\ñÔ\A<0&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'LE3LE3LE3IB2&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&?90LE3LE3LE3&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&?90LE3LE3LE3&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&Ž“¹AC[&&&&&&&&&&&&&&&&&&KNhuyš&0’—¾()<&&&&&&&&&&&&&&&&&&&&&&&&&68N56L&&&&&&&&&0’—¾()<&&&&&&&&&&&&&&&&&&&&&KNhuyš&&&&&&&ƒˆ¬ILe&&&&?AXŽ“¹&&jnŽbf„&&&&&&&&&&KNhuyš&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&Ž“¹AC[&&&&&&&&&&&&&&&&&&KNhuyš&+TVr1&&&&&&&&&&&&&&&&&&&&&&&&&„§CE]&&&&&&&&&+TVr1&&&&&&&&&&&&&&&&&&&&&KNhuyš&&&&&&&ƒˆ¬ILe&&&&?AXŽ“¹&&jnŽbf„&&&&&&&&&&KNhuyš&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&,-AILeKNh*+>&&&&&&&Ž“¹AC[&&&&&)56L*&&#$6-.C&&&+,@MOi,-AKNhuyš&(56L+&&&&9EG`;&&%%8DF_>@W0&&-.B„‰­WZv()<&&,-AILeKNh*+>&&(56L+(56L&13HORl*+>&&&&%%8DF_>@W0&&&&+,@MOi,-AKNhuyš&&&&&&&ƒˆ¬ILe&&&&?AXŽ“¹&&jnŽbf„&&&&&&&+,@MOi,-AKNhuyš&&&%%8DF_>@W0&&(56L&:‘—½./D&*z¡uyš&0’—¾()<#$6�•»9:Q&&imŒae‚&&&& 2’—¾TVr&&#$7�”º68N&&QTo|�£&&„§CE]&"#5Š�µ&':&&Y\ytx™&0’—¾()<0’—¾UXt&&]`}sw˜&#$7�”º68N&&QTo|�£&)*>‘—½./D&*z¡uyš&&&&&&&ƒˆ¬ILe&&&&?AXŽ“¹&&jnŽbf„&&&&&)*>‘—½./D&*z¡uyš&#$7�”º68N&&QTo|�£&0’—¾SVq&&ƒˆ¬v{œ&&\`}jnŽ&+,@’—¾56L&&VYtƒˆ¬'&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&'56L@BZos“x}Ÿ&&&&&&Ž“¹AC[&&&&&""5’—¾$%7&&KNhuyš&KMg}�¤&&&NPkuyš&0’—¾()&&VYu’—¾lp�,uyšˆŽ³uyš~ƒ¦PSmŒ‘¶+0’—¾()<0’—¾()<&&GIb{€¢&&12G�†©�’¸Œ‘·„§)*>&&56L…Š®Š�´Œ‘¶ad‚uyš&&&&&&&&PSmŠ�µ’—¾’—¾�“¸TWr&&&jnŽbf„&&&&&&56L…Š®Š�´Œ‘¶ad‚uyš&&12G�†©�’¸Œ‘·„§)*>&0’—¾()<&&sw˜ORm&&MPjsw˜&&57Lƒˆ¬‰�´‘—½qu–#$6&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&0#$6&&&&&&&&&&&&&&&&&&&)*>&&&&&&&#$6&&&&&&&&&&%%8)&&&&&&&&&&&&&&!!3"#5&&&&&&&&&0#$6&&&&&&&&&&&&&&&&&&!!3"#5&&&&&&#$6&&&&&&&&&&&&&*+?,-A&&&&&&&&&&&&&&&#$6&&&&&&&!!3"#5&&&&&&&&&&&&&&&&&&$%7,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ­­²µµºˆˆˆˆˆ‹‹“»»À��•ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ€€ˆ§§­»»ÀÔÔ×»»À©©¯€€‰ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÛÛÝ÷÷ø¯¯´ˆˆˆˆ——ž÷÷ø››¢ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ••œææè÷÷øÜÜÞÙÙÜÛÛÝ÷÷øääæ��–ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÛÛÝ÷÷øññò��•ˆˆˆ——ž÷÷ø››¢ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ�ììîááã��–ˆˆˆ‘‘™èèêÛÛ݈ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÛÛÝØØÛììí××Úˆˆˆ——ž÷÷ø››¢ˆˆˆ„„Œªª°»»À§§­€€‰ˆˆšš¡��–ˆˆˆœœ£��—ˆˆˆœœ£ŠŠ’ˆˆˆˆˆÂÂÆóóôŒŒ”ˆˆˆˆˆ¦¦¬ññò‹‹“ˆˆŒŒ”®®´»»À²²·ŽŽ–ˆˆˆ››¢ˆˆ�‘‘™ºº¿±±·‡‡�ˆ‘‘˜¹¹¾©©¯‚‚‹ˆˆˆ„„Œªª°»»À§§­€€‰ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÛÛÝÏÏÒ¥¥«÷÷ø±±¶ˆˆ——ž÷÷ø››¢ˆˆ••�ëëíèèêÙÙÜééëääæ��•ˆÓÓÖÔÔ׈ˆ‘‘˜÷÷øÓÓÖˆˆ““š÷÷ø““›ˆˆˆˆˆëëìÏÏÒˆˆˆˆˆˆˆˆˆˆ««±õõöààâÙÙÜééëõõö¢¢¨ˆˆïïðÎÎÒððñÙÙÜððñååç±±·ììíÙÙÜôôõÞÞà€€ˆˆ••�ëëíèèêÙÙÜééëääæ��•ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÛÛÝÏÏÒˆÍÍÐòòóŽŽ–ˆ——ž÷÷ø››¢ˆ€€‰ææèÖÖÙƒƒ‹ˆ††ŽÞÞáÕÕØˆ®®´òòó‚‚Šˆ±±¶ññòññò��‰ˆ¶¶»ææèˆˆˆˆˆˆˆ�÷÷ø··¼ˆˆˆˆˆˆˆˆˆƒƒŒððñ¿¿Äˆˆ��ŠããåÒÒÕˆˆïïðëë쉉‘ˆœœ£÷÷øãã円�ˆ¤¤«÷÷ø——ž€€‰ææèÖÖÙƒƒ‹ˆ††ŽÞÞáÕÕØˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÛÛÝÏÏÒˆˆˆ�ììíÙÙ܈——ž÷÷ø››¢ˆ››¢÷÷ø››¢ˆˆˆ©©¯öö÷ˆˆ�ŠŠ’öö÷ŸŸ¥ˆÑÑÔÃÃÇöö÷™™ ˆÚÚÜÀÀňˆˆˆˆŽŽ–÷÷ø²²¸ˆˆˆ££©ÙÙÜÙÙÜÙÙÜÙÙܦ¦¬ˆ––�††Žˆˆƒƒ‹××ÚÚÚ݈ˆïïðÂÂLjˆ��Š÷÷ø··¼ˆˆŒŒ”÷÷ø  §››¢÷÷ø››¢ˆˆˆ©©¯öö÷ˆˆ�ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÛÛÝÏÏÒˆˆ¥¥«÷÷ø±±¶——ž÷÷ø››¢ˆ¬¬²÷÷ø÷÷ø÷÷ø÷÷ø÷÷ø÷÷ø÷÷ø˜˜ŸˆÝÝß¿¿Ä��‰ññò››¢ááã¹¹¾‡‡�õõö››¢ˆˆˆˆˆ„„�öö÷¾¾Ãˆˆˆ——ž»»À»»À½½Á÷÷ø³³¸ˆŠŠ’½½ÁÙÙÜççé÷÷øóóôÛÛ݈ˆïïð¶¶»ˆˆˆ÷÷ø­­²ˆˆ‹‹“÷÷ø¡¡§¬¬²÷÷ø÷÷ø÷÷ø÷÷ø÷÷ø÷÷ø÷÷ø˜˜Ÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÛÛÝÏÏÒˆˆˆÍÍÐòò󦦬÷÷ø››¢ˆªª°÷÷ø¥¥«��¤��¤��¤��¤��¤……Žˆ¸¸½ááã››¢ññò��‰ÁÁÅ××Ú©©¯ììˆˆˆˆˆˆˆÞÞááá㈈ˆˆˆˆƒƒ‹÷÷ø³³¸‡‡�êêìääæ»»À��¤‰‰‘ÎÎÑÛÛ݈ˆïï𵵺ˆˆˆ÷÷ø­­²ˆˆ‹‹“÷÷ø¡¡§ªª°÷÷ø¥¥«��¤��¤��¤��¤��¤……Žˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÛÛÝÏÏÒˆˆˆˆˆ�ëëìêêë÷÷ø››¢ˆ••œ÷÷ø¦¦¬ˆˆˆ££ª¾¾ÂƒƒŒˆ““›öö÷ÄÄÈÓÓÖˆ¡¡§óóôÑÑÔÈÈ̈ˆˆˆˆˆˆ¨¨®÷÷ø··¼ˆˆˆˆˆ��•÷÷ø³³¸ªª°÷÷ø��—ˆˆˆààâÛÛÞˆˆïï𵵺ˆˆˆ÷÷ø­­²ˆˆ‹‹“÷÷ø¡¡§••œ÷÷ø¦¦¬ˆˆˆ££ª¾¾ÂƒƒŒˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÛÛÝÏÏÒˆˆˆˆ££©÷÷ø÷÷ø››¢ˆˆ××Úêê윜£ˆ••œêêëÕÕØˆˆˆççéôôõ³³¹ˆ„„Œôôõ÷÷ø¢¢©ˆˆˆˆˆˆˆˆÈÈÌ÷÷øÒÒÕ¤¤ª��¤žž¤ÄÄÈððñððñ��¤žž¥÷÷ø¯¯µˆ„„Œ¾¾Ã÷÷øàà㈈ïï𵵺ˆˆˆ÷÷ø­­²ˆˆ‹‹“÷÷ø¡¡§ˆ××Úêê윜£ˆ••œêêëÕÕØˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÛÛÝÏÏÒˆˆˆˆˆËËÎ÷÷ø››¢ˆˆ‡‡�ÑÑÕ÷÷ø÷÷ø÷÷øÖÖÙ††ŽˆˆˆÂÂÆ÷÷ø••œˆˆÙÙÜññò‚‚‹ˆˆˆˆˆˆˆˆˆ©©¯ääæ÷÷ø÷÷ø÷÷øîîðÅÅÉŠŠ’ˆˆÃÃÇ÷÷ø÷÷ø÷÷øÉÉÍ··¼òòó„„�ˆïï𵵺ˆˆˆ÷÷ø­­²ˆˆ‹‹“÷÷ø¡¡§ˆ‡‡�ÑÑÕ÷÷ø÷÷ø÷÷øÖÖÙ††Žˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ……Ž��¤††�ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ‡‡���¤’’™ˆˆˆˆˆˆ€€ˆ��¤ƒƒ‹ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ……Ž��¤††�ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:33Bxx‚’’š©©°ŠŠ’CCQ**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**://>**:**:‡‡�XXe**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:__kââäççéÀÀÅÀÀÅÞÞàîîïvv€**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:ww�­­³**:**:åå燇�**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:LLYëëí··¼55D**:**://>­­´ïïñRR_**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:²²¸¶¶»**:**:XXeAAO**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:µµ»ááã22A**:**:**:**:44Dããå„„�**:**:**:77Fxx‚ŽŽ–mmx--=**:**:**:XXe99HCCQ„„�……ŽBBP**:**:MM[ÂÂÇÅÅÉ\\h//?XXeAAO**:**:XXe99HCCQ„„�……ŽBBP**:**:**:ZZf>>M**:**:**:JJXOO\**:**:**:22Arr}ŽŽ–mmx,,<**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:00@íí£**:**:**:**:**:**:**:**:**:**:\\hääæÖÖÙÀÀÅààâÖÖÙHHU**:**:åå窪°èèêÀÀÅßßáîîï[[g**:••�ââäããåÀÀÅ;;Jåå燇�**:**:åå窪°èèêÀÀÅßßáîîï[[g**:**:ëëí}}‡**:**:**:¬¬²ÀÀÅ**:**:OO\ßßáÚÚÝÀÀÅÛÛÞÒÒÖBBP**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:HHVòòóyyƒ**:**:**:**:**:**:**:**:**:33Bááã´´º//?**:88GÎÎÒÉÉÍ**:**:ååçââäAAO**:33BÖÖÙ²²·**:**:²²¸¶¶»**:**:åå燇�**:**:ååçââäAAO**:33BÖÖÙ²²·**:**:ëëí}}‡**:**:**:¬¬²ÀÀÅ**:,,<ÖÖÙ»»À00@**:55DÉÉͺº¿**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:MM[òòóss}**:**:**:**:**:**:**:**:**:ggsòòóIIW**:**:**:jjuòòóHHU**:ååç››£**:**:**:¨¨®ÆÆÊ**:**:²²¸¶¶»**:**:åå燇�**:**:ååç››£**:**:**:¨¨®ÆÆÊ**:**:ëëí}}‡**:**:**:¬¬²ÀÀÅ**:YYfòòóXXe**:**:**:qq{ññò99H**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:99Hòòó‡‡�**:**:**:**:**:**:**:**:**:��‹ïïñ++;**:**:**:IIWòòó``l**:åå燇�**:**:**:¢¢©ÇÇË**:**:²²¸¶¶»**:**:åå燇�**:**:åå燇�**:**:**:¢¢©ÇÇË**:**:ëëí}}‡**:**:**:¬¬²ÀÀÅ**:uuòòóòòóòòóòòóòòóòòóòòóSS`**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:ÔÔ×¹¹¾**:**:**:**:**:**:½½Á§§­**:||†ññò//?**:**:**:PP]òòó\\i**:ååç„„�**:**:**:¢¢©ÇÇË**:**:²²¸¶¶»**:**:åå燇�**:**:ååç„„�**:**:**:¢¢©ÇÇË**:**:ëëíˆ**:**:**:±±·ÀÀÅ**:qq|òòóiit\\h\\h\\h\\h\\h44D**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:……Žòòó[[g**:**:**:**:XXeòòó��•**:XXeòòó^^j**:**:**:€€‰ððñ;;J**:ååç„„�**:**:**:¢¢©ÇÇË**:**:²²···¼**:**:åå燇�**:**:ååç„„�**:**:**:¢¢©ÇÇË**:**:çç銊“**:**:**:ÏÏÒÀÀÅ**:NN[òòókkw**:**:**:ffr““›11@**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:00@ÉÉÍêê놆�UUbQQ^��‹ååçÑÑÔ22A**:**:ÇÇËÖÖÙRR_**:ddpææè¨¨®**:**:ååç„„�**:**:**:¢¢©ÇÇË**:**:¨¨®ÕÕØ\\h00@åå燇�**:**:ååç„„�**:**:**:¢¢©ÇÇË**:**:ÃÃÈÖÖÙDDR33B��™ííîÀÀÅ**:**:½½ÁÝÝà[[g**:NN[ÜÜߺº¿**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:44D¡¡¨ììîòòóòòóòò󨨮99G**:**:**:99H··¼òòóòòóïïð��¤11@**:**:ååç„„�**:**:**:¢¢©ÇÇË**:**:ddpííîòòóZZfåå燇�**:**:ååç„„�**:**:**:¢¢©ÇÇË**:**:OO\ÛÛÞòòóòòó´´º––žÀÀÅ**:**:77F³³¹òòóòòóòòó»»À55D**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:SS`\\h--=**:**:**:**:**:**:**://?XXe**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:PP]77F**:**:**:**:**:**:**:44D\\h66E**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:44Cyyƒ——Ÿ­­´ŽŽ–JJX**:**:**:**:**:**:**:**:**:**:**:**:**:**://>**:**:‡‡�XXe**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:YYfààâïïðÀÀÅÀÀÅ××Úòò󣣪..=**:**:**:**:**:**:**:**:**:**:**:ww�­­³**:**:åå燇�**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:HHVééêÁÁÅ==K**:**:**:{{„ïïð  §**:**:**:**:**:**:**:**:**:**:**:²²¸¶¶»**:**:XXeAAO**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:±±·ààã44C**:**:**:**:**:‘‘™òòóKKX**:XXe::IPP]ŽŽ–vv�44D**:**:MM[ÂÂÇÅÅÉ\\h//?XXeAAO**:**:**:77Fxx‚ŽŽ–mmx--=**:**:**:XXe99HCCQ„„�……ŽBBP**:**:**:**:``lŽŽ–……ŽIIW**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**://?ëëí››£**:**:**:**:**:**:;;Jññò��•**:åå縸¾ããå¼¼Á××ÚààâIIW**:••�ââäããåÀÀÅ;;Jåå燇�**:**:\\hääæÖÖÙÀÀÅààâÖÖÙHHU**:**:åå窪°èèêÀÀÅßßáîîï[[g**:**:··¼ææèÀÀÅÇÇÌòòó‡‡�**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:JJXòòóyyƒ**:**:**:**:**:**:**:ÛÛݯ¯µ**:ååçââäCCQ**:22AÆÆÊÂÂÆ**:**:²²¸¶¶»**:**:åå燇�**:33Bááã´´º//?**:88GÎÎÒÉÉÍ**:**:ååçââäAAO**:33BÖÖÙ²²·**:RR_òòóNN[**:**:““›ààã**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:RR_òòónny**:**:**:**:**:**:**:ÓÓÖ··¼**:ååç��™**:**:**:llwòòó>>M**:²²¸¶¶»**:**:åå燇�**:ggsòòóIIW**:**:**:jjuòòóHHU**:ååç››£**:**:**:¨¨®ÆÆÊ**:GGUòò󣣪MMZ**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:BBPòò󀀊**:**:**:**:**:**:**:åå礤«**:ååçppz**:**:**:QQ^òòóWWd**:²²¸¶¶»**:**:åå燇�**:��‹ïïñ++;**:**:**:IIWòòó``l**:åå燇�**:**:**:¢¢©ÇÇË**:**:††�ììîòòóÝÝࣣªKKX**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:××Ú¸¸½**:**:**:**:**:**:WWcòòóuu**:ååçrr}**:**:**:WWdòòóRR_**:²²¸¶¶»**:**:åå燇�**:||†ññò//?**:**:**:PP]òòó\\i**:ååç„„�**:**:**:¢¢©ÇÇË**:**:**:33Bkkw¢¢©ááãééêCCQ**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:~~ˆòòóffr**:**:**:**:00@ÅÅÉÞÞà22A**:ååçžž¦**:**:**:……Žééê11@**:²²···¼**:**:åå燇�**:XXeòòó^^j**:**:**:€€‰ððñ;;J**:ååç„„�**:**:**:¢¢©ÇÇË**:UUb££ª,,<**:**:IIWòòónny**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:,,<´´ºîîï’’š[[gCCQjjuËËÏììî^^j**:**:ååçììînny**:aalææè””œ**:**:¨¨®ÕÕØ\\h00@åå燇�**:**:ÇÇËÖÖÙRR_**:ddpææè¨¨®**:**:ååç„„�**:**:**:¢¢©ÇÇË**:MMZññò””œ..=**:ŒŒ•ððñGGU**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:ŠŠ’ààâòòóòòóòòó¹¹¾NN[**:**:**:åå篯µààâòòóððñ››£--=**:**:ddpííîòòóZZfåå燇�**:**:99H··¼òòóòòóïïð��¤11@**:**:ååç„„�**:**:**:¢¢©ÇÇË**:**:xx‚ççéòòóòòóããåqq{**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:IIW\\h//?**:**:**:**:**:ååç„„�**:WWd--=**:**:**:**:**:**:**:**:**:**:**:**:**:**://?XXe**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:QQ^MM[**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:ååç„„�**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:ååç„„�**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:XXe@@N**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:55D{{„™™ °°¶‹‹”GGU**:**:**:**:**:**:**:**:**:**:**:**:**:‡‡�XXe**:**:**://>**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:eepååçêêëÀÀÅÀÀÅÛÛÞòòó™™ **:**:**:**:**:**:**:**:**:**:**:**:åå燇�**:**:ww�­­³**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:RR_ííî³³¹88G**:**:**:……Žòòó��™**:**:**:**:**:**:**:**:**:**:**:XXeAAO**:**:²²¸¶¶»**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:¿¿ÄÕÕØ//?**:**:**:**:**:žž¦îîï>>M**:ZZf>>M**:**:**:JJXOO\**:**:XXeAAO**:MM[ÂÂÇÅÅÉ\\h//?**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:::Iññò‰‰’**:**:**:**:**:**:KKXòòó}}‡**:ëëí}}‡**:**:**:¬¬²ÀÀÅ**:**:åå燇�**:••�ââäããåÀÀÅ;;J**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:\\iòòóeep**:**:**:**:**:**:**:êêìžž¦**:ëëí}}‡**:**:**:¬¬²ÀÀÅ**:**:åå燇�**:**:²²¸¶¶»**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:ccoòòó^^j**:**:**:**:**:**:**:ä俦¦­**:ëëí}}‡**:**:**:¬¬²ÀÀÅ**:**:åå燇�**:**:²²¸¶¶»**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:QQ^òòóqq|**:**:**:**:**:**:11@ððñ””œ**:ëëí}}‡**:**:**:¬¬²ÀÀÅ**:**:åå燇�**:**:²²¸¶¶»**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:--=åå稨®**:**:**://>**:**:ggsòòóeep**:ëëíˆ**:**:**:±±·ÀÀÅ**:**:åå燇�**:**:²²¸¶¶»**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:��˜ïïðWWd**:**:ªª°ËËÏaamÑÑÕÒÒÖ,,<**:çç銊“**:**:**:ÏÏÒÀÀÅ**:**:åå燇�**:**:²²···¼**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:00@ÂÂÇééꈈ‘WWdRR_ÃÃÈòòóòòóSS`**:**:ÃÃÈÖÖÙDDR33B��™ííîÀÀÅ**:**:åå燇�**:**:¨¨®ÕÕØ\\h00@**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**://?‘‘™ååçòòóòòóòòó±±·ÐÐÓÑÑÕggs**:OO\ÛÛÞòòóòòó´´º––žÀÀÅ**:**:åå燇�**:**:ddpííîòòóZZf**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:MMZ\\h**:**://?ˆˆ‘‰‰’**:**:**:PP]77F**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUw**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:**:UUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&UUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUwUUw&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ZZ‚ \ No newline at end of file diff --git a/selfhost/golden/snake.ppm b/selfhost/golden/snake.ppm new file mode 100644 index 00000000..b8e73456 --- /dev/null +++ b/selfhost/golden/snake.ppm @@ -0,0 +1,4 @@ +P6 +320 240 +255 +****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................*******ÿÿÿÿÿÿÿÿÿ***ÿÿÿÿÿÿÿÿÿ...ÿÿÿÿÿÿÿÿÿ..ÿÿÿÿÿÿÿÿÿÿÿÿ..ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ*************.....ÿà`ÿà`ÿà`........****************................****************................****************................****************................****************................****************................****************................****************................******ÿÿÿ***ÿÿÿ*ÿÿÿ***ÿÿÿ.ÿÿÿ...ÿÿÿ.ÿÿÿ...ÿÿÿ.ÿÿÿ.****************....ÿà`...ÿà`.......****************................****************................****************................****************................****************................****************................****************................****************................******ÿÿÿ*****ÿÿÿ***..ÿÿÿ...ÿÿÿ.ÿÿÿ...ÿÿÿ.ÿÿÿ.****************....ÿà`..ÿà`ÿà`.......****************................****************................****************................****************................****************................****************................****************................****************................*******ÿÿÿÿÿÿÿÿÿ**ÿÿÿ***..ÿÿÿ...ÿÿÿ.ÿÿÿÿÿÿÿÿÿÿÿÿ..ÿÿÿÿÿÿÿÿÿ***************....ÿà`.ÿà`.ÿà`.......****************................****************................****************................****************................****************................****************................****************................****************................**********ÿÿÿ*ÿÿÿ***..ÿÿÿ...ÿÿÿ.ÿÿÿ.ÿÿÿ...ÿÿÿ.****************....ÿà`ÿà`..ÿà`.......****************................****************................****************................****************................****************................****************................****************................****************................******ÿÿÿ***ÿÿÿ*ÿÿÿ***ÿÿÿ.ÿÿÿ...ÿÿÿ.ÿÿÿ..ÿÿÿ..ÿÿÿ.****************....ÿà`...ÿà`.......****************................****************................****************................****************................****************................****************................****************................****************................*******ÿÿÿÿÿÿÿÿÿ***ÿÿÿÿÿÿÿÿÿ...ÿÿÿÿÿÿÿÿÿ..ÿÿÿ...ÿÿÿ.ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ*************.....ÿà`ÿà`ÿà`........****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................********************************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................********************************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................********************************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************..ÿUUÿUUÿUUÿUUÿUUÿUU......ÿUUÿUUÿUUÿUUÿUUÿUU****ÿUUÿUU******ÿUUÿUU..ÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUU..**************ÿUUÿUUÿUUÿUUÿUUÿUU....ÿUUÿUU......ÿUUÿUU**ÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUU**ÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUU........****************................****************................****************................****************................****************................****************................****************..ÿUUÿUUÿUUÿUUÿUUÿUU......ÿUUÿUUÿUUÿUUÿUUÿUU****ÿUUÿUU******ÿUUÿUU..ÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUU..**************ÿUUÿUUÿUUÿUUÿUUÿUU....ÿUUÿUU......ÿUUÿUU**ÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUU**ÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUU........****************................****************................****************................****************................****************................****************................****************ÿUUÿUU......ÿUUÿUU..ÿUUÿUU..****ÿUUÿUU**ÿUUÿUUÿUUÿUU**ÿUUÿUUÿUUÿUU..ÿUUÿUU..........************ÿUUÿUU**....ÿUUÿUU..ÿUUÿUU......ÿUUÿUU**ÿUUÿUU**********ÿUUÿUU......ÿUUÿUU......****************................****************................****************................****************................****************................****************................****************ÿUUÿUU......ÿUUÿUU..ÿUUÿUU..****ÿUUÿUU**ÿUUÿUUÿUUÿUU**ÿUUÿUUÿUUÿUU..ÿUUÿUU..........************ÿUUÿUU**....ÿUUÿUU..ÿUUÿUU......ÿUUÿUU**ÿUUÿUU**********ÿUUÿUU......ÿUUÿUU......****************................****************................****************................****************................****************................****************................****************ÿUUÿUU..........ÿUUÿUU..****ÿUUÿUU**ÿUUÿUU**ÿUUÿUU**ÿUUÿUU..ÿUUÿUU..........************ÿUUÿUU**....ÿUUÿUU..ÿUUÿUU......ÿUUÿUU**ÿUUÿUU**********ÿUUÿUU......ÿUUÿUU......****************................****************................****************................****************................****************................****************................****************ÿUUÿUU..........ÿUUÿUU..****ÿUUÿUU**ÿUUÿUU**ÿUUÿUU**ÿUUÿUU..ÿUUÿUU..........************ÿUUÿUU**....ÿUUÿUU..ÿUUÿUU......ÿUUÿUU**ÿUUÿUU**********ÿUUÿUU......ÿUUÿUU......****************................****************................****************................****************................****************................****************................****************ÿUUÿUU..ÿUUÿUUÿUUÿUUÿUUÿUU..ÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUU**ÿUUÿUU**ÿUUÿUU**ÿUUÿUU..ÿUUÿUUÿUUÿUUÿUUÿUU......************ÿUUÿUU**....ÿUUÿUU..ÿUUÿUU......ÿUUÿUU**ÿUUÿUUÿUUÿUUÿUUÿUU******ÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUU........****************................****************................****************................****************................****************................****************................****************ÿUUÿUU..ÿUUÿUUÿUUÿUUÿUUÿUU..ÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUU**ÿUUÿUU**ÿUUÿUU**ÿUUÿUU..ÿUUÿUUÿUUÿUUÿUUÿUU......************ÿUUÿUU**....ÿUUÿUU..ÿUUÿUU......ÿUUÿUU**ÿUUÿUUÿUUÿUUÿUUÿUU******ÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUU........****************................****************................****************................................****************................****************................****************................ÿUUÿUU******ÿUUÿUU**ÿUUÿUU**....ÿUUÿUU..ÿUUÿUU......ÿUUÿUU**ÿUUÿUU**********............ÿUUÿUU..****ÿUUÿUU**ÿUUÿUU******ÿUUÿUU..ÿUUÿUU..........ÿUUÿUU**ÿUUÿUU**********................****************................****************................****************................****************................****************................****************................ÿUUÿUU******ÿUUÿUU**ÿUUÿUU**....ÿUUÿUU..ÿUUÿUU......ÿUUÿUU@À`@À`ÿUUÿUU@À`@À`@À`@À`@À`@À`@À`@À`@À`*.@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`ÿUUÿUU@À`.****ÿUUÿUU**ÿUUÿUU******ÿUUÿUU..ÿUUÿUU..........ÿUUÿUU**ÿUUÿUU**********................****************................****************................****************................****************................****************................****************................ÿUUÿUU******ÿUUÿUU**ÿUUÿUU**....ÿUUÿUU..ÿUUÿUU......ÿUUÿUU@À`@À`ÿUUÿUU@À`@À`@À`@À`@À`@À`@À`@À`@À`*.@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`ÿUUÿUU@À`.****ÿUUÿUU****ÿUUÿUU**ÿUUÿUU....ÿUUÿUU..........ÿUUÿUU****ÿUUÿUU********................****************................****************................****************................****************................****************................****************................ÿUUÿUU******ÿUUÿUU**ÿUUÿUU**....ÿUUÿUU..ÿUUÿUU......ÿUUÿUU@À`@À`ÿUUÿUU@À`@À`@À`@À`@À`@À`@À`@À`@À`*.@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`ÿUUÿUU@À`.****ÿUUÿUU****ÿUUÿUU**ÿUUÿUU....ÿUUÿUU..........ÿUUÿUU****ÿUUÿUU********...à@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Z...****************................****************................****************................****************................****************................****************................**ÿUUÿUUÿUUÿUUÿUUÿUU****ÿUUÿUU**....ÿUUÿUU..ÿUUÿUU......ÿUUÿUU@À`@À`ÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUU@À`*.@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`ÿUUÿUUÿUUÿUUÿUUÿUU********ÿUUÿUU**....ÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUU..ÿUUÿUU******ÿUUÿUU******...à@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Z...****************................****************................****************................****************................****************................****************................**ÿUUÿUUÿUUÿUUÿUUÿUU****ÿUUÿUU**....ÿUUÿUU..ÿUUÿUU......ÿUUÿUU@À`@À`ÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUU@À`*.@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`ÿUUÿUUÿUUÿUUÿUUÿUU********ÿUUÿUU**....ÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUUÿUU..ÿUUÿUU******ÿUUÿUU******...à@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Z...****************................****************................****************................****************................****************................****************................****************................*@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`*.@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`.****************................****************...à@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Z...****************................****************................****************................****************................****************................****************................****************................*@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`*.@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`.****************................****************...à@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Z...****************................****************................****************................****************................****************................****************................****************................*@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`*.@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`.****************................****************...à@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Z...****************................****************................****************................****************................****************................****************................****************................*@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`*.@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`.****************................****************...à@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Z...****************................****************................****************................****************................****************................****************................****************................*@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`*.@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`.****************................****************...à@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Z...****************................****************................****************................****************................****************................****************................****************................*@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`*.@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`.****************................****************...à@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Z...****************................****************................****************................****************................****************................****************................****************................*@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`*.@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`.****************................****************...à@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Zà@Z...****************................****************................****************................****************................****************................****************................****************................*@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`*.@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`.****************................****************................****************................****************................****************................****************................****************................****************................****************................*@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`*.@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`@À`.****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................********************************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************....ÿÿÿÿÿÿÿÿÿÿÿÿ..ÿÿÿÿÿÿÿÿÿÿÿÿ..ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ**ÿÿÿÿÿÿÿÿÿ***ÿÿÿÿÿÿÿÿÿ.........ÿÿÿÿÿÿÿÿÿ..ÿÿÿ.**ÿÿÿ*ÿÿÿ***ÿÿÿ*******ÿÿÿ...ÿÿÿ.ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ.ÿÿÿ...ÿÿÿ***************................****************................****************................****************................****************................****************................****************................****************....ÿÿÿ...ÿÿÿ.ÿÿÿ...ÿÿÿ.ÿÿÿ*****ÿÿÿ***ÿÿÿ*ÿÿÿ***ÿÿÿ.......ÿÿÿ...ÿÿÿ.ÿÿÿÿÿÿ**ÿÿÿ*ÿÿÿ***ÿÿÿ*******ÿÿÿ..ÿÿÿ..ÿÿÿ.....ÿÿÿ...ÿÿÿ***************................****************................****************................****************................****************................****************................****************................****************....ÿÿÿ...ÿÿÿ.ÿÿÿ...ÿÿÿ.ÿÿÿ*****ÿÿÿ*****ÿÿÿ***........ÿÿÿ...ÿÿÿ.ÿÿÿ.ÿÿÿ*ÿÿÿ**ÿÿÿ*ÿÿÿ********ÿÿÿ.ÿÿÿ...ÿÿÿ......ÿÿÿ.ÿÿÿ****************................****************................****************................****************................****************................****************................****************................****************....ÿÿÿÿÿÿÿÿÿÿÿÿ..ÿÿÿÿÿÿÿÿÿÿÿÿ..ÿÿÿÿÿÿÿÿÿ****ÿÿÿÿÿÿÿÿÿ***ÿÿÿÿÿÿÿÿÿ........ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ.ÿÿÿ.ÿÿÿ*ÿÿÿ***ÿÿÿ*********ÿÿÿÿÿÿ....ÿÿÿÿÿÿÿÿÿ.....ÿÿÿ.****************................****************................****************................****************................****************................................****************................****************................****ÿÿÿ*****ÿÿÿ*ÿÿÿ***ÿÿÿ.........ÿÿÿ.....ÿÿÿ*******ÿÿÿ***ÿÿÿ*ÿÿÿ*.ÿÿÿÿÿÿ...ÿÿÿ.........ÿÿÿ*ÿÿÿ***ÿÿÿ*******ÿÿÿ*................****************................****************................****************................****************................****************................****************................****************................****ÿÿÿ*****ÿÿÿ**ÿÿÿ**ÿÿÿ.....ÿÿÿ...ÿÿÿ.ÿÿÿ...ÿÿÿ*******ÿÿÿ***ÿÿÿ*ÿÿÿ*..ÿÿÿ...ÿÿÿ.........ÿÿÿ**ÿÿÿ**ÿÿÿ*******ÿÿÿ*................****************................****************................****************................****************................****************................****************................****************................****ÿÿÿ*****ÿÿÿ***ÿÿÿ*ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ..ÿÿÿÿÿÿÿÿÿ...ÿÿÿÿÿÿÿÿÿ********ÿÿÿ***ÿÿÿ*ÿÿÿ*..ÿÿÿ...ÿÿÿ.........ÿÿÿ***ÿÿÿ*ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ***ÿÿÿ*................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................********************************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................********************************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................********************************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................****************................ \ No newline at end of file diff --git a/selfhost/io.ludic b/selfhost/io.ludic new file mode 100644 index 00000000..3ca2a035 --- /dev/null +++ b/selfhost/io.ludic @@ -0,0 +1,22 @@ +# io.ludic — reading the input file and writing the output, plus tiny stdio. +# The compiler reads one .ludic file whole and emits LLVM IR text to stdout. + +fn read_file(path: str) -> ptr { + let f = file_open(path, "rb") + if ptr_is_null(f) { return ptr_null() } + file_seek(f, 0, 2) + let n = file_tell(f) + file_seek(f, 0, 0) + let buf = mem_alloc(n + 1) + file_read(f, buf, n) + poke8(buf, n, 0) + file_close(f) + return buf +} + +# length of a NUL-terminated buffer +fn cstr_len(s: ptr) -> int { + let n = 0 + while peek8(s, n) != 0 { n = n + 1 } + return n +} diff --git a/selfhost/lex.ludic b/selfhost/lex.ludic new file mode 100644 index 00000000..6e798e55 --- /dev/null +++ b/selfhost/lex.ludic @@ -0,0 +1,138 @@ +# lex.ludic — source text -> a token slice. Mirrors compiler/front/lex.c. +# Tokens carry their kind, their text (identifiers, strings, operators), +# an integer value (numbers, char literals) and a line for diagnostics. + +const TK_ID: int = 0 +const TK_INT: int = 1 +const TK_STR: int = 2 +const TK_OP: int = 3 +const TK_NL: int = 4 +const TK_EOF: int = 5 +const TK_FLOAT: int = 6 + +struct Tok { kind: int = 0, text: ptr = ptr_null(), ival: int = 0, line: int = 0 } + +var toks: []Tok + +fn tok_push(kind: int, text: ptr, ival: int, line: int) -> void { + let t = new Tok + t.kind = kind t.text = text t.ival = ival t.line = line + push(toks, t) +} + +# does src match the 2-char operator op at position i? +fn two_at(src: ptr, i: int, a: int, b: int) -> bool { + return peek8(src, i) == a and peek8(src, i + 1) == b +} + +fn is_op1(c: int) -> bool { + # + - * / % < > = ( ) { } [ ] , : . ! @ + if c == 43 or c == 45 or c == 42 or c == 47 or c == 37 { return true } + if c == 60 or c == 62 or c == 61 { return true } + if c == 40 or c == 41 or c == 123 or c == 125 { return true } + if c == 91 or c == 93 or c == 44 or c == 58 or c == 46 { return true } + if c == 33 or c == 64 { return true } + return false +} + +fn lex(src: ptr) -> void { + toks = new []Tok + let i = 0 + let line = 1 + let n = slen(src) + while i < n { + let c = peek8(src, i) + if c == 10 { tok_push(TK_NL, ptr_null(), 0, line) line = line + 1 i = i + 1 continue } + if c == 32 or c == 9 or c == 13 { i = i + 1 continue } + if c == 35 { # '#' comment to end of line + while i < n and peek8(src, i) != 10 { i = i + 1 } + continue + } + if c == 34 { # "string" + i = i + 1 + let start = i + let out = mem_alloc(n) + let j = 0 + while i < n and peek8(src, i) != 34 { + if peek8(src, i) == 92 { # backslash escape + let e = peek8(src, i + 1) + let r = e + if e == 110 { r = 10 } + if e == 116 { r = 9 } + if e == 48 { r = 0 } + poke8(out, j, r) j = j + 1 i = i + 2 + } else { poke8(out, j, peek8(src, i)) j = j + 1 i = i + 1 } + } + i = i + 1 + poke8(out, j, 0) + tok_push(TK_STR, out, 0, line) + continue + } + if c == 39 { # 'c' char literal -> int + i = i + 1 + let v = 0 + if peek8(src, i) == 92 { + let e = peek8(src, i + 1) + if e == 110 { v = 10 } + if e == 116 { v = 9 } + if e == 48 { v = 0 } + i = i + 2 + } else { v = peek8(src, i) i = i + 1 } + if peek8(src, i) == 39 { i = i + 1 } + tok_push(TK_INT, ptr_null(), v, line) + continue + } + if char_is_digit(c) { + if c == 48 and peek8(src, i + 1) == 120 { # 0x hex + let v = 0 + i = i + 2 + while i < n { + let h = peek8(src, i) + let d = 0 + if char_is_digit(h) { d = h - 48 } + else { if h >= 97 and h <= 102 { d = h - 87 } + else { if h >= 65 and h <= 70 { d = h - 55 } else { break } } } + v = v * 16 + d + i = i + 1 + } + tok_push(TK_INT, ptr_null(), v, line) + continue + } + let v = 0 + while i < n and char_is_digit(peek8(src, i)) { v = v * 10 + (peek8(src, i) - 48) i = i + 1 } + # a fractional part makes it a Q16.16 fixed literal + if i < n and peek8(src, i) == 46 and char_is_digit(peek8(src, i + 1)) { + i = i + 1 + let fnum = 0 let fden = 1 + while i < n and char_is_digit(peek8(src, i)) { fnum = fnum * 10 + (peek8(src, i) - 48) fden = fden * 10 i = i + 1 } + let bits = shl(v, 16) + shl(fnum, 16) / fden + tok_push(TK_FLOAT, ptr_null(), bits, line) + continue + } + tok_push(TK_INT, ptr_null(), v, line) + continue + } + if char_is_alpha(c) { + let start = i + while i < n and char_is_alnum(peek8(src, i)) { i = i + 1 } + tok_push(TK_ID, substr(src, start, i - start), 0, line) + continue + } + if c == 59 { tok_push(TK_NL, ptr_null(), 0, line) i = i + 1 continue } # ';' + # two-character operators + if two_at(src, i, 45, 62) { tok_push(TK_OP, substr(src, i, 2), 0, line) i = i + 2 continue } # -> + if two_at(src, i, 61, 62) { tok_push(TK_OP, substr(src, i, 2), 0, line) i = i + 2 continue } # => + if two_at(src, i, 61, 61) { tok_push(TK_OP, substr(src, i, 2), 0, line) i = i + 2 continue } # == + if two_at(src, i, 33, 61) { tok_push(TK_OP, substr(src, i, 2), 0, line) i = i + 2 continue } # != + if two_at(src, i, 60, 61) { tok_push(TK_OP, substr(src, i, 2), 0, line) i = i + 2 continue } # <= + if two_at(src, i, 62, 61) { tok_push(TK_OP, substr(src, i, 2), 0, line) i = i + 2 continue } # >= + if two_at(src, i, 43, 61) { tok_push(TK_OP, substr(src, i, 2), 0, line) i = i + 2 continue } # += + if two_at(src, i, 45, 61) { tok_push(TK_OP, substr(src, i, 2), 0, line) i = i + 2 continue } # -= + if two_at(src, i, 42, 61) { tok_push(TK_OP, substr(src, i, 2), 0, line) i = i + 2 continue } # *= + if two_at(src, i, 47, 61) { tok_push(TK_OP, substr(src, i, 2), 0, line) i = i + 2 continue } # /= + if two_at(src, i, 46, 46) { tok_push(TK_OP, substr(src, i, 2), 0, line) i = i + 2 continue } # .. + if is_op1(c) { tok_push(TK_OP, substr(src, i, 1), 0, line) i = i + 1 continue } + i = i + 1 # skip anything unrecognised + } + tok_push(TK_EOF, ptr_null(), 0, line) +} diff --git a/selfhost/ludicc.seed.ll b/selfhost/ludicc.seed.ll new file mode 100644 index 00000000..b4d759c4 --- /dev/null +++ b/selfhost/ludicc.seed.ll @@ -0,0 +1,19459 @@ +; Ludic (self-hosted) -> LLVM IR +declare i32 @printf(ptr, ...) +declare ptr @malloc(i64) +declare ptr @realloc(ptr, i64) +declare void @free(ptr) +declare ptr @fopen(ptr, ptr) +declare i64 @fread(ptr, i64, i64, ptr) +declare i64 @fwrite(ptr, i64, i64, ptr) +declare i32 @fseek(ptr, i64, i32) +declare i64 @ftell(ptr) +declare i32 @fclose(ptr) +declare void @exit(i32) +declare i32 @system(ptr) +declare ptr @getenv(ptr) +declare ptr @memcpy(ptr, ptr, i64) +declare ptr @memset(ptr, i32, i64) +declare i64 @strlen(ptr) +declare i32 @getchar() +declare i32 @putchar(i32) +declare i64 @time(ptr) +declare void @win_open(i32, i32, i32, ptr) +declare i32 @win_poll() +declare void @win_present(ptr, i32, i32) +declare i32 @win_running() +declare void @win_close() +@__stderrp = external global ptr +@.fmt_str = private unnamed_addr constant [3 x i8] c"%s\00" +@.fmt_int = private unnamed_addr constant [4 x i8] c"%d\0A\00" +@L_argc = internal global i32 0 +@L_argv = internal global ptr null +@.gametitle = private unnamed_addr constant [9 x i8] c"SelfHost\00" +%LSlice = type { ptr, i32, i32 } +%Str_Buf = type { ptr, i32, i32 } +%Str_Node = type { i32, ptr, i32, ptr, ptr, ptr, ptr, ptr, i32 } +%Str_Tok = type { i32, ptr, i32, i32 } +%Str_Val = type { ptr, ptr } +@g_toks = internal global ptr null +@g_pi = internal global i32 0 +@g_prog = internal global ptr null +@g_g_game_name = internal global ptr null +@g_loaded_paths = internal global ptr null +@g_cur_dir = internal global ptr null +@g_head = internal global ptr null +@g_code = internal global ptr null +@g_falloc = internal global ptr null +@g_ll_t = internal global i32 0 +@g_ll_lbl = internal global i32 0 +@g_ll_str = internal global i32 0 +@g_loc_name = internal global ptr null +@g_loc_reg = internal global ptr null +@g_loc_ty = internal global ptr null +@g_nloc = internal global i32 0 +@g_brk_lbl = internal global ptr null +@g_cnt_lbl = internal global ptr null +@g_nloop = internal global i32 0 +@g_ret_ty = internal global ptr null +@g_g_term = internal global i32 0 +@g_self_stk = internal global ptr null +@g_nself = internal global i32 0 +@g_mach_stk = internal global ptr null +@g_nmach = internal global i32 0 +@g_g_addr_ty = internal global ptr null +@g_g_intrin_ok = internal global i32 0 +@g_g_windowed = internal global i32 0 +@g_g_iok = internal global i32 0 +@g_uiw = internal global ptr null +@g_uiw_parent = internal global ptr null +@g_ui_roots = internal global ptr null +@.str0 = private unnamed_addr constant [3 x i8] c"rb\00" +@.str1 = private unnamed_addr constant [28 x i8] c"ludicc(self): parse error: \00" +@.str2 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str3 = private unnamed_addr constant [20 x i8] c"expected identifier\00" +@.str4 = private unnamed_addr constant [2 x i8] c"[\00" +@.str5 = private unnamed_addr constant [2 x i8] c"]\00" +@.str6 = private unnamed_addr constant [2 x i8] c"(\00" +@.str7 = private unnamed_addr constant [2 x i8] c")\00" +@.str8 = private unnamed_addr constant [2 x i8] c",\00" +@.str9 = private unnamed_addr constant [2 x i8] c")\00" +@.str10 = private unnamed_addr constant [5 x i8] c"true\00" +@.str11 = private unnamed_addr constant [6 x i8] c"false\00" +@.str12 = private unnamed_addr constant [4 x i8] c"new\00" +@.str13 = private unnamed_addr constant [2 x i8] c"(\00" +@.str14 = private unnamed_addr constant [2 x i8] c")\00" +@.str15 = private unnamed_addr constant [20 x i8] c"expected expression\00" +@.str16 = private unnamed_addr constant [2 x i8] c".\00" +@.str17 = private unnamed_addr constant [2 x i8] c"[\00" +@.str18 = private unnamed_addr constant [2 x i8] c"]\00" +@.str19 = private unnamed_addr constant [2 x i8] c"(\00" +@.str20 = private unnamed_addr constant [2 x i8] c"-\00" +@.str21 = private unnamed_addr constant [2 x i8] c"-\00" +@.str22 = private unnamed_addr constant [4 x i8] c"not\00" +@.str23 = private unnamed_addr constant [4 x i8] c"not\00" +@.str24 = private unnamed_addr constant [2 x i8] c"*\00" +@.str25 = private unnamed_addr constant [2 x i8] c"/\00" +@.str26 = private unnamed_addr constant [2 x i8] c"%\00" +@.str27 = private unnamed_addr constant [2 x i8] c"+\00" +@.str28 = private unnamed_addr constant [2 x i8] c"-\00" +@.str29 = private unnamed_addr constant [2 x i8] c"<\00" +@.str30 = private unnamed_addr constant [3 x i8] c"<=\00" +@.str31 = private unnamed_addr constant [2 x i8] c">\00" +@.str32 = private unnamed_addr constant [3 x i8] c">=\00" +@.str33 = private unnamed_addr constant [3 x i8] c"==\00" +@.str34 = private unnamed_addr constant [3 x i8] c"!=\00" +@.str35 = private unnamed_addr constant [4 x i8] c"and\00" +@.str36 = private unnamed_addr constant [4 x i8] c"and\00" +@.str37 = private unnamed_addr constant [3 x i8] c"or\00" +@.str38 = private unnamed_addr constant [3 x i8] c"or\00" +@.str39 = private unnamed_addr constant [2 x i8] c"{\00" +@.str40 = private unnamed_addr constant [2 x i8] c"}\00" +@.str41 = private unnamed_addr constant [2 x i8] c"=\00" +@.str42 = private unnamed_addr constant [2 x i8] c",\00" +@.str43 = private unnamed_addr constant [2 x i8] c"}\00" +@.str44 = private unnamed_addr constant [2 x i8] c"{\00" +@.str45 = private unnamed_addr constant [2 x i8] c"}\00" +@.str46 = private unnamed_addr constant [2 x i8] c"}\00" +@.str47 = private unnamed_addr constant [4 x i8] c"let\00" +@.str48 = private unnamed_addr constant [2 x i8] c":\00" +@.str49 = private unnamed_addr constant [2 x i8] c"=\00" +@.str50 = private unnamed_addr constant [7 x i8] c"return\00" +@.str51 = private unnamed_addr constant [2 x i8] c"}\00" +@.str52 = private unnamed_addr constant [3 x i8] c"if\00" +@.str53 = private unnamed_addr constant [5 x i8] c"else\00" +@.str54 = private unnamed_addr constant [3 x i8] c"if\00" +@.str55 = private unnamed_addr constant [5 x i8] c"when\00" +@.str56 = private unnamed_addr constant [6 x i8] c"while\00" +@.str57 = private unnamed_addr constant [4 x i8] c"for\00" +@.str58 = private unnamed_addr constant [2 x i8] c"(\00" +@.str59 = private unnamed_addr constant [3 x i8] c"..\00" +@.str60 = private unnamed_addr constant [6 x i8] c"spawn\00" +@.str61 = private unnamed_addr constant [8 x i8] c"machine\00" +@.str62 = private unnamed_addr constant [2 x i8] c"{\00" +@.str63 = private unnamed_addr constant [2 x i8] c"}\00" +@.str64 = private unnamed_addr constant [2 x i8] c"=\00" +@.str65 = private unnamed_addr constant [2 x i8] c"}\00" +@.str66 = private unnamed_addr constant [7 x i8] c"become\00" +@.str67 = private unnamed_addr constant [6 x i8] c"enter\00" +@.str68 = private unnamed_addr constant [8 x i8] c"despawn\00" +@.str69 = private unnamed_addr constant [6 x i8] c"break\00" +@.str70 = private unnamed_addr constant [9 x i8] c"continue\00" +@.str71 = private unnamed_addr constant [6 x i8] c"match\00" +@.str72 = private unnamed_addr constant [2 x i8] c"{\00" +@.str73 = private unnamed_addr constant [2 x i8] c"}\00" +@.str74 = private unnamed_addr constant [2 x i8] c",\00" +@.str75 = private unnamed_addr constant [3 x i8] c"=>\00" +@.str76 = private unnamed_addr constant [2 x i8] c"{\00" +@.str77 = private unnamed_addr constant [2 x i8] c"}\00" +@.str78 = private unnamed_addr constant [2 x i8] c"=\00" +@.str79 = private unnamed_addr constant [3 x i8] c"+=\00" +@.str80 = private unnamed_addr constant [3 x i8] c"-=\00" +@.str81 = private unnamed_addr constant [3 x i8] c"*=\00" +@.str82 = private unnamed_addr constant [3 x i8] c"/=\00" +@.str83 = private unnamed_addr constant [2 x i8] c"{\00" +@.str84 = private unnamed_addr constant [2 x i8] c"}\00" +@.str85 = private unnamed_addr constant [2 x i8] c":\00" +@.str86 = private unnamed_addr constant [2 x i8] c"=\00" +@.str87 = private unnamed_addr constant [2 x i8] c",\00" +@.str88 = private unnamed_addr constant [2 x i8] c"}\00" +@.str89 = private unnamed_addr constant [2 x i8] c":\00" +@.str90 = private unnamed_addr constant [2 x i8] c"=\00" +@.str91 = private unnamed_addr constant [2 x i8] c":\00" +@.str92 = private unnamed_addr constant [2 x i8] c"=\00" +@.str93 = private unnamed_addr constant [2 x i8] c"(\00" +@.str94 = private unnamed_addr constant [2 x i8] c")\00" +@.str95 = private unnamed_addr constant [2 x i8] c":\00" +@.str96 = private unnamed_addr constant [2 x i8] c",\00" +@.str97 = private unnamed_addr constant [2 x i8] c")\00" +@.str98 = private unnamed_addr constant [5 x i8] c"void\00" +@.str99 = private unnamed_addr constant [3 x i8] c"->\00" +@.str100 = private unnamed_addr constant [1 x i8] c"\00" +@.str101 = private unnamed_addr constant [7 x i8] c"import\00" +@.str102 = private unnamed_addr constant [29 x i8] c"expected \22path\22 after import\00" +@.str103 = private unnamed_addr constant [7 x i8] c"struct\00" +@.str104 = private unnamed_addr constant [10 x i8] c"component\00" +@.str105 = private unnamed_addr constant [10 x i8] c"archetype\00" +@.str106 = private unnamed_addr constant [7 x i8] c"system\00" +@.str107 = private unnamed_addr constant [5 x i8] c"edge\00" +@.str108 = private unnamed_addr constant [3 x i8] c"ui\00" +@.str109 = private unnamed_addr constant [4 x i8] c"var\00" +@.str110 = private unnamed_addr constant [6 x i8] c"const\00" +@.str111 = private unnamed_addr constant [7 x i8] c"export\00" +@.str112 = private unnamed_addr constant [3 x i8] c"fn\00" +@.str113 = private unnamed_addr constant [5 x i8] c"pure\00" +@.str114 = private unnamed_addr constant [5 x i8] c"pure\00" +@.str115 = private unnamed_addr constant [7 x i8] c"extern\00" +@.str116 = private unnamed_addr constant [5 x i8] c"main\00" +@.str117 = private unnamed_addr constant [21 x i8] c"expected declaration\00" +@.str118 = private unnamed_addr constant [20 x i8] c"cannot open import \00" +@.str119 = private unnamed_addr constant [1 x i8] c"\00" +@.str120 = private unnamed_addr constant [26 x i8] c"runtime/native/core.ludic\00" +@.str121 = private unnamed_addr constant [6 x i8] c"Ludic\00" +@.str122 = private unnamed_addr constant [7 x i8] c"import\00" +@.str123 = private unnamed_addr constant [5 x i8] c"game\00" +@.str124 = private unnamed_addr constant [7 x i8] c"module\00" +@.str125 = private unnamed_addr constant [2 x i8] c"{\00" +@.str126 = private unnamed_addr constant [2 x i8] c"}\00" +@.str127 = private unnamed_addr constant [2 x i8] c"{\00" +@.str128 = private unnamed_addr constant [2 x i8] c"}\00" +@.str129 = private unnamed_addr constant [2 x i8] c":\00" +@.str130 = private unnamed_addr constant [2 x i8] c"=\00" +@.str131 = private unnamed_addr constant [2 x i8] c",\00" +@.str132 = private unnamed_addr constant [2 x i8] c"}\00" +@.str133 = private unnamed_addr constant [2 x i8] c"[\00" +@.str134 = private unnamed_addr constant [2 x i8] c"[\00" +@.str135 = private unnamed_addr constant [2 x i8] c"]\00" +@.str136 = private unnamed_addr constant [5 x i8] c"edge\00" +@.str137 = private unnamed_addr constant [7 x i8] c"Update\00" +@.str138 = private unnamed_addr constant [2 x i8] c"@\00" +@.str139 = private unnamed_addr constant [2 x i8] c"(\00" +@.str140 = private unnamed_addr constant [2 x i8] c"(\00" +@.str141 = private unnamed_addr constant [2 x i8] c")\00" +@.str142 = private unnamed_addr constant [6 x i8] c"phase\00" +@.str143 = private unnamed_addr constant [6 x i8] c"reads\00" +@.str144 = private unnamed_addr constant [7 x i8] c"writes\00" +@.str145 = private unnamed_addr constant [6 x i8] c"needs\00" +@.str146 = private unnamed_addr constant [5 x i8] c"uses\00" +@.str147 = private unnamed_addr constant [6 x i8] c"query\00" +@.str148 = private unnamed_addr constant [2 x i8] c"(\00" +@.str149 = private unnamed_addr constant [2 x i8] c"(\00" +@.str150 = private unnamed_addr constant [2 x i8] c")\00" +@.str151 = private unnamed_addr constant [2 x i8] c",\00" +@.str152 = private unnamed_addr constant [2 x i8] c")\00" +@.str153 = private unnamed_addr constant [2 x i8] c"[\00" +@.str154 = private unnamed_addr constant [2 x i8] c"]\00" +@.str155 = private unnamed_addr constant [2 x i8] c"{\00" +@.str156 = private unnamed_addr constant [2 x i8] c"}\00" +@.str157 = private unnamed_addr constant [2 x i8] c",\00" +@.str158 = private unnamed_addr constant [2 x i8] c"]\00" +@.str159 = private unnamed_addr constant [6 x i8] c"where\00" +@.str160 = private unnamed_addr constant [2 x i8] c"(\00" +@.str161 = private unnamed_addr constant [2 x i8] c")\00" +@.str162 = private unnamed_addr constant [2 x i8] c",\00" +@.str163 = private unnamed_addr constant [2 x i8] c")\00" +@.str164 = private unnamed_addr constant [2 x i8] c"{\00" +@.str165 = private unnamed_addr constant [2 x i8] c"}\00" +@.str166 = private unnamed_addr constant [2 x i8] c"=\00" +@.str167 = private unnamed_addr constant [2 x i8] c",\00" +@.str168 = private unnamed_addr constant [2 x i8] c"}\00" +@.str169 = private unnamed_addr constant [2 x i8] c"{\00" +@.str170 = private unnamed_addr constant [2 x i8] c"}\00" +@.str171 = private unnamed_addr constant [2 x i8] c",\00" +@.str172 = private unnamed_addr constant [2 x i8] c"}\00" +@.str173 = private unnamed_addr constant [2 x i8] c"(\00" +@.str174 = private unnamed_addr constant [2 x i8] c")\00" +@.str175 = private unnamed_addr constant [2 x i8] c":\00" +@.str176 = private unnamed_addr constant [2 x i8] c",\00" +@.str177 = private unnamed_addr constant [2 x i8] c")\00" +@.str178 = private unnamed_addr constant [5 x i8] c"void\00" +@.str179 = private unnamed_addr constant [3 x i8] c"->\00" +@.str180 = private unnamed_addr constant [2 x i8] c"=\00" +@.str181 = private unnamed_addr constant [2 x i8] c"=\00" +@.str182 = private unnamed_addr constant [2 x i8] c"=\00" +@.str183 = private unnamed_addr constant [2 x i8] c"{\00" +@.str184 = private unnamed_addr constant [2 x i8] c"}\00" +@.str185 = private unnamed_addr constant [2 x i8] c"}\00" +@.str186 = private unnamed_addr constant [2 x i8] c"{\00" +@.str187 = private unnamed_addr constant [2 x i8] c"}\00" +@.str188 = private unnamed_addr constant [3 x i8] c"%t\00" +@.str189 = private unnamed_addr constant [3 x i8] c" \00" +@.str190 = private unnamed_addr constant [11 x i8] c" = alloca \00" +@.str191 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str192 = private unnamed_addr constant [3 x i8] c"%t\00" +@.str193 = private unnamed_addr constant [4 x i8] c"int\00" +@.str194 = private unnamed_addr constant [5 x i8] c"bool\00" +@.str195 = private unnamed_addr constant [6 x i8] c"fixed\00" +@.str196 = private unnamed_addr constant [4 x i8] c"i32\00" +@.str197 = private unnamed_addr constant [5 x i8] c"void\00" +@.str198 = private unnamed_addr constant [5 x i8] c"void\00" +@.str199 = private unnamed_addr constant [4 x i8] c"ptr\00" +@.str200 = private unnamed_addr constant [6 x i8] c"%Str_\00" +@.str201 = private unnamed_addr constant [6 x i8] c"%Cmp_\00" +@.str202 = private unnamed_addr constant [4 x i8] c"int\00" +@.str203 = private unnamed_addr constant [6 x i8] c"@.str\00" +@.str204 = private unnamed_addr constant [35 x i8] c" = private unnamed_addr constant [\00" +@.str205 = private unnamed_addr constant [10 x i8] c" x i8] c\22\00" +@.str206 = private unnamed_addr constant [6 x i8] c"\5C00\22\0A\00" +@.str207 = private unnamed_addr constant [3 x i8] c" \00" +@.str208 = private unnamed_addr constant [35 x i8] c" = getelementptr inbounds i8, ptr \00" +@.str209 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str210 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str211 = private unnamed_addr constant [4 x i8] c"ptr\00" +@.str212 = private unnamed_addr constant [5 x i8] c"null\00" +@.str213 = private unnamed_addr constant [2 x i8] c"0\00" +@.str214 = private unnamed_addr constant [2 x i8] c"-\00" +@.str215 = private unnamed_addr constant [2 x i8] c"-\00" +@.str216 = private unnamed_addr constant [4 x i8] c"ptr\00" +@.str217 = private unnamed_addr constant [5 x i8] c"null\00" +@.str218 = private unnamed_addr constant [2 x i8] c"0\00" +@.str219 = private unnamed_addr constant [34 x i8] c"; Ludic (self-hosted) -> LLVM IR\0A\00" +@.str220 = private unnamed_addr constant [31 x i8] c"declare i32 @printf(ptr, ...)\0A\00" +@.str221 = private unnamed_addr constant [26 x i8] c"declare ptr @malloc(i64)\0A\00" +@.str222 = private unnamed_addr constant [32 x i8] c"declare ptr @realloc(ptr, i64)\0A\00" +@.str223 = private unnamed_addr constant [25 x i8] c"declare void @free(ptr)\0A\00" +@.str224 = private unnamed_addr constant [30 x i8] c"declare ptr @fopen(ptr, ptr)\0A\00" +@.str225 = private unnamed_addr constant [40 x i8] c"declare i64 @fread(ptr, i64, i64, ptr)\0A\00" +@.str226 = private unnamed_addr constant [41 x i8] c"declare i64 @fwrite(ptr, i64, i64, ptr)\0A\00" +@.str227 = private unnamed_addr constant [35 x i8] c"declare i32 @fseek(ptr, i64, i32)\0A\00" +@.str228 = private unnamed_addr constant [25 x i8] c"declare i64 @ftell(ptr)\0A\00" +@.str229 = private unnamed_addr constant [26 x i8] c"declare i32 @fclose(ptr)\0A\00" +@.str230 = private unnamed_addr constant [25 x i8] c"declare void @exit(i32)\0A\00" +@.str231 = private unnamed_addr constant [26 x i8] c"declare i32 @system(ptr)\0A\00" +@.str232 = private unnamed_addr constant [26 x i8] c"declare ptr @getenv(ptr)\0A\00" +@.str233 = private unnamed_addr constant [36 x i8] c"declare ptr @memcpy(ptr, ptr, i64)\0A\00" +@.str234 = private unnamed_addr constant [36 x i8] c"declare ptr @memset(ptr, i32, i64)\0A\00" +@.str235 = private unnamed_addr constant [26 x i8] c"declare i64 @strlen(ptr)\0A\00" +@.str236 = private unnamed_addr constant [24 x i8] c"declare i32 @getchar()\0A\00" +@.str237 = private unnamed_addr constant [27 x i8] c"declare i32 @putchar(i32)\0A\00" +@.str238 = private unnamed_addr constant [24 x i8] c"declare i64 @time(ptr)\0A\00" +@.str239 = private unnamed_addr constant [44 x i8] c"declare void @win_open(i32, i32, i32, ptr)\0A\00" +@.str240 = private unnamed_addr constant [25 x i8] c"declare i32 @win_poll()\0A\00" +@.str241 = private unnamed_addr constant [42 x i8] c"declare void @win_present(ptr, i32, i32)\0A\00" +@.str242 = private unnamed_addr constant [28 x i8] c"declare i32 @win_running()\0A\00" +@.str243 = private unnamed_addr constant [27 x i8] c"declare void @win_close()\0A\00" +@.str244 = private unnamed_addr constant [34 x i8] c"@__stderrp = external global ptr\0A\00" +@.str245 = private unnamed_addr constant [61 x i8] c"@.fmt_str = private unnamed_addr constant [3 x i8] c\22%s\5C00\22\0A\00" +@.str246 = private unnamed_addr constant [64 x i8] c"@.fmt_int = private unnamed_addr constant [4 x i8] c\22%d\5C0A\5C00\22\0A\00" +@.str247 = private unnamed_addr constant [33 x i8] c"@L_argc = internal global i32 0\0A\00" +@.str248 = private unnamed_addr constant [36 x i8] c"@L_argv = internal global ptr null\0A\00" +@.str249 = private unnamed_addr constant [46 x i8] c"@.gametitle = private unnamed_addr constant [\00" +@.str250 = private unnamed_addr constant [10 x i8] c" x i8] c\22\00" +@.str251 = private unnamed_addr constant [6 x i8] c"\5C00\22\0A\00" +@.str252 = private unnamed_addr constant [34 x i8] c"%LSlice = type { ptr, i32, i32 }\0A\00" +@.str253 = private unnamed_addr constant [6 x i8] c"%Str_\00" +@.str254 = private unnamed_addr constant [11 x i8] c" = type { \00" +@.str255 = private unnamed_addr constant [4 x i8] c"i32\00" +@.str256 = private unnamed_addr constant [3 x i8] c", \00" +@.str257 = private unnamed_addr constant [4 x i8] c" }\0A\00" +@.str258 = private unnamed_addr constant [4 x i8] c"@g_\00" +@.str259 = private unnamed_addr constant [20 x i8] c" = internal global \00" +@.str260 = private unnamed_addr constant [2 x i8] c" \00" +@.str261 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str262 = private unnamed_addr constant [32 x i8] c"member access on non-aggregate \00" +@.str263 = private unnamed_addr constant [15 x i8] c"no such field \00" +@.str264 = private unnamed_addr constant [3 x i8] c" \00" +@.str265 = private unnamed_addr constant [27 x i8] c" = getelementptr inbounds \00" +@.str266 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str267 = private unnamed_addr constant [14 x i8] c", i32 0, i32 \00" +@.str268 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str269 = private unnamed_addr constant [21 x i8] c"indexing a non-slice\00" +@.str270 = private unnamed_addr constant [3 x i8] c" \00" +@.str271 = private unnamed_addr constant [40 x i8] c" = getelementptr inbounds %LSlice, ptr \00" +@.str272 = private unnamed_addr constant [16 x i8] c", i32 0, i32 0\0A\00" +@.str273 = private unnamed_addr constant [3 x i8] c" \00" +@.str274 = private unnamed_addr constant [18 x i8] c" = load ptr, ptr \00" +@.str275 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str276 = private unnamed_addr constant [3 x i8] c" \00" +@.str277 = private unnamed_addr constant [27 x i8] c" = getelementptr inbounds \00" +@.str278 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str279 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str280 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str281 = private unnamed_addr constant [9 x i8] c"ptr_null\00" +@.str282 = private unnamed_addr constant [10 x i8] c"mem_alloc\00" +@.str283 = private unnamed_addr constant [12 x i8] c"mem_realloc\00" +@.str284 = private unnamed_addr constant [6 x i8] c"peek8\00" +@.str285 = private unnamed_addr constant [6 x i8] c"poke8\00" +@.str286 = private unnamed_addr constant [12 x i8] c"ptr_is_null\00" +@.str287 = private unnamed_addr constant [10 x i8] c"file_open\00" +@.str288 = private unnamed_addr constant [10 x i8] c"file_read\00" +@.str289 = private unnamed_addr constant [11 x i8] c"file_write\00" +@.str290 = private unnamed_addr constant [10 x i8] c"file_seek\00" +@.str291 = private unnamed_addr constant [10 x i8] c"file_tell\00" +@.str292 = private unnamed_addr constant [11 x i8] c"file_close\00" +@.str293 = private unnamed_addr constant [10 x i8] c"print_str\00" +@.str294 = private unnamed_addr constant [10 x i8] c"print_int\00" +@.str295 = private unnamed_addr constant [8 x i8] c"os_argc\00" +@.str296 = private unnamed_addr constant [7 x i8] c"os_arg\00" +@.str297 = private unnamed_addr constant [8 x i8] c"os_exit\00" +@.str298 = private unnamed_addr constant [12 x i8] c"file_stderr\00" +@.str299 = private unnamed_addr constant [10 x i8] c"os_system\00" +@.str300 = private unnamed_addr constant [10 x i8] c"os_getenv\00" +@.str301 = private unnamed_addr constant [4 x i8] c"shl\00" +@.str302 = private unnamed_addr constant [4 x i8] c"shr\00" +@.str303 = private unnamed_addr constant [5 x i8] c"band\00" +@.str304 = private unnamed_addr constant [4 x i8] c"bor\00" +@.str305 = private unnamed_addr constant [5 x i8] c"bxor\00" +@.str306 = private unnamed_addr constant [5 x i8] c"bnot\00" +@.str307 = private unnamed_addr constant [7 x i8] c"peek32\00" +@.str308 = private unnamed_addr constant [7 x i8] c"poke32\00" +@.str309 = private unnamed_addr constant [3 x i8] c" \00" +@.str310 = private unnamed_addr constant [4 x i8] c" = \00" +@.str311 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str312 = private unnamed_addr constant [9 x i8] c"ptr_null\00" +@.str313 = private unnamed_addr constant [5 x i8] c"null\00" +@.str314 = private unnamed_addr constant [4 x i8] c"ptr\00" +@.str315 = private unnamed_addr constant [10 x i8] c"mem_alloc\00" +@.str316 = private unnamed_addr constant [10 x i8] c"zext i32 \00" +@.str317 = private unnamed_addr constant [8 x i8] c" to i64\00" +@.str318 = private unnamed_addr constant [22 x i8] c"call ptr @malloc(i64 \00" +@.str319 = private unnamed_addr constant [2 x i8] c")\00" +@.str320 = private unnamed_addr constant [4 x i8] c"ptr\00" +@.str321 = private unnamed_addr constant [12 x i8] c"mem_realloc\00" +@.str322 = private unnamed_addr constant [10 x i8] c"zext i32 \00" +@.str323 = private unnamed_addr constant [8 x i8] c" to i64\00" +@.str324 = private unnamed_addr constant [23 x i8] c"call ptr @realloc(ptr \00" +@.str325 = private unnamed_addr constant [7 x i8] c", i64 \00" +@.str326 = private unnamed_addr constant [2 x i8] c")\00" +@.str327 = private unnamed_addr constant [4 x i8] c"ptr\00" +@.str328 = private unnamed_addr constant [6 x i8] c"peek8\00" +@.str329 = private unnamed_addr constant [14 x i8] c"load i8, ptr \00" +@.str330 = private unnamed_addr constant [9 x i8] c"zext i8 \00" +@.str331 = private unnamed_addr constant [8 x i8] c" to i32\00" +@.str332 = private unnamed_addr constant [4 x i8] c"int\00" +@.str333 = private unnamed_addr constant [6 x i8] c"poke8\00" +@.str334 = private unnamed_addr constant [11 x i8] c"trunc i32 \00" +@.str335 = private unnamed_addr constant [7 x i8] c" to i8\00" +@.str336 = private unnamed_addr constant [12 x i8] c" store i8 \00" +@.str337 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str338 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str339 = private unnamed_addr constant [2 x i8] c"0\00" +@.str340 = private unnamed_addr constant [5 x i8] c"void\00" +@.str341 = private unnamed_addr constant [12 x i8] c"ptr_is_null\00" +@.str342 = private unnamed_addr constant [13 x i8] c"icmp eq ptr \00" +@.str343 = private unnamed_addr constant [7 x i8] c", null\00" +@.str344 = private unnamed_addr constant [9 x i8] c"zext i1 \00" +@.str345 = private unnamed_addr constant [8 x i8] c" to i32\00" +@.str346 = private unnamed_addr constant [5 x i8] c"bool\00" +@.str347 = private unnamed_addr constant [10 x i8] c"file_open\00" +@.str348 = private unnamed_addr constant [21 x i8] c"call ptr @fopen(ptr \00" +@.str349 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str350 = private unnamed_addr constant [2 x i8] c")\00" +@.str351 = private unnamed_addr constant [4 x i8] c"ptr\00" +@.str352 = private unnamed_addr constant [10 x i8] c"file_read\00" +@.str353 = private unnamed_addr constant [11 x i8] c"file_write\00" +@.str354 = private unnamed_addr constant [10 x i8] c"zext i32 \00" +@.str355 = private unnamed_addr constant [8 x i8] c" to i64\00" +@.str356 = private unnamed_addr constant [7 x i8] c"@fread\00" +@.str357 = private unnamed_addr constant [11 x i8] c"file_write\00" +@.str358 = private unnamed_addr constant [8 x i8] c"@fwrite\00" +@.str359 = private unnamed_addr constant [10 x i8] c"call i64 \00" +@.str360 = private unnamed_addr constant [6 x i8] c"(ptr \00" +@.str361 = private unnamed_addr constant [14 x i8] c", i64 1, i64 \00" +@.str362 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str363 = private unnamed_addr constant [2 x i8] c")\00" +@.str364 = private unnamed_addr constant [11 x i8] c"trunc i64 \00" +@.str365 = private unnamed_addr constant [8 x i8] c" to i32\00" +@.str366 = private unnamed_addr constant [4 x i8] c"int\00" +@.str367 = private unnamed_addr constant [10 x i8] c"file_seek\00" +@.str368 = private unnamed_addr constant [10 x i8] c"sext i32 \00" +@.str369 = private unnamed_addr constant [8 x i8] c" to i64\00" +@.str370 = private unnamed_addr constant [21 x i8] c"call i32 @fseek(ptr \00" +@.str371 = private unnamed_addr constant [7 x i8] c", i64 \00" +@.str372 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str373 = private unnamed_addr constant [2 x i8] c")\00" +@.str374 = private unnamed_addr constant [4 x i8] c"int\00" +@.str375 = private unnamed_addr constant [10 x i8] c"file_tell\00" +@.str376 = private unnamed_addr constant [21 x i8] c"call i64 @ftell(ptr \00" +@.str377 = private unnamed_addr constant [2 x i8] c")\00" +@.str378 = private unnamed_addr constant [11 x i8] c"trunc i64 \00" +@.str379 = private unnamed_addr constant [8 x i8] c" to i32\00" +@.str380 = private unnamed_addr constant [4 x i8] c"int\00" +@.str381 = private unnamed_addr constant [11 x i8] c"file_close\00" +@.str382 = private unnamed_addr constant [24 x i8] c" call i32 @fclose(ptr \00" +@.str383 = private unnamed_addr constant [3 x i8] c")\0A\00" +@.str384 = private unnamed_addr constant [2 x i8] c"0\00" +@.str385 = private unnamed_addr constant [5 x i8] c"void\00" +@.str386 = private unnamed_addr constant [10 x i8] c"print_str\00" +@.str387 = private unnamed_addr constant [50 x i8] c" call i32 (ptr, ...) @printf(ptr @.fmt_str, ptr \00" +@.str388 = private unnamed_addr constant [3 x i8] c")\0A\00" +@.str389 = private unnamed_addr constant [2 x i8] c"0\00" +@.str390 = private unnamed_addr constant [5 x i8] c"void\00" +@.str391 = private unnamed_addr constant [10 x i8] c"print_int\00" +@.str392 = private unnamed_addr constant [50 x i8] c" call i32 (ptr, ...) @printf(ptr @.fmt_int, i32 \00" +@.str393 = private unnamed_addr constant [3 x i8] c")\0A\00" +@.str394 = private unnamed_addr constant [2 x i8] c"0\00" +@.str395 = private unnamed_addr constant [5 x i8] c"void\00" +@.str396 = private unnamed_addr constant [8 x i8] c"os_argc\00" +@.str397 = private unnamed_addr constant [22 x i8] c"load i32, ptr @L_argc\00" +@.str398 = private unnamed_addr constant [4 x i8] c"int\00" +@.str399 = private unnamed_addr constant [7 x i8] c"os_arg\00" +@.str400 = private unnamed_addr constant [22 x i8] c"load ptr, ptr @L_argv\00" +@.str401 = private unnamed_addr constant [24 x i8] c"getelementptr ptr, ptr \00" +@.str402 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str403 = private unnamed_addr constant [15 x i8] c"load ptr, ptr \00" +@.str404 = private unnamed_addr constant [4 x i8] c"str\00" +@.str405 = private unnamed_addr constant [8 x i8] c"os_exit\00" +@.str406 = private unnamed_addr constant [23 x i8] c" call void @exit(i32 \00" +@.str407 = private unnamed_addr constant [3 x i8] c")\0A\00" +@.str408 = private unnamed_addr constant [15 x i8] c" unreachable\0A\00" +@.str409 = private unnamed_addr constant [2 x i8] c"0\00" +@.str410 = private unnamed_addr constant [5 x i8] c"void\00" +@.str411 = private unnamed_addr constant [12 x i8] c"file_stderr\00" +@.str412 = private unnamed_addr constant [25 x i8] c"load ptr, ptr @__stderrp\00" +@.str413 = private unnamed_addr constant [4 x i8] c"ptr\00" +@.str414 = private unnamed_addr constant [10 x i8] c"os_system\00" +@.str415 = private unnamed_addr constant [22 x i8] c"call i32 @system(ptr \00" +@.str416 = private unnamed_addr constant [2 x i8] c")\00" +@.str417 = private unnamed_addr constant [4 x i8] c"int\00" +@.str418 = private unnamed_addr constant [10 x i8] c"os_getenv\00" +@.str419 = private unnamed_addr constant [22 x i8] c"call ptr @getenv(ptr \00" +@.str420 = private unnamed_addr constant [2 x i8] c")\00" +@.str421 = private unnamed_addr constant [4 x i8] c"str\00" +@.str422 = private unnamed_addr constant [5 x i8] c"bnot\00" +@.str423 = private unnamed_addr constant [9 x i8] c"xor i32 \00" +@.str424 = private unnamed_addr constant [5 x i8] c", -1\00" +@.str425 = private unnamed_addr constant [4 x i8] c"int\00" +@.str426 = private unnamed_addr constant [4 x i8] c"shl\00" +@.str427 = private unnamed_addr constant [4 x i8] c"shr\00" +@.str428 = private unnamed_addr constant [5 x i8] c"band\00" +@.str429 = private unnamed_addr constant [4 x i8] c"bor\00" +@.str430 = private unnamed_addr constant [5 x i8] c"bxor\00" +@.str431 = private unnamed_addr constant [4 x i8] c"shl\00" +@.str432 = private unnamed_addr constant [4 x i8] c"shr\00" +@.str433 = private unnamed_addr constant [5 x i8] c"lshr\00" +@.str434 = private unnamed_addr constant [5 x i8] c"band\00" +@.str435 = private unnamed_addr constant [4 x i8] c"and\00" +@.str436 = private unnamed_addr constant [4 x i8] c"bor\00" +@.str437 = private unnamed_addr constant [3 x i8] c"or\00" +@.str438 = private unnamed_addr constant [5 x i8] c"bxor\00" +@.str439 = private unnamed_addr constant [4 x i8] c"xor\00" +@.str440 = private unnamed_addr constant [6 x i8] c" i32 \00" +@.str441 = private unnamed_addr constant [3 x i8] c", \00" +@.str442 = private unnamed_addr constant [4 x i8] c"int\00" +@.str443 = private unnamed_addr constant [7 x i8] c"peek32\00" +@.str444 = private unnamed_addr constant [3 x i8] c" \00" +@.str445 = private unnamed_addr constant [36 x i8] c" = getelementptr inbounds i32, ptr \00" +@.str446 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str447 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str448 = private unnamed_addr constant [15 x i8] c"load i32, ptr \00" +@.str449 = private unnamed_addr constant [4 x i8] c"int\00" +@.str450 = private unnamed_addr constant [7 x i8] c"poke32\00" +@.str451 = private unnamed_addr constant [3 x i8] c" \00" +@.str452 = private unnamed_addr constant [36 x i8] c" = getelementptr inbounds i32, ptr \00" +@.str453 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str454 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str455 = private unnamed_addr constant [13 x i8] c" store i32 \00" +@.str456 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str457 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str458 = private unnamed_addr constant [2 x i8] c"0\00" +@.str459 = private unnamed_addr constant [5 x i8] c"void\00" +@.str460 = private unnamed_addr constant [2 x i8] c"0\00" +@.str461 = private unnamed_addr constant [5 x i8] c"void\00" +@.str462 = private unnamed_addr constant [9 x i8] c"mem_free\00" +@.str463 = private unnamed_addr constant [9 x i8] c"mem_copy\00" +@.str464 = private unnamed_addr constant [8 x i8] c"mem_set\00" +@.str465 = private unnamed_addr constant [8 x i8] c"ptr_add\00" +@.str466 = private unnamed_addr constant [10 x i8] c"read_byte\00" +@.str467 = private unnamed_addr constant [11 x i8] c"write_byte\00" +@.str468 = private unnamed_addr constant [8 x i8] c"str_len\00" +@.str469 = private unnamed_addr constant [8 x i8] c"os_time\00" +@.str470 = private unnamed_addr constant [6 x i8] c"peekf\00" +@.str471 = private unnamed_addr constant [6 x i8] c"pokef\00" +@.str472 = private unnamed_addr constant [9 x i8] c"as_fixed\00" +@.str473 = private unnamed_addr constant [7 x i8] c"as_int\00" +@.str474 = private unnamed_addr constant [6 x i8] c"peekp\00" +@.str475 = private unnamed_addr constant [6 x i8] c"pokep\00" +@.str476 = private unnamed_addr constant [12 x i8] c"is_windowed\00" +@.str477 = private unnamed_addr constant [11 x i8] c"game_title\00" +@.str478 = private unnamed_addr constant [9 x i8] c"win_open\00" +@.str479 = private unnamed_addr constant [9 x i8] c"win_poll\00" +@.str480 = private unnamed_addr constant [12 x i8] c"win_present\00" +@.str481 = private unnamed_addr constant [12 x i8] c"win_running\00" +@.str482 = private unnamed_addr constant [10 x i8] c"win_close\00" +@.str483 = private unnamed_addr constant [9 x i8] c"mem_free\00" +@.str484 = private unnamed_addr constant [23 x i8] c" call void @free(ptr \00" +@.str485 = private unnamed_addr constant [3 x i8] c")\0A\00" +@.str486 = private unnamed_addr constant [2 x i8] c"0\00" +@.str487 = private unnamed_addr constant [5 x i8] c"void\00" +@.str488 = private unnamed_addr constant [9 x i8] c"mem_copy\00" +@.str489 = private unnamed_addr constant [10 x i8] c"zext i32 \00" +@.str490 = private unnamed_addr constant [8 x i8] c" to i64\00" +@.str491 = private unnamed_addr constant [24 x i8] c" call ptr @memcpy(ptr \00" +@.str492 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str493 = private unnamed_addr constant [7 x i8] c", i64 \00" +@.str494 = private unnamed_addr constant [3 x i8] c")\0A\00" +@.str495 = private unnamed_addr constant [2 x i8] c"0\00" +@.str496 = private unnamed_addr constant [5 x i8] c"void\00" +@.str497 = private unnamed_addr constant [8 x i8] c"mem_set\00" +@.str498 = private unnamed_addr constant [10 x i8] c"zext i32 \00" +@.str499 = private unnamed_addr constant [8 x i8] c" to i64\00" +@.str500 = private unnamed_addr constant [24 x i8] c" call ptr @memset(ptr \00" +@.str501 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str502 = private unnamed_addr constant [7 x i8] c", i64 \00" +@.str503 = private unnamed_addr constant [3 x i8] c")\0A\00" +@.str504 = private unnamed_addr constant [2 x i8] c"0\00" +@.str505 = private unnamed_addr constant [5 x i8] c"void\00" +@.str506 = private unnamed_addr constant [8 x i8] c"ptr_add\00" +@.str507 = private unnamed_addr constant [3 x i8] c" \00" +@.str508 = private unnamed_addr constant [35 x i8] c" = getelementptr inbounds i8, ptr \00" +@.str509 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str510 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str511 = private unnamed_addr constant [4 x i8] c"ptr\00" +@.str512 = private unnamed_addr constant [10 x i8] c"read_byte\00" +@.str513 = private unnamed_addr constant [20 x i8] c"call i32 @getchar()\00" +@.str514 = private unnamed_addr constant [4 x i8] c"int\00" +@.str515 = private unnamed_addr constant [11 x i8] c"write_byte\00" +@.str516 = private unnamed_addr constant [25 x i8] c" call i32 @putchar(i32 \00" +@.str517 = private unnamed_addr constant [3 x i8] c")\0A\00" +@.str518 = private unnamed_addr constant [2 x i8] c"0\00" +@.str519 = private unnamed_addr constant [5 x i8] c"void\00" +@.str520 = private unnamed_addr constant [8 x i8] c"str_len\00" +@.str521 = private unnamed_addr constant [22 x i8] c"call i64 @strlen(ptr \00" +@.str522 = private unnamed_addr constant [2 x i8] c")\00" +@.str523 = private unnamed_addr constant [11 x i8] c"trunc i64 \00" +@.str524 = private unnamed_addr constant [8 x i8] c" to i32\00" +@.str525 = private unnamed_addr constant [4 x i8] c"int\00" +@.str526 = private unnamed_addr constant [8 x i8] c"os_time\00" +@.str527 = private unnamed_addr constant [25 x i8] c"call i64 @time(ptr null)\00" +@.str528 = private unnamed_addr constant [11 x i8] c"trunc i64 \00" +@.str529 = private unnamed_addr constant [8 x i8] c" to i32\00" +@.str530 = private unnamed_addr constant [4 x i8] c"int\00" +@.str531 = private unnamed_addr constant [6 x i8] c"peekf\00" +@.str532 = private unnamed_addr constant [3 x i8] c" \00" +@.str533 = private unnamed_addr constant [36 x i8] c" = getelementptr inbounds i32, ptr \00" +@.str534 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str535 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str536 = private unnamed_addr constant [15 x i8] c"load i32, ptr \00" +@.str537 = private unnamed_addr constant [6 x i8] c"fixed\00" +@.str538 = private unnamed_addr constant [6 x i8] c"pokef\00" +@.str539 = private unnamed_addr constant [3 x i8] c" \00" +@.str540 = private unnamed_addr constant [36 x i8] c" = getelementptr inbounds i32, ptr \00" +@.str541 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str542 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str543 = private unnamed_addr constant [13 x i8] c" store i32 \00" +@.str544 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str545 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str546 = private unnamed_addr constant [2 x i8] c"0\00" +@.str547 = private unnamed_addr constant [5 x i8] c"void\00" +@.str548 = private unnamed_addr constant [6 x i8] c"peekp\00" +@.str549 = private unnamed_addr constant [3 x i8] c" \00" +@.str550 = private unnamed_addr constant [36 x i8] c" = getelementptr inbounds ptr, ptr \00" +@.str551 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str552 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str553 = private unnamed_addr constant [15 x i8] c"load ptr, ptr \00" +@.str554 = private unnamed_addr constant [4 x i8] c"ptr\00" +@.str555 = private unnamed_addr constant [6 x i8] c"pokep\00" +@.str556 = private unnamed_addr constant [3 x i8] c" \00" +@.str557 = private unnamed_addr constant [36 x i8] c" = getelementptr inbounds ptr, ptr \00" +@.str558 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str559 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str560 = private unnamed_addr constant [13 x i8] c" store ptr \00" +@.str561 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str562 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str563 = private unnamed_addr constant [2 x i8] c"0\00" +@.str564 = private unnamed_addr constant [5 x i8] c"void\00" +@.str565 = private unnamed_addr constant [9 x i8] c"as_fixed\00" +@.str566 = private unnamed_addr constant [6 x i8] c"fixed\00" +@.str567 = private unnamed_addr constant [7 x i8] c"as_int\00" +@.str568 = private unnamed_addr constant [4 x i8] c"int\00" +@.str569 = private unnamed_addr constant [12 x i8] c"is_windowed\00" +@.str570 = private unnamed_addr constant [2 x i8] c"1\00" +@.str571 = private unnamed_addr constant [5 x i8] c"bool\00" +@.str572 = private unnamed_addr constant [2 x i8] c"0\00" +@.str573 = private unnamed_addr constant [5 x i8] c"bool\00" +@.str574 = private unnamed_addr constant [11 x i8] c"game_title\00" +@.str575 = private unnamed_addr constant [12 x i8] c"@.gametitle\00" +@.str576 = private unnamed_addr constant [4 x i8] c"str\00" +@.str577 = private unnamed_addr constant [9 x i8] c"win_poll\00" +@.str578 = private unnamed_addr constant [21 x i8] c"call i32 @win_poll()\00" +@.str579 = private unnamed_addr constant [4 x i8] c"int\00" +@.str580 = private unnamed_addr constant [12 x i8] c"win_running\00" +@.str581 = private unnamed_addr constant [24 x i8] c"call i32 @win_running()\00" +@.str582 = private unnamed_addr constant [5 x i8] c"bool\00" +@.str583 = private unnamed_addr constant [9 x i8] c"win_open\00" +@.str584 = private unnamed_addr constant [27 x i8] c" call void @win_open(i32 \00" +@.str585 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str586 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str587 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str588 = private unnamed_addr constant [3 x i8] c")\0A\00" +@.str589 = private unnamed_addr constant [2 x i8] c"0\00" +@.str590 = private unnamed_addr constant [5 x i8] c"void\00" +@.str591 = private unnamed_addr constant [12 x i8] c"win_present\00" +@.str592 = private unnamed_addr constant [30 x i8] c" call void @win_present(ptr \00" +@.str593 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str594 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str595 = private unnamed_addr constant [3 x i8] c")\0A\00" +@.str596 = private unnamed_addr constant [2 x i8] c"0\00" +@.str597 = private unnamed_addr constant [5 x i8] c"void\00" +@.str598 = private unnamed_addr constant [10 x i8] c"win_close\00" +@.str599 = private unnamed_addr constant [26 x i8] c" call void @win_close()\0A\00" +@.str600 = private unnamed_addr constant [2 x i8] c"0\00" +@.str601 = private unnamed_addr constant [5 x i8] c"void\00" +@.str602 = private unnamed_addr constant [2 x i8] c"0\00" +@.str603 = private unnamed_addr constant [5 x i8] c"void\00" +@.str604 = private unnamed_addr constant [4 x i8] c"min\00" +@.str605 = private unnamed_addr constant [4 x i8] c"max\00" +@.str606 = private unnamed_addr constant [4 x i8] c"abs\00" +@.str607 = private unnamed_addr constant [6 x i8] c"clamp\00" +@.str608 = private unnamed_addr constant [4 x i8] c"abs\00" +@.str609 = private unnamed_addr constant [14 x i8] c"icmp slt i32 \00" +@.str610 = private unnamed_addr constant [4 x i8] c", 0\00" +@.str611 = private unnamed_addr constant [12 x i8] c"sub i32 0, \00" +@.str612 = private unnamed_addr constant [11 x i8] c"select i1 \00" +@.str613 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str614 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str615 = private unnamed_addr constant [4 x i8] c"int\00" +@.str616 = private unnamed_addr constant [4 x i8] c"min\00" +@.str617 = private unnamed_addr constant [4 x i8] c"max\00" +@.str618 = private unnamed_addr constant [4 x i8] c"slt\00" +@.str619 = private unnamed_addr constant [4 x i8] c"max\00" +@.str620 = private unnamed_addr constant [4 x i8] c"sgt\00" +@.str621 = private unnamed_addr constant [6 x i8] c"icmp \00" +@.str622 = private unnamed_addr constant [6 x i8] c" i32 \00" +@.str623 = private unnamed_addr constant [3 x i8] c", \00" +@.str624 = private unnamed_addr constant [11 x i8] c"select i1 \00" +@.str625 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str626 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str627 = private unnamed_addr constant [4 x i8] c"int\00" +@.str628 = private unnamed_addr constant [14 x i8] c"icmp slt i32 \00" +@.str629 = private unnamed_addr constant [3 x i8] c", \00" +@.str630 = private unnamed_addr constant [11 x i8] c"select i1 \00" +@.str631 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str632 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str633 = private unnamed_addr constant [14 x i8] c"icmp sgt i32 \00" +@.str634 = private unnamed_addr constant [3 x i8] c", \00" +@.str635 = private unnamed_addr constant [11 x i8] c"select i1 \00" +@.str636 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str637 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str638 = private unnamed_addr constant [4 x i8] c"int\00" +@.str639 = private unnamed_addr constant [15 x i8] c"getelementptr \00" +@.str640 = private unnamed_addr constant [18 x i8] c", ptr null, i32 1\00" +@.str641 = private unnamed_addr constant [14 x i8] c"ptrtoint ptr \00" +@.str642 = private unnamed_addr constant [8 x i8] c" to i64\00" +@.str643 = private unnamed_addr constant [22 x i8] c"unknown struct in new\00" +@.str644 = private unnamed_addr constant [6 x i8] c"%Str_\00" +@.str645 = private unnamed_addr constant [22 x i8] c"call ptr @malloc(i64 \00" +@.str646 = private unnamed_addr constant [2 x i8] c")\00" +@.str647 = private unnamed_addr constant [3 x i8] c" \00" +@.str648 = private unnamed_addr constant [32 x i8] c" = getelementptr inbounds %Str_\00" +@.str649 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str650 = private unnamed_addr constant [14 x i8] c", i32 0, i32 \00" +@.str651 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str652 = private unnamed_addr constant [2 x i8] c"0\00" +@.str653 = private unnamed_addr constant [4 x i8] c"ptr\00" +@.str654 = private unnamed_addr constant [5 x i8] c"null\00" +@.str655 = private unnamed_addr constant [9 x i8] c" store \00" +@.str656 = private unnamed_addr constant [2 x i8] c" \00" +@.str657 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str658 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str659 = private unnamed_addr constant [8 x i8] c"%LSlice\00" +@.str660 = private unnamed_addr constant [22 x i8] c"call ptr @malloc(i64 \00" +@.str661 = private unnamed_addr constant [2 x i8] c")\00" +@.str662 = private unnamed_addr constant [3 x i8] c" \00" +@.str663 = private unnamed_addr constant [40 x i8] c" = getelementptr inbounds %LSlice, ptr \00" +@.str664 = private unnamed_addr constant [16 x i8] c", i32 0, i32 0\0A\00" +@.str665 = private unnamed_addr constant [23 x i8] c" store ptr null, ptr \00" +@.str666 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str667 = private unnamed_addr constant [3 x i8] c" \00" +@.str668 = private unnamed_addr constant [40 x i8] c" = getelementptr inbounds %LSlice, ptr \00" +@.str669 = private unnamed_addr constant [16 x i8] c", i32 0, i32 1\0A\00" +@.str670 = private unnamed_addr constant [20 x i8] c" store i32 0, ptr \00" +@.str671 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str672 = private unnamed_addr constant [3 x i8] c" \00" +@.str673 = private unnamed_addr constant [40 x i8] c" = getelementptr inbounds %LSlice, ptr \00" +@.str674 = private unnamed_addr constant [16 x i8] c", i32 0, i32 2\0A\00" +@.str675 = private unnamed_addr constant [20 x i8] c" store i32 0, ptr \00" +@.str676 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str677 = private unnamed_addr constant [3 x i8] c" \00" +@.str678 = private unnamed_addr constant [40 x i8] c" = getelementptr inbounds %LSlice, ptr \00" +@.str679 = private unnamed_addr constant [14 x i8] c", i32 0, i32 \00" +@.str680 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str681 = private unnamed_addr constant [15 x i8] c"load i32, ptr \00" +@.str682 = private unnamed_addr constant [4 x i8] c"int\00" +@.str683 = private unnamed_addr constant [15 x i8] c"load i32, ptr \00" +@.str684 = private unnamed_addr constant [15 x i8] c"load i32, ptr \00" +@.str685 = private unnamed_addr constant [14 x i8] c"icmp sge i32 \00" +@.str686 = private unnamed_addr constant [3 x i8] c", \00" +@.str687 = private unnamed_addr constant [5 x i8] c"grow\00" +@.str688 = private unnamed_addr constant [4 x i8] c"put\00" +@.str689 = private unnamed_addr constant [9 x i8] c" br i1 \00" +@.str690 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str691 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str692 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str693 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str694 = private unnamed_addr constant [9 x i8] c"mul i32 \00" +@.str695 = private unnamed_addr constant [4 x i8] c", 2\00" +@.str696 = private unnamed_addr constant [13 x i8] c"icmp eq i32 \00" +@.str697 = private unnamed_addr constant [4 x i8] c", 0\00" +@.str698 = private unnamed_addr constant [11 x i8] c"select i1 \00" +@.str699 = private unnamed_addr constant [14 x i8] c", i32 8, i32 \00" +@.str700 = private unnamed_addr constant [10 x i8] c"zext i32 \00" +@.str701 = private unnamed_addr constant [8 x i8] c" to i64\00" +@.str702 = private unnamed_addr constant [9 x i8] c"mul i64 \00" +@.str703 = private unnamed_addr constant [3 x i8] c", \00" +@.str704 = private unnamed_addr constant [15 x i8] c"load ptr, ptr \00" +@.str705 = private unnamed_addr constant [23 x i8] c"call ptr @realloc(ptr \00" +@.str706 = private unnamed_addr constant [7 x i8] c", i64 \00" +@.str707 = private unnamed_addr constant [2 x i8] c")\00" +@.str708 = private unnamed_addr constant [13 x i8] c" store ptr \00" +@.str709 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str710 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str711 = private unnamed_addr constant [13 x i8] c" store i32 \00" +@.str712 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str713 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str714 = private unnamed_addr constant [13 x i8] c" br label %\00" +@.str715 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str716 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str717 = private unnamed_addr constant [15 x i8] c"load ptr, ptr \00" +@.str718 = private unnamed_addr constant [3 x i8] c" \00" +@.str719 = private unnamed_addr constant [27 x i8] c" = getelementptr inbounds \00" +@.str720 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str721 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str722 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str723 = private unnamed_addr constant [9 x i8] c" store \00" +@.str724 = private unnamed_addr constant [2 x i8] c" \00" +@.str725 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str726 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str727 = private unnamed_addr constant [9 x i8] c"add i32 \00" +@.str728 = private unnamed_addr constant [4 x i8] c", 1\00" +@.str729 = private unnamed_addr constant [13 x i8] c" store i32 \00" +@.str730 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str731 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str732 = private unnamed_addr constant [2 x i8] c"0\00" +@.str733 = private unnamed_addr constant [5 x i8] c"void\00" +@.str734 = private unnamed_addr constant [6 x i8] c"load \00" +@.str735 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str736 = private unnamed_addr constant [4 x i8] c"i32\00" +@.str737 = private unnamed_addr constant [13 x i8] c"icmp ne i32 \00" +@.str738 = private unnamed_addr constant [4 x i8] c", 0\00" +@.str739 = private unnamed_addr constant [9 x i8] c"zext i1 \00" +@.str740 = private unnamed_addr constant [8 x i8] c" to i32\00" +@.str741 = private unnamed_addr constant [13 x i8] c" store i32 \00" +@.str742 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str743 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str744 = private unnamed_addr constant [3 x i8] c"sc\00" +@.str745 = private unnamed_addr constant [6 x i8] c"scend\00" +@.str746 = private unnamed_addr constant [4 x i8] c"and\00" +@.str747 = private unnamed_addr constant [9 x i8] c" br i1 \00" +@.str748 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str749 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str750 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str751 = private unnamed_addr constant [9 x i8] c" br i1 \00" +@.str752 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str753 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str754 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str755 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str756 = private unnamed_addr constant [13 x i8] c"icmp ne i32 \00" +@.str757 = private unnamed_addr constant [4 x i8] c", 0\00" +@.str758 = private unnamed_addr constant [9 x i8] c"zext i1 \00" +@.str759 = private unnamed_addr constant [8 x i8] c" to i32\00" +@.str760 = private unnamed_addr constant [13 x i8] c" store i32 \00" +@.str761 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str762 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str763 = private unnamed_addr constant [13 x i8] c" br label %\00" +@.str764 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str765 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str766 = private unnamed_addr constant [15 x i8] c"load i32, ptr \00" +@.str767 = private unnamed_addr constant [5 x i8] c"bool\00" +@.str768 = private unnamed_addr constant [2 x i8] c"<\00" +@.str769 = private unnamed_addr constant [4 x i8] c"slt\00" +@.str770 = private unnamed_addr constant [3 x i8] c"<=\00" +@.str771 = private unnamed_addr constant [4 x i8] c"sle\00" +@.str772 = private unnamed_addr constant [2 x i8] c">\00" +@.str773 = private unnamed_addr constant [4 x i8] c"sgt\00" +@.str774 = private unnamed_addr constant [3 x i8] c">=\00" +@.str775 = private unnamed_addr constant [4 x i8] c"sge\00" +@.str776 = private unnamed_addr constant [3 x i8] c"==\00" +@.str777 = private unnamed_addr constant [3 x i8] c"eq\00" +@.str778 = private unnamed_addr constant [3 x i8] c"ne\00" +@.str779 = private unnamed_addr constant [2 x i8] c"<\00" +@.str780 = private unnamed_addr constant [3 x i8] c"<=\00" +@.str781 = private unnamed_addr constant [2 x i8] c">\00" +@.str782 = private unnamed_addr constant [3 x i8] c">=\00" +@.str783 = private unnamed_addr constant [3 x i8] c"==\00" +@.str784 = private unnamed_addr constant [3 x i8] c"!=\00" +@.str785 = private unnamed_addr constant [2 x i8] c"+\00" +@.str786 = private unnamed_addr constant [4 x i8] c"add\00" +@.str787 = private unnamed_addr constant [2 x i8] c"-\00" +@.str788 = private unnamed_addr constant [4 x i8] c"sub\00" +@.str789 = private unnamed_addr constant [2 x i8] c"*\00" +@.str790 = private unnamed_addr constant [4 x i8] c"mul\00" +@.str791 = private unnamed_addr constant [2 x i8] c"/\00" +@.str792 = private unnamed_addr constant [5 x i8] c"sdiv\00" +@.str793 = private unnamed_addr constant [5 x i8] c"srem\00" +@.str794 = private unnamed_addr constant [6 x i8] c"fixed\00" +@.str795 = private unnamed_addr constant [9 x i8] c"shl i32 \00" +@.str796 = private unnamed_addr constant [5 x i8] c", 16\00" +@.str797 = private unnamed_addr constant [4 x i8] c"and\00" +@.str798 = private unnamed_addr constant [3 x i8] c"or\00" +@.str799 = private unnamed_addr constant [6 x i8] c"fixed\00" +@.str800 = private unnamed_addr constant [6 x i8] c"fixed\00" +@.str801 = private unnamed_addr constant [6 x i8] c"icmp \00" +@.str802 = private unnamed_addr constant [6 x i8] c" i32 \00" +@.str803 = private unnamed_addr constant [3 x i8] c", \00" +@.str804 = private unnamed_addr constant [9 x i8] c"zext i1 \00" +@.str805 = private unnamed_addr constant [8 x i8] c" to i32\00" +@.str806 = private unnamed_addr constant [5 x i8] c"bool\00" +@.str807 = private unnamed_addr constant [2 x i8] c"*\00" +@.str808 = private unnamed_addr constant [10 x i8] c"sext i32 \00" +@.str809 = private unnamed_addr constant [8 x i8] c" to i64\00" +@.str810 = private unnamed_addr constant [10 x i8] c"sext i32 \00" +@.str811 = private unnamed_addr constant [8 x i8] c" to i64\00" +@.str812 = private unnamed_addr constant [9 x i8] c"mul i64 \00" +@.str813 = private unnamed_addr constant [3 x i8] c", \00" +@.str814 = private unnamed_addr constant [10 x i8] c"ashr i64 \00" +@.str815 = private unnamed_addr constant [5 x i8] c", 16\00" +@.str816 = private unnamed_addr constant [11 x i8] c"trunc i64 \00" +@.str817 = private unnamed_addr constant [8 x i8] c" to i32\00" +@.str818 = private unnamed_addr constant [6 x i8] c"fixed\00" +@.str819 = private unnamed_addr constant [2 x i8] c"/\00" +@.str820 = private unnamed_addr constant [10 x i8] c"sext i32 \00" +@.str821 = private unnamed_addr constant [8 x i8] c" to i64\00" +@.str822 = private unnamed_addr constant [9 x i8] c"shl i64 \00" +@.str823 = private unnamed_addr constant [5 x i8] c", 16\00" +@.str824 = private unnamed_addr constant [10 x i8] c"sext i32 \00" +@.str825 = private unnamed_addr constant [8 x i8] c" to i64\00" +@.str826 = private unnamed_addr constant [10 x i8] c"sdiv i64 \00" +@.str827 = private unnamed_addr constant [3 x i8] c", \00" +@.str828 = private unnamed_addr constant [11 x i8] c"trunc i64 \00" +@.str829 = private unnamed_addr constant [8 x i8] c" to i32\00" +@.str830 = private unnamed_addr constant [6 x i8] c"fixed\00" +@.str831 = private unnamed_addr constant [6 x i8] c" i32 \00" +@.str832 = private unnamed_addr constant [3 x i8] c", \00" +@.str833 = private unnamed_addr constant [6 x i8] c"fixed\00" +@.str834 = private unnamed_addr constant [6 x i8] c" i32 \00" +@.str835 = private unnamed_addr constant [3 x i8] c", \00" +@.str836 = private unnamed_addr constant [4 x i8] c"int\00" +@.str837 = private unnamed_addr constant [5 x i8] c"self\00" +@.str838 = private unnamed_addr constant [2 x i8] c"0\00" +@.str839 = private unnamed_addr constant [7 x i8] c"entity\00" +@.str840 = private unnamed_addr constant [15 x i8] c"load i32, ptr \00" +@.str841 = private unnamed_addr constant [7 x i8] c"entity\00" +@.str842 = private unnamed_addr constant [4 x i8] c"key\00" +@.str843 = private unnamed_addr constant [21 x i8] c"load i32, ptr @L_key\00" +@.str844 = private unnamed_addr constant [4 x i8] c"int\00" +@.str845 = private unnamed_addr constant [5 x i8] c"save\00" +@.str846 = private unnamed_addr constant [23 x i8] c" call void @L_save()\0A\00" +@.str847 = private unnamed_addr constant [2 x i8] c"0\00" +@.str848 = private unnamed_addr constant [5 x i8] c"void\00" +@.str849 = private unnamed_addr constant [9 x i8] c"ui_build\00" +@.str850 = private unnamed_addr constant [25 x i8] c" call void @ui_build()\0A\00" +@.str851 = private unnamed_addr constant [2 x i8] c"0\00" +@.str852 = private unnamed_addr constant [5 x i8] c"void\00" +@.str853 = private unnamed_addr constant [5 x i8] c"load\00" +@.str854 = private unnamed_addr constant [19 x i8] c"call i32 @L_load()\00" +@.str855 = private unnamed_addr constant [5 x i8] c"bool\00" +@.str856 = private unnamed_addr constant [5 x i8] c"quit\00" +@.str857 = private unnamed_addr constant [31 x i8] c" store i32 0, ptr @L_running\0A\00" +@.str858 = private unnamed_addr constant [2 x i8] c"0\00" +@.str859 = private unnamed_addr constant [5 x i8] c"void\00" +@.str860 = private unnamed_addr constant [4 x i8] c"len\00" +@.str861 = private unnamed_addr constant [5 x i8] c"push\00" +@.str862 = private unnamed_addr constant [3 x i8] c"fx\00" +@.str863 = private unnamed_addr constant [9 x i8] c"shl i32 \00" +@.str864 = private unnamed_addr constant [5 x i8] c", 16\00" +@.str865 = private unnamed_addr constant [6 x i8] c"fixed\00" +@.str866 = private unnamed_addr constant [4 x i8] c"flr\00" +@.str867 = private unnamed_addr constant [10 x i8] c"ashr i32 \00" +@.str868 = private unnamed_addr constant [5 x i8] c", 16\00" +@.str869 = private unnamed_addr constant [4 x i8] c"int\00" +@.str870 = private unnamed_addr constant [4 x i8] c"rt_\00" +@.str871 = private unnamed_addr constant [18 x i8] c"unknown function \00" +@.str872 = private unnamed_addr constant [3 x i8] c" \00" +@.str873 = private unnamed_addr constant [2 x i8] c"0\00" +@.str874 = private unnamed_addr constant [5 x i8] c"void\00" +@.str875 = private unnamed_addr constant [4 x i8] c" = \00" +@.str876 = private unnamed_addr constant [6 x i8] c"call \00" +@.str877 = private unnamed_addr constant [6 x i8] c" @fn_\00" +@.str878 = private unnamed_addr constant [2 x i8] c"(\00" +@.str879 = private unnamed_addr constant [3 x i8] c", \00" +@.str880 = private unnamed_addr constant [2 x i8] c" \00" +@.str881 = private unnamed_addr constant [3 x i8] c")\0A\00" +@.str882 = private unnamed_addr constant [2 x i8] c"0\00" +@.str883 = private unnamed_addr constant [4 x i8] c"int\00" +@.str884 = private unnamed_addr constant [4 x i8] c"int\00" +@.str885 = private unnamed_addr constant [6 x i8] c"fixed\00" +@.str886 = private unnamed_addr constant [5 x i8] c"bool\00" +@.str887 = private unnamed_addr constant [4 x i8] c"str\00" +@.str888 = private unnamed_addr constant [4 x i8] c"int\00" +@.str889 = private unnamed_addr constant [6 x i8] c"load \00" +@.str890 = private unnamed_addr constant [10 x i8] c", ptr @g_\00" +@.str891 = private unnamed_addr constant [4 x i8] c"int\00" +@.str892 = private unnamed_addr constant [20 x i8] c"unknown identifier \00" +@.str893 = private unnamed_addr constant [2 x i8] c"-\00" +@.str894 = private unnamed_addr constant [12 x i8] c"sub i32 0, \00" +@.str895 = private unnamed_addr constant [4 x i8] c"int\00" +@.str896 = private unnamed_addr constant [13 x i8] c"icmp eq i32 \00" +@.str897 = private unnamed_addr constant [4 x i8] c", 0\00" +@.str898 = private unnamed_addr constant [9 x i8] c"zext i1 \00" +@.str899 = private unnamed_addr constant [8 x i8] c" to i32\00" +@.str900 = private unnamed_addr constant [5 x i8] c"bool\00" +@.str901 = private unnamed_addr constant [23 x i8] c"cannot emit expression\00" +@.str902 = private unnamed_addr constant [2 x i8] c"0\00" +@.str903 = private unnamed_addr constant [4 x i8] c"int\00" +@.str904 = private unnamed_addr constant [9 x i8] c" store \00" +@.str905 = private unnamed_addr constant [2 x i8] c" \00" +@.str906 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str907 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str908 = private unnamed_addr constant [2 x i8] c"0\00" +@.str909 = private unnamed_addr constant [4 x i8] c"int\00" +@.str910 = private unnamed_addr constant [19 x i8] c"assign to unknown \00" +@.str911 = private unnamed_addr constant [4 x i8] c"@g_\00" +@.str912 = private unnamed_addr constant [22 x i8] c"bad assignment target\00" +@.str913 = private unnamed_addr constant [2 x i8] c"=\00" +@.str914 = private unnamed_addr constant [6 x i8] c"load \00" +@.str915 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str916 = private unnamed_addr constant [4 x i8] c"add\00" +@.str917 = private unnamed_addr constant [3 x i8] c"-=\00" +@.str918 = private unnamed_addr constant [4 x i8] c"sub\00" +@.str919 = private unnamed_addr constant [3 x i8] c"*=\00" +@.str920 = private unnamed_addr constant [4 x i8] c"mul\00" +@.str921 = private unnamed_addr constant [3 x i8] c"/=\00" +@.str922 = private unnamed_addr constant [5 x i8] c"sdiv\00" +@.str923 = private unnamed_addr constant [6 x i8] c" i32 \00" +@.str924 = private unnamed_addr constant [3 x i8] c", \00" +@.str925 = private unnamed_addr constant [13 x i8] c"icmp ne i32 \00" +@.str926 = private unnamed_addr constant [4 x i8] c", 0\00" +@.str927 = private unnamed_addr constant [5 x i8] c"then\00" +@.str928 = private unnamed_addr constant [5 x i8] c"else\00" +@.str929 = private unnamed_addr constant [6 x i8] c"ifend\00" +@.str930 = private unnamed_addr constant [9 x i8] c" br i1 \00" +@.str931 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str932 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str933 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str934 = private unnamed_addr constant [9 x i8] c" br i1 \00" +@.str935 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str936 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str937 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str938 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str939 = private unnamed_addr constant [13 x i8] c" br label %\00" +@.str940 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str941 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str942 = private unnamed_addr constant [13 x i8] c" br label %\00" +@.str943 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str944 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str945 = private unnamed_addr constant [6 x i8] c"wcond\00" +@.str946 = private unnamed_addr constant [6 x i8] c"wbody\00" +@.str947 = private unnamed_addr constant [5 x i8] c"wend\00" +@.str948 = private unnamed_addr constant [13 x i8] c" br label %\00" +@.str949 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str950 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str951 = private unnamed_addr constant [13 x i8] c"icmp ne i32 \00" +@.str952 = private unnamed_addr constant [4 x i8] c", 0\00" +@.str953 = private unnamed_addr constant [9 x i8] c" br i1 \00" +@.str954 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str955 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str956 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str957 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str958 = private unnamed_addr constant [13 x i8] c" br label %\00" +@.str959 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str960 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str961 = private unnamed_addr constant [4 x i8] c"i32\00" +@.str962 = private unnamed_addr constant [4 x i8] c"i32\00" +@.str963 = private unnamed_addr constant [4 x i8] c"int\00" +@.str964 = private unnamed_addr constant [6 x i8] c"fcond\00" +@.str965 = private unnamed_addr constant [6 x i8] c"fbody\00" +@.str966 = private unnamed_addr constant [6 x i8] c"fcont\00" +@.str967 = private unnamed_addr constant [5 x i8] c"fend\00" +@.str968 = private unnamed_addr constant [13 x i8] c" br label %\00" +@.str969 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str970 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str971 = private unnamed_addr constant [15 x i8] c"load i32, ptr \00" +@.str972 = private unnamed_addr constant [14 x i8] c"icmp slt i32 \00" +@.str973 = private unnamed_addr constant [3 x i8] c", \00" +@.str974 = private unnamed_addr constant [9 x i8] c" br i1 \00" +@.str975 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str976 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str977 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str978 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str979 = private unnamed_addr constant [13 x i8] c" br label %\00" +@.str980 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str981 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str982 = private unnamed_addr constant [15 x i8] c"load i32, ptr \00" +@.str983 = private unnamed_addr constant [9 x i8] c"add i32 \00" +@.str984 = private unnamed_addr constant [4 x i8] c", 1\00" +@.str985 = private unnamed_addr constant [4 x i8] c"i32\00" +@.str986 = private unnamed_addr constant [13 x i8] c" br label %\00" +@.str987 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str988 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str989 = private unnamed_addr constant [8 x i8] c"%retval\00" +@.str990 = private unnamed_addr constant [17 x i8] c" br label %ret\0A\00" +@.str991 = private unnamed_addr constant [2 x i8] c"_\00" +@.str992 = private unnamed_addr constant [5 x i8] c"mend\00" +@.str993 = private unnamed_addr constant [2 x i8] c"0\00" +@.str994 = private unnamed_addr constant [13 x i8] c"icmp eq i32 \00" +@.str995 = private unnamed_addr constant [3 x i8] c", \00" +@.str996 = private unnamed_addr constant [7 x i8] c"or i1 \00" +@.str997 = private unnamed_addr constant [3 x i8] c", \00" +@.str998 = private unnamed_addr constant [6 x i8] c"mbody\00" +@.str999 = private unnamed_addr constant [5 x i8] c"marm\00" +@.str1000 = private unnamed_addr constant [9 x i8] c" br i1 \00" +@.str1001 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str1002 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str1003 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1004 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str1005 = private unnamed_addr constant [13 x i8] c" br label %\00" +@.str1006 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1007 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str1008 = private unnamed_addr constant [13 x i8] c" br label %\00" +@.str1009 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1010 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str1011 = private unnamed_addr constant [2 x i8] c"0\00" +@.str1012 = private unnamed_addr constant [4 x i8] c"ptr\00" +@.str1013 = private unnamed_addr constant [5 x i8] c"null\00" +@.str1014 = private unnamed_addr constant [13 x i8] c" br label %\00" +@.str1015 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1016 = private unnamed_addr constant [13 x i8] c" br label %\00" +@.str1017 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1018 = private unnamed_addr constant [22 x i8] c"cannot emit statement\00" +@.str1019 = private unnamed_addr constant [36 x i8] c"@L_running = internal global i32 1\0A\00" +@.str1020 = private unnamed_addr constant [32 x i8] c"@L_key = internal global i32 0\0A\00" +@.str1021 = private unnamed_addr constant [33 x i8] c"@L_entc = internal global i32 0\0A\00" +@.str1022 = private unnamed_addr constant [29 x i8] c"@L_alive = internal global [\00" +@.str1023 = private unnamed_addr constant [25 x i8] c" x i32] zeroinitializer\0A\00" +@.str1024 = private unnamed_addr constant [28 x i8] c"@L_kind = internal global [\00" +@.str1025 = private unnamed_addr constant [25 x i8] c" x i32] zeroinitializer\0A\00" +@.str1026 = private unnamed_addr constant [32 x i8] c"@L_freelist = internal global [\00" +@.str1027 = private unnamed_addr constant [25 x i8] c" x i32] zeroinitializer\0A\00" +@.str1028 = private unnamed_addr constant [34 x i8] c"@L_freen = internal global i32 0\0A\00" +@.str1029 = private unnamed_addr constant [6 x i8] c"%Cmp_\00" +@.str1030 = private unnamed_addr constant [11 x i8] c" = type { \00" +@.str1031 = private unnamed_addr constant [4 x i8] c"i32\00" +@.str1032 = private unnamed_addr constant [3 x i8] c", \00" +@.str1033 = private unnamed_addr constant [4 x i8] c" }\0A\00" +@.str1034 = private unnamed_addr constant [4 x i8] c"@S_\00" +@.str1035 = private unnamed_addr constant [21 x i8] c" = internal global [\00" +@.str1036 = private unnamed_addr constant [9 x i8] c" x %Cmp_\00" +@.str1037 = private unnamed_addr constant [19 x i8] c"] zeroinitializer\0A\00" +@.str1038 = private unnamed_addr constant [4 x i8] c"@H_\00" +@.str1039 = private unnamed_addr constant [21 x i8] c" = internal global [\00" +@.str1040 = private unnamed_addr constant [24 x i8] c" x i8] zeroinitializer\0A\00" +@.str1041 = private unnamed_addr constant [39 x i8] c"define void @L_reset(i32 %e) {\0Aentry:\0A\00" +@.str1042 = private unnamed_addr constant [3 x i8] c"%h\00" +@.str1043 = private unnamed_addr constant [3 x i8] c" \00" +@.str1044 = private unnamed_addr constant [28 x i8] c" = getelementptr inbounds [\00" +@.str1045 = private unnamed_addr constant [16 x i8] c" x i8], ptr @H_\00" +@.str1046 = private unnamed_addr constant [17 x i8] c", i32 0, i32 %e\0A\00" +@.str1047 = private unnamed_addr constant [19 x i8] c" store i8 0, ptr \00" +@.str1048 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1049 = private unnamed_addr constant [32 x i8] c" %k = getelementptr inbounds [\00" +@.str1050 = private unnamed_addr constant [37 x i8] c" x i32], ptr @L_kind, i32 0, i32 %e\0A\00" +@.str1051 = private unnamed_addr constant [37 x i8] c" store i32 0, ptr %k\0A ret void\0A}\0A\0A\00" +@.str1052 = private unnamed_addr constant [32 x i8] c"define i32 @L_alloc() {\0Aentry:\0A\00" +@.str1053 = private unnamed_addr constant [32 x i8] c" %fn = load i32, ptr @L_freen\0A\00" +@.str1054 = private unnamed_addr constant [30 x i8] c" %has = icmp sgt i32 %fn, 0\0A\00" +@.str1055 = private unnamed_addr constant [42 x i8] c" br i1 %has, label %reuse, label %fresh\0A\00" +@.str1056 = private unnamed_addr constant [8 x i8] c"reuse:\0A\00" +@.str1057 = private unnamed_addr constant [25 x i8] c" %fn1 = sub i32 %fn, 1\0A\00" +@.str1058 = private unnamed_addr constant [32 x i8] c" store i32 %fn1, ptr @L_freen\0A\00" +@.str1059 = private unnamed_addr constant [33 x i8] c" %fp = getelementptr inbounds [\00" +@.str1060 = private unnamed_addr constant [43 x i8] c" x i32], ptr @L_freelist, i32 0, i32 %fn1\0A\00" +@.str1061 = private unnamed_addr constant [27 x i8] c" %re = load i32, ptr %fp\0A\00" +@.str1062 = private unnamed_addr constant [18 x i8] c" br label %done\0A\00" +@.str1063 = private unnamed_addr constant [8 x i8] c"fresh:\0A\00" +@.str1064 = private unnamed_addr constant [31 x i8] c" %ec = load i32, ptr @L_entc\0A\00" +@.str1065 = private unnamed_addr constant [25 x i8] c" %ec1 = add i32 %ec, 1\0A\00" +@.str1066 = private unnamed_addr constant [31 x i8] c" store i32 %ec1, ptr @L_entc\0A\00" +@.str1067 = private unnamed_addr constant [18 x i8] c" br label %done\0A\00" +@.str1068 = private unnamed_addr constant [7 x i8] c"done:\0A\00" +@.str1069 = private unnamed_addr constant [49 x i8] c" %e = phi i32 [ %re, %reuse ], [ %ec, %fresh ]\0A\00" +@.str1070 = private unnamed_addr constant [30 x i8] c" call void @L_reset(i32 %e)\0A\00" +@.str1071 = private unnamed_addr constant [33 x i8] c" %ap = getelementptr inbounds [\00" +@.str1072 = private unnamed_addr constant [38 x i8] c" x i32], ptr @L_alive, i32 0, i32 %e\0A\00" +@.str1073 = private unnamed_addr constant [24 x i8] c" store i32 1, ptr %ap\0A\00" +@.str1074 = private unnamed_addr constant [17 x i8] c" ret i32 %e\0A}\0A\0A\00" +@.str1075 = private unnamed_addr constant [45 x i8] c"define void @L_free_entity(i32 %e) {\0Aentry:\0A\00" +@.str1076 = private unnamed_addr constant [33 x i8] c" %ap = getelementptr inbounds [\00" +@.str1077 = private unnamed_addr constant [38 x i8] c" x i32], ptr @L_alive, i32 0, i32 %e\0A\00" +@.str1078 = private unnamed_addr constant [24 x i8] c" store i32 0, ptr %ap\0A\00" +@.str1079 = private unnamed_addr constant [30 x i8] c" call void @L_reset(i32 %e)\0A\00" +@.str1080 = private unnamed_addr constant [32 x i8] c" %fn = load i32, ptr @L_freen\0A\00" +@.str1081 = private unnamed_addr constant [33 x i8] c" %fp = getelementptr inbounds [\00" +@.str1082 = private unnamed_addr constant [42 x i8] c" x i32], ptr @L_freelist, i32 0, i32 %fn\0A\00" +@.str1083 = private unnamed_addr constant [25 x i8] c" store i32 %e, ptr %fp\0A\00" +@.str1084 = private unnamed_addr constant [25 x i8] c" %fn1 = add i32 %fn, 1\0A\00" +@.str1085 = private unnamed_addr constant [32 x i8] c" store i32 %fn1, ptr @L_freen\0A\00" +@.str1086 = private unnamed_addr constant [15 x i8] c" ret void\0A}\0A\0A\00" +@.str1087 = private unnamed_addr constant [4 x i8] c"i32\00" +@.str1088 = private unnamed_addr constant [4 x i8] c"i32\00" +@.str1089 = private unnamed_addr constant [2 x i8] c"0\00" +@.str1090 = private unnamed_addr constant [6 x i8] c"qcond\00" +@.str1091 = private unnamed_addr constant [6 x i8] c"qbody\00" +@.str1092 = private unnamed_addr constant [6 x i8] c"qnext\00" +@.str1093 = private unnamed_addr constant [5 x i8] c"qend\00" +@.str1094 = private unnamed_addr constant [13 x i8] c" br label %\00" +@.str1095 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1096 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str1097 = private unnamed_addr constant [15 x i8] c"load i32, ptr \00" +@.str1098 = private unnamed_addr constant [22 x i8] c"load i32, ptr @L_entc\00" +@.str1099 = private unnamed_addr constant [14 x i8] c"icmp slt i32 \00" +@.str1100 = private unnamed_addr constant [3 x i8] c", \00" +@.str1101 = private unnamed_addr constant [9 x i8] c" br i1 \00" +@.str1102 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str1103 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str1104 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1105 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str1106 = private unnamed_addr constant [15 x i8] c"load i32, ptr \00" +@.str1107 = private unnamed_addr constant [3 x i8] c" \00" +@.str1108 = private unnamed_addr constant [28 x i8] c" = getelementptr inbounds [\00" +@.str1109 = private unnamed_addr constant [35 x i8] c" x i32], ptr @L_alive, i32 0, i32 \00" +@.str1110 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1111 = private unnamed_addr constant [15 x i8] c"load i32, ptr \00" +@.str1112 = private unnamed_addr constant [13 x i8] c"icmp ne i32 \00" +@.str1113 = private unnamed_addr constant [4 x i8] c", 0\00" +@.str1114 = private unnamed_addr constant [3 x i8] c"qa\00" +@.str1115 = private unnamed_addr constant [9 x i8] c" br i1 \00" +@.str1116 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str1117 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str1118 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1119 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str1120 = private unnamed_addr constant [2 x i8] c"0\00" +@.str1121 = private unnamed_addr constant [3 x i8] c" \00" +@.str1122 = private unnamed_addr constant [28 x i8] c" = getelementptr inbounds [\00" +@.str1123 = private unnamed_addr constant [34 x i8] c" x i32], ptr @L_kind, i32 0, i32 \00" +@.str1124 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1125 = private unnamed_addr constant [15 x i8] c"load i32, ptr \00" +@.str1126 = private unnamed_addr constant [13 x i8] c"icmp eq i32 \00" +@.str1127 = private unnamed_addr constant [3 x i8] c", \00" +@.str1128 = private unnamed_addr constant [3 x i8] c" \00" +@.str1129 = private unnamed_addr constant [28 x i8] c" = getelementptr inbounds [\00" +@.str1130 = private unnamed_addr constant [16 x i8] c" x i8], ptr @H_\00" +@.str1131 = private unnamed_addr constant [14 x i8] c", i32 0, i32 \00" +@.str1132 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1133 = private unnamed_addr constant [14 x i8] c"load i8, ptr \00" +@.str1134 = private unnamed_addr constant [12 x i8] c"icmp ne i8 \00" +@.str1135 = private unnamed_addr constant [4 x i8] c", 0\00" +@.str1136 = private unnamed_addr constant [3 x i8] c"qt\00" +@.str1137 = private unnamed_addr constant [9 x i8] c" br i1 \00" +@.str1138 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str1139 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str1140 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1141 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str1142 = private unnamed_addr constant [3 x i8] c" \00" +@.str1143 = private unnamed_addr constant [28 x i8] c" = getelementptr inbounds [\00" +@.str1144 = private unnamed_addr constant [9 x i8] c" x %Cmp_\00" +@.str1145 = private unnamed_addr constant [11 x i8] c"], ptr @S_\00" +@.str1146 = private unnamed_addr constant [14 x i8] c", i32 0, i32 \00" +@.str1147 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1148 = private unnamed_addr constant [4 x i8] c"ptr\00" +@.str1149 = private unnamed_addr constant [13 x i8] c" store ptr \00" +@.str1150 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str1151 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1152 = private unnamed_addr constant [13 x i8] c"icmp ne i32 \00" +@.str1153 = private unnamed_addr constant [4 x i8] c", 0\00" +@.str1154 = private unnamed_addr constant [3 x i8] c"qw\00" +@.str1155 = private unnamed_addr constant [9 x i8] c" br i1 \00" +@.str1156 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str1157 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str1158 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1159 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str1160 = private unnamed_addr constant [13 x i8] c" br label %\00" +@.str1161 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1162 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str1163 = private unnamed_addr constant [15 x i8] c"load i32, ptr \00" +@.str1164 = private unnamed_addr constant [9 x i8] c"add i32 \00" +@.str1165 = private unnamed_addr constant [4 x i8] c", 1\00" +@.str1166 = private unnamed_addr constant [4 x i8] c"i32\00" +@.str1167 = private unnamed_addr constant [13 x i8] c" br label %\00" +@.str1168 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1169 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str1170 = private unnamed_addr constant [26 x i8] c"spawn: unknown component \00" +@.str1171 = private unnamed_addr constant [3 x i8] c" \00" +@.str1172 = private unnamed_addr constant [28 x i8] c" = getelementptr inbounds [\00" +@.str1173 = private unnamed_addr constant [16 x i8] c" x i8], ptr @H_\00" +@.str1174 = private unnamed_addr constant [14 x i8] c", i32 0, i32 \00" +@.str1175 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1176 = private unnamed_addr constant [19 x i8] c" store i8 1, ptr \00" +@.str1177 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1178 = private unnamed_addr constant [3 x i8] c" \00" +@.str1179 = private unnamed_addr constant [28 x i8] c" = getelementptr inbounds [\00" +@.str1180 = private unnamed_addr constant [9 x i8] c" x %Cmp_\00" +@.str1181 = private unnamed_addr constant [11 x i8] c"], ptr @S_\00" +@.str1182 = private unnamed_addr constant [14 x i8] c", i32 0, i32 \00" +@.str1183 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1184 = private unnamed_addr constant [3 x i8] c" \00" +@.str1185 = private unnamed_addr constant [32 x i8] c" = getelementptr inbounds %Cmp_\00" +@.str1186 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str1187 = private unnamed_addr constant [14 x i8] c", i32 0, i32 \00" +@.str1188 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1189 = private unnamed_addr constant [2 x i8] c"0\00" +@.str1190 = private unnamed_addr constant [4 x i8] c"ptr\00" +@.str1191 = private unnamed_addr constant [5 x i8] c"null\00" +@.str1192 = private unnamed_addr constant [9 x i8] c" store \00" +@.str1193 = private unnamed_addr constant [2 x i8] c" \00" +@.str1194 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str1195 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1196 = private unnamed_addr constant [3 x i8] c" \00" +@.str1197 = private unnamed_addr constant [32 x i8] c" = getelementptr inbounds %Cmp_\00" +@.str1198 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str1199 = private unnamed_addr constant [14 x i8] c", i32 0, i32 \00" +@.str1200 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1201 = private unnamed_addr constant [9 x i8] c" store \00" +@.str1202 = private unnamed_addr constant [2 x i8] c" \00" +@.str1203 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str1204 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1205 = private unnamed_addr constant [20 x i8] c"call i32 @L_alloc()\00" +@.str1206 = private unnamed_addr constant [3 x i8] c" \00" +@.str1207 = private unnamed_addr constant [28 x i8] c" = getelementptr inbounds [\00" +@.str1208 = private unnamed_addr constant [34 x i8] c" x i32], ptr @L_kind, i32 0, i32 \00" +@.str1209 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1210 = private unnamed_addr constant [13 x i8] c" store i32 \00" +@.str1211 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str1212 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1213 = private unnamed_addr constant [32 x i8] c" call void @L_free_entity(i32 \00" +@.str1214 = private unnamed_addr constant [3 x i8] c")\0A\00" +@.str1215 = private unnamed_addr constant [5 x i8] c"void\00" +@.str1216 = private unnamed_addr constant [17 x i8] c" br label %ret\0A\00" +@.str1217 = private unnamed_addr constant [17 x i8] c"ret:\0A ret void\0A\00" +@.str1218 = private unnamed_addr constant [18 x i8] c"define void @sys_\00" +@.str1219 = private unnamed_addr constant [13 x i8] c"() {\0Aentry:\0A\00" +@.str1220 = private unnamed_addr constant [4 x i8] c"}\0A\0A\00" +@.str1221 = private unnamed_addr constant [18 x i8] c" call void @sys_\00" +@.str1222 = private unnamed_addr constant [4 x i8] c"()\0A\00" +@.str1223 = private unnamed_addr constant [49 x i8] c"define i32 @main(i32 %argc, ptr %argv) {\0Aentry:\0A\00" +@.str1224 = private unnamed_addr constant [32 x i8] c" store i32 %argc, ptr @L_argc\0A\00" +@.str1225 = private unnamed_addr constant [32 x i8] c" store ptr %argv, ptr @L_argv\0A\00" +@.str1226 = private unnamed_addr constant [8 x i8] c"rt_init\00" +@.str1227 = private unnamed_addr constant [27 x i8] c" call void @fn_rt_init()\0A\00" +@.str1228 = private unnamed_addr constant [6 x i8] c"Start\00" +@.str1229 = private unnamed_addr constant [18 x i8] c" br label %loop\0A\00" +@.str1230 = private unnamed_addr constant [7 x i8] c"loop:\0A\00" +@.str1231 = private unnamed_addr constant [25 x i8] c"load i32, ptr @L_running\00" +@.str1232 = private unnamed_addr constant [13 x i8] c"icmp ne i32 \00" +@.str1233 = private unnamed_addr constant [4 x i8] c", 0\00" +@.str1234 = private unnamed_addr constant [11 x i8] c"rt_running\00" +@.str1235 = private unnamed_addr constant [26 x i8] c"call i32 @fn_rt_running()\00" +@.str1236 = private unnamed_addr constant [13 x i8] c"icmp ne i32 \00" +@.str1237 = private unnamed_addr constant [4 x i8] c", 0\00" +@.str1238 = private unnamed_addr constant [8 x i8] c"and i1 \00" +@.str1239 = private unnamed_addr constant [3 x i8] c", \00" +@.str1240 = private unnamed_addr constant [9 x i8] c" br i1 \00" +@.str1241 = private unnamed_addr constant [28 x i8] c", label %body, label %done\0A\00" +@.str1242 = private unnamed_addr constant [9 x i8] c" br i1 \00" +@.str1243 = private unnamed_addr constant [28 x i8] c", label %body, label %done\0A\00" +@.str1244 = private unnamed_addr constant [7 x i8] c"body:\0A\00" +@.str1245 = private unnamed_addr constant [8 x i8] c"rt_poll\00" +@.str1246 = private unnamed_addr constant [23 x i8] c"call i32 @fn_rt_poll()\00" +@.str1247 = private unnamed_addr constant [13 x i8] c" store i32 \00" +@.str1248 = private unnamed_addr constant [14 x i8] c", ptr @L_key\0A\00" +@.str1249 = private unnamed_addr constant [6 x i8] c"Input\00" +@.str1250 = private unnamed_addr constant [12 x i8] c"FixedUpdate\00" +@.str1251 = private unnamed_addr constant [7 x i8] c"Update\00" +@.str1252 = private unnamed_addr constant [11 x i8] c"LateUpdate\00" +@.str1253 = private unnamed_addr constant [7 x i8] c"Render\00" +@.str1254 = private unnamed_addr constant [18 x i8] c" br label %loop\0A\00" +@.str1255 = private unnamed_addr constant [7 x i8] c"done:\0A\00" +@.str1256 = private unnamed_addr constant [12 x i8] c"rt_shutdown\00" +@.str1257 = private unnamed_addr constant [31 x i8] c" call void @fn_rt_shutdown()\0A\00" +@.str1258 = private unnamed_addr constant [15 x i8] c" ret i32 0\0A}\0A\00" +@.str1259 = private unnamed_addr constant [25 x i8] c"call i32 @fn_rt_reg(i32 \00" +@.str1260 = private unnamed_addr constant [2 x i8] c")\00" +@.str1261 = private unnamed_addr constant [6 x i8] c"smend\00" +@.str1262 = private unnamed_addr constant [13 x i8] c"icmp eq i32 \00" +@.str1263 = private unnamed_addr constant [3 x i8] c", \00" +@.str1264 = private unnamed_addr constant [6 x i8] c"sbody\00" +@.str1265 = private unnamed_addr constant [5 x i8] c"sarm\00" +@.str1266 = private unnamed_addr constant [9 x i8] c" br i1 \00" +@.str1267 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str1268 = private unnamed_addr constant [10 x i8] c", label %\00" +@.str1269 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1270 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str1271 = private unnamed_addr constant [13 x i8] c" br label %\00" +@.str1272 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1273 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str1274 = private unnamed_addr constant [13 x i8] c" br label %\00" +@.str1275 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1276 = private unnamed_addr constant [3 x i8] c":\0A\00" +@.str1277 = private unnamed_addr constant [27 x i8] c"'become' outside a machine\00" +@.str1278 = private unnamed_addr constant [18 x i8] c"become: no state \00" +@.str1279 = private unnamed_addr constant [31 x i8] c" call void @fn_rt_setreg(i32 \00" +@.str1280 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str1281 = private unnamed_addr constant [3 x i8] c")\0A\00" +@.str1282 = private unnamed_addr constant [4 x i8] c"%io\00" +@.str1283 = private unnamed_addr constant [3 x i8] c" \00" +@.str1284 = private unnamed_addr constant [14 x i8] c" = call i64 @\00" +@.str1285 = private unnamed_addr constant [6 x i8] c"(ptr \00" +@.str1286 = private unnamed_addr constant [14 x i8] c", i64 1, i64 \00" +@.str1287 = private unnamed_addr constant [11 x i8] c", ptr %f)\0A\00" +@.str1288 = private unnamed_addr constant [8 x i8] c"@L_entc\00" +@.str1289 = private unnamed_addr constant [2 x i8] c"4\00" +@.str1290 = private unnamed_addr constant [9 x i8] c"@L_freen\00" +@.str1291 = private unnamed_addr constant [2 x i8] c"4\00" +@.str1292 = private unnamed_addr constant [21 x i8] c" %nalive = mul i64 \00" +@.str1293 = private unnamed_addr constant [5 x i8] c", 4\0A\00" +@.str1294 = private unnamed_addr constant [9 x i8] c"@L_alive\00" +@.str1295 = private unnamed_addr constant [8 x i8] c"%nalive\00" +@.str1296 = private unnamed_addr constant [12 x i8] c"@L_freelist\00" +@.str1297 = private unnamed_addr constant [8 x i8] c"%nalive\00" +@.str1298 = private unnamed_addr constant [8 x i8] c"@L_kind\00" +@.str1299 = private unnamed_addr constant [8 x i8] c"%nalive\00" +@.str1300 = private unnamed_addr constant [4 x i8] c"@g_\00" +@.str1301 = private unnamed_addr constant [2 x i8] c"4\00" +@.str1302 = private unnamed_addr constant [5 x i8] c"%csz\00" +@.str1303 = private unnamed_addr constant [3 x i8] c" \00" +@.str1304 = private unnamed_addr constant [37 x i8] c" = ptrtoint ptr getelementptr (%Cmp_\00" +@.str1305 = private unnamed_addr constant [17 x i8] c", ptr null, i32 \00" +@.str1306 = private unnamed_addr constant [10 x i8] c") to i64\0A\00" +@.str1307 = private unnamed_addr constant [4 x i8] c"@S_\00" +@.str1308 = private unnamed_addr constant [4 x i8] c"@H_\00" +@.str1309 = private unnamed_addr constant [70 x i8] c"@.sav_path = private unnamed_addr constant [10 x i8] c\22ludic.sav\5C00\22\0A\00" +@.str1310 = private unnamed_addr constant [60 x i8] c"@.sav_wb = private unnamed_addr constant [3 x i8] c\22wb\5C00\22\0A\00" +@.str1311 = private unnamed_addr constant [60 x i8] c"@.sav_rb = private unnamed_addr constant [3 x i8] c\22rb\5C00\22\0A\00" +@.str1312 = private unnamed_addr constant [14 x i8] c"rt_save_state\00" +@.str1313 = private unnamed_addr constant [14 x i8] c"rt_load_state\00" +@.str1314 = private unnamed_addr constant [32 x i8] c"define void @L_save() {\0Aentry:\0A\00" +@.str1315 = private unnamed_addr constant [54 x i8] c" %f = call ptr @fopen(ptr @.sav_path, ptr @.sav_wb)\0A\00" +@.str1316 = private unnamed_addr constant [31 x i8] c" %bad = icmp eq ptr %f, null\0A\00" +@.str1317 = private unnamed_addr constant [41 x i8] c" br i1 %bad, label %out, label %go\0Ago:\0A\00" +@.str1318 = private unnamed_addr constant [7 x i8] c"fwrite\00" +@.str1319 = private unnamed_addr constant [39 x i8] c" call void @fn_rt_save_state(ptr %f)\0A\00" +@.str1320 = private unnamed_addr constant [68 x i8] c" %c = call i32 @fclose(ptr %f)\0A br label %out\0Aout:\0A ret void\0A}\0A\0A\00" +@.str1321 = private unnamed_addr constant [31 x i8] c"define i32 @L_load() {\0Aentry:\0A\00" +@.str1322 = private unnamed_addr constant [54 x i8] c" %f = call ptr @fopen(ptr @.sav_path, ptr @.sav_rb)\0A\00" +@.str1323 = private unnamed_addr constant [31 x i8] c" %bad = icmp eq ptr %f, null\0A\00" +@.str1324 = private unnamed_addr constant [60 x i8] c" br i1 %bad, label %miss, label %go\0Amiss:\0A ret i32 0\0Ago:\0A\00" +@.str1325 = private unnamed_addr constant [6 x i8] c"fread\00" +@.str1326 = private unnamed_addr constant [39 x i8] c" call void @fn_rt_load_state(ptr %f)\0A\00" +@.str1327 = private unnamed_addr constant [48 x i8] c" %c = call i32 @fclose(ptr %f)\0A ret i32 1\0A}\0A\0A\00" +@.str1328 = private unnamed_addr constant [6 x i8] c"panel\00" +@.str1329 = private unnamed_addr constant [4 x i8] c"col\00" +@.str1330 = private unnamed_addr constant [4 x i8] c"row\00" +@.str1331 = private unnamed_addr constant [6 x i8] c"label\00" +@.str1332 = private unnamed_addr constant [7 x i8] c"button\00" +@.str1333 = private unnamed_addr constant [6 x i8] c"image\00" +@.str1334 = private unnamed_addr constant [7 x i8] c"spacer\00" +@.str1335 = private unnamed_addr constant [3 x i8] c"id\00" +@.str1336 = private unnamed_addr constant [31 x i8] c" call void @fn_rt_ui_set(i32 \00" +@.str1337 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str1338 = private unnamed_addr constant [7 x i8] c", i32 \00" +@.str1339 = private unnamed_addr constant [3 x i8] c")\0A\00" +@.str1340 = private unnamed_addr constant [2 x i8] c"w\00" +@.str1341 = private unnamed_addr constant [2 x i8] c"h\00" +@.str1342 = private unnamed_addr constant [2 x i8] c"x\00" +@.str1343 = private unnamed_addr constant [2 x i8] c"y\00" +@.str1344 = private unnamed_addr constant [4 x i8] c"pad\00" +@.str1345 = private unnamed_addr constant [4 x i8] c"gap\00" +@.str1346 = private unnamed_addr constant [3 x i8] c"bg\00" +@.str1347 = private unnamed_addr constant [3 x i8] c"fg\00" +@.str1348 = private unnamed_addr constant [7 x i8] c"border\00" +@.str1349 = private unnamed_addr constant [5 x i8] c"grow\00" +@.str1350 = private unnamed_addr constant [5 x i8] c"font\00" +@.str1351 = private unnamed_addr constant [5 x i8] c"size\00" +@.str1352 = private unnamed_addr constant [6 x i8] c"inset\00" +@.str1353 = private unnamed_addr constant [6 x i8] c"focus\00" +@.str1354 = private unnamed_addr constant [33 x i8] c" call void @fn_rt_ui_reset(i32 \00" +@.str1355 = private unnamed_addr constant [3 x i8] c")\0A\00" +@.str1356 = private unnamed_addr constant [2 x i8] c"1\00" +@.str1357 = private unnamed_addr constant [3 x i8] c"id\00" +@.str1358 = private unnamed_addr constant [5 x i8] c"text\00" +@.str1359 = private unnamed_addr constant [39 x i8] c" call void @fn_rt_ui_static_text(i32 \00" +@.str1360 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str1361 = private unnamed_addr constant [3 x i8] c")\0A\00" +@.str1362 = private unnamed_addr constant [5 x i8] c"skin\00" +@.str1363 = private unnamed_addr constant [6 x i8] c"image\00" +@.str1364 = private unnamed_addr constant [32 x i8] c"call i32 @fn_rt_image_load(ptr \00" +@.str1365 = private unnamed_addr constant [2 x i8] c")\00" +@.str1366 = private unnamed_addr constant [5 x i8] c"skin\00" +@.str1367 = private unnamed_addr constant [6 x i8] c"align\00" +@.str1368 = private unnamed_addr constant [7 x i8] c"center\00" +@.str1369 = private unnamed_addr constant [4 x i8] c"end\00" +@.str1370 = private unnamed_addr constant [2 x i8] c"1\00" +@.str1371 = private unnamed_addr constant [34 x i8] c"define void @ui_build() {\0Aentry:\0A\00" +@.str1372 = private unnamed_addr constant [15 x i8] c" ret void\0A}\0A\0A\00" +@.str1373 = private unnamed_addr constant [3 x i8] c", \00" +@.str1374 = private unnamed_addr constant [7 x i8] c" %arg_\00" +@.str1375 = private unnamed_addr constant [5 x i8] c"void\00" +@.str1376 = private unnamed_addr constant [20 x i8] c" %retval = alloca \00" +@.str1377 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1378 = private unnamed_addr constant [9 x i8] c" store \00" +@.str1379 = private unnamed_addr constant [7 x i8] c" %arg_\00" +@.str1380 = private unnamed_addr constant [7 x i8] c", ptr \00" +@.str1381 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1382 = private unnamed_addr constant [17 x i8] c" br label %ret\0A\00" +@.str1383 = private unnamed_addr constant [6 x i8] c"ret:\0A\00" +@.str1384 = private unnamed_addr constant [5 x i8] c"void\00" +@.str1385 = private unnamed_addr constant [12 x i8] c" ret void\0A\00" +@.str1386 = private unnamed_addr constant [6 x i8] c"load \00" +@.str1387 = private unnamed_addr constant [14 x i8] c", ptr %retval\00" +@.str1388 = private unnamed_addr constant [7 x i8] c" ret \00" +@.str1389 = private unnamed_addr constant [2 x i8] c" \00" +@.str1390 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1391 = private unnamed_addr constant [8 x i8] c"define \00" +@.str1392 = private unnamed_addr constant [6 x i8] c" @fn_\00" +@.str1393 = private unnamed_addr constant [2 x i8] c"(\00" +@.str1394 = private unnamed_addr constant [12 x i8] c") {\0Aentry:\0A\00" +@.str1395 = private unnamed_addr constant [4 x i8] c"}\0A\0A\00" +@.str1396 = private unnamed_addr constant [4 x i8] c"int\00" +@.str1397 = private unnamed_addr constant [24 x i8] c" %retval = alloca i32\0A\00" +@.str1398 = private unnamed_addr constant [32 x i8] c" store i32 %argc, ptr @L_argc\0A\00" +@.str1399 = private unnamed_addr constant [32 x i8] c" store ptr %argv, ptr @L_argv\0A\00" +@.str1400 = private unnamed_addr constant [28 x i8] c" store i32 0, ptr %retval\0A\00" +@.str1401 = private unnamed_addr constant [17 x i8] c" br label %ret\0A\00" +@.str1402 = private unnamed_addr constant [6 x i8] c"ret:\0A\00" +@.str1403 = private unnamed_addr constant [22 x i8] c"load i32, ptr %retval\00" +@.str1404 = private unnamed_addr constant [11 x i8] c" ret i32 \00" +@.str1405 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1406 = private unnamed_addr constant [49 x i8] c"define i32 @main(i32 %argc, ptr %argv) {\0Aentry:\0A\00" +@.str1407 = private unnamed_addr constant [3 x i8] c"}\0A\00" +@.str1408 = private unnamed_addr constant [3 x i8] c"wb\00" +@.str1409 = private unnamed_addr constant [7 x i8] c".ludic\00" +@.str1410 = private unnamed_addr constant [2 x i8] c"/\00" +@.str1411 = private unnamed_addr constant [6 x i8] c"ludic\00" +@.str1412 = private unnamed_addr constant [11 x i8] c"--windowed\00" +@.str1413 = private unnamed_addr constant [11 x i8] c"--headless\00" +@.str1414 = private unnamed_addr constant [12 x i8] c"--emit-llvm\00" +@.str1415 = private unnamed_addr constant [6 x i8] c"--fmt\00" +@.str1416 = private unnamed_addr constant [13 x i8] c"--save-temps\00" +@.str1417 = private unnamed_addr constant [6 x i8] c"--run\00" +@.str1418 = private unnamed_addr constant [3 x i8] c"-o\00" +@.str1419 = private unnamed_addr constant [31 x i8] c"ludicc: ignoring unknown flag \00" +@.str1420 = private unnamed_addr constant [2 x i8] c"\0A\00" +@.str1421 = private unnamed_addr constant [90 x i8] c"usage: ludicc [-o out] [--windowed|--headless] [--emit-llvm] [--save-temps]\0A\00" +@.str1422 = private unnamed_addr constant [27 x i8] c"ludicc: cannot open input\0A\00" +@.str1423 = private unnamed_addr constant [16 x i8] c"/tmp/ludic-run-\00" +@.str1424 = private unnamed_addr constant [10 x i8] c"mkdir -p \00" +@.str1425 = private unnamed_addr constant [4 x i8] c".ll\00" +@.str1426 = private unnamed_addr constant [25 x i8] c"ludicc: cannot write IR\0A\00" +@.str1427 = private unnamed_addr constant [9 x i8] c"LUDIC_CC\00" +@.str1428 = private unnamed_addr constant [6 x i8] c"clang\00" +@.str1429 = private unnamed_addr constant [11 x i8] c"LUDIC_HOME\00" +@.str1430 = private unnamed_addr constant [27 x i8] c" -O2 -Wno-override-module \00" +@.str1431 = private unnamed_addr constant [24 x i8] c"runtime/native/cocoa.ll\00" +@.str1432 = private unnamed_addr constant [2 x i8] c" \00" +@.str1433 = private unnamed_addr constant [42 x i8] c" -framework Cocoa -Wl,-rpath,@loader_path\00" +@.str1434 = private unnamed_addr constant [5 x i8] c" -o \00" +@.str1435 = private unnamed_addr constant [7 x i8] c"rm -f \00" +@.str1436 = private unnamed_addr constant [21 x i8] c"ludicc: link failed\0A\00" +define i32 @fn_streq(ptr %arg_a, ptr %arg_b) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t1 = alloca ptr + %t2 = alloca i32 + %t9 = alloca i32 + %t15 = alloca i32 + store ptr %arg_a, ptr %t0 + store ptr %arg_b, ptr %t1 + store i32 0, ptr %t2 + br label %wcond0 +wcond0: + %t3 = icmp ne i32 1, 0 + br i1 %t3, label %wbody1, label %wend2 +wbody1: + %t4 = load ptr, ptr %t0 + %t5 = load i32, ptr %t2 + %t6 = getelementptr inbounds i8, ptr %t4, i32 %t5 + %t7 = load i8, ptr %t6 + %t8 = zext i8 %t7 to i32 + store i32 %t8, ptr %t9 + %t10 = load ptr, ptr %t1 + %t11 = load i32, ptr %t2 + %t12 = getelementptr inbounds i8, ptr %t10, i32 %t11 + %t13 = load i8, ptr %t12 + %t14 = zext i8 %t13 to i32 + store i32 %t14, ptr %t15 + %t16 = load i32, ptr %t9 + %t17 = load i32, ptr %t15 + %t18 = icmp ne i32 %t16, %t17 + %t19 = zext i1 %t18 to i32 + %t20 = icmp ne i32 %t19, 0 + br i1 %t20, label %then3, label %ifend5 +then3: + store i32 0, ptr %retval + br label %ret +ifend5: + %t21 = load i32, ptr %t9 + %t22 = icmp eq i32 %t21, 0 + %t23 = zext i1 %t22 to i32 + %t24 = icmp ne i32 %t23, 0 + br i1 %t24, label %then6, label %ifend8 +then6: + store i32 1, ptr %retval + br label %ret +ifend8: + %t25 = load i32, ptr %t2 + %t26 = add i32 %t25, 1 + store i32 %t26, ptr %t2 + br label %wcond0 +wend2: + store i32 0, ptr %retval + br label %ret +ret: + %t27 = load i32, ptr %retval + ret i32 %t27 +} + +define i32 @fn_slen(ptr %arg_s) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t1 = alloca i32 + store ptr %arg_s, ptr %t0 + store i32 0, ptr %t1 + br label %wcond0 +wcond0: + %t2 = load ptr, ptr %t0 + %t3 = load i32, ptr %t1 + %t4 = getelementptr inbounds i8, ptr %t2, i32 %t3 + %t5 = load i8, ptr %t4 + %t6 = zext i8 %t5 to i32 + %t7 = icmp ne i32 %t6, 0 + %t8 = zext i1 %t7 to i32 + %t9 = icmp ne i32 %t8, 0 + br i1 %t9, label %wbody1, label %wend2 +wbody1: + %t10 = load i32, ptr %t1 + %t11 = add i32 %t10, 1 + store i32 %t11, ptr %t1 + br label %wcond0 +wend2: + %t12 = load i32, ptr %t1 + store i32 %t12, ptr %retval + br label %ret +ret: + %t13 = load i32, ptr %retval + ret i32 %t13 +} + +define ptr @fn_substr(ptr %arg_src, i32 %arg_start, i32 %arg_n) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca i32 + %t2 = alloca i32 + %t7 = alloca ptr + %t8 = alloca i32 + store ptr %arg_src, ptr %t0 + store i32 %arg_start, ptr %t1 + store i32 %arg_n, ptr %t2 + %t3 = load i32, ptr %t2 + %t4 = add i32 %t3, 1 + %t5 = zext i32 %t4 to i64 + %t6 = call ptr @malloc(i64 %t5) + store ptr %t6, ptr %t7 + store i32 0, ptr %t8 + br label %wcond0 +wcond0: + %t9 = load i32, ptr %t8 + %t10 = load i32, ptr %t2 + %t11 = icmp slt i32 %t9, %t10 + %t12 = zext i1 %t11 to i32 + %t13 = icmp ne i32 %t12, 0 + br i1 %t13, label %wbody1, label %wend2 +wbody1: + %t14 = load ptr, ptr %t7 + %t15 = load i32, ptr %t8 + %t16 = load ptr, ptr %t0 + %t17 = load i32, ptr %t1 + %t18 = load i32, ptr %t8 + %t19 = add i32 %t17, %t18 + %t20 = getelementptr inbounds i8, ptr %t16, i32 %t19 + %t21 = load i8, ptr %t20 + %t22 = zext i8 %t21 to i32 + %t23 = getelementptr inbounds i8, ptr %t14, i32 %t15 + %t24 = trunc i32 %t22 to i8 + store i8 %t24, ptr %t23 + %t25 = load i32, ptr %t8 + %t26 = add i32 %t25, 1 + store i32 %t26, ptr %t8 + br label %wcond0 +wend2: + %t27 = load ptr, ptr %t7 + %t28 = load i32, ptr %t2 + %t29 = getelementptr inbounds i8, ptr %t27, i32 %t28 + %t30 = trunc i32 0 to i8 + store i8 %t30, ptr %t29 + %t31 = load ptr, ptr %t7 + store ptr %t31, ptr %retval + br label %ret +ret: + %t32 = load ptr, ptr %retval + ret ptr %t32 +} + +define i32 @fn_char_is_digit(i32 %arg_c) { +entry: + %retval = alloca i32 + %t0 = alloca i32 + %t1 = alloca i32 + store i32 %arg_c, ptr %t0 + %t2 = load i32, ptr %t0 + %t3 = icmp sge i32 %t2, 48 + %t4 = zext i1 %t3 to i32 + %t5 = icmp ne i32 %t4, 0 + %t6 = zext i1 %t5 to i32 + store i32 %t6, ptr %t1 + br i1 %t5, label %sc0, label %scend1 +sc0: + %t7 = load i32, ptr %t0 + %t8 = icmp sle i32 %t7, 57 + %t9 = zext i1 %t8 to i32 + %t10 = icmp ne i32 %t9, 0 + %t11 = zext i1 %t10 to i32 + store i32 %t11, ptr %t1 + br label %scend1 +scend1: + %t12 = load i32, ptr %t1 + store i32 %t12, ptr %retval + br label %ret +ret: + %t13 = load i32, ptr %retval + ret i32 %t13 +} + +define i32 @fn_char_is_alpha(i32 %arg_c) { +entry: + %retval = alloca i32 + %t0 = alloca i32 + %t1 = alloca i32 + %t14 = alloca i32 + store i32 %arg_c, ptr %t0 + %t2 = load i32, ptr %t0 + %t3 = icmp sge i32 %t2, 65 + %t4 = zext i1 %t3 to i32 + %t5 = icmp ne i32 %t4, 0 + %t6 = zext i1 %t5 to i32 + store i32 %t6, ptr %t1 + br i1 %t5, label %sc0, label %scend1 +sc0: + %t7 = load i32, ptr %t0 + %t8 = icmp sle i32 %t7, 90 + %t9 = zext i1 %t8 to i32 + %t10 = icmp ne i32 %t9, 0 + %t11 = zext i1 %t10 to i32 + store i32 %t11, ptr %t1 + br label %scend1 +scend1: + %t12 = load i32, ptr %t1 + %t13 = icmp ne i32 %t12, 0 + br i1 %t13, label %then2, label %ifend4 +then2: + store i32 1, ptr %retval + br label %ret +ifend4: + %t15 = load i32, ptr %t0 + %t16 = icmp sge i32 %t15, 97 + %t17 = zext i1 %t16 to i32 + %t18 = icmp ne i32 %t17, 0 + %t19 = zext i1 %t18 to i32 + store i32 %t19, ptr %t14 + br i1 %t18, label %sc5, label %scend6 +sc5: + %t20 = load i32, ptr %t0 + %t21 = icmp sle i32 %t20, 122 + %t22 = zext i1 %t21 to i32 + %t23 = icmp ne i32 %t22, 0 + %t24 = zext i1 %t23 to i32 + store i32 %t24, ptr %t14 + br label %scend6 +scend6: + %t25 = load i32, ptr %t14 + %t26 = icmp ne i32 %t25, 0 + br i1 %t26, label %then7, label %ifend9 +then7: + store i32 1, ptr %retval + br label %ret +ifend9: + %t27 = load i32, ptr %t0 + %t28 = icmp eq i32 %t27, 95 + %t29 = zext i1 %t28 to i32 + store i32 %t29, ptr %retval + br label %ret +ret: + %t30 = load i32, ptr %retval + ret i32 %t30 +} + +define i32 @fn_char_is_alnum(i32 %arg_c) { +entry: + %retval = alloca i32 + %t0 = alloca i32 + %t1 = alloca i32 + store i32 %arg_c, ptr %t0 + %t2 = load i32, ptr %t0 + %t3 = call i32 @fn_char_is_alpha(i32 %t2) + %t4 = icmp ne i32 %t3, 0 + %t5 = zext i1 %t4 to i32 + store i32 %t5, ptr %t1 + br i1 %t4, label %scend1, label %sc0 +sc0: + %t6 = load i32, ptr %t0 + %t7 = call i32 @fn_char_is_digit(i32 %t6) + %t8 = icmp ne i32 %t7, 0 + %t9 = zext i1 %t8 to i32 + store i32 %t9, ptr %t1 + br label %scend1 +scend1: + %t10 = load i32, ptr %t1 + store i32 %t10, ptr %retval + br label %ret +ret: + %t11 = load i32, ptr %retval + ret i32 %t11 +} + +define ptr @fn_itoa(i32 %arg_v) { +entry: + %retval = alloca ptr + %t0 = alloca i32 + %t7 = alloca ptr + %t15 = alloca i32 + %t17 = alloca i32 + %t26 = alloca ptr + %t27 = alloca i32 + %t44 = alloca i32 + %t53 = alloca ptr + %t54 = alloca i32 + %t60 = alloca i32 + store i32 %arg_v, ptr %t0 + %t1 = load i32, ptr %t0 + %t2 = icmp eq i32 %t1, 0 + %t3 = zext i1 %t2 to i32 + %t4 = icmp ne i32 %t3, 0 + br i1 %t4, label %then0, label %ifend2 +then0: + %t5 = zext i32 2 to i64 + %t6 = call ptr @malloc(i64 %t5) + store ptr %t6, ptr %t7 + %t8 = load ptr, ptr %t7 + %t9 = getelementptr inbounds i8, ptr %t8, i32 0 + %t10 = trunc i32 48 to i8 + store i8 %t10, ptr %t9 + %t11 = load ptr, ptr %t7 + %t12 = getelementptr inbounds i8, ptr %t11, i32 1 + %t13 = trunc i32 0 to i8 + store i8 %t13, ptr %t12 + %t14 = load ptr, ptr %t7 + store ptr %t14, ptr %retval + br label %ret +ifend2: + store i32 0, ptr %t15 + %t16 = load i32, ptr %t0 + store i32 %t16, ptr %t17 + %t18 = load i32, ptr %t17 + %t19 = icmp slt i32 %t18, 0 + %t20 = zext i1 %t19 to i32 + %t21 = icmp ne i32 %t20, 0 + br i1 %t21, label %then3, label %ifend5 +then3: + store i32 1, ptr %t15 + %t22 = load i32, ptr %t17 + %t23 = sub i32 0, %t22 + store i32 %t23, ptr %t17 + br label %ifend5 +ifend5: + %t24 = zext i32 16 to i64 + %t25 = call ptr @malloc(i64 %t24) + store ptr %t25, ptr %t26 + store i32 0, ptr %t27 + br label %wcond6 +wcond6: + %t28 = load i32, ptr %t17 + %t29 = icmp sgt i32 %t28, 0 + %t30 = zext i1 %t29 to i32 + %t31 = icmp ne i32 %t30, 0 + br i1 %t31, label %wbody7, label %wend8 +wbody7: + %t32 = load ptr, ptr %t26 + %t33 = load i32, ptr %t27 + %t34 = load i32, ptr %t17 + %t35 = srem i32 %t34, 10 + %t36 = add i32 48, %t35 + %t37 = getelementptr inbounds i8, ptr %t32, i32 %t33 + %t38 = trunc i32 %t36 to i8 + store i8 %t38, ptr %t37 + %t39 = load i32, ptr %t17 + %t40 = sdiv i32 %t39, 10 + store i32 %t40, ptr %t17 + %t41 = load i32, ptr %t27 + %t42 = add i32 %t41, 1 + store i32 %t42, ptr %t27 + br label %wcond6 +wend8: + %t43 = load i32, ptr %t27 + store i32 %t43, ptr %t44 + %t45 = load i32, ptr %t15 + %t46 = icmp ne i32 %t45, 0 + br i1 %t46, label %then9, label %ifend11 +then9: + %t47 = load i32, ptr %t44 + %t48 = add i32 %t47, 1 + store i32 %t48, ptr %t44 + br label %ifend11 +ifend11: + %t49 = load i32, ptr %t44 + %t50 = add i32 %t49, 1 + %t51 = zext i32 %t50 to i64 + %t52 = call ptr @malloc(i64 %t51) + store ptr %t52, ptr %t53 + store i32 0, ptr %t54 + %t55 = load i32, ptr %t15 + %t56 = icmp ne i32 %t55, 0 + br i1 %t56, label %then12, label %ifend14 +then12: + %t57 = load ptr, ptr %t53 + %t58 = getelementptr inbounds i8, ptr %t57, i32 0 + %t59 = trunc i32 45 to i8 + store i8 %t59, ptr %t58 + store i32 1, ptr %t54 + br label %ifend14 +ifend14: + store i32 0, ptr %t60 + br label %wcond15 +wcond15: + %t61 = load i32, ptr %t60 + %t62 = load i32, ptr %t27 + %t63 = icmp slt i32 %t61, %t62 + %t64 = zext i1 %t63 to i32 + %t65 = icmp ne i32 %t64, 0 + br i1 %t65, label %wbody16, label %wend17 +wbody16: + %t66 = load ptr, ptr %t53 + %t67 = load i32, ptr %t54 + %t68 = load i32, ptr %t60 + %t69 = add i32 %t67, %t68 + %t70 = load ptr, ptr %t26 + %t71 = load i32, ptr %t27 + %t72 = sub i32 %t71, 1 + %t73 = load i32, ptr %t60 + %t74 = sub i32 %t72, %t73 + %t75 = getelementptr inbounds i8, ptr %t70, i32 %t74 + %t76 = load i8, ptr %t75 + %t77 = zext i8 %t76 to i32 + %t78 = getelementptr inbounds i8, ptr %t66, i32 %t69 + %t79 = trunc i32 %t77 to i8 + store i8 %t79, ptr %t78 + %t80 = load i32, ptr %t60 + %t81 = add i32 %t80, 1 + store i32 %t81, ptr %t60 + br label %wcond15 +wend17: + %t82 = load ptr, ptr %t53 + %t83 = load i32, ptr %t44 + %t84 = getelementptr inbounds i8, ptr %t82, i32 %t83 + %t85 = trunc i32 0 to i8 + store i8 %t85, ptr %t84 + %t86 = load ptr, ptr %t53 + store ptr %t86, ptr %retval + br label %ret +ret: + %t87 = load ptr, ptr %retval + ret ptr %t87 +} + +define ptr @fn_buf_new() { +entry: + %retval = alloca ptr + %t6 = alloca ptr + %t0 = getelementptr %Str_Buf, ptr null, i32 1 + %t1 = ptrtoint ptr %t0 to i64 + %t2 = call ptr @malloc(i64 %t1) + %t3 = getelementptr inbounds %Str_Buf, ptr %t2, i32 0, i32 0 + store ptr null, ptr %t3 + %t4 = getelementptr inbounds %Str_Buf, ptr %t2, i32 0, i32 1 + store i32 0, ptr %t4 + %t5 = getelementptr inbounds %Str_Buf, ptr %t2, i32 0, i32 2 + store i32 0, ptr %t5 + store ptr %t2, ptr %t6 + %t7 = load ptr, ptr %t6 + %t8 = getelementptr inbounds %Str_Buf, ptr %t7, i32 0, i32 2 + store i32 256, ptr %t8 + %t9 = load ptr, ptr %t6 + %t10 = getelementptr inbounds %Str_Buf, ptr %t9, i32 0, i32 0 + %t11 = load ptr, ptr %t6 + %t12 = getelementptr inbounds %Str_Buf, ptr %t11, i32 0, i32 2 + %t13 = load i32, ptr %t12 + %t14 = zext i32 %t13 to i64 + %t15 = call ptr @malloc(i64 %t14) + store ptr %t15, ptr %t10 + %t16 = load ptr, ptr %t6 + %t17 = getelementptr inbounds %Str_Buf, ptr %t16, i32 0, i32 1 + store i32 0, ptr %t17 + %t18 = load ptr, ptr %t6 + store ptr %t18, ptr %retval + br label %ret +ret: + %t19 = load ptr, ptr %retval + ret ptr %t19 +} + +define void @fn_buf_ensure(ptr %arg_b, i32 %arg_extra) { +entry: + %t0 = alloca ptr + %t1 = alloca i32 + store ptr %arg_b, ptr %t0 + store i32 %arg_extra, ptr %t1 + %t2 = load ptr, ptr %t0 + %t3 = getelementptr inbounds %Str_Buf, ptr %t2, i32 0, i32 1 + %t4 = load i32, ptr %t3 + %t5 = load i32, ptr %t1 + %t6 = add i32 %t4, %t5 + %t7 = add i32 %t6, 1 + %t8 = load ptr, ptr %t0 + %t9 = getelementptr inbounds %Str_Buf, ptr %t8, i32 0, i32 2 + %t10 = load i32, ptr %t9 + %t11 = icmp sle i32 %t7, %t10 + %t12 = zext i1 %t11 to i32 + %t13 = icmp ne i32 %t12, 0 + br i1 %t13, label %then0, label %ifend2 +then0: + br label %ret +ifend2: + br label %wcond3 +wcond3: + %t14 = load ptr, ptr %t0 + %t15 = getelementptr inbounds %Str_Buf, ptr %t14, i32 0, i32 1 + %t16 = load i32, ptr %t15 + %t17 = load i32, ptr %t1 + %t18 = add i32 %t16, %t17 + %t19 = add i32 %t18, 1 + %t20 = load ptr, ptr %t0 + %t21 = getelementptr inbounds %Str_Buf, ptr %t20, i32 0, i32 2 + %t22 = load i32, ptr %t21 + %t23 = icmp sgt i32 %t19, %t22 + %t24 = zext i1 %t23 to i32 + %t25 = icmp ne i32 %t24, 0 + br i1 %t25, label %wbody4, label %wend5 +wbody4: + %t26 = load ptr, ptr %t0 + %t27 = getelementptr inbounds %Str_Buf, ptr %t26, i32 0, i32 2 + %t28 = load ptr, ptr %t0 + %t29 = getelementptr inbounds %Str_Buf, ptr %t28, i32 0, i32 2 + %t30 = load i32, ptr %t29 + %t31 = mul i32 %t30, 2 + store i32 %t31, ptr %t27 + br label %wcond3 +wend5: + %t32 = load ptr, ptr %t0 + %t33 = getelementptr inbounds %Str_Buf, ptr %t32, i32 0, i32 0 + %t34 = load ptr, ptr %t0 + %t35 = getelementptr inbounds %Str_Buf, ptr %t34, i32 0, i32 0 + %t36 = load ptr, ptr %t35 + %t37 = load ptr, ptr %t0 + %t38 = getelementptr inbounds %Str_Buf, ptr %t37, i32 0, i32 2 + %t39 = load i32, ptr %t38 + %t40 = zext i32 %t39 to i64 + %t41 = call ptr @realloc(ptr %t36, i64 %t40) + store ptr %t41, ptr %t33 + br label %ret +ret: + ret void +} + +define void @fn_buf_putc(ptr %arg_b, i32 %arg_c) { +entry: + %t0 = alloca ptr + %t1 = alloca i32 + store ptr %arg_b, ptr %t0 + store i32 %arg_c, ptr %t1 + %t2 = load ptr, ptr %t0 + call void @fn_buf_ensure(ptr %t2, i32 1) + %t3 = load ptr, ptr %t0 + %t4 = getelementptr inbounds %Str_Buf, ptr %t3, i32 0, i32 0 + %t5 = load ptr, ptr %t4 + %t6 = load ptr, ptr %t0 + %t7 = getelementptr inbounds %Str_Buf, ptr %t6, i32 0, i32 1 + %t8 = load i32, ptr %t7 + %t9 = load i32, ptr %t1 + %t10 = getelementptr inbounds i8, ptr %t5, i32 %t8 + %t11 = trunc i32 %t9 to i8 + store i8 %t11, ptr %t10 + %t12 = load ptr, ptr %t0 + %t13 = getelementptr inbounds %Str_Buf, ptr %t12, i32 0, i32 1 + %t14 = load ptr, ptr %t0 + %t15 = getelementptr inbounds %Str_Buf, ptr %t14, i32 0, i32 1 + %t16 = load i32, ptr %t15 + %t17 = add i32 %t16, 1 + store i32 %t17, ptr %t13 + br label %ret +ret: + ret void +} + +define void @fn_buf_puts(ptr %arg_b, ptr %arg_s) { +entry: + %t0 = alloca ptr + %t1 = alloca ptr + %t2 = alloca i32 + store ptr %arg_b, ptr %t0 + store ptr %arg_s, ptr %t1 + store i32 0, ptr %t2 + br label %wcond0 +wcond0: + %t3 = load ptr, ptr %t1 + %t4 = load i32, ptr %t2 + %t5 = getelementptr inbounds i8, ptr %t3, i32 %t4 + %t6 = load i8, ptr %t5 + %t7 = zext i8 %t6 to i32 + %t8 = icmp ne i32 %t7, 0 + %t9 = zext i1 %t8 to i32 + %t10 = icmp ne i32 %t9, 0 + br i1 %t10, label %wbody1, label %wend2 +wbody1: + %t11 = load ptr, ptr %t0 + %t12 = load ptr, ptr %t1 + %t13 = load i32, ptr %t2 + %t14 = getelementptr inbounds i8, ptr %t12, i32 %t13 + %t15 = load i8, ptr %t14 + %t16 = zext i8 %t15 to i32 + call void @fn_buf_putc(ptr %t11, i32 %t16) + %t17 = load i32, ptr %t2 + %t18 = add i32 %t17, 1 + store i32 %t18, ptr %t2 + br label %wcond0 +wend2: + br label %ret +ret: + ret void +} + +define void @fn_buf_puti(ptr %arg_b, i32 %arg_n) { +entry: + %t0 = alloca ptr + %t1 = alloca i32 + store ptr %arg_b, ptr %t0 + store i32 %arg_n, ptr %t1 + %t2 = load ptr, ptr %t0 + %t3 = load i32, ptr %t1 + %t4 = call ptr @fn_itoa(i32 %t3) + call void @fn_buf_puts(ptr %t2, ptr %t4) + br label %ret +ret: + ret void +} + +define ptr @fn_buf_str(ptr %arg_b) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + store ptr %arg_b, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = getelementptr inbounds %Str_Buf, ptr %t1, i32 0, i32 0 + %t3 = load ptr, ptr %t2 + %t4 = load ptr, ptr %t0 + %t5 = getelementptr inbounds %Str_Buf, ptr %t4, i32 0, i32 1 + %t6 = load i32, ptr %t5 + %t7 = getelementptr inbounds i8, ptr %t3, i32 %t6 + %t8 = trunc i32 0 to i8 + store i8 %t8, ptr %t7 + %t9 = load ptr, ptr %t0 + %t10 = getelementptr inbounds %Str_Buf, ptr %t9, i32 0, i32 0 + %t11 = load ptr, ptr %t10 + store ptr %t11, ptr %retval + br label %ret +ret: + %t12 = load ptr, ptr %retval + ret ptr %t12 +} + +define ptr @fn_read_file(ptr %arg_path) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t3 = alloca ptr + %t14 = alloca i32 + %t22 = alloca ptr + store ptr %arg_path, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = call ptr @fopen(ptr %t1, ptr @.str0) + store ptr %t2, ptr %t3 + %t4 = load ptr, ptr %t3 + %t5 = icmp eq ptr %t4, null + %t6 = zext i1 %t5 to i32 + %t7 = icmp ne i32 %t6, 0 + br i1 %t7, label %then0, label %ifend2 +then0: + store ptr null, ptr %retval + br label %ret +ifend2: + %t8 = load ptr, ptr %t3 + %t9 = sext i32 0 to i64 + %t10 = call i32 @fseek(ptr %t8, i64 %t9, i32 2) + %t11 = load ptr, ptr %t3 + %t12 = call i64 @ftell(ptr %t11) + %t13 = trunc i64 %t12 to i32 + store i32 %t13, ptr %t14 + %t15 = load ptr, ptr %t3 + %t16 = sext i32 0 to i64 + %t17 = call i32 @fseek(ptr %t15, i64 %t16, i32 0) + %t18 = load i32, ptr %t14 + %t19 = add i32 %t18, 1 + %t20 = zext i32 %t19 to i64 + %t21 = call ptr @malloc(i64 %t20) + store ptr %t21, ptr %t22 + %t23 = load ptr, ptr %t3 + %t24 = load ptr, ptr %t22 + %t25 = load i32, ptr %t14 + %t26 = zext i32 %t25 to i64 + %t27 = call i64 @fread(ptr %t24, i64 1, i64 %t26, ptr %t23) + %t28 = trunc i64 %t27 to i32 + %t29 = load ptr, ptr %t22 + %t30 = load i32, ptr %t14 + %t31 = getelementptr inbounds i8, ptr %t29, i32 %t30 + %t32 = trunc i32 0 to i8 + store i8 %t32, ptr %t31 + %t33 = load ptr, ptr %t3 + call i32 @fclose(ptr %t33) + %t34 = load ptr, ptr %t22 + store ptr %t34, ptr %retval + br label %ret +ret: + %t35 = load ptr, ptr %retval + ret ptr %t35 +} + +define i32 @fn_cstr_len(ptr %arg_s) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t1 = alloca i32 + store ptr %arg_s, ptr %t0 + store i32 0, ptr %t1 + br label %wcond0 +wcond0: + %t2 = load ptr, ptr %t0 + %t3 = load i32, ptr %t1 + %t4 = getelementptr inbounds i8, ptr %t2, i32 %t3 + %t5 = load i8, ptr %t4 + %t6 = zext i8 %t5 to i32 + %t7 = icmp ne i32 %t6, 0 + %t8 = zext i1 %t7 to i32 + %t9 = icmp ne i32 %t8, 0 + br i1 %t9, label %wbody1, label %wend2 +wbody1: + %t10 = load i32, ptr %t1 + %t11 = add i32 %t10, 1 + store i32 %t11, ptr %t1 + br label %wcond0 +wend2: + %t12 = load i32, ptr %t1 + store i32 %t12, ptr %retval + br label %ret +ret: + %t13 = load i32, ptr %retval + ret i32 %t13 +} + +define ptr @fn_node(i32 %arg_kind) { +entry: + %retval = alloca ptr + %t0 = alloca i32 + %t13 = alloca ptr + store i32 %arg_kind, ptr %t0 + %t1 = getelementptr %Str_Node, ptr null, i32 1 + %t2 = ptrtoint ptr %t1 to i64 + %t3 = call ptr @malloc(i64 %t2) + %t4 = getelementptr inbounds %Str_Node, ptr %t3, i32 0, i32 0 + store i32 0, ptr %t4 + %t5 = getelementptr inbounds %Str_Node, ptr %t3, i32 0, i32 1 + store ptr null, ptr %t5 + %t6 = getelementptr inbounds %Str_Node, ptr %t3, i32 0, i32 2 + store i32 0, ptr %t6 + %t7 = getelementptr inbounds %Str_Node, ptr %t3, i32 0, i32 3 + store ptr null, ptr %t7 + %t8 = getelementptr inbounds %Str_Node, ptr %t3, i32 0, i32 4 + store ptr null, ptr %t8 + %t9 = getelementptr inbounds %Str_Node, ptr %t3, i32 0, i32 5 + store ptr null, ptr %t9 + %t10 = getelementptr inbounds %Str_Node, ptr %t3, i32 0, i32 6 + store ptr null, ptr %t10 + %t11 = getelementptr inbounds %Str_Node, ptr %t3, i32 0, i32 7 + store ptr null, ptr %t11 + %t12 = getelementptr inbounds %Str_Node, ptr %t3, i32 0, i32 8 + store i32 0, ptr %t12 + store ptr %t3, ptr %t13 + %t14 = load ptr, ptr %t13 + %t15 = getelementptr inbounds %Str_Node, ptr %t14, i32 0, i32 0 + %t16 = load i32, ptr %t0 + store i32 %t16, ptr %t15 + %t17 = load ptr, ptr %t13 + %t18 = getelementptr inbounds %Str_Node, ptr %t17, i32 0, i32 7 + %t19 = getelementptr %LSlice, ptr null, i32 1 + %t20 = ptrtoint ptr %t19 to i64 + %t21 = call ptr @malloc(i64 %t20) + %t22 = getelementptr inbounds %LSlice, ptr %t21, i32 0, i32 0 + store ptr null, ptr %t22 + %t23 = getelementptr inbounds %LSlice, ptr %t21, i32 0, i32 1 + store i32 0, ptr %t23 + %t24 = getelementptr inbounds %LSlice, ptr %t21, i32 0, i32 2 + store i32 0, ptr %t24 + store ptr %t21, ptr %t18 + %t25 = load ptr, ptr %t13 + store ptr %t25, ptr %retval + br label %ret +ret: + %t26 = load ptr, ptr %retval + ret ptr %t26 +} + +define void @fn_tok_push(i32 %arg_kind, ptr %arg_text, i32 %arg_ival, i32 %arg_line) { +entry: + %t0 = alloca i32 + %t1 = alloca ptr + %t2 = alloca i32 + %t3 = alloca i32 + %t11 = alloca ptr + store i32 %arg_kind, ptr %t0 + store ptr %arg_text, ptr %t1 + store i32 %arg_ival, ptr %t2 + store i32 %arg_line, ptr %t3 + %t4 = getelementptr %Str_Tok, ptr null, i32 1 + %t5 = ptrtoint ptr %t4 to i64 + %t6 = call ptr @malloc(i64 %t5) + %t7 = getelementptr inbounds %Str_Tok, ptr %t6, i32 0, i32 0 + store i32 0, ptr %t7 + %t8 = getelementptr inbounds %Str_Tok, ptr %t6, i32 0, i32 1 + store ptr null, ptr %t8 + %t9 = getelementptr inbounds %Str_Tok, ptr %t6, i32 0, i32 2 + store i32 0, ptr %t9 + %t10 = getelementptr inbounds %Str_Tok, ptr %t6, i32 0, i32 3 + store i32 0, ptr %t10 + store ptr %t6, ptr %t11 + %t12 = load ptr, ptr %t11 + %t13 = getelementptr inbounds %Str_Tok, ptr %t12, i32 0, i32 0 + %t14 = load i32, ptr %t0 + store i32 %t14, ptr %t13 + %t15 = load ptr, ptr %t11 + %t16 = getelementptr inbounds %Str_Tok, ptr %t15, i32 0, i32 1 + %t17 = load ptr, ptr %t1 + store ptr %t17, ptr %t16 + %t18 = load ptr, ptr %t11 + %t19 = getelementptr inbounds %Str_Tok, ptr %t18, i32 0, i32 2 + %t20 = load i32, ptr %t2 + store i32 %t20, ptr %t19 + %t21 = load ptr, ptr %t11 + %t22 = getelementptr inbounds %Str_Tok, ptr %t21, i32 0, i32 3 + %t23 = load i32, ptr %t3 + store i32 %t23, ptr %t22 + %t24 = load ptr, ptr @g_toks + %t25 = getelementptr inbounds %LSlice, ptr %t24, i32 0, i32 1 + %t26 = getelementptr inbounds %LSlice, ptr %t24, i32 0, i32 2 + %t27 = getelementptr inbounds %LSlice, ptr %t24, i32 0, i32 0 + %t28 = load i32, ptr %t25 + %t29 = load i32, ptr %t26 + %t30 = icmp sge i32 %t28, %t29 + br i1 %t30, label %grow0, label %put1 +grow0: + %t31 = mul i32 %t29, 2 + %t32 = icmp eq i32 %t29, 0 + %t33 = select i1 %t32, i32 8, i32 %t31 + %t34 = getelementptr ptr, ptr null, i32 1 + %t35 = ptrtoint ptr %t34 to i64 + %t36 = zext i32 %t33 to i64 + %t37 = mul i64 %t36, %t35 + %t38 = load ptr, ptr %t27 + %t39 = call ptr @realloc(ptr %t38, i64 %t37) + store ptr %t39, ptr %t27 + store i32 %t33, ptr %t26 + br label %put1 +put1: + %t40 = load ptr, ptr %t11 + %t41 = load ptr, ptr %t27 + %t42 = getelementptr inbounds ptr, ptr %t41, i32 %t28 + store ptr %t40, ptr %t42 + %t43 = add i32 %t28, 1 + store i32 %t43, ptr %t25 + br label %ret +ret: + ret void +} + +define i32 @fn_two_at(ptr %arg_src, i32 %arg_i, i32 %arg_a, i32 %arg_b) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t1 = alloca i32 + %t2 = alloca i32 + %t3 = alloca i32 + %t4 = alloca i32 + store ptr %arg_src, ptr %t0 + store i32 %arg_i, ptr %t1 + store i32 %arg_a, ptr %t2 + store i32 %arg_b, ptr %t3 + %t5 = load ptr, ptr %t0 + %t6 = load i32, ptr %t1 + %t7 = getelementptr inbounds i8, ptr %t5, i32 %t6 + %t8 = load i8, ptr %t7 + %t9 = zext i8 %t8 to i32 + %t10 = load i32, ptr %t2 + %t11 = icmp eq i32 %t9, %t10 + %t12 = zext i1 %t11 to i32 + %t13 = icmp ne i32 %t12, 0 + %t14 = zext i1 %t13 to i32 + store i32 %t14, ptr %t4 + br i1 %t13, label %sc0, label %scend1 +sc0: + %t15 = load ptr, ptr %t0 + %t16 = load i32, ptr %t1 + %t17 = add i32 %t16, 1 + %t18 = getelementptr inbounds i8, ptr %t15, i32 %t17 + %t19 = load i8, ptr %t18 + %t20 = zext i8 %t19 to i32 + %t21 = load i32, ptr %t3 + %t22 = icmp eq i32 %t20, %t21 + %t23 = zext i1 %t22 to i32 + %t24 = icmp ne i32 %t23, 0 + %t25 = zext i1 %t24 to i32 + store i32 %t25, ptr %t4 + br label %scend1 +scend1: + %t26 = load i32, ptr %t4 + store i32 %t26, ptr %retval + br label %ret +ret: + %t27 = load i32, ptr %retval + ret i32 %t27 +} + +define i32 @fn_is_op1(i32 %arg_c) { +entry: + %retval = alloca i32 + %t0 = alloca i32 + %t1 = alloca i32 + %t2 = alloca i32 + %t3 = alloca i32 + %t4 = alloca i32 + %t41 = alloca i32 + %t42 = alloca i32 + %t63 = alloca i32 + %t64 = alloca i32 + %t65 = alloca i32 + %t94 = alloca i32 + %t95 = alloca i32 + %t96 = alloca i32 + %t97 = alloca i32 + %t134 = alloca i32 + store i32 %arg_c, ptr %t0 + %t5 = load i32, ptr %t0 + %t6 = icmp eq i32 %t5, 43 + %t7 = zext i1 %t6 to i32 + %t8 = icmp ne i32 %t7, 0 + %t9 = zext i1 %t8 to i32 + store i32 %t9, ptr %t4 + br i1 %t8, label %scend1, label %sc0 +sc0: + %t10 = load i32, ptr %t0 + %t11 = icmp eq i32 %t10, 45 + %t12 = zext i1 %t11 to i32 + %t13 = icmp ne i32 %t12, 0 + %t14 = zext i1 %t13 to i32 + store i32 %t14, ptr %t4 + br label %scend1 +scend1: + %t15 = load i32, ptr %t4 + %t16 = icmp ne i32 %t15, 0 + %t17 = zext i1 %t16 to i32 + store i32 %t17, ptr %t3 + br i1 %t16, label %scend3, label %sc2 +sc2: + %t18 = load i32, ptr %t0 + %t19 = icmp eq i32 %t18, 42 + %t20 = zext i1 %t19 to i32 + %t21 = icmp ne i32 %t20, 0 + %t22 = zext i1 %t21 to i32 + store i32 %t22, ptr %t3 + br label %scend3 +scend3: + %t23 = load i32, ptr %t3 + %t24 = icmp ne i32 %t23, 0 + %t25 = zext i1 %t24 to i32 + store i32 %t25, ptr %t2 + br i1 %t24, label %scend5, label %sc4 +sc4: + %t26 = load i32, ptr %t0 + %t27 = icmp eq i32 %t26, 47 + %t28 = zext i1 %t27 to i32 + %t29 = icmp ne i32 %t28, 0 + %t30 = zext i1 %t29 to i32 + store i32 %t30, ptr %t2 + br label %scend5 +scend5: + %t31 = load i32, ptr %t2 + %t32 = icmp ne i32 %t31, 0 + %t33 = zext i1 %t32 to i32 + store i32 %t33, ptr %t1 + br i1 %t32, label %scend7, label %sc6 +sc6: + %t34 = load i32, ptr %t0 + %t35 = icmp eq i32 %t34, 37 + %t36 = zext i1 %t35 to i32 + %t37 = icmp ne i32 %t36, 0 + %t38 = zext i1 %t37 to i32 + store i32 %t38, ptr %t1 + br label %scend7 +scend7: + %t39 = load i32, ptr %t1 + %t40 = icmp ne i32 %t39, 0 + br i1 %t40, label %then8, label %ifend10 +then8: + store i32 1, ptr %retval + br label %ret +ifend10: + %t43 = load i32, ptr %t0 + %t44 = icmp eq i32 %t43, 60 + %t45 = zext i1 %t44 to i32 + %t46 = icmp ne i32 %t45, 0 + %t47 = zext i1 %t46 to i32 + store i32 %t47, ptr %t42 + br i1 %t46, label %scend12, label %sc11 +sc11: + %t48 = load i32, ptr %t0 + %t49 = icmp eq i32 %t48, 62 + %t50 = zext i1 %t49 to i32 + %t51 = icmp ne i32 %t50, 0 + %t52 = zext i1 %t51 to i32 + store i32 %t52, ptr %t42 + br label %scend12 +scend12: + %t53 = load i32, ptr %t42 + %t54 = icmp ne i32 %t53, 0 + %t55 = zext i1 %t54 to i32 + store i32 %t55, ptr %t41 + br i1 %t54, label %scend14, label %sc13 +sc13: + %t56 = load i32, ptr %t0 + %t57 = icmp eq i32 %t56, 61 + %t58 = zext i1 %t57 to i32 + %t59 = icmp ne i32 %t58, 0 + %t60 = zext i1 %t59 to i32 + store i32 %t60, ptr %t41 + br label %scend14 +scend14: + %t61 = load i32, ptr %t41 + %t62 = icmp ne i32 %t61, 0 + br i1 %t62, label %then15, label %ifend17 +then15: + store i32 1, ptr %retval + br label %ret +ifend17: + %t66 = load i32, ptr %t0 + %t67 = icmp eq i32 %t66, 40 + %t68 = zext i1 %t67 to i32 + %t69 = icmp ne i32 %t68, 0 + %t70 = zext i1 %t69 to i32 + store i32 %t70, ptr %t65 + br i1 %t69, label %scend19, label %sc18 +sc18: + %t71 = load i32, ptr %t0 + %t72 = icmp eq i32 %t71, 41 + %t73 = zext i1 %t72 to i32 + %t74 = icmp ne i32 %t73, 0 + %t75 = zext i1 %t74 to i32 + store i32 %t75, ptr %t65 + br label %scend19 +scend19: + %t76 = load i32, ptr %t65 + %t77 = icmp ne i32 %t76, 0 + %t78 = zext i1 %t77 to i32 + store i32 %t78, ptr %t64 + br i1 %t77, label %scend21, label %sc20 +sc20: + %t79 = load i32, ptr %t0 + %t80 = icmp eq i32 %t79, 123 + %t81 = zext i1 %t80 to i32 + %t82 = icmp ne i32 %t81, 0 + %t83 = zext i1 %t82 to i32 + store i32 %t83, ptr %t64 + br label %scend21 +scend21: + %t84 = load i32, ptr %t64 + %t85 = icmp ne i32 %t84, 0 + %t86 = zext i1 %t85 to i32 + store i32 %t86, ptr %t63 + br i1 %t85, label %scend23, label %sc22 +sc22: + %t87 = load i32, ptr %t0 + %t88 = icmp eq i32 %t87, 125 + %t89 = zext i1 %t88 to i32 + %t90 = icmp ne i32 %t89, 0 + %t91 = zext i1 %t90 to i32 + store i32 %t91, ptr %t63 + br label %scend23 +scend23: + %t92 = load i32, ptr %t63 + %t93 = icmp ne i32 %t92, 0 + br i1 %t93, label %then24, label %ifend26 +then24: + store i32 1, ptr %retval + br label %ret +ifend26: + %t98 = load i32, ptr %t0 + %t99 = icmp eq i32 %t98, 91 + %t100 = zext i1 %t99 to i32 + %t101 = icmp ne i32 %t100, 0 + %t102 = zext i1 %t101 to i32 + store i32 %t102, ptr %t97 + br i1 %t101, label %scend28, label %sc27 +sc27: + %t103 = load i32, ptr %t0 + %t104 = icmp eq i32 %t103, 93 + %t105 = zext i1 %t104 to i32 + %t106 = icmp ne i32 %t105, 0 + %t107 = zext i1 %t106 to i32 + store i32 %t107, ptr %t97 + br label %scend28 +scend28: + %t108 = load i32, ptr %t97 + %t109 = icmp ne i32 %t108, 0 + %t110 = zext i1 %t109 to i32 + store i32 %t110, ptr %t96 + br i1 %t109, label %scend30, label %sc29 +sc29: + %t111 = load i32, ptr %t0 + %t112 = icmp eq i32 %t111, 44 + %t113 = zext i1 %t112 to i32 + %t114 = icmp ne i32 %t113, 0 + %t115 = zext i1 %t114 to i32 + store i32 %t115, ptr %t96 + br label %scend30 +scend30: + %t116 = load i32, ptr %t96 + %t117 = icmp ne i32 %t116, 0 + %t118 = zext i1 %t117 to i32 + store i32 %t118, ptr %t95 + br i1 %t117, label %scend32, label %sc31 +sc31: + %t119 = load i32, ptr %t0 + %t120 = icmp eq i32 %t119, 58 + %t121 = zext i1 %t120 to i32 + %t122 = icmp ne i32 %t121, 0 + %t123 = zext i1 %t122 to i32 + store i32 %t123, ptr %t95 + br label %scend32 +scend32: + %t124 = load i32, ptr %t95 + %t125 = icmp ne i32 %t124, 0 + %t126 = zext i1 %t125 to i32 + store i32 %t126, ptr %t94 + br i1 %t125, label %scend34, label %sc33 +sc33: + %t127 = load i32, ptr %t0 + %t128 = icmp eq i32 %t127, 46 + %t129 = zext i1 %t128 to i32 + %t130 = icmp ne i32 %t129, 0 + %t131 = zext i1 %t130 to i32 + store i32 %t131, ptr %t94 + br label %scend34 +scend34: + %t132 = load i32, ptr %t94 + %t133 = icmp ne i32 %t132, 0 + br i1 %t133, label %then35, label %ifend37 +then35: + store i32 1, ptr %retval + br label %ret +ifend37: + %t135 = load i32, ptr %t0 + %t136 = icmp eq i32 %t135, 33 + %t137 = zext i1 %t136 to i32 + %t138 = icmp ne i32 %t137, 0 + %t139 = zext i1 %t138 to i32 + store i32 %t139, ptr %t134 + br i1 %t138, label %scend39, label %sc38 +sc38: + %t140 = load i32, ptr %t0 + %t141 = icmp eq i32 %t140, 64 + %t142 = zext i1 %t141 to i32 + %t143 = icmp ne i32 %t142, 0 + %t144 = zext i1 %t143 to i32 + store i32 %t144, ptr %t134 + br label %scend39 +scend39: + %t145 = load i32, ptr %t134 + %t146 = icmp ne i32 %t145, 0 + br i1 %t146, label %then40, label %ifend42 +then40: + store i32 1, ptr %retval + br label %ret +ifend42: + store i32 0, ptr %retval + br label %ret +ret: + %t147 = load i32, ptr %retval + ret i32 %t147 +} + +define void @fn_lex(ptr %arg_src) { +entry: + %t0 = alloca ptr + %t7 = alloca i32 + %t8 = alloca i32 + %t11 = alloca i32 + %t22 = alloca i32 + %t32 = alloca i32 + %t33 = alloca i32 + %t60 = alloca i32 + %t87 = alloca i32 + %t91 = alloca ptr + %t92 = alloca i32 + %t93 = alloca i32 + %t125 = alloca i32 + %t127 = alloca i32 + %t176 = alloca i32 + %t191 = alloca i32 + %t228 = alloca i32 + %t246 = alloca i32 + %t259 = alloca i32 + %t260 = alloca i32 + %t266 = alloca i32 + %t281 = alloca i32 + %t304 = alloca i32 + %t305 = alloca i32 + %t333 = alloca i32 + %t334 = alloca i32 + %t366 = alloca i32 + %t367 = alloca i32 + %t368 = alloca i32 + %t405 = alloca i32 + %t414 = alloca i32 + %t415 = alloca i32 + store ptr %arg_src, ptr %t0 + %t1 = getelementptr %LSlice, ptr null, i32 1 + %t2 = ptrtoint ptr %t1 to i64 + %t3 = call ptr @malloc(i64 %t2) + %t4 = getelementptr inbounds %LSlice, ptr %t3, i32 0, i32 0 + store ptr null, ptr %t4 + %t5 = getelementptr inbounds %LSlice, ptr %t3, i32 0, i32 1 + store i32 0, ptr %t5 + %t6 = getelementptr inbounds %LSlice, ptr %t3, i32 0, i32 2 + store i32 0, ptr %t6 + store ptr %t3, ptr @g_toks + store i32 0, ptr %t7 + store i32 1, ptr %t8 + %t9 = load ptr, ptr %t0 + %t10 = call i32 @fn_slen(ptr %t9) + store i32 %t10, ptr %t11 + br label %wcond0 +wcond0: + %t12 = load i32, ptr %t7 + %t13 = load i32, ptr %t11 + %t14 = icmp slt i32 %t12, %t13 + %t15 = zext i1 %t14 to i32 + %t16 = icmp ne i32 %t15, 0 + br i1 %t16, label %wbody1, label %wend2 +wbody1: + %t17 = load ptr, ptr %t0 + %t18 = load i32, ptr %t7 + %t19 = getelementptr inbounds i8, ptr %t17, i32 %t18 + %t20 = load i8, ptr %t19 + %t21 = zext i8 %t20 to i32 + store i32 %t21, ptr %t22 + %t23 = load i32, ptr %t22 + %t24 = icmp eq i32 %t23, 10 + %t25 = zext i1 %t24 to i32 + %t26 = icmp ne i32 %t25, 0 + br i1 %t26, label %then3, label %ifend5 +then3: + %t27 = load i32, ptr %t8 + call void @fn_tok_push(i32 4, ptr null, i32 0, i32 %t27) + %t28 = load i32, ptr %t8 + %t29 = add i32 %t28, 1 + store i32 %t29, ptr %t8 + %t30 = load i32, ptr %t7 + %t31 = add i32 %t30, 1 + store i32 %t31, ptr %t7 + br label %wcond0 +ifend5: + %t34 = load i32, ptr %t22 + %t35 = icmp eq i32 %t34, 32 + %t36 = zext i1 %t35 to i32 + %t37 = icmp ne i32 %t36, 0 + %t38 = zext i1 %t37 to i32 + store i32 %t38, ptr %t33 + br i1 %t37, label %scend7, label %sc6 +sc6: + %t39 = load i32, ptr %t22 + %t40 = icmp eq i32 %t39, 9 + %t41 = zext i1 %t40 to i32 + %t42 = icmp ne i32 %t41, 0 + %t43 = zext i1 %t42 to i32 + store i32 %t43, ptr %t33 + br label %scend7 +scend7: + %t44 = load i32, ptr %t33 + %t45 = icmp ne i32 %t44, 0 + %t46 = zext i1 %t45 to i32 + store i32 %t46, ptr %t32 + br i1 %t45, label %scend9, label %sc8 +sc8: + %t47 = load i32, ptr %t22 + %t48 = icmp eq i32 %t47, 13 + %t49 = zext i1 %t48 to i32 + %t50 = icmp ne i32 %t49, 0 + %t51 = zext i1 %t50 to i32 + store i32 %t51, ptr %t32 + br label %scend9 +scend9: + %t52 = load i32, ptr %t32 + %t53 = icmp ne i32 %t52, 0 + br i1 %t53, label %then10, label %ifend12 +then10: + %t54 = load i32, ptr %t7 + %t55 = add i32 %t54, 1 + store i32 %t55, ptr %t7 + br label %wcond0 +ifend12: + %t56 = load i32, ptr %t22 + %t57 = icmp eq i32 %t56, 35 + %t58 = zext i1 %t57 to i32 + %t59 = icmp ne i32 %t58, 0 + br i1 %t59, label %then13, label %ifend15 +then13: + br label %wcond16 +wcond16: + %t61 = load i32, ptr %t7 + %t62 = load i32, ptr %t11 + %t63 = icmp slt i32 %t61, %t62 + %t64 = zext i1 %t63 to i32 + %t65 = icmp ne i32 %t64, 0 + %t66 = zext i1 %t65 to i32 + store i32 %t66, ptr %t60 + br i1 %t65, label %sc19, label %scend20 +sc19: + %t67 = load ptr, ptr %t0 + %t68 = load i32, ptr %t7 + %t69 = getelementptr inbounds i8, ptr %t67, i32 %t68 + %t70 = load i8, ptr %t69 + %t71 = zext i8 %t70 to i32 + %t72 = icmp ne i32 %t71, 10 + %t73 = zext i1 %t72 to i32 + %t74 = icmp ne i32 %t73, 0 + %t75 = zext i1 %t74 to i32 + store i32 %t75, ptr %t60 + br label %scend20 +scend20: + %t76 = load i32, ptr %t60 + %t77 = icmp ne i32 %t76, 0 + br i1 %t77, label %wbody17, label %wend18 +wbody17: + %t78 = load i32, ptr %t7 + %t79 = add i32 %t78, 1 + store i32 %t79, ptr %t7 + br label %wcond16 +wend18: + br label %wcond0 +ifend15: + %t80 = load i32, ptr %t22 + %t81 = icmp eq i32 %t80, 34 + %t82 = zext i1 %t81 to i32 + %t83 = icmp ne i32 %t82, 0 + br i1 %t83, label %then21, label %ifend23 +then21: + %t84 = load i32, ptr %t7 + %t85 = add i32 %t84, 1 + store i32 %t85, ptr %t7 + %t86 = load i32, ptr %t7 + store i32 %t86, ptr %t87 + %t88 = load i32, ptr %t11 + %t89 = zext i32 %t88 to i64 + %t90 = call ptr @malloc(i64 %t89) + store ptr %t90, ptr %t91 + store i32 0, ptr %t92 + br label %wcond24 +wcond24: + %t94 = load i32, ptr %t7 + %t95 = load i32, ptr %t11 + %t96 = icmp slt i32 %t94, %t95 + %t97 = zext i1 %t96 to i32 + %t98 = icmp ne i32 %t97, 0 + %t99 = zext i1 %t98 to i32 + store i32 %t99, ptr %t93 + br i1 %t98, label %sc27, label %scend28 +sc27: + %t100 = load ptr, ptr %t0 + %t101 = load i32, ptr %t7 + %t102 = getelementptr inbounds i8, ptr %t100, i32 %t101 + %t103 = load i8, ptr %t102 + %t104 = zext i8 %t103 to i32 + %t105 = icmp ne i32 %t104, 34 + %t106 = zext i1 %t105 to i32 + %t107 = icmp ne i32 %t106, 0 + %t108 = zext i1 %t107 to i32 + store i32 %t108, ptr %t93 + br label %scend28 +scend28: + %t109 = load i32, ptr %t93 + %t110 = icmp ne i32 %t109, 0 + br i1 %t110, label %wbody25, label %wend26 +wbody25: + %t111 = load ptr, ptr %t0 + %t112 = load i32, ptr %t7 + %t113 = getelementptr inbounds i8, ptr %t111, i32 %t112 + %t114 = load i8, ptr %t113 + %t115 = zext i8 %t114 to i32 + %t116 = icmp eq i32 %t115, 92 + %t117 = zext i1 %t116 to i32 + %t118 = icmp ne i32 %t117, 0 + br i1 %t118, label %then29, label %else30 +then29: + %t119 = load ptr, ptr %t0 + %t120 = load i32, ptr %t7 + %t121 = add i32 %t120, 1 + %t122 = getelementptr inbounds i8, ptr %t119, i32 %t121 + %t123 = load i8, ptr %t122 + %t124 = zext i8 %t123 to i32 + store i32 %t124, ptr %t125 + %t126 = load i32, ptr %t125 + store i32 %t126, ptr %t127 + %t128 = load i32, ptr %t125 + %t129 = icmp eq i32 %t128, 110 + %t130 = zext i1 %t129 to i32 + %t131 = icmp ne i32 %t130, 0 + br i1 %t131, label %then32, label %ifend34 +then32: + store i32 10, ptr %t127 + br label %ifend34 +ifend34: + %t132 = load i32, ptr %t125 + %t133 = icmp eq i32 %t132, 116 + %t134 = zext i1 %t133 to i32 + %t135 = icmp ne i32 %t134, 0 + br i1 %t135, label %then35, label %ifend37 +then35: + store i32 9, ptr %t127 + br label %ifend37 +ifend37: + %t136 = load i32, ptr %t125 + %t137 = icmp eq i32 %t136, 48 + %t138 = zext i1 %t137 to i32 + %t139 = icmp ne i32 %t138, 0 + br i1 %t139, label %then38, label %ifend40 +then38: + store i32 0, ptr %t127 + br label %ifend40 +ifend40: + %t140 = load ptr, ptr %t91 + %t141 = load i32, ptr %t92 + %t142 = load i32, ptr %t127 + %t143 = getelementptr inbounds i8, ptr %t140, i32 %t141 + %t144 = trunc i32 %t142 to i8 + store i8 %t144, ptr %t143 + %t145 = load i32, ptr %t92 + %t146 = add i32 %t145, 1 + store i32 %t146, ptr %t92 + %t147 = load i32, ptr %t7 + %t148 = add i32 %t147, 2 + store i32 %t148, ptr %t7 + br label %ifend31 +else30: + %t149 = load ptr, ptr %t91 + %t150 = load i32, ptr %t92 + %t151 = load ptr, ptr %t0 + %t152 = load i32, ptr %t7 + %t153 = getelementptr inbounds i8, ptr %t151, i32 %t152 + %t154 = load i8, ptr %t153 + %t155 = zext i8 %t154 to i32 + %t156 = getelementptr inbounds i8, ptr %t149, i32 %t150 + %t157 = trunc i32 %t155 to i8 + store i8 %t157, ptr %t156 + %t158 = load i32, ptr %t92 + %t159 = add i32 %t158, 1 + store i32 %t159, ptr %t92 + %t160 = load i32, ptr %t7 + %t161 = add i32 %t160, 1 + store i32 %t161, ptr %t7 + br label %ifend31 +ifend31: + br label %wcond24 +wend26: + %t162 = load i32, ptr %t7 + %t163 = add i32 %t162, 1 + store i32 %t163, ptr %t7 + %t164 = load ptr, ptr %t91 + %t165 = load i32, ptr %t92 + %t166 = getelementptr inbounds i8, ptr %t164, i32 %t165 + %t167 = trunc i32 0 to i8 + store i8 %t167, ptr %t166 + %t168 = load ptr, ptr %t91 + %t169 = load i32, ptr %t8 + call void @fn_tok_push(i32 2, ptr %t168, i32 0, i32 %t169) + br label %wcond0 +ifend23: + %t170 = load i32, ptr %t22 + %t171 = icmp eq i32 %t170, 39 + %t172 = zext i1 %t171 to i32 + %t173 = icmp ne i32 %t172, 0 + br i1 %t173, label %then41, label %ifend43 +then41: + %t174 = load i32, ptr %t7 + %t175 = add i32 %t174, 1 + store i32 %t175, ptr %t7 + store i32 0, ptr %t176 + %t177 = load ptr, ptr %t0 + %t178 = load i32, ptr %t7 + %t179 = getelementptr inbounds i8, ptr %t177, i32 %t178 + %t180 = load i8, ptr %t179 + %t181 = zext i8 %t180 to i32 + %t182 = icmp eq i32 %t181, 92 + %t183 = zext i1 %t182 to i32 + %t184 = icmp ne i32 %t183, 0 + br i1 %t184, label %then44, label %else45 +then44: + %t185 = load ptr, ptr %t0 + %t186 = load i32, ptr %t7 + %t187 = add i32 %t186, 1 + %t188 = getelementptr inbounds i8, ptr %t185, i32 %t187 + %t189 = load i8, ptr %t188 + %t190 = zext i8 %t189 to i32 + store i32 %t190, ptr %t191 + %t192 = load i32, ptr %t191 + %t193 = icmp eq i32 %t192, 110 + %t194 = zext i1 %t193 to i32 + %t195 = icmp ne i32 %t194, 0 + br i1 %t195, label %then47, label %ifend49 +then47: + store i32 10, ptr %t176 + br label %ifend49 +ifend49: + %t196 = load i32, ptr %t191 + %t197 = icmp eq i32 %t196, 116 + %t198 = zext i1 %t197 to i32 + %t199 = icmp ne i32 %t198, 0 + br i1 %t199, label %then50, label %ifend52 +then50: + store i32 9, ptr %t176 + br label %ifend52 +ifend52: + %t200 = load i32, ptr %t191 + %t201 = icmp eq i32 %t200, 48 + %t202 = zext i1 %t201 to i32 + %t203 = icmp ne i32 %t202, 0 + br i1 %t203, label %then53, label %ifend55 +then53: + store i32 0, ptr %t176 + br label %ifend55 +ifend55: + %t204 = load i32, ptr %t7 + %t205 = add i32 %t204, 2 + store i32 %t205, ptr %t7 + br label %ifend46 +else45: + %t206 = load ptr, ptr %t0 + %t207 = load i32, ptr %t7 + %t208 = getelementptr inbounds i8, ptr %t206, i32 %t207 + %t209 = load i8, ptr %t208 + %t210 = zext i8 %t209 to i32 + store i32 %t210, ptr %t176 + %t211 = load i32, ptr %t7 + %t212 = add i32 %t211, 1 + store i32 %t212, ptr %t7 + br label %ifend46 +ifend46: + %t213 = load ptr, ptr %t0 + %t214 = load i32, ptr %t7 + %t215 = getelementptr inbounds i8, ptr %t213, i32 %t214 + %t216 = load i8, ptr %t215 + %t217 = zext i8 %t216 to i32 + %t218 = icmp eq i32 %t217, 39 + %t219 = zext i1 %t218 to i32 + %t220 = icmp ne i32 %t219, 0 + br i1 %t220, label %then56, label %ifend58 +then56: + %t221 = load i32, ptr %t7 + %t222 = add i32 %t221, 1 + store i32 %t222, ptr %t7 + br label %ifend58 +ifend58: + %t223 = load i32, ptr %t176 + %t224 = load i32, ptr %t8 + call void @fn_tok_push(i32 1, ptr null, i32 %t223, i32 %t224) + br label %wcond0 +ifend43: + %t225 = load i32, ptr %t22 + %t226 = call i32 @fn_char_is_digit(i32 %t225) + %t227 = icmp ne i32 %t226, 0 + br i1 %t227, label %then59, label %ifend61 +then59: + %t229 = load i32, ptr %t22 + %t230 = icmp eq i32 %t229, 48 + %t231 = zext i1 %t230 to i32 + %t232 = icmp ne i32 %t231, 0 + %t233 = zext i1 %t232 to i32 + store i32 %t233, ptr %t228 + br i1 %t232, label %sc62, label %scend63 +sc62: + %t234 = load ptr, ptr %t0 + %t235 = load i32, ptr %t7 + %t236 = add i32 %t235, 1 + %t237 = getelementptr inbounds i8, ptr %t234, i32 %t236 + %t238 = load i8, ptr %t237 + %t239 = zext i8 %t238 to i32 + %t240 = icmp eq i32 %t239, 120 + %t241 = zext i1 %t240 to i32 + %t242 = icmp ne i32 %t241, 0 + %t243 = zext i1 %t242 to i32 + store i32 %t243, ptr %t228 + br label %scend63 +scend63: + %t244 = load i32, ptr %t228 + %t245 = icmp ne i32 %t244, 0 + br i1 %t245, label %then64, label %ifend66 +then64: + store i32 0, ptr %t246 + %t247 = load i32, ptr %t7 + %t248 = add i32 %t247, 2 + store i32 %t248, ptr %t7 + br label %wcond67 +wcond67: + %t249 = load i32, ptr %t7 + %t250 = load i32, ptr %t11 + %t251 = icmp slt i32 %t249, %t250 + %t252 = zext i1 %t251 to i32 + %t253 = icmp ne i32 %t252, 0 + br i1 %t253, label %wbody68, label %wend69 +wbody68: + %t254 = load ptr, ptr %t0 + %t255 = load i32, ptr %t7 + %t256 = getelementptr inbounds i8, ptr %t254, i32 %t255 + %t257 = load i8, ptr %t256 + %t258 = zext i8 %t257 to i32 + store i32 %t258, ptr %t259 + store i32 0, ptr %t260 + %t261 = load i32, ptr %t259 + %t262 = call i32 @fn_char_is_digit(i32 %t261) + %t263 = icmp ne i32 %t262, 0 + br i1 %t263, label %then70, label %else71 +then70: + %t264 = load i32, ptr %t259 + %t265 = sub i32 %t264, 48 + store i32 %t265, ptr %t260 + br label %ifend72 +else71: + %t267 = load i32, ptr %t259 + %t268 = icmp sge i32 %t267, 97 + %t269 = zext i1 %t268 to i32 + %t270 = icmp ne i32 %t269, 0 + %t271 = zext i1 %t270 to i32 + store i32 %t271, ptr %t266 + br i1 %t270, label %sc73, label %scend74 +sc73: + %t272 = load i32, ptr %t259 + %t273 = icmp sle i32 %t272, 102 + %t274 = zext i1 %t273 to i32 + %t275 = icmp ne i32 %t274, 0 + %t276 = zext i1 %t275 to i32 + store i32 %t276, ptr %t266 + br label %scend74 +scend74: + %t277 = load i32, ptr %t266 + %t278 = icmp ne i32 %t277, 0 + br i1 %t278, label %then75, label %else76 +then75: + %t279 = load i32, ptr %t259 + %t280 = sub i32 %t279, 87 + store i32 %t280, ptr %t260 + br label %ifend77 +else76: + %t282 = load i32, ptr %t259 + %t283 = icmp sge i32 %t282, 65 + %t284 = zext i1 %t283 to i32 + %t285 = icmp ne i32 %t284, 0 + %t286 = zext i1 %t285 to i32 + store i32 %t286, ptr %t281 + br i1 %t285, label %sc78, label %scend79 +sc78: + %t287 = load i32, ptr %t259 + %t288 = icmp sle i32 %t287, 70 + %t289 = zext i1 %t288 to i32 + %t290 = icmp ne i32 %t289, 0 + %t291 = zext i1 %t290 to i32 + store i32 %t291, ptr %t281 + br label %scend79 +scend79: + %t292 = load i32, ptr %t281 + %t293 = icmp ne i32 %t292, 0 + br i1 %t293, label %then80, label %else81 +then80: + %t294 = load i32, ptr %t259 + %t295 = sub i32 %t294, 55 + store i32 %t295, ptr %t260 + br label %ifend82 +else81: + br label %wend69 +ifend82: + br label %ifend77 +ifend77: + br label %ifend72 +ifend72: + %t296 = load i32, ptr %t246 + %t297 = mul i32 %t296, 16 + %t298 = load i32, ptr %t260 + %t299 = add i32 %t297, %t298 + store i32 %t299, ptr %t246 + %t300 = load i32, ptr %t7 + %t301 = add i32 %t300, 1 + store i32 %t301, ptr %t7 + br label %wcond67 +wend69: + %t302 = load i32, ptr %t246 + %t303 = load i32, ptr %t8 + call void @fn_tok_push(i32 1, ptr null, i32 %t302, i32 %t303) + br label %wcond0 +ifend66: + store i32 0, ptr %t304 + br label %wcond83 +wcond83: + %t306 = load i32, ptr %t7 + %t307 = load i32, ptr %t11 + %t308 = icmp slt i32 %t306, %t307 + %t309 = zext i1 %t308 to i32 + %t310 = icmp ne i32 %t309, 0 + %t311 = zext i1 %t310 to i32 + store i32 %t311, ptr %t305 + br i1 %t310, label %sc86, label %scend87 +sc86: + %t312 = load ptr, ptr %t0 + %t313 = load i32, ptr %t7 + %t314 = getelementptr inbounds i8, ptr %t312, i32 %t313 + %t315 = load i8, ptr %t314 + %t316 = zext i8 %t315 to i32 + %t317 = call i32 @fn_char_is_digit(i32 %t316) + %t318 = icmp ne i32 %t317, 0 + %t319 = zext i1 %t318 to i32 + store i32 %t319, ptr %t305 + br label %scend87 +scend87: + %t320 = load i32, ptr %t305 + %t321 = icmp ne i32 %t320, 0 + br i1 %t321, label %wbody84, label %wend85 +wbody84: + %t322 = load i32, ptr %t304 + %t323 = mul i32 %t322, 10 + %t324 = load ptr, ptr %t0 + %t325 = load i32, ptr %t7 + %t326 = getelementptr inbounds i8, ptr %t324, i32 %t325 + %t327 = load i8, ptr %t326 + %t328 = zext i8 %t327 to i32 + %t329 = sub i32 %t328, 48 + %t330 = add i32 %t323, %t329 + store i32 %t330, ptr %t304 + %t331 = load i32, ptr %t7 + %t332 = add i32 %t331, 1 + store i32 %t332, ptr %t7 + br label %wcond83 +wend85: + %t335 = load i32, ptr %t7 + %t336 = load i32, ptr %t11 + %t337 = icmp slt i32 %t335, %t336 + %t338 = zext i1 %t337 to i32 + %t339 = icmp ne i32 %t338, 0 + %t340 = zext i1 %t339 to i32 + store i32 %t340, ptr %t334 + br i1 %t339, label %sc88, label %scend89 +sc88: + %t341 = load ptr, ptr %t0 + %t342 = load i32, ptr %t7 + %t343 = getelementptr inbounds i8, ptr %t341, i32 %t342 + %t344 = load i8, ptr %t343 + %t345 = zext i8 %t344 to i32 + %t346 = icmp eq i32 %t345, 46 + %t347 = zext i1 %t346 to i32 + %t348 = icmp ne i32 %t347, 0 + %t349 = zext i1 %t348 to i32 + store i32 %t349, ptr %t334 + br label %scend89 +scend89: + %t350 = load i32, ptr %t334 + %t351 = icmp ne i32 %t350, 0 + %t352 = zext i1 %t351 to i32 + store i32 %t352, ptr %t333 + br i1 %t351, label %sc90, label %scend91 +sc90: + %t353 = load ptr, ptr %t0 + %t354 = load i32, ptr %t7 + %t355 = add i32 %t354, 1 + %t356 = getelementptr inbounds i8, ptr %t353, i32 %t355 + %t357 = load i8, ptr %t356 + %t358 = zext i8 %t357 to i32 + %t359 = call i32 @fn_char_is_digit(i32 %t358) + %t360 = icmp ne i32 %t359, 0 + %t361 = zext i1 %t360 to i32 + store i32 %t361, ptr %t333 + br label %scend91 +scend91: + %t362 = load i32, ptr %t333 + %t363 = icmp ne i32 %t362, 0 + br i1 %t363, label %then92, label %ifend94 +then92: + %t364 = load i32, ptr %t7 + %t365 = add i32 %t364, 1 + store i32 %t365, ptr %t7 + store i32 0, ptr %t366 + store i32 1, ptr %t367 + br label %wcond95 +wcond95: + %t369 = load i32, ptr %t7 + %t370 = load i32, ptr %t11 + %t371 = icmp slt i32 %t369, %t370 + %t372 = zext i1 %t371 to i32 + %t373 = icmp ne i32 %t372, 0 + %t374 = zext i1 %t373 to i32 + store i32 %t374, ptr %t368 + br i1 %t373, label %sc98, label %scend99 +sc98: + %t375 = load ptr, ptr %t0 + %t376 = load i32, ptr %t7 + %t377 = getelementptr inbounds i8, ptr %t375, i32 %t376 + %t378 = load i8, ptr %t377 + %t379 = zext i8 %t378 to i32 + %t380 = call i32 @fn_char_is_digit(i32 %t379) + %t381 = icmp ne i32 %t380, 0 + %t382 = zext i1 %t381 to i32 + store i32 %t382, ptr %t368 + br label %scend99 +scend99: + %t383 = load i32, ptr %t368 + %t384 = icmp ne i32 %t383, 0 + br i1 %t384, label %wbody96, label %wend97 +wbody96: + %t385 = load i32, ptr %t366 + %t386 = mul i32 %t385, 10 + %t387 = load ptr, ptr %t0 + %t388 = load i32, ptr %t7 + %t389 = getelementptr inbounds i8, ptr %t387, i32 %t388 + %t390 = load i8, ptr %t389 + %t391 = zext i8 %t390 to i32 + %t392 = sub i32 %t391, 48 + %t393 = add i32 %t386, %t392 + store i32 %t393, ptr %t366 + %t394 = load i32, ptr %t367 + %t395 = mul i32 %t394, 10 + store i32 %t395, ptr %t367 + %t396 = load i32, ptr %t7 + %t397 = add i32 %t396, 1 + store i32 %t397, ptr %t7 + br label %wcond95 +wend97: + %t398 = load i32, ptr %t304 + %t399 = shl i32 %t398, 16 + %t400 = load i32, ptr %t366 + %t401 = shl i32 %t400, 16 + %t402 = load i32, ptr %t367 + %t403 = sdiv i32 %t401, %t402 + %t404 = add i32 %t399, %t403 + store i32 %t404, ptr %t405 + %t406 = load i32, ptr %t405 + %t407 = load i32, ptr %t8 + call void @fn_tok_push(i32 6, ptr null, i32 %t406, i32 %t407) + br label %wcond0 +ifend94: + %t408 = load i32, ptr %t304 + %t409 = load i32, ptr %t8 + call void @fn_tok_push(i32 1, ptr null, i32 %t408, i32 %t409) + br label %wcond0 +ifend61: + %t410 = load i32, ptr %t22 + %t411 = call i32 @fn_char_is_alpha(i32 %t410) + %t412 = icmp ne i32 %t411, 0 + br i1 %t412, label %then100, label %ifend102 +then100: + %t413 = load i32, ptr %t7 + store i32 %t413, ptr %t414 + br label %wcond103 +wcond103: + %t416 = load i32, ptr %t7 + %t417 = load i32, ptr %t11 + %t418 = icmp slt i32 %t416, %t417 + %t419 = zext i1 %t418 to i32 + %t420 = icmp ne i32 %t419, 0 + %t421 = zext i1 %t420 to i32 + store i32 %t421, ptr %t415 + br i1 %t420, label %sc106, label %scend107 +sc106: + %t422 = load ptr, ptr %t0 + %t423 = load i32, ptr %t7 + %t424 = getelementptr inbounds i8, ptr %t422, i32 %t423 + %t425 = load i8, ptr %t424 + %t426 = zext i8 %t425 to i32 + %t427 = call i32 @fn_char_is_alnum(i32 %t426) + %t428 = icmp ne i32 %t427, 0 + %t429 = zext i1 %t428 to i32 + store i32 %t429, ptr %t415 + br label %scend107 +scend107: + %t430 = load i32, ptr %t415 + %t431 = icmp ne i32 %t430, 0 + br i1 %t431, label %wbody104, label %wend105 +wbody104: + %t432 = load i32, ptr %t7 + %t433 = add i32 %t432, 1 + store i32 %t433, ptr %t7 + br label %wcond103 +wend105: + %t434 = load ptr, ptr %t0 + %t435 = load i32, ptr %t414 + %t436 = load i32, ptr %t7 + %t437 = load i32, ptr %t414 + %t438 = sub i32 %t436, %t437 + %t439 = call ptr @fn_substr(ptr %t434, i32 %t435, i32 %t438) + %t440 = load i32, ptr %t8 + call void @fn_tok_push(i32 0, ptr %t439, i32 0, i32 %t440) + br label %wcond0 +ifend102: + %t441 = load i32, ptr %t22 + %t442 = icmp eq i32 %t441, 59 + %t443 = zext i1 %t442 to i32 + %t444 = icmp ne i32 %t443, 0 + br i1 %t444, label %then108, label %ifend110 +then108: + %t445 = load i32, ptr %t8 + call void @fn_tok_push(i32 4, ptr null, i32 0, i32 %t445) + %t446 = load i32, ptr %t7 + %t447 = add i32 %t446, 1 + store i32 %t447, ptr %t7 + br label %wcond0 +ifend110: + %t448 = load ptr, ptr %t0 + %t449 = load i32, ptr %t7 + %t450 = call i32 @fn_two_at(ptr %t448, i32 %t449, i32 45, i32 62) + %t451 = icmp ne i32 %t450, 0 + br i1 %t451, label %then111, label %ifend113 +then111: + %t452 = load ptr, ptr %t0 + %t453 = load i32, ptr %t7 + %t454 = call ptr @fn_substr(ptr %t452, i32 %t453, i32 2) + %t455 = load i32, ptr %t8 + call void @fn_tok_push(i32 3, ptr %t454, i32 0, i32 %t455) + %t456 = load i32, ptr %t7 + %t457 = add i32 %t456, 2 + store i32 %t457, ptr %t7 + br label %wcond0 +ifend113: + %t458 = load ptr, ptr %t0 + %t459 = load i32, ptr %t7 + %t460 = call i32 @fn_two_at(ptr %t458, i32 %t459, i32 61, i32 62) + %t461 = icmp ne i32 %t460, 0 + br i1 %t461, label %then114, label %ifend116 +then114: + %t462 = load ptr, ptr %t0 + %t463 = load i32, ptr %t7 + %t464 = call ptr @fn_substr(ptr %t462, i32 %t463, i32 2) + %t465 = load i32, ptr %t8 + call void @fn_tok_push(i32 3, ptr %t464, i32 0, i32 %t465) + %t466 = load i32, ptr %t7 + %t467 = add i32 %t466, 2 + store i32 %t467, ptr %t7 + br label %wcond0 +ifend116: + %t468 = load ptr, ptr %t0 + %t469 = load i32, ptr %t7 + %t470 = call i32 @fn_two_at(ptr %t468, i32 %t469, i32 61, i32 61) + %t471 = icmp ne i32 %t470, 0 + br i1 %t471, label %then117, label %ifend119 +then117: + %t472 = load ptr, ptr %t0 + %t473 = load i32, ptr %t7 + %t474 = call ptr @fn_substr(ptr %t472, i32 %t473, i32 2) + %t475 = load i32, ptr %t8 + call void @fn_tok_push(i32 3, ptr %t474, i32 0, i32 %t475) + %t476 = load i32, ptr %t7 + %t477 = add i32 %t476, 2 + store i32 %t477, ptr %t7 + br label %wcond0 +ifend119: + %t478 = load ptr, ptr %t0 + %t479 = load i32, ptr %t7 + %t480 = call i32 @fn_two_at(ptr %t478, i32 %t479, i32 33, i32 61) + %t481 = icmp ne i32 %t480, 0 + br i1 %t481, label %then120, label %ifend122 +then120: + %t482 = load ptr, ptr %t0 + %t483 = load i32, ptr %t7 + %t484 = call ptr @fn_substr(ptr %t482, i32 %t483, i32 2) + %t485 = load i32, ptr %t8 + call void @fn_tok_push(i32 3, ptr %t484, i32 0, i32 %t485) + %t486 = load i32, ptr %t7 + %t487 = add i32 %t486, 2 + store i32 %t487, ptr %t7 + br label %wcond0 +ifend122: + %t488 = load ptr, ptr %t0 + %t489 = load i32, ptr %t7 + %t490 = call i32 @fn_two_at(ptr %t488, i32 %t489, i32 60, i32 61) + %t491 = icmp ne i32 %t490, 0 + br i1 %t491, label %then123, label %ifend125 +then123: + %t492 = load ptr, ptr %t0 + %t493 = load i32, ptr %t7 + %t494 = call ptr @fn_substr(ptr %t492, i32 %t493, i32 2) + %t495 = load i32, ptr %t8 + call void @fn_tok_push(i32 3, ptr %t494, i32 0, i32 %t495) + %t496 = load i32, ptr %t7 + %t497 = add i32 %t496, 2 + store i32 %t497, ptr %t7 + br label %wcond0 +ifend125: + %t498 = load ptr, ptr %t0 + %t499 = load i32, ptr %t7 + %t500 = call i32 @fn_two_at(ptr %t498, i32 %t499, i32 62, i32 61) + %t501 = icmp ne i32 %t500, 0 + br i1 %t501, label %then126, label %ifend128 +then126: + %t502 = load ptr, ptr %t0 + %t503 = load i32, ptr %t7 + %t504 = call ptr @fn_substr(ptr %t502, i32 %t503, i32 2) + %t505 = load i32, ptr %t8 + call void @fn_tok_push(i32 3, ptr %t504, i32 0, i32 %t505) + %t506 = load i32, ptr %t7 + %t507 = add i32 %t506, 2 + store i32 %t507, ptr %t7 + br label %wcond0 +ifend128: + %t508 = load ptr, ptr %t0 + %t509 = load i32, ptr %t7 + %t510 = call i32 @fn_two_at(ptr %t508, i32 %t509, i32 43, i32 61) + %t511 = icmp ne i32 %t510, 0 + br i1 %t511, label %then129, label %ifend131 +then129: + %t512 = load ptr, ptr %t0 + %t513 = load i32, ptr %t7 + %t514 = call ptr @fn_substr(ptr %t512, i32 %t513, i32 2) + %t515 = load i32, ptr %t8 + call void @fn_tok_push(i32 3, ptr %t514, i32 0, i32 %t515) + %t516 = load i32, ptr %t7 + %t517 = add i32 %t516, 2 + store i32 %t517, ptr %t7 + br label %wcond0 +ifend131: + %t518 = load ptr, ptr %t0 + %t519 = load i32, ptr %t7 + %t520 = call i32 @fn_two_at(ptr %t518, i32 %t519, i32 45, i32 61) + %t521 = icmp ne i32 %t520, 0 + br i1 %t521, label %then132, label %ifend134 +then132: + %t522 = load ptr, ptr %t0 + %t523 = load i32, ptr %t7 + %t524 = call ptr @fn_substr(ptr %t522, i32 %t523, i32 2) + %t525 = load i32, ptr %t8 + call void @fn_tok_push(i32 3, ptr %t524, i32 0, i32 %t525) + %t526 = load i32, ptr %t7 + %t527 = add i32 %t526, 2 + store i32 %t527, ptr %t7 + br label %wcond0 +ifend134: + %t528 = load ptr, ptr %t0 + %t529 = load i32, ptr %t7 + %t530 = call i32 @fn_two_at(ptr %t528, i32 %t529, i32 42, i32 61) + %t531 = icmp ne i32 %t530, 0 + br i1 %t531, label %then135, label %ifend137 +then135: + %t532 = load ptr, ptr %t0 + %t533 = load i32, ptr %t7 + %t534 = call ptr @fn_substr(ptr %t532, i32 %t533, i32 2) + %t535 = load i32, ptr %t8 + call void @fn_tok_push(i32 3, ptr %t534, i32 0, i32 %t535) + %t536 = load i32, ptr %t7 + %t537 = add i32 %t536, 2 + store i32 %t537, ptr %t7 + br label %wcond0 +ifend137: + %t538 = load ptr, ptr %t0 + %t539 = load i32, ptr %t7 + %t540 = call i32 @fn_two_at(ptr %t538, i32 %t539, i32 47, i32 61) + %t541 = icmp ne i32 %t540, 0 + br i1 %t541, label %then138, label %ifend140 +then138: + %t542 = load ptr, ptr %t0 + %t543 = load i32, ptr %t7 + %t544 = call ptr @fn_substr(ptr %t542, i32 %t543, i32 2) + %t545 = load i32, ptr %t8 + call void @fn_tok_push(i32 3, ptr %t544, i32 0, i32 %t545) + %t546 = load i32, ptr %t7 + %t547 = add i32 %t546, 2 + store i32 %t547, ptr %t7 + br label %wcond0 +ifend140: + %t548 = load ptr, ptr %t0 + %t549 = load i32, ptr %t7 + %t550 = call i32 @fn_two_at(ptr %t548, i32 %t549, i32 46, i32 46) + %t551 = icmp ne i32 %t550, 0 + br i1 %t551, label %then141, label %ifend143 +then141: + %t552 = load ptr, ptr %t0 + %t553 = load i32, ptr %t7 + %t554 = call ptr @fn_substr(ptr %t552, i32 %t553, i32 2) + %t555 = load i32, ptr %t8 + call void @fn_tok_push(i32 3, ptr %t554, i32 0, i32 %t555) + %t556 = load i32, ptr %t7 + %t557 = add i32 %t556, 2 + store i32 %t557, ptr %t7 + br label %wcond0 +ifend143: + %t558 = load i32, ptr %t22 + %t559 = call i32 @fn_is_op1(i32 %t558) + %t560 = icmp ne i32 %t559, 0 + br i1 %t560, label %then144, label %ifend146 +then144: + %t561 = load ptr, ptr %t0 + %t562 = load i32, ptr %t7 + %t563 = call ptr @fn_substr(ptr %t561, i32 %t562, i32 1) + %t564 = load i32, ptr %t8 + call void @fn_tok_push(i32 3, ptr %t563, i32 0, i32 %t564) + %t565 = load i32, ptr %t7 + %t566 = add i32 %t565, 1 + store i32 %t566, ptr %t7 + br label %wcond0 +ifend146: + %t567 = load i32, ptr %t7 + %t568 = add i32 %t567, 1 + store i32 %t568, ptr %t7 + br label %wcond0 +wend2: + %t569 = load i32, ptr %t8 + call void @fn_tok_push(i32 5, ptr null, i32 0, i32 %t569) + br label %ret +ret: + ret void +} + +define ptr @fn_cur() { +entry: + %retval = alloca ptr + %t0 = load ptr, ptr @g_toks + %t1 = getelementptr inbounds %LSlice, ptr %t0, i32 0, i32 0 + %t2 = load ptr, ptr %t1 + %t3 = load i32, ptr @g_pi + %t4 = getelementptr inbounds ptr, ptr %t2, i32 %t3 + %t5 = load ptr, ptr %t4 + store ptr %t5, ptr %retval + br label %ret +ret: + %t6 = load ptr, ptr %retval + ret ptr %t6 +} + +define ptr @fn_pk(i32 %arg_o) { +entry: + %retval = alloca ptr + %t0 = alloca i32 + store i32 %arg_o, ptr %t0 + %t1 = load ptr, ptr @g_toks + %t2 = getelementptr inbounds %LSlice, ptr %t1, i32 0, i32 0 + %t3 = load ptr, ptr %t2 + %t4 = load i32, ptr @g_pi + %t5 = load i32, ptr %t0 + %t6 = add i32 %t4, %t5 + %t7 = getelementptr inbounds ptr, ptr %t3, i32 %t6 + %t8 = load ptr, ptr %t7 + store ptr %t8, ptr %retval + br label %ret +ret: + %t9 = load ptr, ptr %retval + ret ptr %t9 +} + +define i32 @fn_is_op(ptr %arg_v) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t7 = alloca ptr + %t8 = alloca i32 + store ptr %arg_v, ptr %t0 + %t1 = load ptr, ptr @g_toks + %t2 = getelementptr inbounds %LSlice, ptr %t1, i32 0, i32 0 + %t3 = load ptr, ptr %t2 + %t4 = load i32, ptr @g_pi + %t5 = getelementptr inbounds ptr, ptr %t3, i32 %t4 + %t6 = load ptr, ptr %t5 + store ptr %t6, ptr %t7 + %t9 = load ptr, ptr %t7 + %t10 = getelementptr inbounds %Str_Tok, ptr %t9, i32 0, i32 0 + %t11 = load i32, ptr %t10 + %t12 = icmp eq i32 %t11, 3 + %t13 = zext i1 %t12 to i32 + %t14 = icmp ne i32 %t13, 0 + %t15 = zext i1 %t14 to i32 + store i32 %t15, ptr %t8 + br i1 %t14, label %sc0, label %scend1 +sc0: + %t16 = load ptr, ptr %t7 + %t17 = getelementptr inbounds %Str_Tok, ptr %t16, i32 0, i32 1 + %t18 = load ptr, ptr %t17 + %t19 = load ptr, ptr %t0 + %t20 = call i32 @fn_streq(ptr %t18, ptr %t19) + %t21 = icmp ne i32 %t20, 0 + %t22 = zext i1 %t21 to i32 + store i32 %t22, ptr %t8 + br label %scend1 +scend1: + %t23 = load i32, ptr %t8 + store i32 %t23, ptr %retval + br label %ret +ret: + %t24 = load i32, ptr %retval + ret i32 %t24 +} + +define i32 @fn_is_id(ptr %arg_v) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t7 = alloca ptr + %t8 = alloca i32 + store ptr %arg_v, ptr %t0 + %t1 = load ptr, ptr @g_toks + %t2 = getelementptr inbounds %LSlice, ptr %t1, i32 0, i32 0 + %t3 = load ptr, ptr %t2 + %t4 = load i32, ptr @g_pi + %t5 = getelementptr inbounds ptr, ptr %t3, i32 %t4 + %t6 = load ptr, ptr %t5 + store ptr %t6, ptr %t7 + %t9 = load ptr, ptr %t7 + %t10 = getelementptr inbounds %Str_Tok, ptr %t9, i32 0, i32 0 + %t11 = load i32, ptr %t10 + %t12 = icmp eq i32 %t11, 0 + %t13 = zext i1 %t12 to i32 + %t14 = icmp ne i32 %t13, 0 + %t15 = zext i1 %t14 to i32 + store i32 %t15, ptr %t8 + br i1 %t14, label %sc0, label %scend1 +sc0: + %t16 = load ptr, ptr %t7 + %t17 = getelementptr inbounds %Str_Tok, ptr %t16, i32 0, i32 1 + %t18 = load ptr, ptr %t17 + %t19 = load ptr, ptr %t0 + %t20 = call i32 @fn_streq(ptr %t18, ptr %t19) + %t21 = icmp ne i32 %t20, 0 + %t22 = zext i1 %t21 to i32 + store i32 %t22, ptr %t8 + br label %scend1 +scend1: + %t23 = load i32, ptr %t8 + store i32 %t23, ptr %retval + br label %ret +ret: + %t24 = load i32, ptr %retval + ret i32 %t24 +} + +define i32 @fn_is_kw(ptr %arg_v) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + store ptr %arg_v, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = call i32 @fn_is_id(ptr %t1) + store i32 %t2, ptr %retval + br label %ret +ret: + %t3 = load i32, ptr %retval + ret i32 %t3 +} + +define void @fn_perr(ptr %arg_msg) { +entry: + %t0 = alloca ptr + %t2 = alloca ptr + store ptr %arg_msg, ptr %t0 + %t1 = load ptr, ptr @__stderrp + store ptr %t1, ptr %t2 + %t3 = load ptr, ptr %t2 + %t4 = zext i32 27 to i64 + %t5 = call i64 @fwrite(ptr @.str1, i64 1, i64 %t4, ptr %t3) + %t6 = trunc i64 %t5 to i32 + %t7 = load ptr, ptr %t2 + %t8 = load ptr, ptr %t0 + %t9 = load ptr, ptr %t0 + %t10 = call i32 @fn_slen(ptr %t9) + %t11 = zext i32 %t10 to i64 + %t12 = call i64 @fwrite(ptr %t8, i64 1, i64 %t11, ptr %t7) + %t13 = trunc i64 %t12 to i32 + %t14 = load ptr, ptr %t2 + %t15 = zext i32 1 to i64 + %t16 = call i64 @fwrite(ptr @.str2, i64 1, i64 %t15, ptr %t14) + %t17 = trunc i64 %t16 to i32 + call void @exit(i32 1) + unreachable +ret: + ret void +} + +define void @fn_eat_op(ptr %arg_v) { +entry: + %t0 = alloca ptr + store ptr %arg_v, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = call i32 @fn_is_op(ptr %t1) + %t3 = icmp eq i32 %t2, 0 + %t4 = zext i1 %t3 to i32 + %t5 = icmp ne i32 %t4, 0 + br i1 %t5, label %then0, label %ifend2 +then0: + %t6 = load ptr, ptr %t0 + call void @fn_perr(ptr %t6) + br label %ifend2 +ifend2: + %t7 = load i32, ptr @g_pi + %t8 = add i32 %t7, 1 + store i32 %t8, ptr @g_pi + br label %ret +ret: + ret void +} + +define ptr @fn_eat_id() { +entry: + %retval = alloca ptr + %t6 = alloca ptr + %t0 = load ptr, ptr @g_toks + %t1 = getelementptr inbounds %LSlice, ptr %t0, i32 0, i32 0 + %t2 = load ptr, ptr %t1 + %t3 = load i32, ptr @g_pi + %t4 = getelementptr inbounds ptr, ptr %t2, i32 %t3 + %t5 = load ptr, ptr %t4 + store ptr %t5, ptr %t6 + %t7 = load ptr, ptr %t6 + %t8 = getelementptr inbounds %Str_Tok, ptr %t7, i32 0, i32 0 + %t9 = load i32, ptr %t8 + %t10 = icmp ne i32 %t9, 0 + %t11 = zext i1 %t10 to i32 + %t12 = icmp ne i32 %t11, 0 + br i1 %t12, label %then0, label %ifend2 +then0: + call void @fn_perr(ptr @.str3) + br label %ifend2 +ifend2: + %t13 = load i32, ptr @g_pi + %t14 = add i32 %t13, 1 + store i32 %t14, ptr @g_pi + %t15 = load ptr, ptr %t6 + %t16 = getelementptr inbounds %Str_Tok, ptr %t15, i32 0, i32 1 + %t17 = load ptr, ptr %t16 + store ptr %t17, ptr %retval + br label %ret +ret: + %t18 = load ptr, ptr %retval + ret ptr %t18 +} + +define void @fn_skipnl() { +entry: + br label %wcond0 +wcond0: + %t0 = load ptr, ptr @g_toks + %t1 = getelementptr inbounds %LSlice, ptr %t0, i32 0, i32 0 + %t2 = load ptr, ptr %t1 + %t3 = load i32, ptr @g_pi + %t4 = getelementptr inbounds ptr, ptr %t2, i32 %t3 + %t5 = load ptr, ptr %t4 + %t6 = getelementptr inbounds %Str_Tok, ptr %t5, i32 0, i32 0 + %t7 = load i32, ptr %t6 + %t8 = icmp eq i32 %t7, 4 + %t9 = zext i1 %t8 to i32 + %t10 = icmp ne i32 %t9, 0 + br i1 %t10, label %wbody1, label %wend2 +wbody1: + %t11 = load i32, ptr @g_pi + %t12 = add i32 %t11, 1 + store i32 %t12, ptr @g_pi + br label %wcond0 +wend2: + br label %ret +ret: + ret void +} + +define ptr @fn_ptype() { +entry: + %retval = alloca ptr + %t5 = alloca ptr + %t11 = alloca ptr + %t18 = alloca i32 + %t0 = call i32 @fn_is_op(ptr @.str4) + %t1 = icmp ne i32 %t0, 0 + br i1 %t1, label %then0, label %ifend2 +then0: + %t2 = load i32, ptr @g_pi + %t3 = add i32 %t2, 1 + store i32 %t3, ptr @g_pi + call void @fn_eat_op(ptr @.str5) + %t4 = call ptr @fn_ptype() + store ptr %t4, ptr %t5 + %t6 = load ptr, ptr %t5 + %t7 = call i32 @fn_slen(ptr %t6) + %t8 = add i32 %t7, 3 + %t9 = zext i32 %t8 to i64 + %t10 = call ptr @malloc(i64 %t9) + store ptr %t10, ptr %t11 + %t12 = load ptr, ptr %t11 + %t13 = getelementptr inbounds i8, ptr %t12, i32 0 + %t14 = trunc i32 91 to i8 + store i8 %t14, ptr %t13 + %t15 = load ptr, ptr %t11 + %t16 = getelementptr inbounds i8, ptr %t15, i32 1 + %t17 = trunc i32 93 to i8 + store i8 %t17, ptr %t16 + store i32 0, ptr %t18 + br label %wcond3 +wcond3: + %t19 = load ptr, ptr %t5 + %t20 = load i32, ptr %t18 + %t21 = getelementptr inbounds i8, ptr %t19, i32 %t20 + %t22 = load i8, ptr %t21 + %t23 = zext i8 %t22 to i32 + %t24 = icmp ne i32 %t23, 0 + %t25 = zext i1 %t24 to i32 + %t26 = icmp ne i32 %t25, 0 + br i1 %t26, label %wbody4, label %wend5 +wbody4: + %t27 = load ptr, ptr %t11 + %t28 = load i32, ptr %t18 + %t29 = add i32 2, %t28 + %t30 = load ptr, ptr %t5 + %t31 = load i32, ptr %t18 + %t32 = getelementptr inbounds i8, ptr %t30, i32 %t31 + %t33 = load i8, ptr %t32 + %t34 = zext i8 %t33 to i32 + %t35 = getelementptr inbounds i8, ptr %t27, i32 %t29 + %t36 = trunc i32 %t34 to i8 + store i8 %t36, ptr %t35 + %t37 = load i32, ptr %t18 + %t38 = add i32 %t37, 1 + store i32 %t38, ptr %t18 + br label %wcond3 +wend5: + %t39 = load ptr, ptr %t11 + %t40 = load i32, ptr %t18 + %t41 = add i32 2, %t40 + %t42 = getelementptr inbounds i8, ptr %t39, i32 %t41 + %t43 = trunc i32 0 to i8 + store i8 %t43, ptr %t42 + %t44 = load ptr, ptr %t11 + store ptr %t44, ptr %retval + br label %ret +ifend2: + %t45 = call ptr @fn_eat_id() + store ptr %t45, ptr %retval + br label %ret +ret: + %t46 = load ptr, ptr %retval + ret ptr %t46 +} + +define ptr @fn_expr() { +entry: + %retval = alloca ptr + %t0 = call ptr @fn_p_or() + store ptr %t0, ptr %retval + br label %ret +ret: + %t1 = load ptr, ptr %retval + ret ptr %t1 +} + +define void @fn_args_call(ptr %arg_call) { +entry: + %t0 = alloca ptr + store ptr %arg_call, ptr %t0 + call void @fn_eat_op(ptr @.str6) + call void @fn_skipnl() + br label %wcond0 +wcond0: + %t1 = call i32 @fn_is_op(ptr @.str7) + %t2 = icmp eq i32 %t1, 0 + %t3 = zext i1 %t2 to i32 + %t4 = icmp ne i32 %t3, 0 + br i1 %t4, label %wbody1, label %wend2 +wbody1: + %t5 = load ptr, ptr %t0 + %t6 = getelementptr inbounds %Str_Node, ptr %t5, i32 0, i32 7 + %t7 = load ptr, ptr %t6 + %t8 = getelementptr inbounds %LSlice, ptr %t7, i32 0, i32 1 + %t9 = getelementptr inbounds %LSlice, ptr %t7, i32 0, i32 2 + %t10 = getelementptr inbounds %LSlice, ptr %t7, i32 0, i32 0 + %t11 = load i32, ptr %t8 + %t12 = load i32, ptr %t9 + %t13 = icmp sge i32 %t11, %t12 + br i1 %t13, label %grow3, label %put4 +grow3: + %t14 = mul i32 %t12, 2 + %t15 = icmp eq i32 %t12, 0 + %t16 = select i1 %t15, i32 8, i32 %t14 + %t17 = getelementptr ptr, ptr null, i32 1 + %t18 = ptrtoint ptr %t17 to i64 + %t19 = zext i32 %t16 to i64 + %t20 = mul i64 %t19, %t18 + %t21 = load ptr, ptr %t10 + %t22 = call ptr @realloc(ptr %t21, i64 %t20) + store ptr %t22, ptr %t10 + store i32 %t16, ptr %t9 + br label %put4 +put4: + %t23 = call ptr @fn_expr() + %t24 = load ptr, ptr %t10 + %t25 = getelementptr inbounds ptr, ptr %t24, i32 %t11 + store ptr %t23, ptr %t25 + %t26 = add i32 %t11, 1 + store i32 %t26, ptr %t8 + call void @fn_skipnl() + %t27 = call i32 @fn_is_op(ptr @.str8) + %t28 = icmp ne i32 %t27, 0 + br i1 %t28, label %then5, label %ifend7 +then5: + %t29 = load i32, ptr @g_pi + %t30 = add i32 %t29, 1 + store i32 %t30, ptr @g_pi + call void @fn_skipnl() + br label %ifend7 +ifend7: + br label %wcond0 +wend2: + call void @fn_eat_op(ptr @.str9) + br label %ret +ret: + ret void +} + +define ptr @fn_p_primary() { +entry: + %retval = alloca ptr + %t6 = alloca ptr + %t14 = alloca ptr + %t30 = alloca ptr + %t46 = alloca ptr + %t67 = alloca ptr + %t79 = alloca ptr + %t93 = alloca ptr + %t99 = alloca ptr + %t113 = alloca ptr + %t0 = load ptr, ptr @g_toks + %t1 = getelementptr inbounds %LSlice, ptr %t0, i32 0, i32 0 + %t2 = load ptr, ptr %t1 + %t3 = load i32, ptr @g_pi + %t4 = getelementptr inbounds ptr, ptr %t2, i32 %t3 + %t5 = load ptr, ptr %t4 + store ptr %t5, ptr %t6 + %t7 = load ptr, ptr %t6 + %t8 = getelementptr inbounds %Str_Tok, ptr %t7, i32 0, i32 0 + %t9 = load i32, ptr %t8 + %t10 = icmp eq i32 %t9, 1 + %t11 = zext i1 %t10 to i32 + %t12 = icmp ne i32 %t11, 0 + br i1 %t12, label %then0, label %ifend2 +then0: + %t13 = call ptr @fn_node(i32 30) + store ptr %t13, ptr %t14 + %t15 = load ptr, ptr %t14 + %t16 = getelementptr inbounds %Str_Node, ptr %t15, i32 0, i32 2 + %t17 = load ptr, ptr %t6 + %t18 = getelementptr inbounds %Str_Tok, ptr %t17, i32 0, i32 2 + %t19 = load i32, ptr %t18 + store i32 %t19, ptr %t16 + %t20 = load i32, ptr @g_pi + %t21 = add i32 %t20, 1 + store i32 %t21, ptr @g_pi + %t22 = load ptr, ptr %t14 + store ptr %t22, ptr %retval + br label %ret +ifend2: + %t23 = load ptr, ptr %t6 + %t24 = getelementptr inbounds %Str_Tok, ptr %t23, i32 0, i32 0 + %t25 = load i32, ptr %t24 + %t26 = icmp eq i32 %t25, 6 + %t27 = zext i1 %t26 to i32 + %t28 = icmp ne i32 %t27, 0 + br i1 %t28, label %then3, label %ifend5 +then3: + %t29 = call ptr @fn_node(i32 40) + store ptr %t29, ptr %t30 + %t31 = load ptr, ptr %t30 + %t32 = getelementptr inbounds %Str_Node, ptr %t31, i32 0, i32 2 + %t33 = load ptr, ptr %t6 + %t34 = getelementptr inbounds %Str_Tok, ptr %t33, i32 0, i32 2 + %t35 = load i32, ptr %t34 + store i32 %t35, ptr %t32 + %t36 = load i32, ptr @g_pi + %t37 = add i32 %t36, 1 + store i32 %t37, ptr @g_pi + %t38 = load ptr, ptr %t30 + store ptr %t38, ptr %retval + br label %ret +ifend5: + %t39 = load ptr, ptr %t6 + %t40 = getelementptr inbounds %Str_Tok, ptr %t39, i32 0, i32 0 + %t41 = load i32, ptr %t40 + %t42 = icmp eq i32 %t41, 2 + %t43 = zext i1 %t42 to i32 + %t44 = icmp ne i32 %t43, 0 + br i1 %t44, label %then6, label %ifend8 +then6: + %t45 = call ptr @fn_node(i32 31) + store ptr %t45, ptr %t46 + %t47 = load ptr, ptr %t46 + %t48 = getelementptr inbounds %Str_Node, ptr %t47, i32 0, i32 1 + %t49 = load ptr, ptr %t6 + %t50 = getelementptr inbounds %Str_Tok, ptr %t49, i32 0, i32 1 + %t51 = load ptr, ptr %t50 + store ptr %t51, ptr %t48 + %t52 = load i32, ptr @g_pi + %t53 = add i32 %t52, 1 + store i32 %t53, ptr @g_pi + %t54 = load ptr, ptr %t46 + store ptr %t54, ptr %retval + br label %ret +ifend8: + %t55 = load ptr, ptr %t6 + %t56 = getelementptr inbounds %Str_Tok, ptr %t55, i32 0, i32 0 + %t57 = load i32, ptr %t56 + %t58 = icmp eq i32 %t57, 0 + %t59 = zext i1 %t58 to i32 + %t60 = icmp ne i32 %t59, 0 + br i1 %t60, label %then9, label %ifend11 +then9: + %t61 = load ptr, ptr %t6 + %t62 = getelementptr inbounds %Str_Tok, ptr %t61, i32 0, i32 1 + %t63 = load ptr, ptr %t62 + %t64 = call i32 @fn_streq(ptr %t63, ptr @.str10) + %t65 = icmp ne i32 %t64, 0 + br i1 %t65, label %then12, label %ifend14 +then12: + %t66 = call ptr @fn_node(i32 32) + store ptr %t66, ptr %t67 + %t68 = load ptr, ptr %t67 + %t69 = getelementptr inbounds %Str_Node, ptr %t68, i32 0, i32 2 + store i32 1, ptr %t69 + %t70 = load i32, ptr @g_pi + %t71 = add i32 %t70, 1 + store i32 %t71, ptr @g_pi + %t72 = load ptr, ptr %t67 + store ptr %t72, ptr %retval + br label %ret +ifend14: + %t73 = load ptr, ptr %t6 + %t74 = getelementptr inbounds %Str_Tok, ptr %t73, i32 0, i32 1 + %t75 = load ptr, ptr %t74 + %t76 = call i32 @fn_streq(ptr %t75, ptr @.str11) + %t77 = icmp ne i32 %t76, 0 + br i1 %t77, label %then15, label %ifend17 +then15: + %t78 = call ptr @fn_node(i32 32) + store ptr %t78, ptr %t79 + %t80 = load ptr, ptr %t79 + %t81 = getelementptr inbounds %Str_Node, ptr %t80, i32 0, i32 2 + store i32 0, ptr %t81 + %t82 = load i32, ptr @g_pi + %t83 = add i32 %t82, 1 + store i32 %t83, ptr @g_pi + %t84 = load ptr, ptr %t79 + store ptr %t84, ptr %retval + br label %ret +ifend17: + %t85 = load ptr, ptr %t6 + %t86 = getelementptr inbounds %Str_Tok, ptr %t85, i32 0, i32 1 + %t87 = load ptr, ptr %t86 + %t88 = call i32 @fn_streq(ptr %t87, ptr @.str12) + %t89 = icmp ne i32 %t88, 0 + br i1 %t89, label %then18, label %ifend20 +then18: + %t90 = load i32, ptr @g_pi + %t91 = add i32 %t90, 1 + store i32 %t91, ptr @g_pi + %t92 = call ptr @fn_node(i32 39) + store ptr %t92, ptr %t93 + %t94 = load ptr, ptr %t93 + %t95 = getelementptr inbounds %Str_Node, ptr %t94, i32 0, i32 1 + %t96 = call ptr @fn_ptype() + store ptr %t96, ptr %t95 + %t97 = load ptr, ptr %t93 + store ptr %t97, ptr %retval + br label %ret +ifend20: + %t98 = call ptr @fn_node(i32 33) + store ptr %t98, ptr %t99 + %t100 = load ptr, ptr %t99 + %t101 = getelementptr inbounds %Str_Node, ptr %t100, i32 0, i32 1 + %t102 = load ptr, ptr %t6 + %t103 = getelementptr inbounds %Str_Tok, ptr %t102, i32 0, i32 1 + %t104 = load ptr, ptr %t103 + store ptr %t104, ptr %t101 + %t105 = load i32, ptr @g_pi + %t106 = add i32 %t105, 1 + store i32 %t106, ptr @g_pi + %t107 = load ptr, ptr %t99 + store ptr %t107, ptr %retval + br label %ret +ifend11: + %t108 = call i32 @fn_is_op(ptr @.str13) + %t109 = icmp ne i32 %t108, 0 + br i1 %t109, label %then21, label %ifend23 +then21: + %t110 = load i32, ptr @g_pi + %t111 = add i32 %t110, 1 + store i32 %t111, ptr @g_pi + call void @fn_skipnl() + %t112 = call ptr @fn_expr() + store ptr %t112, ptr %t113 + call void @fn_skipnl() + call void @fn_eat_op(ptr @.str14) + %t114 = load ptr, ptr %t113 + store ptr %t114, ptr %retval + br label %ret +ifend23: + call void @fn_perr(ptr @.str15) + %t115 = call ptr @fn_node(i32 30) + store ptr %t115, ptr %retval + br label %ret +ret: + %t116 = load ptr, ptr %retval + ret ptr %t116 +} + +define ptr @fn_p_postfix() { +entry: + %retval = alloca ptr + %t1 = alloca ptr + %t8 = alloca ptr + %t21 = alloca ptr + %t32 = alloca ptr + %t0 = call ptr @fn_p_primary() + store ptr %t0, ptr %t1 + br label %wcond0 +wcond0: + %t2 = icmp ne i32 1, 0 + br i1 %t2, label %wbody1, label %wend2 +wbody1: + %t3 = call i32 @fn_is_op(ptr @.str16) + %t4 = icmp ne i32 %t3, 0 + br i1 %t4, label %then3, label %else4 +then3: + %t5 = load i32, ptr @g_pi + %t6 = add i32 %t5, 1 + store i32 %t6, ptr @g_pi + %t7 = call ptr @fn_node(i32 35) + store ptr %t7, ptr %t8 + %t9 = load ptr, ptr %t8 + %t10 = getelementptr inbounds %Str_Node, ptr %t9, i32 0, i32 4 + %t11 = load ptr, ptr %t1 + store ptr %t11, ptr %t10 + %t12 = load ptr, ptr %t8 + %t13 = getelementptr inbounds %Str_Node, ptr %t12, i32 0, i32 1 + %t14 = call ptr @fn_eat_id() + store ptr %t14, ptr %t13 + %t15 = load ptr, ptr %t8 + store ptr %t15, ptr %t1 + br label %ifend5 +else4: + %t16 = call i32 @fn_is_op(ptr @.str17) + %t17 = icmp ne i32 %t16, 0 + br i1 %t17, label %then6, label %else7 +then6: + %t18 = load i32, ptr @g_pi + %t19 = add i32 %t18, 1 + store i32 %t19, ptr @g_pi + %t20 = call ptr @fn_node(i32 36) + store ptr %t20, ptr %t21 + %t22 = load ptr, ptr %t21 + %t23 = getelementptr inbounds %Str_Node, ptr %t22, i32 0, i32 4 + %t24 = load ptr, ptr %t1 + store ptr %t24, ptr %t23 + %t25 = load ptr, ptr %t21 + %t26 = getelementptr inbounds %Str_Node, ptr %t25, i32 0, i32 5 + %t27 = call ptr @fn_expr() + store ptr %t27, ptr %t26 + call void @fn_eat_op(ptr @.str18) + %t28 = load ptr, ptr %t21 + store ptr %t28, ptr %t1 + br label %ifend8 +else7: + %t29 = call i32 @fn_is_op(ptr @.str19) + %t30 = icmp ne i32 %t29, 0 + br i1 %t30, label %then9, label %else10 +then9: + %t31 = call ptr @fn_node(i32 34) + store ptr %t31, ptr %t32 + %t33 = load ptr, ptr %t32 + %t34 = getelementptr inbounds %Str_Node, ptr %t33, i32 0, i32 4 + %t35 = load ptr, ptr %t1 + store ptr %t35, ptr %t34 + %t36 = load ptr, ptr %t32 + call void @fn_args_call(ptr %t36) + %t37 = load ptr, ptr %t32 + store ptr %t37, ptr %t1 + br label %ifend11 +else10: + br label %wend2 +ifend11: + br label %ifend8 +ifend8: + br label %ifend5 +ifend5: + br label %wcond0 +wend2: + %t38 = load ptr, ptr %t1 + store ptr %t38, ptr %retval + br label %ret +ret: + %t39 = load ptr, ptr %retval + ret ptr %t39 +} + +define ptr @fn_p_unary() { +entry: + %retval = alloca ptr + %t5 = alloca ptr + %t17 = alloca ptr + %t0 = call i32 @fn_is_op(ptr @.str20) + %t1 = icmp ne i32 %t0, 0 + br i1 %t1, label %then0, label %ifend2 +then0: + %t2 = load i32, ptr @g_pi + %t3 = add i32 %t2, 1 + store i32 %t3, ptr @g_pi + %t4 = call ptr @fn_node(i32 38) + store ptr %t4, ptr %t5 + %t6 = load ptr, ptr %t5 + %t7 = getelementptr inbounds %Str_Node, ptr %t6, i32 0, i32 1 + store ptr @.str21, ptr %t7 + %t8 = load ptr, ptr %t5 + %t9 = getelementptr inbounds %Str_Node, ptr %t8, i32 0, i32 4 + %t10 = call ptr @fn_p_unary() + store ptr %t10, ptr %t9 + %t11 = load ptr, ptr %t5 + store ptr %t11, ptr %retval + br label %ret +ifend2: + %t12 = call i32 @fn_is_id(ptr @.str22) + %t13 = icmp ne i32 %t12, 0 + br i1 %t13, label %then3, label %ifend5 +then3: + %t14 = load i32, ptr @g_pi + %t15 = add i32 %t14, 1 + store i32 %t15, ptr @g_pi + %t16 = call ptr @fn_node(i32 38) + store ptr %t16, ptr %t17 + %t18 = load ptr, ptr %t17 + %t19 = getelementptr inbounds %Str_Node, ptr %t18, i32 0, i32 1 + store ptr @.str23, ptr %t19 + %t20 = load ptr, ptr %t17 + %t21 = getelementptr inbounds %Str_Node, ptr %t20, i32 0, i32 4 + %t22 = call ptr @fn_p_unary() + store ptr %t22, ptr %t21 + %t23 = load ptr, ptr %t17 + store ptr %t23, ptr %retval + br label %ret +ifend5: + %t24 = call ptr @fn_p_postfix() + store ptr %t24, ptr %retval + br label %ret +ret: + %t25 = load ptr, ptr %retval + ret ptr %t25 +} + +define ptr @fn_mkbin(ptr %arg_op, ptr %arg_l, ptr %arg_r) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca ptr + %t2 = alloca ptr + %t4 = alloca ptr + store ptr %arg_op, ptr %t0 + store ptr %arg_l, ptr %t1 + store ptr %arg_r, ptr %t2 + %t3 = call ptr @fn_node(i32 37) + store ptr %t3, ptr %t4 + %t5 = load ptr, ptr %t4 + %t6 = getelementptr inbounds %Str_Node, ptr %t5, i32 0, i32 1 + %t7 = load ptr, ptr %t0 + store ptr %t7, ptr %t6 + %t8 = load ptr, ptr %t4 + %t9 = getelementptr inbounds %Str_Node, ptr %t8, i32 0, i32 4 + %t10 = load ptr, ptr %t1 + store ptr %t10, ptr %t9 + %t11 = load ptr, ptr %t4 + %t12 = getelementptr inbounds %Str_Node, ptr %t11, i32 0, i32 5 + %t13 = load ptr, ptr %t2 + store ptr %t13, ptr %t12 + %t14 = load ptr, ptr %t4 + store ptr %t14, ptr %retval + br label %ret +ret: + %t15 = load ptr, ptr %retval + ret ptr %t15 +} + +define ptr @fn_p_mul() { +entry: + %retval = alloca ptr + %t1 = alloca ptr + %t2 = alloca i32 + %t3 = alloca i32 + %t26 = alloca ptr + %t0 = call ptr @fn_p_unary() + store ptr %t0, ptr %t1 + br label %wcond0 +wcond0: + %t4 = call i32 @fn_is_op(ptr @.str24) + %t5 = icmp ne i32 %t4, 0 + %t6 = zext i1 %t5 to i32 + store i32 %t6, ptr %t3 + br i1 %t5, label %scend4, label %sc3 +sc3: + %t7 = call i32 @fn_is_op(ptr @.str25) + %t8 = icmp ne i32 %t7, 0 + %t9 = zext i1 %t8 to i32 + store i32 %t9, ptr %t3 + br label %scend4 +scend4: + %t10 = load i32, ptr %t3 + %t11 = icmp ne i32 %t10, 0 + %t12 = zext i1 %t11 to i32 + store i32 %t12, ptr %t2 + br i1 %t11, label %scend6, label %sc5 +sc5: + %t13 = call i32 @fn_is_op(ptr @.str26) + %t14 = icmp ne i32 %t13, 0 + %t15 = zext i1 %t14 to i32 + store i32 %t15, ptr %t2 + br label %scend6 +scend6: + %t16 = load i32, ptr %t2 + %t17 = icmp ne i32 %t16, 0 + br i1 %t17, label %wbody1, label %wend2 +wbody1: + %t18 = load ptr, ptr @g_toks + %t19 = getelementptr inbounds %LSlice, ptr %t18, i32 0, i32 0 + %t20 = load ptr, ptr %t19 + %t21 = load i32, ptr @g_pi + %t22 = getelementptr inbounds ptr, ptr %t20, i32 %t21 + %t23 = load ptr, ptr %t22 + %t24 = getelementptr inbounds %Str_Tok, ptr %t23, i32 0, i32 1 + %t25 = load ptr, ptr %t24 + store ptr %t25, ptr %t26 + %t27 = load i32, ptr @g_pi + %t28 = add i32 %t27, 1 + store i32 %t28, ptr @g_pi + %t29 = load ptr, ptr %t26 + %t30 = load ptr, ptr %t1 + %t31 = call ptr @fn_p_unary() + %t32 = call ptr @fn_mkbin(ptr %t29, ptr %t30, ptr %t31) + store ptr %t32, ptr %t1 + br label %wcond0 +wend2: + %t33 = load ptr, ptr %t1 + store ptr %t33, ptr %retval + br label %ret +ret: + %t34 = load ptr, ptr %retval + ret ptr %t34 +} + +define ptr @fn_p_add() { +entry: + %retval = alloca ptr + %t1 = alloca ptr + %t2 = alloca i32 + %t19 = alloca ptr + %t0 = call ptr @fn_p_mul() + store ptr %t0, ptr %t1 + br label %wcond0 +wcond0: + %t3 = call i32 @fn_is_op(ptr @.str27) + %t4 = icmp ne i32 %t3, 0 + %t5 = zext i1 %t4 to i32 + store i32 %t5, ptr %t2 + br i1 %t4, label %scend4, label %sc3 +sc3: + %t6 = call i32 @fn_is_op(ptr @.str28) + %t7 = icmp ne i32 %t6, 0 + %t8 = zext i1 %t7 to i32 + store i32 %t8, ptr %t2 + br label %scend4 +scend4: + %t9 = load i32, ptr %t2 + %t10 = icmp ne i32 %t9, 0 + br i1 %t10, label %wbody1, label %wend2 +wbody1: + %t11 = load ptr, ptr @g_toks + %t12 = getelementptr inbounds %LSlice, ptr %t11, i32 0, i32 0 + %t13 = load ptr, ptr %t12 + %t14 = load i32, ptr @g_pi + %t15 = getelementptr inbounds ptr, ptr %t13, i32 %t14 + %t16 = load ptr, ptr %t15 + %t17 = getelementptr inbounds %Str_Tok, ptr %t16, i32 0, i32 1 + %t18 = load ptr, ptr %t17 + store ptr %t18, ptr %t19 + %t20 = load i32, ptr @g_pi + %t21 = add i32 %t20, 1 + store i32 %t21, ptr @g_pi + %t22 = load ptr, ptr %t19 + %t23 = load ptr, ptr %t1 + %t24 = call ptr @fn_p_mul() + %t25 = call ptr @fn_mkbin(ptr %t22, ptr %t23, ptr %t24) + store ptr %t25, ptr %t1 + br label %wcond0 +wend2: + %t26 = load ptr, ptr %t1 + store ptr %t26, ptr %retval + br label %ret +ret: + %t27 = load ptr, ptr %retval + ret ptr %t27 +} + +define ptr @fn_p_cmp() { +entry: + %retval = alloca ptr + %t1 = alloca ptr + %t2 = alloca i32 + %t3 = alloca i32 + %t4 = alloca i32 + %t5 = alloca i32 + %t6 = alloca i32 + %t47 = alloca ptr + %t0 = call ptr @fn_p_add() + store ptr %t0, ptr %t1 + br label %wcond0 +wcond0: + %t7 = call i32 @fn_is_op(ptr @.str29) + %t8 = icmp ne i32 %t7, 0 + %t9 = zext i1 %t8 to i32 + store i32 %t9, ptr %t6 + br i1 %t8, label %scend4, label %sc3 +sc3: + %t10 = call i32 @fn_is_op(ptr @.str30) + %t11 = icmp ne i32 %t10, 0 + %t12 = zext i1 %t11 to i32 + store i32 %t12, ptr %t6 + br label %scend4 +scend4: + %t13 = load i32, ptr %t6 + %t14 = icmp ne i32 %t13, 0 + %t15 = zext i1 %t14 to i32 + store i32 %t15, ptr %t5 + br i1 %t14, label %scend6, label %sc5 +sc5: + %t16 = call i32 @fn_is_op(ptr @.str31) + %t17 = icmp ne i32 %t16, 0 + %t18 = zext i1 %t17 to i32 + store i32 %t18, ptr %t5 + br label %scend6 +scend6: + %t19 = load i32, ptr %t5 + %t20 = icmp ne i32 %t19, 0 + %t21 = zext i1 %t20 to i32 + store i32 %t21, ptr %t4 + br i1 %t20, label %scend8, label %sc7 +sc7: + %t22 = call i32 @fn_is_op(ptr @.str32) + %t23 = icmp ne i32 %t22, 0 + %t24 = zext i1 %t23 to i32 + store i32 %t24, ptr %t4 + br label %scend8 +scend8: + %t25 = load i32, ptr %t4 + %t26 = icmp ne i32 %t25, 0 + %t27 = zext i1 %t26 to i32 + store i32 %t27, ptr %t3 + br i1 %t26, label %scend10, label %sc9 +sc9: + %t28 = call i32 @fn_is_op(ptr @.str33) + %t29 = icmp ne i32 %t28, 0 + %t30 = zext i1 %t29 to i32 + store i32 %t30, ptr %t3 + br label %scend10 +scend10: + %t31 = load i32, ptr %t3 + %t32 = icmp ne i32 %t31, 0 + %t33 = zext i1 %t32 to i32 + store i32 %t33, ptr %t2 + br i1 %t32, label %scend12, label %sc11 +sc11: + %t34 = call i32 @fn_is_op(ptr @.str34) + %t35 = icmp ne i32 %t34, 0 + %t36 = zext i1 %t35 to i32 + store i32 %t36, ptr %t2 + br label %scend12 +scend12: + %t37 = load i32, ptr %t2 + %t38 = icmp ne i32 %t37, 0 + br i1 %t38, label %wbody1, label %wend2 +wbody1: + %t39 = load ptr, ptr @g_toks + %t40 = getelementptr inbounds %LSlice, ptr %t39, i32 0, i32 0 + %t41 = load ptr, ptr %t40 + %t42 = load i32, ptr @g_pi + %t43 = getelementptr inbounds ptr, ptr %t41, i32 %t42 + %t44 = load ptr, ptr %t43 + %t45 = getelementptr inbounds %Str_Tok, ptr %t44, i32 0, i32 1 + %t46 = load ptr, ptr %t45 + store ptr %t46, ptr %t47 + %t48 = load i32, ptr @g_pi + %t49 = add i32 %t48, 1 + store i32 %t49, ptr @g_pi + %t50 = load ptr, ptr %t47 + %t51 = load ptr, ptr %t1 + %t52 = call ptr @fn_p_add() + %t53 = call ptr @fn_mkbin(ptr %t50, ptr %t51, ptr %t52) + store ptr %t53, ptr %t1 + br label %wcond0 +wend2: + %t54 = load ptr, ptr %t1 + store ptr %t54, ptr %retval + br label %ret +ret: + %t55 = load ptr, ptr %retval + ret ptr %t55 +} + +define ptr @fn_p_and() { +entry: + %retval = alloca ptr + %t1 = alloca ptr + %t0 = call ptr @fn_p_cmp() + store ptr %t0, ptr %t1 + br label %wcond0 +wcond0: + %t2 = call i32 @fn_is_id(ptr @.str35) + %t3 = icmp ne i32 %t2, 0 + br i1 %t3, label %wbody1, label %wend2 +wbody1: + %t4 = load i32, ptr @g_pi + %t5 = add i32 %t4, 1 + store i32 %t5, ptr @g_pi + %t6 = load ptr, ptr %t1 + %t7 = call ptr @fn_p_cmp() + %t8 = call ptr @fn_mkbin(ptr @.str36, ptr %t6, ptr %t7) + store ptr %t8, ptr %t1 + br label %wcond0 +wend2: + %t9 = load ptr, ptr %t1 + store ptr %t9, ptr %retval + br label %ret +ret: + %t10 = load ptr, ptr %retval + ret ptr %t10 +} + +define ptr @fn_p_or() { +entry: + %retval = alloca ptr + %t1 = alloca ptr + %t0 = call ptr @fn_p_and() + store ptr %t0, ptr %t1 + br label %wcond0 +wcond0: + %t2 = call i32 @fn_is_id(ptr @.str37) + %t3 = icmp ne i32 %t2, 0 + br i1 %t3, label %wbody1, label %wend2 +wbody1: + %t4 = load i32, ptr @g_pi + %t5 = add i32 %t4, 1 + store i32 %t5, ptr @g_pi + %t6 = load ptr, ptr %t1 + %t7 = call ptr @fn_p_and() + %t8 = call ptr @fn_mkbin(ptr @.str38, ptr %t6, ptr %t7) + store ptr %t8, ptr %t1 + br label %wcond0 +wend2: + %t9 = load ptr, ptr %t1 + store ptr %t9, ptr %retval + br label %ret +ret: + %t10 = load ptr, ptr %retval + ret ptr %t10 +} + +define ptr @fn_record() { +entry: + %retval = alloca ptr + %t1 = alloca ptr + %t6 = alloca ptr + call void @fn_eat_op(ptr @.str39) + %t0 = call ptr @fn_node(i32 41) + store ptr %t0, ptr %t1 + br label %wcond0 +wcond0: + %t2 = icmp ne i32 1, 0 + br i1 %t2, label %wbody1, label %wend2 +wbody1: + call void @fn_skipnl() + %t3 = call i32 @fn_is_op(ptr @.str40) + %t4 = icmp ne i32 %t3, 0 + br i1 %t4, label %then3, label %ifend5 +then3: + br label %wend2 +ifend5: + %t5 = call ptr @fn_node(i32 42) + store ptr %t5, ptr %t6 + %t7 = load ptr, ptr %t6 + %t8 = getelementptr inbounds %Str_Node, ptr %t7, i32 0, i32 1 + %t9 = call ptr @fn_eat_id() + store ptr %t9, ptr %t8 + call void @fn_eat_op(ptr @.str41) + %t10 = load ptr, ptr %t6 + %t11 = getelementptr inbounds %Str_Node, ptr %t10, i32 0, i32 4 + %t12 = call ptr @fn_expr() + store ptr %t12, ptr %t11 + %t13 = load ptr, ptr %t1 + %t14 = getelementptr inbounds %Str_Node, ptr %t13, i32 0, i32 7 + %t15 = load ptr, ptr %t14 + %t16 = getelementptr inbounds %LSlice, ptr %t15, i32 0, i32 1 + %t17 = getelementptr inbounds %LSlice, ptr %t15, i32 0, i32 2 + %t18 = getelementptr inbounds %LSlice, ptr %t15, i32 0, i32 0 + %t19 = load i32, ptr %t16 + %t20 = load i32, ptr %t17 + %t21 = icmp sge i32 %t19, %t20 + br i1 %t21, label %grow6, label %put7 +grow6: + %t22 = mul i32 %t20, 2 + %t23 = icmp eq i32 %t20, 0 + %t24 = select i1 %t23, i32 8, i32 %t22 + %t25 = getelementptr ptr, ptr null, i32 1 + %t26 = ptrtoint ptr %t25 to i64 + %t27 = zext i32 %t24 to i64 + %t28 = mul i64 %t27, %t26 + %t29 = load ptr, ptr %t18 + %t30 = call ptr @realloc(ptr %t29, i64 %t28) + store ptr %t30, ptr %t18 + store i32 %t24, ptr %t17 + br label %put7 +put7: + %t31 = load ptr, ptr %t6 + %t32 = load ptr, ptr %t18 + %t33 = getelementptr inbounds ptr, ptr %t32, i32 %t19 + store ptr %t31, ptr %t33 + %t34 = add i32 %t19, 1 + store i32 %t34, ptr %t16 + %t35 = call i32 @fn_is_op(ptr @.str42) + %t36 = icmp ne i32 %t35, 0 + br i1 %t36, label %then8, label %ifend10 +then8: + %t37 = load i32, ptr @g_pi + %t38 = add i32 %t37, 1 + store i32 %t38, ptr @g_pi + br label %ifend10 +ifend10: + br label %wcond0 +wend2: + call void @fn_eat_op(ptr @.str43) + %t39 = load ptr, ptr %t1 + store ptr %t39, ptr %retval + br label %ret +ret: + %t40 = load ptr, ptr %retval + ret ptr %t40 +} + +define ptr @fn_block() { +entry: + %retval = alloca ptr + %t1 = alloca ptr + call void @fn_skipnl() + call void @fn_eat_op(ptr @.str44) + %t0 = call ptr @fn_node(i32 7) + store ptr %t0, ptr %t1 + br label %wcond0 +wcond0: + %t2 = icmp ne i32 1, 0 + br i1 %t2, label %wbody1, label %wend2 +wbody1: + call void @fn_skipnl() + %t3 = call i32 @fn_is_op(ptr @.str45) + %t4 = icmp ne i32 %t3, 0 + br i1 %t4, label %then3, label %ifend5 +then3: + br label %wend2 +ifend5: + %t5 = load ptr, ptr %t1 + %t6 = getelementptr inbounds %Str_Node, ptr %t5, i32 0, i32 7 + %t7 = load ptr, ptr %t6 + %t8 = getelementptr inbounds %LSlice, ptr %t7, i32 0, i32 1 + %t9 = getelementptr inbounds %LSlice, ptr %t7, i32 0, i32 2 + %t10 = getelementptr inbounds %LSlice, ptr %t7, i32 0, i32 0 + %t11 = load i32, ptr %t8 + %t12 = load i32, ptr %t9 + %t13 = icmp sge i32 %t11, %t12 + br i1 %t13, label %grow6, label %put7 +grow6: + %t14 = mul i32 %t12, 2 + %t15 = icmp eq i32 %t12, 0 + %t16 = select i1 %t15, i32 8, i32 %t14 + %t17 = getelementptr ptr, ptr null, i32 1 + %t18 = ptrtoint ptr %t17 to i64 + %t19 = zext i32 %t16 to i64 + %t20 = mul i64 %t19, %t18 + %t21 = load ptr, ptr %t10 + %t22 = call ptr @realloc(ptr %t21, i64 %t20) + store ptr %t22, ptr %t10 + store i32 %t16, ptr %t9 + br label %put7 +put7: + %t23 = call ptr @fn_stmt() + %t24 = load ptr, ptr %t10 + %t25 = getelementptr inbounds ptr, ptr %t24, i32 %t11 + store ptr %t23, ptr %t25 + %t26 = add i32 %t11, 1 + store i32 %t26, ptr %t8 + br label %wcond0 +wend2: + call void @fn_eat_op(ptr @.str46) + %t27 = load ptr, ptr %t1 + store ptr %t27, ptr %retval + br label %ret +ret: + %t28 = load ptr, ptr %retval + ret ptr %t28 +} + +define ptr @fn_stmt() { +entry: + %retval = alloca ptr + %t6 = alloca ptr + %t21 = alloca ptr + %t48 = alloca ptr + %t49 = alloca i32 + %t81 = alloca ptr + %t109 = alloca ptr + %t125 = alloca ptr + %t144 = alloca ptr + %t149 = alloca ptr + %t174 = alloca ptr + %t182 = alloca ptr + %t184 = alloca ptr + %t225 = alloca ptr + %t238 = alloca ptr + %t253 = alloca ptr + %t282 = alloca ptr + %t290 = alloca ptr + %t324 = alloca ptr + %t374 = alloca ptr + %t375 = alloca i32 + %t376 = alloca i32 + %t377 = alloca i32 + %t378 = alloca i32 + %t406 = alloca ptr + %t427 = alloca ptr + %t0 = load ptr, ptr @g_toks + %t1 = getelementptr inbounds %LSlice, ptr %t0, i32 0, i32 0 + %t2 = load ptr, ptr %t1 + %t3 = load i32, ptr @g_pi + %t4 = getelementptr inbounds ptr, ptr %t2, i32 %t3 + %t5 = load ptr, ptr %t4 + store ptr %t5, ptr %t6 + %t7 = load ptr, ptr %t6 + %t8 = getelementptr inbounds %Str_Tok, ptr %t7, i32 0, i32 0 + %t9 = load i32, ptr %t8 + %t10 = icmp eq i32 %t9, 0 + %t11 = zext i1 %t10 to i32 + %t12 = icmp ne i32 %t11, 0 + br i1 %t12, label %then0, label %ifend2 +then0: + %t13 = load ptr, ptr %t6 + %t14 = getelementptr inbounds %Str_Tok, ptr %t13, i32 0, i32 1 + %t15 = load ptr, ptr %t14 + %t16 = call i32 @fn_streq(ptr %t15, ptr @.str47) + %t17 = icmp ne i32 %t16, 0 + br i1 %t17, label %then3, label %ifend5 +then3: + %t18 = load i32, ptr @g_pi + %t19 = add i32 %t18, 1 + store i32 %t19, ptr @g_pi + %t20 = call ptr @fn_node(i32 10) + store ptr %t20, ptr %t21 + %t22 = load ptr, ptr %t21 + %t23 = getelementptr inbounds %Str_Node, ptr %t22, i32 0, i32 1 + %t24 = call ptr @fn_eat_id() + store ptr %t24, ptr %t23 + %t25 = call i32 @fn_is_op(ptr @.str48) + %t26 = icmp ne i32 %t25, 0 + br i1 %t26, label %then6, label %ifend8 +then6: + %t27 = load i32, ptr @g_pi + %t28 = add i32 %t27, 1 + store i32 %t28, ptr @g_pi + %t29 = load ptr, ptr %t21 + %t30 = getelementptr inbounds %Str_Node, ptr %t29, i32 0, i32 3 + %t31 = call ptr @fn_ptype() + store ptr %t31, ptr %t30 + br label %ifend8 +ifend8: + %t32 = call i32 @fn_is_op(ptr @.str49) + %t33 = icmp ne i32 %t32, 0 + br i1 %t33, label %then9, label %ifend11 +then9: + %t34 = load i32, ptr @g_pi + %t35 = add i32 %t34, 1 + store i32 %t35, ptr @g_pi + %t36 = load ptr, ptr %t21 + %t37 = getelementptr inbounds %Str_Node, ptr %t36, i32 0, i32 4 + %t38 = call ptr @fn_expr() + store ptr %t38, ptr %t37 + br label %ifend11 +ifend11: + %t39 = load ptr, ptr %t21 + store ptr %t39, ptr %retval + br label %ret +ifend5: + %t40 = load ptr, ptr %t6 + %t41 = getelementptr inbounds %Str_Tok, ptr %t40, i32 0, i32 1 + %t42 = load ptr, ptr %t41 + %t43 = call i32 @fn_streq(ptr %t42, ptr @.str50) + %t44 = icmp ne i32 %t43, 0 + br i1 %t44, label %then12, label %ifend14 +then12: + %t45 = load i32, ptr @g_pi + %t46 = add i32 %t45, 1 + store i32 %t46, ptr @g_pi + %t47 = call ptr @fn_node(i32 15) + store ptr %t47, ptr %t48 + %t50 = load ptr, ptr @g_toks + %t51 = getelementptr inbounds %LSlice, ptr %t50, i32 0, i32 0 + %t52 = load ptr, ptr %t51 + %t53 = load i32, ptr @g_pi + %t54 = getelementptr inbounds ptr, ptr %t52, i32 %t53 + %t55 = load ptr, ptr %t54 + %t56 = getelementptr inbounds %Str_Tok, ptr %t55, i32 0, i32 0 + %t57 = load i32, ptr %t56 + %t58 = icmp ne i32 %t57, 4 + %t59 = zext i1 %t58 to i32 + %t60 = icmp ne i32 %t59, 0 + %t61 = zext i1 %t60 to i32 + store i32 %t61, ptr %t49 + br i1 %t60, label %sc15, label %scend16 +sc15: + %t62 = call i32 @fn_is_op(ptr @.str51) + %t63 = icmp eq i32 %t62, 0 + %t64 = zext i1 %t63 to i32 + %t65 = icmp ne i32 %t64, 0 + %t66 = zext i1 %t65 to i32 + store i32 %t66, ptr %t49 + br label %scend16 +scend16: + %t67 = load i32, ptr %t49 + %t68 = icmp ne i32 %t67, 0 + br i1 %t68, label %then17, label %ifend19 +then17: + %t69 = load ptr, ptr %t48 + %t70 = getelementptr inbounds %Str_Node, ptr %t69, i32 0, i32 4 + %t71 = call ptr @fn_expr() + store ptr %t71, ptr %t70 + br label %ifend19 +ifend19: + %t72 = load ptr, ptr %t48 + store ptr %t72, ptr %retval + br label %ret +ifend14: + %t73 = load ptr, ptr %t6 + %t74 = getelementptr inbounds %Str_Tok, ptr %t73, i32 0, i32 1 + %t75 = load ptr, ptr %t74 + %t76 = call i32 @fn_streq(ptr %t75, ptr @.str52) + %t77 = icmp ne i32 %t76, 0 + br i1 %t77, label %then20, label %ifend22 +then20: + %t78 = load i32, ptr @g_pi + %t79 = add i32 %t78, 1 + store i32 %t79, ptr @g_pi + %t80 = call ptr @fn_node(i32 12) + store ptr %t80, ptr %t81 + %t82 = load ptr, ptr %t81 + %t83 = getelementptr inbounds %Str_Node, ptr %t82, i32 0, i32 4 + %t84 = call ptr @fn_expr() + store ptr %t84, ptr %t83 + %t85 = load ptr, ptr %t81 + %t86 = getelementptr inbounds %Str_Node, ptr %t85, i32 0, i32 5 + %t87 = call ptr @fn_block() + store ptr %t87, ptr %t86 + call void @fn_skipnl() + %t88 = call i32 @fn_is_id(ptr @.str53) + %t89 = icmp ne i32 %t88, 0 + br i1 %t89, label %then23, label %ifend25 +then23: + %t90 = load i32, ptr @g_pi + %t91 = add i32 %t90, 1 + store i32 %t91, ptr @g_pi + call void @fn_skipnl() + %t92 = call i32 @fn_is_id(ptr @.str54) + %t93 = icmp ne i32 %t92, 0 + br i1 %t93, label %then26, label %else27 +then26: + %t94 = load ptr, ptr %t81 + %t95 = getelementptr inbounds %Str_Node, ptr %t94, i32 0, i32 6 + %t96 = call ptr @fn_stmt() + store ptr %t96, ptr %t95 + br label %ifend28 +else27: + %t97 = load ptr, ptr %t81 + %t98 = getelementptr inbounds %Str_Node, ptr %t97, i32 0, i32 6 + %t99 = call ptr @fn_block() + store ptr %t99, ptr %t98 + br label %ifend28 +ifend28: + br label %ifend25 +ifend25: + %t100 = load ptr, ptr %t81 + store ptr %t100, ptr %retval + br label %ret +ifend22: + %t101 = load ptr, ptr %t6 + %t102 = getelementptr inbounds %Str_Tok, ptr %t101, i32 0, i32 1 + %t103 = load ptr, ptr %t102 + %t104 = call i32 @fn_streq(ptr %t103, ptr @.str55) + %t105 = icmp ne i32 %t104, 0 + br i1 %t105, label %then29, label %ifend31 +then29: + %t106 = load i32, ptr @g_pi + %t107 = add i32 %t106, 1 + store i32 %t107, ptr @g_pi + %t108 = call ptr @fn_node(i32 12) + store ptr %t108, ptr %t109 + %t110 = load ptr, ptr %t109 + %t111 = getelementptr inbounds %Str_Node, ptr %t110, i32 0, i32 4 + %t112 = call ptr @fn_expr() + store ptr %t112, ptr %t111 + %t113 = load ptr, ptr %t109 + %t114 = getelementptr inbounds %Str_Node, ptr %t113, i32 0, i32 5 + %t115 = call ptr @fn_block() + store ptr %t115, ptr %t114 + %t116 = load ptr, ptr %t109 + store ptr %t116, ptr %retval + br label %ret +ifend31: + %t117 = load ptr, ptr %t6 + %t118 = getelementptr inbounds %Str_Tok, ptr %t117, i32 0, i32 1 + %t119 = load ptr, ptr %t118 + %t120 = call i32 @fn_streq(ptr %t119, ptr @.str56) + %t121 = icmp ne i32 %t120, 0 + br i1 %t121, label %then32, label %ifend34 +then32: + %t122 = load i32, ptr @g_pi + %t123 = add i32 %t122, 1 + store i32 %t123, ptr @g_pi + %t124 = call ptr @fn_node(i32 13) + store ptr %t124, ptr %t125 + %t126 = load ptr, ptr %t125 + %t127 = getelementptr inbounds %Str_Node, ptr %t126, i32 0, i32 4 + %t128 = call ptr @fn_expr() + store ptr %t128, ptr %t127 + %t129 = load ptr, ptr %t125 + %t130 = getelementptr inbounds %Str_Node, ptr %t129, i32 0, i32 5 + %t131 = call ptr @fn_block() + store ptr %t131, ptr %t130 + %t132 = load ptr, ptr %t125 + store ptr %t132, ptr %retval + br label %ret +ifend34: + %t133 = load ptr, ptr %t6 + %t134 = getelementptr inbounds %Str_Tok, ptr %t133, i32 0, i32 1 + %t135 = load ptr, ptr %t134 + %t136 = call i32 @fn_streq(ptr %t135, ptr @.str57) + %t137 = icmp ne i32 %t136, 0 + br i1 %t137, label %then35, label %ifend37 +then35: + %t138 = load i32, ptr @g_pi + %t139 = add i32 %t138, 1 + store i32 %t139, ptr @g_pi + %t140 = call i32 @fn_is_op(ptr @.str58) + %t141 = icmp ne i32 %t140, 0 + br i1 %t141, label %then38, label %ifend40 +then38: + %t142 = call ptr @fn_parse_query_for() + store ptr %t142, ptr %retval + br label %ret +ifend40: + %t143 = call ptr @fn_node(i32 14) + store ptr %t143, ptr %t144 + %t145 = load ptr, ptr %t144 + %t146 = getelementptr inbounds %Str_Node, ptr %t145, i32 0, i32 1 + %t147 = call ptr @fn_eat_id() + store ptr %t147, ptr %t146 + %t148 = call ptr @fn_eat_id() + store ptr %t148, ptr %t149 + %t150 = load ptr, ptr %t144 + %t151 = getelementptr inbounds %Str_Node, ptr %t150, i32 0, i32 4 + %t152 = call ptr @fn_expr() + store ptr %t152, ptr %t151 + call void @fn_eat_op(ptr @.str59) + %t153 = load ptr, ptr %t144 + %t154 = getelementptr inbounds %Str_Node, ptr %t153, i32 0, i32 5 + %t155 = call ptr @fn_expr() + store ptr %t155, ptr %t154 + %t156 = load ptr, ptr %t144 + %t157 = getelementptr inbounds %Str_Node, ptr %t156, i32 0, i32 6 + %t158 = call ptr @fn_block() + store ptr %t158, ptr %t157 + %t159 = load ptr, ptr %t144 + store ptr %t159, ptr %retval + br label %ret +ifend37: + %t160 = load ptr, ptr %t6 + %t161 = getelementptr inbounds %Str_Tok, ptr %t160, i32 0, i32 1 + %t162 = load ptr, ptr %t161 + %t163 = call i32 @fn_streq(ptr %t162, ptr @.str60) + %t164 = icmp ne i32 %t163, 0 + br i1 %t164, label %then41, label %ifend43 +then41: + %t165 = call ptr @fn_parse_spawn() + store ptr %t165, ptr %retval + br label %ret +ifend43: + %t166 = load ptr, ptr %t6 + %t167 = getelementptr inbounds %Str_Tok, ptr %t166, i32 0, i32 1 + %t168 = load ptr, ptr %t167 + %t169 = call i32 @fn_streq(ptr %t168, ptr @.str61) + %t170 = icmp ne i32 %t169, 0 + br i1 %t170, label %then44, label %ifend46 +then44: + %t171 = load i32, ptr @g_pi + %t172 = add i32 %t171, 1 + store i32 %t172, ptr @g_pi + %t173 = call ptr @fn_node(i32 24) + store ptr %t173, ptr %t174 + %t175 = load ptr, ptr %t174 + %t176 = getelementptr inbounds %Str_Node, ptr %t175, i32 0, i32 4 + %t177 = call ptr @fn_expr() + store ptr %t177, ptr %t176 + call void @fn_skipnl() + call void @fn_eat_op(ptr @.str62) + br label %wcond47 +wcond47: + %t178 = icmp ne i32 1, 0 + br i1 %t178, label %wbody48, label %wend49 +wbody48: + call void @fn_skipnl() + %t179 = call i32 @fn_is_op(ptr @.str63) + %t180 = icmp ne i32 %t179, 0 + br i1 %t180, label %then50, label %ifend52 +then50: + br label %wend49 +ifend52: + %t181 = call ptr @fn_eat_id() + store ptr %t181, ptr %t182 + %t183 = call ptr @fn_node(i32 25) + store ptr %t183, ptr %t184 + %t185 = load ptr, ptr %t184 + %t186 = getelementptr inbounds %Str_Node, ptr %t185, i32 0, i32 1 + %t187 = call ptr @fn_eat_id() + store ptr %t187, ptr %t186 + call void @fn_eat_op(ptr @.str64) + %t188 = load ptr, ptr %t184 + %t189 = getelementptr inbounds %Str_Node, ptr %t188, i32 0, i32 5 + %t190 = call ptr @fn_expr() + store ptr %t190, ptr %t189 + call void @fn_skipnl() + %t191 = load ptr, ptr %t184 + %t192 = getelementptr inbounds %Str_Node, ptr %t191, i32 0, i32 4 + %t193 = call ptr @fn_block() + store ptr %t193, ptr %t192 + %t194 = load ptr, ptr %t174 + %t195 = getelementptr inbounds %Str_Node, ptr %t194, i32 0, i32 7 + %t196 = load ptr, ptr %t195 + %t197 = getelementptr inbounds %LSlice, ptr %t196, i32 0, i32 1 + %t198 = getelementptr inbounds %LSlice, ptr %t196, i32 0, i32 2 + %t199 = getelementptr inbounds %LSlice, ptr %t196, i32 0, i32 0 + %t200 = load i32, ptr %t197 + %t201 = load i32, ptr %t198 + %t202 = icmp sge i32 %t200, %t201 + br i1 %t202, label %grow53, label %put54 +grow53: + %t203 = mul i32 %t201, 2 + %t204 = icmp eq i32 %t201, 0 + %t205 = select i1 %t204, i32 8, i32 %t203 + %t206 = getelementptr ptr, ptr null, i32 1 + %t207 = ptrtoint ptr %t206 to i64 + %t208 = zext i32 %t205 to i64 + %t209 = mul i64 %t208, %t207 + %t210 = load ptr, ptr %t199 + %t211 = call ptr @realloc(ptr %t210, i64 %t209) + store ptr %t211, ptr %t199 + store i32 %t205, ptr %t198 + br label %put54 +put54: + %t212 = load ptr, ptr %t184 + %t213 = load ptr, ptr %t199 + %t214 = getelementptr inbounds ptr, ptr %t213, i32 %t200 + store ptr %t212, ptr %t214 + %t215 = add i32 %t200, 1 + store i32 %t215, ptr %t197 + br label %wcond47 +wend49: + call void @fn_eat_op(ptr @.str65) + %t216 = load ptr, ptr %t174 + store ptr %t216, ptr %retval + br label %ret +ifend46: + %t217 = load ptr, ptr %t6 + %t218 = getelementptr inbounds %Str_Tok, ptr %t217, i32 0, i32 1 + %t219 = load ptr, ptr %t218 + %t220 = call i32 @fn_streq(ptr %t219, ptr @.str66) + %t221 = icmp ne i32 %t220, 0 + br i1 %t221, label %then55, label %ifend57 +then55: + %t222 = load i32, ptr @g_pi + %t223 = add i32 %t222, 1 + store i32 %t223, ptr @g_pi + %t224 = call ptr @fn_node(i32 26) + store ptr %t224, ptr %t225 + %t226 = load ptr, ptr %t225 + %t227 = getelementptr inbounds %Str_Node, ptr %t226, i32 0, i32 1 + %t228 = call ptr @fn_eat_id() + store ptr %t228, ptr %t227 + %t229 = load ptr, ptr %t225 + store ptr %t229, ptr %retval + br label %ret +ifend57: + %t230 = load ptr, ptr %t6 + %t231 = getelementptr inbounds %Str_Tok, ptr %t230, i32 0, i32 1 + %t232 = load ptr, ptr %t231 + %t233 = call i32 @fn_streq(ptr %t232, ptr @.str67) + %t234 = icmp ne i32 %t233, 0 + br i1 %t234, label %then58, label %ifend60 +then58: + %t235 = load i32, ptr @g_pi + %t236 = add i32 %t235, 1 + store i32 %t236, ptr @g_pi + %t237 = call ptr @fn_node(i32 26) + store ptr %t237, ptr %t238 + %t239 = load ptr, ptr %t238 + %t240 = getelementptr inbounds %Str_Node, ptr %t239, i32 0, i32 1 + %t241 = call ptr @fn_eat_id() + store ptr %t241, ptr %t240 + %t242 = load ptr, ptr %t238 + %t243 = getelementptr inbounds %Str_Node, ptr %t242, i32 0, i32 2 + store i32 1, ptr %t243 + %t244 = load ptr, ptr %t238 + store ptr %t244, ptr %retval + br label %ret +ifend60: + %t245 = load ptr, ptr %t6 + %t246 = getelementptr inbounds %Str_Tok, ptr %t245, i32 0, i32 1 + %t247 = load ptr, ptr %t246 + %t248 = call i32 @fn_streq(ptr %t247, ptr @.str68) + %t249 = icmp ne i32 %t248, 0 + br i1 %t249, label %then61, label %ifend63 +then61: + %t250 = load i32, ptr @g_pi + %t251 = add i32 %t250, 1 + store i32 %t251, ptr @g_pi + %t252 = call ptr @fn_node(i32 23) + store ptr %t252, ptr %t253 + %t254 = load ptr, ptr %t253 + %t255 = getelementptr inbounds %Str_Node, ptr %t254, i32 0, i32 4 + %t256 = call ptr @fn_expr() + store ptr %t256, ptr %t255 + %t257 = load ptr, ptr %t253 + store ptr %t257, ptr %retval + br label %ret +ifend63: + %t258 = load ptr, ptr %t6 + %t259 = getelementptr inbounds %Str_Tok, ptr %t258, i32 0, i32 1 + %t260 = load ptr, ptr %t259 + %t261 = call i32 @fn_streq(ptr %t260, ptr @.str69) + %t262 = icmp ne i32 %t261, 0 + br i1 %t262, label %then64, label %ifend66 +then64: + %t263 = load i32, ptr @g_pi + %t264 = add i32 %t263, 1 + store i32 %t264, ptr @g_pi + %t265 = call ptr @fn_node(i32 17) + store ptr %t265, ptr %retval + br label %ret +ifend66: + %t266 = load ptr, ptr %t6 + %t267 = getelementptr inbounds %Str_Tok, ptr %t266, i32 0, i32 1 + %t268 = load ptr, ptr %t267 + %t269 = call i32 @fn_streq(ptr %t268, ptr @.str70) + %t270 = icmp ne i32 %t269, 0 + br i1 %t270, label %then67, label %ifend69 +then67: + %t271 = load i32, ptr @g_pi + %t272 = add i32 %t271, 1 + store i32 %t272, ptr @g_pi + %t273 = call ptr @fn_node(i32 18) + store ptr %t273, ptr %retval + br label %ret +ifend69: + %t274 = load ptr, ptr %t6 + %t275 = getelementptr inbounds %Str_Tok, ptr %t274, i32 0, i32 1 + %t276 = load ptr, ptr %t275 + %t277 = call i32 @fn_streq(ptr %t276, ptr @.str71) + %t278 = icmp ne i32 %t277, 0 + br i1 %t278, label %then70, label %ifend72 +then70: + %t279 = load i32, ptr @g_pi + %t280 = add i32 %t279, 1 + store i32 %t280, ptr @g_pi + %t281 = call ptr @fn_node(i32 19) + store ptr %t281, ptr %t282 + %t283 = load ptr, ptr %t282 + %t284 = getelementptr inbounds %Str_Node, ptr %t283, i32 0, i32 4 + %t285 = call ptr @fn_expr() + store ptr %t285, ptr %t284 + call void @fn_skipnl() + call void @fn_eat_op(ptr @.str72) + br label %wcond73 +wcond73: + %t286 = icmp ne i32 1, 0 + br i1 %t286, label %wbody74, label %wend75 +wbody74: + call void @fn_skipnl() + %t287 = call i32 @fn_is_op(ptr @.str73) + %t288 = icmp ne i32 %t287, 0 + br i1 %t288, label %then76, label %ifend78 +then76: + br label %wend75 +ifend78: + %t289 = call ptr @fn_node(i32 20) + store ptr %t289, ptr %t290 + br label %wcond79 +wcond79: + %t291 = icmp ne i32 1, 0 + br i1 %t291, label %wbody80, label %wend81 +wbody80: + %t292 = load ptr, ptr %t290 + %t293 = getelementptr inbounds %Str_Node, ptr %t292, i32 0, i32 7 + %t294 = load ptr, ptr %t293 + %t295 = getelementptr inbounds %LSlice, ptr %t294, i32 0, i32 1 + %t296 = getelementptr inbounds %LSlice, ptr %t294, i32 0, i32 2 + %t297 = getelementptr inbounds %LSlice, ptr %t294, i32 0, i32 0 + %t298 = load i32, ptr %t295 + %t299 = load i32, ptr %t296 + %t300 = icmp sge i32 %t298, %t299 + br i1 %t300, label %grow82, label %put83 +grow82: + %t301 = mul i32 %t299, 2 + %t302 = icmp eq i32 %t299, 0 + %t303 = select i1 %t302, i32 8, i32 %t301 + %t304 = getelementptr ptr, ptr null, i32 1 + %t305 = ptrtoint ptr %t304 to i64 + %t306 = zext i32 %t303 to i64 + %t307 = mul i64 %t306, %t305 + %t308 = load ptr, ptr %t297 + %t309 = call ptr @realloc(ptr %t308, i64 %t307) + store ptr %t309, ptr %t297 + store i32 %t303, ptr %t296 + br label %put83 +put83: + %t310 = call ptr @fn_expr() + %t311 = load ptr, ptr %t297 + %t312 = getelementptr inbounds ptr, ptr %t311, i32 %t298 + store ptr %t310, ptr %t312 + %t313 = add i32 %t298, 1 + store i32 %t313, ptr %t295 + %t314 = call i32 @fn_is_op(ptr @.str74) + %t315 = icmp ne i32 %t314, 0 + br i1 %t315, label %then84, label %ifend86 +then84: + %t316 = load i32, ptr @g_pi + %t317 = add i32 %t316, 1 + store i32 %t317, ptr @g_pi + call void @fn_skipnl() + br label %wcond79 +ifend86: + br label %wend81 +wend81: + call void @fn_eat_op(ptr @.str75) + call void @fn_skipnl() + %t318 = call i32 @fn_is_op(ptr @.str76) + %t319 = icmp ne i32 %t318, 0 + br i1 %t319, label %then87, label %else88 +then87: + %t320 = load ptr, ptr %t290 + %t321 = getelementptr inbounds %Str_Node, ptr %t320, i32 0, i32 4 + %t322 = call ptr @fn_block() + store ptr %t322, ptr %t321 + br label %ifend89 +else88: + %t323 = call ptr @fn_node(i32 7) + store ptr %t323, ptr %t324 + %t325 = load ptr, ptr %t324 + %t326 = getelementptr inbounds %Str_Node, ptr %t325, i32 0, i32 7 + %t327 = load ptr, ptr %t326 + %t328 = getelementptr inbounds %LSlice, ptr %t327, i32 0, i32 1 + %t329 = getelementptr inbounds %LSlice, ptr %t327, i32 0, i32 2 + %t330 = getelementptr inbounds %LSlice, ptr %t327, i32 0, i32 0 + %t331 = load i32, ptr %t328 + %t332 = load i32, ptr %t329 + %t333 = icmp sge i32 %t331, %t332 + br i1 %t333, label %grow90, label %put91 +grow90: + %t334 = mul i32 %t332, 2 + %t335 = icmp eq i32 %t332, 0 + %t336 = select i1 %t335, i32 8, i32 %t334 + %t337 = getelementptr ptr, ptr null, i32 1 + %t338 = ptrtoint ptr %t337 to i64 + %t339 = zext i32 %t336 to i64 + %t340 = mul i64 %t339, %t338 + %t341 = load ptr, ptr %t330 + %t342 = call ptr @realloc(ptr %t341, i64 %t340) + store ptr %t342, ptr %t330 + store i32 %t336, ptr %t329 + br label %put91 +put91: + %t343 = call ptr @fn_stmt() + %t344 = load ptr, ptr %t330 + %t345 = getelementptr inbounds ptr, ptr %t344, i32 %t331 + store ptr %t343, ptr %t345 + %t346 = add i32 %t331, 1 + store i32 %t346, ptr %t328 + %t347 = load ptr, ptr %t290 + %t348 = getelementptr inbounds %Str_Node, ptr %t347, i32 0, i32 4 + %t349 = load ptr, ptr %t324 + store ptr %t349, ptr %t348 + br label %ifend89 +ifend89: + %t350 = load ptr, ptr %t282 + %t351 = getelementptr inbounds %Str_Node, ptr %t350, i32 0, i32 7 + %t352 = load ptr, ptr %t351 + %t353 = getelementptr inbounds %LSlice, ptr %t352, i32 0, i32 1 + %t354 = getelementptr inbounds %LSlice, ptr %t352, i32 0, i32 2 + %t355 = getelementptr inbounds %LSlice, ptr %t352, i32 0, i32 0 + %t356 = load i32, ptr %t353 + %t357 = load i32, ptr %t354 + %t358 = icmp sge i32 %t356, %t357 + br i1 %t358, label %grow92, label %put93 +grow92: + %t359 = mul i32 %t357, 2 + %t360 = icmp eq i32 %t357, 0 + %t361 = select i1 %t360, i32 8, i32 %t359 + %t362 = getelementptr ptr, ptr null, i32 1 + %t363 = ptrtoint ptr %t362 to i64 + %t364 = zext i32 %t361 to i64 + %t365 = mul i64 %t364, %t363 + %t366 = load ptr, ptr %t355 + %t367 = call ptr @realloc(ptr %t366, i64 %t365) + store ptr %t367, ptr %t355 + store i32 %t361, ptr %t354 + br label %put93 +put93: + %t368 = load ptr, ptr %t290 + %t369 = load ptr, ptr %t355 + %t370 = getelementptr inbounds ptr, ptr %t369, i32 %t356 + store ptr %t368, ptr %t370 + %t371 = add i32 %t356, 1 + store i32 %t371, ptr %t353 + br label %wcond73 +wend75: + call void @fn_eat_op(ptr @.str77) + %t372 = load ptr, ptr %t282 + store ptr %t372, ptr %retval + br label %ret +ifend72: + br label %ifend2 +ifend2: + %t373 = call ptr @fn_expr() + store ptr %t373, ptr %t374 + %t379 = call i32 @fn_is_op(ptr @.str78) + %t380 = icmp ne i32 %t379, 0 + %t381 = zext i1 %t380 to i32 + store i32 %t381, ptr %t378 + br i1 %t380, label %scend95, label %sc94 +sc94: + %t382 = call i32 @fn_is_op(ptr @.str79) + %t383 = icmp ne i32 %t382, 0 + %t384 = zext i1 %t383 to i32 + store i32 %t384, ptr %t378 + br label %scend95 +scend95: + %t385 = load i32, ptr %t378 + %t386 = icmp ne i32 %t385, 0 + %t387 = zext i1 %t386 to i32 + store i32 %t387, ptr %t377 + br i1 %t386, label %scend97, label %sc96 +sc96: + %t388 = call i32 @fn_is_op(ptr @.str80) + %t389 = icmp ne i32 %t388, 0 + %t390 = zext i1 %t389 to i32 + store i32 %t390, ptr %t377 + br label %scend97 +scend97: + %t391 = load i32, ptr %t377 + %t392 = icmp ne i32 %t391, 0 + %t393 = zext i1 %t392 to i32 + store i32 %t393, ptr %t376 + br i1 %t392, label %scend99, label %sc98 +sc98: + %t394 = call i32 @fn_is_op(ptr @.str81) + %t395 = icmp ne i32 %t394, 0 + %t396 = zext i1 %t395 to i32 + store i32 %t396, ptr %t376 + br label %scend99 +scend99: + %t397 = load i32, ptr %t376 + %t398 = icmp ne i32 %t397, 0 + %t399 = zext i1 %t398 to i32 + store i32 %t399, ptr %t375 + br i1 %t398, label %scend101, label %sc100 +sc100: + %t400 = call i32 @fn_is_op(ptr @.str82) + %t401 = icmp ne i32 %t400, 0 + %t402 = zext i1 %t401 to i32 + store i32 %t402, ptr %t375 + br label %scend101 +scend101: + %t403 = load i32, ptr %t375 + %t404 = icmp ne i32 %t403, 0 + br i1 %t404, label %then102, label %ifend104 +then102: + %t405 = call ptr @fn_node(i32 11) + store ptr %t405, ptr %t406 + %t407 = load ptr, ptr %t406 + %t408 = getelementptr inbounds %Str_Node, ptr %t407, i32 0, i32 1 + %t409 = load ptr, ptr @g_toks + %t410 = getelementptr inbounds %LSlice, ptr %t409, i32 0, i32 0 + %t411 = load ptr, ptr %t410 + %t412 = load i32, ptr @g_pi + %t413 = getelementptr inbounds ptr, ptr %t411, i32 %t412 + %t414 = load ptr, ptr %t413 + %t415 = getelementptr inbounds %Str_Tok, ptr %t414, i32 0, i32 1 + %t416 = load ptr, ptr %t415 + store ptr %t416, ptr %t408 + %t417 = load i32, ptr @g_pi + %t418 = add i32 %t417, 1 + store i32 %t418, ptr @g_pi + %t419 = load ptr, ptr %t406 + %t420 = getelementptr inbounds %Str_Node, ptr %t419, i32 0, i32 4 + %t421 = load ptr, ptr %t374 + store ptr %t421, ptr %t420 + %t422 = load ptr, ptr %t406 + %t423 = getelementptr inbounds %Str_Node, ptr %t422, i32 0, i32 5 + %t424 = call ptr @fn_expr() + store ptr %t424, ptr %t423 + %t425 = load ptr, ptr %t406 + store ptr %t425, ptr %retval + br label %ret +ifend104: + %t426 = call ptr @fn_node(i32 16) + store ptr %t426, ptr %t427 + %t428 = load ptr, ptr %t427 + %t429 = getelementptr inbounds %Str_Node, ptr %t428, i32 0, i32 4 + %t430 = load ptr, ptr %t374 + store ptr %t430, ptr %t429 + %t431 = load ptr, ptr %t427 + store ptr %t431, ptr %retval + br label %ret +ret: + %t432 = load ptr, ptr %retval + ret ptr %t432 +} + +define ptr @fn_parse_struct() { +entry: + %retval = alloca ptr + %t3 = alloca ptr + %t11 = alloca ptr + %t0 = load i32, ptr @g_pi + %t1 = add i32 %t0, 1 + store i32 %t1, ptr @g_pi + %t2 = call ptr @fn_node(i32 0) + store ptr %t2, ptr %t3 + %t4 = load ptr, ptr %t3 + %t5 = getelementptr inbounds %Str_Node, ptr %t4, i32 0, i32 1 + %t6 = call ptr @fn_eat_id() + store ptr %t6, ptr %t5 + call void @fn_skipnl() + call void @fn_eat_op(ptr @.str83) + br label %wcond0 +wcond0: + %t7 = icmp ne i32 1, 0 + br i1 %t7, label %wbody1, label %wend2 +wbody1: + call void @fn_skipnl() + %t8 = call i32 @fn_is_op(ptr @.str84) + %t9 = icmp ne i32 %t8, 0 + br i1 %t9, label %then3, label %ifend5 +then3: + br label %wend2 +ifend5: + %t10 = call ptr @fn_node(i32 1) + store ptr %t10, ptr %t11 + %t12 = load ptr, ptr %t11 + %t13 = getelementptr inbounds %Str_Node, ptr %t12, i32 0, i32 1 + %t14 = call ptr @fn_eat_id() + store ptr %t14, ptr %t13 + call void @fn_eat_op(ptr @.str85) + %t15 = load ptr, ptr %t11 + %t16 = getelementptr inbounds %Str_Node, ptr %t15, i32 0, i32 3 + %t17 = call ptr @fn_ptype() + store ptr %t17, ptr %t16 + %t18 = call i32 @fn_is_op(ptr @.str86) + %t19 = icmp ne i32 %t18, 0 + br i1 %t19, label %then6, label %ifend8 +then6: + %t20 = load i32, ptr @g_pi + %t21 = add i32 %t20, 1 + store i32 %t21, ptr @g_pi + %t22 = load ptr, ptr %t11 + %t23 = getelementptr inbounds %Str_Node, ptr %t22, i32 0, i32 4 + %t24 = call ptr @fn_expr() + store ptr %t24, ptr %t23 + br label %ifend8 +ifend8: + %t25 = load ptr, ptr %t3 + %t26 = getelementptr inbounds %Str_Node, ptr %t25, i32 0, i32 7 + %t27 = load ptr, ptr %t26 + %t28 = getelementptr inbounds %LSlice, ptr %t27, i32 0, i32 1 + %t29 = getelementptr inbounds %LSlice, ptr %t27, i32 0, i32 2 + %t30 = getelementptr inbounds %LSlice, ptr %t27, i32 0, i32 0 + %t31 = load i32, ptr %t28 + %t32 = load i32, ptr %t29 + %t33 = icmp sge i32 %t31, %t32 + br i1 %t33, label %grow9, label %put10 +grow9: + %t34 = mul i32 %t32, 2 + %t35 = icmp eq i32 %t32, 0 + %t36 = select i1 %t35, i32 8, i32 %t34 + %t37 = getelementptr ptr, ptr null, i32 1 + %t38 = ptrtoint ptr %t37 to i64 + %t39 = zext i32 %t36 to i64 + %t40 = mul i64 %t39, %t38 + %t41 = load ptr, ptr %t30 + %t42 = call ptr @realloc(ptr %t41, i64 %t40) + store ptr %t42, ptr %t30 + store i32 %t36, ptr %t29 + br label %put10 +put10: + %t43 = load ptr, ptr %t11 + %t44 = load ptr, ptr %t30 + %t45 = getelementptr inbounds ptr, ptr %t44, i32 %t31 + store ptr %t43, ptr %t45 + %t46 = add i32 %t31, 1 + store i32 %t46, ptr %t28 + %t47 = call i32 @fn_is_op(ptr @.str87) + %t48 = icmp ne i32 %t47, 0 + br i1 %t48, label %then11, label %ifend13 +then11: + %t49 = load i32, ptr @g_pi + %t50 = add i32 %t49, 1 + store i32 %t50, ptr @g_pi + br label %ifend13 +ifend13: + br label %wcond0 +wend2: + call void @fn_eat_op(ptr @.str88) + %t51 = load ptr, ptr %t3 + store ptr %t51, ptr %retval + br label %ret +ret: + %t52 = load ptr, ptr %retval + ret ptr %t52 +} + +define ptr @fn_parse_var() { +entry: + %retval = alloca ptr + %t3 = alloca ptr + %t0 = load i32, ptr @g_pi + %t1 = add i32 %t0, 1 + store i32 %t1, ptr @g_pi + %t2 = call ptr @fn_node(i32 2) + store ptr %t2, ptr %t3 + %t4 = load ptr, ptr %t3 + %t5 = getelementptr inbounds %Str_Node, ptr %t4, i32 0, i32 1 + %t6 = call ptr @fn_eat_id() + store ptr %t6, ptr %t5 + call void @fn_eat_op(ptr @.str89) + %t7 = load ptr, ptr %t3 + %t8 = getelementptr inbounds %Str_Node, ptr %t7, i32 0, i32 3 + %t9 = call ptr @fn_ptype() + store ptr %t9, ptr %t8 + %t10 = call i32 @fn_is_op(ptr @.str90) + %t11 = icmp ne i32 %t10, 0 + br i1 %t11, label %then0, label %ifend2 +then0: + %t12 = load i32, ptr @g_pi + %t13 = add i32 %t12, 1 + store i32 %t13, ptr @g_pi + %t14 = load ptr, ptr %t3 + %t15 = getelementptr inbounds %Str_Node, ptr %t14, i32 0, i32 4 + %t16 = call ptr @fn_expr() + store ptr %t16, ptr %t15 + br label %ifend2 +ifend2: + %t17 = load ptr, ptr %t3 + store ptr %t17, ptr %retval + br label %ret +ret: + %t18 = load ptr, ptr %retval + ret ptr %t18 +} + +define ptr @fn_parse_const() { +entry: + %retval = alloca ptr + %t3 = alloca ptr + %t0 = load i32, ptr @g_pi + %t1 = add i32 %t0, 1 + store i32 %t1, ptr @g_pi + %t2 = call ptr @fn_node(i32 3) + store ptr %t2, ptr %t3 + %t4 = load ptr, ptr %t3 + %t5 = getelementptr inbounds %Str_Node, ptr %t4, i32 0, i32 1 + %t6 = call ptr @fn_eat_id() + store ptr %t6, ptr %t5 + call void @fn_eat_op(ptr @.str91) + %t7 = load ptr, ptr %t3 + %t8 = getelementptr inbounds %Str_Node, ptr %t7, i32 0, i32 3 + %t9 = call ptr @fn_ptype() + store ptr %t9, ptr %t8 + call void @fn_eat_op(ptr @.str92) + %t10 = load ptr, ptr %t3 + %t11 = getelementptr inbounds %Str_Node, ptr %t10, i32 0, i32 4 + %t12 = call ptr @fn_expr() + store ptr %t12, ptr %t11 + %t13 = load ptr, ptr %t3 + store ptr %t13, ptr %retval + br label %ret +ret: + %t14 = load ptr, ptr %retval + ret ptr %t14 +} + +define ptr @fn_parse_fn() { +entry: + %retval = alloca ptr + %t3 = alloca ptr + %t12 = alloca ptr + %t0 = load i32, ptr @g_pi + %t1 = add i32 %t0, 1 + store i32 %t1, ptr @g_pi + %t2 = call ptr @fn_node(i32 4) + store ptr %t2, ptr %t3 + %t4 = load ptr, ptr %t3 + %t5 = getelementptr inbounds %Str_Node, ptr %t4, i32 0, i32 1 + %t6 = call ptr @fn_eat_id() + store ptr %t6, ptr %t5 + call void @fn_eat_op(ptr @.str93) + br label %wcond0 +wcond0: + %t7 = call i32 @fn_is_op(ptr @.str94) + %t8 = icmp eq i32 %t7, 0 + %t9 = zext i1 %t8 to i32 + %t10 = icmp ne i32 %t9, 0 + br i1 %t10, label %wbody1, label %wend2 +wbody1: + %t11 = call ptr @fn_node(i32 5) + store ptr %t11, ptr %t12 + %t13 = load ptr, ptr %t12 + %t14 = getelementptr inbounds %Str_Node, ptr %t13, i32 0, i32 1 + %t15 = call ptr @fn_eat_id() + store ptr %t15, ptr %t14 + call void @fn_eat_op(ptr @.str95) + %t16 = load ptr, ptr %t12 + %t17 = getelementptr inbounds %Str_Node, ptr %t16, i32 0, i32 3 + %t18 = call ptr @fn_ptype() + store ptr %t18, ptr %t17 + %t19 = load ptr, ptr %t3 + %t20 = getelementptr inbounds %Str_Node, ptr %t19, i32 0, i32 7 + %t21 = load ptr, ptr %t20 + %t22 = getelementptr inbounds %LSlice, ptr %t21, i32 0, i32 1 + %t23 = getelementptr inbounds %LSlice, ptr %t21, i32 0, i32 2 + %t24 = getelementptr inbounds %LSlice, ptr %t21, i32 0, i32 0 + %t25 = load i32, ptr %t22 + %t26 = load i32, ptr %t23 + %t27 = icmp sge i32 %t25, %t26 + br i1 %t27, label %grow3, label %put4 +grow3: + %t28 = mul i32 %t26, 2 + %t29 = icmp eq i32 %t26, 0 + %t30 = select i1 %t29, i32 8, i32 %t28 + %t31 = getelementptr ptr, ptr null, i32 1 + %t32 = ptrtoint ptr %t31 to i64 + %t33 = zext i32 %t30 to i64 + %t34 = mul i64 %t33, %t32 + %t35 = load ptr, ptr %t24 + %t36 = call ptr @realloc(ptr %t35, i64 %t34) + store ptr %t36, ptr %t24 + store i32 %t30, ptr %t23 + br label %put4 +put4: + %t37 = load ptr, ptr %t12 + %t38 = load ptr, ptr %t24 + %t39 = getelementptr inbounds ptr, ptr %t38, i32 %t25 + store ptr %t37, ptr %t39 + %t40 = add i32 %t25, 1 + store i32 %t40, ptr %t22 + %t41 = call i32 @fn_is_op(ptr @.str96) + %t42 = icmp ne i32 %t41, 0 + br i1 %t42, label %then5, label %ifend7 +then5: + %t43 = load i32, ptr @g_pi + %t44 = add i32 %t43, 1 + store i32 %t44, ptr @g_pi + br label %ifend7 +ifend7: + br label %wcond0 +wend2: + call void @fn_eat_op(ptr @.str97) + %t45 = load ptr, ptr %t3 + %t46 = getelementptr inbounds %Str_Node, ptr %t45, i32 0, i32 3 + store ptr @.str98, ptr %t46 + %t47 = call i32 @fn_is_op(ptr @.str99) + %t48 = icmp ne i32 %t47, 0 + br i1 %t48, label %then8, label %ifend10 +then8: + %t49 = load i32, ptr @g_pi + %t50 = add i32 %t49, 1 + store i32 %t50, ptr @g_pi + %t51 = load ptr, ptr %t3 + %t52 = getelementptr inbounds %Str_Node, ptr %t51, i32 0, i32 3 + %t53 = call ptr @fn_ptype() + store ptr %t53, ptr %t52 + br label %ifend10 +ifend10: + %t54 = load ptr, ptr %t3 + %t55 = getelementptr inbounds %Str_Node, ptr %t54, i32 0, i32 4 + %t56 = call ptr @fn_block() + store ptr %t56, ptr %t55 + %t57 = load ptr, ptr %t3 + store ptr %t57, ptr %retval + br label %ret +ret: + %t58 = load ptr, ptr %retval + ret ptr %t58 +} + +define ptr @fn_parse_main() { +entry: + %retval = alloca ptr + %t3 = alloca ptr + %t0 = load i32, ptr @g_pi + %t1 = add i32 %t0, 1 + store i32 %t1, ptr @g_pi + %t2 = call ptr @fn_node(i32 6) + store ptr %t2, ptr %t3 + %t4 = load ptr, ptr %t3 + %t5 = getelementptr inbounds %Str_Node, ptr %t4, i32 0, i32 4 + %t6 = call ptr @fn_block() + store ptr %t6, ptr %t5 + %t7 = load ptr, ptr %t3 + store ptr %t7, ptr %retval + br label %ret +ret: + %t8 = load ptr, ptr %retval + ret ptr %t8 +} + +define ptr @fn_dir_of(ptr %arg_path) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t2 = alloca i32 + %t3 = alloca i32 + store ptr %arg_path, ptr %t0 + %t1 = sub i32 0, 1 + store i32 %t1, ptr %t2 + store i32 0, ptr %t3 + br label %wcond0 +wcond0: + %t4 = load ptr, ptr %t0 + %t5 = load i32, ptr %t3 + %t6 = getelementptr inbounds i8, ptr %t4, i32 %t5 + %t7 = load i8, ptr %t6 + %t8 = zext i8 %t7 to i32 + %t9 = icmp ne i32 %t8, 0 + %t10 = zext i1 %t9 to i32 + %t11 = icmp ne i32 %t10, 0 + br i1 %t11, label %wbody1, label %wend2 +wbody1: + %t12 = load ptr, ptr %t0 + %t13 = load i32, ptr %t3 + %t14 = getelementptr inbounds i8, ptr %t12, i32 %t13 + %t15 = load i8, ptr %t14 + %t16 = zext i8 %t15 to i32 + %t17 = icmp eq i32 %t16, 47 + %t18 = zext i1 %t17 to i32 + %t19 = icmp ne i32 %t18, 0 + br i1 %t19, label %then3, label %ifend5 +then3: + %t20 = load i32, ptr %t3 + store i32 %t20, ptr %t2 + br label %ifend5 +ifend5: + %t21 = load i32, ptr %t3 + %t22 = add i32 %t21, 1 + store i32 %t22, ptr %t3 + br label %wcond0 +wend2: + %t23 = load i32, ptr %t2 + %t24 = icmp slt i32 %t23, 0 + %t25 = zext i1 %t24 to i32 + %t26 = icmp ne i32 %t25, 0 + br i1 %t26, label %then6, label %ifend8 +then6: + store ptr @.str100, ptr %retval + br label %ret +ifend8: + %t27 = load ptr, ptr %t0 + %t28 = load i32, ptr %t2 + %t29 = add i32 %t28, 1 + %t30 = call ptr @fn_substr(ptr %t27, i32 0, i32 %t29) + store ptr %t30, ptr %retval + br label %ret +ret: + %t31 = load ptr, ptr %retval + ret ptr %t31 +} + +define ptr @fn_path_join(ptr %arg_dir, ptr %arg_rel) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca ptr + store ptr %arg_dir, ptr %t0 + store ptr %arg_rel, ptr %t1 + %t2 = load ptr, ptr %t1 + %t3 = getelementptr inbounds i8, ptr %t2, i32 0 + %t4 = load i8, ptr %t3 + %t5 = zext i8 %t4 to i32 + %t6 = icmp eq i32 %t5, 47 + %t7 = zext i1 %t6 to i32 + %t8 = icmp ne i32 %t7, 0 + br i1 %t8, label %then0, label %ifend2 +then0: + %t9 = load ptr, ptr %t1 + store ptr %t9, ptr %retval + br label %ret +ifend2: + %t10 = load ptr, ptr %t0 + %t11 = load ptr, ptr %t1 + %t12 = call ptr @fn_sconcat(ptr %t10, ptr %t11) + store ptr %t12, ptr %retval + br label %ret +ret: + %t13 = load ptr, ptr %retval + ret ptr %t13 +} + +define i32 @fn_already_loaded(ptr %arg_full) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t1 = alloca i32 + store ptr %arg_full, ptr %t0 + store i32 0, ptr %t1 + br label %wcond0 +wcond0: + %t2 = load i32, ptr %t1 + %t3 = load ptr, ptr @g_loaded_paths + %t4 = getelementptr inbounds %LSlice, ptr %t3, i32 0, i32 1 + %t5 = load i32, ptr %t4 + %t6 = icmp slt i32 %t2, %t5 + %t7 = zext i1 %t6 to i32 + %t8 = icmp ne i32 %t7, 0 + br i1 %t8, label %wbody1, label %wend2 +wbody1: + %t9 = load ptr, ptr @g_loaded_paths + %t10 = getelementptr inbounds %LSlice, ptr %t9, i32 0, i32 0 + %t11 = load ptr, ptr %t10 + %t12 = load i32, ptr %t1 + %t13 = getelementptr inbounds ptr, ptr %t11, i32 %t12 + %t14 = load ptr, ptr %t13 + %t15 = load ptr, ptr %t0 + %t16 = call i32 @fn_streq(ptr %t14, ptr %t15) + %t17 = icmp ne i32 %t16, 0 + br i1 %t17, label %then3, label %ifend5 +then3: + store i32 1, ptr %retval + br label %ret +ifend5: + %t18 = load i32, ptr %t1 + %t19 = add i32 %t18, 1 + store i32 %t19, ptr %t1 + br label %wcond0 +wend2: + store i32 0, ptr %retval + br label %ret +ret: + %t20 = load i32, ptr %retval + ret i32 %t20 +} + +define void @fn_parse_one_decl() { +entry: + %t10 = alloca ptr + %t20 = alloca ptr + %t90 = alloca i32 + %t190 = alloca ptr + %t213 = alloca i32 + %t0 = call i32 @fn_is_id(ptr @.str101) + %t1 = icmp ne i32 %t0, 0 + br i1 %t1, label %then0, label %ifend2 +then0: + %t2 = load i32, ptr @g_pi + %t3 = add i32 %t2, 1 + store i32 %t3, ptr @g_pi + %t4 = load ptr, ptr @g_toks + %t5 = getelementptr inbounds %LSlice, ptr %t4, i32 0, i32 0 + %t6 = load ptr, ptr %t5 + %t7 = load i32, ptr @g_pi + %t8 = getelementptr inbounds ptr, ptr %t6, i32 %t7 + %t9 = load ptr, ptr %t8 + store ptr %t9, ptr %t10 + %t11 = load ptr, ptr %t10 + %t12 = getelementptr inbounds %Str_Tok, ptr %t11, i32 0, i32 0 + %t13 = load i32, ptr %t12 + %t14 = icmp ne i32 %t13, 2 + %t15 = zext i1 %t14 to i32 + %t16 = icmp ne i32 %t15, 0 + br i1 %t16, label %then3, label %ifend5 +then3: + call void @fn_perr(ptr @.str102) + br label %ifend5 +ifend5: + %t17 = load ptr, ptr %t10 + %t18 = getelementptr inbounds %Str_Tok, ptr %t17, i32 0, i32 1 + %t19 = load ptr, ptr %t18 + store ptr %t19, ptr %t20 + %t21 = load i32, ptr @g_pi + %t22 = add i32 %t21, 1 + store i32 %t22, ptr @g_pi + %t23 = load ptr, ptr %t20 + call void @fn_do_import(ptr %t23) + br label %ret +ifend2: + %t24 = call i32 @fn_is_id(ptr @.str103) + %t25 = icmp ne i32 %t24, 0 + br i1 %t25, label %then6, label %ifend8 +then6: + %t26 = load ptr, ptr @g_prog + %t27 = getelementptr inbounds %LSlice, ptr %t26, i32 0, i32 1 + %t28 = getelementptr inbounds %LSlice, ptr %t26, i32 0, i32 2 + %t29 = getelementptr inbounds %LSlice, ptr %t26, i32 0, i32 0 + %t30 = load i32, ptr %t27 + %t31 = load i32, ptr %t28 + %t32 = icmp sge i32 %t30, %t31 + br i1 %t32, label %grow9, label %put10 +grow9: + %t33 = mul i32 %t31, 2 + %t34 = icmp eq i32 %t31, 0 + %t35 = select i1 %t34, i32 8, i32 %t33 + %t36 = getelementptr ptr, ptr null, i32 1 + %t37 = ptrtoint ptr %t36 to i64 + %t38 = zext i32 %t35 to i64 + %t39 = mul i64 %t38, %t37 + %t40 = load ptr, ptr %t29 + %t41 = call ptr @realloc(ptr %t40, i64 %t39) + store ptr %t41, ptr %t29 + store i32 %t35, ptr %t28 + br label %put10 +put10: + %t42 = call ptr @fn_parse_struct() + %t43 = load ptr, ptr %t29 + %t44 = getelementptr inbounds ptr, ptr %t43, i32 %t30 + store ptr %t42, ptr %t44 + %t45 = add i32 %t30, 1 + store i32 %t45, ptr %t27 + br label %ret +ifend8: + %t46 = call i32 @fn_is_id(ptr @.str104) + %t47 = icmp ne i32 %t46, 0 + br i1 %t47, label %then11, label %ifend13 +then11: + %t48 = load ptr, ptr @g_prog + %t49 = getelementptr inbounds %LSlice, ptr %t48, i32 0, i32 1 + %t50 = getelementptr inbounds %LSlice, ptr %t48, i32 0, i32 2 + %t51 = getelementptr inbounds %LSlice, ptr %t48, i32 0, i32 0 + %t52 = load i32, ptr %t49 + %t53 = load i32, ptr %t50 + %t54 = icmp sge i32 %t52, %t53 + br i1 %t54, label %grow14, label %put15 +grow14: + %t55 = mul i32 %t53, 2 + %t56 = icmp eq i32 %t53, 0 + %t57 = select i1 %t56, i32 8, i32 %t55 + %t58 = getelementptr ptr, ptr null, i32 1 + %t59 = ptrtoint ptr %t58 to i64 + %t60 = zext i32 %t57 to i64 + %t61 = mul i64 %t60, %t59 + %t62 = load ptr, ptr %t51 + %t63 = call ptr @realloc(ptr %t62, i64 %t61) + store ptr %t63, ptr %t51 + store i32 %t57, ptr %t50 + br label %put15 +put15: + %t64 = call ptr @fn_parse_component() + %t65 = load ptr, ptr %t51 + %t66 = getelementptr inbounds ptr, ptr %t65, i32 %t52 + store ptr %t64, ptr %t66 + %t67 = add i32 %t52, 1 + store i32 %t67, ptr %t49 + br label %ret +ifend13: + %t68 = call i32 @fn_is_id(ptr @.str105) + %t69 = icmp ne i32 %t68, 0 + br i1 %t69, label %then16, label %ifend18 +then16: + %t70 = load ptr, ptr @g_prog + %t71 = getelementptr inbounds %LSlice, ptr %t70, i32 0, i32 1 + %t72 = getelementptr inbounds %LSlice, ptr %t70, i32 0, i32 2 + %t73 = getelementptr inbounds %LSlice, ptr %t70, i32 0, i32 0 + %t74 = load i32, ptr %t71 + %t75 = load i32, ptr %t72 + %t76 = icmp sge i32 %t74, %t75 + br i1 %t76, label %grow19, label %put20 +grow19: + %t77 = mul i32 %t75, 2 + %t78 = icmp eq i32 %t75, 0 + %t79 = select i1 %t78, i32 8, i32 %t77 + %t80 = getelementptr ptr, ptr null, i32 1 + %t81 = ptrtoint ptr %t80 to i64 + %t82 = zext i32 %t79 to i64 + %t83 = mul i64 %t82, %t81 + %t84 = load ptr, ptr %t73 + %t85 = call ptr @realloc(ptr %t84, i64 %t83) + store ptr %t85, ptr %t73 + store i32 %t79, ptr %t72 + br label %put20 +put20: + %t86 = call ptr @fn_parse_archetype() + %t87 = load ptr, ptr %t73 + %t88 = getelementptr inbounds ptr, ptr %t87, i32 %t74 + store ptr %t86, ptr %t88 + %t89 = add i32 %t74, 1 + store i32 %t89, ptr %t71 + br label %ret +ifend18: + %t91 = call i32 @fn_is_id(ptr @.str106) + %t92 = icmp ne i32 %t91, 0 + %t93 = zext i1 %t92 to i32 + store i32 %t93, ptr %t90 + br i1 %t92, label %scend22, label %sc21 +sc21: + %t94 = call i32 @fn_is_id(ptr @.str107) + %t95 = icmp ne i32 %t94, 0 + %t96 = zext i1 %t95 to i32 + store i32 %t96, ptr %t90 + br label %scend22 +scend22: + %t97 = load i32, ptr %t90 + %t98 = icmp ne i32 %t97, 0 + br i1 %t98, label %then23, label %ifend25 +then23: + %t99 = load ptr, ptr @g_prog + %t100 = getelementptr inbounds %LSlice, ptr %t99, i32 0, i32 1 + %t101 = getelementptr inbounds %LSlice, ptr %t99, i32 0, i32 2 + %t102 = getelementptr inbounds %LSlice, ptr %t99, i32 0, i32 0 + %t103 = load i32, ptr %t100 + %t104 = load i32, ptr %t101 + %t105 = icmp sge i32 %t103, %t104 + br i1 %t105, label %grow26, label %put27 +grow26: + %t106 = mul i32 %t104, 2 + %t107 = icmp eq i32 %t104, 0 + %t108 = select i1 %t107, i32 8, i32 %t106 + %t109 = getelementptr ptr, ptr null, i32 1 + %t110 = ptrtoint ptr %t109 to i64 + %t111 = zext i32 %t108 to i64 + %t112 = mul i64 %t111, %t110 + %t113 = load ptr, ptr %t102 + %t114 = call ptr @realloc(ptr %t113, i64 %t112) + store ptr %t114, ptr %t102 + store i32 %t108, ptr %t101 + br label %put27 +put27: + %t115 = call ptr @fn_parse_system() + %t116 = load ptr, ptr %t102 + %t117 = getelementptr inbounds ptr, ptr %t116, i32 %t103 + store ptr %t115, ptr %t117 + %t118 = add i32 %t103, 1 + store i32 %t118, ptr %t100 + br label %ret +ifend25: + %t119 = call i32 @fn_is_id(ptr @.str108) + %t120 = icmp ne i32 %t119, 0 + br i1 %t120, label %then28, label %ifend30 +then28: + %t121 = load ptr, ptr @g_prog + %t122 = getelementptr inbounds %LSlice, ptr %t121, i32 0, i32 1 + %t123 = getelementptr inbounds %LSlice, ptr %t121, i32 0, i32 2 + %t124 = getelementptr inbounds %LSlice, ptr %t121, i32 0, i32 0 + %t125 = load i32, ptr %t122 + %t126 = load i32, ptr %t123 + %t127 = icmp sge i32 %t125, %t126 + br i1 %t127, label %grow31, label %put32 +grow31: + %t128 = mul i32 %t126, 2 + %t129 = icmp eq i32 %t126, 0 + %t130 = select i1 %t129, i32 8, i32 %t128 + %t131 = getelementptr ptr, ptr null, i32 1 + %t132 = ptrtoint ptr %t131 to i64 + %t133 = zext i32 %t130 to i64 + %t134 = mul i64 %t133, %t132 + %t135 = load ptr, ptr %t124 + %t136 = call ptr @realloc(ptr %t135, i64 %t134) + store ptr %t136, ptr %t124 + store i32 %t130, ptr %t123 + br label %put32 +put32: + %t137 = call ptr @fn_parse_ui() + %t138 = load ptr, ptr %t124 + %t139 = getelementptr inbounds ptr, ptr %t138, i32 %t125 + store ptr %t137, ptr %t139 + %t140 = add i32 %t125, 1 + store i32 %t140, ptr %t122 + br label %ret +ifend30: + %t141 = call i32 @fn_is_id(ptr @.str109) + %t142 = icmp ne i32 %t141, 0 + br i1 %t142, label %then33, label %ifend35 +then33: + %t143 = load ptr, ptr @g_prog + %t144 = getelementptr inbounds %LSlice, ptr %t143, i32 0, i32 1 + %t145 = getelementptr inbounds %LSlice, ptr %t143, i32 0, i32 2 + %t146 = getelementptr inbounds %LSlice, ptr %t143, i32 0, i32 0 + %t147 = load i32, ptr %t144 + %t148 = load i32, ptr %t145 + %t149 = icmp sge i32 %t147, %t148 + br i1 %t149, label %grow36, label %put37 +grow36: + %t150 = mul i32 %t148, 2 + %t151 = icmp eq i32 %t148, 0 + %t152 = select i1 %t151, i32 8, i32 %t150 + %t153 = getelementptr ptr, ptr null, i32 1 + %t154 = ptrtoint ptr %t153 to i64 + %t155 = zext i32 %t152 to i64 + %t156 = mul i64 %t155, %t154 + %t157 = load ptr, ptr %t146 + %t158 = call ptr @realloc(ptr %t157, i64 %t156) + store ptr %t158, ptr %t146 + store i32 %t152, ptr %t145 + br label %put37 +put37: + %t159 = call ptr @fn_parse_var() + %t160 = load ptr, ptr %t146 + %t161 = getelementptr inbounds ptr, ptr %t160, i32 %t147 + store ptr %t159, ptr %t161 + %t162 = add i32 %t147, 1 + store i32 %t162, ptr %t144 + br label %ret +ifend35: + %t163 = call i32 @fn_is_id(ptr @.str110) + %t164 = icmp ne i32 %t163, 0 + br i1 %t164, label %then38, label %ifend40 +then38: + %t165 = load ptr, ptr @g_prog + %t166 = getelementptr inbounds %LSlice, ptr %t165, i32 0, i32 1 + %t167 = getelementptr inbounds %LSlice, ptr %t165, i32 0, i32 2 + %t168 = getelementptr inbounds %LSlice, ptr %t165, i32 0, i32 0 + %t169 = load i32, ptr %t166 + %t170 = load i32, ptr %t167 + %t171 = icmp sge i32 %t169, %t170 + br i1 %t171, label %grow41, label %put42 +grow41: + %t172 = mul i32 %t170, 2 + %t173 = icmp eq i32 %t170, 0 + %t174 = select i1 %t173, i32 8, i32 %t172 + %t175 = getelementptr ptr, ptr null, i32 1 + %t176 = ptrtoint ptr %t175 to i64 + %t177 = zext i32 %t174 to i64 + %t178 = mul i64 %t177, %t176 + %t179 = load ptr, ptr %t168 + %t180 = call ptr @realloc(ptr %t179, i64 %t178) + store ptr %t180, ptr %t168 + store i32 %t174, ptr %t167 + br label %put42 +put42: + %t181 = call ptr @fn_parse_const() + %t182 = load ptr, ptr %t168 + %t183 = getelementptr inbounds ptr, ptr %t182, i32 %t169 + store ptr %t181, ptr %t183 + %t184 = add i32 %t169, 1 + store i32 %t184, ptr %t166 + br label %ret +ifend40: + %t185 = call i32 @fn_is_id(ptr @.str111) + %t186 = icmp ne i32 %t185, 0 + br i1 %t186, label %then43, label %ifend45 +then43: + %t187 = load i32, ptr @g_pi + %t188 = add i32 %t187, 1 + store i32 %t188, ptr @g_pi + %t189 = call ptr @fn_parse_fn() + store ptr %t189, ptr %t190 + %t191 = load ptr, ptr %t190 + %t192 = getelementptr inbounds %Str_Node, ptr %t191, i32 0, i32 2 + store i32 1, ptr %t192 + %t193 = load ptr, ptr @g_prog + %t194 = getelementptr inbounds %LSlice, ptr %t193, i32 0, i32 1 + %t195 = getelementptr inbounds %LSlice, ptr %t193, i32 0, i32 2 + %t196 = getelementptr inbounds %LSlice, ptr %t193, i32 0, i32 0 + %t197 = load i32, ptr %t194 + %t198 = load i32, ptr %t195 + %t199 = icmp sge i32 %t197, %t198 + br i1 %t199, label %grow46, label %put47 +grow46: + %t200 = mul i32 %t198, 2 + %t201 = icmp eq i32 %t198, 0 + %t202 = select i1 %t201, i32 8, i32 %t200 + %t203 = getelementptr ptr, ptr null, i32 1 + %t204 = ptrtoint ptr %t203 to i64 + %t205 = zext i32 %t202 to i64 + %t206 = mul i64 %t205, %t204 + %t207 = load ptr, ptr %t196 + %t208 = call ptr @realloc(ptr %t207, i64 %t206) + store ptr %t208, ptr %t196 + store i32 %t202, ptr %t195 + br label %put47 +put47: + %t209 = load ptr, ptr %t190 + %t210 = load ptr, ptr %t196 + %t211 = getelementptr inbounds ptr, ptr %t210, i32 %t197 + store ptr %t209, ptr %t211 + %t212 = add i32 %t197, 1 + store i32 %t212, ptr %t194 + br label %ret +ifend45: + %t214 = call i32 @fn_is_id(ptr @.str112) + %t215 = icmp ne i32 %t214, 0 + %t216 = zext i1 %t215 to i32 + store i32 %t216, ptr %t213 + br i1 %t215, label %scend49, label %sc48 +sc48: + %t217 = call i32 @fn_is_id(ptr @.str113) + %t218 = icmp ne i32 %t217, 0 + %t219 = zext i1 %t218 to i32 + store i32 %t219, ptr %t213 + br label %scend49 +scend49: + %t220 = load i32, ptr %t213 + %t221 = icmp ne i32 %t220, 0 + br i1 %t221, label %then50, label %ifend52 +then50: + %t222 = call i32 @fn_is_id(ptr @.str114) + %t223 = icmp ne i32 %t222, 0 + br i1 %t223, label %then53, label %ifend55 +then53: + %t224 = load i32, ptr @g_pi + %t225 = add i32 %t224, 1 + store i32 %t225, ptr @g_pi + br label %ifend55 +ifend55: + %t226 = load ptr, ptr @g_prog + %t227 = getelementptr inbounds %LSlice, ptr %t226, i32 0, i32 1 + %t228 = getelementptr inbounds %LSlice, ptr %t226, i32 0, i32 2 + %t229 = getelementptr inbounds %LSlice, ptr %t226, i32 0, i32 0 + %t230 = load i32, ptr %t227 + %t231 = load i32, ptr %t228 + %t232 = icmp sge i32 %t230, %t231 + br i1 %t232, label %grow56, label %put57 +grow56: + %t233 = mul i32 %t231, 2 + %t234 = icmp eq i32 %t231, 0 + %t235 = select i1 %t234, i32 8, i32 %t233 + %t236 = getelementptr ptr, ptr null, i32 1 + %t237 = ptrtoint ptr %t236 to i64 + %t238 = zext i32 %t235 to i64 + %t239 = mul i64 %t238, %t237 + %t240 = load ptr, ptr %t229 + %t241 = call ptr @realloc(ptr %t240, i64 %t239) + store ptr %t241, ptr %t229 + store i32 %t235, ptr %t228 + br label %put57 +put57: + %t242 = call ptr @fn_parse_fn() + %t243 = load ptr, ptr %t229 + %t244 = getelementptr inbounds ptr, ptr %t243, i32 %t230 + store ptr %t242, ptr %t244 + %t245 = add i32 %t230, 1 + store i32 %t245, ptr %t227 + br label %ret +ifend52: + %t246 = call i32 @fn_is_id(ptr @.str115) + %t247 = icmp ne i32 %t246, 0 + br i1 %t247, label %then58, label %ifend60 +then58: + %t248 = load ptr, ptr @g_prog + %t249 = getelementptr inbounds %LSlice, ptr %t248, i32 0, i32 1 + %t250 = getelementptr inbounds %LSlice, ptr %t248, i32 0, i32 2 + %t251 = getelementptr inbounds %LSlice, ptr %t248, i32 0, i32 0 + %t252 = load i32, ptr %t249 + %t253 = load i32, ptr %t250 + %t254 = icmp sge i32 %t252, %t253 + br i1 %t254, label %grow61, label %put62 +grow61: + %t255 = mul i32 %t253, 2 + %t256 = icmp eq i32 %t253, 0 + %t257 = select i1 %t256, i32 8, i32 %t255 + %t258 = getelementptr ptr, ptr null, i32 1 + %t259 = ptrtoint ptr %t258 to i64 + %t260 = zext i32 %t257 to i64 + %t261 = mul i64 %t260, %t259 + %t262 = load ptr, ptr %t251 + %t263 = call ptr @realloc(ptr %t262, i64 %t261) + store ptr %t263, ptr %t251 + store i32 %t257, ptr %t250 + br label %put62 +put62: + %t264 = call ptr @fn_parse_extern() + %t265 = load ptr, ptr %t251 + %t266 = getelementptr inbounds ptr, ptr %t265, i32 %t252 + store ptr %t264, ptr %t266 + %t267 = add i32 %t252, 1 + store i32 %t267, ptr %t249 + br label %ret +ifend60: + %t268 = call i32 @fn_is_id(ptr @.str116) + %t269 = icmp ne i32 %t268, 0 + br i1 %t269, label %then63, label %ifend65 +then63: + %t270 = load ptr, ptr @g_prog + %t271 = getelementptr inbounds %LSlice, ptr %t270, i32 0, i32 1 + %t272 = getelementptr inbounds %LSlice, ptr %t270, i32 0, i32 2 + %t273 = getelementptr inbounds %LSlice, ptr %t270, i32 0, i32 0 + %t274 = load i32, ptr %t271 + %t275 = load i32, ptr %t272 + %t276 = icmp sge i32 %t274, %t275 + br i1 %t276, label %grow66, label %put67 +grow66: + %t277 = mul i32 %t275, 2 + %t278 = icmp eq i32 %t275, 0 + %t279 = select i1 %t278, i32 8, i32 %t277 + %t280 = getelementptr ptr, ptr null, i32 1 + %t281 = ptrtoint ptr %t280 to i64 + %t282 = zext i32 %t279 to i64 + %t283 = mul i64 %t282, %t281 + %t284 = load ptr, ptr %t273 + %t285 = call ptr @realloc(ptr %t284, i64 %t283) + store ptr %t285, ptr %t273 + store i32 %t279, ptr %t272 + br label %put67 +put67: + %t286 = call ptr @fn_parse_main() + %t287 = load ptr, ptr %t273 + %t288 = getelementptr inbounds ptr, ptr %t287, i32 %t274 + store ptr %t286, ptr %t288 + %t289 = add i32 %t274, 1 + store i32 %t289, ptr %t271 + br label %ret +ifend65: + call void @fn_perr(ptr @.str117) + br label %ret +ret: + ret void +} + +define void @fn_do_import(ptr %arg_rel) { +entry: + %t0 = alloca ptr + %t4 = alloca ptr + %t30 = alloca ptr + %t38 = alloca ptr + %t40 = alloca i32 + %t42 = alloca ptr + store ptr %arg_rel, ptr %t0 + %t1 = load ptr, ptr @g_cur_dir + %t2 = load ptr, ptr %t0 + %t3 = call ptr @fn_path_join(ptr %t1, ptr %t2) + store ptr %t3, ptr %t4 + %t5 = load ptr, ptr %t4 + %t6 = call i32 @fn_already_loaded(ptr %t5) + %t7 = icmp ne i32 %t6, 0 + br i1 %t7, label %then0, label %ifend2 +then0: + br label %ret +ifend2: + %t8 = load ptr, ptr @g_loaded_paths + %t9 = getelementptr inbounds %LSlice, ptr %t8, i32 0, i32 1 + %t10 = getelementptr inbounds %LSlice, ptr %t8, i32 0, i32 2 + %t11 = getelementptr inbounds %LSlice, ptr %t8, i32 0, i32 0 + %t12 = load i32, ptr %t9 + %t13 = load i32, ptr %t10 + %t14 = icmp sge i32 %t12, %t13 + br i1 %t14, label %grow3, label %put4 +grow3: + %t15 = mul i32 %t13, 2 + %t16 = icmp eq i32 %t13, 0 + %t17 = select i1 %t16, i32 8, i32 %t15 + %t18 = getelementptr ptr, ptr null, i32 1 + %t19 = ptrtoint ptr %t18 to i64 + %t20 = zext i32 %t17 to i64 + %t21 = mul i64 %t20, %t19 + %t22 = load ptr, ptr %t11 + %t23 = call ptr @realloc(ptr %t22, i64 %t21) + store ptr %t23, ptr %t11 + store i32 %t17, ptr %t10 + br label %put4 +put4: + %t24 = load ptr, ptr %t4 + %t25 = load ptr, ptr %t11 + %t26 = getelementptr inbounds ptr, ptr %t25, i32 %t12 + store ptr %t24, ptr %t26 + %t27 = add i32 %t12, 1 + store i32 %t27, ptr %t9 + %t28 = load ptr, ptr %t4 + %t29 = call ptr @fn_read_file(ptr %t28) + store ptr %t29, ptr %t30 + %t31 = load ptr, ptr %t30 + %t32 = icmp eq ptr %t31, null + %t33 = zext i1 %t32 to i32 + %t34 = icmp ne i32 %t33, 0 + br i1 %t34, label %then5, label %ifend7 +then5: + %t35 = load ptr, ptr %t4 + %t36 = call ptr @fn_sconcat(ptr @.str118, ptr %t35) + call void @fn_perr(ptr %t36) + br label %ifend7 +ifend7: + %t37 = load ptr, ptr @g_toks + store ptr %t37, ptr %t38 + %t39 = load i32, ptr @g_pi + store i32 %t39, ptr %t40 + %t41 = load ptr, ptr @g_cur_dir + store ptr %t41, ptr %t42 + %t43 = load ptr, ptr %t4 + %t44 = call ptr @fn_dir_of(ptr %t43) + store ptr %t44, ptr @g_cur_dir + %t45 = load ptr, ptr %t30 + call void @fn_lex(ptr %t45) + store i32 0, ptr @g_pi + call void @fn_skipnl() + br label %wcond8 +wcond8: + %t46 = load ptr, ptr @g_toks + %t47 = getelementptr inbounds %LSlice, ptr %t46, i32 0, i32 0 + %t48 = load ptr, ptr %t47 + %t49 = load i32, ptr @g_pi + %t50 = getelementptr inbounds ptr, ptr %t48, i32 %t49 + %t51 = load ptr, ptr %t50 + %t52 = getelementptr inbounds %Str_Tok, ptr %t51, i32 0, i32 0 + %t53 = load i32, ptr %t52 + %t54 = icmp ne i32 %t53, 5 + %t55 = zext i1 %t54 to i32 + %t56 = icmp ne i32 %t55, 0 + br i1 %t56, label %wbody9, label %wend10 +wbody9: + call void @fn_parse_one_decl() + call void @fn_skipnl() + br label %wcond8 +wend10: + %t57 = load ptr, ptr %t38 + store ptr %t57, ptr @g_toks + %t58 = load i32, ptr %t40 + store i32 %t58, ptr @g_pi + %t59 = load ptr, ptr %t42 + store ptr %t59, ptr @g_cur_dir + br label %ret +ret: + ret void +} + +define void @fn_maybe_splice_runtime() { +entry: + %t5 = alloca ptr + %t0 = call i32 @fn_has_ecs() + %t1 = icmp eq i32 %t0, 0 + %t2 = zext i1 %t1 to i32 + %t3 = icmp ne i32 %t2, 0 + br i1 %t3, label %then0, label %ifend2 +then0: + br label %ret +ifend2: + %t4 = load ptr, ptr @g_cur_dir + store ptr %t4, ptr %t5 + store ptr @.str119, ptr @g_cur_dir + call void @fn_do_import(ptr @.str120) + %t6 = load ptr, ptr %t5 + store ptr %t6, ptr @g_cur_dir + br label %ret +ret: + ret void +} + +define void @fn_parse_program() { +entry: + %t22 = alloca ptr + %t26 = alloca ptr + %t30 = alloca i32 + %t0 = getelementptr %LSlice, ptr null, i32 1 + %t1 = ptrtoint ptr %t0 to i64 + %t2 = call ptr @malloc(i64 %t1) + %t3 = getelementptr inbounds %LSlice, ptr %t2, i32 0, i32 0 + store ptr null, ptr %t3 + %t4 = getelementptr inbounds %LSlice, ptr %t2, i32 0, i32 1 + store i32 0, ptr %t4 + %t5 = getelementptr inbounds %LSlice, ptr %t2, i32 0, i32 2 + store i32 0, ptr %t5 + store ptr %t2, ptr @g_prog + %t6 = getelementptr %LSlice, ptr null, i32 1 + %t7 = ptrtoint ptr %t6 to i64 + %t8 = call ptr @malloc(i64 %t7) + %t9 = getelementptr inbounds %LSlice, ptr %t8, i32 0, i32 0 + store ptr null, ptr %t9 + %t10 = getelementptr inbounds %LSlice, ptr %t8, i32 0, i32 1 + store i32 0, ptr %t10 + %t11 = getelementptr inbounds %LSlice, ptr %t8, i32 0, i32 2 + store i32 0, ptr %t11 + store ptr %t8, ptr @g_loaded_paths + call void @fn_skipnl() + store ptr @.str121, ptr @g_g_game_name + br label %wcond0 +wcond0: + %t12 = call i32 @fn_is_id(ptr @.str122) + %t13 = icmp ne i32 %t12, 0 + br i1 %t13, label %wbody1, label %wend2 +wbody1: + %t14 = load i32, ptr @g_pi + %t15 = add i32 %t14, 1 + store i32 %t15, ptr @g_pi + %t16 = load ptr, ptr @g_toks + %t17 = getelementptr inbounds %LSlice, ptr %t16, i32 0, i32 0 + %t18 = load ptr, ptr %t17 + %t19 = load i32, ptr @g_pi + %t20 = getelementptr inbounds ptr, ptr %t18, i32 %t19 + %t21 = load ptr, ptr %t20 + store ptr %t21, ptr %t22 + %t23 = load ptr, ptr %t22 + %t24 = getelementptr inbounds %Str_Tok, ptr %t23, i32 0, i32 1 + %t25 = load ptr, ptr %t24 + store ptr %t25, ptr %t26 + %t27 = load i32, ptr @g_pi + %t28 = add i32 %t27, 1 + store i32 %t28, ptr @g_pi + %t29 = load ptr, ptr %t26 + call void @fn_do_import(ptr %t29) + call void @fn_skipnl() + br label %wcond0 +wend2: + %t31 = call i32 @fn_is_id(ptr @.str123) + %t32 = icmp ne i32 %t31, 0 + %t33 = zext i1 %t32 to i32 + store i32 %t33, ptr %t30 + br i1 %t32, label %scend4, label %sc3 +sc3: + %t34 = call i32 @fn_is_id(ptr @.str124) + %t35 = icmp ne i32 %t34, 0 + %t36 = zext i1 %t35 to i32 + store i32 %t36, ptr %t30 + br label %scend4 +scend4: + %t37 = load i32, ptr %t30 + %t38 = icmp ne i32 %t37, 0 + br i1 %t38, label %then5, label %ifend7 +then5: + %t39 = load i32, ptr @g_pi + %t40 = add i32 %t39, 1 + store i32 %t40, ptr @g_pi + %t41 = call ptr @fn_eat_id() + store ptr %t41, ptr @g_g_game_name + call void @fn_skipnl() + call void @fn_eat_op(ptr @.str125) + br label %ifend7 +ifend7: + br label %wcond8 +wcond8: + %t42 = icmp ne i32 1, 0 + br i1 %t42, label %wbody9, label %wend10 +wbody9: + call void @fn_skipnl() + %t43 = load ptr, ptr @g_toks + %t44 = getelementptr inbounds %LSlice, ptr %t43, i32 0, i32 0 + %t45 = load ptr, ptr %t44 + %t46 = load i32, ptr @g_pi + %t47 = getelementptr inbounds ptr, ptr %t45, i32 %t46 + %t48 = load ptr, ptr %t47 + %t49 = getelementptr inbounds %Str_Tok, ptr %t48, i32 0, i32 0 + %t50 = load i32, ptr %t49 + %t51 = icmp eq i32 %t50, 5 + %t52 = zext i1 %t51 to i32 + %t53 = icmp ne i32 %t52, 0 + br i1 %t53, label %then11, label %ifend13 +then11: + br label %wend10 +ifend13: + %t54 = call i32 @fn_is_op(ptr @.str126) + %t55 = icmp ne i32 %t54, 0 + br i1 %t55, label %then14, label %ifend16 +then14: + br label %wend10 +ifend16: + call void @fn_parse_one_decl() + br label %wcond8 +wend10: + br label %ret +ret: + ret void +} + +define ptr @fn_parse_component() { +entry: + %retval = alloca ptr + %t3 = alloca ptr + %t11 = alloca ptr + %t0 = load i32, ptr @g_pi + %t1 = add i32 %t0, 1 + store i32 %t1, ptr @g_pi + %t2 = call ptr @fn_node(i32 8) + store ptr %t2, ptr %t3 + %t4 = load ptr, ptr %t3 + %t5 = getelementptr inbounds %Str_Node, ptr %t4, i32 0, i32 1 + %t6 = call ptr @fn_eat_id() + store ptr %t6, ptr %t5 + call void @fn_skipnl() + call void @fn_eat_op(ptr @.str127) + br label %wcond0 +wcond0: + %t7 = icmp ne i32 1, 0 + br i1 %t7, label %wbody1, label %wend2 +wbody1: + call void @fn_skipnl() + %t8 = call i32 @fn_is_op(ptr @.str128) + %t9 = icmp ne i32 %t8, 0 + br i1 %t9, label %then3, label %ifend5 +then3: + br label %wend2 +ifend5: + %t10 = call ptr @fn_node(i32 1) + store ptr %t10, ptr %t11 + %t12 = load ptr, ptr %t11 + %t13 = getelementptr inbounds %Str_Node, ptr %t12, i32 0, i32 1 + %t14 = call ptr @fn_eat_id() + store ptr %t14, ptr %t13 + call void @fn_eat_op(ptr @.str129) + %t15 = load ptr, ptr %t11 + %t16 = getelementptr inbounds %Str_Node, ptr %t15, i32 0, i32 3 + %t17 = call ptr @fn_ptype() + store ptr %t17, ptr %t16 + %t18 = call i32 @fn_is_op(ptr @.str130) + %t19 = icmp ne i32 %t18, 0 + br i1 %t19, label %then6, label %ifend8 +then6: + %t20 = load i32, ptr @g_pi + %t21 = add i32 %t20, 1 + store i32 %t21, ptr @g_pi + %t22 = load ptr, ptr %t11 + %t23 = getelementptr inbounds %Str_Node, ptr %t22, i32 0, i32 4 + %t24 = call ptr @fn_expr() + store ptr %t24, ptr %t23 + br label %ifend8 +ifend8: + %t25 = load ptr, ptr %t3 + %t26 = getelementptr inbounds %Str_Node, ptr %t25, i32 0, i32 7 + %t27 = load ptr, ptr %t26 + %t28 = getelementptr inbounds %LSlice, ptr %t27, i32 0, i32 1 + %t29 = getelementptr inbounds %LSlice, ptr %t27, i32 0, i32 2 + %t30 = getelementptr inbounds %LSlice, ptr %t27, i32 0, i32 0 + %t31 = load i32, ptr %t28 + %t32 = load i32, ptr %t29 + %t33 = icmp sge i32 %t31, %t32 + br i1 %t33, label %grow9, label %put10 +grow9: + %t34 = mul i32 %t32, 2 + %t35 = icmp eq i32 %t32, 0 + %t36 = select i1 %t35, i32 8, i32 %t34 + %t37 = getelementptr ptr, ptr null, i32 1 + %t38 = ptrtoint ptr %t37 to i64 + %t39 = zext i32 %t36 to i64 + %t40 = mul i64 %t39, %t38 + %t41 = load ptr, ptr %t30 + %t42 = call ptr @realloc(ptr %t41, i64 %t40) + store ptr %t42, ptr %t30 + store i32 %t36, ptr %t29 + br label %put10 +put10: + %t43 = load ptr, ptr %t11 + %t44 = load ptr, ptr %t30 + %t45 = getelementptr inbounds ptr, ptr %t44, i32 %t31 + store ptr %t43, ptr %t45 + %t46 = add i32 %t31, 1 + store i32 %t46, ptr %t28 + %t47 = call i32 @fn_is_op(ptr @.str131) + %t48 = icmp ne i32 %t47, 0 + br i1 %t48, label %then11, label %ifend13 +then11: + %t49 = load i32, ptr @g_pi + %t50 = add i32 %t49, 1 + store i32 %t50, ptr @g_pi + br label %ifend13 +ifend13: + br label %wcond0 +wend2: + call void @fn_eat_op(ptr @.str132) + %t51 = load ptr, ptr %t3 + store ptr %t51, ptr %retval + br label %ret +ret: + %t52 = load ptr, ptr %retval + ret ptr %t52 +} + +define void @fn_skip_clause() { +entry: + %t2 = alloca i32 + %t0 = call i32 @fn_is_op(ptr @.str133) + %t1 = icmp ne i32 %t0, 0 + br i1 %t1, label %then0, label %ifend2 +then0: + store i32 0, ptr %t2 + br label %wcond3 +wcond3: + %t3 = icmp ne i32 1, 0 + br i1 %t3, label %wbody4, label %wend5 +wbody4: + %t4 = call i32 @fn_is_op(ptr @.str134) + %t5 = icmp ne i32 %t4, 0 + br i1 %t5, label %then6, label %ifend8 +then6: + %t6 = load i32, ptr %t2 + %t7 = add i32 %t6, 1 + store i32 %t7, ptr %t2 + br label %ifend8 +ifend8: + %t8 = call i32 @fn_is_op(ptr @.str135) + %t9 = icmp ne i32 %t8, 0 + br i1 %t9, label %then9, label %ifend11 +then9: + %t10 = load i32, ptr %t2 + %t11 = sub i32 %t10, 1 + store i32 %t11, ptr %t2 + br label %ifend11 +ifend11: + %t12 = load i32, ptr @g_pi + %t13 = add i32 %t12, 1 + store i32 %t13, ptr @g_pi + %t14 = load i32, ptr %t2 + %t15 = icmp eq i32 %t14, 0 + %t16 = zext i1 %t15 to i32 + %t17 = icmp ne i32 %t16, 0 + br i1 %t17, label %then12, label %ifend14 +then12: + br label %wend5 +ifend14: + br label %wcond3 +wend5: + br label %ifend2 +ifend2: + br label %ret +ret: + ret void +} + +define ptr @fn_parse_system() { +entry: + %retval = alloca ptr + %t7 = alloca ptr + %t13 = alloca i32 + %t15 = alloca ptr + %t22 = alloca ptr + %t25 = alloca i32 + %t48 = alloca i32 + %t49 = alloca i32 + %t50 = alloca i32 + %t84 = alloca ptr + %t125 = alloca ptr + %t132 = alloca ptr + %t0 = call i32 @fn_is_id(ptr @.str136) + %t1 = icmp ne i32 %t0, 0 + br i1 %t1, label %then0, label %ifend2 +then0: + %t2 = load i32, ptr @g_pi + %t3 = add i32 %t2, 1 + store i32 %t3, ptr @g_pi + br label %ifend2 +ifend2: + %t4 = load i32, ptr @g_pi + %t5 = add i32 %t4, 1 + store i32 %t5, ptr @g_pi + %t6 = call ptr @fn_node(i32 9) + store ptr %t6, ptr %t7 + %t8 = load ptr, ptr %t7 + %t9 = getelementptr inbounds %Str_Node, ptr %t8, i32 0, i32 1 + %t10 = call ptr @fn_eat_id() + store ptr %t10, ptr %t9 + %t11 = load ptr, ptr %t7 + %t12 = getelementptr inbounds %Str_Node, ptr %t11, i32 0, i32 3 + store ptr @.str137, ptr %t12 + store i32 0, ptr %t13 + %t14 = call ptr @fn_node(i32 21) + store ptr %t14, ptr %t15 + br label %wcond3 +wcond3: + %t16 = icmp ne i32 1, 0 + br i1 %t16, label %wbody4, label %wend5 +wbody4: + call void @fn_skipnl() + %t17 = call i32 @fn_is_op(ptr @.str138) + %t18 = icmp ne i32 %t17, 0 + br i1 %t18, label %then6, label %ifend8 +then6: + %t19 = load i32, ptr @g_pi + %t20 = add i32 %t19, 1 + store i32 %t20, ptr @g_pi + %t21 = call ptr @fn_eat_id() + store ptr %t21, ptr %t22 + %t23 = call i32 @fn_is_op(ptr @.str139) + %t24 = icmp ne i32 %t23, 0 + br i1 %t24, label %then9, label %ifend11 +then9: + store i32 0, ptr %t25 + br label %wcond12 +wcond12: + %t26 = icmp ne i32 1, 0 + br i1 %t26, label %wbody13, label %wend14 +wbody13: + %t27 = call i32 @fn_is_op(ptr @.str140) + %t28 = icmp ne i32 %t27, 0 + br i1 %t28, label %then15, label %ifend17 +then15: + %t29 = load i32, ptr %t25 + %t30 = add i32 %t29, 1 + store i32 %t30, ptr %t25 + br label %ifend17 +ifend17: + %t31 = call i32 @fn_is_op(ptr @.str141) + %t32 = icmp ne i32 %t31, 0 + br i1 %t32, label %then18, label %ifend20 +then18: + %t33 = load i32, ptr %t25 + %t34 = sub i32 %t33, 1 + store i32 %t34, ptr %t25 + br label %ifend20 +ifend20: + %t35 = load i32, ptr @g_pi + %t36 = add i32 %t35, 1 + store i32 %t36, ptr @g_pi + %t37 = load i32, ptr %t25 + %t38 = icmp eq i32 %t37, 0 + %t39 = zext i1 %t38 to i32 + %t40 = icmp ne i32 %t39, 0 + br i1 %t40, label %then21, label %ifend23 +then21: + br label %wend14 +ifend23: + br label %wcond12 +wend14: + br label %ifend11 +ifend11: + br label %wcond3 +ifend8: + %t41 = call i32 @fn_is_id(ptr @.str142) + %t42 = icmp ne i32 %t41, 0 + br i1 %t42, label %then24, label %ifend26 +then24: + %t43 = load i32, ptr @g_pi + %t44 = add i32 %t43, 1 + store i32 %t44, ptr @g_pi + %t45 = load ptr, ptr %t7 + %t46 = getelementptr inbounds %Str_Node, ptr %t45, i32 0, i32 3 + %t47 = call ptr @fn_eat_id() + store ptr %t47, ptr %t46 + br label %wcond3 +ifend26: + %t51 = call i32 @fn_is_id(ptr @.str143) + %t52 = icmp ne i32 %t51, 0 + %t53 = zext i1 %t52 to i32 + store i32 %t53, ptr %t50 + br i1 %t52, label %scend28, label %sc27 +sc27: + %t54 = call i32 @fn_is_id(ptr @.str144) + %t55 = icmp ne i32 %t54, 0 + %t56 = zext i1 %t55 to i32 + store i32 %t56, ptr %t50 + br label %scend28 +scend28: + %t57 = load i32, ptr %t50 + %t58 = icmp ne i32 %t57, 0 + %t59 = zext i1 %t58 to i32 + store i32 %t59, ptr %t49 + br i1 %t58, label %scend30, label %sc29 +sc29: + %t60 = call i32 @fn_is_id(ptr @.str145) + %t61 = icmp ne i32 %t60, 0 + %t62 = zext i1 %t61 to i32 + store i32 %t62, ptr %t49 + br label %scend30 +scend30: + %t63 = load i32, ptr %t49 + %t64 = icmp ne i32 %t63, 0 + %t65 = zext i1 %t64 to i32 + store i32 %t65, ptr %t48 + br i1 %t64, label %scend32, label %sc31 +sc31: + %t66 = call i32 @fn_is_id(ptr @.str146) + %t67 = icmp ne i32 %t66, 0 + %t68 = zext i1 %t67 to i32 + store i32 %t68, ptr %t48 + br label %scend32 +scend32: + %t69 = load i32, ptr %t48 + %t70 = icmp ne i32 %t69, 0 + br i1 %t70, label %then33, label %ifend35 +then33: + %t71 = load i32, ptr @g_pi + %t72 = add i32 %t71, 1 + store i32 %t72, ptr @g_pi + call void @fn_skip_clause() + br label %wcond3 +ifend35: + %t73 = call i32 @fn_is_id(ptr @.str147) + %t74 = icmp ne i32 %t73, 0 + br i1 %t74, label %then36, label %ifend38 +then36: + %t75 = load i32, ptr @g_pi + %t76 = add i32 %t75, 1 + store i32 %t76, ptr @g_pi + store i32 1, ptr %t13 + %t77 = call i32 @fn_is_op(ptr @.str148) + %t78 = icmp ne i32 %t77, 0 + br i1 %t78, label %then39, label %ifend41 +then39: + call void @fn_eat_op(ptr @.str149) + br label %wcond42 +wcond42: + %t79 = call i32 @fn_is_op(ptr @.str150) + %t80 = icmp eq i32 %t79, 0 + %t81 = zext i1 %t80 to i32 + %t82 = icmp ne i32 %t81, 0 + br i1 %t82, label %wbody43, label %wend44 +wbody43: + %t83 = call ptr @fn_node(i32 33) + store ptr %t83, ptr %t84 + %t85 = load ptr, ptr %t84 + %t86 = getelementptr inbounds %Str_Node, ptr %t85, i32 0, i32 1 + %t87 = call ptr @fn_eat_id() + store ptr %t87, ptr %t86 + %t88 = load ptr, ptr %t15 + %t89 = getelementptr inbounds %Str_Node, ptr %t88, i32 0, i32 7 + %t90 = load ptr, ptr %t89 + %t91 = getelementptr inbounds %LSlice, ptr %t90, i32 0, i32 1 + %t92 = getelementptr inbounds %LSlice, ptr %t90, i32 0, i32 2 + %t93 = getelementptr inbounds %LSlice, ptr %t90, i32 0, i32 0 + %t94 = load i32, ptr %t91 + %t95 = load i32, ptr %t92 + %t96 = icmp sge i32 %t94, %t95 + br i1 %t96, label %grow45, label %put46 +grow45: + %t97 = mul i32 %t95, 2 + %t98 = icmp eq i32 %t95, 0 + %t99 = select i1 %t98, i32 8, i32 %t97 + %t100 = getelementptr ptr, ptr null, i32 1 + %t101 = ptrtoint ptr %t100 to i64 + %t102 = zext i32 %t99 to i64 + %t103 = mul i64 %t102, %t101 + %t104 = load ptr, ptr %t93 + %t105 = call ptr @realloc(ptr %t104, i64 %t103) + store ptr %t105, ptr %t93 + store i32 %t99, ptr %t92 + br label %put46 +put46: + %t106 = load ptr, ptr %t84 + %t107 = load ptr, ptr %t93 + %t108 = getelementptr inbounds ptr, ptr %t107, i32 %t94 + store ptr %t106, ptr %t108 + %t109 = add i32 %t94, 1 + store i32 %t109, ptr %t91 + %t110 = call i32 @fn_is_op(ptr @.str151) + %t111 = icmp ne i32 %t110, 0 + br i1 %t111, label %then47, label %ifend49 +then47: + %t112 = load i32, ptr @g_pi + %t113 = add i32 %t112, 1 + store i32 %t113, ptr @g_pi + br label %ifend49 +ifend49: + br label %wcond42 +wend44: + call void @fn_eat_op(ptr @.str152) + br label %ifend41 +ifend41: + %t114 = load ptr, ptr %t15 + %t115 = getelementptr inbounds %Str_Node, ptr %t114, i32 0, i32 6 + %t116 = call ptr @fn_parse_query_tail() + store ptr %t116, ptr %t115 + %t117 = load ptr, ptr %t15 + %t118 = getelementptr inbounds %Str_Node, ptr %t117, i32 0, i32 5 + %t119 = load ptr, ptr %t15 + %t120 = getelementptr inbounds %Str_Node, ptr %t119, i32 0, i32 6 + %t121 = load ptr, ptr %t120 + %t122 = getelementptr inbounds %Str_Node, ptr %t121, i32 0, i32 4 + %t123 = load ptr, ptr %t122 + store ptr %t123, ptr %t118 + br label %wcond3 +ifend38: + br label %wend5 +wend5: + call void @fn_skipnl() + %t124 = call ptr @fn_block() + store ptr %t124, ptr %t125 + %t126 = load i32, ptr %t13 + %t127 = icmp ne i32 %t126, 0 + br i1 %t127, label %then50, label %else51 +then50: + %t128 = load ptr, ptr %t15 + %t129 = getelementptr inbounds %Str_Node, ptr %t128, i32 0, i32 4 + %t130 = load ptr, ptr %t125 + store ptr %t130, ptr %t129 + %t131 = call ptr @fn_node(i32 7) + store ptr %t131, ptr %t132 + %t133 = load ptr, ptr %t132 + %t134 = getelementptr inbounds %Str_Node, ptr %t133, i32 0, i32 7 + %t135 = load ptr, ptr %t134 + %t136 = getelementptr inbounds %LSlice, ptr %t135, i32 0, i32 1 + %t137 = getelementptr inbounds %LSlice, ptr %t135, i32 0, i32 2 + %t138 = getelementptr inbounds %LSlice, ptr %t135, i32 0, i32 0 + %t139 = load i32, ptr %t136 + %t140 = load i32, ptr %t137 + %t141 = icmp sge i32 %t139, %t140 + br i1 %t141, label %grow53, label %put54 +grow53: + %t142 = mul i32 %t140, 2 + %t143 = icmp eq i32 %t140, 0 + %t144 = select i1 %t143, i32 8, i32 %t142 + %t145 = getelementptr ptr, ptr null, i32 1 + %t146 = ptrtoint ptr %t145 to i64 + %t147 = zext i32 %t144 to i64 + %t148 = mul i64 %t147, %t146 + %t149 = load ptr, ptr %t138 + %t150 = call ptr @realloc(ptr %t149, i64 %t148) + store ptr %t150, ptr %t138 + store i32 %t144, ptr %t137 + br label %put54 +put54: + %t151 = load ptr, ptr %t15 + %t152 = load ptr, ptr %t138 + %t153 = getelementptr inbounds ptr, ptr %t152, i32 %t139 + store ptr %t151, ptr %t153 + %t154 = add i32 %t139, 1 + store i32 %t154, ptr %t136 + %t155 = load ptr, ptr %t7 + %t156 = getelementptr inbounds %Str_Node, ptr %t155, i32 0, i32 4 + %t157 = load ptr, ptr %t132 + store ptr %t157, ptr %t156 + br label %ifend52 +else51: + %t158 = load ptr, ptr %t7 + %t159 = getelementptr inbounds %Str_Node, ptr %t158, i32 0, i32 4 + %t160 = load ptr, ptr %t125 + store ptr %t160, ptr %t159 + br label %ifend52 +ifend52: + %t161 = load ptr, ptr %t7 + store ptr %t161, ptr %retval + br label %ret +ret: + %t162 = load ptr, ptr %retval + ret ptr %t162 +} + +define ptr @fn_parse_query_tail() { +entry: + %retval = alloca ptr + %t1 = alloca ptr + %t11 = alloca ptr + %t40 = alloca ptr + call void @fn_eat_op(ptr @.str153) + %t0 = call ptr @fn_node(i32 7) + store ptr %t0, ptr %t1 + br label %wcond0 +wcond0: + %t2 = call i32 @fn_is_op(ptr @.str154) + %t3 = icmp eq i32 %t2, 0 + %t4 = zext i1 %t3 to i32 + %t5 = icmp ne i32 %t4, 0 + br i1 %t5, label %wbody1, label %wend2 +wbody1: + %t6 = call i32 @fn_is_op(ptr @.str155) + %t7 = icmp ne i32 %t6, 0 + br i1 %t7, label %then3, label %else4 +then3: + %t8 = load i32, ptr @g_pi + %t9 = add i32 %t8, 1 + store i32 %t9, ptr @g_pi + %t10 = call ptr @fn_node(i32 33) + store ptr %t10, ptr %t11 + %t12 = load ptr, ptr %t11 + %t13 = getelementptr inbounds %Str_Node, ptr %t12, i32 0, i32 1 + %t14 = call ptr @fn_eat_id() + store ptr %t14, ptr %t13 + %t15 = load ptr, ptr %t11 + %t16 = getelementptr inbounds %Str_Node, ptr %t15, i32 0, i32 2 + store i32 1, ptr %t16 + %t17 = load ptr, ptr %t1 + %t18 = getelementptr inbounds %Str_Node, ptr %t17, i32 0, i32 7 + %t19 = load ptr, ptr %t18 + %t20 = getelementptr inbounds %LSlice, ptr %t19, i32 0, i32 1 + %t21 = getelementptr inbounds %LSlice, ptr %t19, i32 0, i32 2 + %t22 = getelementptr inbounds %LSlice, ptr %t19, i32 0, i32 0 + %t23 = load i32, ptr %t20 + %t24 = load i32, ptr %t21 + %t25 = icmp sge i32 %t23, %t24 + br i1 %t25, label %grow6, label %put7 +grow6: + %t26 = mul i32 %t24, 2 + %t27 = icmp eq i32 %t24, 0 + %t28 = select i1 %t27, i32 8, i32 %t26 + %t29 = getelementptr ptr, ptr null, i32 1 + %t30 = ptrtoint ptr %t29 to i64 + %t31 = zext i32 %t28 to i64 + %t32 = mul i64 %t31, %t30 + %t33 = load ptr, ptr %t22 + %t34 = call ptr @realloc(ptr %t33, i64 %t32) + store ptr %t34, ptr %t22 + store i32 %t28, ptr %t21 + br label %put7 +put7: + %t35 = load ptr, ptr %t11 + %t36 = load ptr, ptr %t22 + %t37 = getelementptr inbounds ptr, ptr %t36, i32 %t23 + store ptr %t35, ptr %t37 + %t38 = add i32 %t23, 1 + store i32 %t38, ptr %t20 + call void @fn_eat_op(ptr @.str156) + br label %ifend5 +else4: + %t39 = call ptr @fn_node(i32 33) + store ptr %t39, ptr %t40 + %t41 = load ptr, ptr %t40 + %t42 = getelementptr inbounds %Str_Node, ptr %t41, i32 0, i32 1 + %t43 = call ptr @fn_eat_id() + store ptr %t43, ptr %t42 + %t44 = load ptr, ptr %t40 + %t45 = getelementptr inbounds %Str_Node, ptr %t44, i32 0, i32 2 + store i32 0, ptr %t45 + %t46 = load ptr, ptr %t1 + %t47 = getelementptr inbounds %Str_Node, ptr %t46, i32 0, i32 7 + %t48 = load ptr, ptr %t47 + %t49 = getelementptr inbounds %LSlice, ptr %t48, i32 0, i32 1 + %t50 = getelementptr inbounds %LSlice, ptr %t48, i32 0, i32 2 + %t51 = getelementptr inbounds %LSlice, ptr %t48, i32 0, i32 0 + %t52 = load i32, ptr %t49 + %t53 = load i32, ptr %t50 + %t54 = icmp sge i32 %t52, %t53 + br i1 %t54, label %grow8, label %put9 +grow8: + %t55 = mul i32 %t53, 2 + %t56 = icmp eq i32 %t53, 0 + %t57 = select i1 %t56, i32 8, i32 %t55 + %t58 = getelementptr ptr, ptr null, i32 1 + %t59 = ptrtoint ptr %t58 to i64 + %t60 = zext i32 %t57 to i64 + %t61 = mul i64 %t60, %t59 + %t62 = load ptr, ptr %t51 + %t63 = call ptr @realloc(ptr %t62, i64 %t61) + store ptr %t63, ptr %t51 + store i32 %t57, ptr %t50 + br label %put9 +put9: + %t64 = load ptr, ptr %t40 + %t65 = load ptr, ptr %t51 + %t66 = getelementptr inbounds ptr, ptr %t65, i32 %t52 + store ptr %t64, ptr %t66 + %t67 = add i32 %t52, 1 + store i32 %t67, ptr %t49 + br label %ifend5 +ifend5: + %t68 = call i32 @fn_is_op(ptr @.str157) + %t69 = icmp ne i32 %t68, 0 + br i1 %t69, label %then10, label %ifend12 +then10: + %t70 = load i32, ptr @g_pi + %t71 = add i32 %t70, 1 + store i32 %t71, ptr @g_pi + br label %ifend12 +ifend12: + br label %wcond0 +wend2: + call void @fn_eat_op(ptr @.str158) + %t72 = call i32 @fn_is_id(ptr @.str159) + %t73 = icmp ne i32 %t72, 0 + br i1 %t73, label %then13, label %ifend15 +then13: + %t74 = load i32, ptr @g_pi + %t75 = add i32 %t74, 1 + store i32 %t75, ptr @g_pi + %t76 = load ptr, ptr %t1 + %t77 = getelementptr inbounds %Str_Node, ptr %t76, i32 0, i32 4 + %t78 = call ptr @fn_expr() + store ptr %t78, ptr %t77 + br label %ifend15 +ifend15: + %t79 = load ptr, ptr %t1 + store ptr %t79, ptr %retval + br label %ret +ret: + %t80 = load ptr, ptr %retval + ret ptr %t80 +} + +define ptr @fn_parse_query_for() { +entry: + %retval = alloca ptr + %t1 = alloca ptr + %t7 = alloca ptr + %t38 = alloca ptr + %t40 = alloca ptr + %t0 = call ptr @fn_node(i32 21) + store ptr %t0, ptr %t1 + call void @fn_eat_op(ptr @.str160) + br label %wcond0 +wcond0: + %t2 = call i32 @fn_is_op(ptr @.str161) + %t3 = icmp eq i32 %t2, 0 + %t4 = zext i1 %t3 to i32 + %t5 = icmp ne i32 %t4, 0 + br i1 %t5, label %wbody1, label %wend2 +wbody1: + %t6 = call ptr @fn_node(i32 33) + store ptr %t6, ptr %t7 + %t8 = load ptr, ptr %t7 + %t9 = getelementptr inbounds %Str_Node, ptr %t8, i32 0, i32 1 + %t10 = call ptr @fn_eat_id() + store ptr %t10, ptr %t9 + %t11 = load ptr, ptr %t1 + %t12 = getelementptr inbounds %Str_Node, ptr %t11, i32 0, i32 7 + %t13 = load ptr, ptr %t12 + %t14 = getelementptr inbounds %LSlice, ptr %t13, i32 0, i32 1 + %t15 = getelementptr inbounds %LSlice, ptr %t13, i32 0, i32 2 + %t16 = getelementptr inbounds %LSlice, ptr %t13, i32 0, i32 0 + %t17 = load i32, ptr %t14 + %t18 = load i32, ptr %t15 + %t19 = icmp sge i32 %t17, %t18 + br i1 %t19, label %grow3, label %put4 +grow3: + %t20 = mul i32 %t18, 2 + %t21 = icmp eq i32 %t18, 0 + %t22 = select i1 %t21, i32 8, i32 %t20 + %t23 = getelementptr ptr, ptr null, i32 1 + %t24 = ptrtoint ptr %t23 to i64 + %t25 = zext i32 %t22 to i64 + %t26 = mul i64 %t25, %t24 + %t27 = load ptr, ptr %t16 + %t28 = call ptr @realloc(ptr %t27, i64 %t26) + store ptr %t28, ptr %t16 + store i32 %t22, ptr %t15 + br label %put4 +put4: + %t29 = load ptr, ptr %t7 + %t30 = load ptr, ptr %t16 + %t31 = getelementptr inbounds ptr, ptr %t30, i32 %t17 + store ptr %t29, ptr %t31 + %t32 = add i32 %t17, 1 + store i32 %t32, ptr %t14 + %t33 = call i32 @fn_is_op(ptr @.str162) + %t34 = icmp ne i32 %t33, 0 + br i1 %t34, label %then5, label %ifend7 +then5: + %t35 = load i32, ptr @g_pi + %t36 = add i32 %t35, 1 + store i32 %t36, ptr @g_pi + br label %ifend7 +ifend7: + br label %wcond0 +wend2: + call void @fn_eat_op(ptr @.str163) + %t37 = call ptr @fn_eat_id() + store ptr %t37, ptr %t38 + %t39 = call ptr @fn_eat_id() + store ptr %t39, ptr %t40 + %t41 = load ptr, ptr %t1 + %t42 = getelementptr inbounds %Str_Node, ptr %t41, i32 0, i32 6 + %t43 = call ptr @fn_parse_query_tail() + store ptr %t43, ptr %t42 + %t44 = load ptr, ptr %t1 + %t45 = getelementptr inbounds %Str_Node, ptr %t44, i32 0, i32 5 + %t46 = load ptr, ptr %t1 + %t47 = getelementptr inbounds %Str_Node, ptr %t46, i32 0, i32 6 + %t48 = load ptr, ptr %t47 + %t49 = getelementptr inbounds %Str_Node, ptr %t48, i32 0, i32 4 + %t50 = load ptr, ptr %t49 + store ptr %t50, ptr %t45 + %t51 = load ptr, ptr %t1 + %t52 = getelementptr inbounds %Str_Node, ptr %t51, i32 0, i32 4 + %t53 = call ptr @fn_block() + store ptr %t53, ptr %t52 + %t54 = load ptr, ptr %t1 + store ptr %t54, ptr %retval + br label %ret +ret: + %t55 = load ptr, ptr %retval + ret ptr %t55 +} + +define ptr @fn_parse_spawn() { +entry: + %retval = alloca ptr + %t3 = alloca ptr + %t11 = alloca ptr + %t0 = load i32, ptr @g_pi + %t1 = add i32 %t0, 1 + store i32 %t1, ptr @g_pi + %t2 = call ptr @fn_node(i32 22) + store ptr %t2, ptr %t3 + %t4 = load ptr, ptr %t3 + %t5 = getelementptr inbounds %Str_Node, ptr %t4, i32 0, i32 1 + %t6 = call ptr @fn_eat_id() + store ptr %t6, ptr %t5 + call void @fn_skipnl() + call void @fn_eat_op(ptr @.str164) + br label %wcond0 +wcond0: + %t7 = icmp ne i32 1, 0 + br i1 %t7, label %wbody1, label %wend2 +wbody1: + call void @fn_skipnl() + %t8 = call i32 @fn_is_op(ptr @.str165) + %t9 = icmp ne i32 %t8, 0 + br i1 %t9, label %then3, label %ifend5 +then3: + br label %wend2 +ifend5: + %t10 = call ptr @fn_node(i32 42) + store ptr %t10, ptr %t11 + %t12 = load ptr, ptr %t11 + %t13 = getelementptr inbounds %Str_Node, ptr %t12, i32 0, i32 1 + %t14 = call ptr @fn_eat_id() + store ptr %t14, ptr %t13 + call void @fn_eat_op(ptr @.str166) + %t15 = load ptr, ptr %t11 + %t16 = getelementptr inbounds %Str_Node, ptr %t15, i32 0, i32 4 + %t17 = call ptr @fn_record() + store ptr %t17, ptr %t16 + %t18 = load ptr, ptr %t3 + %t19 = getelementptr inbounds %Str_Node, ptr %t18, i32 0, i32 7 + %t20 = load ptr, ptr %t19 + %t21 = getelementptr inbounds %LSlice, ptr %t20, i32 0, i32 1 + %t22 = getelementptr inbounds %LSlice, ptr %t20, i32 0, i32 2 + %t23 = getelementptr inbounds %LSlice, ptr %t20, i32 0, i32 0 + %t24 = load i32, ptr %t21 + %t25 = load i32, ptr %t22 + %t26 = icmp sge i32 %t24, %t25 + br i1 %t26, label %grow6, label %put7 +grow6: + %t27 = mul i32 %t25, 2 + %t28 = icmp eq i32 %t25, 0 + %t29 = select i1 %t28, i32 8, i32 %t27 + %t30 = getelementptr ptr, ptr null, i32 1 + %t31 = ptrtoint ptr %t30 to i64 + %t32 = zext i32 %t29 to i64 + %t33 = mul i64 %t32, %t31 + %t34 = load ptr, ptr %t23 + %t35 = call ptr @realloc(ptr %t34, i64 %t33) + store ptr %t35, ptr %t23 + store i32 %t29, ptr %t22 + br label %put7 +put7: + %t36 = load ptr, ptr %t11 + %t37 = load ptr, ptr %t23 + %t38 = getelementptr inbounds ptr, ptr %t37, i32 %t24 + store ptr %t36, ptr %t38 + %t39 = add i32 %t24, 1 + store i32 %t39, ptr %t21 + %t40 = call i32 @fn_is_op(ptr @.str167) + %t41 = icmp ne i32 %t40, 0 + br i1 %t41, label %then8, label %ifend10 +then8: + %t42 = load i32, ptr @g_pi + %t43 = add i32 %t42, 1 + store i32 %t43, ptr @g_pi + br label %ifend10 +ifend10: + br label %wcond0 +wend2: + call void @fn_eat_op(ptr @.str168) + %t44 = load ptr, ptr %t3 + store ptr %t44, ptr %retval + br label %ret +ret: + %t45 = load ptr, ptr %retval + ret ptr %t45 +} + +define ptr @fn_parse_archetype() { +entry: + %retval = alloca ptr + %t3 = alloca ptr + %t11 = alloca ptr + %t0 = load i32, ptr @g_pi + %t1 = add i32 %t0, 1 + store i32 %t1, ptr @g_pi + %t2 = call ptr @fn_node(i32 10) + store ptr %t2, ptr %t3 + %t4 = load ptr, ptr %t3 + %t5 = getelementptr inbounds %Str_Node, ptr %t4, i32 0, i32 1 + %t6 = call ptr @fn_eat_id() + store ptr %t6, ptr %t5 + call void @fn_skipnl() + call void @fn_eat_op(ptr @.str169) + br label %wcond0 +wcond0: + %t7 = icmp ne i32 1, 0 + br i1 %t7, label %wbody1, label %wend2 +wbody1: + call void @fn_skipnl() + %t8 = call i32 @fn_is_op(ptr @.str170) + %t9 = icmp ne i32 %t8, 0 + br i1 %t9, label %then3, label %ifend5 +then3: + br label %wend2 +ifend5: + %t10 = call ptr @fn_node(i32 33) + store ptr %t10, ptr %t11 + %t12 = load ptr, ptr %t11 + %t13 = getelementptr inbounds %Str_Node, ptr %t12, i32 0, i32 1 + %t14 = call ptr @fn_eat_id() + store ptr %t14, ptr %t13 + %t15 = load ptr, ptr %t3 + %t16 = getelementptr inbounds %Str_Node, ptr %t15, i32 0, i32 7 + %t17 = load ptr, ptr %t16 + %t18 = getelementptr inbounds %LSlice, ptr %t17, i32 0, i32 1 + %t19 = getelementptr inbounds %LSlice, ptr %t17, i32 0, i32 2 + %t20 = getelementptr inbounds %LSlice, ptr %t17, i32 0, i32 0 + %t21 = load i32, ptr %t18 + %t22 = load i32, ptr %t19 + %t23 = icmp sge i32 %t21, %t22 + br i1 %t23, label %grow6, label %put7 +grow6: + %t24 = mul i32 %t22, 2 + %t25 = icmp eq i32 %t22, 0 + %t26 = select i1 %t25, i32 8, i32 %t24 + %t27 = getelementptr ptr, ptr null, i32 1 + %t28 = ptrtoint ptr %t27 to i64 + %t29 = zext i32 %t26 to i64 + %t30 = mul i64 %t29, %t28 + %t31 = load ptr, ptr %t20 + %t32 = call ptr @realloc(ptr %t31, i64 %t30) + store ptr %t32, ptr %t20 + store i32 %t26, ptr %t19 + br label %put7 +put7: + %t33 = load ptr, ptr %t11 + %t34 = load ptr, ptr %t20 + %t35 = getelementptr inbounds ptr, ptr %t34, i32 %t21 + store ptr %t33, ptr %t35 + %t36 = add i32 %t21, 1 + store i32 %t36, ptr %t18 + %t37 = call i32 @fn_is_op(ptr @.str171) + %t38 = icmp ne i32 %t37, 0 + br i1 %t38, label %then8, label %ifend10 +then8: + %t39 = load i32, ptr @g_pi + %t40 = add i32 %t39, 1 + store i32 %t40, ptr @g_pi + br label %ifend10 +ifend10: + call void @fn_skipnl() + br label %wcond0 +wend2: + call void @fn_eat_op(ptr @.str172) + %t41 = load ptr, ptr %t3 + store ptr %t41, ptr %retval + br label %ret +ret: + %t42 = load ptr, ptr %retval + ret ptr %t42 +} + +define ptr @fn_parse_extern() { +entry: + %retval = alloca ptr + %t3 = alloca ptr + %t5 = alloca ptr + %t14 = alloca ptr + %t62 = alloca ptr + %t0 = load i32, ptr @g_pi + %t1 = add i32 %t0, 1 + store i32 %t1, ptr @g_pi + %t2 = call ptr @fn_eat_id() + store ptr %t2, ptr %t3 + %t4 = call ptr @fn_node(i32 11) + store ptr %t4, ptr %t5 + %t6 = load ptr, ptr %t5 + %t7 = getelementptr inbounds %Str_Node, ptr %t6, i32 0, i32 1 + %t8 = call ptr @fn_eat_id() + store ptr %t8, ptr %t7 + call void @fn_eat_op(ptr @.str173) + br label %wcond0 +wcond0: + %t9 = call i32 @fn_is_op(ptr @.str174) + %t10 = icmp eq i32 %t9, 0 + %t11 = zext i1 %t10 to i32 + %t12 = icmp ne i32 %t11, 0 + br i1 %t12, label %wbody1, label %wend2 +wbody1: + %t13 = call ptr @fn_node(i32 5) + store ptr %t13, ptr %t14 + %t15 = load ptr, ptr %t14 + %t16 = getelementptr inbounds %Str_Node, ptr %t15, i32 0, i32 1 + %t17 = call ptr @fn_eat_id() + store ptr %t17, ptr %t16 + call void @fn_eat_op(ptr @.str175) + %t18 = load ptr, ptr %t14 + %t19 = getelementptr inbounds %Str_Node, ptr %t18, i32 0, i32 3 + %t20 = call ptr @fn_ptype() + store ptr %t20, ptr %t19 + %t21 = load ptr, ptr %t5 + %t22 = getelementptr inbounds %Str_Node, ptr %t21, i32 0, i32 7 + %t23 = load ptr, ptr %t22 + %t24 = getelementptr inbounds %LSlice, ptr %t23, i32 0, i32 1 + %t25 = getelementptr inbounds %LSlice, ptr %t23, i32 0, i32 2 + %t26 = getelementptr inbounds %LSlice, ptr %t23, i32 0, i32 0 + %t27 = load i32, ptr %t24 + %t28 = load i32, ptr %t25 + %t29 = icmp sge i32 %t27, %t28 + br i1 %t29, label %grow3, label %put4 +grow3: + %t30 = mul i32 %t28, 2 + %t31 = icmp eq i32 %t28, 0 + %t32 = select i1 %t31, i32 8, i32 %t30 + %t33 = getelementptr ptr, ptr null, i32 1 + %t34 = ptrtoint ptr %t33 to i64 + %t35 = zext i32 %t32 to i64 + %t36 = mul i64 %t35, %t34 + %t37 = load ptr, ptr %t26 + %t38 = call ptr @realloc(ptr %t37, i64 %t36) + store ptr %t38, ptr %t26 + store i32 %t32, ptr %t25 + br label %put4 +put4: + %t39 = load ptr, ptr %t14 + %t40 = load ptr, ptr %t26 + %t41 = getelementptr inbounds ptr, ptr %t40, i32 %t27 + store ptr %t39, ptr %t41 + %t42 = add i32 %t27, 1 + store i32 %t42, ptr %t24 + %t43 = call i32 @fn_is_op(ptr @.str176) + %t44 = icmp ne i32 %t43, 0 + br i1 %t44, label %then5, label %ifend7 +then5: + %t45 = load i32, ptr @g_pi + %t46 = add i32 %t45, 1 + store i32 %t46, ptr @g_pi + br label %ifend7 +ifend7: + br label %wcond0 +wend2: + call void @fn_eat_op(ptr @.str177) + %t47 = load ptr, ptr %t5 + %t48 = getelementptr inbounds %Str_Node, ptr %t47, i32 0, i32 3 + store ptr @.str178, ptr %t48 + %t49 = call i32 @fn_is_op(ptr @.str179) + %t50 = icmp ne i32 %t49, 0 + br i1 %t50, label %then8, label %ifend10 +then8: + %t51 = load i32, ptr @g_pi + %t52 = add i32 %t51, 1 + store i32 %t52, ptr @g_pi + %t53 = load ptr, ptr %t5 + %t54 = getelementptr inbounds %Str_Node, ptr %t53, i32 0, i32 3 + %t55 = call ptr @fn_ptype() + store ptr %t55, ptr %t54 + br label %ifend10 +ifend10: + call void @fn_eat_op(ptr @.str180) + %t56 = load ptr, ptr @g_toks + %t57 = getelementptr inbounds %LSlice, ptr %t56, i32 0, i32 0 + %t58 = load ptr, ptr %t57 + %t59 = load i32, ptr @g_pi + %t60 = getelementptr inbounds ptr, ptr %t58, i32 %t59 + %t61 = load ptr, ptr %t60 + store ptr %t61, ptr %t62 + %t63 = load ptr, ptr %t5 + %t64 = getelementptr inbounds %Str_Node, ptr %t63, i32 0, i32 4 + %t65 = call ptr @fn_node(i32 31) + store ptr %t65, ptr %t64 + %t66 = load ptr, ptr %t5 + %t67 = getelementptr inbounds %Str_Node, ptr %t66, i32 0, i32 4 + %t68 = load ptr, ptr %t67 + %t69 = getelementptr inbounds %Str_Node, ptr %t68, i32 0, i32 1 + %t70 = load ptr, ptr %t62 + %t71 = getelementptr inbounds %Str_Tok, ptr %t70, i32 0, i32 1 + %t72 = load ptr, ptr %t71 + store ptr %t72, ptr %t69 + %t73 = load i32, ptr @g_pi + %t74 = add i32 %t73, 1 + store i32 %t74, ptr @g_pi + %t75 = load ptr, ptr %t5 + store ptr %t75, ptr %retval + br label %ret +ret: + %t76 = load ptr, ptr %retval + ret ptr %t76 +} + +define ptr @fn_parse_widget() { +entry: + %retval = alloca ptr + %t1 = alloca ptr + %t8 = alloca i32 + %t9 = alloca i32 + %t53 = alloca ptr + %t0 = call ptr @fn_node(i32 12) + store ptr %t0, ptr %t1 + %t2 = load ptr, ptr %t1 + %t3 = getelementptr inbounds %Str_Node, ptr %t2, i32 0, i32 1 + %t4 = call ptr @fn_eat_id() + store ptr %t4, ptr %t3 + %t5 = load ptr, ptr %t1 + %t6 = getelementptr inbounds %Str_Node, ptr %t5, i32 0, i32 5 + %t7 = call ptr @fn_node(i32 7) + store ptr %t7, ptr %t6 + br label %wcond0 +wcond0: + %t10 = load ptr, ptr @g_toks + %t11 = getelementptr inbounds %LSlice, ptr %t10, i32 0, i32 0 + %t12 = load ptr, ptr %t11 + %t13 = load i32, ptr @g_pi + %t14 = getelementptr inbounds ptr, ptr %t12, i32 %t13 + %t15 = load ptr, ptr %t14 + %t16 = getelementptr inbounds %Str_Tok, ptr %t15, i32 0, i32 0 + %t17 = load i32, ptr %t16 + %t18 = icmp eq i32 %t17, 0 + %t19 = zext i1 %t18 to i32 + %t20 = icmp ne i32 %t19, 0 + %t21 = zext i1 %t20 to i32 + store i32 %t21, ptr %t9 + br i1 %t20, label %sc3, label %scend4 +sc3: + %t22 = load ptr, ptr @g_toks + %t23 = getelementptr inbounds %LSlice, ptr %t22, i32 0, i32 0 + %t24 = load ptr, ptr %t23 + %t25 = load i32, ptr @g_pi + %t26 = add i32 %t25, 1 + %t27 = getelementptr inbounds ptr, ptr %t24, i32 %t26 + %t28 = load ptr, ptr %t27 + %t29 = getelementptr inbounds %Str_Tok, ptr %t28, i32 0, i32 0 + %t30 = load i32, ptr %t29 + %t31 = icmp eq i32 %t30, 3 + %t32 = zext i1 %t31 to i32 + %t33 = icmp ne i32 %t32, 0 + %t34 = zext i1 %t33 to i32 + store i32 %t34, ptr %t9 + br label %scend4 +scend4: + %t35 = load i32, ptr %t9 + %t36 = icmp ne i32 %t35, 0 + %t37 = zext i1 %t36 to i32 + store i32 %t37, ptr %t8 + br i1 %t36, label %sc5, label %scend6 +sc5: + %t38 = load ptr, ptr @g_toks + %t39 = getelementptr inbounds %LSlice, ptr %t38, i32 0, i32 0 + %t40 = load ptr, ptr %t39 + %t41 = load i32, ptr @g_pi + %t42 = add i32 %t41, 1 + %t43 = getelementptr inbounds ptr, ptr %t40, i32 %t42 + %t44 = load ptr, ptr %t43 + %t45 = getelementptr inbounds %Str_Tok, ptr %t44, i32 0, i32 1 + %t46 = load ptr, ptr %t45 + %t47 = call i32 @fn_streq(ptr %t46, ptr @.str181) + %t48 = icmp ne i32 %t47, 0 + %t49 = zext i1 %t48 to i32 + store i32 %t49, ptr %t8 + br label %scend6 +scend6: + %t50 = load i32, ptr %t8 + %t51 = icmp ne i32 %t50, 0 + br i1 %t51, label %wbody1, label %wend2 +wbody1: + %t52 = call ptr @fn_node(i32 42) + store ptr %t52, ptr %t53 + %t54 = load ptr, ptr %t53 + %t55 = getelementptr inbounds %Str_Node, ptr %t54, i32 0, i32 1 + %t56 = call ptr @fn_eat_id() + store ptr %t56, ptr %t55 + call void @fn_eat_op(ptr @.str182) + %t57 = load ptr, ptr %t53 + %t58 = getelementptr inbounds %Str_Node, ptr %t57, i32 0, i32 4 + %t59 = call ptr @fn_expr() + store ptr %t59, ptr %t58 + %t60 = load ptr, ptr %t1 + %t61 = getelementptr inbounds %Str_Node, ptr %t60, i32 0, i32 5 + %t62 = load ptr, ptr %t61 + %t63 = getelementptr inbounds %Str_Node, ptr %t62, i32 0, i32 7 + %t64 = load ptr, ptr %t63 + %t65 = getelementptr inbounds %LSlice, ptr %t64, i32 0, i32 1 + %t66 = getelementptr inbounds %LSlice, ptr %t64, i32 0, i32 2 + %t67 = getelementptr inbounds %LSlice, ptr %t64, i32 0, i32 0 + %t68 = load i32, ptr %t65 + %t69 = load i32, ptr %t66 + %t70 = icmp sge i32 %t68, %t69 + br i1 %t70, label %grow7, label %put8 +grow7: + %t71 = mul i32 %t69, 2 + %t72 = icmp eq i32 %t69, 0 + %t73 = select i1 %t72, i32 8, i32 %t71 + %t74 = getelementptr ptr, ptr null, i32 1 + %t75 = ptrtoint ptr %t74 to i64 + %t76 = zext i32 %t73 to i64 + %t77 = mul i64 %t76, %t75 + %t78 = load ptr, ptr %t67 + %t79 = call ptr @realloc(ptr %t78, i64 %t77) + store ptr %t79, ptr %t67 + store i32 %t73, ptr %t66 + br label %put8 +put8: + %t80 = load ptr, ptr %t53 + %t81 = load ptr, ptr %t67 + %t82 = getelementptr inbounds ptr, ptr %t81, i32 %t68 + store ptr %t80, ptr %t82 + %t83 = add i32 %t68, 1 + store i32 %t83, ptr %t65 + br label %wcond0 +wend2: + call void @fn_skipnl() + %t84 = call i32 @fn_is_op(ptr @.str183) + %t85 = icmp ne i32 %t84, 0 + br i1 %t85, label %then9, label %ifend11 +then9: + %t86 = load i32, ptr @g_pi + %t87 = add i32 %t86, 1 + store i32 %t87, ptr @g_pi + br label %wcond12 +wcond12: + %t88 = icmp ne i32 1, 0 + br i1 %t88, label %wbody13, label %wend14 +wbody13: + call void @fn_skipnl() + %t89 = call i32 @fn_is_op(ptr @.str184) + %t90 = icmp ne i32 %t89, 0 + br i1 %t90, label %then15, label %ifend17 +then15: + br label %wend14 +ifend17: + %t91 = load ptr, ptr %t1 + %t92 = getelementptr inbounds %Str_Node, ptr %t91, i32 0, i32 7 + %t93 = load ptr, ptr %t92 + %t94 = getelementptr inbounds %LSlice, ptr %t93, i32 0, i32 1 + %t95 = getelementptr inbounds %LSlice, ptr %t93, i32 0, i32 2 + %t96 = getelementptr inbounds %LSlice, ptr %t93, i32 0, i32 0 + %t97 = load i32, ptr %t94 + %t98 = load i32, ptr %t95 + %t99 = icmp sge i32 %t97, %t98 + br i1 %t99, label %grow18, label %put19 +grow18: + %t100 = mul i32 %t98, 2 + %t101 = icmp eq i32 %t98, 0 + %t102 = select i1 %t101, i32 8, i32 %t100 + %t103 = getelementptr ptr, ptr null, i32 1 + %t104 = ptrtoint ptr %t103 to i64 + %t105 = zext i32 %t102 to i64 + %t106 = mul i64 %t105, %t104 + %t107 = load ptr, ptr %t96 + %t108 = call ptr @realloc(ptr %t107, i64 %t106) + store ptr %t108, ptr %t96 + store i32 %t102, ptr %t95 + br label %put19 +put19: + %t109 = call ptr @fn_parse_widget() + %t110 = load ptr, ptr %t96 + %t111 = getelementptr inbounds ptr, ptr %t110, i32 %t97 + store ptr %t109, ptr %t111 + %t112 = add i32 %t97, 1 + store i32 %t112, ptr %t94 + br label %wcond12 +wend14: + call void @fn_eat_op(ptr @.str185) + br label %ifend11 +ifend11: + %t113 = load ptr, ptr %t1 + store ptr %t113, ptr %retval + br label %ret +ret: + %t114 = load ptr, ptr %retval + ret ptr %t114 +} + +define ptr @fn_parse_ui() { +entry: + %retval = alloca ptr + %t3 = alloca ptr + %t0 = load i32, ptr @g_pi + %t1 = add i32 %t0, 1 + store i32 %t1, ptr @g_pi + %t2 = call ptr @fn_node(i32 12) + store ptr %t2, ptr %t3 + %t4 = load ptr, ptr %t3 + %t5 = getelementptr inbounds %Str_Node, ptr %t4, i32 0, i32 1 + %t6 = call ptr @fn_eat_id() + store ptr %t6, ptr %t5 + %t7 = load ptr, ptr %t3 + %t8 = getelementptr inbounds %Str_Node, ptr %t7, i32 0, i32 2 + store i32 1, ptr %t8 + call void @fn_skipnl() + call void @fn_eat_op(ptr @.str186) + call void @fn_skipnl() + %t9 = load ptr, ptr %t3 + %t10 = getelementptr inbounds %Str_Node, ptr %t9, i32 0, i32 4 + %t11 = call ptr @fn_parse_widget() + store ptr %t11, ptr %t10 + call void @fn_skipnl() + call void @fn_eat_op(ptr @.str187) + %t12 = load ptr, ptr %t3 + store ptr %t12, ptr %retval + br label %ret +ret: + %t13 = load ptr, ptr %retval + ret ptr %t13 +} + +define ptr @fn_val(ptr %arg_code, ptr %arg_ty) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca ptr + %t7 = alloca ptr + store ptr %arg_code, ptr %t0 + store ptr %arg_ty, ptr %t1 + %t2 = getelementptr %Str_Val, ptr null, i32 1 + %t3 = ptrtoint ptr %t2 to i64 + %t4 = call ptr @malloc(i64 %t3) + %t5 = getelementptr inbounds %Str_Val, ptr %t4, i32 0, i32 0 + store ptr null, ptr %t5 + %t6 = getelementptr inbounds %Str_Val, ptr %t4, i32 0, i32 1 + store ptr null, ptr %t6 + store ptr %t4, ptr %t7 + %t8 = load ptr, ptr %t7 + %t9 = getelementptr inbounds %Str_Val, ptr %t8, i32 0, i32 0 + %t10 = load ptr, ptr %t0 + store ptr %t10, ptr %t9 + %t11 = load ptr, ptr %t7 + %t12 = getelementptr inbounds %Str_Val, ptr %t11, i32 0, i32 1 + %t13 = load ptr, ptr %t1 + store ptr %t13, ptr %t12 + %t14 = load ptr, ptr %t7 + store ptr %t14, ptr %retval + br label %ret +ret: + %t15 = load ptr, ptr %retval + ret ptr %t15 +} + +define void @fn_emit(ptr %arg_s) { +entry: + %t0 = alloca ptr + store ptr %arg_s, ptr %t0 + %t1 = load ptr, ptr @g_code + %t2 = load ptr, ptr %t0 + call void @fn_buf_puts(ptr %t1, ptr %t2) + br label %ret +ret: + ret void +} + +define void @fn_emith(ptr %arg_s) { +entry: + %t0 = alloca ptr + store ptr %arg_s, ptr %t0 + %t1 = load ptr, ptr @g_head + %t2 = load ptr, ptr %t0 + call void @fn_buf_puts(ptr %t1, ptr %t2) + br label %ret +ret: + ret void +} + +define ptr @fn_emit_alloca(ptr %arg_llt) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t4 = alloca ptr + store ptr %arg_llt, ptr %t0 + %t1 = load i32, ptr @g_ll_t + %t2 = call ptr @fn_itoa(i32 %t1) + %t3 = call ptr @fn_sconcat(ptr @.str188, ptr %t2) + store ptr %t3, ptr %t4 + %t5 = load i32, ptr @g_ll_t + %t6 = add i32 %t5, 1 + store i32 %t6, ptr @g_ll_t + %t7 = load ptr, ptr @g_falloc + call void @fn_buf_puts(ptr %t7, ptr @.str189) + %t8 = load ptr, ptr @g_falloc + %t9 = load ptr, ptr %t4 + call void @fn_buf_puts(ptr %t8, ptr %t9) + %t10 = load ptr, ptr @g_falloc + call void @fn_buf_puts(ptr %t10, ptr @.str190) + %t11 = load ptr, ptr @g_falloc + %t12 = load ptr, ptr %t0 + call void @fn_buf_puts(ptr %t11, ptr %t12) + %t13 = load ptr, ptr @g_falloc + call void @fn_buf_puts(ptr %t13, ptr @.str191) + %t14 = load ptr, ptr %t4 + store ptr %t14, ptr %retval + br label %ret +ret: + %t15 = load ptr, ptr %retval + ret ptr %t15 +} + +define ptr @fn_sconcat(ptr %arg_a, ptr %arg_b) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca ptr + %t4 = alloca i32 + %t7 = alloca i32 + %t14 = alloca ptr + %t15 = alloca i32 + %t32 = alloca i32 + store ptr %arg_a, ptr %t0 + store ptr %arg_b, ptr %t1 + %t2 = load ptr, ptr %t0 + %t3 = call i32 @fn_slen(ptr %t2) + store i32 %t3, ptr %t4 + %t5 = load ptr, ptr %t1 + %t6 = call i32 @fn_slen(ptr %t5) + store i32 %t6, ptr %t7 + %t8 = load i32, ptr %t4 + %t9 = load i32, ptr %t7 + %t10 = add i32 %t8, %t9 + %t11 = add i32 %t10, 1 + %t12 = zext i32 %t11 to i64 + %t13 = call ptr @malloc(i64 %t12) + store ptr %t13, ptr %t14 + store i32 0, ptr %t15 + br label %wcond0 +wcond0: + %t16 = load i32, ptr %t15 + %t17 = load i32, ptr %t4 + %t18 = icmp slt i32 %t16, %t17 + %t19 = zext i1 %t18 to i32 + %t20 = icmp ne i32 %t19, 0 + br i1 %t20, label %wbody1, label %wend2 +wbody1: + %t21 = load ptr, ptr %t14 + %t22 = load i32, ptr %t15 + %t23 = load ptr, ptr %t0 + %t24 = load i32, ptr %t15 + %t25 = getelementptr inbounds i8, ptr %t23, i32 %t24 + %t26 = load i8, ptr %t25 + %t27 = zext i8 %t26 to i32 + %t28 = getelementptr inbounds i8, ptr %t21, i32 %t22 + %t29 = trunc i32 %t27 to i8 + store i8 %t29, ptr %t28 + %t30 = load i32, ptr %t15 + %t31 = add i32 %t30, 1 + store i32 %t31, ptr %t15 + br label %wcond0 +wend2: + store i32 0, ptr %t32 + br label %wcond3 +wcond3: + %t33 = load i32, ptr %t32 + %t34 = load i32, ptr %t7 + %t35 = icmp slt i32 %t33, %t34 + %t36 = zext i1 %t35 to i32 + %t37 = icmp ne i32 %t36, 0 + br i1 %t37, label %wbody4, label %wend5 +wbody4: + %t38 = load ptr, ptr %t14 + %t39 = load i32, ptr %t4 + %t40 = load i32, ptr %t32 + %t41 = add i32 %t39, %t40 + %t42 = load ptr, ptr %t1 + %t43 = load i32, ptr %t32 + %t44 = getelementptr inbounds i8, ptr %t42, i32 %t43 + %t45 = load i8, ptr %t44 + %t46 = zext i8 %t45 to i32 + %t47 = getelementptr inbounds i8, ptr %t38, i32 %t41 + %t48 = trunc i32 %t46 to i8 + store i8 %t48, ptr %t47 + %t49 = load i32, ptr %t32 + %t50 = add i32 %t49, 1 + store i32 %t50, ptr %t32 + br label %wcond3 +wend5: + %t51 = load ptr, ptr %t14 + %t52 = load i32, ptr %t4 + %t53 = load i32, ptr %t7 + %t54 = add i32 %t52, %t53 + %t55 = getelementptr inbounds i8, ptr %t51, i32 %t54 + %t56 = trunc i32 0 to i8 + store i8 %t56, ptr %t55 + %t57 = load ptr, ptr %t14 + store ptr %t57, ptr %retval + br label %ret +ret: + %t58 = load ptr, ptr %retval + ret ptr %t58 +} + +define ptr @fn_nreg() { +entry: + %retval = alloca ptr + %t3 = alloca ptr + %t0 = load i32, ptr @g_ll_t + %t1 = call ptr @fn_itoa(i32 %t0) + %t2 = call ptr @fn_sconcat(ptr @.str192, ptr %t1) + store ptr %t2, ptr %t3 + %t4 = load i32, ptr @g_ll_t + %t5 = add i32 %t4, 1 + store i32 %t5, ptr @g_ll_t + %t6 = load ptr, ptr %t3 + store ptr %t6, ptr %retval + br label %ret +ret: + %t7 = load ptr, ptr %retval + ret ptr %t7 +} + +define ptr @fn_lbl(ptr %arg_pfx) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t5 = alloca ptr + store ptr %arg_pfx, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = load i32, ptr @g_ll_lbl + %t3 = call ptr @fn_itoa(i32 %t2) + %t4 = call ptr @fn_sconcat(ptr %t1, ptr %t3) + store ptr %t4, ptr %t5 + %t6 = load i32, ptr @g_ll_lbl + %t7 = add i32 %t6, 1 + store i32 %t7, ptr @g_ll_lbl + %t8 = load ptr, ptr %t5 + store ptr %t8, ptr %retval + br label %ret +ret: + %t9 = load ptr, ptr %retval + ret ptr %t9 +} + +define ptr @fn_llty(ptr %arg_t) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca i32 + %t2 = alloca i32 + store ptr %arg_t, ptr %t0 + %t3 = load ptr, ptr %t0 + %t4 = call i32 @fn_streq(ptr %t3, ptr @.str193) + %t5 = icmp ne i32 %t4, 0 + %t6 = zext i1 %t5 to i32 + store i32 %t6, ptr %t2 + br i1 %t5, label %scend1, label %sc0 +sc0: + %t7 = load ptr, ptr %t0 + %t8 = call i32 @fn_streq(ptr %t7, ptr @.str194) + %t9 = icmp ne i32 %t8, 0 + %t10 = zext i1 %t9 to i32 + store i32 %t10, ptr %t2 + br label %scend1 +scend1: + %t11 = load i32, ptr %t2 + %t12 = icmp ne i32 %t11, 0 + %t13 = zext i1 %t12 to i32 + store i32 %t13, ptr %t1 + br i1 %t12, label %scend3, label %sc2 +sc2: + %t14 = load ptr, ptr %t0 + %t15 = call i32 @fn_streq(ptr %t14, ptr @.str195) + %t16 = icmp ne i32 %t15, 0 + %t17 = zext i1 %t16 to i32 + store i32 %t17, ptr %t1 + br label %scend3 +scend3: + %t18 = load i32, ptr %t1 + %t19 = icmp ne i32 %t18, 0 + br i1 %t19, label %then4, label %ifend6 +then4: + store ptr @.str196, ptr %retval + br label %ret +ifend6: + %t20 = load ptr, ptr %t0 + %t21 = call i32 @fn_streq(ptr %t20, ptr @.str197) + %t22 = icmp ne i32 %t21, 0 + br i1 %t22, label %then7, label %ifend9 +then7: + store ptr @.str198, ptr %retval + br label %ret +ifend9: + store ptr @.str199, ptr %retval + br label %ret +ret: + %t23 = load ptr, ptr %retval + ret ptr %t23 +} + +define i32 @fn_is_slice_ty(ptr %arg_t) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t1 = alloca i32 + store ptr %arg_t, ptr %t0 + %t2 = load ptr, ptr %t0 + %t3 = getelementptr inbounds i8, ptr %t2, i32 0 + %t4 = load i8, ptr %t3 + %t5 = zext i8 %t4 to i32 + %t6 = icmp eq i32 %t5, 91 + %t7 = zext i1 %t6 to i32 + %t8 = icmp ne i32 %t7, 0 + %t9 = zext i1 %t8 to i32 + store i32 %t9, ptr %t1 + br i1 %t8, label %sc0, label %scend1 +sc0: + %t10 = load ptr, ptr %t0 + %t11 = getelementptr inbounds i8, ptr %t10, i32 1 + %t12 = load i8, ptr %t11 + %t13 = zext i8 %t12 to i32 + %t14 = icmp eq i32 %t13, 93 + %t15 = zext i1 %t14 to i32 + %t16 = icmp ne i32 %t15, 0 + %t17 = zext i1 %t16 to i32 + store i32 %t17, ptr %t1 + br label %scend1 +scend1: + %t18 = load i32, ptr %t1 + store i32 %t18, ptr %retval + br label %ret +ret: + %t19 = load i32, ptr %retval + ret i32 %t19 +} + +define ptr @fn_slice_elem(ptr %arg_t) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + store ptr %arg_t, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = load ptr, ptr %t0 + %t3 = call i32 @fn_slen(ptr %t2) + %t4 = sub i32 %t3, 2 + %t5 = call ptr @fn_substr(ptr %t1, i32 2, i32 %t4) + store ptr %t5, ptr %retval + br label %ret +ret: + %t6 = load ptr, ptr %retval + ret ptr %t6 +} + +define ptr @fn_find_struct(ptr %arg_name) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca i32 + %t15 = alloca ptr + %t16 = alloca i32 + store ptr %arg_name, ptr %t0 + store i32 0, ptr %t1 + br label %wcond0 +wcond0: + %t2 = load i32, ptr %t1 + %t3 = load ptr, ptr @g_prog + %t4 = getelementptr inbounds %LSlice, ptr %t3, i32 0, i32 1 + %t5 = load i32, ptr %t4 + %t6 = icmp slt i32 %t2, %t5 + %t7 = zext i1 %t6 to i32 + %t8 = icmp ne i32 %t7, 0 + br i1 %t8, label %wbody1, label %wend2 +wbody1: + %t9 = load ptr, ptr @g_prog + %t10 = getelementptr inbounds %LSlice, ptr %t9, i32 0, i32 0 + %t11 = load ptr, ptr %t10 + %t12 = load i32, ptr %t1 + %t13 = getelementptr inbounds ptr, ptr %t11, i32 %t12 + %t14 = load ptr, ptr %t13 + store ptr %t14, ptr %t15 + %t17 = load ptr, ptr %t15 + %t18 = getelementptr inbounds %Str_Node, ptr %t17, i32 0, i32 0 + %t19 = load i32, ptr %t18 + %t20 = icmp eq i32 %t19, 0 + %t21 = zext i1 %t20 to i32 + %t22 = icmp ne i32 %t21, 0 + %t23 = zext i1 %t22 to i32 + store i32 %t23, ptr %t16 + br i1 %t22, label %sc3, label %scend4 +sc3: + %t24 = load ptr, ptr %t15 + %t25 = getelementptr inbounds %Str_Node, ptr %t24, i32 0, i32 1 + %t26 = load ptr, ptr %t25 + %t27 = load ptr, ptr %t0 + %t28 = call i32 @fn_streq(ptr %t26, ptr %t27) + %t29 = icmp ne i32 %t28, 0 + %t30 = zext i1 %t29 to i32 + store i32 %t30, ptr %t16 + br label %scend4 +scend4: + %t31 = load i32, ptr %t16 + %t32 = icmp ne i32 %t31, 0 + br i1 %t32, label %then5, label %ifend7 +then5: + %t33 = load ptr, ptr %t15 + store ptr %t33, ptr %retval + br label %ret +ifend7: + %t34 = load i32, ptr %t1 + %t35 = add i32 %t34, 1 + store i32 %t35, ptr %t1 + br label %wcond0 +wend2: + store ptr null, ptr %retval + br label %ret +ret: + %t36 = load ptr, ptr %retval + ret ptr %t36 +} + +define i32 @fn_is_struct_ty(ptr %arg_t) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + store ptr %arg_t, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = call ptr @fn_find_struct(ptr %t1) + %t3 = icmp eq ptr %t2, null + %t4 = zext i1 %t3 to i32 + %t5 = icmp eq i32 %t4, 0 + %t6 = zext i1 %t5 to i32 + store i32 %t6, ptr %retval + br label %ret +ret: + %t7 = load i32, ptr %retval + ret i32 %t7 +} + +define ptr @fn_find_arch(ptr %arg_name) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca i32 + %t15 = alloca ptr + %t16 = alloca i32 + store ptr %arg_name, ptr %t0 + store i32 0, ptr %t1 + br label %wcond0 +wcond0: + %t2 = load i32, ptr %t1 + %t3 = load ptr, ptr @g_prog + %t4 = getelementptr inbounds %LSlice, ptr %t3, i32 0, i32 1 + %t5 = load i32, ptr %t4 + %t6 = icmp slt i32 %t2, %t5 + %t7 = zext i1 %t6 to i32 + %t8 = icmp ne i32 %t7, 0 + br i1 %t8, label %wbody1, label %wend2 +wbody1: + %t9 = load ptr, ptr @g_prog + %t10 = getelementptr inbounds %LSlice, ptr %t9, i32 0, i32 0 + %t11 = load ptr, ptr %t10 + %t12 = load i32, ptr %t1 + %t13 = getelementptr inbounds ptr, ptr %t11, i32 %t12 + %t14 = load ptr, ptr %t13 + store ptr %t14, ptr %t15 + %t17 = load ptr, ptr %t15 + %t18 = getelementptr inbounds %Str_Node, ptr %t17, i32 0, i32 0 + %t19 = load i32, ptr %t18 + %t20 = icmp eq i32 %t19, 10 + %t21 = zext i1 %t20 to i32 + %t22 = icmp ne i32 %t21, 0 + %t23 = zext i1 %t22 to i32 + store i32 %t23, ptr %t16 + br i1 %t22, label %sc3, label %scend4 +sc3: + %t24 = load ptr, ptr %t15 + %t25 = getelementptr inbounds %Str_Node, ptr %t24, i32 0, i32 1 + %t26 = load ptr, ptr %t25 + %t27 = load ptr, ptr %t0 + %t28 = call i32 @fn_streq(ptr %t26, ptr %t27) + %t29 = icmp ne i32 %t28, 0 + %t30 = zext i1 %t29 to i32 + store i32 %t30, ptr %t16 + br label %scend4 +scend4: + %t31 = load i32, ptr %t16 + %t32 = icmp ne i32 %t31, 0 + br i1 %t32, label %then5, label %ifend7 +then5: + %t33 = load ptr, ptr %t15 + store ptr %t33, ptr %retval + br label %ret +ifend7: + %t34 = load i32, ptr %t1 + %t35 = add i32 %t34, 1 + store i32 %t35, ptr %t1 + br label %wcond0 +wend2: + store ptr null, ptr %retval + br label %ret +ret: + %t36 = load ptr, ptr %retval + ret ptr %t36 +} + +define ptr @fn_find_comp(ptr %arg_name) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca i32 + %t15 = alloca ptr + %t16 = alloca i32 + store ptr %arg_name, ptr %t0 + store i32 0, ptr %t1 + br label %wcond0 +wcond0: + %t2 = load i32, ptr %t1 + %t3 = load ptr, ptr @g_prog + %t4 = getelementptr inbounds %LSlice, ptr %t3, i32 0, i32 1 + %t5 = load i32, ptr %t4 + %t6 = icmp slt i32 %t2, %t5 + %t7 = zext i1 %t6 to i32 + %t8 = icmp ne i32 %t7, 0 + br i1 %t8, label %wbody1, label %wend2 +wbody1: + %t9 = load ptr, ptr @g_prog + %t10 = getelementptr inbounds %LSlice, ptr %t9, i32 0, i32 0 + %t11 = load ptr, ptr %t10 + %t12 = load i32, ptr %t1 + %t13 = getelementptr inbounds ptr, ptr %t11, i32 %t12 + %t14 = load ptr, ptr %t13 + store ptr %t14, ptr %t15 + %t17 = load ptr, ptr %t15 + %t18 = getelementptr inbounds %Str_Node, ptr %t17, i32 0, i32 0 + %t19 = load i32, ptr %t18 + %t20 = icmp eq i32 %t19, 8 + %t21 = zext i1 %t20 to i32 + %t22 = icmp ne i32 %t21, 0 + %t23 = zext i1 %t22 to i32 + store i32 %t23, ptr %t16 + br i1 %t22, label %sc3, label %scend4 +sc3: + %t24 = load ptr, ptr %t15 + %t25 = getelementptr inbounds %Str_Node, ptr %t24, i32 0, i32 1 + %t26 = load ptr, ptr %t25 + %t27 = load ptr, ptr %t0 + %t28 = call i32 @fn_streq(ptr %t26, ptr %t27) + %t29 = icmp ne i32 %t28, 0 + %t30 = zext i1 %t29 to i32 + store i32 %t30, ptr %t16 + br label %scend4 +scend4: + %t31 = load i32, ptr %t16 + %t32 = icmp ne i32 %t31, 0 + br i1 %t32, label %then5, label %ifend7 +then5: + %t33 = load ptr, ptr %t15 + store ptr %t33, ptr %retval + br label %ret +ifend7: + %t34 = load i32, ptr %t1 + %t35 = add i32 %t34, 1 + store i32 %t35, ptr %t1 + br label %wcond0 +wend2: + store ptr null, ptr %retval + br label %ret +ret: + %t36 = load ptr, ptr %retval + ret ptr %t36 +} + +define ptr @fn_layout_node(ptr %arg_name) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t3 = alloca ptr + store ptr %arg_name, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = call ptr @fn_find_struct(ptr %t1) + store ptr %t2, ptr %t3 + %t4 = load ptr, ptr %t3 + %t5 = icmp eq ptr %t4, null + %t6 = zext i1 %t5 to i32 + %t7 = icmp eq i32 %t6, 0 + %t8 = zext i1 %t7 to i32 + %t9 = icmp ne i32 %t8, 0 + br i1 %t9, label %then0, label %ifend2 +then0: + %t10 = load ptr, ptr %t3 + store ptr %t10, ptr %retval + br label %ret +ifend2: + %t11 = load ptr, ptr %t0 + %t12 = call ptr @fn_find_comp(ptr %t11) + store ptr %t12, ptr %retval + br label %ret +ret: + %t13 = load ptr, ptr %retval + ret ptr %t13 +} + +define ptr @fn_layout_ty(ptr %arg_name) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + store ptr %arg_name, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = call ptr @fn_find_struct(ptr %t1) + %t3 = icmp eq ptr %t2, null + %t4 = zext i1 %t3 to i32 + %t5 = icmp eq i32 %t4, 0 + %t6 = zext i1 %t5 to i32 + %t7 = icmp ne i32 %t6, 0 + br i1 %t7, label %then0, label %ifend2 +then0: + %t8 = load ptr, ptr %t0 + %t9 = call ptr @fn_sconcat(ptr @.str200, ptr %t8) + store ptr %t9, ptr %retval + br label %ret +ifend2: + %t10 = load ptr, ptr %t0 + %t11 = call ptr @fn_sconcat(ptr @.str201, ptr %t10) + store ptr %t11, ptr %retval + br label %ret +ret: + %t12 = load ptr, ptr %retval + ret ptr %t12 +} + +define i32 @fn_field_index(ptr %arg_s, ptr %arg_fname) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t1 = alloca ptr + %t2 = alloca i32 + store ptr %arg_s, ptr %t0 + store ptr %arg_fname, ptr %t1 + store i32 0, ptr %t2 + br label %wcond0 +wcond0: + %t3 = load i32, ptr %t2 + %t4 = load ptr, ptr %t0 + %t5 = getelementptr inbounds %Str_Node, ptr %t4, i32 0, i32 7 + %t6 = load ptr, ptr %t5 + %t7 = getelementptr inbounds %LSlice, ptr %t6, i32 0, i32 1 + %t8 = load i32, ptr %t7 + %t9 = icmp slt i32 %t3, %t8 + %t10 = zext i1 %t9 to i32 + %t11 = icmp ne i32 %t10, 0 + br i1 %t11, label %wbody1, label %wend2 +wbody1: + %t12 = load ptr, ptr %t0 + %t13 = getelementptr inbounds %Str_Node, ptr %t12, i32 0, i32 7 + %t14 = load ptr, ptr %t13 + %t15 = getelementptr inbounds %LSlice, ptr %t14, i32 0, i32 0 + %t16 = load ptr, ptr %t15 + %t17 = load i32, ptr %t2 + %t18 = getelementptr inbounds ptr, ptr %t16, i32 %t17 + %t19 = load ptr, ptr %t18 + %t20 = getelementptr inbounds %Str_Node, ptr %t19, i32 0, i32 1 + %t21 = load ptr, ptr %t20 + %t22 = load ptr, ptr %t1 + %t23 = call i32 @fn_streq(ptr %t21, ptr %t22) + %t24 = icmp ne i32 %t23, 0 + br i1 %t24, label %then3, label %ifend5 +then3: + %t25 = load i32, ptr %t2 + store i32 %t25, ptr %retval + br label %ret +ifend5: + %t26 = load i32, ptr %t2 + %t27 = add i32 %t26, 1 + store i32 %t27, ptr %t2 + br label %wcond0 +wend2: + %t28 = sub i32 0, 1 + store i32 %t28, ptr %retval + br label %ret +ret: + %t29 = load i32, ptr %retval + ret i32 %t29 +} + +define ptr @fn_field_type(ptr %arg_s, ptr %arg_fname) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca ptr + %t2 = alloca i32 + store ptr %arg_s, ptr %t0 + store ptr %arg_fname, ptr %t1 + store i32 0, ptr %t2 + br label %wcond0 +wcond0: + %t3 = load i32, ptr %t2 + %t4 = load ptr, ptr %t0 + %t5 = getelementptr inbounds %Str_Node, ptr %t4, i32 0, i32 7 + %t6 = load ptr, ptr %t5 + %t7 = getelementptr inbounds %LSlice, ptr %t6, i32 0, i32 1 + %t8 = load i32, ptr %t7 + %t9 = icmp slt i32 %t3, %t8 + %t10 = zext i1 %t9 to i32 + %t11 = icmp ne i32 %t10, 0 + br i1 %t11, label %wbody1, label %wend2 +wbody1: + %t12 = load ptr, ptr %t0 + %t13 = getelementptr inbounds %Str_Node, ptr %t12, i32 0, i32 7 + %t14 = load ptr, ptr %t13 + %t15 = getelementptr inbounds %LSlice, ptr %t14, i32 0, i32 0 + %t16 = load ptr, ptr %t15 + %t17 = load i32, ptr %t2 + %t18 = getelementptr inbounds ptr, ptr %t16, i32 %t17 + %t19 = load ptr, ptr %t18 + %t20 = getelementptr inbounds %Str_Node, ptr %t19, i32 0, i32 1 + %t21 = load ptr, ptr %t20 + %t22 = load ptr, ptr %t1 + %t23 = call i32 @fn_streq(ptr %t21, ptr %t22) + %t24 = icmp ne i32 %t23, 0 + br i1 %t24, label %then3, label %ifend5 +then3: + %t25 = load ptr, ptr %t0 + %t26 = getelementptr inbounds %Str_Node, ptr %t25, i32 0, i32 7 + %t27 = load ptr, ptr %t26 + %t28 = getelementptr inbounds %LSlice, ptr %t27, i32 0, i32 0 + %t29 = load ptr, ptr %t28 + %t30 = load i32, ptr %t2 + %t31 = getelementptr inbounds ptr, ptr %t29, i32 %t30 + %t32 = load ptr, ptr %t31 + %t33 = getelementptr inbounds %Str_Node, ptr %t32, i32 0, i32 3 + %t34 = load ptr, ptr %t33 + store ptr %t34, ptr %retval + br label %ret +ifend5: + %t35 = load i32, ptr %t2 + %t36 = add i32 %t35, 1 + store i32 %t36, ptr %t2 + br label %wcond0 +wend2: + store ptr @.str202, ptr %retval + br label %ret +ret: + %t37 = load ptr, ptr %retval + ret ptr %t37 +} + +define ptr @fn_find_global(ptr %arg_name) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca i32 + %t15 = alloca ptr + %t16 = alloca i32 + %t34 = alloca i32 + store ptr %arg_name, ptr %t0 + store i32 0, ptr %t1 + br label %wcond0 +wcond0: + %t2 = load i32, ptr %t1 + %t3 = load ptr, ptr @g_prog + %t4 = getelementptr inbounds %LSlice, ptr %t3, i32 0, i32 1 + %t5 = load i32, ptr %t4 + %t6 = icmp slt i32 %t2, %t5 + %t7 = zext i1 %t6 to i32 + %t8 = icmp ne i32 %t7, 0 + br i1 %t8, label %wbody1, label %wend2 +wbody1: + %t9 = load ptr, ptr @g_prog + %t10 = getelementptr inbounds %LSlice, ptr %t9, i32 0, i32 0 + %t11 = load ptr, ptr %t10 + %t12 = load i32, ptr %t1 + %t13 = getelementptr inbounds ptr, ptr %t11, i32 %t12 + %t14 = load ptr, ptr %t13 + store ptr %t14, ptr %t15 + %t17 = load ptr, ptr %t15 + %t18 = getelementptr inbounds %Str_Node, ptr %t17, i32 0, i32 0 + %t19 = load i32, ptr %t18 + %t20 = icmp eq i32 %t19, 2 + %t21 = zext i1 %t20 to i32 + %t22 = icmp ne i32 %t21, 0 + %t23 = zext i1 %t22 to i32 + store i32 %t23, ptr %t16 + br i1 %t22, label %sc3, label %scend4 +sc3: + %t24 = load ptr, ptr %t15 + %t25 = getelementptr inbounds %Str_Node, ptr %t24, i32 0, i32 1 + %t26 = load ptr, ptr %t25 + %t27 = load ptr, ptr %t0 + %t28 = call i32 @fn_streq(ptr %t26, ptr %t27) + %t29 = icmp ne i32 %t28, 0 + %t30 = zext i1 %t29 to i32 + store i32 %t30, ptr %t16 + br label %scend4 +scend4: + %t31 = load i32, ptr %t16 + %t32 = icmp ne i32 %t31, 0 + br i1 %t32, label %then5, label %ifend7 +then5: + %t33 = load ptr, ptr %t15 + store ptr %t33, ptr %retval + br label %ret +ifend7: + %t35 = load ptr, ptr %t15 + %t36 = getelementptr inbounds %Str_Node, ptr %t35, i32 0, i32 0 + %t37 = load i32, ptr %t36 + %t38 = icmp eq i32 %t37, 3 + %t39 = zext i1 %t38 to i32 + %t40 = icmp ne i32 %t39, 0 + %t41 = zext i1 %t40 to i32 + store i32 %t41, ptr %t34 + br i1 %t40, label %sc8, label %scend9 +sc8: + %t42 = load ptr, ptr %t15 + %t43 = getelementptr inbounds %Str_Node, ptr %t42, i32 0, i32 1 + %t44 = load ptr, ptr %t43 + %t45 = load ptr, ptr %t0 + %t46 = call i32 @fn_streq(ptr %t44, ptr %t45) + %t47 = icmp ne i32 %t46, 0 + %t48 = zext i1 %t47 to i32 + store i32 %t48, ptr %t34 + br label %scend9 +scend9: + %t49 = load i32, ptr %t34 + %t50 = icmp ne i32 %t49, 0 + br i1 %t50, label %then10, label %ifend12 +then10: + %t51 = load ptr, ptr %t15 + store ptr %t51, ptr %retval + br label %ret +ifend12: + %t52 = load i32, ptr %t1 + %t53 = add i32 %t52, 1 + store i32 %t53, ptr %t1 + br label %wcond0 +wend2: + store ptr null, ptr %retval + br label %ret +ret: + %t54 = load ptr, ptr %retval + ret ptr %t54 +} + +define ptr @fn_find_fn(ptr %arg_name) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca i32 + %t15 = alloca ptr + %t16 = alloca i32 + store ptr %arg_name, ptr %t0 + store i32 0, ptr %t1 + br label %wcond0 +wcond0: + %t2 = load i32, ptr %t1 + %t3 = load ptr, ptr @g_prog + %t4 = getelementptr inbounds %LSlice, ptr %t3, i32 0, i32 1 + %t5 = load i32, ptr %t4 + %t6 = icmp slt i32 %t2, %t5 + %t7 = zext i1 %t6 to i32 + %t8 = icmp ne i32 %t7, 0 + br i1 %t8, label %wbody1, label %wend2 +wbody1: + %t9 = load ptr, ptr @g_prog + %t10 = getelementptr inbounds %LSlice, ptr %t9, i32 0, i32 0 + %t11 = load ptr, ptr %t10 + %t12 = load i32, ptr %t1 + %t13 = getelementptr inbounds ptr, ptr %t11, i32 %t12 + %t14 = load ptr, ptr %t13 + store ptr %t14, ptr %t15 + %t17 = load ptr, ptr %t15 + %t18 = getelementptr inbounds %Str_Node, ptr %t17, i32 0, i32 0 + %t19 = load i32, ptr %t18 + %t20 = icmp eq i32 %t19, 4 + %t21 = zext i1 %t20 to i32 + %t22 = icmp ne i32 %t21, 0 + %t23 = zext i1 %t22 to i32 + store i32 %t23, ptr %t16 + br i1 %t22, label %sc3, label %scend4 +sc3: + %t24 = load ptr, ptr %t15 + %t25 = getelementptr inbounds %Str_Node, ptr %t24, i32 0, i32 1 + %t26 = load ptr, ptr %t25 + %t27 = load ptr, ptr %t0 + %t28 = call i32 @fn_streq(ptr %t26, ptr %t27) + %t29 = icmp ne i32 %t28, 0 + %t30 = zext i1 %t29 to i32 + store i32 %t30, ptr %t16 + br label %scend4 +scend4: + %t31 = load i32, ptr %t16 + %t32 = icmp ne i32 %t31, 0 + br i1 %t32, label %then5, label %ifend7 +then5: + %t33 = load ptr, ptr %t15 + store ptr %t33, ptr %retval + br label %ret +ifend7: + %t34 = load i32, ptr %t1 + %t35 = add i32 %t34, 1 + store i32 %t35, ptr %t1 + br label %wcond0 +wend2: + store ptr null, ptr %retval + br label %ret +ret: + %t36 = load ptr, ptr %retval + ret ptr %t36 +} + +define void @fn_loc_reset() { +entry: + store i32 0, ptr @g_nloc + br label %ret +ret: + ret void +} + +define void @fn_loc_push(ptr %arg_name, ptr %arg_r, ptr %arg_ty) { +entry: + %t0 = alloca ptr + %t1 = alloca ptr + %t2 = alloca ptr + store ptr %arg_name, ptr %t0 + store ptr %arg_r, ptr %t1 + store ptr %arg_ty, ptr %t2 + %t3 = load i32, ptr @g_nloc + %t4 = load ptr, ptr @g_loc_name + %t5 = getelementptr inbounds %LSlice, ptr %t4, i32 0, i32 1 + %t6 = load i32, ptr %t5 + %t7 = icmp slt i32 %t3, %t6 + %t8 = zext i1 %t7 to i32 + %t9 = icmp ne i32 %t8, 0 + br i1 %t9, label %then0, label %else1 +then0: + %t10 = load ptr, ptr @g_loc_name + %t11 = getelementptr inbounds %LSlice, ptr %t10, i32 0, i32 0 + %t12 = load ptr, ptr %t11 + %t13 = load i32, ptr @g_nloc + %t14 = getelementptr inbounds ptr, ptr %t12, i32 %t13 + %t15 = load ptr, ptr %t0 + store ptr %t15, ptr %t14 + %t16 = load ptr, ptr @g_loc_reg + %t17 = getelementptr inbounds %LSlice, ptr %t16, i32 0, i32 0 + %t18 = load ptr, ptr %t17 + %t19 = load i32, ptr @g_nloc + %t20 = getelementptr inbounds ptr, ptr %t18, i32 %t19 + %t21 = load ptr, ptr %t1 + store ptr %t21, ptr %t20 + %t22 = load ptr, ptr @g_loc_ty + %t23 = getelementptr inbounds %LSlice, ptr %t22, i32 0, i32 0 + %t24 = load ptr, ptr %t23 + %t25 = load i32, ptr @g_nloc + %t26 = getelementptr inbounds ptr, ptr %t24, i32 %t25 + %t27 = load ptr, ptr %t2 + store ptr %t27, ptr %t26 + br label %ifend2 +else1: + %t28 = load ptr, ptr @g_loc_name + %t29 = getelementptr inbounds %LSlice, ptr %t28, i32 0, i32 1 + %t30 = getelementptr inbounds %LSlice, ptr %t28, i32 0, i32 2 + %t31 = getelementptr inbounds %LSlice, ptr %t28, i32 0, i32 0 + %t32 = load i32, ptr %t29 + %t33 = load i32, ptr %t30 + %t34 = icmp sge i32 %t32, %t33 + br i1 %t34, label %grow3, label %put4 +grow3: + %t35 = mul i32 %t33, 2 + %t36 = icmp eq i32 %t33, 0 + %t37 = select i1 %t36, i32 8, i32 %t35 + %t38 = getelementptr ptr, ptr null, i32 1 + %t39 = ptrtoint ptr %t38 to i64 + %t40 = zext i32 %t37 to i64 + %t41 = mul i64 %t40, %t39 + %t42 = load ptr, ptr %t31 + %t43 = call ptr @realloc(ptr %t42, i64 %t41) + store ptr %t43, ptr %t31 + store i32 %t37, ptr %t30 + br label %put4 +put4: + %t44 = load ptr, ptr %t0 + %t45 = load ptr, ptr %t31 + %t46 = getelementptr inbounds ptr, ptr %t45, i32 %t32 + store ptr %t44, ptr %t46 + %t47 = add i32 %t32, 1 + store i32 %t47, ptr %t29 + %t48 = load ptr, ptr @g_loc_reg + %t49 = getelementptr inbounds %LSlice, ptr %t48, i32 0, i32 1 + %t50 = getelementptr inbounds %LSlice, ptr %t48, i32 0, i32 2 + %t51 = getelementptr inbounds %LSlice, ptr %t48, i32 0, i32 0 + %t52 = load i32, ptr %t49 + %t53 = load i32, ptr %t50 + %t54 = icmp sge i32 %t52, %t53 + br i1 %t54, label %grow5, label %put6 +grow5: + %t55 = mul i32 %t53, 2 + %t56 = icmp eq i32 %t53, 0 + %t57 = select i1 %t56, i32 8, i32 %t55 + %t58 = getelementptr ptr, ptr null, i32 1 + %t59 = ptrtoint ptr %t58 to i64 + %t60 = zext i32 %t57 to i64 + %t61 = mul i64 %t60, %t59 + %t62 = load ptr, ptr %t51 + %t63 = call ptr @realloc(ptr %t62, i64 %t61) + store ptr %t63, ptr %t51 + store i32 %t57, ptr %t50 + br label %put6 +put6: + %t64 = load ptr, ptr %t1 + %t65 = load ptr, ptr %t51 + %t66 = getelementptr inbounds ptr, ptr %t65, i32 %t52 + store ptr %t64, ptr %t66 + %t67 = add i32 %t52, 1 + store i32 %t67, ptr %t49 + %t68 = load ptr, ptr @g_loc_ty + %t69 = getelementptr inbounds %LSlice, ptr %t68, i32 0, i32 1 + %t70 = getelementptr inbounds %LSlice, ptr %t68, i32 0, i32 2 + %t71 = getelementptr inbounds %LSlice, ptr %t68, i32 0, i32 0 + %t72 = load i32, ptr %t69 + %t73 = load i32, ptr %t70 + %t74 = icmp sge i32 %t72, %t73 + br i1 %t74, label %grow7, label %put8 +grow7: + %t75 = mul i32 %t73, 2 + %t76 = icmp eq i32 %t73, 0 + %t77 = select i1 %t76, i32 8, i32 %t75 + %t78 = getelementptr ptr, ptr null, i32 1 + %t79 = ptrtoint ptr %t78 to i64 + %t80 = zext i32 %t77 to i64 + %t81 = mul i64 %t80, %t79 + %t82 = load ptr, ptr %t71 + %t83 = call ptr @realloc(ptr %t82, i64 %t81) + store ptr %t83, ptr %t71 + store i32 %t77, ptr %t70 + br label %put8 +put8: + %t84 = load ptr, ptr %t2 + %t85 = load ptr, ptr %t71 + %t86 = getelementptr inbounds ptr, ptr %t85, i32 %t72 + store ptr %t84, ptr %t86 + %t87 = add i32 %t72, 1 + store i32 %t87, ptr %t69 + br label %ifend2 +ifend2: + %t88 = load i32, ptr @g_nloc + %t89 = add i32 %t88, 1 + store i32 %t89, ptr @g_nloc + br label %ret +ret: + ret void +} + +define i32 @fn_loc_find(ptr %arg_name) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t3 = alloca i32 + store ptr %arg_name, ptr %t0 + %t1 = load i32, ptr @g_nloc + %t2 = sub i32 %t1, 1 + store i32 %t2, ptr %t3 + br label %wcond0 +wcond0: + %t4 = load i32, ptr %t3 + %t5 = icmp sge i32 %t4, 0 + %t6 = zext i1 %t5 to i32 + %t7 = icmp ne i32 %t6, 0 + br i1 %t7, label %wbody1, label %wend2 +wbody1: + %t8 = load ptr, ptr @g_loc_name + %t9 = getelementptr inbounds %LSlice, ptr %t8, i32 0, i32 0 + %t10 = load ptr, ptr %t9 + %t11 = load i32, ptr %t3 + %t12 = getelementptr inbounds ptr, ptr %t10, i32 %t11 + %t13 = load ptr, ptr %t12 + %t14 = load ptr, ptr %t0 + %t15 = call i32 @fn_streq(ptr %t13, ptr %t14) + %t16 = icmp ne i32 %t15, 0 + br i1 %t16, label %then3, label %ifend5 +then3: + %t17 = load i32, ptr %t3 + store i32 %t17, ptr %retval + br label %ret +ifend5: + %t18 = load i32, ptr %t3 + %t19 = sub i32 %t18, 1 + store i32 %t19, ptr %t3 + br label %wcond0 +wend2: + %t20 = sub i32 0, 1 + store i32 %t20, ptr %retval + br label %ret +ret: + %t21 = load i32, ptr %retval + ret i32 %t21 +} + +define i32 @fn_hexdig(i32 %arg_n) { +entry: + %retval = alloca i32 + %t0 = alloca i32 + store i32 %arg_n, ptr %t0 + %t1 = load i32, ptr %t0 + %t2 = icmp slt i32 %t1, 10 + %t3 = zext i1 %t2 to i32 + %t4 = icmp ne i32 %t3, 0 + br i1 %t4, label %then0, label %ifend2 +then0: + %t5 = load i32, ptr %t0 + %t6 = add i32 48, %t5 + store i32 %t6, ptr %retval + br label %ret +ifend2: + %t7 = load i32, ptr %t0 + %t8 = add i32 55, %t7 + store i32 %t8, ptr %retval + br label %ret +ret: + %t9 = load i32, ptr %retval + ret i32 %t9 +} + +define ptr @fn_emit_str_const(ptr %arg_s) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t4 = alloca ptr + %t9 = alloca i32 + %t14 = alloca i32 + %t25 = alloca i32 + %t26 = alloca i32 + %t27 = alloca i32 + %t28 = alloca i32 + store ptr %arg_s, ptr %t0 + %t1 = load i32, ptr @g_ll_str + %t2 = call ptr @fn_itoa(i32 %t1) + %t3 = call ptr @fn_sconcat(ptr @.str203, ptr %t2) + store ptr %t3, ptr %t4 + %t5 = load i32, ptr @g_ll_str + %t6 = add i32 %t5, 1 + store i32 %t6, ptr @g_ll_str + %t7 = load ptr, ptr %t0 + %t8 = call i32 @fn_slen(ptr %t7) + store i32 %t8, ptr %t9 + %t10 = load ptr, ptr %t4 + call void @fn_emith(ptr %t10) + call void @fn_emith(ptr @.str204) + %t11 = load i32, ptr %t9 + %t12 = add i32 %t11, 1 + %t13 = call ptr @fn_itoa(i32 %t12) + call void @fn_emith(ptr %t13) + call void @fn_emith(ptr @.str205) + store i32 0, ptr %t14 + br label %wcond0 +wcond0: + %t15 = load i32, ptr %t14 + %t16 = load i32, ptr %t9 + %t17 = icmp slt i32 %t15, %t16 + %t18 = zext i1 %t17 to i32 + %t19 = icmp ne i32 %t18, 0 + br i1 %t19, label %wbody1, label %wend2 +wbody1: + %t20 = load ptr, ptr %t0 + %t21 = load i32, ptr %t14 + %t22 = getelementptr inbounds i8, ptr %t20, i32 %t21 + %t23 = load i8, ptr %t22 + %t24 = zext i8 %t23 to i32 + store i32 %t24, ptr %t25 + %t29 = load i32, ptr %t25 + %t30 = icmp eq i32 %t29, 34 + %t31 = zext i1 %t30 to i32 + %t32 = icmp ne i32 %t31, 0 + %t33 = zext i1 %t32 to i32 + store i32 %t33, ptr %t28 + br i1 %t32, label %scend4, label %sc3 +sc3: + %t34 = load i32, ptr %t25 + %t35 = icmp eq i32 %t34, 92 + %t36 = zext i1 %t35 to i32 + %t37 = icmp ne i32 %t36, 0 + %t38 = zext i1 %t37 to i32 + store i32 %t38, ptr %t28 + br label %scend4 +scend4: + %t39 = load i32, ptr %t28 + %t40 = icmp ne i32 %t39, 0 + %t41 = zext i1 %t40 to i32 + store i32 %t41, ptr %t27 + br i1 %t40, label %scend6, label %sc5 +sc5: + %t42 = load i32, ptr %t25 + %t43 = icmp slt i32 %t42, 32 + %t44 = zext i1 %t43 to i32 + %t45 = icmp ne i32 %t44, 0 + %t46 = zext i1 %t45 to i32 + store i32 %t46, ptr %t27 + br label %scend6 +scend6: + %t47 = load i32, ptr %t27 + %t48 = icmp ne i32 %t47, 0 + %t49 = zext i1 %t48 to i32 + store i32 %t49, ptr %t26 + br i1 %t48, label %scend8, label %sc7 +sc7: + %t50 = load i32, ptr %t25 + %t51 = icmp sgt i32 %t50, 126 + %t52 = zext i1 %t51 to i32 + %t53 = icmp ne i32 %t52, 0 + %t54 = zext i1 %t53 to i32 + store i32 %t54, ptr %t26 + br label %scend8 +scend8: + %t55 = load i32, ptr %t26 + %t56 = icmp ne i32 %t55, 0 + br i1 %t56, label %then9, label %else10 +then9: + %t57 = load ptr, ptr @g_head + call void @fn_buf_putc(ptr %t57, i32 92) + %t58 = load ptr, ptr @g_head + %t59 = load i32, ptr %t25 + %t60 = sdiv i32 %t59, 16 + %t61 = call i32 @fn_hexdig(i32 %t60) + call void @fn_buf_putc(ptr %t58, i32 %t61) + %t62 = load ptr, ptr @g_head + %t63 = load i32, ptr %t25 + %t64 = srem i32 %t63, 16 + %t65 = call i32 @fn_hexdig(i32 %t64) + call void @fn_buf_putc(ptr %t62, i32 %t65) + br label %ifend11 +else10: + %t66 = load ptr, ptr @g_head + %t67 = load i32, ptr %t25 + call void @fn_buf_putc(ptr %t66, i32 %t67) + br label %ifend11 +ifend11: + %t68 = load i32, ptr %t14 + %t69 = add i32 %t68, 1 + store i32 %t69, ptr %t14 + br label %wcond0 +wend2: + call void @fn_emith(ptr @.str206) + %t70 = load ptr, ptr %t4 + store ptr %t70, ptr %retval + br label %ret +ret: + %t71 = load ptr, ptr %retval + ret ptr %t71 +} + +define ptr @fn_emit_gep_i8(ptr %arg_base, ptr %arg_idx) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca ptr + %t3 = alloca ptr + store ptr %arg_base, ptr %t0 + store ptr %arg_idx, ptr %t1 + %t2 = call ptr @fn_nreg() + store ptr %t2, ptr %t3 + call void @fn_emit(ptr @.str207) + %t4 = load ptr, ptr %t3 + call void @fn_emit(ptr %t4) + call void @fn_emit(ptr @.str208) + %t5 = load ptr, ptr %t0 + call void @fn_emit(ptr %t5) + call void @fn_emit(ptr @.str209) + %t6 = load ptr, ptr %t1 + call void @fn_emit(ptr %t6) + call void @fn_emit(ptr @.str210) + %t7 = load ptr, ptr %t3 + store ptr %t7, ptr %retval + br label %ret +ret: + %t8 = load ptr, ptr %retval + ret ptr %t8 +} + +define ptr @fn_global_init(ptr %arg_d) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t16 = alloca ptr + %t17 = alloca i32 + %t18 = alloca i32 + %t49 = alloca i32 + %t50 = alloca i32 + store ptr %arg_d, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = getelementptr inbounds %Str_Node, ptr %t1, i32 0, i32 4 + %t3 = load ptr, ptr %t2 + %t4 = icmp eq ptr %t3, null + %t5 = zext i1 %t4 to i32 + %t6 = icmp ne i32 %t5, 0 + br i1 %t6, label %then0, label %ifend2 +then0: + %t7 = load ptr, ptr %t0 + %t8 = getelementptr inbounds %Str_Node, ptr %t7, i32 0, i32 3 + %t9 = load ptr, ptr %t8 + %t10 = call ptr @fn_llty(ptr %t9) + %t11 = call i32 @fn_streq(ptr %t10, ptr @.str211) + %t12 = icmp ne i32 %t11, 0 + br i1 %t12, label %then3, label %ifend5 +then3: + store ptr @.str212, ptr %retval + br label %ret +ifend5: + store ptr @.str213, ptr %retval + br label %ret +ifend2: + %t13 = load ptr, ptr %t0 + %t14 = getelementptr inbounds %Str_Node, ptr %t13, i32 0, i32 4 + %t15 = load ptr, ptr %t14 + store ptr %t15, ptr %t16 + %t19 = load ptr, ptr %t16 + %t20 = getelementptr inbounds %Str_Node, ptr %t19, i32 0, i32 0 + %t21 = load i32, ptr %t20 + %t22 = icmp eq i32 %t21, 30 + %t23 = zext i1 %t22 to i32 + %t24 = icmp ne i32 %t23, 0 + %t25 = zext i1 %t24 to i32 + store i32 %t25, ptr %t18 + br i1 %t24, label %scend7, label %sc6 +sc6: + %t26 = load ptr, ptr %t16 + %t27 = getelementptr inbounds %Str_Node, ptr %t26, i32 0, i32 0 + %t28 = load i32, ptr %t27 + %t29 = icmp eq i32 %t28, 40 + %t30 = zext i1 %t29 to i32 + %t31 = icmp ne i32 %t30, 0 + %t32 = zext i1 %t31 to i32 + store i32 %t32, ptr %t18 + br label %scend7 +scend7: + %t33 = load i32, ptr %t18 + %t34 = icmp ne i32 %t33, 0 + %t35 = zext i1 %t34 to i32 + store i32 %t35, ptr %t17 + br i1 %t34, label %scend9, label %sc8 +sc8: + %t36 = load ptr, ptr %t16 + %t37 = getelementptr inbounds %Str_Node, ptr %t36, i32 0, i32 0 + %t38 = load i32, ptr %t37 + %t39 = icmp eq i32 %t38, 32 + %t40 = zext i1 %t39 to i32 + %t41 = icmp ne i32 %t40, 0 + %t42 = zext i1 %t41 to i32 + store i32 %t42, ptr %t17 + br label %scend9 +scend9: + %t43 = load i32, ptr %t17 + %t44 = icmp ne i32 %t43, 0 + br i1 %t44, label %then10, label %ifend12 +then10: + %t45 = load ptr, ptr %t16 + %t46 = getelementptr inbounds %Str_Node, ptr %t45, i32 0, i32 2 + %t47 = load i32, ptr %t46 + %t48 = call ptr @fn_itoa(i32 %t47) + store ptr %t48, ptr %retval + br label %ret +ifend12: + %t51 = load ptr, ptr %t16 + %t52 = getelementptr inbounds %Str_Node, ptr %t51, i32 0, i32 0 + %t53 = load i32, ptr %t52 + %t54 = icmp eq i32 %t53, 38 + %t55 = zext i1 %t54 to i32 + %t56 = icmp ne i32 %t55, 0 + %t57 = zext i1 %t56 to i32 + store i32 %t57, ptr %t50 + br i1 %t56, label %sc13, label %scend14 +sc13: + %t58 = load ptr, ptr %t16 + %t59 = getelementptr inbounds %Str_Node, ptr %t58, i32 0, i32 1 + %t60 = load ptr, ptr %t59 + %t61 = call i32 @fn_streq(ptr %t60, ptr @.str214) + %t62 = icmp ne i32 %t61, 0 + %t63 = zext i1 %t62 to i32 + store i32 %t63, ptr %t50 + br label %scend14 +scend14: + %t64 = load i32, ptr %t50 + %t65 = icmp ne i32 %t64, 0 + %t66 = zext i1 %t65 to i32 + store i32 %t66, ptr %t49 + br i1 %t65, label %sc15, label %scend16 +sc15: + %t67 = load ptr, ptr %t16 + %t68 = getelementptr inbounds %Str_Node, ptr %t67, i32 0, i32 4 + %t69 = load ptr, ptr %t68 + %t70 = getelementptr inbounds %Str_Node, ptr %t69, i32 0, i32 0 + %t71 = load i32, ptr %t70 + %t72 = icmp eq i32 %t71, 30 + %t73 = zext i1 %t72 to i32 + %t74 = icmp ne i32 %t73, 0 + %t75 = zext i1 %t74 to i32 + store i32 %t75, ptr %t49 + br label %scend16 +scend16: + %t76 = load i32, ptr %t49 + %t77 = icmp ne i32 %t76, 0 + br i1 %t77, label %then17, label %ifend19 +then17: + %t78 = load ptr, ptr %t16 + %t79 = getelementptr inbounds %Str_Node, ptr %t78, i32 0, i32 4 + %t80 = load ptr, ptr %t79 + %t81 = getelementptr inbounds %Str_Node, ptr %t80, i32 0, i32 2 + %t82 = load i32, ptr %t81 + %t83 = call ptr @fn_itoa(i32 %t82) + %t84 = call ptr @fn_sconcat(ptr @.str215, ptr %t83) + store ptr %t84, ptr %retval + br label %ret +ifend19: + %t85 = load ptr, ptr %t0 + %t86 = getelementptr inbounds %Str_Node, ptr %t85, i32 0, i32 3 + %t87 = load ptr, ptr %t86 + %t88 = call ptr @fn_llty(ptr %t87) + %t89 = call i32 @fn_streq(ptr %t88, ptr @.str216) + %t90 = icmp ne i32 %t89, 0 + br i1 %t90, label %then20, label %ifend22 +then20: + store ptr @.str217, ptr %retval + br label %ret +ifend22: + store ptr @.str218, ptr %retval + br label %ret +ret: + %t91 = load ptr, ptr %retval + ret ptr %t91 +} + +define void @fn_emit_header() { +entry: + %t5 = alloca i32 + %t19 = alloca ptr + %t37 = alloca i32 + %t79 = alloca ptr + call void @fn_emith(ptr @.str219) + call void @fn_emith(ptr @.str220) + call void @fn_emith(ptr @.str221) + call void @fn_emith(ptr @.str222) + call void @fn_emith(ptr @.str223) + call void @fn_emith(ptr @.str224) + call void @fn_emith(ptr @.str225) + call void @fn_emith(ptr @.str226) + call void @fn_emith(ptr @.str227) + call void @fn_emith(ptr @.str228) + call void @fn_emith(ptr @.str229) + call void @fn_emith(ptr @.str230) + call void @fn_emith(ptr @.str231) + call void @fn_emith(ptr @.str232) + call void @fn_emith(ptr @.str233) + call void @fn_emith(ptr @.str234) + call void @fn_emith(ptr @.str235) + call void @fn_emith(ptr @.str236) + call void @fn_emith(ptr @.str237) + call void @fn_emith(ptr @.str238) + call void @fn_emith(ptr @.str239) + call void @fn_emith(ptr @.str240) + call void @fn_emith(ptr @.str241) + call void @fn_emith(ptr @.str242) + call void @fn_emith(ptr @.str243) + call void @fn_emith(ptr @.str244) + call void @fn_emith(ptr @.str245) + call void @fn_emith(ptr @.str246) + call void @fn_emith(ptr @.str247) + call void @fn_emith(ptr @.str248) + call void @fn_emith(ptr @.str249) + %t0 = load ptr, ptr @g_g_game_name + %t1 = call i32 @fn_slen(ptr %t0) + %t2 = add i32 %t1, 1 + %t3 = call ptr @fn_itoa(i32 %t2) + call void @fn_emith(ptr %t3) + call void @fn_emith(ptr @.str250) + %t4 = load ptr, ptr @g_g_game_name + call void @fn_emith(ptr %t4) + call void @fn_emith(ptr @.str251) + call void @fn_emith(ptr @.str252) + store i32 0, ptr %t5 + br label %wcond0 +wcond0: + %t6 = load i32, ptr %t5 + %t7 = load ptr, ptr @g_prog + %t8 = getelementptr inbounds %LSlice, ptr %t7, i32 0, i32 1 + %t9 = load i32, ptr %t8 + %t10 = icmp slt i32 %t6, %t9 + %t11 = zext i1 %t10 to i32 + %t12 = icmp ne i32 %t11, 0 + br i1 %t12, label %wbody1, label %wend2 +wbody1: + %t13 = load ptr, ptr @g_prog + %t14 = getelementptr inbounds %LSlice, ptr %t13, i32 0, i32 0 + %t15 = load ptr, ptr %t14 + %t16 = load i32, ptr %t5 + %t17 = getelementptr inbounds ptr, ptr %t15, i32 %t16 + %t18 = load ptr, ptr %t17 + store ptr %t18, ptr %t19 + %t20 = load ptr, ptr %t19 + %t21 = getelementptr inbounds %Str_Node, ptr %t20, i32 0, i32 0 + %t22 = load i32, ptr %t21 + %t23 = icmp eq i32 %t22, 0 + %t24 = zext i1 %t23 to i32 + %t25 = icmp ne i32 %t24, 0 + br i1 %t25, label %then3, label %ifend5 +then3: + call void @fn_emith(ptr @.str253) + %t26 = load ptr, ptr %t19 + %t27 = getelementptr inbounds %Str_Node, ptr %t26, i32 0, i32 1 + %t28 = load ptr, ptr %t27 + call void @fn_emith(ptr %t28) + call void @fn_emith(ptr @.str254) + %t29 = load ptr, ptr %t19 + %t30 = getelementptr inbounds %Str_Node, ptr %t29, i32 0, i32 7 + %t31 = load ptr, ptr %t30 + %t32 = getelementptr inbounds %LSlice, ptr %t31, i32 0, i32 1 + %t33 = load i32, ptr %t32 + %t34 = icmp eq i32 %t33, 0 + %t35 = zext i1 %t34 to i32 + %t36 = icmp ne i32 %t35, 0 + br i1 %t36, label %then6, label %ifend8 +then6: + call void @fn_emith(ptr @.str255) + br label %ifend8 +ifend8: + store i32 0, ptr %t37 + br label %wcond9 +wcond9: + %t38 = load i32, ptr %t37 + %t39 = load ptr, ptr %t19 + %t40 = getelementptr inbounds %Str_Node, ptr %t39, i32 0, i32 7 + %t41 = load ptr, ptr %t40 + %t42 = getelementptr inbounds %LSlice, ptr %t41, i32 0, i32 1 + %t43 = load i32, ptr %t42 + %t44 = icmp slt i32 %t38, %t43 + %t45 = zext i1 %t44 to i32 + %t46 = icmp ne i32 %t45, 0 + br i1 %t46, label %wbody10, label %wend11 +wbody10: + %t47 = load i32, ptr %t37 + %t48 = icmp sgt i32 %t47, 0 + %t49 = zext i1 %t48 to i32 + %t50 = icmp ne i32 %t49, 0 + br i1 %t50, label %then12, label %ifend14 +then12: + call void @fn_emith(ptr @.str256) + br label %ifend14 +ifend14: + %t51 = load ptr, ptr %t19 + %t52 = getelementptr inbounds %Str_Node, ptr %t51, i32 0, i32 7 + %t53 = load ptr, ptr %t52 + %t54 = getelementptr inbounds %LSlice, ptr %t53, i32 0, i32 0 + %t55 = load ptr, ptr %t54 + %t56 = load i32, ptr %t37 + %t57 = getelementptr inbounds ptr, ptr %t55, i32 %t56 + %t58 = load ptr, ptr %t57 + %t59 = getelementptr inbounds %Str_Node, ptr %t58, i32 0, i32 3 + %t60 = load ptr, ptr %t59 + %t61 = call ptr @fn_llty(ptr %t60) + call void @fn_emith(ptr %t61) + %t62 = load i32, ptr %t37 + %t63 = add i32 %t62, 1 + store i32 %t63, ptr %t37 + br label %wcond9 +wend11: + call void @fn_emith(ptr @.str257) + br label %ifend5 +ifend5: + %t64 = load i32, ptr %t5 + %t65 = add i32 %t64, 1 + store i32 %t65, ptr %t5 + br label %wcond0 +wend2: + store i32 0, ptr %t5 + br label %wcond15 +wcond15: + %t66 = load i32, ptr %t5 + %t67 = load ptr, ptr @g_prog + %t68 = getelementptr inbounds %LSlice, ptr %t67, i32 0, i32 1 + %t69 = load i32, ptr %t68 + %t70 = icmp slt i32 %t66, %t69 + %t71 = zext i1 %t70 to i32 + %t72 = icmp ne i32 %t71, 0 + br i1 %t72, label %wbody16, label %wend17 +wbody16: + %t73 = load ptr, ptr @g_prog + %t74 = getelementptr inbounds %LSlice, ptr %t73, i32 0, i32 0 + %t75 = load ptr, ptr %t74 + %t76 = load i32, ptr %t5 + %t77 = getelementptr inbounds ptr, ptr %t75, i32 %t76 + %t78 = load ptr, ptr %t77 + store ptr %t78, ptr %t79 + %t80 = load ptr, ptr %t79 + %t81 = getelementptr inbounds %Str_Node, ptr %t80, i32 0, i32 0 + %t82 = load i32, ptr %t81 + %t83 = icmp eq i32 %t82, 2 + %t84 = zext i1 %t83 to i32 + %t85 = icmp ne i32 %t84, 0 + br i1 %t85, label %then18, label %ifend20 +then18: + call void @fn_emith(ptr @.str258) + %t86 = load ptr, ptr %t79 + %t87 = getelementptr inbounds %Str_Node, ptr %t86, i32 0, i32 1 + %t88 = load ptr, ptr %t87 + call void @fn_emith(ptr %t88) + call void @fn_emith(ptr @.str259) + %t89 = load ptr, ptr %t79 + %t90 = getelementptr inbounds %Str_Node, ptr %t89, i32 0, i32 3 + %t91 = load ptr, ptr %t90 + %t92 = call ptr @fn_llty(ptr %t91) + call void @fn_emith(ptr %t92) + call void @fn_emith(ptr @.str260) + %t93 = load ptr, ptr %t79 + %t94 = call ptr @fn_global_init(ptr %t93) + call void @fn_emith(ptr %t94) + call void @fn_emith(ptr @.str261) + br label %ifend20 +ifend20: + %t95 = load i32, ptr %t5 + %t96 = add i32 %t95, 1 + store i32 %t96, ptr %t5 + br label %wcond15 +wend17: + br label %ret +ret: + ret void +} + +define ptr @fn_emit_member_addr(ptr %arg_e) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t5 = alloca ptr + %t10 = alloca ptr + %t24 = alloca i32 + %t39 = alloca ptr + store ptr %arg_e, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = getelementptr inbounds %Str_Node, ptr %t1, i32 0, i32 4 + %t3 = load ptr, ptr %t2 + %t4 = call ptr @fn_emit_expr(ptr %t3) + store ptr %t4, ptr %t5 + %t6 = load ptr, ptr %t5 + %t7 = getelementptr inbounds %Str_Val, ptr %t6, i32 0, i32 1 + %t8 = load ptr, ptr %t7 + %t9 = call ptr @fn_layout_node(ptr %t8) + store ptr %t9, ptr %t10 + %t11 = load ptr, ptr %t10 + %t12 = icmp eq ptr %t11, null + %t13 = zext i1 %t12 to i32 + %t14 = icmp ne i32 %t13, 0 + br i1 %t14, label %then0, label %ifend2 +then0: + %t15 = load ptr, ptr %t5 + %t16 = getelementptr inbounds %Str_Val, ptr %t15, i32 0, i32 1 + %t17 = load ptr, ptr %t16 + %t18 = call ptr @fn_sconcat(ptr @.str262, ptr %t17) + call void @fn_perr(ptr %t18) + br label %ifend2 +ifend2: + %t19 = load ptr, ptr %t10 + %t20 = load ptr, ptr %t0 + %t21 = getelementptr inbounds %Str_Node, ptr %t20, i32 0, i32 1 + %t22 = load ptr, ptr %t21 + %t23 = call i32 @fn_field_index(ptr %t19, ptr %t22) + store i32 %t23, ptr %t24 + %t25 = load i32, ptr %t24 + %t26 = icmp slt i32 %t25, 0 + %t27 = zext i1 %t26 to i32 + %t28 = icmp ne i32 %t27, 0 + br i1 %t28, label %then3, label %ifend5 +then3: + %t29 = load ptr, ptr %t0 + %t30 = getelementptr inbounds %Str_Node, ptr %t29, i32 0, i32 1 + %t31 = load ptr, ptr %t30 + %t32 = call ptr @fn_sconcat(ptr @.str263, ptr %t31) + call void @fn_perr(ptr %t32) + br label %ifend5 +ifend5: + %t33 = load ptr, ptr %t10 + %t34 = load ptr, ptr %t0 + %t35 = getelementptr inbounds %Str_Node, ptr %t34, i32 0, i32 1 + %t36 = load ptr, ptr %t35 + %t37 = call ptr @fn_field_type(ptr %t33, ptr %t36) + store ptr %t37, ptr @g_g_addr_ty + %t38 = call ptr @fn_nreg() + store ptr %t38, ptr %t39 + call void @fn_emit(ptr @.str264) + %t40 = load ptr, ptr %t39 + call void @fn_emit(ptr %t40) + call void @fn_emit(ptr @.str265) + %t41 = load ptr, ptr %t5 + %t42 = getelementptr inbounds %Str_Val, ptr %t41, i32 0, i32 1 + %t43 = load ptr, ptr %t42 + %t44 = call ptr @fn_layout_ty(ptr %t43) + call void @fn_emit(ptr %t44) + call void @fn_emit(ptr @.str266) + %t45 = load ptr, ptr %t5 + %t46 = getelementptr inbounds %Str_Val, ptr %t45, i32 0, i32 0 + %t47 = load ptr, ptr %t46 + call void @fn_emit(ptr %t47) + call void @fn_emit(ptr @.str267) + %t48 = load i32, ptr %t24 + %t49 = call ptr @fn_itoa(i32 %t48) + call void @fn_emit(ptr %t49) + call void @fn_emit(ptr @.str268) + %t50 = load ptr, ptr %t39 + store ptr %t50, ptr %retval + br label %ret +ret: + %t51 = load ptr, ptr %retval + ret ptr %t51 +} + +define ptr @fn_emit_index_addr(ptr %arg_e) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t5 = alloca ptr + %t17 = alloca ptr + %t20 = alloca ptr + %t26 = alloca ptr + %t33 = alloca ptr + %t35 = alloca ptr + store ptr %arg_e, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = getelementptr inbounds %Str_Node, ptr %t1, i32 0, i32 4 + %t3 = load ptr, ptr %t2 + %t4 = call ptr @fn_emit_expr(ptr %t3) + store ptr %t4, ptr %t5 + %t6 = load ptr, ptr %t5 + %t7 = getelementptr inbounds %Str_Val, ptr %t6, i32 0, i32 1 + %t8 = load ptr, ptr %t7 + %t9 = call i32 @fn_is_slice_ty(ptr %t8) + %t10 = icmp eq i32 %t9, 0 + %t11 = zext i1 %t10 to i32 + %t12 = icmp ne i32 %t11, 0 + br i1 %t12, label %then0, label %ifend2 +then0: + call void @fn_perr(ptr @.str269) + br label %ifend2 +ifend2: + %t13 = load ptr, ptr %t5 + %t14 = getelementptr inbounds %Str_Val, ptr %t13, i32 0, i32 1 + %t15 = load ptr, ptr %t14 + %t16 = call ptr @fn_slice_elem(ptr %t15) + store ptr %t16, ptr %t17 + %t18 = load ptr, ptr %t17 + store ptr %t18, ptr @g_g_addr_ty + %t19 = call ptr @fn_nreg() + store ptr %t19, ptr %t20 + call void @fn_emit(ptr @.str270) + %t21 = load ptr, ptr %t20 + call void @fn_emit(ptr %t21) + call void @fn_emit(ptr @.str271) + %t22 = load ptr, ptr %t5 + %t23 = getelementptr inbounds %Str_Val, ptr %t22, i32 0, i32 0 + %t24 = load ptr, ptr %t23 + call void @fn_emit(ptr %t24) + call void @fn_emit(ptr @.str272) + %t25 = call ptr @fn_nreg() + store ptr %t25, ptr %t26 + call void @fn_emit(ptr @.str273) + %t27 = load ptr, ptr %t26 + call void @fn_emit(ptr %t27) + call void @fn_emit(ptr @.str274) + %t28 = load ptr, ptr %t20 + call void @fn_emit(ptr %t28) + call void @fn_emit(ptr @.str275) + %t29 = load ptr, ptr %t0 + %t30 = getelementptr inbounds %Str_Node, ptr %t29, i32 0, i32 5 + %t31 = load ptr, ptr %t30 + %t32 = call ptr @fn_emit_expr(ptr %t31) + store ptr %t32, ptr %t33 + %t34 = call ptr @fn_nreg() + store ptr %t34, ptr %t35 + call void @fn_emit(ptr @.str276) + %t36 = load ptr, ptr %t35 + call void @fn_emit(ptr %t36) + call void @fn_emit(ptr @.str277) + %t37 = load ptr, ptr %t17 + %t38 = call ptr @fn_llty(ptr %t37) + call void @fn_emit(ptr %t38) + call void @fn_emit(ptr @.str278) + %t39 = load ptr, ptr %t26 + call void @fn_emit(ptr %t39) + call void @fn_emit(ptr @.str279) + %t40 = load ptr, ptr %t33 + %t41 = getelementptr inbounds %Str_Val, ptr %t40, i32 0, i32 0 + %t42 = load ptr, ptr %t41 + call void @fn_emit(ptr %t42) + call void @fn_emit(ptr @.str280) + %t43 = load ptr, ptr %t35 + store ptr %t43, ptr %retval + br label %ret +ret: + %t44 = load ptr, ptr %retval + ret ptr %t44 +} + +define i32 @fn_is_intrinsic(ptr %arg_name) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t1 = alloca i32 + %t2 = alloca i32 + %t20 = alloca i32 + %t21 = alloca i32 + %t39 = alloca i32 + %t40 = alloca i32 + %t58 = alloca i32 + %t59 = alloca i32 + %t77 = alloca i32 + %t88 = alloca i32 + %t89 = alloca i32 + %t90 = alloca i32 + %t115 = alloca i32 + %t126 = alloca i32 + %t127 = alloca i32 + %t128 = alloca i32 + %t129 = alloca i32 + %t130 = alloca i32 + %t169 = alloca i32 + store ptr %arg_name, ptr %t0 + %t3 = load ptr, ptr %t0 + %t4 = call i32 @fn_streq(ptr %t3, ptr @.str281) + %t5 = icmp ne i32 %t4, 0 + %t6 = zext i1 %t5 to i32 + store i32 %t6, ptr %t2 + br i1 %t5, label %scend1, label %sc0 +sc0: + %t7 = load ptr, ptr %t0 + %t8 = call i32 @fn_streq(ptr %t7, ptr @.str282) + %t9 = icmp ne i32 %t8, 0 + %t10 = zext i1 %t9 to i32 + store i32 %t10, ptr %t2 + br label %scend1 +scend1: + %t11 = load i32, ptr %t2 + %t12 = icmp ne i32 %t11, 0 + %t13 = zext i1 %t12 to i32 + store i32 %t13, ptr %t1 + br i1 %t12, label %scend3, label %sc2 +sc2: + %t14 = load ptr, ptr %t0 + %t15 = call i32 @fn_streq(ptr %t14, ptr @.str283) + %t16 = icmp ne i32 %t15, 0 + %t17 = zext i1 %t16 to i32 + store i32 %t17, ptr %t1 + br label %scend3 +scend3: + %t18 = load i32, ptr %t1 + %t19 = icmp ne i32 %t18, 0 + br i1 %t19, label %then4, label %ifend6 +then4: + store i32 1, ptr %retval + br label %ret +ifend6: + %t22 = load ptr, ptr %t0 + %t23 = call i32 @fn_streq(ptr %t22, ptr @.str284) + %t24 = icmp ne i32 %t23, 0 + %t25 = zext i1 %t24 to i32 + store i32 %t25, ptr %t21 + br i1 %t24, label %scend8, label %sc7 +sc7: + %t26 = load ptr, ptr %t0 + %t27 = call i32 @fn_streq(ptr %t26, ptr @.str285) + %t28 = icmp ne i32 %t27, 0 + %t29 = zext i1 %t28 to i32 + store i32 %t29, ptr %t21 + br label %scend8 +scend8: + %t30 = load i32, ptr %t21 + %t31 = icmp ne i32 %t30, 0 + %t32 = zext i1 %t31 to i32 + store i32 %t32, ptr %t20 + br i1 %t31, label %scend10, label %sc9 +sc9: + %t33 = load ptr, ptr %t0 + %t34 = call i32 @fn_streq(ptr %t33, ptr @.str286) + %t35 = icmp ne i32 %t34, 0 + %t36 = zext i1 %t35 to i32 + store i32 %t36, ptr %t20 + br label %scend10 +scend10: + %t37 = load i32, ptr %t20 + %t38 = icmp ne i32 %t37, 0 + br i1 %t38, label %then11, label %ifend13 +then11: + store i32 1, ptr %retval + br label %ret +ifend13: + %t41 = load ptr, ptr %t0 + %t42 = call i32 @fn_streq(ptr %t41, ptr @.str287) + %t43 = icmp ne i32 %t42, 0 + %t44 = zext i1 %t43 to i32 + store i32 %t44, ptr %t40 + br i1 %t43, label %scend15, label %sc14 +sc14: + %t45 = load ptr, ptr %t0 + %t46 = call i32 @fn_streq(ptr %t45, ptr @.str288) + %t47 = icmp ne i32 %t46, 0 + %t48 = zext i1 %t47 to i32 + store i32 %t48, ptr %t40 + br label %scend15 +scend15: + %t49 = load i32, ptr %t40 + %t50 = icmp ne i32 %t49, 0 + %t51 = zext i1 %t50 to i32 + store i32 %t51, ptr %t39 + br i1 %t50, label %scend17, label %sc16 +sc16: + %t52 = load ptr, ptr %t0 + %t53 = call i32 @fn_streq(ptr %t52, ptr @.str289) + %t54 = icmp ne i32 %t53, 0 + %t55 = zext i1 %t54 to i32 + store i32 %t55, ptr %t39 + br label %scend17 +scend17: + %t56 = load i32, ptr %t39 + %t57 = icmp ne i32 %t56, 0 + br i1 %t57, label %then18, label %ifend20 +then18: + store i32 1, ptr %retval + br label %ret +ifend20: + %t60 = load ptr, ptr %t0 + %t61 = call i32 @fn_streq(ptr %t60, ptr @.str290) + %t62 = icmp ne i32 %t61, 0 + %t63 = zext i1 %t62 to i32 + store i32 %t63, ptr %t59 + br i1 %t62, label %scend22, label %sc21 +sc21: + %t64 = load ptr, ptr %t0 + %t65 = call i32 @fn_streq(ptr %t64, ptr @.str291) + %t66 = icmp ne i32 %t65, 0 + %t67 = zext i1 %t66 to i32 + store i32 %t67, ptr %t59 + br label %scend22 +scend22: + %t68 = load i32, ptr %t59 + %t69 = icmp ne i32 %t68, 0 + %t70 = zext i1 %t69 to i32 + store i32 %t70, ptr %t58 + br i1 %t69, label %scend24, label %sc23 +sc23: + %t71 = load ptr, ptr %t0 + %t72 = call i32 @fn_streq(ptr %t71, ptr @.str292) + %t73 = icmp ne i32 %t72, 0 + %t74 = zext i1 %t73 to i32 + store i32 %t74, ptr %t58 + br label %scend24 +scend24: + %t75 = load i32, ptr %t58 + %t76 = icmp ne i32 %t75, 0 + br i1 %t76, label %then25, label %ifend27 +then25: + store i32 1, ptr %retval + br label %ret +ifend27: + %t78 = load ptr, ptr %t0 + %t79 = call i32 @fn_streq(ptr %t78, ptr @.str293) + %t80 = icmp ne i32 %t79, 0 + %t81 = zext i1 %t80 to i32 + store i32 %t81, ptr %t77 + br i1 %t80, label %scend29, label %sc28 +sc28: + %t82 = load ptr, ptr %t0 + %t83 = call i32 @fn_streq(ptr %t82, ptr @.str294) + %t84 = icmp ne i32 %t83, 0 + %t85 = zext i1 %t84 to i32 + store i32 %t85, ptr %t77 + br label %scend29 +scend29: + %t86 = load i32, ptr %t77 + %t87 = icmp ne i32 %t86, 0 + br i1 %t87, label %then30, label %ifend32 +then30: + store i32 1, ptr %retval + br label %ret +ifend32: + %t91 = load ptr, ptr %t0 + %t92 = call i32 @fn_streq(ptr %t91, ptr @.str295) + %t93 = icmp ne i32 %t92, 0 + %t94 = zext i1 %t93 to i32 + store i32 %t94, ptr %t90 + br i1 %t93, label %scend34, label %sc33 +sc33: + %t95 = load ptr, ptr %t0 + %t96 = call i32 @fn_streq(ptr %t95, ptr @.str296) + %t97 = icmp ne i32 %t96, 0 + %t98 = zext i1 %t97 to i32 + store i32 %t98, ptr %t90 + br label %scend34 +scend34: + %t99 = load i32, ptr %t90 + %t100 = icmp ne i32 %t99, 0 + %t101 = zext i1 %t100 to i32 + store i32 %t101, ptr %t89 + br i1 %t100, label %scend36, label %sc35 +sc35: + %t102 = load ptr, ptr %t0 + %t103 = call i32 @fn_streq(ptr %t102, ptr @.str297) + %t104 = icmp ne i32 %t103, 0 + %t105 = zext i1 %t104 to i32 + store i32 %t105, ptr %t89 + br label %scend36 +scend36: + %t106 = load i32, ptr %t89 + %t107 = icmp ne i32 %t106, 0 + %t108 = zext i1 %t107 to i32 + store i32 %t108, ptr %t88 + br i1 %t107, label %scend38, label %sc37 +sc37: + %t109 = load ptr, ptr %t0 + %t110 = call i32 @fn_streq(ptr %t109, ptr @.str298) + %t111 = icmp ne i32 %t110, 0 + %t112 = zext i1 %t111 to i32 + store i32 %t112, ptr %t88 + br label %scend38 +scend38: + %t113 = load i32, ptr %t88 + %t114 = icmp ne i32 %t113, 0 + br i1 %t114, label %then39, label %ifend41 +then39: + store i32 1, ptr %retval + br label %ret +ifend41: + %t116 = load ptr, ptr %t0 + %t117 = call i32 @fn_streq(ptr %t116, ptr @.str299) + %t118 = icmp ne i32 %t117, 0 + %t119 = zext i1 %t118 to i32 + store i32 %t119, ptr %t115 + br i1 %t118, label %scend43, label %sc42 +sc42: + %t120 = load ptr, ptr %t0 + %t121 = call i32 @fn_streq(ptr %t120, ptr @.str300) + %t122 = icmp ne i32 %t121, 0 + %t123 = zext i1 %t122 to i32 + store i32 %t123, ptr %t115 + br label %scend43 +scend43: + %t124 = load i32, ptr %t115 + %t125 = icmp ne i32 %t124, 0 + br i1 %t125, label %then44, label %ifend46 +then44: + store i32 1, ptr %retval + br label %ret +ifend46: + %t131 = load ptr, ptr %t0 + %t132 = call i32 @fn_streq(ptr %t131, ptr @.str301) + %t133 = icmp ne i32 %t132, 0 + %t134 = zext i1 %t133 to i32 + store i32 %t134, ptr %t130 + br i1 %t133, label %scend48, label %sc47 +sc47: + %t135 = load ptr, ptr %t0 + %t136 = call i32 @fn_streq(ptr %t135, ptr @.str302) + %t137 = icmp ne i32 %t136, 0 + %t138 = zext i1 %t137 to i32 + store i32 %t138, ptr %t130 + br label %scend48 +scend48: + %t139 = load i32, ptr %t130 + %t140 = icmp ne i32 %t139, 0 + %t141 = zext i1 %t140 to i32 + store i32 %t141, ptr %t129 + br i1 %t140, label %scend50, label %sc49 +sc49: + %t142 = load ptr, ptr %t0 + %t143 = call i32 @fn_streq(ptr %t142, ptr @.str303) + %t144 = icmp ne i32 %t143, 0 + %t145 = zext i1 %t144 to i32 + store i32 %t145, ptr %t129 + br label %scend50 +scend50: + %t146 = load i32, ptr %t129 + %t147 = icmp ne i32 %t146, 0 + %t148 = zext i1 %t147 to i32 + store i32 %t148, ptr %t128 + br i1 %t147, label %scend52, label %sc51 +sc51: + %t149 = load ptr, ptr %t0 + %t150 = call i32 @fn_streq(ptr %t149, ptr @.str304) + %t151 = icmp ne i32 %t150, 0 + %t152 = zext i1 %t151 to i32 + store i32 %t152, ptr %t128 + br label %scend52 +scend52: + %t153 = load i32, ptr %t128 + %t154 = icmp ne i32 %t153, 0 + %t155 = zext i1 %t154 to i32 + store i32 %t155, ptr %t127 + br i1 %t154, label %scend54, label %sc53 +sc53: + %t156 = load ptr, ptr %t0 + %t157 = call i32 @fn_streq(ptr %t156, ptr @.str305) + %t158 = icmp ne i32 %t157, 0 + %t159 = zext i1 %t158 to i32 + store i32 %t159, ptr %t127 + br label %scend54 +scend54: + %t160 = load i32, ptr %t127 + %t161 = icmp ne i32 %t160, 0 + %t162 = zext i1 %t161 to i32 + store i32 %t162, ptr %t126 + br i1 %t161, label %scend56, label %sc55 +sc55: + %t163 = load ptr, ptr %t0 + %t164 = call i32 @fn_streq(ptr %t163, ptr @.str306) + %t165 = icmp ne i32 %t164, 0 + %t166 = zext i1 %t165 to i32 + store i32 %t166, ptr %t126 + br label %scend56 +scend56: + %t167 = load i32, ptr %t126 + %t168 = icmp ne i32 %t167, 0 + br i1 %t168, label %then57, label %ifend59 +then57: + store i32 1, ptr %retval + br label %ret +ifend59: + %t170 = load ptr, ptr %t0 + %t171 = call i32 @fn_streq(ptr %t170, ptr @.str307) + %t172 = icmp ne i32 %t171, 0 + %t173 = zext i1 %t172 to i32 + store i32 %t173, ptr %t169 + br i1 %t172, label %scend61, label %sc60 +sc60: + %t174 = load ptr, ptr %t0 + %t175 = call i32 @fn_streq(ptr %t174, ptr @.str308) + %t176 = icmp ne i32 %t175, 0 + %t177 = zext i1 %t176 to i32 + store i32 %t177, ptr %t169 + br label %scend61 +scend61: + %t178 = load i32, ptr %t169 + %t179 = icmp ne i32 %t178, 0 + br i1 %t179, label %then62, label %ifend64 +then62: + store i32 1, ptr %retval + br label %ret +ifend64: + store i32 0, ptr %retval + br label %ret +ret: + %t180 = load i32, ptr %retval + ret i32 %t180 +} + +define ptr @fn_emit_bind(ptr %arg_rest) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t2 = alloca ptr + store ptr %arg_rest, ptr %t0 + %t1 = call ptr @fn_nreg() + store ptr %t1, ptr %t2 + call void @fn_emit(ptr @.str309) + %t3 = load ptr, ptr %t2 + call void @fn_emit(ptr %t3) + call void @fn_emit(ptr @.str310) + %t4 = load ptr, ptr %t0 + call void @fn_emit(ptr %t4) + call void @fn_emit(ptr @.str311) + %t5 = load ptr, ptr %t2 + store ptr %t5, ptr %retval + br label %ret +ret: + %t6 = load ptr, ptr %retval + ret ptr %t6 +} + +define ptr @fn_arg_code(ptr %arg_e, i32 %arg_i) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca i32 + %t11 = alloca ptr + store ptr %arg_e, ptr %t0 + store i32 %arg_i, ptr %t1 + %t2 = load ptr, ptr %t0 + %t3 = getelementptr inbounds %Str_Node, ptr %t2, i32 0, i32 7 + %t4 = load ptr, ptr %t3 + %t5 = getelementptr inbounds %LSlice, ptr %t4, i32 0, i32 0 + %t6 = load ptr, ptr %t5 + %t7 = load i32, ptr %t1 + %t8 = getelementptr inbounds ptr, ptr %t6, i32 %t7 + %t9 = load ptr, ptr %t8 + %t10 = call ptr @fn_emit_expr(ptr %t9) + store ptr %t10, ptr %t11 + %t12 = load ptr, ptr %t11 + %t13 = getelementptr inbounds %Str_Val, ptr %t12, i32 0, i32 0 + %t14 = load ptr, ptr %t13 + store ptr %t14, ptr %retval + br label %ret +ret: + %t15 = load ptr, ptr %retval + ret ptr %t15 +} + +define ptr @fn_emit_intrinsic(ptr %arg_name, ptr %arg_e) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca ptr + %t11 = alloca ptr + %t16 = alloca ptr + %t27 = alloca ptr + %t30 = alloca ptr + %t35 = alloca ptr + %t49 = alloca ptr + %t52 = alloca ptr + %t56 = alloca ptr + %t60 = alloca ptr + %t71 = alloca ptr + %t74 = alloca ptr + %t77 = alloca ptr + %t81 = alloca ptr + %t86 = alloca ptr + %t95 = alloca ptr + %t100 = alloca ptr + %t111 = alloca ptr + %t114 = alloca ptr + %t123 = alloca i32 + %t136 = alloca ptr + %t139 = alloca ptr + %t142 = alloca ptr + %t147 = alloca ptr + %t148 = alloca ptr + %t165 = alloca ptr + %t176 = alloca ptr + %t179 = alloca ptr + %t182 = alloca ptr + %t187 = alloca ptr + %t204 = alloca ptr + %t209 = alloca ptr + %t220 = alloca ptr + %t228 = alloca ptr + %t236 = alloca ptr + %t249 = alloca ptr + %t251 = alloca ptr + %t258 = alloca ptr + %t268 = alloca ptr + %t281 = alloca ptr + %t292 = alloca ptr + %t303 = alloca ptr + %t309 = alloca i32 + %t310 = alloca i32 + %t311 = alloca i32 + %t312 = alloca i32 + %t346 = alloca ptr + %t349 = alloca ptr + %t350 = alloca ptr + %t377 = alloca ptr + %t380 = alloca ptr + %t382 = alloca ptr + %t395 = alloca ptr + %t398 = alloca ptr + %t401 = alloca ptr + %t403 = alloca ptr + store ptr %arg_name, ptr %t0 + store ptr %arg_e, ptr %t1 + store i32 1, ptr @g_g_intrin_ok + %t2 = load ptr, ptr %t0 + %t3 = call i32 @fn_streq(ptr %t2, ptr @.str312) + %t4 = icmp ne i32 %t3, 0 + br i1 %t4, label %then0, label %ifend2 +then0: + %t5 = call ptr @fn_val(ptr @.str313, ptr @.str314) + store ptr %t5, ptr %retval + br label %ret +ifend2: + %t6 = load ptr, ptr %t0 + %t7 = call i32 @fn_streq(ptr %t6, ptr @.str315) + %t8 = icmp ne i32 %t7, 0 + br i1 %t8, label %then3, label %ifend5 +then3: + %t9 = load ptr, ptr %t1 + %t10 = call ptr @fn_arg_code(ptr %t9, i32 0) + store ptr %t10, ptr %t11 + %t12 = load ptr, ptr %t11 + %t13 = call ptr @fn_sconcat(ptr %t12, ptr @.str317) + %t14 = call ptr @fn_sconcat(ptr @.str316, ptr %t13) + %t15 = call ptr @fn_emit_bind(ptr %t14) + store ptr %t15, ptr %t16 + %t17 = load ptr, ptr %t16 + %t18 = call ptr @fn_sconcat(ptr %t17, ptr @.str319) + %t19 = call ptr @fn_sconcat(ptr @.str318, ptr %t18) + %t20 = call ptr @fn_emit_bind(ptr %t19) + %t21 = call ptr @fn_val(ptr %t20, ptr @.str320) + store ptr %t21, ptr %retval + br label %ret +ifend5: + %t22 = load ptr, ptr %t0 + %t23 = call i32 @fn_streq(ptr %t22, ptr @.str321) + %t24 = icmp ne i32 %t23, 0 + br i1 %t24, label %then6, label %ifend8 +then6: + %t25 = load ptr, ptr %t1 + %t26 = call ptr @fn_arg_code(ptr %t25, i32 0) + store ptr %t26, ptr %t27 + %t28 = load ptr, ptr %t1 + %t29 = call ptr @fn_arg_code(ptr %t28, i32 1) + store ptr %t29, ptr %t30 + %t31 = load ptr, ptr %t30 + %t32 = call ptr @fn_sconcat(ptr %t31, ptr @.str323) + %t33 = call ptr @fn_sconcat(ptr @.str322, ptr %t32) + %t34 = call ptr @fn_emit_bind(ptr %t33) + store ptr %t34, ptr %t35 + %t36 = load ptr, ptr %t27 + %t37 = load ptr, ptr %t35 + %t38 = call ptr @fn_sconcat(ptr %t37, ptr @.str326) + %t39 = call ptr @fn_sconcat(ptr @.str325, ptr %t38) + %t40 = call ptr @fn_sconcat(ptr %t36, ptr %t39) + %t41 = call ptr @fn_sconcat(ptr @.str324, ptr %t40) + %t42 = call ptr @fn_emit_bind(ptr %t41) + %t43 = call ptr @fn_val(ptr %t42, ptr @.str327) + store ptr %t43, ptr %retval + br label %ret +ifend8: + %t44 = load ptr, ptr %t0 + %t45 = call i32 @fn_streq(ptr %t44, ptr @.str328) + %t46 = icmp ne i32 %t45, 0 + br i1 %t46, label %then9, label %ifend11 +then9: + %t47 = load ptr, ptr %t1 + %t48 = call ptr @fn_arg_code(ptr %t47, i32 0) + store ptr %t48, ptr %t49 + %t50 = load ptr, ptr %t1 + %t51 = call ptr @fn_arg_code(ptr %t50, i32 1) + store ptr %t51, ptr %t52 + %t53 = load ptr, ptr %t49 + %t54 = load ptr, ptr %t52 + %t55 = call ptr @fn_emit_gep_i8(ptr %t53, ptr %t54) + store ptr %t55, ptr %t56 + %t57 = load ptr, ptr %t56 + %t58 = call ptr @fn_sconcat(ptr @.str329, ptr %t57) + %t59 = call ptr @fn_emit_bind(ptr %t58) + store ptr %t59, ptr %t60 + %t61 = load ptr, ptr %t60 + %t62 = call ptr @fn_sconcat(ptr %t61, ptr @.str331) + %t63 = call ptr @fn_sconcat(ptr @.str330, ptr %t62) + %t64 = call ptr @fn_emit_bind(ptr %t63) + %t65 = call ptr @fn_val(ptr %t64, ptr @.str332) + store ptr %t65, ptr %retval + br label %ret +ifend11: + %t66 = load ptr, ptr %t0 + %t67 = call i32 @fn_streq(ptr %t66, ptr @.str333) + %t68 = icmp ne i32 %t67, 0 + br i1 %t68, label %then12, label %ifend14 +then12: + %t69 = load ptr, ptr %t1 + %t70 = call ptr @fn_arg_code(ptr %t69, i32 0) + store ptr %t70, ptr %t71 + %t72 = load ptr, ptr %t1 + %t73 = call ptr @fn_arg_code(ptr %t72, i32 1) + store ptr %t73, ptr %t74 + %t75 = load ptr, ptr %t1 + %t76 = call ptr @fn_arg_code(ptr %t75, i32 2) + store ptr %t76, ptr %t77 + %t78 = load ptr, ptr %t71 + %t79 = load ptr, ptr %t74 + %t80 = call ptr @fn_emit_gep_i8(ptr %t78, ptr %t79) + store ptr %t80, ptr %t81 + %t82 = load ptr, ptr %t77 + %t83 = call ptr @fn_sconcat(ptr %t82, ptr @.str335) + %t84 = call ptr @fn_sconcat(ptr @.str334, ptr %t83) + %t85 = call ptr @fn_emit_bind(ptr %t84) + store ptr %t85, ptr %t86 + call void @fn_emit(ptr @.str336) + %t87 = load ptr, ptr %t86 + call void @fn_emit(ptr %t87) + call void @fn_emit(ptr @.str337) + %t88 = load ptr, ptr %t81 + call void @fn_emit(ptr %t88) + call void @fn_emit(ptr @.str338) + %t89 = call ptr @fn_val(ptr @.str339, ptr @.str340) + store ptr %t89, ptr %retval + br label %ret +ifend14: + %t90 = load ptr, ptr %t0 + %t91 = call i32 @fn_streq(ptr %t90, ptr @.str341) + %t92 = icmp ne i32 %t91, 0 + br i1 %t92, label %then15, label %ifend17 +then15: + %t93 = load ptr, ptr %t1 + %t94 = call ptr @fn_arg_code(ptr %t93, i32 0) + store ptr %t94, ptr %t95 + %t96 = load ptr, ptr %t95 + %t97 = call ptr @fn_sconcat(ptr %t96, ptr @.str343) + %t98 = call ptr @fn_sconcat(ptr @.str342, ptr %t97) + %t99 = call ptr @fn_emit_bind(ptr %t98) + store ptr %t99, ptr %t100 + %t101 = load ptr, ptr %t100 + %t102 = call ptr @fn_sconcat(ptr %t101, ptr @.str345) + %t103 = call ptr @fn_sconcat(ptr @.str344, ptr %t102) + %t104 = call ptr @fn_emit_bind(ptr %t103) + %t105 = call ptr @fn_val(ptr %t104, ptr @.str346) + store ptr %t105, ptr %retval + br label %ret +ifend17: + %t106 = load ptr, ptr %t0 + %t107 = call i32 @fn_streq(ptr %t106, ptr @.str347) + %t108 = icmp ne i32 %t107, 0 + br i1 %t108, label %then18, label %ifend20 +then18: + %t109 = load ptr, ptr %t1 + %t110 = call ptr @fn_arg_code(ptr %t109, i32 0) + store ptr %t110, ptr %t111 + %t112 = load ptr, ptr %t1 + %t113 = call ptr @fn_arg_code(ptr %t112, i32 1) + store ptr %t113, ptr %t114 + %t115 = load ptr, ptr %t111 + %t116 = load ptr, ptr %t114 + %t117 = call ptr @fn_sconcat(ptr %t116, ptr @.str350) + %t118 = call ptr @fn_sconcat(ptr @.str349, ptr %t117) + %t119 = call ptr @fn_sconcat(ptr %t115, ptr %t118) + %t120 = call ptr @fn_sconcat(ptr @.str348, ptr %t119) + %t121 = call ptr @fn_emit_bind(ptr %t120) + %t122 = call ptr @fn_val(ptr %t121, ptr @.str351) + store ptr %t122, ptr %retval + br label %ret +ifend20: + %t124 = load ptr, ptr %t0 + %t125 = call i32 @fn_streq(ptr %t124, ptr @.str352) + %t126 = icmp ne i32 %t125, 0 + %t127 = zext i1 %t126 to i32 + store i32 %t127, ptr %t123 + br i1 %t126, label %scend22, label %sc21 +sc21: + %t128 = load ptr, ptr %t0 + %t129 = call i32 @fn_streq(ptr %t128, ptr @.str353) + %t130 = icmp ne i32 %t129, 0 + %t131 = zext i1 %t130 to i32 + store i32 %t131, ptr %t123 + br label %scend22 +scend22: + %t132 = load i32, ptr %t123 + %t133 = icmp ne i32 %t132, 0 + br i1 %t133, label %then23, label %ifend25 +then23: + %t134 = load ptr, ptr %t1 + %t135 = call ptr @fn_arg_code(ptr %t134, i32 0) + store ptr %t135, ptr %t136 + %t137 = load ptr, ptr %t1 + %t138 = call ptr @fn_arg_code(ptr %t137, i32 1) + store ptr %t138, ptr %t139 + %t140 = load ptr, ptr %t1 + %t141 = call ptr @fn_arg_code(ptr %t140, i32 2) + store ptr %t141, ptr %t142 + %t143 = load ptr, ptr %t142 + %t144 = call ptr @fn_sconcat(ptr %t143, ptr @.str355) + %t145 = call ptr @fn_sconcat(ptr @.str354, ptr %t144) + %t146 = call ptr @fn_emit_bind(ptr %t145) + store ptr %t146, ptr %t147 + store ptr @.str356, ptr %t148 + %t149 = load ptr, ptr %t0 + %t150 = call i32 @fn_streq(ptr %t149, ptr @.str357) + %t151 = icmp ne i32 %t150, 0 + br i1 %t151, label %then26, label %ifend28 +then26: + store ptr @.str358, ptr %t148 + br label %ifend28 +ifend28: + %t152 = load ptr, ptr %t148 + %t153 = load ptr, ptr %t139 + %t154 = load ptr, ptr %t147 + %t155 = load ptr, ptr %t136 + %t156 = call ptr @fn_sconcat(ptr %t155, ptr @.str363) + %t157 = call ptr @fn_sconcat(ptr @.str362, ptr %t156) + %t158 = call ptr @fn_sconcat(ptr %t154, ptr %t157) + %t159 = call ptr @fn_sconcat(ptr @.str361, ptr %t158) + %t160 = call ptr @fn_sconcat(ptr %t153, ptr %t159) + %t161 = call ptr @fn_sconcat(ptr @.str360, ptr %t160) + %t162 = call ptr @fn_sconcat(ptr %t152, ptr %t161) + %t163 = call ptr @fn_sconcat(ptr @.str359, ptr %t162) + %t164 = call ptr @fn_emit_bind(ptr %t163) + store ptr %t164, ptr %t165 + %t166 = load ptr, ptr %t165 + %t167 = call ptr @fn_sconcat(ptr %t166, ptr @.str365) + %t168 = call ptr @fn_sconcat(ptr @.str364, ptr %t167) + %t169 = call ptr @fn_emit_bind(ptr %t168) + %t170 = call ptr @fn_val(ptr %t169, ptr @.str366) + store ptr %t170, ptr %retval + br label %ret +ifend25: + %t171 = load ptr, ptr %t0 + %t172 = call i32 @fn_streq(ptr %t171, ptr @.str367) + %t173 = icmp ne i32 %t172, 0 + br i1 %t173, label %then29, label %ifend31 +then29: + %t174 = load ptr, ptr %t1 + %t175 = call ptr @fn_arg_code(ptr %t174, i32 0) + store ptr %t175, ptr %t176 + %t177 = load ptr, ptr %t1 + %t178 = call ptr @fn_arg_code(ptr %t177, i32 1) + store ptr %t178, ptr %t179 + %t180 = load ptr, ptr %t1 + %t181 = call ptr @fn_arg_code(ptr %t180, i32 2) + store ptr %t181, ptr %t182 + %t183 = load ptr, ptr %t179 + %t184 = call ptr @fn_sconcat(ptr %t183, ptr @.str369) + %t185 = call ptr @fn_sconcat(ptr @.str368, ptr %t184) + %t186 = call ptr @fn_emit_bind(ptr %t185) + store ptr %t186, ptr %t187 + %t188 = load ptr, ptr %t176 + %t189 = load ptr, ptr %t187 + %t190 = load ptr, ptr %t182 + %t191 = call ptr @fn_sconcat(ptr %t190, ptr @.str373) + %t192 = call ptr @fn_sconcat(ptr @.str372, ptr %t191) + %t193 = call ptr @fn_sconcat(ptr %t189, ptr %t192) + %t194 = call ptr @fn_sconcat(ptr @.str371, ptr %t193) + %t195 = call ptr @fn_sconcat(ptr %t188, ptr %t194) + %t196 = call ptr @fn_sconcat(ptr @.str370, ptr %t195) + %t197 = call ptr @fn_emit_bind(ptr %t196) + %t198 = call ptr @fn_val(ptr %t197, ptr @.str374) + store ptr %t198, ptr %retval + br label %ret +ifend31: + %t199 = load ptr, ptr %t0 + %t200 = call i32 @fn_streq(ptr %t199, ptr @.str375) + %t201 = icmp ne i32 %t200, 0 + br i1 %t201, label %then32, label %ifend34 +then32: + %t202 = load ptr, ptr %t1 + %t203 = call ptr @fn_arg_code(ptr %t202, i32 0) + store ptr %t203, ptr %t204 + %t205 = load ptr, ptr %t204 + %t206 = call ptr @fn_sconcat(ptr %t205, ptr @.str377) + %t207 = call ptr @fn_sconcat(ptr @.str376, ptr %t206) + %t208 = call ptr @fn_emit_bind(ptr %t207) + store ptr %t208, ptr %t209 + %t210 = load ptr, ptr %t209 + %t211 = call ptr @fn_sconcat(ptr %t210, ptr @.str379) + %t212 = call ptr @fn_sconcat(ptr @.str378, ptr %t211) + %t213 = call ptr @fn_emit_bind(ptr %t212) + %t214 = call ptr @fn_val(ptr %t213, ptr @.str380) + store ptr %t214, ptr %retval + br label %ret +ifend34: + %t215 = load ptr, ptr %t0 + %t216 = call i32 @fn_streq(ptr %t215, ptr @.str381) + %t217 = icmp ne i32 %t216, 0 + br i1 %t217, label %then35, label %ifend37 +then35: + %t218 = load ptr, ptr %t1 + %t219 = call ptr @fn_arg_code(ptr %t218, i32 0) + store ptr %t219, ptr %t220 + call void @fn_emit(ptr @.str382) + %t221 = load ptr, ptr %t220 + call void @fn_emit(ptr %t221) + call void @fn_emit(ptr @.str383) + %t222 = call ptr @fn_val(ptr @.str384, ptr @.str385) + store ptr %t222, ptr %retval + br label %ret +ifend37: + %t223 = load ptr, ptr %t0 + %t224 = call i32 @fn_streq(ptr %t223, ptr @.str386) + %t225 = icmp ne i32 %t224, 0 + br i1 %t225, label %then38, label %ifend40 +then38: + %t226 = load ptr, ptr %t1 + %t227 = call ptr @fn_arg_code(ptr %t226, i32 0) + store ptr %t227, ptr %t228 + call void @fn_emit(ptr @.str387) + %t229 = load ptr, ptr %t228 + call void @fn_emit(ptr %t229) + call void @fn_emit(ptr @.str388) + %t230 = call ptr @fn_val(ptr @.str389, ptr @.str390) + store ptr %t230, ptr %retval + br label %ret +ifend40: + %t231 = load ptr, ptr %t0 + %t232 = call i32 @fn_streq(ptr %t231, ptr @.str391) + %t233 = icmp ne i32 %t232, 0 + br i1 %t233, label %then41, label %ifend43 +then41: + %t234 = load ptr, ptr %t1 + %t235 = call ptr @fn_arg_code(ptr %t234, i32 0) + store ptr %t235, ptr %t236 + call void @fn_emit(ptr @.str392) + %t237 = load ptr, ptr %t236 + call void @fn_emit(ptr %t237) + call void @fn_emit(ptr @.str393) + %t238 = call ptr @fn_val(ptr @.str394, ptr @.str395) + store ptr %t238, ptr %retval + br label %ret +ifend43: + %t239 = load ptr, ptr %t0 + %t240 = call i32 @fn_streq(ptr %t239, ptr @.str396) + %t241 = icmp ne i32 %t240, 0 + br i1 %t241, label %then44, label %ifend46 +then44: + %t242 = call ptr @fn_emit_bind(ptr @.str397) + %t243 = call ptr @fn_val(ptr %t242, ptr @.str398) + store ptr %t243, ptr %retval + br label %ret +ifend46: + %t244 = load ptr, ptr %t0 + %t245 = call i32 @fn_streq(ptr %t244, ptr @.str399) + %t246 = icmp ne i32 %t245, 0 + br i1 %t246, label %then47, label %ifend49 +then47: + %t247 = load ptr, ptr %t1 + %t248 = call ptr @fn_arg_code(ptr %t247, i32 0) + store ptr %t248, ptr %t249 + %t250 = call ptr @fn_emit_bind(ptr @.str400) + store ptr %t250, ptr %t251 + %t252 = load ptr, ptr %t251 + %t253 = load ptr, ptr %t249 + %t254 = call ptr @fn_sconcat(ptr @.str402, ptr %t253) + %t255 = call ptr @fn_sconcat(ptr %t252, ptr %t254) + %t256 = call ptr @fn_sconcat(ptr @.str401, ptr %t255) + %t257 = call ptr @fn_emit_bind(ptr %t256) + store ptr %t257, ptr %t258 + %t259 = load ptr, ptr %t258 + %t260 = call ptr @fn_sconcat(ptr @.str403, ptr %t259) + %t261 = call ptr @fn_emit_bind(ptr %t260) + %t262 = call ptr @fn_val(ptr %t261, ptr @.str404) + store ptr %t262, ptr %retval + br label %ret +ifend49: + %t263 = load ptr, ptr %t0 + %t264 = call i32 @fn_streq(ptr %t263, ptr @.str405) + %t265 = icmp ne i32 %t264, 0 + br i1 %t265, label %then50, label %ifend52 +then50: + %t266 = load ptr, ptr %t1 + %t267 = call ptr @fn_arg_code(ptr %t266, i32 0) + store ptr %t267, ptr %t268 + call void @fn_emit(ptr @.str406) + %t269 = load ptr, ptr %t268 + call void @fn_emit(ptr %t269) + call void @fn_emit(ptr @.str407) + call void @fn_emit(ptr @.str408) + store i32 1, ptr @g_g_term + %t270 = call ptr @fn_val(ptr @.str409, ptr @.str410) + store ptr %t270, ptr %retval + br label %ret +ifend52: + %t271 = load ptr, ptr %t0 + %t272 = call i32 @fn_streq(ptr %t271, ptr @.str411) + %t273 = icmp ne i32 %t272, 0 + br i1 %t273, label %then53, label %ifend55 +then53: + %t274 = call ptr @fn_emit_bind(ptr @.str412) + %t275 = call ptr @fn_val(ptr %t274, ptr @.str413) + store ptr %t275, ptr %retval + br label %ret +ifend55: + %t276 = load ptr, ptr %t0 + %t277 = call i32 @fn_streq(ptr %t276, ptr @.str414) + %t278 = icmp ne i32 %t277, 0 + br i1 %t278, label %then56, label %ifend58 +then56: + %t279 = load ptr, ptr %t1 + %t280 = call ptr @fn_arg_code(ptr %t279, i32 0) + store ptr %t280, ptr %t281 + %t282 = load ptr, ptr %t281 + %t283 = call ptr @fn_sconcat(ptr %t282, ptr @.str416) + %t284 = call ptr @fn_sconcat(ptr @.str415, ptr %t283) + %t285 = call ptr @fn_emit_bind(ptr %t284) + %t286 = call ptr @fn_val(ptr %t285, ptr @.str417) + store ptr %t286, ptr %retval + br label %ret +ifend58: + %t287 = load ptr, ptr %t0 + %t288 = call i32 @fn_streq(ptr %t287, ptr @.str418) + %t289 = icmp ne i32 %t288, 0 + br i1 %t289, label %then59, label %ifend61 +then59: + %t290 = load ptr, ptr %t1 + %t291 = call ptr @fn_arg_code(ptr %t290, i32 0) + store ptr %t291, ptr %t292 + %t293 = load ptr, ptr %t292 + %t294 = call ptr @fn_sconcat(ptr %t293, ptr @.str420) + %t295 = call ptr @fn_sconcat(ptr @.str419, ptr %t294) + %t296 = call ptr @fn_emit_bind(ptr %t295) + %t297 = call ptr @fn_val(ptr %t296, ptr @.str421) + store ptr %t297, ptr %retval + br label %ret +ifend61: + %t298 = load ptr, ptr %t0 + %t299 = call i32 @fn_streq(ptr %t298, ptr @.str422) + %t300 = icmp ne i32 %t299, 0 + br i1 %t300, label %then62, label %ifend64 +then62: + %t301 = load ptr, ptr %t1 + %t302 = call ptr @fn_arg_code(ptr %t301, i32 0) + store ptr %t302, ptr %t303 + %t304 = load ptr, ptr %t303 + %t305 = call ptr @fn_sconcat(ptr %t304, ptr @.str424) + %t306 = call ptr @fn_sconcat(ptr @.str423, ptr %t305) + %t307 = call ptr @fn_emit_bind(ptr %t306) + %t308 = call ptr @fn_val(ptr %t307, ptr @.str425) + store ptr %t308, ptr %retval + br label %ret +ifend64: + %t313 = load ptr, ptr %t0 + %t314 = call i32 @fn_streq(ptr %t313, ptr @.str426) + %t315 = icmp ne i32 %t314, 0 + %t316 = zext i1 %t315 to i32 + store i32 %t316, ptr %t312 + br i1 %t315, label %scend66, label %sc65 +sc65: + %t317 = load ptr, ptr %t0 + %t318 = call i32 @fn_streq(ptr %t317, ptr @.str427) + %t319 = icmp ne i32 %t318, 0 + %t320 = zext i1 %t319 to i32 + store i32 %t320, ptr %t312 + br label %scend66 +scend66: + %t321 = load i32, ptr %t312 + %t322 = icmp ne i32 %t321, 0 + %t323 = zext i1 %t322 to i32 + store i32 %t323, ptr %t311 + br i1 %t322, label %scend68, label %sc67 +sc67: + %t324 = load ptr, ptr %t0 + %t325 = call i32 @fn_streq(ptr %t324, ptr @.str428) + %t326 = icmp ne i32 %t325, 0 + %t327 = zext i1 %t326 to i32 + store i32 %t327, ptr %t311 + br label %scend68 +scend68: + %t328 = load i32, ptr %t311 + %t329 = icmp ne i32 %t328, 0 + %t330 = zext i1 %t329 to i32 + store i32 %t330, ptr %t310 + br i1 %t329, label %scend70, label %sc69 +sc69: + %t331 = load ptr, ptr %t0 + %t332 = call i32 @fn_streq(ptr %t331, ptr @.str429) + %t333 = icmp ne i32 %t332, 0 + %t334 = zext i1 %t333 to i32 + store i32 %t334, ptr %t310 + br label %scend70 +scend70: + %t335 = load i32, ptr %t310 + %t336 = icmp ne i32 %t335, 0 + %t337 = zext i1 %t336 to i32 + store i32 %t337, ptr %t309 + br i1 %t336, label %scend72, label %sc71 +sc71: + %t338 = load ptr, ptr %t0 + %t339 = call i32 @fn_streq(ptr %t338, ptr @.str430) + %t340 = icmp ne i32 %t339, 0 + %t341 = zext i1 %t340 to i32 + store i32 %t341, ptr %t309 + br label %scend72 +scend72: + %t342 = load i32, ptr %t309 + %t343 = icmp ne i32 %t342, 0 + br i1 %t343, label %then73, label %ifend75 +then73: + %t344 = load ptr, ptr %t1 + %t345 = call ptr @fn_arg_code(ptr %t344, i32 0) + store ptr %t345, ptr %t346 + %t347 = load ptr, ptr %t1 + %t348 = call ptr @fn_arg_code(ptr %t347, i32 1) + store ptr %t348, ptr %t349 + store ptr @.str431, ptr %t350 + %t351 = load ptr, ptr %t0 + %t352 = call i32 @fn_streq(ptr %t351, ptr @.str432) + %t353 = icmp ne i32 %t352, 0 + br i1 %t353, label %then76, label %ifend78 +then76: + store ptr @.str433, ptr %t350 + br label %ifend78 +ifend78: + %t354 = load ptr, ptr %t0 + %t355 = call i32 @fn_streq(ptr %t354, ptr @.str434) + %t356 = icmp ne i32 %t355, 0 + br i1 %t356, label %then79, label %ifend81 +then79: + store ptr @.str435, ptr %t350 + br label %ifend81 +ifend81: + %t357 = load ptr, ptr %t0 + %t358 = call i32 @fn_streq(ptr %t357, ptr @.str436) + %t359 = icmp ne i32 %t358, 0 + br i1 %t359, label %then82, label %ifend84 +then82: + store ptr @.str437, ptr %t350 + br label %ifend84 +ifend84: + %t360 = load ptr, ptr %t0 + %t361 = call i32 @fn_streq(ptr %t360, ptr @.str438) + %t362 = icmp ne i32 %t361, 0 + br i1 %t362, label %then85, label %ifend87 +then85: + store ptr @.str439, ptr %t350 + br label %ifend87 +ifend87: + %t363 = load ptr, ptr %t350 + %t364 = load ptr, ptr %t346 + %t365 = load ptr, ptr %t349 + %t366 = call ptr @fn_sconcat(ptr @.str441, ptr %t365) + %t367 = call ptr @fn_sconcat(ptr %t364, ptr %t366) + %t368 = call ptr @fn_sconcat(ptr @.str440, ptr %t367) + %t369 = call ptr @fn_sconcat(ptr %t363, ptr %t368) + %t370 = call ptr @fn_emit_bind(ptr %t369) + %t371 = call ptr @fn_val(ptr %t370, ptr @.str442) + store ptr %t371, ptr %retval + br label %ret +ifend75: + %t372 = load ptr, ptr %t0 + %t373 = call i32 @fn_streq(ptr %t372, ptr @.str443) + %t374 = icmp ne i32 %t373, 0 + br i1 %t374, label %then88, label %ifend90 +then88: + %t375 = load ptr, ptr %t1 + %t376 = call ptr @fn_arg_code(ptr %t375, i32 0) + store ptr %t376, ptr %t377 + %t378 = load ptr, ptr %t1 + %t379 = call ptr @fn_arg_code(ptr %t378, i32 1) + store ptr %t379, ptr %t380 + %t381 = call ptr @fn_nreg() + store ptr %t381, ptr %t382 + call void @fn_emit(ptr @.str444) + %t383 = load ptr, ptr %t382 + call void @fn_emit(ptr %t383) + call void @fn_emit(ptr @.str445) + %t384 = load ptr, ptr %t377 + call void @fn_emit(ptr %t384) + call void @fn_emit(ptr @.str446) + %t385 = load ptr, ptr %t380 + call void @fn_emit(ptr %t385) + call void @fn_emit(ptr @.str447) + %t386 = load ptr, ptr %t382 + %t387 = call ptr @fn_sconcat(ptr @.str448, ptr %t386) + %t388 = call ptr @fn_emit_bind(ptr %t387) + %t389 = call ptr @fn_val(ptr %t388, ptr @.str449) + store ptr %t389, ptr %retval + br label %ret +ifend90: + %t390 = load ptr, ptr %t0 + %t391 = call i32 @fn_streq(ptr %t390, ptr @.str450) + %t392 = icmp ne i32 %t391, 0 + br i1 %t392, label %then91, label %ifend93 +then91: + %t393 = load ptr, ptr %t1 + %t394 = call ptr @fn_arg_code(ptr %t393, i32 0) + store ptr %t394, ptr %t395 + %t396 = load ptr, ptr %t1 + %t397 = call ptr @fn_arg_code(ptr %t396, i32 1) + store ptr %t397, ptr %t398 + %t399 = load ptr, ptr %t1 + %t400 = call ptr @fn_arg_code(ptr %t399, i32 2) + store ptr %t400, ptr %t401 + %t402 = call ptr @fn_nreg() + store ptr %t402, ptr %t403 + call void @fn_emit(ptr @.str451) + %t404 = load ptr, ptr %t403 + call void @fn_emit(ptr %t404) + call void @fn_emit(ptr @.str452) + %t405 = load ptr, ptr %t395 + call void @fn_emit(ptr %t405) + call void @fn_emit(ptr @.str453) + %t406 = load ptr, ptr %t398 + call void @fn_emit(ptr %t406) + call void @fn_emit(ptr @.str454) + call void @fn_emit(ptr @.str455) + %t407 = load ptr, ptr %t401 + call void @fn_emit(ptr %t407) + call void @fn_emit(ptr @.str456) + %t408 = load ptr, ptr %t403 + call void @fn_emit(ptr %t408) + call void @fn_emit(ptr @.str457) + %t409 = call ptr @fn_val(ptr @.str458, ptr @.str459) + store ptr %t409, ptr %retval + br label %ret +ifend93: + store i32 0, ptr @g_g_intrin_ok + %t410 = call ptr @fn_val(ptr @.str460, ptr @.str461) + store ptr %t410, ptr %retval + br label %ret +ret: + %t411 = load ptr, ptr %retval + ret ptr %t411 +} + +define i32 @fn_is_intrinsic2(ptr %arg_name) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t1 = alloca i32 + %t2 = alloca i32 + %t20 = alloca i32 + %t21 = alloca i32 + %t39 = alloca i32 + %t50 = alloca i32 + %t51 = alloca i32 + %t52 = alloca i32 + %t77 = alloca i32 + %t88 = alloca i32 + %t99 = alloca i32 + %t100 = alloca i32 + %t118 = alloca i32 + store ptr %arg_name, ptr %t0 + %t3 = load ptr, ptr %t0 + %t4 = call i32 @fn_streq(ptr %t3, ptr @.str462) + %t5 = icmp ne i32 %t4, 0 + %t6 = zext i1 %t5 to i32 + store i32 %t6, ptr %t2 + br i1 %t5, label %scend1, label %sc0 +sc0: + %t7 = load ptr, ptr %t0 + %t8 = call i32 @fn_streq(ptr %t7, ptr @.str463) + %t9 = icmp ne i32 %t8, 0 + %t10 = zext i1 %t9 to i32 + store i32 %t10, ptr %t2 + br label %scend1 +scend1: + %t11 = load i32, ptr %t2 + %t12 = icmp ne i32 %t11, 0 + %t13 = zext i1 %t12 to i32 + store i32 %t13, ptr %t1 + br i1 %t12, label %scend3, label %sc2 +sc2: + %t14 = load ptr, ptr %t0 + %t15 = call i32 @fn_streq(ptr %t14, ptr @.str464) + %t16 = icmp ne i32 %t15, 0 + %t17 = zext i1 %t16 to i32 + store i32 %t17, ptr %t1 + br label %scend3 +scend3: + %t18 = load i32, ptr %t1 + %t19 = icmp ne i32 %t18, 0 + br i1 %t19, label %then4, label %ifend6 +then4: + store i32 1, ptr %retval + br label %ret +ifend6: + %t22 = load ptr, ptr %t0 + %t23 = call i32 @fn_streq(ptr %t22, ptr @.str465) + %t24 = icmp ne i32 %t23, 0 + %t25 = zext i1 %t24 to i32 + store i32 %t25, ptr %t21 + br i1 %t24, label %scend8, label %sc7 +sc7: + %t26 = load ptr, ptr %t0 + %t27 = call i32 @fn_streq(ptr %t26, ptr @.str466) + %t28 = icmp ne i32 %t27, 0 + %t29 = zext i1 %t28 to i32 + store i32 %t29, ptr %t21 + br label %scend8 +scend8: + %t30 = load i32, ptr %t21 + %t31 = icmp ne i32 %t30, 0 + %t32 = zext i1 %t31 to i32 + store i32 %t32, ptr %t20 + br i1 %t31, label %scend10, label %sc9 +sc9: + %t33 = load ptr, ptr %t0 + %t34 = call i32 @fn_streq(ptr %t33, ptr @.str467) + %t35 = icmp ne i32 %t34, 0 + %t36 = zext i1 %t35 to i32 + store i32 %t36, ptr %t20 + br label %scend10 +scend10: + %t37 = load i32, ptr %t20 + %t38 = icmp ne i32 %t37, 0 + br i1 %t38, label %then11, label %ifend13 +then11: + store i32 1, ptr %retval + br label %ret +ifend13: + %t40 = load ptr, ptr %t0 + %t41 = call i32 @fn_streq(ptr %t40, ptr @.str468) + %t42 = icmp ne i32 %t41, 0 + %t43 = zext i1 %t42 to i32 + store i32 %t43, ptr %t39 + br i1 %t42, label %scend15, label %sc14 +sc14: + %t44 = load ptr, ptr %t0 + %t45 = call i32 @fn_streq(ptr %t44, ptr @.str469) + %t46 = icmp ne i32 %t45, 0 + %t47 = zext i1 %t46 to i32 + store i32 %t47, ptr %t39 + br label %scend15 +scend15: + %t48 = load i32, ptr %t39 + %t49 = icmp ne i32 %t48, 0 + br i1 %t49, label %then16, label %ifend18 +then16: + store i32 1, ptr %retval + br label %ret +ifend18: + %t53 = load ptr, ptr %t0 + %t54 = call i32 @fn_streq(ptr %t53, ptr @.str470) + %t55 = icmp ne i32 %t54, 0 + %t56 = zext i1 %t55 to i32 + store i32 %t56, ptr %t52 + br i1 %t55, label %scend20, label %sc19 +sc19: + %t57 = load ptr, ptr %t0 + %t58 = call i32 @fn_streq(ptr %t57, ptr @.str471) + %t59 = icmp ne i32 %t58, 0 + %t60 = zext i1 %t59 to i32 + store i32 %t60, ptr %t52 + br label %scend20 +scend20: + %t61 = load i32, ptr %t52 + %t62 = icmp ne i32 %t61, 0 + %t63 = zext i1 %t62 to i32 + store i32 %t63, ptr %t51 + br i1 %t62, label %scend22, label %sc21 +sc21: + %t64 = load ptr, ptr %t0 + %t65 = call i32 @fn_streq(ptr %t64, ptr @.str472) + %t66 = icmp ne i32 %t65, 0 + %t67 = zext i1 %t66 to i32 + store i32 %t67, ptr %t51 + br label %scend22 +scend22: + %t68 = load i32, ptr %t51 + %t69 = icmp ne i32 %t68, 0 + %t70 = zext i1 %t69 to i32 + store i32 %t70, ptr %t50 + br i1 %t69, label %scend24, label %sc23 +sc23: + %t71 = load ptr, ptr %t0 + %t72 = call i32 @fn_streq(ptr %t71, ptr @.str473) + %t73 = icmp ne i32 %t72, 0 + %t74 = zext i1 %t73 to i32 + store i32 %t74, ptr %t50 + br label %scend24 +scend24: + %t75 = load i32, ptr %t50 + %t76 = icmp ne i32 %t75, 0 + br i1 %t76, label %then25, label %ifend27 +then25: + store i32 1, ptr %retval + br label %ret +ifend27: + %t78 = load ptr, ptr %t0 + %t79 = call i32 @fn_streq(ptr %t78, ptr @.str474) + %t80 = icmp ne i32 %t79, 0 + %t81 = zext i1 %t80 to i32 + store i32 %t81, ptr %t77 + br i1 %t80, label %scend29, label %sc28 +sc28: + %t82 = load ptr, ptr %t0 + %t83 = call i32 @fn_streq(ptr %t82, ptr @.str475) + %t84 = icmp ne i32 %t83, 0 + %t85 = zext i1 %t84 to i32 + store i32 %t85, ptr %t77 + br label %scend29 +scend29: + %t86 = load i32, ptr %t77 + %t87 = icmp ne i32 %t86, 0 + br i1 %t87, label %then30, label %ifend32 +then30: + store i32 1, ptr %retval + br label %ret +ifend32: + %t89 = load ptr, ptr %t0 + %t90 = call i32 @fn_streq(ptr %t89, ptr @.str476) + %t91 = icmp ne i32 %t90, 0 + %t92 = zext i1 %t91 to i32 + store i32 %t92, ptr %t88 + br i1 %t91, label %scend34, label %sc33 +sc33: + %t93 = load ptr, ptr %t0 + %t94 = call i32 @fn_streq(ptr %t93, ptr @.str477) + %t95 = icmp ne i32 %t94, 0 + %t96 = zext i1 %t95 to i32 + store i32 %t96, ptr %t88 + br label %scend34 +scend34: + %t97 = load i32, ptr %t88 + %t98 = icmp ne i32 %t97, 0 + br i1 %t98, label %then35, label %ifend37 +then35: + store i32 1, ptr %retval + br label %ret +ifend37: + %t101 = load ptr, ptr %t0 + %t102 = call i32 @fn_streq(ptr %t101, ptr @.str478) + %t103 = icmp ne i32 %t102, 0 + %t104 = zext i1 %t103 to i32 + store i32 %t104, ptr %t100 + br i1 %t103, label %scend39, label %sc38 +sc38: + %t105 = load ptr, ptr %t0 + %t106 = call i32 @fn_streq(ptr %t105, ptr @.str479) + %t107 = icmp ne i32 %t106, 0 + %t108 = zext i1 %t107 to i32 + store i32 %t108, ptr %t100 + br label %scend39 +scend39: + %t109 = load i32, ptr %t100 + %t110 = icmp ne i32 %t109, 0 + %t111 = zext i1 %t110 to i32 + store i32 %t111, ptr %t99 + br i1 %t110, label %scend41, label %sc40 +sc40: + %t112 = load ptr, ptr %t0 + %t113 = call i32 @fn_streq(ptr %t112, ptr @.str480) + %t114 = icmp ne i32 %t113, 0 + %t115 = zext i1 %t114 to i32 + store i32 %t115, ptr %t99 + br label %scend41 +scend41: + %t116 = load i32, ptr %t99 + %t117 = icmp ne i32 %t116, 0 + br i1 %t117, label %then42, label %ifend44 +then42: + store i32 1, ptr %retval + br label %ret +ifend44: + %t119 = load ptr, ptr %t0 + %t120 = call i32 @fn_streq(ptr %t119, ptr @.str481) + %t121 = icmp ne i32 %t120, 0 + %t122 = zext i1 %t121 to i32 + store i32 %t122, ptr %t118 + br i1 %t121, label %scend46, label %sc45 +sc45: + %t123 = load ptr, ptr %t0 + %t124 = call i32 @fn_streq(ptr %t123, ptr @.str482) + %t125 = icmp ne i32 %t124, 0 + %t126 = zext i1 %t125 to i32 + store i32 %t126, ptr %t118 + br label %scend46 +scend46: + %t127 = load i32, ptr %t118 + %t128 = icmp ne i32 %t127, 0 + br i1 %t128, label %then47, label %ifend49 +then47: + store i32 1, ptr %retval + br label %ret +ifend49: + store i32 0, ptr %retval + br label %ret +ret: + %t129 = load i32, ptr %retval + ret i32 %t129 +} + +define ptr @fn_emit_intrinsic2(ptr %arg_name, ptr %arg_e) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca ptr + %t7 = alloca ptr + %t15 = alloca ptr + %t18 = alloca ptr + %t21 = alloca ptr + %t26 = alloca ptr + %t36 = alloca ptr + %t39 = alloca ptr + %t42 = alloca ptr + %t47 = alloca ptr + %t57 = alloca ptr + %t60 = alloca ptr + %t62 = alloca ptr + %t78 = alloca ptr + %t86 = alloca ptr + %t91 = alloca ptr + %t101 = alloca ptr + %t112 = alloca ptr + %t115 = alloca ptr + %t117 = alloca ptr + %t130 = alloca ptr + %t133 = alloca ptr + %t136 = alloca ptr + %t138 = alloca ptr + %t150 = alloca ptr + %t153 = alloca ptr + %t155 = alloca ptr + %t168 = alloca ptr + %t171 = alloca ptr + %t174 = alloca ptr + %t176 = alloca ptr + %t194 = alloca ptr + %t210 = alloca ptr + %t241 = alloca ptr + %t244 = alloca ptr + %t247 = alloca ptr + %t250 = alloca ptr + %t261 = alloca ptr + %t264 = alloca ptr + %t267 = alloca ptr + store ptr %arg_name, ptr %t0 + store ptr %arg_e, ptr %t1 + %t2 = load ptr, ptr %t0 + %t3 = call i32 @fn_streq(ptr %t2, ptr @.str483) + %t4 = icmp ne i32 %t3, 0 + br i1 %t4, label %then0, label %ifend2 +then0: + %t5 = load ptr, ptr %t1 + %t6 = call ptr @fn_arg_code(ptr %t5, i32 0) + store ptr %t6, ptr %t7 + call void @fn_emit(ptr @.str484) + %t8 = load ptr, ptr %t7 + call void @fn_emit(ptr %t8) + call void @fn_emit(ptr @.str485) + %t9 = call ptr @fn_val(ptr @.str486, ptr @.str487) + store ptr %t9, ptr %retval + br label %ret +ifend2: + %t10 = load ptr, ptr %t0 + %t11 = call i32 @fn_streq(ptr %t10, ptr @.str488) + %t12 = icmp ne i32 %t11, 0 + br i1 %t12, label %then3, label %ifend5 +then3: + %t13 = load ptr, ptr %t1 + %t14 = call ptr @fn_arg_code(ptr %t13, i32 0) + store ptr %t14, ptr %t15 + %t16 = load ptr, ptr %t1 + %t17 = call ptr @fn_arg_code(ptr %t16, i32 1) + store ptr %t17, ptr %t18 + %t19 = load ptr, ptr %t1 + %t20 = call ptr @fn_arg_code(ptr %t19, i32 2) + store ptr %t20, ptr %t21 + %t22 = load ptr, ptr %t21 + %t23 = call ptr @fn_sconcat(ptr %t22, ptr @.str490) + %t24 = call ptr @fn_sconcat(ptr @.str489, ptr %t23) + %t25 = call ptr @fn_emit_bind(ptr %t24) + store ptr %t25, ptr %t26 + call void @fn_emit(ptr @.str491) + %t27 = load ptr, ptr %t15 + call void @fn_emit(ptr %t27) + call void @fn_emit(ptr @.str492) + %t28 = load ptr, ptr %t18 + call void @fn_emit(ptr %t28) + call void @fn_emit(ptr @.str493) + %t29 = load ptr, ptr %t26 + call void @fn_emit(ptr %t29) + call void @fn_emit(ptr @.str494) + %t30 = call ptr @fn_val(ptr @.str495, ptr @.str496) + store ptr %t30, ptr %retval + br label %ret +ifend5: + %t31 = load ptr, ptr %t0 + %t32 = call i32 @fn_streq(ptr %t31, ptr @.str497) + %t33 = icmp ne i32 %t32, 0 + br i1 %t33, label %then6, label %ifend8 +then6: + %t34 = load ptr, ptr %t1 + %t35 = call ptr @fn_arg_code(ptr %t34, i32 0) + store ptr %t35, ptr %t36 + %t37 = load ptr, ptr %t1 + %t38 = call ptr @fn_arg_code(ptr %t37, i32 1) + store ptr %t38, ptr %t39 + %t40 = load ptr, ptr %t1 + %t41 = call ptr @fn_arg_code(ptr %t40, i32 2) + store ptr %t41, ptr %t42 + %t43 = load ptr, ptr %t42 + %t44 = call ptr @fn_sconcat(ptr %t43, ptr @.str499) + %t45 = call ptr @fn_sconcat(ptr @.str498, ptr %t44) + %t46 = call ptr @fn_emit_bind(ptr %t45) + store ptr %t46, ptr %t47 + call void @fn_emit(ptr @.str500) + %t48 = load ptr, ptr %t36 + call void @fn_emit(ptr %t48) + call void @fn_emit(ptr @.str501) + %t49 = load ptr, ptr %t39 + call void @fn_emit(ptr %t49) + call void @fn_emit(ptr @.str502) + %t50 = load ptr, ptr %t47 + call void @fn_emit(ptr %t50) + call void @fn_emit(ptr @.str503) + %t51 = call ptr @fn_val(ptr @.str504, ptr @.str505) + store ptr %t51, ptr %retval + br label %ret +ifend8: + %t52 = load ptr, ptr %t0 + %t53 = call i32 @fn_streq(ptr %t52, ptr @.str506) + %t54 = icmp ne i32 %t53, 0 + br i1 %t54, label %then9, label %ifend11 +then9: + %t55 = load ptr, ptr %t1 + %t56 = call ptr @fn_arg_code(ptr %t55, i32 0) + store ptr %t56, ptr %t57 + %t58 = load ptr, ptr %t1 + %t59 = call ptr @fn_arg_code(ptr %t58, i32 1) + store ptr %t59, ptr %t60 + %t61 = call ptr @fn_nreg() + store ptr %t61, ptr %t62 + call void @fn_emit(ptr @.str507) + %t63 = load ptr, ptr %t62 + call void @fn_emit(ptr %t63) + call void @fn_emit(ptr @.str508) + %t64 = load ptr, ptr %t57 + call void @fn_emit(ptr %t64) + call void @fn_emit(ptr @.str509) + %t65 = load ptr, ptr %t60 + call void @fn_emit(ptr %t65) + call void @fn_emit(ptr @.str510) + %t66 = load ptr, ptr %t62 + %t67 = call ptr @fn_val(ptr %t66, ptr @.str511) + store ptr %t67, ptr %retval + br label %ret +ifend11: + %t68 = load ptr, ptr %t0 + %t69 = call i32 @fn_streq(ptr %t68, ptr @.str512) + %t70 = icmp ne i32 %t69, 0 + br i1 %t70, label %then12, label %ifend14 +then12: + %t71 = call ptr @fn_emit_bind(ptr @.str513) + %t72 = call ptr @fn_val(ptr %t71, ptr @.str514) + store ptr %t72, ptr %retval + br label %ret +ifend14: + %t73 = load ptr, ptr %t0 + %t74 = call i32 @fn_streq(ptr %t73, ptr @.str515) + %t75 = icmp ne i32 %t74, 0 + br i1 %t75, label %then15, label %ifend17 +then15: + %t76 = load ptr, ptr %t1 + %t77 = call ptr @fn_arg_code(ptr %t76, i32 0) + store ptr %t77, ptr %t78 + call void @fn_emit(ptr @.str516) + %t79 = load ptr, ptr %t78 + call void @fn_emit(ptr %t79) + call void @fn_emit(ptr @.str517) + %t80 = call ptr @fn_val(ptr @.str518, ptr @.str519) + store ptr %t80, ptr %retval + br label %ret +ifend17: + %t81 = load ptr, ptr %t0 + %t82 = call i32 @fn_streq(ptr %t81, ptr @.str520) + %t83 = icmp ne i32 %t82, 0 + br i1 %t83, label %then18, label %ifend20 +then18: + %t84 = load ptr, ptr %t1 + %t85 = call ptr @fn_arg_code(ptr %t84, i32 0) + store ptr %t85, ptr %t86 + %t87 = load ptr, ptr %t86 + %t88 = call ptr @fn_sconcat(ptr %t87, ptr @.str522) + %t89 = call ptr @fn_sconcat(ptr @.str521, ptr %t88) + %t90 = call ptr @fn_emit_bind(ptr %t89) + store ptr %t90, ptr %t91 + %t92 = load ptr, ptr %t91 + %t93 = call ptr @fn_sconcat(ptr %t92, ptr @.str524) + %t94 = call ptr @fn_sconcat(ptr @.str523, ptr %t93) + %t95 = call ptr @fn_emit_bind(ptr %t94) + %t96 = call ptr @fn_val(ptr %t95, ptr @.str525) + store ptr %t96, ptr %retval + br label %ret +ifend20: + %t97 = load ptr, ptr %t0 + %t98 = call i32 @fn_streq(ptr %t97, ptr @.str526) + %t99 = icmp ne i32 %t98, 0 + br i1 %t99, label %then21, label %ifend23 +then21: + %t100 = call ptr @fn_emit_bind(ptr @.str527) + store ptr %t100, ptr %t101 + %t102 = load ptr, ptr %t101 + %t103 = call ptr @fn_sconcat(ptr %t102, ptr @.str529) + %t104 = call ptr @fn_sconcat(ptr @.str528, ptr %t103) + %t105 = call ptr @fn_emit_bind(ptr %t104) + %t106 = call ptr @fn_val(ptr %t105, ptr @.str530) + store ptr %t106, ptr %retval + br label %ret +ifend23: + %t107 = load ptr, ptr %t0 + %t108 = call i32 @fn_streq(ptr %t107, ptr @.str531) + %t109 = icmp ne i32 %t108, 0 + br i1 %t109, label %then24, label %ifend26 +then24: + %t110 = load ptr, ptr %t1 + %t111 = call ptr @fn_arg_code(ptr %t110, i32 0) + store ptr %t111, ptr %t112 + %t113 = load ptr, ptr %t1 + %t114 = call ptr @fn_arg_code(ptr %t113, i32 1) + store ptr %t114, ptr %t115 + %t116 = call ptr @fn_nreg() + store ptr %t116, ptr %t117 + call void @fn_emit(ptr @.str532) + %t118 = load ptr, ptr %t117 + call void @fn_emit(ptr %t118) + call void @fn_emit(ptr @.str533) + %t119 = load ptr, ptr %t112 + call void @fn_emit(ptr %t119) + call void @fn_emit(ptr @.str534) + %t120 = load ptr, ptr %t115 + call void @fn_emit(ptr %t120) + call void @fn_emit(ptr @.str535) + %t121 = load ptr, ptr %t117 + %t122 = call ptr @fn_sconcat(ptr @.str536, ptr %t121) + %t123 = call ptr @fn_emit_bind(ptr %t122) + %t124 = call ptr @fn_val(ptr %t123, ptr @.str537) + store ptr %t124, ptr %retval + br label %ret +ifend26: + %t125 = load ptr, ptr %t0 + %t126 = call i32 @fn_streq(ptr %t125, ptr @.str538) + %t127 = icmp ne i32 %t126, 0 + br i1 %t127, label %then27, label %ifend29 +then27: + %t128 = load ptr, ptr %t1 + %t129 = call ptr @fn_arg_code(ptr %t128, i32 0) + store ptr %t129, ptr %t130 + %t131 = load ptr, ptr %t1 + %t132 = call ptr @fn_arg_code(ptr %t131, i32 1) + store ptr %t132, ptr %t133 + %t134 = load ptr, ptr %t1 + %t135 = call ptr @fn_arg_code(ptr %t134, i32 2) + store ptr %t135, ptr %t136 + %t137 = call ptr @fn_nreg() + store ptr %t137, ptr %t138 + call void @fn_emit(ptr @.str539) + %t139 = load ptr, ptr %t138 + call void @fn_emit(ptr %t139) + call void @fn_emit(ptr @.str540) + %t140 = load ptr, ptr %t130 + call void @fn_emit(ptr %t140) + call void @fn_emit(ptr @.str541) + %t141 = load ptr, ptr %t133 + call void @fn_emit(ptr %t141) + call void @fn_emit(ptr @.str542) + call void @fn_emit(ptr @.str543) + %t142 = load ptr, ptr %t136 + call void @fn_emit(ptr %t142) + call void @fn_emit(ptr @.str544) + %t143 = load ptr, ptr %t138 + call void @fn_emit(ptr %t143) + call void @fn_emit(ptr @.str545) + %t144 = call ptr @fn_val(ptr @.str546, ptr @.str547) + store ptr %t144, ptr %retval + br label %ret +ifend29: + %t145 = load ptr, ptr %t0 + %t146 = call i32 @fn_streq(ptr %t145, ptr @.str548) + %t147 = icmp ne i32 %t146, 0 + br i1 %t147, label %then30, label %ifend32 +then30: + %t148 = load ptr, ptr %t1 + %t149 = call ptr @fn_arg_code(ptr %t148, i32 0) + store ptr %t149, ptr %t150 + %t151 = load ptr, ptr %t1 + %t152 = call ptr @fn_arg_code(ptr %t151, i32 1) + store ptr %t152, ptr %t153 + %t154 = call ptr @fn_nreg() + store ptr %t154, ptr %t155 + call void @fn_emit(ptr @.str549) + %t156 = load ptr, ptr %t155 + call void @fn_emit(ptr %t156) + call void @fn_emit(ptr @.str550) + %t157 = load ptr, ptr %t150 + call void @fn_emit(ptr %t157) + call void @fn_emit(ptr @.str551) + %t158 = load ptr, ptr %t153 + call void @fn_emit(ptr %t158) + call void @fn_emit(ptr @.str552) + %t159 = load ptr, ptr %t155 + %t160 = call ptr @fn_sconcat(ptr @.str553, ptr %t159) + %t161 = call ptr @fn_emit_bind(ptr %t160) + %t162 = call ptr @fn_val(ptr %t161, ptr @.str554) + store ptr %t162, ptr %retval + br label %ret +ifend32: + %t163 = load ptr, ptr %t0 + %t164 = call i32 @fn_streq(ptr %t163, ptr @.str555) + %t165 = icmp ne i32 %t164, 0 + br i1 %t165, label %then33, label %ifend35 +then33: + %t166 = load ptr, ptr %t1 + %t167 = call ptr @fn_arg_code(ptr %t166, i32 0) + store ptr %t167, ptr %t168 + %t169 = load ptr, ptr %t1 + %t170 = call ptr @fn_arg_code(ptr %t169, i32 1) + store ptr %t170, ptr %t171 + %t172 = load ptr, ptr %t1 + %t173 = call ptr @fn_arg_code(ptr %t172, i32 2) + store ptr %t173, ptr %t174 + %t175 = call ptr @fn_nreg() + store ptr %t175, ptr %t176 + call void @fn_emit(ptr @.str556) + %t177 = load ptr, ptr %t176 + call void @fn_emit(ptr %t177) + call void @fn_emit(ptr @.str557) + %t178 = load ptr, ptr %t168 + call void @fn_emit(ptr %t178) + call void @fn_emit(ptr @.str558) + %t179 = load ptr, ptr %t171 + call void @fn_emit(ptr %t179) + call void @fn_emit(ptr @.str559) + call void @fn_emit(ptr @.str560) + %t180 = load ptr, ptr %t174 + call void @fn_emit(ptr %t180) + call void @fn_emit(ptr @.str561) + %t181 = load ptr, ptr %t176 + call void @fn_emit(ptr %t181) + call void @fn_emit(ptr @.str562) + %t182 = call ptr @fn_val(ptr @.str563, ptr @.str564) + store ptr %t182, ptr %retval + br label %ret +ifend35: + %t183 = load ptr, ptr %t0 + %t184 = call i32 @fn_streq(ptr %t183, ptr @.str565) + %t185 = icmp ne i32 %t184, 0 + br i1 %t185, label %then36, label %ifend38 +then36: + %t186 = load ptr, ptr %t1 + %t187 = getelementptr inbounds %Str_Node, ptr %t186, i32 0, i32 7 + %t188 = load ptr, ptr %t187 + %t189 = getelementptr inbounds %LSlice, ptr %t188, i32 0, i32 0 + %t190 = load ptr, ptr %t189 + %t191 = getelementptr inbounds ptr, ptr %t190, i32 0 + %t192 = load ptr, ptr %t191 + %t193 = call ptr @fn_emit_expr(ptr %t192) + store ptr %t193, ptr %t194 + %t195 = load ptr, ptr %t194 + %t196 = getelementptr inbounds %Str_Val, ptr %t195, i32 0, i32 0 + %t197 = load ptr, ptr %t196 + %t198 = call ptr @fn_val(ptr %t197, ptr @.str566) + store ptr %t198, ptr %retval + br label %ret +ifend38: + %t199 = load ptr, ptr %t0 + %t200 = call i32 @fn_streq(ptr %t199, ptr @.str567) + %t201 = icmp ne i32 %t200, 0 + br i1 %t201, label %then39, label %ifend41 +then39: + %t202 = load ptr, ptr %t1 + %t203 = getelementptr inbounds %Str_Node, ptr %t202, i32 0, i32 7 + %t204 = load ptr, ptr %t203 + %t205 = getelementptr inbounds %LSlice, ptr %t204, i32 0, i32 0 + %t206 = load ptr, ptr %t205 + %t207 = getelementptr inbounds ptr, ptr %t206, i32 0 + %t208 = load ptr, ptr %t207 + %t209 = call ptr @fn_emit_expr(ptr %t208) + store ptr %t209, ptr %t210 + %t211 = load ptr, ptr %t210 + %t212 = getelementptr inbounds %Str_Val, ptr %t211, i32 0, i32 0 + %t213 = load ptr, ptr %t212 + %t214 = call ptr @fn_val(ptr %t213, ptr @.str568) + store ptr %t214, ptr %retval + br label %ret +ifend41: + %t215 = load ptr, ptr %t0 + %t216 = call i32 @fn_streq(ptr %t215, ptr @.str569) + %t217 = icmp ne i32 %t216, 0 + br i1 %t217, label %then42, label %ifend44 +then42: + %t218 = load i32, ptr @g_g_windowed + %t219 = icmp ne i32 %t218, 0 + br i1 %t219, label %then45, label %ifend47 +then45: + %t220 = call ptr @fn_val(ptr @.str570, ptr @.str571) + store ptr %t220, ptr %retval + br label %ret +ifend47: + %t221 = call ptr @fn_val(ptr @.str572, ptr @.str573) + store ptr %t221, ptr %retval + br label %ret +ifend44: + %t222 = load ptr, ptr %t0 + %t223 = call i32 @fn_streq(ptr %t222, ptr @.str574) + %t224 = icmp ne i32 %t223, 0 + br i1 %t224, label %then48, label %ifend50 +then48: + %t225 = call ptr @fn_val(ptr @.str575, ptr @.str576) + store ptr %t225, ptr %retval + br label %ret +ifend50: + %t226 = load ptr, ptr %t0 + %t227 = call i32 @fn_streq(ptr %t226, ptr @.str577) + %t228 = icmp ne i32 %t227, 0 + br i1 %t228, label %then51, label %ifend53 +then51: + %t229 = call ptr @fn_emit_bind(ptr @.str578) + %t230 = call ptr @fn_val(ptr %t229, ptr @.str579) + store ptr %t230, ptr %retval + br label %ret +ifend53: + %t231 = load ptr, ptr %t0 + %t232 = call i32 @fn_streq(ptr %t231, ptr @.str580) + %t233 = icmp ne i32 %t232, 0 + br i1 %t233, label %then54, label %ifend56 +then54: + %t234 = call ptr @fn_emit_bind(ptr @.str581) + %t235 = call ptr @fn_val(ptr %t234, ptr @.str582) + store ptr %t235, ptr %retval + br label %ret +ifend56: + %t236 = load ptr, ptr %t0 + %t237 = call i32 @fn_streq(ptr %t236, ptr @.str583) + %t238 = icmp ne i32 %t237, 0 + br i1 %t238, label %then57, label %ifend59 +then57: + %t239 = load ptr, ptr %t1 + %t240 = call ptr @fn_arg_code(ptr %t239, i32 0) + store ptr %t240, ptr %t241 + %t242 = load ptr, ptr %t1 + %t243 = call ptr @fn_arg_code(ptr %t242, i32 1) + store ptr %t243, ptr %t244 + %t245 = load ptr, ptr %t1 + %t246 = call ptr @fn_arg_code(ptr %t245, i32 2) + store ptr %t246, ptr %t247 + %t248 = load ptr, ptr %t1 + %t249 = call ptr @fn_arg_code(ptr %t248, i32 3) + store ptr %t249, ptr %t250 + call void @fn_emit(ptr @.str584) + %t251 = load ptr, ptr %t241 + call void @fn_emit(ptr %t251) + call void @fn_emit(ptr @.str585) + %t252 = load ptr, ptr %t244 + call void @fn_emit(ptr %t252) + call void @fn_emit(ptr @.str586) + %t253 = load ptr, ptr %t247 + call void @fn_emit(ptr %t253) + call void @fn_emit(ptr @.str587) + %t254 = load ptr, ptr %t250 + call void @fn_emit(ptr %t254) + call void @fn_emit(ptr @.str588) + %t255 = call ptr @fn_val(ptr @.str589, ptr @.str590) + store ptr %t255, ptr %retval + br label %ret +ifend59: + %t256 = load ptr, ptr %t0 + %t257 = call i32 @fn_streq(ptr %t256, ptr @.str591) + %t258 = icmp ne i32 %t257, 0 + br i1 %t258, label %then60, label %ifend62 +then60: + %t259 = load ptr, ptr %t1 + %t260 = call ptr @fn_arg_code(ptr %t259, i32 0) + store ptr %t260, ptr %t261 + %t262 = load ptr, ptr %t1 + %t263 = call ptr @fn_arg_code(ptr %t262, i32 1) + store ptr %t263, ptr %t264 + %t265 = load ptr, ptr %t1 + %t266 = call ptr @fn_arg_code(ptr %t265, i32 2) + store ptr %t266, ptr %t267 + call void @fn_emit(ptr @.str592) + %t268 = load ptr, ptr %t261 + call void @fn_emit(ptr %t268) + call void @fn_emit(ptr @.str593) + %t269 = load ptr, ptr %t264 + call void @fn_emit(ptr %t269) + call void @fn_emit(ptr @.str594) + %t270 = load ptr, ptr %t267 + call void @fn_emit(ptr %t270) + call void @fn_emit(ptr @.str595) + %t271 = call ptr @fn_val(ptr @.str596, ptr @.str597) + store ptr %t271, ptr %retval + br label %ret +ifend62: + %t272 = load ptr, ptr %t0 + %t273 = call i32 @fn_streq(ptr %t272, ptr @.str598) + %t274 = icmp ne i32 %t273, 0 + br i1 %t274, label %then63, label %ifend65 +then63: + call void @fn_emit(ptr @.str599) + %t275 = call ptr @fn_val(ptr @.str600, ptr @.str601) + store ptr %t275, ptr %retval + br label %ret +ifend65: + %t276 = call ptr @fn_val(ptr @.str602, ptr @.str603) + store ptr %t276, ptr %retval + br label %ret +ret: + %t277 = load ptr, ptr %retval + ret ptr %t277 +} + +define i32 @fn_is_math_builtin(ptr %arg_name) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t1 = alloca i32 + %t2 = alloca i32 + %t3 = alloca i32 + store ptr %arg_name, ptr %t0 + %t4 = load ptr, ptr %t0 + %t5 = call i32 @fn_streq(ptr %t4, ptr @.str604) + %t6 = icmp ne i32 %t5, 0 + %t7 = zext i1 %t6 to i32 + store i32 %t7, ptr %t3 + br i1 %t6, label %scend1, label %sc0 +sc0: + %t8 = load ptr, ptr %t0 + %t9 = call i32 @fn_streq(ptr %t8, ptr @.str605) + %t10 = icmp ne i32 %t9, 0 + %t11 = zext i1 %t10 to i32 + store i32 %t11, ptr %t3 + br label %scend1 +scend1: + %t12 = load i32, ptr %t3 + %t13 = icmp ne i32 %t12, 0 + %t14 = zext i1 %t13 to i32 + store i32 %t14, ptr %t2 + br i1 %t13, label %scend3, label %sc2 +sc2: + %t15 = load ptr, ptr %t0 + %t16 = call i32 @fn_streq(ptr %t15, ptr @.str606) + %t17 = icmp ne i32 %t16, 0 + %t18 = zext i1 %t17 to i32 + store i32 %t18, ptr %t2 + br label %scend3 +scend3: + %t19 = load i32, ptr %t2 + %t20 = icmp ne i32 %t19, 0 + %t21 = zext i1 %t20 to i32 + store i32 %t21, ptr %t1 + br i1 %t20, label %scend5, label %sc4 +sc4: + %t22 = load ptr, ptr %t0 + %t23 = call i32 @fn_streq(ptr %t22, ptr @.str607) + %t24 = icmp ne i32 %t23, 0 + %t25 = zext i1 %t24 to i32 + store i32 %t25, ptr %t1 + br label %scend5 +scend5: + %t26 = load i32, ptr %t1 + store i32 %t26, ptr %retval + br label %ret +ret: + %t27 = load i32, ptr %retval + ret i32 %t27 +} + +define ptr @fn_emit_math_builtin(ptr %arg_name, ptr %arg_e) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca ptr + %t13 = alloca ptr + %t20 = alloca ptr + %t26 = alloca ptr + %t39 = alloca i32 + %t58 = alloca ptr + %t67 = alloca ptr + %t68 = alloca ptr + %t85 = alloca ptr + %t108 = alloca ptr + %t117 = alloca ptr + %t126 = alloca ptr + %t137 = alloca ptr + %t151 = alloca ptr + %t160 = alloca ptr + store ptr %arg_name, ptr %t0 + store ptr %arg_e, ptr %t1 + %t2 = load ptr, ptr %t0 + %t3 = call i32 @fn_streq(ptr %t2, ptr @.str608) + %t4 = icmp ne i32 %t3, 0 + br i1 %t4, label %then0, label %ifend2 +then0: + %t5 = load ptr, ptr %t1 + %t6 = getelementptr inbounds %Str_Node, ptr %t5, i32 0, i32 7 + %t7 = load ptr, ptr %t6 + %t8 = getelementptr inbounds %LSlice, ptr %t7, i32 0, i32 0 + %t9 = load ptr, ptr %t8 + %t10 = getelementptr inbounds ptr, ptr %t9, i32 0 + %t11 = load ptr, ptr %t10 + %t12 = call ptr @fn_emit_expr(ptr %t11) + store ptr %t12, ptr %t13 + %t14 = load ptr, ptr %t13 + %t15 = getelementptr inbounds %Str_Val, ptr %t14, i32 0, i32 0 + %t16 = load ptr, ptr %t15 + %t17 = call ptr @fn_sconcat(ptr %t16, ptr @.str610) + %t18 = call ptr @fn_sconcat(ptr @.str609, ptr %t17) + %t19 = call ptr @fn_emit_bind(ptr %t18) + store ptr %t19, ptr %t20 + %t21 = load ptr, ptr %t13 + %t22 = getelementptr inbounds %Str_Val, ptr %t21, i32 0, i32 0 + %t23 = load ptr, ptr %t22 + %t24 = call ptr @fn_sconcat(ptr @.str611, ptr %t23) + %t25 = call ptr @fn_emit_bind(ptr %t24) + store ptr %t25, ptr %t26 + %t27 = load ptr, ptr %t20 + %t28 = load ptr, ptr %t26 + %t29 = load ptr, ptr %t13 + %t30 = getelementptr inbounds %Str_Val, ptr %t29, i32 0, i32 0 + %t31 = load ptr, ptr %t30 + %t32 = call ptr @fn_sconcat(ptr @.str614, ptr %t31) + %t33 = call ptr @fn_sconcat(ptr %t28, ptr %t32) + %t34 = call ptr @fn_sconcat(ptr @.str613, ptr %t33) + %t35 = call ptr @fn_sconcat(ptr %t27, ptr %t34) + %t36 = call ptr @fn_sconcat(ptr @.str612, ptr %t35) + %t37 = call ptr @fn_emit_bind(ptr %t36) + %t38 = call ptr @fn_val(ptr %t37, ptr @.str615) + store ptr %t38, ptr %retval + br label %ret +ifend2: + %t40 = load ptr, ptr %t0 + %t41 = call i32 @fn_streq(ptr %t40, ptr @.str616) + %t42 = icmp ne i32 %t41, 0 + %t43 = zext i1 %t42 to i32 + store i32 %t43, ptr %t39 + br i1 %t42, label %scend4, label %sc3 +sc3: + %t44 = load ptr, ptr %t0 + %t45 = call i32 @fn_streq(ptr %t44, ptr @.str617) + %t46 = icmp ne i32 %t45, 0 + %t47 = zext i1 %t46 to i32 + store i32 %t47, ptr %t39 + br label %scend4 +scend4: + %t48 = load i32, ptr %t39 + %t49 = icmp ne i32 %t48, 0 + br i1 %t49, label %then5, label %ifend7 +then5: + %t50 = load ptr, ptr %t1 + %t51 = getelementptr inbounds %Str_Node, ptr %t50, i32 0, i32 7 + %t52 = load ptr, ptr %t51 + %t53 = getelementptr inbounds %LSlice, ptr %t52, i32 0, i32 0 + %t54 = load ptr, ptr %t53 + %t55 = getelementptr inbounds ptr, ptr %t54, i32 0 + %t56 = load ptr, ptr %t55 + %t57 = call ptr @fn_emit_expr(ptr %t56) + store ptr %t57, ptr %t58 + %t59 = load ptr, ptr %t1 + %t60 = getelementptr inbounds %Str_Node, ptr %t59, i32 0, i32 7 + %t61 = load ptr, ptr %t60 + %t62 = getelementptr inbounds %LSlice, ptr %t61, i32 0, i32 0 + %t63 = load ptr, ptr %t62 + %t64 = getelementptr inbounds ptr, ptr %t63, i32 1 + %t65 = load ptr, ptr %t64 + %t66 = call ptr @fn_emit_expr(ptr %t65) + store ptr %t66, ptr %t67 + store ptr @.str618, ptr %t68 + %t69 = load ptr, ptr %t0 + %t70 = call i32 @fn_streq(ptr %t69, ptr @.str619) + %t71 = icmp ne i32 %t70, 0 + br i1 %t71, label %then8, label %ifend10 +then8: + store ptr @.str620, ptr %t68 + br label %ifend10 +ifend10: + %t72 = load ptr, ptr %t68 + %t73 = load ptr, ptr %t58 + %t74 = getelementptr inbounds %Str_Val, ptr %t73, i32 0, i32 0 + %t75 = load ptr, ptr %t74 + %t76 = load ptr, ptr %t67 + %t77 = getelementptr inbounds %Str_Val, ptr %t76, i32 0, i32 0 + %t78 = load ptr, ptr %t77 + %t79 = call ptr @fn_sconcat(ptr @.str623, ptr %t78) + %t80 = call ptr @fn_sconcat(ptr %t75, ptr %t79) + %t81 = call ptr @fn_sconcat(ptr @.str622, ptr %t80) + %t82 = call ptr @fn_sconcat(ptr %t72, ptr %t81) + %t83 = call ptr @fn_sconcat(ptr @.str621, ptr %t82) + %t84 = call ptr @fn_emit_bind(ptr %t83) + store ptr %t84, ptr %t85 + %t86 = load ptr, ptr %t85 + %t87 = load ptr, ptr %t58 + %t88 = getelementptr inbounds %Str_Val, ptr %t87, i32 0, i32 0 + %t89 = load ptr, ptr %t88 + %t90 = load ptr, ptr %t67 + %t91 = getelementptr inbounds %Str_Val, ptr %t90, i32 0, i32 0 + %t92 = load ptr, ptr %t91 + %t93 = call ptr @fn_sconcat(ptr @.str626, ptr %t92) + %t94 = call ptr @fn_sconcat(ptr %t89, ptr %t93) + %t95 = call ptr @fn_sconcat(ptr @.str625, ptr %t94) + %t96 = call ptr @fn_sconcat(ptr %t86, ptr %t95) + %t97 = call ptr @fn_sconcat(ptr @.str624, ptr %t96) + %t98 = call ptr @fn_emit_bind(ptr %t97) + %t99 = call ptr @fn_val(ptr %t98, ptr @.str627) + store ptr %t99, ptr %retval + br label %ret +ifend7: + %t100 = load ptr, ptr %t1 + %t101 = getelementptr inbounds %Str_Node, ptr %t100, i32 0, i32 7 + %t102 = load ptr, ptr %t101 + %t103 = getelementptr inbounds %LSlice, ptr %t102, i32 0, i32 0 + %t104 = load ptr, ptr %t103 + %t105 = getelementptr inbounds ptr, ptr %t104, i32 0 + %t106 = load ptr, ptr %t105 + %t107 = call ptr @fn_emit_expr(ptr %t106) + store ptr %t107, ptr %t108 + %t109 = load ptr, ptr %t1 + %t110 = getelementptr inbounds %Str_Node, ptr %t109, i32 0, i32 7 + %t111 = load ptr, ptr %t110 + %t112 = getelementptr inbounds %LSlice, ptr %t111, i32 0, i32 0 + %t113 = load ptr, ptr %t112 + %t114 = getelementptr inbounds ptr, ptr %t113, i32 1 + %t115 = load ptr, ptr %t114 + %t116 = call ptr @fn_emit_expr(ptr %t115) + store ptr %t116, ptr %t117 + %t118 = load ptr, ptr %t1 + %t119 = getelementptr inbounds %Str_Node, ptr %t118, i32 0, i32 7 + %t120 = load ptr, ptr %t119 + %t121 = getelementptr inbounds %LSlice, ptr %t120, i32 0, i32 0 + %t122 = load ptr, ptr %t121 + %t123 = getelementptr inbounds ptr, ptr %t122, i32 2 + %t124 = load ptr, ptr %t123 + %t125 = call ptr @fn_emit_expr(ptr %t124) + store ptr %t125, ptr %t126 + %t127 = load ptr, ptr %t108 + %t128 = getelementptr inbounds %Str_Val, ptr %t127, i32 0, i32 0 + %t129 = load ptr, ptr %t128 + %t130 = load ptr, ptr %t126 + %t131 = getelementptr inbounds %Str_Val, ptr %t130, i32 0, i32 0 + %t132 = load ptr, ptr %t131 + %t133 = call ptr @fn_sconcat(ptr @.str629, ptr %t132) + %t134 = call ptr @fn_sconcat(ptr %t129, ptr %t133) + %t135 = call ptr @fn_sconcat(ptr @.str628, ptr %t134) + %t136 = call ptr @fn_emit_bind(ptr %t135) + store ptr %t136, ptr %t137 + %t138 = load ptr, ptr %t137 + %t139 = load ptr, ptr %t108 + %t140 = getelementptr inbounds %Str_Val, ptr %t139, i32 0, i32 0 + %t141 = load ptr, ptr %t140 + %t142 = load ptr, ptr %t126 + %t143 = getelementptr inbounds %Str_Val, ptr %t142, i32 0, i32 0 + %t144 = load ptr, ptr %t143 + %t145 = call ptr @fn_sconcat(ptr @.str632, ptr %t144) + %t146 = call ptr @fn_sconcat(ptr %t141, ptr %t145) + %t147 = call ptr @fn_sconcat(ptr @.str631, ptr %t146) + %t148 = call ptr @fn_sconcat(ptr %t138, ptr %t147) + %t149 = call ptr @fn_sconcat(ptr @.str630, ptr %t148) + %t150 = call ptr @fn_emit_bind(ptr %t149) + store ptr %t150, ptr %t151 + %t152 = load ptr, ptr %t117 + %t153 = getelementptr inbounds %Str_Val, ptr %t152, i32 0, i32 0 + %t154 = load ptr, ptr %t153 + %t155 = load ptr, ptr %t151 + %t156 = call ptr @fn_sconcat(ptr @.str634, ptr %t155) + %t157 = call ptr @fn_sconcat(ptr %t154, ptr %t156) + %t158 = call ptr @fn_sconcat(ptr @.str633, ptr %t157) + %t159 = call ptr @fn_emit_bind(ptr %t158) + store ptr %t159, ptr %t160 + %t161 = load ptr, ptr %t160 + %t162 = load ptr, ptr %t117 + %t163 = getelementptr inbounds %Str_Val, ptr %t162, i32 0, i32 0 + %t164 = load ptr, ptr %t163 + %t165 = load ptr, ptr %t151 + %t166 = call ptr @fn_sconcat(ptr @.str637, ptr %t165) + %t167 = call ptr @fn_sconcat(ptr %t164, ptr %t166) + %t168 = call ptr @fn_sconcat(ptr @.str636, ptr %t167) + %t169 = call ptr @fn_sconcat(ptr %t161, ptr %t168) + %t170 = call ptr @fn_sconcat(ptr @.str635, ptr %t169) + %t171 = call ptr @fn_emit_bind(ptr %t170) + %t172 = call ptr @fn_val(ptr %t171, ptr @.str638) + store ptr %t172, ptr %retval + br label %ret +ret: + %t173 = load ptr, ptr %retval + ret ptr %t173 +} + +define ptr @fn_emit_sizeof(ptr %arg_llt) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t5 = alloca ptr + store ptr %arg_llt, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = call ptr @fn_sconcat(ptr %t1, ptr @.str640) + %t3 = call ptr @fn_sconcat(ptr @.str639, ptr %t2) + %t4 = call ptr @fn_emit_bind(ptr %t3) + store ptr %t4, ptr %t5 + %t6 = load ptr, ptr %t5 + %t7 = call ptr @fn_sconcat(ptr %t6, ptr @.str642) + %t8 = call ptr @fn_sconcat(ptr @.str641, ptr %t7) + %t9 = call ptr @fn_emit_bind(ptr %t8) + store ptr %t9, ptr %retval + br label %ret +ret: + %t10 = load ptr, ptr %retval + ret ptr %t10 +} + +define ptr @fn_emit_new_struct(ptr %arg_name) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t3 = alloca ptr + %t11 = alloca ptr + %t16 = alloca ptr + %t17 = alloca i32 + %t35 = alloca ptr + %t37 = alloca ptr + %t47 = alloca ptr + %t48 = alloca ptr + %t64 = alloca ptr + store ptr %arg_name, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = call ptr @fn_find_struct(ptr %t1) + store ptr %t2, ptr %t3 + %t4 = load ptr, ptr %t3 + %t5 = icmp eq ptr %t4, null + %t6 = zext i1 %t5 to i32 + %t7 = icmp ne i32 %t6, 0 + br i1 %t7, label %then0, label %ifend2 +then0: + call void @fn_perr(ptr @.str643) + br label %ifend2 +ifend2: + %t8 = load ptr, ptr %t0 + %t9 = call ptr @fn_sconcat(ptr @.str644, ptr %t8) + %t10 = call ptr @fn_emit_sizeof(ptr %t9) + store ptr %t10, ptr %t11 + %t12 = load ptr, ptr %t11 + %t13 = call ptr @fn_sconcat(ptr %t12, ptr @.str646) + %t14 = call ptr @fn_sconcat(ptr @.str645, ptr %t13) + %t15 = call ptr @fn_emit_bind(ptr %t14) + store ptr %t15, ptr %t16 + store i32 0, ptr %t17 + br label %wcond3 +wcond3: + %t18 = load i32, ptr %t17 + %t19 = load ptr, ptr %t3 + %t20 = getelementptr inbounds %Str_Node, ptr %t19, i32 0, i32 7 + %t21 = load ptr, ptr %t20 + %t22 = getelementptr inbounds %LSlice, ptr %t21, i32 0, i32 1 + %t23 = load i32, ptr %t22 + %t24 = icmp slt i32 %t18, %t23 + %t25 = zext i1 %t24 to i32 + %t26 = icmp ne i32 %t25, 0 + br i1 %t26, label %wbody4, label %wend5 +wbody4: + %t27 = load ptr, ptr %t3 + %t28 = getelementptr inbounds %Str_Node, ptr %t27, i32 0, i32 7 + %t29 = load ptr, ptr %t28 + %t30 = getelementptr inbounds %LSlice, ptr %t29, i32 0, i32 0 + %t31 = load ptr, ptr %t30 + %t32 = load i32, ptr %t17 + %t33 = getelementptr inbounds ptr, ptr %t31, i32 %t32 + %t34 = load ptr, ptr %t33 + store ptr %t34, ptr %t35 + %t36 = call ptr @fn_nreg() + store ptr %t36, ptr %t37 + call void @fn_emit(ptr @.str647) + %t38 = load ptr, ptr %t37 + call void @fn_emit(ptr %t38) + call void @fn_emit(ptr @.str648) + %t39 = load ptr, ptr %t0 + call void @fn_emit(ptr %t39) + call void @fn_emit(ptr @.str649) + %t40 = load ptr, ptr %t16 + call void @fn_emit(ptr %t40) + call void @fn_emit(ptr @.str650) + %t41 = load i32, ptr %t17 + %t42 = call ptr @fn_itoa(i32 %t41) + call void @fn_emit(ptr %t42) + call void @fn_emit(ptr @.str651) + %t43 = load ptr, ptr %t35 + %t44 = getelementptr inbounds %Str_Node, ptr %t43, i32 0, i32 3 + %t45 = load ptr, ptr %t44 + %t46 = call ptr @fn_llty(ptr %t45) + store ptr %t46, ptr %t47 + store ptr @.str652, ptr %t48 + %t49 = load ptr, ptr %t47 + %t50 = call i32 @fn_streq(ptr %t49, ptr @.str653) + %t51 = icmp ne i32 %t50, 0 + br i1 %t51, label %then6, label %ifend8 +then6: + store ptr @.str654, ptr %t48 + br label %ifend8 +ifend8: + %t52 = load ptr, ptr %t35 + %t53 = getelementptr inbounds %Str_Node, ptr %t52, i32 0, i32 4 + %t54 = load ptr, ptr %t53 + %t55 = icmp eq ptr %t54, null + %t56 = zext i1 %t55 to i32 + %t57 = icmp eq i32 %t56, 0 + %t58 = zext i1 %t57 to i32 + %t59 = icmp ne i32 %t58, 0 + br i1 %t59, label %then9, label %ifend11 +then9: + %t60 = load ptr, ptr %t35 + %t61 = getelementptr inbounds %Str_Node, ptr %t60, i32 0, i32 4 + %t62 = load ptr, ptr %t61 + %t63 = call ptr @fn_emit_expr(ptr %t62) + store ptr %t63, ptr %t64 + %t65 = load ptr, ptr %t64 + %t66 = getelementptr inbounds %Str_Val, ptr %t65, i32 0, i32 0 + %t67 = load ptr, ptr %t66 + store ptr %t67, ptr %t48 + br label %ifend11 +ifend11: + call void @fn_emit(ptr @.str655) + %t68 = load ptr, ptr %t47 + call void @fn_emit(ptr %t68) + call void @fn_emit(ptr @.str656) + %t69 = load ptr, ptr %t48 + call void @fn_emit(ptr %t69) + call void @fn_emit(ptr @.str657) + %t70 = load ptr, ptr %t37 + call void @fn_emit(ptr %t70) + call void @fn_emit(ptr @.str658) + %t71 = load i32, ptr %t17 + %t72 = add i32 %t71, 1 + store i32 %t72, ptr %t17 + br label %wcond3 +wend5: + %t73 = load ptr, ptr %t16 + %t74 = load ptr, ptr %t0 + %t75 = call ptr @fn_val(ptr %t73, ptr %t74) + store ptr %t75, ptr %retval + br label %ret +ret: + %t76 = load ptr, ptr %retval + ret ptr %t76 +} + +define ptr @fn_emit_new_slice(ptr %arg_ty) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t2 = alloca ptr + %t7 = alloca ptr + %t9 = alloca ptr + %t14 = alloca ptr + %t19 = alloca ptr + store ptr %arg_ty, ptr %t0 + %t1 = call ptr @fn_emit_sizeof(ptr @.str659) + store ptr %t1, ptr %t2 + %t3 = load ptr, ptr %t2 + %t4 = call ptr @fn_sconcat(ptr %t3, ptr @.str661) + %t5 = call ptr @fn_sconcat(ptr @.str660, ptr %t4) + %t6 = call ptr @fn_emit_bind(ptr %t5) + store ptr %t6, ptr %t7 + %t8 = call ptr @fn_nreg() + store ptr %t8, ptr %t9 + call void @fn_emit(ptr @.str662) + %t10 = load ptr, ptr %t9 + call void @fn_emit(ptr %t10) + call void @fn_emit(ptr @.str663) + %t11 = load ptr, ptr %t7 + call void @fn_emit(ptr %t11) + call void @fn_emit(ptr @.str664) + call void @fn_emit(ptr @.str665) + %t12 = load ptr, ptr %t9 + call void @fn_emit(ptr %t12) + call void @fn_emit(ptr @.str666) + %t13 = call ptr @fn_nreg() + store ptr %t13, ptr %t14 + call void @fn_emit(ptr @.str667) + %t15 = load ptr, ptr %t14 + call void @fn_emit(ptr %t15) + call void @fn_emit(ptr @.str668) + %t16 = load ptr, ptr %t7 + call void @fn_emit(ptr %t16) + call void @fn_emit(ptr @.str669) + call void @fn_emit(ptr @.str670) + %t17 = load ptr, ptr %t14 + call void @fn_emit(ptr %t17) + call void @fn_emit(ptr @.str671) + %t18 = call ptr @fn_nreg() + store ptr %t18, ptr %t19 + call void @fn_emit(ptr @.str672) + %t20 = load ptr, ptr %t19 + call void @fn_emit(ptr %t20) + call void @fn_emit(ptr @.str673) + %t21 = load ptr, ptr %t7 + call void @fn_emit(ptr %t21) + call void @fn_emit(ptr @.str674) + call void @fn_emit(ptr @.str675) + %t22 = load ptr, ptr %t19 + call void @fn_emit(ptr %t22) + call void @fn_emit(ptr @.str676) + %t23 = load ptr, ptr %t7 + %t24 = load ptr, ptr %t0 + %t25 = call ptr @fn_val(ptr %t23, ptr %t24) + store ptr %t25, ptr %retval + br label %ret +ret: + %t26 = load ptr, ptr %retval + ret ptr %t26 +} + +define ptr @fn_slice_field(ptr %arg_h, i32 %arg_i) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca i32 + %t3 = alloca ptr + store ptr %arg_h, ptr %t0 + store i32 %arg_i, ptr %t1 + %t2 = call ptr @fn_nreg() + store ptr %t2, ptr %t3 + call void @fn_emit(ptr @.str677) + %t4 = load ptr, ptr %t3 + call void @fn_emit(ptr %t4) + call void @fn_emit(ptr @.str678) + %t5 = load ptr, ptr %t0 + call void @fn_emit(ptr %t5) + call void @fn_emit(ptr @.str679) + %t6 = load i32, ptr %t1 + %t7 = call ptr @fn_itoa(i32 %t6) + call void @fn_emit(ptr %t7) + call void @fn_emit(ptr @.str680) + %t8 = load ptr, ptr %t3 + store ptr %t8, ptr %retval + br label %ret +ret: + %t9 = load ptr, ptr %retval + ret ptr %t9 +} + +define ptr @fn_emit_len(ptr %arg_e) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t9 = alloca ptr + %t14 = alloca ptr + store ptr %arg_e, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = getelementptr inbounds %Str_Node, ptr %t1, i32 0, i32 7 + %t3 = load ptr, ptr %t2 + %t4 = getelementptr inbounds %LSlice, ptr %t3, i32 0, i32 0 + %t5 = load ptr, ptr %t4 + %t6 = getelementptr inbounds ptr, ptr %t5, i32 0 + %t7 = load ptr, ptr %t6 + %t8 = call ptr @fn_emit_expr(ptr %t7) + store ptr %t8, ptr %t9 + %t10 = load ptr, ptr %t9 + %t11 = getelementptr inbounds %Str_Val, ptr %t10, i32 0, i32 0 + %t12 = load ptr, ptr %t11 + %t13 = call ptr @fn_slice_field(ptr %t12, i32 1) + store ptr %t13, ptr %t14 + %t15 = load ptr, ptr %t14 + %t16 = call ptr @fn_sconcat(ptr @.str681, ptr %t15) + %t17 = call ptr @fn_emit_bind(ptr %t16) + %t18 = call ptr @fn_val(ptr %t17, ptr @.str682) + store ptr %t18, ptr %retval + br label %ret +ret: + %t19 = load ptr, ptr %retval + ret ptr %t19 +} + +define ptr @fn_emit_push(ptr %arg_e) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t9 = alloca ptr + %t14 = alloca ptr + %t17 = alloca ptr + %t21 = alloca ptr + %t24 = alloca ptr + %t27 = alloca ptr + %t30 = alloca ptr + %t34 = alloca ptr + %t38 = alloca ptr + %t45 = alloca ptr + %t47 = alloca ptr + %t49 = alloca ptr + %t58 = alloca ptr + %t63 = alloca ptr + %t70 = alloca ptr + %t73 = alloca ptr + %t78 = alloca ptr + %t85 = alloca ptr + %t89 = alloca ptr + %t97 = alloca ptr + %t112 = alloca ptr + %t116 = alloca ptr + %t118 = alloca ptr + %t132 = alloca ptr + store ptr %arg_e, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = getelementptr inbounds %Str_Node, ptr %t1, i32 0, i32 7 + %t3 = load ptr, ptr %t2 + %t4 = getelementptr inbounds %LSlice, ptr %t3, i32 0, i32 0 + %t5 = load ptr, ptr %t4 + %t6 = getelementptr inbounds ptr, ptr %t5, i32 0 + %t7 = load ptr, ptr %t6 + %t8 = call ptr @fn_emit_expr(ptr %t7) + store ptr %t8, ptr %t9 + %t10 = load ptr, ptr %t9 + %t11 = getelementptr inbounds %Str_Val, ptr %t10, i32 0, i32 1 + %t12 = load ptr, ptr %t11 + %t13 = call ptr @fn_slice_elem(ptr %t12) + store ptr %t13, ptr %t14 + %t15 = load ptr, ptr %t14 + %t16 = call ptr @fn_llty(ptr %t15) + store ptr %t16, ptr %t17 + %t18 = load ptr, ptr %t9 + %t19 = getelementptr inbounds %Str_Val, ptr %t18, i32 0, i32 0 + %t20 = load ptr, ptr %t19 + store ptr %t20, ptr %t21 + %t22 = load ptr, ptr %t21 + %t23 = call ptr @fn_slice_field(ptr %t22, i32 1) + store ptr %t23, ptr %t24 + %t25 = load ptr, ptr %t21 + %t26 = call ptr @fn_slice_field(ptr %t25, i32 2) + store ptr %t26, ptr %t27 + %t28 = load ptr, ptr %t21 + %t29 = call ptr @fn_slice_field(ptr %t28, i32 0) + store ptr %t29, ptr %t30 + %t31 = load ptr, ptr %t24 + %t32 = call ptr @fn_sconcat(ptr @.str683, ptr %t31) + %t33 = call ptr @fn_emit_bind(ptr %t32) + store ptr %t33, ptr %t34 + %t35 = load ptr, ptr %t27 + %t36 = call ptr @fn_sconcat(ptr @.str684, ptr %t35) + %t37 = call ptr @fn_emit_bind(ptr %t36) + store ptr %t37, ptr %t38 + %t39 = load ptr, ptr %t34 + %t40 = load ptr, ptr %t38 + %t41 = call ptr @fn_sconcat(ptr @.str686, ptr %t40) + %t42 = call ptr @fn_sconcat(ptr %t39, ptr %t41) + %t43 = call ptr @fn_sconcat(ptr @.str685, ptr %t42) + %t44 = call ptr @fn_emit_bind(ptr %t43) + store ptr %t44, ptr %t45 + %t46 = call ptr @fn_lbl(ptr @.str687) + store ptr %t46, ptr %t47 + %t48 = call ptr @fn_lbl(ptr @.str688) + store ptr %t48, ptr %t49 + call void @fn_emit(ptr @.str689) + %t50 = load ptr, ptr %t45 + call void @fn_emit(ptr %t50) + call void @fn_emit(ptr @.str690) + %t51 = load ptr, ptr %t47 + call void @fn_emit(ptr %t51) + call void @fn_emit(ptr @.str691) + %t52 = load ptr, ptr %t49 + call void @fn_emit(ptr %t52) + call void @fn_emit(ptr @.str692) + %t53 = load ptr, ptr %t47 + call void @fn_emit(ptr %t53) + call void @fn_emit(ptr @.str693) + %t54 = load ptr, ptr %t38 + %t55 = call ptr @fn_sconcat(ptr %t54, ptr @.str695) + %t56 = call ptr @fn_sconcat(ptr @.str694, ptr %t55) + %t57 = call ptr @fn_emit_bind(ptr %t56) + store ptr %t57, ptr %t58 + %t59 = load ptr, ptr %t38 + %t60 = call ptr @fn_sconcat(ptr %t59, ptr @.str697) + %t61 = call ptr @fn_sconcat(ptr @.str696, ptr %t60) + %t62 = call ptr @fn_emit_bind(ptr %t61) + store ptr %t62, ptr %t63 + %t64 = load ptr, ptr %t63 + %t65 = load ptr, ptr %t58 + %t66 = call ptr @fn_sconcat(ptr @.str699, ptr %t65) + %t67 = call ptr @fn_sconcat(ptr %t64, ptr %t66) + %t68 = call ptr @fn_sconcat(ptr @.str698, ptr %t67) + %t69 = call ptr @fn_emit_bind(ptr %t68) + store ptr %t69, ptr %t70 + %t71 = load ptr, ptr %t17 + %t72 = call ptr @fn_emit_sizeof(ptr %t71) + store ptr %t72, ptr %t73 + %t74 = load ptr, ptr %t70 + %t75 = call ptr @fn_sconcat(ptr %t74, ptr @.str701) + %t76 = call ptr @fn_sconcat(ptr @.str700, ptr %t75) + %t77 = call ptr @fn_emit_bind(ptr %t76) + store ptr %t77, ptr %t78 + %t79 = load ptr, ptr %t78 + %t80 = load ptr, ptr %t73 + %t81 = call ptr @fn_sconcat(ptr @.str703, ptr %t80) + %t82 = call ptr @fn_sconcat(ptr %t79, ptr %t81) + %t83 = call ptr @fn_sconcat(ptr @.str702, ptr %t82) + %t84 = call ptr @fn_emit_bind(ptr %t83) + store ptr %t84, ptr %t85 + %t86 = load ptr, ptr %t30 + %t87 = call ptr @fn_sconcat(ptr @.str704, ptr %t86) + %t88 = call ptr @fn_emit_bind(ptr %t87) + store ptr %t88, ptr %t89 + %t90 = load ptr, ptr %t89 + %t91 = load ptr, ptr %t85 + %t92 = call ptr @fn_sconcat(ptr %t91, ptr @.str707) + %t93 = call ptr @fn_sconcat(ptr @.str706, ptr %t92) + %t94 = call ptr @fn_sconcat(ptr %t90, ptr %t93) + %t95 = call ptr @fn_sconcat(ptr @.str705, ptr %t94) + %t96 = call ptr @fn_emit_bind(ptr %t95) + store ptr %t96, ptr %t97 + call void @fn_emit(ptr @.str708) + %t98 = load ptr, ptr %t97 + call void @fn_emit(ptr %t98) + call void @fn_emit(ptr @.str709) + %t99 = load ptr, ptr %t30 + call void @fn_emit(ptr %t99) + call void @fn_emit(ptr @.str710) + call void @fn_emit(ptr @.str711) + %t100 = load ptr, ptr %t70 + call void @fn_emit(ptr %t100) + call void @fn_emit(ptr @.str712) + %t101 = load ptr, ptr %t27 + call void @fn_emit(ptr %t101) + call void @fn_emit(ptr @.str713) + call void @fn_emit(ptr @.str714) + %t102 = load ptr, ptr %t49 + call void @fn_emit(ptr %t102) + call void @fn_emit(ptr @.str715) + %t103 = load ptr, ptr %t49 + call void @fn_emit(ptr %t103) + call void @fn_emit(ptr @.str716) + %t104 = load ptr, ptr %t0 + %t105 = getelementptr inbounds %Str_Node, ptr %t104, i32 0, i32 7 + %t106 = load ptr, ptr %t105 + %t107 = getelementptr inbounds %LSlice, ptr %t106, i32 0, i32 0 + %t108 = load ptr, ptr %t107 + %t109 = getelementptr inbounds ptr, ptr %t108, i32 1 + %t110 = load ptr, ptr %t109 + %t111 = call ptr @fn_emit_expr(ptr %t110) + store ptr %t111, ptr %t112 + %t113 = load ptr, ptr %t30 + %t114 = call ptr @fn_sconcat(ptr @.str717, ptr %t113) + %t115 = call ptr @fn_emit_bind(ptr %t114) + store ptr %t115, ptr %t116 + %t117 = call ptr @fn_nreg() + store ptr %t117, ptr %t118 + call void @fn_emit(ptr @.str718) + %t119 = load ptr, ptr %t118 + call void @fn_emit(ptr %t119) + call void @fn_emit(ptr @.str719) + %t120 = load ptr, ptr %t17 + call void @fn_emit(ptr %t120) + call void @fn_emit(ptr @.str720) + %t121 = load ptr, ptr %t116 + call void @fn_emit(ptr %t121) + call void @fn_emit(ptr @.str721) + %t122 = load ptr, ptr %t34 + call void @fn_emit(ptr %t122) + call void @fn_emit(ptr @.str722) + call void @fn_emit(ptr @.str723) + %t123 = load ptr, ptr %t17 + call void @fn_emit(ptr %t123) + call void @fn_emit(ptr @.str724) + %t124 = load ptr, ptr %t112 + %t125 = getelementptr inbounds %Str_Val, ptr %t124, i32 0, i32 0 + %t126 = load ptr, ptr %t125 + call void @fn_emit(ptr %t126) + call void @fn_emit(ptr @.str725) + %t127 = load ptr, ptr %t118 + call void @fn_emit(ptr %t127) + call void @fn_emit(ptr @.str726) + %t128 = load ptr, ptr %t34 + %t129 = call ptr @fn_sconcat(ptr %t128, ptr @.str728) + %t130 = call ptr @fn_sconcat(ptr @.str727, ptr %t129) + %t131 = call ptr @fn_emit_bind(ptr %t130) + store ptr %t131, ptr %t132 + call void @fn_emit(ptr @.str729) + %t133 = load ptr, ptr %t132 + call void @fn_emit(ptr %t133) + call void @fn_emit(ptr @.str730) + %t134 = load ptr, ptr %t24 + call void @fn_emit(ptr %t134) + call void @fn_emit(ptr @.str731) + %t135 = call ptr @fn_val(ptr @.str732, ptr @.str733) + store ptr %t135, ptr %retval + br label %ret +ret: + %t136 = load ptr, ptr %retval + ret ptr %t136 +} + +define ptr @fn_emit_load_at(ptr %arg_addr, ptr %arg_ty) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca ptr + %t9 = alloca ptr + store ptr %arg_addr, ptr %t0 + store ptr %arg_ty, ptr %t1 + %t2 = load ptr, ptr %t1 + %t3 = call ptr @fn_llty(ptr %t2) + %t4 = load ptr, ptr %t0 + %t5 = call ptr @fn_sconcat(ptr @.str735, ptr %t4) + %t6 = call ptr @fn_sconcat(ptr %t3, ptr %t5) + %t7 = call ptr @fn_sconcat(ptr @.str734, ptr %t6) + %t8 = call ptr @fn_emit_bind(ptr %t7) + store ptr %t8, ptr %t9 + %t10 = load ptr, ptr %t9 + %t11 = load ptr, ptr %t1 + %t12 = call ptr @fn_val(ptr %t10, ptr %t11) + store ptr %t12, ptr %retval + br label %ret +ret: + %t13 = load ptr, ptr %retval + ret ptr %t13 +} + +define ptr @fn_emit_logic(ptr %arg_e) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t2 = alloca ptr + %t7 = alloca ptr + %t14 = alloca ptr + %t19 = alloca ptr + %t23 = alloca ptr + %t25 = alloca ptr + %t42 = alloca ptr + %t49 = alloca ptr + %t54 = alloca ptr + store ptr %arg_e, ptr %t0 + %t1 = call ptr @fn_emit_alloca(ptr @.str736) + store ptr %t1, ptr %t2 + %t3 = load ptr, ptr %t0 + %t4 = getelementptr inbounds %Str_Node, ptr %t3, i32 0, i32 4 + %t5 = load ptr, ptr %t4 + %t6 = call ptr @fn_emit_expr(ptr %t5) + store ptr %t6, ptr %t7 + %t8 = load ptr, ptr %t7 + %t9 = getelementptr inbounds %Str_Val, ptr %t8, i32 0, i32 0 + %t10 = load ptr, ptr %t9 + %t11 = call ptr @fn_sconcat(ptr %t10, ptr @.str738) + %t12 = call ptr @fn_sconcat(ptr @.str737, ptr %t11) + %t13 = call ptr @fn_emit_bind(ptr %t12) + store ptr %t13, ptr %t14 + %t15 = load ptr, ptr %t14 + %t16 = call ptr @fn_sconcat(ptr %t15, ptr @.str740) + %t17 = call ptr @fn_sconcat(ptr @.str739, ptr %t16) + %t18 = call ptr @fn_emit_bind(ptr %t17) + store ptr %t18, ptr %t19 + call void @fn_emit(ptr @.str741) + %t20 = load ptr, ptr %t19 + call void @fn_emit(ptr %t20) + call void @fn_emit(ptr @.str742) + %t21 = load ptr, ptr %t2 + call void @fn_emit(ptr %t21) + call void @fn_emit(ptr @.str743) + %t22 = call ptr @fn_lbl(ptr @.str744) + store ptr %t22, ptr %t23 + %t24 = call ptr @fn_lbl(ptr @.str745) + store ptr %t24, ptr %t25 + %t26 = load ptr, ptr %t0 + %t27 = getelementptr inbounds %Str_Node, ptr %t26, i32 0, i32 1 + %t28 = load ptr, ptr %t27 + %t29 = call i32 @fn_streq(ptr %t28, ptr @.str746) + %t30 = icmp ne i32 %t29, 0 + br i1 %t30, label %then0, label %else1 +then0: + call void @fn_emit(ptr @.str747) + %t31 = load ptr, ptr %t14 + call void @fn_emit(ptr %t31) + call void @fn_emit(ptr @.str748) + %t32 = load ptr, ptr %t23 + call void @fn_emit(ptr %t32) + call void @fn_emit(ptr @.str749) + %t33 = load ptr, ptr %t25 + call void @fn_emit(ptr %t33) + call void @fn_emit(ptr @.str750) + br label %ifend2 +else1: + call void @fn_emit(ptr @.str751) + %t34 = load ptr, ptr %t14 + call void @fn_emit(ptr %t34) + call void @fn_emit(ptr @.str752) + %t35 = load ptr, ptr %t25 + call void @fn_emit(ptr %t35) + call void @fn_emit(ptr @.str753) + %t36 = load ptr, ptr %t23 + call void @fn_emit(ptr %t36) + call void @fn_emit(ptr @.str754) + br label %ifend2 +ifend2: + %t37 = load ptr, ptr %t23 + call void @fn_emit(ptr %t37) + call void @fn_emit(ptr @.str755) + %t38 = load ptr, ptr %t0 + %t39 = getelementptr inbounds %Str_Node, ptr %t38, i32 0, i32 5 + %t40 = load ptr, ptr %t39 + %t41 = call ptr @fn_emit_expr(ptr %t40) + store ptr %t41, ptr %t42 + %t43 = load ptr, ptr %t42 + %t44 = getelementptr inbounds %Str_Val, ptr %t43, i32 0, i32 0 + %t45 = load ptr, ptr %t44 + %t46 = call ptr @fn_sconcat(ptr %t45, ptr @.str757) + %t47 = call ptr @fn_sconcat(ptr @.str756, ptr %t46) + %t48 = call ptr @fn_emit_bind(ptr %t47) + store ptr %t48, ptr %t49 + %t50 = load ptr, ptr %t49 + %t51 = call ptr @fn_sconcat(ptr %t50, ptr @.str759) + %t52 = call ptr @fn_sconcat(ptr @.str758, ptr %t51) + %t53 = call ptr @fn_emit_bind(ptr %t52) + store ptr %t53, ptr %t54 + call void @fn_emit(ptr @.str760) + %t55 = load ptr, ptr %t54 + call void @fn_emit(ptr %t55) + call void @fn_emit(ptr @.str761) + %t56 = load ptr, ptr %t2 + call void @fn_emit(ptr %t56) + call void @fn_emit(ptr @.str762) + call void @fn_emit(ptr @.str763) + %t57 = load ptr, ptr %t25 + call void @fn_emit(ptr %t57) + call void @fn_emit(ptr @.str764) + %t58 = load ptr, ptr %t25 + call void @fn_emit(ptr %t58) + call void @fn_emit(ptr @.str765) + %t59 = load ptr, ptr %t2 + %t60 = call ptr @fn_sconcat(ptr @.str766, ptr %t59) + %t61 = call ptr @fn_emit_bind(ptr %t60) + %t62 = call ptr @fn_val(ptr %t61, ptr @.str767) + store ptr %t62, ptr %retval + br label %ret +ret: + %t63 = load ptr, ptr %retval + ret ptr %t63 +} + +define ptr @fn_cmp_code(ptr %arg_op) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + store ptr %arg_op, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = call i32 @fn_streq(ptr %t1, ptr @.str768) + %t3 = icmp ne i32 %t2, 0 + br i1 %t3, label %then0, label %ifend2 +then0: + store ptr @.str769, ptr %retval + br label %ret +ifend2: + %t4 = load ptr, ptr %t0 + %t5 = call i32 @fn_streq(ptr %t4, ptr @.str770) + %t6 = icmp ne i32 %t5, 0 + br i1 %t6, label %then3, label %ifend5 +then3: + store ptr @.str771, ptr %retval + br label %ret +ifend5: + %t7 = load ptr, ptr %t0 + %t8 = call i32 @fn_streq(ptr %t7, ptr @.str772) + %t9 = icmp ne i32 %t8, 0 + br i1 %t9, label %then6, label %ifend8 +then6: + store ptr @.str773, ptr %retval + br label %ret +ifend8: + %t10 = load ptr, ptr %t0 + %t11 = call i32 @fn_streq(ptr %t10, ptr @.str774) + %t12 = icmp ne i32 %t11, 0 + br i1 %t12, label %then9, label %ifend11 +then9: + store ptr @.str775, ptr %retval + br label %ret +ifend11: + %t13 = load ptr, ptr %t0 + %t14 = call i32 @fn_streq(ptr %t13, ptr @.str776) + %t15 = icmp ne i32 %t14, 0 + br i1 %t15, label %then12, label %ifend14 +then12: + store ptr @.str777, ptr %retval + br label %ret +ifend14: + store ptr @.str778, ptr %retval + br label %ret +ret: + %t16 = load ptr, ptr %retval + ret ptr %t16 +} + +define i32 @fn_is_cmp(ptr %arg_op) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t1 = alloca i32 + %t2 = alloca i32 + %t3 = alloca i32 + %t4 = alloca i32 + %t5 = alloca i32 + store ptr %arg_op, ptr %t0 + %t6 = load ptr, ptr %t0 + %t7 = call i32 @fn_streq(ptr %t6, ptr @.str779) + %t8 = icmp ne i32 %t7, 0 + %t9 = zext i1 %t8 to i32 + store i32 %t9, ptr %t5 + br i1 %t8, label %scend1, label %sc0 +sc0: + %t10 = load ptr, ptr %t0 + %t11 = call i32 @fn_streq(ptr %t10, ptr @.str780) + %t12 = icmp ne i32 %t11, 0 + %t13 = zext i1 %t12 to i32 + store i32 %t13, ptr %t5 + br label %scend1 +scend1: + %t14 = load i32, ptr %t5 + %t15 = icmp ne i32 %t14, 0 + %t16 = zext i1 %t15 to i32 + store i32 %t16, ptr %t4 + br i1 %t15, label %scend3, label %sc2 +sc2: + %t17 = load ptr, ptr %t0 + %t18 = call i32 @fn_streq(ptr %t17, ptr @.str781) + %t19 = icmp ne i32 %t18, 0 + %t20 = zext i1 %t19 to i32 + store i32 %t20, ptr %t4 + br label %scend3 +scend3: + %t21 = load i32, ptr %t4 + %t22 = icmp ne i32 %t21, 0 + %t23 = zext i1 %t22 to i32 + store i32 %t23, ptr %t3 + br i1 %t22, label %scend5, label %sc4 +sc4: + %t24 = load ptr, ptr %t0 + %t25 = call i32 @fn_streq(ptr %t24, ptr @.str782) + %t26 = icmp ne i32 %t25, 0 + %t27 = zext i1 %t26 to i32 + store i32 %t27, ptr %t3 + br label %scend5 +scend5: + %t28 = load i32, ptr %t3 + %t29 = icmp ne i32 %t28, 0 + %t30 = zext i1 %t29 to i32 + store i32 %t30, ptr %t2 + br i1 %t29, label %scend7, label %sc6 +sc6: + %t31 = load ptr, ptr %t0 + %t32 = call i32 @fn_streq(ptr %t31, ptr @.str783) + %t33 = icmp ne i32 %t32, 0 + %t34 = zext i1 %t33 to i32 + store i32 %t34, ptr %t2 + br label %scend7 +scend7: + %t35 = load i32, ptr %t2 + %t36 = icmp ne i32 %t35, 0 + %t37 = zext i1 %t36 to i32 + store i32 %t37, ptr %t1 + br i1 %t36, label %scend9, label %sc8 +sc8: + %t38 = load ptr, ptr %t0 + %t39 = call i32 @fn_streq(ptr %t38, ptr @.str784) + %t40 = icmp ne i32 %t39, 0 + %t41 = zext i1 %t40 to i32 + store i32 %t41, ptr %t1 + br label %scend9 +scend9: + %t42 = load i32, ptr %t1 + store i32 %t42, ptr %retval + br label %ret +ret: + %t43 = load i32, ptr %retval + ret i32 %t43 +} + +define ptr @fn_arith_code(ptr %arg_op) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + store ptr %arg_op, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = call i32 @fn_streq(ptr %t1, ptr @.str785) + %t3 = icmp ne i32 %t2, 0 + br i1 %t3, label %then0, label %ifend2 +then0: + store ptr @.str786, ptr %retval + br label %ret +ifend2: + %t4 = load ptr, ptr %t0 + %t5 = call i32 @fn_streq(ptr %t4, ptr @.str787) + %t6 = icmp ne i32 %t5, 0 + br i1 %t6, label %then3, label %ifend5 +then3: + store ptr @.str788, ptr %retval + br label %ret +ifend5: + %t7 = load ptr, ptr %t0 + %t8 = call i32 @fn_streq(ptr %t7, ptr @.str789) + %t9 = icmp ne i32 %t8, 0 + br i1 %t9, label %then6, label %ifend8 +then6: + store ptr @.str790, ptr %retval + br label %ret +ifend8: + %t10 = load ptr, ptr %t0 + %t11 = call i32 @fn_streq(ptr %t10, ptr @.str791) + %t12 = icmp ne i32 %t11, 0 + br i1 %t12, label %then9, label %ifend11 +then9: + store ptr @.str792, ptr %retval + br label %ret +ifend11: + store ptr @.str793, ptr %retval + br label %ret +ret: + %t13 = load ptr, ptr %retval + ret ptr %t13 +} + +define ptr @fn_to_fixed(ptr %arg_v) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + store ptr %arg_v, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = getelementptr inbounds %Str_Val, ptr %t1, i32 0, i32 1 + %t3 = load ptr, ptr %t2 + %t4 = call i32 @fn_streq(ptr %t3, ptr @.str794) + %t5 = icmp ne i32 %t4, 0 + br i1 %t5, label %then0, label %ifend2 +then0: + %t6 = load ptr, ptr %t0 + %t7 = getelementptr inbounds %Str_Val, ptr %t6, i32 0, i32 0 + %t8 = load ptr, ptr %t7 + store ptr %t8, ptr %retval + br label %ret +ifend2: + %t9 = load ptr, ptr %t0 + %t10 = getelementptr inbounds %Str_Val, ptr %t9, i32 0, i32 0 + %t11 = load ptr, ptr %t10 + %t12 = call ptr @fn_sconcat(ptr %t11, ptr @.str796) + %t13 = call ptr @fn_sconcat(ptr @.str795, ptr %t12) + %t14 = call ptr @fn_emit_bind(ptr %t13) + store ptr %t14, ptr %retval + br label %ret +ret: + %t15 = load ptr, ptr %retval + ret ptr %t15 +} + +define ptr @fn_emit_bin(ptr %arg_e) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca i32 + %t22 = alloca ptr + %t27 = alloca ptr + %t28 = alloca i32 + %t42 = alloca i32 + %t51 = alloca ptr + %t55 = alloca ptr + %t74 = alloca ptr + %t84 = alloca ptr + %t87 = alloca ptr + %t97 = alloca ptr + %t102 = alloca ptr + %t109 = alloca ptr + %t114 = alloca ptr + %t129 = alloca ptr + %t134 = alloca ptr + %t139 = alloca ptr + %t146 = alloca ptr + %t163 = alloca ptr + %t181 = alloca ptr + store ptr %arg_e, ptr %t0 + %t2 = load ptr, ptr %t0 + %t3 = getelementptr inbounds %Str_Node, ptr %t2, i32 0, i32 1 + %t4 = load ptr, ptr %t3 + %t5 = call i32 @fn_streq(ptr %t4, ptr @.str797) + %t6 = icmp ne i32 %t5, 0 + %t7 = zext i1 %t6 to i32 + store i32 %t7, ptr %t1 + br i1 %t6, label %scend1, label %sc0 +sc0: + %t8 = load ptr, ptr %t0 + %t9 = getelementptr inbounds %Str_Node, ptr %t8, i32 0, i32 1 + %t10 = load ptr, ptr %t9 + %t11 = call i32 @fn_streq(ptr %t10, ptr @.str798) + %t12 = icmp ne i32 %t11, 0 + %t13 = zext i1 %t12 to i32 + store i32 %t13, ptr %t1 + br label %scend1 +scend1: + %t14 = load i32, ptr %t1 + %t15 = icmp ne i32 %t14, 0 + br i1 %t15, label %then2, label %ifend4 +then2: + %t16 = load ptr, ptr %t0 + %t17 = call ptr @fn_emit_logic(ptr %t16) + store ptr %t17, ptr %retval + br label %ret +ifend4: + %t18 = load ptr, ptr %t0 + %t19 = getelementptr inbounds %Str_Node, ptr %t18, i32 0, i32 4 + %t20 = load ptr, ptr %t19 + %t21 = call ptr @fn_emit_expr(ptr %t20) + store ptr %t21, ptr %t22 + %t23 = load ptr, ptr %t0 + %t24 = getelementptr inbounds %Str_Node, ptr %t23, i32 0, i32 5 + %t25 = load ptr, ptr %t24 + %t26 = call ptr @fn_emit_expr(ptr %t25) + store ptr %t26, ptr %t27 + %t29 = load ptr, ptr %t22 + %t30 = getelementptr inbounds %Str_Val, ptr %t29, i32 0, i32 1 + %t31 = load ptr, ptr %t30 + %t32 = call i32 @fn_streq(ptr %t31, ptr @.str799) + %t33 = icmp ne i32 %t32, 0 + %t34 = zext i1 %t33 to i32 + store i32 %t34, ptr %t28 + br i1 %t33, label %scend6, label %sc5 +sc5: + %t35 = load ptr, ptr %t27 + %t36 = getelementptr inbounds %Str_Val, ptr %t35, i32 0, i32 1 + %t37 = load ptr, ptr %t36 + %t38 = call i32 @fn_streq(ptr %t37, ptr @.str800) + %t39 = icmp ne i32 %t38, 0 + %t40 = zext i1 %t39 to i32 + store i32 %t40, ptr %t28 + br label %scend6 +scend6: + %t41 = load i32, ptr %t28 + store i32 %t41, ptr %t42 + %t43 = load ptr, ptr %t0 + %t44 = getelementptr inbounds %Str_Node, ptr %t43, i32 0, i32 1 + %t45 = load ptr, ptr %t44 + %t46 = call i32 @fn_is_cmp(ptr %t45) + %t47 = icmp ne i32 %t46, 0 + br i1 %t47, label %then7, label %ifend9 +then7: + %t48 = load ptr, ptr %t22 + %t49 = getelementptr inbounds %Str_Val, ptr %t48, i32 0, i32 0 + %t50 = load ptr, ptr %t49 + store ptr %t50, ptr %t51 + %t52 = load ptr, ptr %t27 + %t53 = getelementptr inbounds %Str_Val, ptr %t52, i32 0, i32 0 + %t54 = load ptr, ptr %t53 + store ptr %t54, ptr %t55 + %t56 = load i32, ptr %t42 + %t57 = icmp ne i32 %t56, 0 + br i1 %t57, label %then10, label %ifend12 +then10: + %t58 = load ptr, ptr %t22 + %t59 = call ptr @fn_to_fixed(ptr %t58) + store ptr %t59, ptr %t51 + %t60 = load ptr, ptr %t27 + %t61 = call ptr @fn_to_fixed(ptr %t60) + store ptr %t61, ptr %t55 + br label %ifend12 +ifend12: + %t62 = load ptr, ptr %t0 + %t63 = getelementptr inbounds %Str_Node, ptr %t62, i32 0, i32 1 + %t64 = load ptr, ptr %t63 + %t65 = call ptr @fn_cmp_code(ptr %t64) + %t66 = load ptr, ptr %t51 + %t67 = load ptr, ptr %t55 + %t68 = call ptr @fn_sconcat(ptr @.str803, ptr %t67) + %t69 = call ptr @fn_sconcat(ptr %t66, ptr %t68) + %t70 = call ptr @fn_sconcat(ptr @.str802, ptr %t69) + %t71 = call ptr @fn_sconcat(ptr %t65, ptr %t70) + %t72 = call ptr @fn_sconcat(ptr @.str801, ptr %t71) + %t73 = call ptr @fn_emit_bind(ptr %t72) + store ptr %t73, ptr %t74 + %t75 = load ptr, ptr %t74 + %t76 = call ptr @fn_sconcat(ptr %t75, ptr @.str805) + %t77 = call ptr @fn_sconcat(ptr @.str804, ptr %t76) + %t78 = call ptr @fn_emit_bind(ptr %t77) + %t79 = call ptr @fn_val(ptr %t78, ptr @.str806) + store ptr %t79, ptr %retval + br label %ret +ifend9: + %t80 = load i32, ptr %t42 + %t81 = icmp ne i32 %t80, 0 + br i1 %t81, label %then13, label %ifend15 +then13: + %t82 = load ptr, ptr %t22 + %t83 = call ptr @fn_to_fixed(ptr %t82) + store ptr %t83, ptr %t84 + %t85 = load ptr, ptr %t27 + %t86 = call ptr @fn_to_fixed(ptr %t85) + store ptr %t86, ptr %t87 + %t88 = load ptr, ptr %t0 + %t89 = getelementptr inbounds %Str_Node, ptr %t88, i32 0, i32 1 + %t90 = load ptr, ptr %t89 + %t91 = call i32 @fn_streq(ptr %t90, ptr @.str807) + %t92 = icmp ne i32 %t91, 0 + br i1 %t92, label %then16, label %ifend18 +then16: + %t93 = load ptr, ptr %t84 + %t94 = call ptr @fn_sconcat(ptr %t93, ptr @.str809) + %t95 = call ptr @fn_sconcat(ptr @.str808, ptr %t94) + %t96 = call ptr @fn_emit_bind(ptr %t95) + store ptr %t96, ptr %t97 + %t98 = load ptr, ptr %t87 + %t99 = call ptr @fn_sconcat(ptr %t98, ptr @.str811) + %t100 = call ptr @fn_sconcat(ptr @.str810, ptr %t99) + %t101 = call ptr @fn_emit_bind(ptr %t100) + store ptr %t101, ptr %t102 + %t103 = load ptr, ptr %t97 + %t104 = load ptr, ptr %t102 + %t105 = call ptr @fn_sconcat(ptr @.str813, ptr %t104) + %t106 = call ptr @fn_sconcat(ptr %t103, ptr %t105) + %t107 = call ptr @fn_sconcat(ptr @.str812, ptr %t106) + %t108 = call ptr @fn_emit_bind(ptr %t107) + store ptr %t108, ptr %t109 + %t110 = load ptr, ptr %t109 + %t111 = call ptr @fn_sconcat(ptr %t110, ptr @.str815) + %t112 = call ptr @fn_sconcat(ptr @.str814, ptr %t111) + %t113 = call ptr @fn_emit_bind(ptr %t112) + store ptr %t113, ptr %t114 + %t115 = load ptr, ptr %t114 + %t116 = call ptr @fn_sconcat(ptr %t115, ptr @.str817) + %t117 = call ptr @fn_sconcat(ptr @.str816, ptr %t116) + %t118 = call ptr @fn_emit_bind(ptr %t117) + %t119 = call ptr @fn_val(ptr %t118, ptr @.str818) + store ptr %t119, ptr %retval + br label %ret +ifend18: + %t120 = load ptr, ptr %t0 + %t121 = getelementptr inbounds %Str_Node, ptr %t120, i32 0, i32 1 + %t122 = load ptr, ptr %t121 + %t123 = call i32 @fn_streq(ptr %t122, ptr @.str819) + %t124 = icmp ne i32 %t123, 0 + br i1 %t124, label %then19, label %ifend21 +then19: + %t125 = load ptr, ptr %t84 + %t126 = call ptr @fn_sconcat(ptr %t125, ptr @.str821) + %t127 = call ptr @fn_sconcat(ptr @.str820, ptr %t126) + %t128 = call ptr @fn_emit_bind(ptr %t127) + store ptr %t128, ptr %t129 + %t130 = load ptr, ptr %t129 + %t131 = call ptr @fn_sconcat(ptr %t130, ptr @.str823) + %t132 = call ptr @fn_sconcat(ptr @.str822, ptr %t131) + %t133 = call ptr @fn_emit_bind(ptr %t132) + store ptr %t133, ptr %t134 + %t135 = load ptr, ptr %t87 + %t136 = call ptr @fn_sconcat(ptr %t135, ptr @.str825) + %t137 = call ptr @fn_sconcat(ptr @.str824, ptr %t136) + %t138 = call ptr @fn_emit_bind(ptr %t137) + store ptr %t138, ptr %t139 + %t140 = load ptr, ptr %t134 + %t141 = load ptr, ptr %t139 + %t142 = call ptr @fn_sconcat(ptr @.str827, ptr %t141) + %t143 = call ptr @fn_sconcat(ptr %t140, ptr %t142) + %t144 = call ptr @fn_sconcat(ptr @.str826, ptr %t143) + %t145 = call ptr @fn_emit_bind(ptr %t144) + store ptr %t145, ptr %t146 + %t147 = load ptr, ptr %t146 + %t148 = call ptr @fn_sconcat(ptr %t147, ptr @.str829) + %t149 = call ptr @fn_sconcat(ptr @.str828, ptr %t148) + %t150 = call ptr @fn_emit_bind(ptr %t149) + %t151 = call ptr @fn_val(ptr %t150, ptr @.str830) + store ptr %t151, ptr %retval + br label %ret +ifend21: + %t152 = load ptr, ptr %t0 + %t153 = getelementptr inbounds %Str_Node, ptr %t152, i32 0, i32 1 + %t154 = load ptr, ptr %t153 + %t155 = call ptr @fn_arith_code(ptr %t154) + %t156 = load ptr, ptr %t84 + %t157 = load ptr, ptr %t87 + %t158 = call ptr @fn_sconcat(ptr @.str832, ptr %t157) + %t159 = call ptr @fn_sconcat(ptr %t156, ptr %t158) + %t160 = call ptr @fn_sconcat(ptr @.str831, ptr %t159) + %t161 = call ptr @fn_sconcat(ptr %t155, ptr %t160) + %t162 = call ptr @fn_emit_bind(ptr %t161) + store ptr %t162, ptr %t163 + %t164 = load ptr, ptr %t163 + %t165 = call ptr @fn_val(ptr %t164, ptr @.str833) + store ptr %t165, ptr %retval + br label %ret +ifend15: + %t166 = load ptr, ptr %t0 + %t167 = getelementptr inbounds %Str_Node, ptr %t166, i32 0, i32 1 + %t168 = load ptr, ptr %t167 + %t169 = call ptr @fn_arith_code(ptr %t168) + %t170 = load ptr, ptr %t22 + %t171 = getelementptr inbounds %Str_Val, ptr %t170, i32 0, i32 0 + %t172 = load ptr, ptr %t171 + %t173 = load ptr, ptr %t27 + %t174 = getelementptr inbounds %Str_Val, ptr %t173, i32 0, i32 0 + %t175 = load ptr, ptr %t174 + %t176 = call ptr @fn_sconcat(ptr @.str835, ptr %t175) + %t177 = call ptr @fn_sconcat(ptr %t172, ptr %t176) + %t178 = call ptr @fn_sconcat(ptr @.str834, ptr %t177) + %t179 = call ptr @fn_sconcat(ptr %t169, ptr %t178) + %t180 = call ptr @fn_emit_bind(ptr %t179) + store ptr %t180, ptr %t181 + %t182 = load ptr, ptr %t181 + %t183 = call ptr @fn_val(ptr %t182, ptr @.str836) + store ptr %t183, ptr %retval + br label %ret +ret: + %t184 = load ptr, ptr %retval + ret ptr %t184 +} + +define ptr @fn_emit_call(ptr %arg_e) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t6 = alloca ptr + %t68 = alloca ptr + %t87 = alloca ptr + %t115 = alloca ptr + %t117 = alloca ptr + %t124 = alloca ptr + %t140 = alloca ptr + %t147 = alloca ptr + %t148 = alloca i32 + %t167 = alloca ptr + %t218 = alloca ptr + %t219 = alloca ptr + store ptr %arg_e, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = getelementptr inbounds %Str_Node, ptr %t1, i32 0, i32 4 + %t3 = load ptr, ptr %t2 + %t4 = getelementptr inbounds %Str_Node, ptr %t3, i32 0, i32 1 + %t5 = load ptr, ptr %t4 + store ptr %t5, ptr %t6 + %t7 = load ptr, ptr %t6 + %t8 = call i32 @fn_streq(ptr %t7, ptr @.str837) + %t9 = icmp ne i32 %t8, 0 + br i1 %t9, label %then0, label %ifend2 +then0: + %t10 = load i32, ptr @g_nself + %t11 = icmp eq i32 %t10, 0 + %t12 = zext i1 %t11 to i32 + %t13 = icmp ne i32 %t12, 0 + br i1 %t13, label %then3, label %ifend5 +then3: + %t14 = call ptr @fn_val(ptr @.str838, ptr @.str839) + store ptr %t14, ptr %retval + br label %ret +ifend5: + %t15 = load ptr, ptr @g_self_stk + %t16 = getelementptr inbounds %LSlice, ptr %t15, i32 0, i32 0 + %t17 = load ptr, ptr %t16 + %t18 = load i32, ptr @g_nself + %t19 = sub i32 %t18, 1 + %t20 = getelementptr inbounds ptr, ptr %t17, i32 %t19 + %t21 = load ptr, ptr %t20 + %t22 = call ptr @fn_sconcat(ptr @.str840, ptr %t21) + %t23 = call ptr @fn_emit_bind(ptr %t22) + %t24 = call ptr @fn_val(ptr %t23, ptr @.str841) + store ptr %t24, ptr %retval + br label %ret +ifend2: + %t25 = load ptr, ptr %t6 + %t26 = call i32 @fn_streq(ptr %t25, ptr @.str842) + %t27 = icmp ne i32 %t26, 0 + br i1 %t27, label %then6, label %ifend8 +then6: + %t28 = call ptr @fn_emit_bind(ptr @.str843) + %t29 = call ptr @fn_val(ptr %t28, ptr @.str844) + store ptr %t29, ptr %retval + br label %ret +ifend8: + %t30 = load ptr, ptr %t6 + %t31 = call i32 @fn_streq(ptr %t30, ptr @.str845) + %t32 = icmp ne i32 %t31, 0 + br i1 %t32, label %then9, label %ifend11 +then9: + call void @fn_emit(ptr @.str846) + %t33 = call ptr @fn_val(ptr @.str847, ptr @.str848) + store ptr %t33, ptr %retval + br label %ret +ifend11: + %t34 = load ptr, ptr %t6 + %t35 = call i32 @fn_streq(ptr %t34, ptr @.str849) + %t36 = icmp ne i32 %t35, 0 + br i1 %t36, label %then12, label %ifend14 +then12: + call void @fn_emit(ptr @.str850) + %t37 = call ptr @fn_val(ptr @.str851, ptr @.str852) + store ptr %t37, ptr %retval + br label %ret +ifend14: + %t38 = load ptr, ptr %t6 + %t39 = call i32 @fn_streq(ptr %t38, ptr @.str853) + %t40 = icmp ne i32 %t39, 0 + br i1 %t40, label %then15, label %ifend17 +then15: + %t41 = call ptr @fn_emit_bind(ptr @.str854) + %t42 = call ptr @fn_val(ptr %t41, ptr @.str855) + store ptr %t42, ptr %retval + br label %ret +ifend17: + %t43 = load ptr, ptr %t6 + %t44 = call i32 @fn_streq(ptr %t43, ptr @.str856) + %t45 = icmp ne i32 %t44, 0 + br i1 %t45, label %then18, label %ifend20 +then18: + call void @fn_emit(ptr @.str857) + %t46 = call ptr @fn_val(ptr @.str858, ptr @.str859) + store ptr %t46, ptr %retval + br label %ret +ifend20: + %t47 = load ptr, ptr %t6 + %t48 = call i32 @fn_streq(ptr %t47, ptr @.str860) + %t49 = icmp ne i32 %t48, 0 + br i1 %t49, label %then21, label %ifend23 +then21: + %t50 = load ptr, ptr %t0 + %t51 = call ptr @fn_emit_len(ptr %t50) + store ptr %t51, ptr %retval + br label %ret +ifend23: + %t52 = load ptr, ptr %t6 + %t53 = call i32 @fn_streq(ptr %t52, ptr @.str861) + %t54 = icmp ne i32 %t53, 0 + br i1 %t54, label %then24, label %ifend26 +then24: + %t55 = load ptr, ptr %t0 + %t56 = call ptr @fn_emit_push(ptr %t55) + store ptr %t56, ptr %retval + br label %ret +ifend26: + %t57 = load ptr, ptr %t6 + %t58 = call i32 @fn_streq(ptr %t57, ptr @.str862) + %t59 = icmp ne i32 %t58, 0 + br i1 %t59, label %then27, label %ifend29 +then27: + %t60 = load ptr, ptr %t0 + %t61 = getelementptr inbounds %Str_Node, ptr %t60, i32 0, i32 7 + %t62 = load ptr, ptr %t61 + %t63 = getelementptr inbounds %LSlice, ptr %t62, i32 0, i32 0 + %t64 = load ptr, ptr %t63 + %t65 = getelementptr inbounds ptr, ptr %t64, i32 0 + %t66 = load ptr, ptr %t65 + %t67 = call ptr @fn_emit_expr(ptr %t66) + store ptr %t67, ptr %t68 + %t69 = load ptr, ptr %t68 + %t70 = getelementptr inbounds %Str_Val, ptr %t69, i32 0, i32 0 + %t71 = load ptr, ptr %t70 + %t72 = call ptr @fn_sconcat(ptr %t71, ptr @.str864) + %t73 = call ptr @fn_sconcat(ptr @.str863, ptr %t72) + %t74 = call ptr @fn_emit_bind(ptr %t73) + %t75 = call ptr @fn_val(ptr %t74, ptr @.str865) + store ptr %t75, ptr %retval + br label %ret +ifend29: + %t76 = load ptr, ptr %t6 + %t77 = call i32 @fn_streq(ptr %t76, ptr @.str866) + %t78 = icmp ne i32 %t77, 0 + br i1 %t78, label %then30, label %ifend32 +then30: + %t79 = load ptr, ptr %t0 + %t80 = getelementptr inbounds %Str_Node, ptr %t79, i32 0, i32 7 + %t81 = load ptr, ptr %t80 + %t82 = getelementptr inbounds %LSlice, ptr %t81, i32 0, i32 0 + %t83 = load ptr, ptr %t82 + %t84 = getelementptr inbounds ptr, ptr %t83, i32 0 + %t85 = load ptr, ptr %t84 + %t86 = call ptr @fn_emit_expr(ptr %t85) + store ptr %t86, ptr %t87 + %t88 = load ptr, ptr %t87 + %t89 = getelementptr inbounds %Str_Val, ptr %t88, i32 0, i32 0 + %t90 = load ptr, ptr %t89 + %t91 = call ptr @fn_sconcat(ptr %t90, ptr @.str868) + %t92 = call ptr @fn_sconcat(ptr @.str867, ptr %t91) + %t93 = call ptr @fn_emit_bind(ptr %t92) + %t94 = call ptr @fn_val(ptr %t93, ptr @.str869) + store ptr %t94, ptr %retval + br label %ret +ifend32: + %t95 = load ptr, ptr %t6 + %t96 = call i32 @fn_is_intrinsic(ptr %t95) + %t97 = icmp ne i32 %t96, 0 + br i1 %t97, label %then33, label %ifend35 +then33: + %t98 = load ptr, ptr %t6 + %t99 = load ptr, ptr %t0 + %t100 = call ptr @fn_emit_intrinsic(ptr %t98, ptr %t99) + store ptr %t100, ptr %retval + br label %ret +ifend35: + %t101 = load ptr, ptr %t6 + %t102 = call i32 @fn_is_intrinsic2(ptr %t101) + %t103 = icmp ne i32 %t102, 0 + br i1 %t103, label %then36, label %ifend38 +then36: + %t104 = load ptr, ptr %t6 + %t105 = load ptr, ptr %t0 + %t106 = call ptr @fn_emit_intrinsic2(ptr %t104, ptr %t105) + store ptr %t106, ptr %retval + br label %ret +ifend38: + %t107 = load ptr, ptr %t6 + %t108 = call i32 @fn_is_math_builtin(ptr %t107) + %t109 = icmp ne i32 %t108, 0 + br i1 %t109, label %then39, label %ifend41 +then39: + %t110 = load ptr, ptr %t6 + %t111 = load ptr, ptr %t0 + %t112 = call ptr @fn_emit_math_builtin(ptr %t110, ptr %t111) + store ptr %t112, ptr %retval + br label %ret +ifend41: + %t113 = load ptr, ptr %t6 + %t114 = call ptr @fn_find_fn(ptr %t113) + store ptr %t114, ptr %t115 + %t116 = load ptr, ptr %t6 + store ptr %t116, ptr %t117 + %t118 = load ptr, ptr %t115 + %t119 = icmp eq ptr %t118, null + %t120 = zext i1 %t119 to i32 + %t121 = icmp ne i32 %t120, 0 + br i1 %t121, label %then42, label %ifend44 +then42: + %t122 = load ptr, ptr %t6 + %t123 = call ptr @fn_sconcat(ptr @.str870, ptr %t122) + store ptr %t123, ptr %t124 + %t125 = load ptr, ptr %t124 + %t126 = call ptr @fn_find_fn(ptr %t125) + store ptr %t126, ptr %t115 + %t127 = load ptr, ptr %t115 + %t128 = icmp eq ptr %t127, null + %t129 = zext i1 %t128 to i32 + %t130 = icmp ne i32 %t129, 0 + br i1 %t130, label %then45, label %ifend47 +then45: + %t131 = load ptr, ptr %t6 + %t132 = call ptr @fn_sconcat(ptr @.str871, ptr %t131) + call void @fn_perr(ptr %t132) + br label %ifend47 +ifend47: + %t133 = load ptr, ptr %t124 + store ptr %t133, ptr %t117 + br label %ifend44 +ifend44: + %t134 = getelementptr %LSlice, ptr null, i32 1 + %t135 = ptrtoint ptr %t134 to i64 + %t136 = call ptr @malloc(i64 %t135) + %t137 = getelementptr inbounds %LSlice, ptr %t136, i32 0, i32 0 + store ptr null, ptr %t137 + %t138 = getelementptr inbounds %LSlice, ptr %t136, i32 0, i32 1 + store i32 0, ptr %t138 + %t139 = getelementptr inbounds %LSlice, ptr %t136, i32 0, i32 2 + store i32 0, ptr %t139 + store ptr %t136, ptr %t140 + %t141 = getelementptr %LSlice, ptr null, i32 1 + %t142 = ptrtoint ptr %t141 to i64 + %t143 = call ptr @malloc(i64 %t142) + %t144 = getelementptr inbounds %LSlice, ptr %t143, i32 0, i32 0 + store ptr null, ptr %t144 + %t145 = getelementptr inbounds %LSlice, ptr %t143, i32 0, i32 1 + store i32 0, ptr %t145 + %t146 = getelementptr inbounds %LSlice, ptr %t143, i32 0, i32 2 + store i32 0, ptr %t146 + store ptr %t143, ptr %t147 + store i32 0, ptr %t148 + br label %wcond48 +wcond48: + %t149 = load i32, ptr %t148 + %t150 = load ptr, ptr %t0 + %t151 = getelementptr inbounds %Str_Node, ptr %t150, i32 0, i32 7 + %t152 = load ptr, ptr %t151 + %t153 = getelementptr inbounds %LSlice, ptr %t152, i32 0, i32 1 + %t154 = load i32, ptr %t153 + %t155 = icmp slt i32 %t149, %t154 + %t156 = zext i1 %t155 to i32 + %t157 = icmp ne i32 %t156, 0 + br i1 %t157, label %wbody49, label %wend50 +wbody49: + %t158 = load ptr, ptr %t0 + %t159 = getelementptr inbounds %Str_Node, ptr %t158, i32 0, i32 7 + %t160 = load ptr, ptr %t159 + %t161 = getelementptr inbounds %LSlice, ptr %t160, i32 0, i32 0 + %t162 = load ptr, ptr %t161 + %t163 = load i32, ptr %t148 + %t164 = getelementptr inbounds ptr, ptr %t162, i32 %t163 + %t165 = load ptr, ptr %t164 + %t166 = call ptr @fn_emit_expr(ptr %t165) + store ptr %t166, ptr %t167 + %t168 = load ptr, ptr %t140 + %t169 = getelementptr inbounds %LSlice, ptr %t168, i32 0, i32 1 + %t170 = getelementptr inbounds %LSlice, ptr %t168, i32 0, i32 2 + %t171 = getelementptr inbounds %LSlice, ptr %t168, i32 0, i32 0 + %t172 = load i32, ptr %t169 + %t173 = load i32, ptr %t170 + %t174 = icmp sge i32 %t172, %t173 + br i1 %t174, label %grow51, label %put52 +grow51: + %t175 = mul i32 %t173, 2 + %t176 = icmp eq i32 %t173, 0 + %t177 = select i1 %t176, i32 8, i32 %t175 + %t178 = getelementptr ptr, ptr null, i32 1 + %t179 = ptrtoint ptr %t178 to i64 + %t180 = zext i32 %t177 to i64 + %t181 = mul i64 %t180, %t179 + %t182 = load ptr, ptr %t171 + %t183 = call ptr @realloc(ptr %t182, i64 %t181) + store ptr %t183, ptr %t171 + store i32 %t177, ptr %t170 + br label %put52 +put52: + %t184 = load ptr, ptr %t167 + %t185 = getelementptr inbounds %Str_Val, ptr %t184, i32 0, i32 0 + %t186 = load ptr, ptr %t185 + %t187 = load ptr, ptr %t171 + %t188 = getelementptr inbounds ptr, ptr %t187, i32 %t172 + store ptr %t186, ptr %t188 + %t189 = add i32 %t172, 1 + store i32 %t189, ptr %t169 + %t190 = load ptr, ptr %t147 + %t191 = getelementptr inbounds %LSlice, ptr %t190, i32 0, i32 1 + %t192 = getelementptr inbounds %LSlice, ptr %t190, i32 0, i32 2 + %t193 = getelementptr inbounds %LSlice, ptr %t190, i32 0, i32 0 + %t194 = load i32, ptr %t191 + %t195 = load i32, ptr %t192 + %t196 = icmp sge i32 %t194, %t195 + br i1 %t196, label %grow53, label %put54 +grow53: + %t197 = mul i32 %t195, 2 + %t198 = icmp eq i32 %t195, 0 + %t199 = select i1 %t198, i32 8, i32 %t197 + %t200 = getelementptr ptr, ptr null, i32 1 + %t201 = ptrtoint ptr %t200 to i64 + %t202 = zext i32 %t199 to i64 + %t203 = mul i64 %t202, %t201 + %t204 = load ptr, ptr %t193 + %t205 = call ptr @realloc(ptr %t204, i64 %t203) + store ptr %t205, ptr %t193 + store i32 %t199, ptr %t192 + br label %put54 +put54: + %t206 = load ptr, ptr %t167 + %t207 = getelementptr inbounds %Str_Val, ptr %t206, i32 0, i32 1 + %t208 = load ptr, ptr %t207 + %t209 = load ptr, ptr %t193 + %t210 = getelementptr inbounds ptr, ptr %t209, i32 %t194 + store ptr %t208, ptr %t210 + %t211 = add i32 %t194, 1 + store i32 %t211, ptr %t191 + %t212 = load i32, ptr %t148 + %t213 = add i32 %t212, 1 + store i32 %t213, ptr %t148 + br label %wcond48 +wend50: + %t214 = load ptr, ptr %t115 + %t215 = getelementptr inbounds %Str_Node, ptr %t214, i32 0, i32 3 + %t216 = load ptr, ptr %t215 + %t217 = call ptr @fn_llty(ptr %t216) + store ptr %t217, ptr %t218 + call void @fn_emit(ptr @.str872) + store ptr @.str873, ptr %t219 + %t220 = load ptr, ptr %t218 + %t221 = call i32 @fn_streq(ptr %t220, ptr @.str874) + %t222 = icmp eq i32 %t221, 0 + %t223 = zext i1 %t222 to i32 + %t224 = icmp ne i32 %t223, 0 + br i1 %t224, label %then55, label %ifend57 +then55: + %t225 = call ptr @fn_nreg() + store ptr %t225, ptr %t219 + %t226 = load ptr, ptr %t219 + call void @fn_emit(ptr %t226) + call void @fn_emit(ptr @.str875) + br label %ifend57 +ifend57: + call void @fn_emit(ptr @.str876) + %t227 = load ptr, ptr %t218 + call void @fn_emit(ptr %t227) + call void @fn_emit(ptr @.str877) + %t228 = load ptr, ptr %t117 + call void @fn_emit(ptr %t228) + call void @fn_emit(ptr @.str878) + store i32 0, ptr %t148 + br label %wcond58 +wcond58: + %t229 = load i32, ptr %t148 + %t230 = load ptr, ptr %t140 + %t231 = getelementptr inbounds %LSlice, ptr %t230, i32 0, i32 1 + %t232 = load i32, ptr %t231 + %t233 = icmp slt i32 %t229, %t232 + %t234 = zext i1 %t233 to i32 + %t235 = icmp ne i32 %t234, 0 + br i1 %t235, label %wbody59, label %wend60 +wbody59: + %t236 = load i32, ptr %t148 + %t237 = icmp sgt i32 %t236, 0 + %t238 = zext i1 %t237 to i32 + %t239 = icmp ne i32 %t238, 0 + br i1 %t239, label %then61, label %ifend63 +then61: + call void @fn_emit(ptr @.str879) + br label %ifend63 +ifend63: + %t240 = load ptr, ptr %t147 + %t241 = getelementptr inbounds %LSlice, ptr %t240, i32 0, i32 0 + %t242 = load ptr, ptr %t241 + %t243 = load i32, ptr %t148 + %t244 = getelementptr inbounds ptr, ptr %t242, i32 %t243 + %t245 = load ptr, ptr %t244 + %t246 = call ptr @fn_llty(ptr %t245) + call void @fn_emit(ptr %t246) + call void @fn_emit(ptr @.str880) + %t247 = load ptr, ptr %t140 + %t248 = getelementptr inbounds %LSlice, ptr %t247, i32 0, i32 0 + %t249 = load ptr, ptr %t248 + %t250 = load i32, ptr %t148 + %t251 = getelementptr inbounds ptr, ptr %t249, i32 %t250 + %t252 = load ptr, ptr %t251 + call void @fn_emit(ptr %t252) + %t253 = load i32, ptr %t148 + %t254 = add i32 %t253, 1 + store i32 %t254, ptr %t148 + br label %wcond58 +wend60: + call void @fn_emit(ptr @.str881) + %t255 = load ptr, ptr %t219 + %t256 = load ptr, ptr %t115 + %t257 = getelementptr inbounds %Str_Node, ptr %t256, i32 0, i32 3 + %t258 = load ptr, ptr %t257 + %t259 = call ptr @fn_val(ptr %t255, ptr %t258) + store ptr %t259, ptr %retval + br label %ret +ret: + %t260 = load ptr, ptr %retval + ret ptr %t260 +} + +define ptr @fn_emit_expr(ptr %arg_e) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t79 = alloca i32 + %t101 = alloca ptr + %t132 = alloca ptr + %t161 = alloca ptr + %t173 = alloca ptr + %t203 = alloca ptr + %t221 = alloca ptr + store ptr %arg_e, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = icmp eq ptr %t1, null + %t3 = zext i1 %t2 to i32 + %t4 = icmp ne i32 %t3, 0 + br i1 %t4, label %then0, label %ifend2 +then0: + %t5 = call ptr @fn_val(ptr @.str882, ptr @.str883) + store ptr %t5, ptr %retval + br label %ret +ifend2: + %t6 = load ptr, ptr %t0 + %t7 = getelementptr inbounds %Str_Node, ptr %t6, i32 0, i32 0 + %t8 = load i32, ptr %t7 + %t9 = icmp eq i32 %t8, 30 + %t10 = zext i1 %t9 to i32 + %t11 = icmp ne i32 %t10, 0 + br i1 %t11, label %then3, label %ifend5 +then3: + %t12 = load ptr, ptr %t0 + %t13 = getelementptr inbounds %Str_Node, ptr %t12, i32 0, i32 2 + %t14 = load i32, ptr %t13 + %t15 = call ptr @fn_itoa(i32 %t14) + %t16 = call ptr @fn_val(ptr %t15, ptr @.str884) + store ptr %t16, ptr %retval + br label %ret +ifend5: + %t17 = load ptr, ptr %t0 + %t18 = getelementptr inbounds %Str_Node, ptr %t17, i32 0, i32 0 + %t19 = load i32, ptr %t18 + %t20 = icmp eq i32 %t19, 40 + %t21 = zext i1 %t20 to i32 + %t22 = icmp ne i32 %t21, 0 + br i1 %t22, label %then6, label %ifend8 +then6: + %t23 = load ptr, ptr %t0 + %t24 = getelementptr inbounds %Str_Node, ptr %t23, i32 0, i32 2 + %t25 = load i32, ptr %t24 + %t26 = call ptr @fn_itoa(i32 %t25) + %t27 = call ptr @fn_val(ptr %t26, ptr @.str885) + store ptr %t27, ptr %retval + br label %ret +ifend8: + %t28 = load ptr, ptr %t0 + %t29 = getelementptr inbounds %Str_Node, ptr %t28, i32 0, i32 0 + %t30 = load i32, ptr %t29 + %t31 = icmp eq i32 %t30, 32 + %t32 = zext i1 %t31 to i32 + %t33 = icmp ne i32 %t32, 0 + br i1 %t33, label %then9, label %ifend11 +then9: + %t34 = load ptr, ptr %t0 + %t35 = getelementptr inbounds %Str_Node, ptr %t34, i32 0, i32 2 + %t36 = load i32, ptr %t35 + %t37 = call ptr @fn_itoa(i32 %t36) + %t38 = call ptr @fn_val(ptr %t37, ptr @.str886) + store ptr %t38, ptr %retval + br label %ret +ifend11: + %t39 = load ptr, ptr %t0 + %t40 = getelementptr inbounds %Str_Node, ptr %t39, i32 0, i32 0 + %t41 = load i32, ptr %t40 + %t42 = icmp eq i32 %t41, 31 + %t43 = zext i1 %t42 to i32 + %t44 = icmp ne i32 %t43, 0 + br i1 %t44, label %then12, label %ifend14 +then12: + %t45 = load ptr, ptr %t0 + %t46 = getelementptr inbounds %Str_Node, ptr %t45, i32 0, i32 1 + %t47 = load ptr, ptr %t46 + %t48 = call ptr @fn_emit_str_const(ptr %t47) + %t49 = call ptr @fn_val(ptr %t48, ptr @.str887) + store ptr %t49, ptr %retval + br label %ret +ifend14: + %t50 = load ptr, ptr %t0 + %t51 = getelementptr inbounds %Str_Node, ptr %t50, i32 0, i32 0 + %t52 = load i32, ptr %t51 + %t53 = icmp eq i32 %t52, 39 + %t54 = zext i1 %t53 to i32 + %t55 = icmp ne i32 %t54, 0 + br i1 %t55, label %then15, label %ifend17 +then15: + %t56 = load ptr, ptr %t0 + %t57 = getelementptr inbounds %Str_Node, ptr %t56, i32 0, i32 1 + %t58 = load ptr, ptr %t57 + %t59 = call i32 @fn_is_slice_ty(ptr %t58) + %t60 = icmp ne i32 %t59, 0 + br i1 %t60, label %then18, label %ifend20 +then18: + %t61 = load ptr, ptr %t0 + %t62 = getelementptr inbounds %Str_Node, ptr %t61, i32 0, i32 1 + %t63 = load ptr, ptr %t62 + %t64 = call ptr @fn_emit_new_slice(ptr %t63) + store ptr %t64, ptr %retval + br label %ret +ifend20: + %t65 = load ptr, ptr %t0 + %t66 = getelementptr inbounds %Str_Node, ptr %t65, i32 0, i32 1 + %t67 = load ptr, ptr %t66 + %t68 = call ptr @fn_emit_new_struct(ptr %t67) + store ptr %t68, ptr %retval + br label %ret +ifend17: + %t69 = load ptr, ptr %t0 + %t70 = getelementptr inbounds %Str_Node, ptr %t69, i32 0, i32 0 + %t71 = load i32, ptr %t70 + %t72 = icmp eq i32 %t71, 33 + %t73 = zext i1 %t72 to i32 + %t74 = icmp ne i32 %t73, 0 + br i1 %t74, label %then21, label %ifend23 +then21: + %t75 = load ptr, ptr %t0 + %t76 = getelementptr inbounds %Str_Node, ptr %t75, i32 0, i32 1 + %t77 = load ptr, ptr %t76 + %t78 = call i32 @fn_loc_find(ptr %t77) + store i32 %t78, ptr %t79 + %t80 = load i32, ptr %t79 + %t81 = icmp sge i32 %t80, 0 + %t82 = zext i1 %t81 to i32 + %t83 = icmp ne i32 %t82, 0 + br i1 %t83, label %then24, label %ifend26 +then24: + %t84 = load ptr, ptr @g_loc_reg + %t85 = getelementptr inbounds %LSlice, ptr %t84, i32 0, i32 0 + %t86 = load ptr, ptr %t85 + %t87 = load i32, ptr %t79 + %t88 = getelementptr inbounds ptr, ptr %t86, i32 %t87 + %t89 = load ptr, ptr %t88 + %t90 = load ptr, ptr @g_loc_ty + %t91 = getelementptr inbounds %LSlice, ptr %t90, i32 0, i32 0 + %t92 = load ptr, ptr %t91 + %t93 = load i32, ptr %t79 + %t94 = getelementptr inbounds ptr, ptr %t92, i32 %t93 + %t95 = load ptr, ptr %t94 + %t96 = call ptr @fn_emit_load_at(ptr %t89, ptr %t95) + store ptr %t96, ptr %retval + br label %ret +ifend26: + %t97 = load ptr, ptr %t0 + %t98 = getelementptr inbounds %Str_Node, ptr %t97, i32 0, i32 1 + %t99 = load ptr, ptr %t98 + %t100 = call ptr @fn_find_global(ptr %t99) + store ptr %t100, ptr %t101 + %t102 = load ptr, ptr %t101 + %t103 = icmp eq ptr %t102, null + %t104 = zext i1 %t103 to i32 + %t105 = icmp eq i32 %t104, 0 + %t106 = zext i1 %t105 to i32 + %t107 = icmp ne i32 %t106, 0 + br i1 %t107, label %then27, label %ifend29 +then27: + %t108 = load ptr, ptr %t101 + %t109 = getelementptr inbounds %Str_Node, ptr %t108, i32 0, i32 0 + %t110 = load i32, ptr %t109 + %t111 = icmp eq i32 %t110, 3 + %t112 = zext i1 %t111 to i32 + %t113 = icmp ne i32 %t112, 0 + br i1 %t113, label %then30, label %ifend32 +then30: + %t114 = load ptr, ptr %t101 + %t115 = getelementptr inbounds %Str_Node, ptr %t114, i32 0, i32 4 + %t116 = load ptr, ptr %t115 + %t117 = getelementptr inbounds %Str_Node, ptr %t116, i32 0, i32 2 + %t118 = load i32, ptr %t117 + %t119 = call ptr @fn_itoa(i32 %t118) + %t120 = call ptr @fn_val(ptr %t119, ptr @.str888) + store ptr %t120, ptr %retval + br label %ret +ifend32: + %t121 = load ptr, ptr %t101 + %t122 = getelementptr inbounds %Str_Node, ptr %t121, i32 0, i32 3 + %t123 = load ptr, ptr %t122 + %t124 = call ptr @fn_llty(ptr %t123) + %t125 = load ptr, ptr %t0 + %t126 = getelementptr inbounds %Str_Node, ptr %t125, i32 0, i32 1 + %t127 = load ptr, ptr %t126 + %t128 = call ptr @fn_sconcat(ptr @.str890, ptr %t127) + %t129 = call ptr @fn_sconcat(ptr %t124, ptr %t128) + %t130 = call ptr @fn_sconcat(ptr @.str889, ptr %t129) + %t131 = call ptr @fn_emit_bind(ptr %t130) + store ptr %t131, ptr %t132 + %t133 = load ptr, ptr %t132 + %t134 = load ptr, ptr %t101 + %t135 = getelementptr inbounds %Str_Node, ptr %t134, i32 0, i32 3 + %t136 = load ptr, ptr %t135 + %t137 = call ptr @fn_val(ptr %t133, ptr %t136) + store ptr %t137, ptr %retval + br label %ret +ifend29: + %t138 = load ptr, ptr %t0 + %t139 = getelementptr inbounds %Str_Node, ptr %t138, i32 0, i32 1 + %t140 = load ptr, ptr %t139 + %t141 = call i32 @fn_is_ui_ident(ptr %t140) + %t142 = icmp ne i32 %t141, 0 + br i1 %t142, label %then33, label %ifend35 +then33: + %t143 = load ptr, ptr %t0 + %t144 = getelementptr inbounds %Str_Node, ptr %t143, i32 0, i32 1 + %t145 = load ptr, ptr %t144 + %t146 = call i32 @fn_ui_index_of(ptr %t145) + %t147 = call ptr @fn_itoa(i32 %t146) + %t148 = call ptr @fn_val(ptr %t147, ptr @.str891) + store ptr %t148, ptr %retval + br label %ret +ifend35: + %t149 = load ptr, ptr %t0 + %t150 = getelementptr inbounds %Str_Node, ptr %t149, i32 0, i32 1 + %t151 = load ptr, ptr %t150 + %t152 = call ptr @fn_sconcat(ptr @.str892, ptr %t151) + call void @fn_perr(ptr %t152) + br label %ifend23 +ifend23: + %t153 = load ptr, ptr %t0 + %t154 = getelementptr inbounds %Str_Node, ptr %t153, i32 0, i32 0 + %t155 = load i32, ptr %t154 + %t156 = icmp eq i32 %t155, 35 + %t157 = zext i1 %t156 to i32 + %t158 = icmp ne i32 %t157, 0 + br i1 %t158, label %then36, label %ifend38 +then36: + %t159 = load ptr, ptr %t0 + %t160 = call ptr @fn_emit_member_addr(ptr %t159) + store ptr %t160, ptr %t161 + %t162 = load ptr, ptr %t161 + %t163 = load ptr, ptr @g_g_addr_ty + %t164 = call ptr @fn_emit_load_at(ptr %t162, ptr %t163) + store ptr %t164, ptr %retval + br label %ret +ifend38: + %t165 = load ptr, ptr %t0 + %t166 = getelementptr inbounds %Str_Node, ptr %t165, i32 0, i32 0 + %t167 = load i32, ptr %t166 + %t168 = icmp eq i32 %t167, 36 + %t169 = zext i1 %t168 to i32 + %t170 = icmp ne i32 %t169, 0 + br i1 %t170, label %then39, label %ifend41 +then39: + %t171 = load ptr, ptr %t0 + %t172 = call ptr @fn_emit_index_addr(ptr %t171) + store ptr %t172, ptr %t173 + %t174 = load ptr, ptr %t173 + %t175 = load ptr, ptr @g_g_addr_ty + %t176 = call ptr @fn_emit_load_at(ptr %t174, ptr %t175) + store ptr %t176, ptr %retval + br label %ret +ifend41: + %t177 = load ptr, ptr %t0 + %t178 = getelementptr inbounds %Str_Node, ptr %t177, i32 0, i32 0 + %t179 = load i32, ptr %t178 + %t180 = icmp eq i32 %t179, 34 + %t181 = zext i1 %t180 to i32 + %t182 = icmp ne i32 %t181, 0 + br i1 %t182, label %then42, label %ifend44 +then42: + %t183 = load ptr, ptr %t0 + %t184 = call ptr @fn_emit_call(ptr %t183) + store ptr %t184, ptr %retval + br label %ret +ifend44: + %t185 = load ptr, ptr %t0 + %t186 = getelementptr inbounds %Str_Node, ptr %t185, i32 0, i32 0 + %t187 = load i32, ptr %t186 + %t188 = icmp eq i32 %t187, 37 + %t189 = zext i1 %t188 to i32 + %t190 = icmp ne i32 %t189, 0 + br i1 %t190, label %then45, label %ifend47 +then45: + %t191 = load ptr, ptr %t0 + %t192 = call ptr @fn_emit_bin(ptr %t191) + store ptr %t192, ptr %retval + br label %ret +ifend47: + %t193 = load ptr, ptr %t0 + %t194 = getelementptr inbounds %Str_Node, ptr %t193, i32 0, i32 0 + %t195 = load i32, ptr %t194 + %t196 = icmp eq i32 %t195, 38 + %t197 = zext i1 %t196 to i32 + %t198 = icmp ne i32 %t197, 0 + br i1 %t198, label %then48, label %ifend50 +then48: + %t199 = load ptr, ptr %t0 + %t200 = getelementptr inbounds %Str_Node, ptr %t199, i32 0, i32 4 + %t201 = load ptr, ptr %t200 + %t202 = call ptr @fn_emit_expr(ptr %t201) + store ptr %t202, ptr %t203 + %t204 = load ptr, ptr %t0 + %t205 = getelementptr inbounds %Str_Node, ptr %t204, i32 0, i32 1 + %t206 = load ptr, ptr %t205 + %t207 = call i32 @fn_streq(ptr %t206, ptr @.str893) + %t208 = icmp ne i32 %t207, 0 + br i1 %t208, label %then51, label %ifend53 +then51: + %t209 = load ptr, ptr %t203 + %t210 = getelementptr inbounds %Str_Val, ptr %t209, i32 0, i32 0 + %t211 = load ptr, ptr %t210 + %t212 = call ptr @fn_sconcat(ptr @.str894, ptr %t211) + %t213 = call ptr @fn_emit_bind(ptr %t212) + %t214 = call ptr @fn_val(ptr %t213, ptr @.str895) + store ptr %t214, ptr %retval + br label %ret +ifend53: + %t215 = load ptr, ptr %t203 + %t216 = getelementptr inbounds %Str_Val, ptr %t215, i32 0, i32 0 + %t217 = load ptr, ptr %t216 + %t218 = call ptr @fn_sconcat(ptr %t217, ptr @.str897) + %t219 = call ptr @fn_sconcat(ptr @.str896, ptr %t218) + %t220 = call ptr @fn_emit_bind(ptr %t219) + store ptr %t220, ptr %t221 + %t222 = load ptr, ptr %t221 + %t223 = call ptr @fn_sconcat(ptr %t222, ptr @.str899) + %t224 = call ptr @fn_sconcat(ptr @.str898, ptr %t223) + %t225 = call ptr @fn_emit_bind(ptr %t224) + %t226 = call ptr @fn_val(ptr %t225, ptr @.str900) + store ptr %t226, ptr %retval + br label %ret +ifend50: + call void @fn_perr(ptr @.str901) + %t227 = call ptr @fn_val(ptr @.str902, ptr @.str903) + store ptr %t227, ptr %retval + br label %ret +ret: + %t228 = load ptr, ptr %retval + ret ptr %t228 +} + +define void @fn_emit_block(ptr %arg_b) { +entry: + %t0 = alloca ptr + %t1 = alloca i32 + store ptr %arg_b, ptr %t0 + store i32 0, ptr %t1 + br label %wcond0 +wcond0: + %t2 = load i32, ptr %t1 + %t3 = load ptr, ptr %t0 + %t4 = getelementptr inbounds %Str_Node, ptr %t3, i32 0, i32 7 + %t5 = load ptr, ptr %t4 + %t6 = getelementptr inbounds %LSlice, ptr %t5, i32 0, i32 1 + %t7 = load i32, ptr %t6 + %t8 = icmp slt i32 %t2, %t7 + %t9 = zext i1 %t8 to i32 + %t10 = icmp ne i32 %t9, 0 + br i1 %t10, label %wbody1, label %wend2 +wbody1: + %t11 = load i32, ptr @g_g_term + %t12 = icmp ne i32 %t11, 0 + br i1 %t12, label %then3, label %ifend5 +then3: + br label %ret +ifend5: + %t13 = load ptr, ptr %t0 + %t14 = getelementptr inbounds %Str_Node, ptr %t13, i32 0, i32 7 + %t15 = load ptr, ptr %t14 + %t16 = getelementptr inbounds %LSlice, ptr %t15, i32 0, i32 0 + %t17 = load ptr, ptr %t16 + %t18 = load i32, ptr %t1 + %t19 = getelementptr inbounds ptr, ptr %t17, i32 %t18 + %t20 = load ptr, ptr %t19 + call void @fn_emit_stmt(ptr %t20) + %t21 = load i32, ptr %t1 + %t22 = add i32 %t21, 1 + store i32 %t22, ptr %t1 + br label %wcond0 +wend2: + br label %ret +ret: + ret void +} + +define void @fn_store_at(ptr %arg_lt, ptr %arg_v, ptr %arg_addr) { +entry: + %t0 = alloca ptr + %t1 = alloca ptr + %t2 = alloca ptr + store ptr %arg_lt, ptr %t0 + store ptr %arg_v, ptr %t1 + store ptr %arg_addr, ptr %t2 + call void @fn_emit(ptr @.str904) + %t3 = load ptr, ptr %t0 + call void @fn_emit(ptr %t3) + call void @fn_emit(ptr @.str905) + %t4 = load ptr, ptr %t1 + call void @fn_emit(ptr %t4) + call void @fn_emit(ptr @.str906) + %t5 = load ptr, ptr %t2 + call void @fn_emit(ptr %t5) + call void @fn_emit(ptr @.str907) + br label %ret +ret: + ret void +} + +define void @fn_emit_assign(ptr %arg_st) { +entry: + %t0 = alloca ptr + %t4 = alloca ptr + %t5 = alloca ptr + %t6 = alloca ptr + %t17 = alloca i32 + %t38 = alloca ptr + %t74 = alloca ptr + %t79 = alloca ptr + %t83 = alloca ptr + %t97 = alloca ptr + %t98 = alloca ptr + store ptr %arg_st, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = getelementptr inbounds %Str_Node, ptr %t1, i32 0, i32 4 + %t3 = load ptr, ptr %t2 + store ptr %t3, ptr %t4 + store ptr @.str908, ptr %t5 + store ptr @.str909, ptr %t6 + %t7 = load ptr, ptr %t4 + %t8 = getelementptr inbounds %Str_Node, ptr %t7, i32 0, i32 0 + %t9 = load i32, ptr %t8 + %t10 = icmp eq i32 %t9, 33 + %t11 = zext i1 %t10 to i32 + %t12 = icmp ne i32 %t11, 0 + br i1 %t12, label %then0, label %else1 +then0: + %t13 = load ptr, ptr %t4 + %t14 = getelementptr inbounds %Str_Node, ptr %t13, i32 0, i32 1 + %t15 = load ptr, ptr %t14 + %t16 = call i32 @fn_loc_find(ptr %t15) + store i32 %t16, ptr %t17 + %t18 = load i32, ptr %t17 + %t19 = icmp sge i32 %t18, 0 + %t20 = zext i1 %t19 to i32 + %t21 = icmp ne i32 %t20, 0 + br i1 %t21, label %then3, label %else4 +then3: + %t22 = load ptr, ptr @g_loc_reg + %t23 = getelementptr inbounds %LSlice, ptr %t22, i32 0, i32 0 + %t24 = load ptr, ptr %t23 + %t25 = load i32, ptr %t17 + %t26 = getelementptr inbounds ptr, ptr %t24, i32 %t25 + %t27 = load ptr, ptr %t26 + store ptr %t27, ptr %t5 + %t28 = load ptr, ptr @g_loc_ty + %t29 = getelementptr inbounds %LSlice, ptr %t28, i32 0, i32 0 + %t30 = load ptr, ptr %t29 + %t31 = load i32, ptr %t17 + %t32 = getelementptr inbounds ptr, ptr %t30, i32 %t31 + %t33 = load ptr, ptr %t32 + store ptr %t33, ptr %t6 + br label %ifend5 +else4: + %t34 = load ptr, ptr %t4 + %t35 = getelementptr inbounds %Str_Node, ptr %t34, i32 0, i32 1 + %t36 = load ptr, ptr %t35 + %t37 = call ptr @fn_find_global(ptr %t36) + store ptr %t37, ptr %t38 + %t39 = load ptr, ptr %t38 + %t40 = icmp eq ptr %t39, null + %t41 = zext i1 %t40 to i32 + %t42 = icmp ne i32 %t41, 0 + br i1 %t42, label %then6, label %ifend8 +then6: + %t43 = load ptr, ptr %t4 + %t44 = getelementptr inbounds %Str_Node, ptr %t43, i32 0, i32 1 + %t45 = load ptr, ptr %t44 + %t46 = call ptr @fn_sconcat(ptr @.str910, ptr %t45) + call void @fn_perr(ptr %t46) + br label %ifend8 +ifend8: + %t47 = load ptr, ptr %t4 + %t48 = getelementptr inbounds %Str_Node, ptr %t47, i32 0, i32 1 + %t49 = load ptr, ptr %t48 + %t50 = call ptr @fn_sconcat(ptr @.str911, ptr %t49) + store ptr %t50, ptr %t5 + %t51 = load ptr, ptr %t38 + %t52 = getelementptr inbounds %Str_Node, ptr %t51, i32 0, i32 3 + %t53 = load ptr, ptr %t52 + store ptr %t53, ptr %t6 + br label %ifend5 +ifend5: + br label %ifend2 +else1: + %t54 = load ptr, ptr %t4 + %t55 = getelementptr inbounds %Str_Node, ptr %t54, i32 0, i32 0 + %t56 = load i32, ptr %t55 + %t57 = icmp eq i32 %t56, 35 + %t58 = zext i1 %t57 to i32 + %t59 = icmp ne i32 %t58, 0 + br i1 %t59, label %then9, label %else10 +then9: + %t60 = load ptr, ptr %t4 + %t61 = call ptr @fn_emit_member_addr(ptr %t60) + store ptr %t61, ptr %t5 + %t62 = load ptr, ptr @g_g_addr_ty + store ptr %t62, ptr %t6 + br label %ifend11 +else10: + %t63 = load ptr, ptr %t4 + %t64 = getelementptr inbounds %Str_Node, ptr %t63, i32 0, i32 0 + %t65 = load i32, ptr %t64 + %t66 = icmp eq i32 %t65, 36 + %t67 = zext i1 %t66 to i32 + %t68 = icmp ne i32 %t67, 0 + br i1 %t68, label %then12, label %else13 +then12: + %t69 = load ptr, ptr %t4 + %t70 = call ptr @fn_emit_index_addr(ptr %t69) + store ptr %t70, ptr %t5 + %t71 = load ptr, ptr @g_g_addr_ty + store ptr %t71, ptr %t6 + br label %ifend14 +else13: + call void @fn_perr(ptr @.str912) + br label %ifend14 +ifend14: + br label %ifend11 +ifend11: + br label %ifend2 +ifend2: + %t72 = load ptr, ptr %t6 + %t73 = call ptr @fn_llty(ptr %t72) + store ptr %t73, ptr %t74 + %t75 = load ptr, ptr %t0 + %t76 = getelementptr inbounds %Str_Node, ptr %t75, i32 0, i32 5 + %t77 = load ptr, ptr %t76 + %t78 = call ptr @fn_emit_expr(ptr %t77) + store ptr %t78, ptr %t79 + %t80 = load ptr, ptr %t79 + %t81 = getelementptr inbounds %Str_Val, ptr %t80, i32 0, i32 0 + %t82 = load ptr, ptr %t81 + store ptr %t82, ptr %t83 + %t84 = load ptr, ptr %t0 + %t85 = getelementptr inbounds %Str_Node, ptr %t84, i32 0, i32 1 + %t86 = load ptr, ptr %t85 + %t87 = call i32 @fn_streq(ptr %t86, ptr @.str913) + %t88 = icmp eq i32 %t87, 0 + %t89 = zext i1 %t88 to i32 + %t90 = icmp ne i32 %t89, 0 + br i1 %t90, label %then15, label %ifend17 +then15: + %t91 = load ptr, ptr %t74 + %t92 = load ptr, ptr %t5 + %t93 = call ptr @fn_sconcat(ptr @.str915, ptr %t92) + %t94 = call ptr @fn_sconcat(ptr %t91, ptr %t93) + %t95 = call ptr @fn_sconcat(ptr @.str914, ptr %t94) + %t96 = call ptr @fn_emit_bind(ptr %t95) + store ptr %t96, ptr %t97 + store ptr @.str916, ptr %t98 + %t99 = load ptr, ptr %t0 + %t100 = getelementptr inbounds %Str_Node, ptr %t99, i32 0, i32 1 + %t101 = load ptr, ptr %t100 + %t102 = call i32 @fn_streq(ptr %t101, ptr @.str917) + %t103 = icmp ne i32 %t102, 0 + br i1 %t103, label %then18, label %ifend20 +then18: + store ptr @.str918, ptr %t98 + br label %ifend20 +ifend20: + %t104 = load ptr, ptr %t0 + %t105 = getelementptr inbounds %Str_Node, ptr %t104, i32 0, i32 1 + %t106 = load ptr, ptr %t105 + %t107 = call i32 @fn_streq(ptr %t106, ptr @.str919) + %t108 = icmp ne i32 %t107, 0 + br i1 %t108, label %then21, label %ifend23 +then21: + store ptr @.str920, ptr %t98 + br label %ifend23 +ifend23: + %t109 = load ptr, ptr %t0 + %t110 = getelementptr inbounds %Str_Node, ptr %t109, i32 0, i32 1 + %t111 = load ptr, ptr %t110 + %t112 = call i32 @fn_streq(ptr %t111, ptr @.str921) + %t113 = icmp ne i32 %t112, 0 + br i1 %t113, label %then24, label %ifend26 +then24: + store ptr @.str922, ptr %t98 + br label %ifend26 +ifend26: + %t114 = load ptr, ptr %t98 + %t115 = load ptr, ptr %t97 + %t116 = load ptr, ptr %t83 + %t117 = call ptr @fn_sconcat(ptr @.str924, ptr %t116) + %t118 = call ptr @fn_sconcat(ptr %t115, ptr %t117) + %t119 = call ptr @fn_sconcat(ptr @.str923, ptr %t118) + %t120 = call ptr @fn_sconcat(ptr %t114, ptr %t119) + %t121 = call ptr @fn_emit_bind(ptr %t120) + store ptr %t121, ptr %t83 + br label %ifend17 +ifend17: + %t122 = load ptr, ptr %t74 + %t123 = load ptr, ptr %t83 + %t124 = load ptr, ptr %t5 + call void @fn_store_at(ptr %t122, ptr %t123, ptr %t124) + br label %ret +ret: + ret void +} + +define void @fn_emit_if(ptr %arg_st) { +entry: + %t0 = alloca ptr + %t5 = alloca ptr + %t12 = alloca ptr + %t20 = alloca i32 + %t22 = alloca ptr + %t24 = alloca ptr + %t26 = alloca ptr + store ptr %arg_st, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = getelementptr inbounds %Str_Node, ptr %t1, i32 0, i32 4 + %t3 = load ptr, ptr %t2 + %t4 = call ptr @fn_emit_expr(ptr %t3) + store ptr %t4, ptr %t5 + %t6 = load ptr, ptr %t5 + %t7 = getelementptr inbounds %Str_Val, ptr %t6, i32 0, i32 0 + %t8 = load ptr, ptr %t7 + %t9 = call ptr @fn_sconcat(ptr %t8, ptr @.str926) + %t10 = call ptr @fn_sconcat(ptr @.str925, ptr %t9) + %t11 = call ptr @fn_emit_bind(ptr %t10) + store ptr %t11, ptr %t12 + %t13 = load ptr, ptr %t0 + %t14 = getelementptr inbounds %Str_Node, ptr %t13, i32 0, i32 6 + %t15 = load ptr, ptr %t14 + %t16 = icmp eq ptr %t15, null + %t17 = zext i1 %t16 to i32 + %t18 = icmp eq i32 %t17, 0 + %t19 = zext i1 %t18 to i32 + store i32 %t19, ptr %t20 + %t21 = call ptr @fn_lbl(ptr @.str927) + store ptr %t21, ptr %t22 + %t23 = call ptr @fn_lbl(ptr @.str928) + store ptr %t23, ptr %t24 + %t25 = call ptr @fn_lbl(ptr @.str929) + store ptr %t25, ptr %t26 + %t27 = load i32, ptr %t20 + %t28 = icmp ne i32 %t27, 0 + br i1 %t28, label %then0, label %else1 +then0: + call void @fn_emit(ptr @.str930) + %t29 = load ptr, ptr %t12 + call void @fn_emit(ptr %t29) + call void @fn_emit(ptr @.str931) + %t30 = load ptr, ptr %t22 + call void @fn_emit(ptr %t30) + call void @fn_emit(ptr @.str932) + %t31 = load ptr, ptr %t24 + call void @fn_emit(ptr %t31) + call void @fn_emit(ptr @.str933) + br label %ifend2 +else1: + call void @fn_emit(ptr @.str934) + %t32 = load ptr, ptr %t12 + call void @fn_emit(ptr %t32) + call void @fn_emit(ptr @.str935) + %t33 = load ptr, ptr %t22 + call void @fn_emit(ptr %t33) + call void @fn_emit(ptr @.str936) + %t34 = load ptr, ptr %t26 + call void @fn_emit(ptr %t34) + call void @fn_emit(ptr @.str937) + br label %ifend2 +ifend2: + %t35 = load ptr, ptr %t22 + call void @fn_emit(ptr %t35) + call void @fn_emit(ptr @.str938) + store i32 0, ptr @g_g_term + %t36 = load ptr, ptr %t0 + %t37 = getelementptr inbounds %Str_Node, ptr %t36, i32 0, i32 5 + %t38 = load ptr, ptr %t37 + call void @fn_emit_block(ptr %t38) + %t39 = load i32, ptr @g_g_term + %t40 = icmp eq i32 %t39, 0 + %t41 = zext i1 %t40 to i32 + %t42 = icmp ne i32 %t41, 0 + br i1 %t42, label %then3, label %ifend5 +then3: + call void @fn_emit(ptr @.str939) + %t43 = load ptr, ptr %t26 + call void @fn_emit(ptr %t43) + call void @fn_emit(ptr @.str940) + br label %ifend5 +ifend5: + %t44 = load i32, ptr %t20 + %t45 = icmp ne i32 %t44, 0 + br i1 %t45, label %then6, label %ifend8 +then6: + %t46 = load ptr, ptr %t24 + call void @fn_emit(ptr %t46) + call void @fn_emit(ptr @.str941) + store i32 0, ptr @g_g_term + %t47 = load ptr, ptr %t0 + %t48 = getelementptr inbounds %Str_Node, ptr %t47, i32 0, i32 6 + %t49 = load ptr, ptr %t48 + %t50 = getelementptr inbounds %Str_Node, ptr %t49, i32 0, i32 0 + %t51 = load i32, ptr %t50 + %t52 = icmp eq i32 %t51, 12 + %t53 = zext i1 %t52 to i32 + %t54 = icmp ne i32 %t53, 0 + br i1 %t54, label %then9, label %else10 +then9: + %t55 = load ptr, ptr %t0 + %t56 = getelementptr inbounds %Str_Node, ptr %t55, i32 0, i32 6 + %t57 = load ptr, ptr %t56 + call void @fn_emit_stmt(ptr %t57) + br label %ifend11 +else10: + %t58 = load ptr, ptr %t0 + %t59 = getelementptr inbounds %Str_Node, ptr %t58, i32 0, i32 6 + %t60 = load ptr, ptr %t59 + call void @fn_emit_block(ptr %t60) + br label %ifend11 +ifend11: + %t61 = load i32, ptr @g_g_term + %t62 = icmp eq i32 %t61, 0 + %t63 = zext i1 %t62 to i32 + %t64 = icmp ne i32 %t63, 0 + br i1 %t64, label %then12, label %ifend14 +then12: + call void @fn_emit(ptr @.str942) + %t65 = load ptr, ptr %t26 + call void @fn_emit(ptr %t65) + call void @fn_emit(ptr @.str943) + br label %ifend14 +ifend14: + br label %ifend8 +ifend8: + %t66 = load ptr, ptr %t26 + call void @fn_emit(ptr %t66) + call void @fn_emit(ptr @.str944) + store i32 0, ptr @g_g_term + br label %ret +ret: + ret void +} + +define void @fn_emit_while(ptr %arg_st) { +entry: + %t0 = alloca ptr + %t2 = alloca ptr + %t4 = alloca ptr + %t6 = alloca ptr + %t13 = alloca ptr + %t20 = alloca ptr + store ptr %arg_st, ptr %t0 + %t1 = call ptr @fn_lbl(ptr @.str945) + store ptr %t1, ptr %t2 + %t3 = call ptr @fn_lbl(ptr @.str946) + store ptr %t3, ptr %t4 + %t5 = call ptr @fn_lbl(ptr @.str947) + store ptr %t5, ptr %t6 + call void @fn_emit(ptr @.str948) + %t7 = load ptr, ptr %t2 + call void @fn_emit(ptr %t7) + call void @fn_emit(ptr @.str949) + %t8 = load ptr, ptr %t2 + call void @fn_emit(ptr %t8) + call void @fn_emit(ptr @.str950) + %t9 = load ptr, ptr %t0 + %t10 = getelementptr inbounds %Str_Node, ptr %t9, i32 0, i32 4 + %t11 = load ptr, ptr %t10 + %t12 = call ptr @fn_emit_expr(ptr %t11) + store ptr %t12, ptr %t13 + %t14 = load ptr, ptr %t13 + %t15 = getelementptr inbounds %Str_Val, ptr %t14, i32 0, i32 0 + %t16 = load ptr, ptr %t15 + %t17 = call ptr @fn_sconcat(ptr %t16, ptr @.str952) + %t18 = call ptr @fn_sconcat(ptr @.str951, ptr %t17) + %t19 = call ptr @fn_emit_bind(ptr %t18) + store ptr %t19, ptr %t20 + call void @fn_emit(ptr @.str953) + %t21 = load ptr, ptr %t20 + call void @fn_emit(ptr %t21) + call void @fn_emit(ptr @.str954) + %t22 = load ptr, ptr %t4 + call void @fn_emit(ptr %t22) + call void @fn_emit(ptr @.str955) + %t23 = load ptr, ptr %t6 + call void @fn_emit(ptr %t23) + call void @fn_emit(ptr @.str956) + %t24 = load ptr, ptr %t4 + call void @fn_emit(ptr %t24) + call void @fn_emit(ptr @.str957) + store i32 0, ptr @g_g_term + %t25 = load ptr, ptr %t2 + %t26 = load ptr, ptr %t6 + call void @fn_loop_push(ptr %t25, ptr %t26) + %t27 = load ptr, ptr %t0 + %t28 = getelementptr inbounds %Str_Node, ptr %t27, i32 0, i32 5 + %t29 = load ptr, ptr %t28 + call void @fn_emit_block(ptr %t29) + call void @fn_loop_pop() + %t30 = load i32, ptr @g_g_term + %t31 = icmp eq i32 %t30, 0 + %t32 = zext i1 %t31 to i32 + %t33 = icmp ne i32 %t32, 0 + br i1 %t33, label %then0, label %ifend2 +then0: + call void @fn_emit(ptr @.str958) + %t34 = load ptr, ptr %t2 + call void @fn_emit(ptr %t34) + call void @fn_emit(ptr @.str959) + br label %ifend2 +ifend2: + %t35 = load ptr, ptr %t6 + call void @fn_emit(ptr %t35) + call void @fn_emit(ptr @.str960) + store i32 0, ptr @g_g_term + br label %ret +ret: + ret void +} + +define void @fn_emit_for(ptr %arg_st) { +entry: + %t0 = alloca ptr + %t2 = alloca ptr + %t7 = alloca ptr + %t17 = alloca ptr + %t19 = alloca ptr + %t21 = alloca ptr + %t23 = alloca ptr + %t29 = alloca ptr + %t34 = alloca ptr + %t43 = alloca ptr + %t62 = alloca ptr + %t67 = alloca ptr + store ptr %arg_st, ptr %t0 + %t1 = call ptr @fn_emit_alloca(ptr @.str961) + store ptr %t1, ptr %t2 + %t3 = load ptr, ptr %t0 + %t4 = getelementptr inbounds %Str_Node, ptr %t3, i32 0, i32 4 + %t5 = load ptr, ptr %t4 + %t6 = call ptr @fn_emit_expr(ptr %t5) + store ptr %t6, ptr %t7 + %t8 = load ptr, ptr %t7 + %t9 = getelementptr inbounds %Str_Val, ptr %t8, i32 0, i32 0 + %t10 = load ptr, ptr %t9 + %t11 = load ptr, ptr %t2 + call void @fn_store_at(ptr @.str962, ptr %t10, ptr %t11) + %t12 = load ptr, ptr %t0 + %t13 = getelementptr inbounds %Str_Node, ptr %t12, i32 0, i32 1 + %t14 = load ptr, ptr %t13 + %t15 = load ptr, ptr %t2 + call void @fn_loc_push(ptr %t14, ptr %t15, ptr @.str963) + %t16 = call ptr @fn_lbl(ptr @.str964) + store ptr %t16, ptr %t17 + %t18 = call ptr @fn_lbl(ptr @.str965) + store ptr %t18, ptr %t19 + %t20 = call ptr @fn_lbl(ptr @.str966) + store ptr %t20, ptr %t21 + %t22 = call ptr @fn_lbl(ptr @.str967) + store ptr %t22, ptr %t23 + call void @fn_emit(ptr @.str968) + %t24 = load ptr, ptr %t17 + call void @fn_emit(ptr %t24) + call void @fn_emit(ptr @.str969) + %t25 = load ptr, ptr %t17 + call void @fn_emit(ptr %t25) + call void @fn_emit(ptr @.str970) + %t26 = load ptr, ptr %t2 + %t27 = call ptr @fn_sconcat(ptr @.str971, ptr %t26) + %t28 = call ptr @fn_emit_bind(ptr %t27) + store ptr %t28, ptr %t29 + %t30 = load ptr, ptr %t0 + %t31 = getelementptr inbounds %Str_Node, ptr %t30, i32 0, i32 5 + %t32 = load ptr, ptr %t31 + %t33 = call ptr @fn_emit_expr(ptr %t32) + store ptr %t33, ptr %t34 + %t35 = load ptr, ptr %t29 + %t36 = load ptr, ptr %t34 + %t37 = getelementptr inbounds %Str_Val, ptr %t36, i32 0, i32 0 + %t38 = load ptr, ptr %t37 + %t39 = call ptr @fn_sconcat(ptr @.str973, ptr %t38) + %t40 = call ptr @fn_sconcat(ptr %t35, ptr %t39) + %t41 = call ptr @fn_sconcat(ptr @.str972, ptr %t40) + %t42 = call ptr @fn_emit_bind(ptr %t41) + store ptr %t42, ptr %t43 + call void @fn_emit(ptr @.str974) + %t44 = load ptr, ptr %t43 + call void @fn_emit(ptr %t44) + call void @fn_emit(ptr @.str975) + %t45 = load ptr, ptr %t19 + call void @fn_emit(ptr %t45) + call void @fn_emit(ptr @.str976) + %t46 = load ptr, ptr %t23 + call void @fn_emit(ptr %t46) + call void @fn_emit(ptr @.str977) + %t47 = load ptr, ptr %t19 + call void @fn_emit(ptr %t47) + call void @fn_emit(ptr @.str978) + store i32 0, ptr @g_g_term + %t48 = load ptr, ptr %t21 + %t49 = load ptr, ptr %t23 + call void @fn_loop_push(ptr %t48, ptr %t49) + %t50 = load ptr, ptr %t0 + %t51 = getelementptr inbounds %Str_Node, ptr %t50, i32 0, i32 6 + %t52 = load ptr, ptr %t51 + call void @fn_emit_block(ptr %t52) + call void @fn_loop_pop() + %t53 = load i32, ptr @g_g_term + %t54 = icmp eq i32 %t53, 0 + %t55 = zext i1 %t54 to i32 + %t56 = icmp ne i32 %t55, 0 + br i1 %t56, label %then0, label %ifend2 +then0: + call void @fn_emit(ptr @.str979) + %t57 = load ptr, ptr %t21 + call void @fn_emit(ptr %t57) + call void @fn_emit(ptr @.str980) + br label %ifend2 +ifend2: + %t58 = load ptr, ptr %t21 + call void @fn_emit(ptr %t58) + call void @fn_emit(ptr @.str981) + %t59 = load ptr, ptr %t2 + %t60 = call ptr @fn_sconcat(ptr @.str982, ptr %t59) + %t61 = call ptr @fn_emit_bind(ptr %t60) + store ptr %t61, ptr %t62 + %t63 = load ptr, ptr %t62 + %t64 = call ptr @fn_sconcat(ptr %t63, ptr @.str984) + %t65 = call ptr @fn_sconcat(ptr @.str983, ptr %t64) + %t66 = call ptr @fn_emit_bind(ptr %t65) + store ptr %t66, ptr %t67 + %t68 = load ptr, ptr %t67 + %t69 = load ptr, ptr %t2 + call void @fn_store_at(ptr @.str985, ptr %t68, ptr %t69) + call void @fn_emit(ptr @.str986) + %t70 = load ptr, ptr %t17 + call void @fn_emit(ptr %t70) + call void @fn_emit(ptr @.str987) + %t71 = load ptr, ptr %t23 + call void @fn_emit(ptr %t71) + call void @fn_emit(ptr @.str988) + store i32 0, ptr @g_g_term + br label %ret +ret: + ret void +} + +define void @fn_emit_return(ptr %arg_st) { +entry: + %t0 = alloca ptr + %t13 = alloca ptr + store ptr %arg_st, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = getelementptr inbounds %Str_Node, ptr %t1, i32 0, i32 4 + %t3 = load ptr, ptr %t2 + %t4 = icmp eq ptr %t3, null + %t5 = zext i1 %t4 to i32 + %t6 = icmp eq i32 %t5, 0 + %t7 = zext i1 %t6 to i32 + %t8 = icmp ne i32 %t7, 0 + br i1 %t8, label %then0, label %ifend2 +then0: + %t9 = load ptr, ptr %t0 + %t10 = getelementptr inbounds %Str_Node, ptr %t9, i32 0, i32 4 + %t11 = load ptr, ptr %t10 + %t12 = call ptr @fn_emit_expr(ptr %t11) + store ptr %t12, ptr %t13 + %t14 = load ptr, ptr @g_ret_ty + %t15 = call ptr @fn_llty(ptr %t14) + %t16 = load ptr, ptr %t13 + %t17 = getelementptr inbounds %Str_Val, ptr %t16, i32 0, i32 0 + %t18 = load ptr, ptr %t17 + call void @fn_store_at(ptr %t15, ptr %t18, ptr @.str989) + br label %ifend2 +ifend2: + call void @fn_emit(ptr @.str990) + store i32 1, ptr @g_g_term + br label %ret +ret: + ret void +} + +define i32 @fn_arm_is_default(ptr %arg_arm) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t1 = alloca i32 + %t11 = alloca i32 + store ptr %arg_arm, ptr %t0 + store i32 0, ptr %t1 + br label %wcond0 +wcond0: + %t2 = load i32, ptr %t1 + %t3 = load ptr, ptr %t0 + %t4 = getelementptr inbounds %Str_Node, ptr %t3, i32 0, i32 7 + %t5 = load ptr, ptr %t4 + %t6 = getelementptr inbounds %LSlice, ptr %t5, i32 0, i32 1 + %t7 = load i32, ptr %t6 + %t8 = icmp slt i32 %t2, %t7 + %t9 = zext i1 %t8 to i32 + %t10 = icmp ne i32 %t9, 0 + br i1 %t10, label %wbody1, label %wend2 +wbody1: + %t12 = load ptr, ptr %t0 + %t13 = getelementptr inbounds %Str_Node, ptr %t12, i32 0, i32 7 + %t14 = load ptr, ptr %t13 + %t15 = getelementptr inbounds %LSlice, ptr %t14, i32 0, i32 0 + %t16 = load ptr, ptr %t15 + %t17 = load i32, ptr %t1 + %t18 = getelementptr inbounds ptr, ptr %t16, i32 %t17 + %t19 = load ptr, ptr %t18 + %t20 = getelementptr inbounds %Str_Node, ptr %t19, i32 0, i32 0 + %t21 = load i32, ptr %t20 + %t22 = icmp eq i32 %t21, 33 + %t23 = zext i1 %t22 to i32 + %t24 = icmp ne i32 %t23, 0 + %t25 = zext i1 %t24 to i32 + store i32 %t25, ptr %t11 + br i1 %t24, label %sc3, label %scend4 +sc3: + %t26 = load ptr, ptr %t0 + %t27 = getelementptr inbounds %Str_Node, ptr %t26, i32 0, i32 7 + %t28 = load ptr, ptr %t27 + %t29 = getelementptr inbounds %LSlice, ptr %t28, i32 0, i32 0 + %t30 = load ptr, ptr %t29 + %t31 = load i32, ptr %t1 + %t32 = getelementptr inbounds ptr, ptr %t30, i32 %t31 + %t33 = load ptr, ptr %t32 + %t34 = getelementptr inbounds %Str_Node, ptr %t33, i32 0, i32 1 + %t35 = load ptr, ptr %t34 + %t36 = call i32 @fn_streq(ptr %t35, ptr @.str991) + %t37 = icmp ne i32 %t36, 0 + %t38 = zext i1 %t37 to i32 + store i32 %t38, ptr %t11 + br label %scend4 +scend4: + %t39 = load i32, ptr %t11 + %t40 = icmp ne i32 %t39, 0 + br i1 %t40, label %then5, label %ifend7 +then5: + store i32 1, ptr %retval + br label %ret +ifend7: + %t41 = load i32, ptr %t1 + %t42 = add i32 %t41, 1 + store i32 %t42, ptr %t1 + br label %wcond0 +wend2: + store i32 0, ptr %retval + br label %ret +ret: + %t43 = load i32, ptr %retval + ret i32 %t43 +} + +define void @fn_emit_match(ptr %arg_st) { +entry: + %t0 = alloca ptr + %t5 = alloca ptr + %t7 = alloca ptr + %t8 = alloca ptr + %t9 = alloca i32 + %t27 = alloca ptr + %t32 = alloca ptr + %t33 = alloca i32 + %t34 = alloca i32 + %t53 = alloca ptr + %t64 = alloca ptr + %t77 = alloca ptr + %t79 = alloca ptr + store ptr %arg_st, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = getelementptr inbounds %Str_Node, ptr %t1, i32 0, i32 4 + %t3 = load ptr, ptr %t2 + %t4 = call ptr @fn_emit_expr(ptr %t3) + store ptr %t4, ptr %t5 + %t6 = call ptr @fn_lbl(ptr @.str992) + store ptr %t6, ptr %t7 + store ptr null, ptr %t8 + store i32 0, ptr %t9 + br label %wcond0 +wcond0: + %t10 = load i32, ptr %t9 + %t11 = load ptr, ptr %t0 + %t12 = getelementptr inbounds %Str_Node, ptr %t11, i32 0, i32 7 + %t13 = load ptr, ptr %t12 + %t14 = getelementptr inbounds %LSlice, ptr %t13, i32 0, i32 1 + %t15 = load i32, ptr %t14 + %t16 = icmp slt i32 %t10, %t15 + %t17 = zext i1 %t16 to i32 + %t18 = icmp ne i32 %t17, 0 + br i1 %t18, label %wbody1, label %wend2 +wbody1: + %t19 = load ptr, ptr %t0 + %t20 = getelementptr inbounds %Str_Node, ptr %t19, i32 0, i32 7 + %t21 = load ptr, ptr %t20 + %t22 = getelementptr inbounds %LSlice, ptr %t21, i32 0, i32 0 + %t23 = load ptr, ptr %t22 + %t24 = load i32, ptr %t9 + %t25 = getelementptr inbounds ptr, ptr %t23, i32 %t24 + %t26 = load ptr, ptr %t25 + store ptr %t26, ptr %t27 + %t28 = load ptr, ptr %t27 + %t29 = call i32 @fn_arm_is_default(ptr %t28) + %t30 = icmp ne i32 %t29, 0 + br i1 %t30, label %then3, label %else4 +then3: + %t31 = load ptr, ptr %t27 + store ptr %t31, ptr %t8 + br label %ifend5 +else4: + store ptr @.str993, ptr %t32 + store i32 1, ptr %t33 + store i32 0, ptr %t34 + br label %wcond6 +wcond6: + %t35 = load i32, ptr %t34 + %t36 = load ptr, ptr %t27 + %t37 = getelementptr inbounds %Str_Node, ptr %t36, i32 0, i32 7 + %t38 = load ptr, ptr %t37 + %t39 = getelementptr inbounds %LSlice, ptr %t38, i32 0, i32 1 + %t40 = load i32, ptr %t39 + %t41 = icmp slt i32 %t35, %t40 + %t42 = zext i1 %t41 to i32 + %t43 = icmp ne i32 %t42, 0 + br i1 %t43, label %wbody7, label %wend8 +wbody7: + %t44 = load ptr, ptr %t27 + %t45 = getelementptr inbounds %Str_Node, ptr %t44, i32 0, i32 7 + %t46 = load ptr, ptr %t45 + %t47 = getelementptr inbounds %LSlice, ptr %t46, i32 0, i32 0 + %t48 = load ptr, ptr %t47 + %t49 = load i32, ptr %t34 + %t50 = getelementptr inbounds ptr, ptr %t48, i32 %t49 + %t51 = load ptr, ptr %t50 + %t52 = call ptr @fn_emit_expr(ptr %t51) + store ptr %t52, ptr %t53 + %t54 = load ptr, ptr %t5 + %t55 = getelementptr inbounds %Str_Val, ptr %t54, i32 0, i32 0 + %t56 = load ptr, ptr %t55 + %t57 = load ptr, ptr %t53 + %t58 = getelementptr inbounds %Str_Val, ptr %t57, i32 0, i32 0 + %t59 = load ptr, ptr %t58 + %t60 = call ptr @fn_sconcat(ptr @.str995, ptr %t59) + %t61 = call ptr @fn_sconcat(ptr %t56, ptr %t60) + %t62 = call ptr @fn_sconcat(ptr @.str994, ptr %t61) + %t63 = call ptr @fn_emit_bind(ptr %t62) + store ptr %t63, ptr %t64 + %t65 = load i32, ptr %t33 + %t66 = icmp ne i32 %t65, 0 + br i1 %t66, label %then9, label %else10 +then9: + %t67 = load ptr, ptr %t64 + store ptr %t67, ptr %t32 + store i32 0, ptr %t33 + br label %ifend11 +else10: + %t68 = load ptr, ptr %t32 + %t69 = load ptr, ptr %t64 + %t70 = call ptr @fn_sconcat(ptr @.str997, ptr %t69) + %t71 = call ptr @fn_sconcat(ptr %t68, ptr %t70) + %t72 = call ptr @fn_sconcat(ptr @.str996, ptr %t71) + %t73 = call ptr @fn_emit_bind(ptr %t72) + store ptr %t73, ptr %t32 + br label %ifend11 +ifend11: + %t74 = load i32, ptr %t34 + %t75 = add i32 %t74, 1 + store i32 %t75, ptr %t34 + br label %wcond6 +wend8: + %t76 = call ptr @fn_lbl(ptr @.str998) + store ptr %t76, ptr %t77 + %t78 = call ptr @fn_lbl(ptr @.str999) + store ptr %t78, ptr %t79 + call void @fn_emit(ptr @.str1000) + %t80 = load ptr, ptr %t32 + call void @fn_emit(ptr %t80) + call void @fn_emit(ptr @.str1001) + %t81 = load ptr, ptr %t77 + call void @fn_emit(ptr %t81) + call void @fn_emit(ptr @.str1002) + %t82 = load ptr, ptr %t79 + call void @fn_emit(ptr %t82) + call void @fn_emit(ptr @.str1003) + %t83 = load ptr, ptr %t77 + call void @fn_emit(ptr %t83) + call void @fn_emit(ptr @.str1004) + store i32 0, ptr @g_g_term + %t84 = load ptr, ptr %t27 + %t85 = getelementptr inbounds %Str_Node, ptr %t84, i32 0, i32 4 + %t86 = load ptr, ptr %t85 + call void @fn_emit_block(ptr %t86) + %t87 = load i32, ptr @g_g_term + %t88 = icmp eq i32 %t87, 0 + %t89 = zext i1 %t88 to i32 + %t90 = icmp ne i32 %t89, 0 + br i1 %t90, label %then12, label %ifend14 +then12: + call void @fn_emit(ptr @.str1005) + %t91 = load ptr, ptr %t7 + call void @fn_emit(ptr %t91) + call void @fn_emit(ptr @.str1006) + br label %ifend14 +ifend14: + %t92 = load ptr, ptr %t79 + call void @fn_emit(ptr %t92) + call void @fn_emit(ptr @.str1007) + store i32 0, ptr @g_g_term + br label %ifend5 +ifend5: + %t93 = load i32, ptr %t9 + %t94 = add i32 %t93, 1 + store i32 %t94, ptr %t9 + br label %wcond0 +wend2: + %t95 = load ptr, ptr %t8 + %t96 = icmp eq ptr %t95, null + %t97 = zext i1 %t96 to i32 + %t98 = icmp eq i32 %t97, 0 + %t99 = zext i1 %t98 to i32 + %t100 = icmp ne i32 %t99, 0 + br i1 %t100, label %then15, label %ifend17 +then15: + %t101 = load ptr, ptr %t8 + %t102 = getelementptr inbounds %Str_Node, ptr %t101, i32 0, i32 4 + %t103 = load ptr, ptr %t102 + call void @fn_emit_block(ptr %t103) + br label %ifend17 +ifend17: + %t104 = load i32, ptr @g_g_term + %t105 = icmp eq i32 %t104, 0 + %t106 = zext i1 %t105 to i32 + %t107 = icmp ne i32 %t106, 0 + br i1 %t107, label %then18, label %ifend20 +then18: + call void @fn_emit(ptr @.str1008) + %t108 = load ptr, ptr %t7 + call void @fn_emit(ptr %t108) + call void @fn_emit(ptr @.str1009) + br label %ifend20 +ifend20: + %t109 = load ptr, ptr %t7 + call void @fn_emit(ptr %t109) + call void @fn_emit(ptr @.str1010) + store i32 0, ptr @g_g_term + br label %ret +ret: + ret void +} + +define void @fn_emit_stmt(ptr %arg_st) { +entry: + %t0 = alloca ptr + %t10 = alloca ptr + %t19 = alloca ptr + %t26 = alloca ptr + %t41 = alloca ptr + %t48 = alloca ptr + %t61 = alloca ptr + %t186 = alloca ptr + store ptr %arg_st, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = getelementptr inbounds %Str_Node, ptr %t1, i32 0, i32 0 + %t3 = load i32, ptr %t2 + %t4 = icmp eq i32 %t3, 10 + %t5 = zext i1 %t4 to i32 + %t6 = icmp ne i32 %t5, 0 + br i1 %t6, label %then0, label %ifend2 +then0: + %t7 = load ptr, ptr %t0 + %t8 = getelementptr inbounds %Str_Node, ptr %t7, i32 0, i32 3 + %t9 = load ptr, ptr %t8 + store ptr %t9, ptr %t10 + %t11 = load ptr, ptr %t10 + %t12 = icmp eq ptr %t11, null + %t13 = zext i1 %t12 to i32 + %t14 = icmp ne i32 %t13, 0 + br i1 %t14, label %then3, label %ifend5 +then3: + %t15 = load ptr, ptr %t0 + %t16 = getelementptr inbounds %Str_Node, ptr %t15, i32 0, i32 4 + %t17 = load ptr, ptr %t16 + %t18 = call ptr @fn_emit_expr(ptr %t17) + store ptr %t18, ptr %t19 + %t20 = load ptr, ptr %t19 + %t21 = getelementptr inbounds %Str_Val, ptr %t20, i32 0, i32 1 + %t22 = load ptr, ptr %t21 + store ptr %t22, ptr %t10 + %t23 = load ptr, ptr %t10 + %t24 = call ptr @fn_llty(ptr %t23) + %t25 = call ptr @fn_emit_alloca(ptr %t24) + store ptr %t25, ptr %t26 + %t27 = load ptr, ptr %t10 + %t28 = call ptr @fn_llty(ptr %t27) + %t29 = load ptr, ptr %t19 + %t30 = getelementptr inbounds %Str_Val, ptr %t29, i32 0, i32 0 + %t31 = load ptr, ptr %t30 + %t32 = load ptr, ptr %t26 + call void @fn_store_at(ptr %t28, ptr %t31, ptr %t32) + %t33 = load ptr, ptr %t0 + %t34 = getelementptr inbounds %Str_Node, ptr %t33, i32 0, i32 1 + %t35 = load ptr, ptr %t34 + %t36 = load ptr, ptr %t26 + %t37 = load ptr, ptr %t10 + call void @fn_loc_push(ptr %t35, ptr %t36, ptr %t37) + br label %ret +ifend5: + %t38 = load ptr, ptr %t10 + %t39 = call ptr @fn_llty(ptr %t38) + %t40 = call ptr @fn_emit_alloca(ptr %t39) + store ptr %t40, ptr %t41 + %t42 = load ptr, ptr %t0 + %t43 = getelementptr inbounds %Str_Node, ptr %t42, i32 0, i32 4 + %t44 = load ptr, ptr %t43 + %t45 = icmp eq ptr %t44, null + %t46 = zext i1 %t45 to i32 + %t47 = icmp ne i32 %t46, 0 + br i1 %t47, label %then6, label %else7 +then6: + store ptr @.str1011, ptr %t48 + %t49 = load ptr, ptr %t10 + %t50 = call ptr @fn_llty(ptr %t49) + %t51 = call i32 @fn_streq(ptr %t50, ptr @.str1012) + %t52 = icmp ne i32 %t51, 0 + br i1 %t52, label %then9, label %ifend11 +then9: + store ptr @.str1013, ptr %t48 + br label %ifend11 +ifend11: + %t53 = load ptr, ptr %t10 + %t54 = call ptr @fn_llty(ptr %t53) + %t55 = load ptr, ptr %t48 + %t56 = load ptr, ptr %t41 + call void @fn_store_at(ptr %t54, ptr %t55, ptr %t56) + br label %ifend8 +else7: + %t57 = load ptr, ptr %t0 + %t58 = getelementptr inbounds %Str_Node, ptr %t57, i32 0, i32 4 + %t59 = load ptr, ptr %t58 + %t60 = call ptr @fn_emit_expr(ptr %t59) + store ptr %t60, ptr %t61 + %t62 = load ptr, ptr %t10 + %t63 = call ptr @fn_llty(ptr %t62) + %t64 = load ptr, ptr %t61 + %t65 = getelementptr inbounds %Str_Val, ptr %t64, i32 0, i32 0 + %t66 = load ptr, ptr %t65 + %t67 = load ptr, ptr %t41 + call void @fn_store_at(ptr %t63, ptr %t66, ptr %t67) + br label %ifend8 +ifend8: + %t68 = load ptr, ptr %t0 + %t69 = getelementptr inbounds %Str_Node, ptr %t68, i32 0, i32 1 + %t70 = load ptr, ptr %t69 + %t71 = load ptr, ptr %t41 + %t72 = load ptr, ptr %t10 + call void @fn_loc_push(ptr %t70, ptr %t71, ptr %t72) + br label %ret +ifend2: + %t73 = load ptr, ptr %t0 + %t74 = getelementptr inbounds %Str_Node, ptr %t73, i32 0, i32 0 + %t75 = load i32, ptr %t74 + %t76 = icmp eq i32 %t75, 11 + %t77 = zext i1 %t76 to i32 + %t78 = icmp ne i32 %t77, 0 + br i1 %t78, label %then12, label %ifend14 +then12: + %t79 = load ptr, ptr %t0 + call void @fn_emit_assign(ptr %t79) + br label %ret +ifend14: + %t80 = load ptr, ptr %t0 + %t81 = getelementptr inbounds %Str_Node, ptr %t80, i32 0, i32 0 + %t82 = load i32, ptr %t81 + %t83 = icmp eq i32 %t82, 12 + %t84 = zext i1 %t83 to i32 + %t85 = icmp ne i32 %t84, 0 + br i1 %t85, label %then15, label %ifend17 +then15: + %t86 = load ptr, ptr %t0 + call void @fn_emit_if(ptr %t86) + br label %ret +ifend17: + %t87 = load ptr, ptr %t0 + %t88 = getelementptr inbounds %Str_Node, ptr %t87, i32 0, i32 0 + %t89 = load i32, ptr %t88 + %t90 = icmp eq i32 %t89, 13 + %t91 = zext i1 %t90 to i32 + %t92 = icmp ne i32 %t91, 0 + br i1 %t92, label %then18, label %ifend20 +then18: + %t93 = load ptr, ptr %t0 + call void @fn_emit_while(ptr %t93) + br label %ret +ifend20: + %t94 = load ptr, ptr %t0 + %t95 = getelementptr inbounds %Str_Node, ptr %t94, i32 0, i32 0 + %t96 = load i32, ptr %t95 + %t97 = icmp eq i32 %t96, 14 + %t98 = zext i1 %t97 to i32 + %t99 = icmp ne i32 %t98, 0 + br i1 %t99, label %then21, label %ifend23 +then21: + %t100 = load ptr, ptr %t0 + call void @fn_emit_for(ptr %t100) + br label %ret +ifend23: + %t101 = load ptr, ptr %t0 + %t102 = getelementptr inbounds %Str_Node, ptr %t101, i32 0, i32 0 + %t103 = load i32, ptr %t102 + %t104 = icmp eq i32 %t103, 15 + %t105 = zext i1 %t104 to i32 + %t106 = icmp ne i32 %t105, 0 + br i1 %t106, label %then24, label %ifend26 +then24: + %t107 = load ptr, ptr %t0 + call void @fn_emit_return(ptr %t107) + br label %ret +ifend26: + %t108 = load ptr, ptr %t0 + %t109 = getelementptr inbounds %Str_Node, ptr %t108, i32 0, i32 0 + %t110 = load i32, ptr %t109 + %t111 = icmp eq i32 %t110, 17 + %t112 = zext i1 %t111 to i32 + %t113 = icmp ne i32 %t112, 0 + br i1 %t113, label %then27, label %ifend29 +then27: + call void @fn_emit(ptr @.str1014) + %t114 = load ptr, ptr @g_brk_lbl + %t115 = getelementptr inbounds %LSlice, ptr %t114, i32 0, i32 0 + %t116 = load ptr, ptr %t115 + %t117 = load i32, ptr @g_nloop + %t118 = sub i32 %t117, 1 + %t119 = getelementptr inbounds ptr, ptr %t116, i32 %t118 + %t120 = load ptr, ptr %t119 + call void @fn_emit(ptr %t120) + call void @fn_emit(ptr @.str1015) + store i32 1, ptr @g_g_term + br label %ret +ifend29: + %t121 = load ptr, ptr %t0 + %t122 = getelementptr inbounds %Str_Node, ptr %t121, i32 0, i32 0 + %t123 = load i32, ptr %t122 + %t124 = icmp eq i32 %t123, 18 + %t125 = zext i1 %t124 to i32 + %t126 = icmp ne i32 %t125, 0 + br i1 %t126, label %then30, label %ifend32 +then30: + call void @fn_emit(ptr @.str1016) + %t127 = load ptr, ptr @g_cnt_lbl + %t128 = getelementptr inbounds %LSlice, ptr %t127, i32 0, i32 0 + %t129 = load ptr, ptr %t128 + %t130 = load i32, ptr @g_nloop + %t131 = sub i32 %t130, 1 + %t132 = getelementptr inbounds ptr, ptr %t129, i32 %t131 + %t133 = load ptr, ptr %t132 + call void @fn_emit(ptr %t133) + call void @fn_emit(ptr @.str1017) + store i32 1, ptr @g_g_term + br label %ret +ifend32: + %t134 = load ptr, ptr %t0 + %t135 = getelementptr inbounds %Str_Node, ptr %t134, i32 0, i32 0 + %t136 = load i32, ptr %t135 + %t137 = icmp eq i32 %t136, 19 + %t138 = zext i1 %t137 to i32 + %t139 = icmp ne i32 %t138, 0 + br i1 %t139, label %then33, label %ifend35 +then33: + %t140 = load ptr, ptr %t0 + call void @fn_emit_match(ptr %t140) + br label %ret +ifend35: + %t141 = load ptr, ptr %t0 + %t142 = getelementptr inbounds %Str_Node, ptr %t141, i32 0, i32 0 + %t143 = load i32, ptr %t142 + %t144 = icmp eq i32 %t143, 21 + %t145 = zext i1 %t144 to i32 + %t146 = icmp ne i32 %t145, 0 + br i1 %t146, label %then36, label %ifend38 +then36: + %t147 = load ptr, ptr %t0 + call void @fn_emit_query(ptr %t147) + br label %ret +ifend38: + %t148 = load ptr, ptr %t0 + %t149 = getelementptr inbounds %Str_Node, ptr %t148, i32 0, i32 0 + %t150 = load i32, ptr %t149 + %t151 = icmp eq i32 %t150, 22 + %t152 = zext i1 %t151 to i32 + %t153 = icmp ne i32 %t152, 0 + br i1 %t153, label %then39, label %ifend41 +then39: + %t154 = load ptr, ptr %t0 + call void @fn_emit_spawn(ptr %t154) + br label %ret +ifend41: + %t155 = load ptr, ptr %t0 + %t156 = getelementptr inbounds %Str_Node, ptr %t155, i32 0, i32 0 + %t157 = load i32, ptr %t156 + %t158 = icmp eq i32 %t157, 23 + %t159 = zext i1 %t158 to i32 + %t160 = icmp ne i32 %t159, 0 + br i1 %t160, label %then42, label %ifend44 +then42: + %t161 = load ptr, ptr %t0 + call void @fn_emit_despawn(ptr %t161) + br label %ret +ifend44: + %t162 = load ptr, ptr %t0 + %t163 = getelementptr inbounds %Str_Node, ptr %t162, i32 0, i32 0 + %t164 = load i32, ptr %t163 + %t165 = icmp eq i32 %t164, 24 + %t166 = zext i1 %t165 to i32 + %t167 = icmp ne i32 %t166, 0 + br i1 %t167, label %then45, label %ifend47 +then45: + %t168 = load ptr, ptr %t0 + call void @fn_emit_machine(ptr %t168) + br label %ret +ifend47: + %t169 = load ptr, ptr %t0 + %t170 = getelementptr inbounds %Str_Node, ptr %t169, i32 0, i32 0 + %t171 = load i32, ptr %t170 + %t172 = icmp eq i32 %t171, 26 + %t173 = zext i1 %t172 to i32 + %t174 = icmp ne i32 %t173, 0 + br i1 %t174, label %then48, label %ifend50 +then48: + %t175 = load ptr, ptr %t0 + call void @fn_emit_become(ptr %t175) + br label %ret +ifend50: + %t176 = load ptr, ptr %t0 + %t177 = getelementptr inbounds %Str_Node, ptr %t176, i32 0, i32 0 + %t178 = load i32, ptr %t177 + %t179 = icmp eq i32 %t178, 16 + %t180 = zext i1 %t179 to i32 + %t181 = icmp ne i32 %t180, 0 + br i1 %t181, label %then51, label %ifend53 +then51: + %t182 = load ptr, ptr %t0 + %t183 = getelementptr inbounds %Str_Node, ptr %t182, i32 0, i32 4 + %t184 = load ptr, ptr %t183 + %t185 = call ptr @fn_emit_expr(ptr %t184) + store ptr %t185, ptr %t186 + br label %ret +ifend53: + call void @fn_perr(ptr @.str1018) + br label %ret +ret: + ret void +} + +define void @fn_loop_push(ptr %arg_cont, ptr %arg_brk) { +entry: + %t0 = alloca ptr + %t1 = alloca ptr + store ptr %arg_cont, ptr %t0 + store ptr %arg_brk, ptr %t1 + %t2 = load i32, ptr @g_nloop + %t3 = load ptr, ptr @g_cnt_lbl + %t4 = getelementptr inbounds %LSlice, ptr %t3, i32 0, i32 1 + %t5 = load i32, ptr %t4 + %t6 = icmp slt i32 %t2, %t5 + %t7 = zext i1 %t6 to i32 + %t8 = icmp ne i32 %t7, 0 + br i1 %t8, label %then0, label %else1 +then0: + %t9 = load ptr, ptr @g_cnt_lbl + %t10 = getelementptr inbounds %LSlice, ptr %t9, i32 0, i32 0 + %t11 = load ptr, ptr %t10 + %t12 = load i32, ptr @g_nloop + %t13 = getelementptr inbounds ptr, ptr %t11, i32 %t12 + %t14 = load ptr, ptr %t0 + store ptr %t14, ptr %t13 + %t15 = load ptr, ptr @g_brk_lbl + %t16 = getelementptr inbounds %LSlice, ptr %t15, i32 0, i32 0 + %t17 = load ptr, ptr %t16 + %t18 = load i32, ptr @g_nloop + %t19 = getelementptr inbounds ptr, ptr %t17, i32 %t18 + %t20 = load ptr, ptr %t1 + store ptr %t20, ptr %t19 + br label %ifend2 +else1: + %t21 = load ptr, ptr @g_cnt_lbl + %t22 = getelementptr inbounds %LSlice, ptr %t21, i32 0, i32 1 + %t23 = getelementptr inbounds %LSlice, ptr %t21, i32 0, i32 2 + %t24 = getelementptr inbounds %LSlice, ptr %t21, i32 0, i32 0 + %t25 = load i32, ptr %t22 + %t26 = load i32, ptr %t23 + %t27 = icmp sge i32 %t25, %t26 + br i1 %t27, label %grow3, label %put4 +grow3: + %t28 = mul i32 %t26, 2 + %t29 = icmp eq i32 %t26, 0 + %t30 = select i1 %t29, i32 8, i32 %t28 + %t31 = getelementptr ptr, ptr null, i32 1 + %t32 = ptrtoint ptr %t31 to i64 + %t33 = zext i32 %t30 to i64 + %t34 = mul i64 %t33, %t32 + %t35 = load ptr, ptr %t24 + %t36 = call ptr @realloc(ptr %t35, i64 %t34) + store ptr %t36, ptr %t24 + store i32 %t30, ptr %t23 + br label %put4 +put4: + %t37 = load ptr, ptr %t0 + %t38 = load ptr, ptr %t24 + %t39 = getelementptr inbounds ptr, ptr %t38, i32 %t25 + store ptr %t37, ptr %t39 + %t40 = add i32 %t25, 1 + store i32 %t40, ptr %t22 + %t41 = load ptr, ptr @g_brk_lbl + %t42 = getelementptr inbounds %LSlice, ptr %t41, i32 0, i32 1 + %t43 = getelementptr inbounds %LSlice, ptr %t41, i32 0, i32 2 + %t44 = getelementptr inbounds %LSlice, ptr %t41, i32 0, i32 0 + %t45 = load i32, ptr %t42 + %t46 = load i32, ptr %t43 + %t47 = icmp sge i32 %t45, %t46 + br i1 %t47, label %grow5, label %put6 +grow5: + %t48 = mul i32 %t46, 2 + %t49 = icmp eq i32 %t46, 0 + %t50 = select i1 %t49, i32 8, i32 %t48 + %t51 = getelementptr ptr, ptr null, i32 1 + %t52 = ptrtoint ptr %t51 to i64 + %t53 = zext i32 %t50 to i64 + %t54 = mul i64 %t53, %t52 + %t55 = load ptr, ptr %t44 + %t56 = call ptr @realloc(ptr %t55, i64 %t54) + store ptr %t56, ptr %t44 + store i32 %t50, ptr %t43 + br label %put6 +put6: + %t57 = load ptr, ptr %t1 + %t58 = load ptr, ptr %t44 + %t59 = getelementptr inbounds ptr, ptr %t58, i32 %t45 + store ptr %t57, ptr %t59 + %t60 = add i32 %t45, 1 + store i32 %t60, ptr %t42 + br label %ifend2 +ifend2: + %t61 = load i32, ptr @g_nloop + %t62 = add i32 %t61, 1 + store i32 %t62, ptr @g_nloop + br label %ret +ret: + ret void +} + +define void @fn_loop_pop() { +entry: + %t0 = load i32, ptr @g_nloop + %t1 = sub i32 %t0, 1 + store i32 %t1, ptr @g_nloop + br label %ret +ret: + ret void +} + +define i32 @fn_has_ecs() { +entry: + %retval = alloca i32 + %t0 = alloca i32 + %t16 = alloca i32 + %t17 = alloca i32 + store i32 0, ptr %t0 + br label %wcond0 +wcond0: + %t1 = load i32, ptr %t0 + %t2 = load ptr, ptr @g_prog + %t3 = getelementptr inbounds %LSlice, ptr %t2, i32 0, i32 1 + %t4 = load i32, ptr %t3 + %t5 = icmp slt i32 %t1, %t4 + %t6 = zext i1 %t5 to i32 + %t7 = icmp ne i32 %t6, 0 + br i1 %t7, label %wbody1, label %wend2 +wbody1: + %t8 = load ptr, ptr @g_prog + %t9 = getelementptr inbounds %LSlice, ptr %t8, i32 0, i32 0 + %t10 = load ptr, ptr %t9 + %t11 = load i32, ptr %t0 + %t12 = getelementptr inbounds ptr, ptr %t10, i32 %t11 + %t13 = load ptr, ptr %t12 + %t14 = getelementptr inbounds %Str_Node, ptr %t13, i32 0, i32 0 + %t15 = load i32, ptr %t14 + store i32 %t15, ptr %t16 + %t18 = load i32, ptr %t16 + %t19 = icmp eq i32 %t18, 8 + %t20 = zext i1 %t19 to i32 + %t21 = icmp ne i32 %t20, 0 + %t22 = zext i1 %t21 to i32 + store i32 %t22, ptr %t17 + br i1 %t21, label %scend4, label %sc3 +sc3: + %t23 = load i32, ptr %t16 + %t24 = icmp eq i32 %t23, 9 + %t25 = zext i1 %t24 to i32 + %t26 = icmp ne i32 %t25, 0 + %t27 = zext i1 %t26 to i32 + store i32 %t27, ptr %t17 + br label %scend4 +scend4: + %t28 = load i32, ptr %t17 + %t29 = icmp ne i32 %t28, 0 + br i1 %t29, label %then5, label %ifend7 +then5: + store i32 1, ptr %retval + br label %ret +ifend7: + %t30 = load i32, ptr %t0 + %t31 = add i32 %t30, 1 + store i32 %t31, ptr %t0 + br label %wcond0 +wend2: + store i32 0, ptr %retval + br label %ret +ret: + %t32 = load i32, ptr %retval + ret i32 %t32 +} + +define i32 @fn_has_systems() { +entry: + %retval = alloca i32 + %t0 = alloca i32 + store i32 0, ptr %t0 + br label %wcond0 +wcond0: + %t1 = load i32, ptr %t0 + %t2 = load ptr, ptr @g_prog + %t3 = getelementptr inbounds %LSlice, ptr %t2, i32 0, i32 1 + %t4 = load i32, ptr %t3 + %t5 = icmp slt i32 %t1, %t4 + %t6 = zext i1 %t5 to i32 + %t7 = icmp ne i32 %t6, 0 + br i1 %t7, label %wbody1, label %wend2 +wbody1: + %t8 = load ptr, ptr @g_prog + %t9 = getelementptr inbounds %LSlice, ptr %t8, i32 0, i32 0 + %t10 = load ptr, ptr %t9 + %t11 = load i32, ptr %t0 + %t12 = getelementptr inbounds ptr, ptr %t10, i32 %t11 + %t13 = load ptr, ptr %t12 + %t14 = getelementptr inbounds %Str_Node, ptr %t13, i32 0, i32 0 + %t15 = load i32, ptr %t14 + %t16 = icmp eq i32 %t15, 9 + %t17 = zext i1 %t16 to i32 + %t18 = icmp ne i32 %t17, 0 + br i1 %t18, label %then3, label %ifend5 +then3: + store i32 1, ptr %retval + br label %ret +ifend5: + %t19 = load i32, ptr %t0 + %t20 = add i32 %t19, 1 + store i32 %t20, ptr %t0 + br label %wcond0 +wend2: + store i32 0, ptr %retval + br label %ret +ret: + %t21 = load i32, ptr %retval + ret i32 %t21 +} + +define void @fn_emit_ecs_storage() { +entry: + %t1 = alloca ptr + %t11 = alloca i32 + %t25 = alloca ptr + %t45 = alloca i32 + call void @fn_emith(ptr @.str1019) + call void @fn_emith(ptr @.str1020) + call void @fn_emith(ptr @.str1021) + %t0 = call ptr @fn_itoa(i32 1024) + store ptr %t0, ptr %t1 + %t2 = load ptr, ptr %t1 + %t3 = call ptr @fn_sconcat(ptr %t2, ptr @.str1023) + %t4 = call ptr @fn_sconcat(ptr @.str1022, ptr %t3) + call void @fn_emith(ptr %t4) + %t5 = load ptr, ptr %t1 + %t6 = call ptr @fn_sconcat(ptr %t5, ptr @.str1025) + %t7 = call ptr @fn_sconcat(ptr @.str1024, ptr %t6) + call void @fn_emith(ptr %t7) + %t8 = load ptr, ptr %t1 + %t9 = call ptr @fn_sconcat(ptr %t8, ptr @.str1027) + %t10 = call ptr @fn_sconcat(ptr @.str1026, ptr %t9) + call void @fn_emith(ptr %t10) + call void @fn_emith(ptr @.str1028) + store i32 0, ptr %t11 + br label %wcond0 +wcond0: + %t12 = load i32, ptr %t11 + %t13 = load ptr, ptr @g_prog + %t14 = getelementptr inbounds %LSlice, ptr %t13, i32 0, i32 1 + %t15 = load i32, ptr %t14 + %t16 = icmp slt i32 %t12, %t15 + %t17 = zext i1 %t16 to i32 + %t18 = icmp ne i32 %t17, 0 + br i1 %t18, label %wbody1, label %wend2 +wbody1: + %t19 = load ptr, ptr @g_prog + %t20 = getelementptr inbounds %LSlice, ptr %t19, i32 0, i32 0 + %t21 = load ptr, ptr %t20 + %t22 = load i32, ptr %t11 + %t23 = getelementptr inbounds ptr, ptr %t21, i32 %t22 + %t24 = load ptr, ptr %t23 + store ptr %t24, ptr %t25 + %t26 = load ptr, ptr %t25 + %t27 = getelementptr inbounds %Str_Node, ptr %t26, i32 0, i32 0 + %t28 = load i32, ptr %t27 + %t29 = icmp eq i32 %t28, 8 + %t30 = zext i1 %t29 to i32 + %t31 = icmp ne i32 %t30, 0 + br i1 %t31, label %then3, label %ifend5 +then3: + %t32 = load ptr, ptr %t25 + %t33 = getelementptr inbounds %Str_Node, ptr %t32, i32 0, i32 1 + %t34 = load ptr, ptr %t33 + %t35 = call ptr @fn_sconcat(ptr %t34, ptr @.str1030) + %t36 = call ptr @fn_sconcat(ptr @.str1029, ptr %t35) + call void @fn_emith(ptr %t36) + %t37 = load ptr, ptr %t25 + %t38 = getelementptr inbounds %Str_Node, ptr %t37, i32 0, i32 7 + %t39 = load ptr, ptr %t38 + %t40 = getelementptr inbounds %LSlice, ptr %t39, i32 0, i32 1 + %t41 = load i32, ptr %t40 + %t42 = icmp eq i32 %t41, 0 + %t43 = zext i1 %t42 to i32 + %t44 = icmp ne i32 %t43, 0 + br i1 %t44, label %then6, label %ifend8 +then6: + call void @fn_emith(ptr @.str1031) + br label %ifend8 +ifend8: + store i32 0, ptr %t45 + br label %wcond9 +wcond9: + %t46 = load i32, ptr %t45 + %t47 = load ptr, ptr %t25 + %t48 = getelementptr inbounds %Str_Node, ptr %t47, i32 0, i32 7 + %t49 = load ptr, ptr %t48 + %t50 = getelementptr inbounds %LSlice, ptr %t49, i32 0, i32 1 + %t51 = load i32, ptr %t50 + %t52 = icmp slt i32 %t46, %t51 + %t53 = zext i1 %t52 to i32 + %t54 = icmp ne i32 %t53, 0 + br i1 %t54, label %wbody10, label %wend11 +wbody10: + %t55 = load i32, ptr %t45 + %t56 = icmp sgt i32 %t55, 0 + %t57 = zext i1 %t56 to i32 + %t58 = icmp ne i32 %t57, 0 + br i1 %t58, label %then12, label %ifend14 +then12: + call void @fn_emith(ptr @.str1032) + br label %ifend14 +ifend14: + %t59 = load ptr, ptr %t25 + %t60 = getelementptr inbounds %Str_Node, ptr %t59, i32 0, i32 7 + %t61 = load ptr, ptr %t60 + %t62 = getelementptr inbounds %LSlice, ptr %t61, i32 0, i32 0 + %t63 = load ptr, ptr %t62 + %t64 = load i32, ptr %t45 + %t65 = getelementptr inbounds ptr, ptr %t63, i32 %t64 + %t66 = load ptr, ptr %t65 + %t67 = getelementptr inbounds %Str_Node, ptr %t66, i32 0, i32 3 + %t68 = load ptr, ptr %t67 + %t69 = call ptr @fn_llty(ptr %t68) + call void @fn_emith(ptr %t69) + %t70 = load i32, ptr %t45 + %t71 = add i32 %t70, 1 + store i32 %t71, ptr %t45 + br label %wcond9 +wend11: + call void @fn_emith(ptr @.str1033) + %t72 = load ptr, ptr %t25 + %t73 = getelementptr inbounds %Str_Node, ptr %t72, i32 0, i32 1 + %t74 = load ptr, ptr %t73 + %t75 = load ptr, ptr %t1 + %t76 = load ptr, ptr %t25 + %t77 = getelementptr inbounds %Str_Node, ptr %t76, i32 0, i32 1 + %t78 = load ptr, ptr %t77 + %t79 = call ptr @fn_sconcat(ptr %t78, ptr @.str1037) + %t80 = call ptr @fn_sconcat(ptr @.str1036, ptr %t79) + %t81 = call ptr @fn_sconcat(ptr %t75, ptr %t80) + %t82 = call ptr @fn_sconcat(ptr @.str1035, ptr %t81) + %t83 = call ptr @fn_sconcat(ptr %t74, ptr %t82) + %t84 = call ptr @fn_sconcat(ptr @.str1034, ptr %t83) + call void @fn_emith(ptr %t84) + %t85 = load ptr, ptr %t25 + %t86 = getelementptr inbounds %Str_Node, ptr %t85, i32 0, i32 1 + %t87 = load ptr, ptr %t86 + %t88 = load ptr, ptr %t1 + %t89 = call ptr @fn_sconcat(ptr %t88, ptr @.str1040) + %t90 = call ptr @fn_sconcat(ptr @.str1039, ptr %t89) + %t91 = call ptr @fn_sconcat(ptr %t87, ptr %t90) + %t92 = call ptr @fn_sconcat(ptr @.str1038, ptr %t91) + call void @fn_emith(ptr %t92) + br label %ifend5 +ifend5: + %t93 = load i32, ptr %t11 + %t94 = add i32 %t93, 1 + store i32 %t94, ptr %t11 + br label %wcond0 +wend2: + br label %ret +ret: + ret void +} + +define void @fn_emit_ecs_allocator() { +entry: + %t1 = alloca ptr + %t2 = alloca i32 + %t24 = alloca ptr + %t0 = call ptr @fn_itoa(i32 1024) + store ptr %t0, ptr %t1 + call void @fn_emit(ptr @.str1041) + store i32 0, ptr %t2 + br label %wcond0 +wcond0: + %t3 = load i32, ptr %t2 + %t4 = load ptr, ptr @g_prog + %t5 = getelementptr inbounds %LSlice, ptr %t4, i32 0, i32 1 + %t6 = load i32, ptr %t5 + %t7 = icmp slt i32 %t3, %t6 + %t8 = zext i1 %t7 to i32 + %t9 = icmp ne i32 %t8, 0 + br i1 %t9, label %wbody1, label %wend2 +wbody1: + %t10 = load ptr, ptr @g_prog + %t11 = getelementptr inbounds %LSlice, ptr %t10, i32 0, i32 0 + %t12 = load ptr, ptr %t11 + %t13 = load i32, ptr %t2 + %t14 = getelementptr inbounds ptr, ptr %t12, i32 %t13 + %t15 = load ptr, ptr %t14 + %t16 = getelementptr inbounds %Str_Node, ptr %t15, i32 0, i32 0 + %t17 = load i32, ptr %t16 + %t18 = icmp eq i32 %t17, 8 + %t19 = zext i1 %t18 to i32 + %t20 = icmp ne i32 %t19, 0 + br i1 %t20, label %then3, label %ifend5 +then3: + %t21 = load i32, ptr %t2 + %t22 = call ptr @fn_itoa(i32 %t21) + %t23 = call ptr @fn_sconcat(ptr @.str1042, ptr %t22) + store ptr %t23, ptr %t24 + call void @fn_emit(ptr @.str1043) + %t25 = load ptr, ptr %t24 + call void @fn_emit(ptr %t25) + call void @fn_emit(ptr @.str1044) + %t26 = load ptr, ptr %t1 + call void @fn_emit(ptr %t26) + call void @fn_emit(ptr @.str1045) + %t27 = load ptr, ptr @g_prog + %t28 = getelementptr inbounds %LSlice, ptr %t27, i32 0, i32 0 + %t29 = load ptr, ptr %t28 + %t30 = load i32, ptr %t2 + %t31 = getelementptr inbounds ptr, ptr %t29, i32 %t30 + %t32 = load ptr, ptr %t31 + %t33 = getelementptr inbounds %Str_Node, ptr %t32, i32 0, i32 1 + %t34 = load ptr, ptr %t33 + call void @fn_emit(ptr %t34) + call void @fn_emit(ptr @.str1046) + call void @fn_emit(ptr @.str1047) + %t35 = load ptr, ptr %t24 + call void @fn_emit(ptr %t35) + call void @fn_emit(ptr @.str1048) + br label %ifend5 +ifend5: + %t36 = load i32, ptr %t2 + %t37 = add i32 %t36, 1 + store i32 %t37, ptr %t2 + br label %wcond0 +wend2: + call void @fn_emit(ptr @.str1049) + %t38 = load ptr, ptr %t1 + call void @fn_emit(ptr %t38) + call void @fn_emit(ptr @.str1050) + call void @fn_emit(ptr @.str1051) + call void @fn_emit(ptr @.str1052) + call void @fn_emit(ptr @.str1053) + call void @fn_emit(ptr @.str1054) + call void @fn_emit(ptr @.str1055) + call void @fn_emit(ptr @.str1056) + call void @fn_emit(ptr @.str1057) + call void @fn_emit(ptr @.str1058) + call void @fn_emit(ptr @.str1059) + %t39 = load ptr, ptr %t1 + call void @fn_emit(ptr %t39) + call void @fn_emit(ptr @.str1060) + call void @fn_emit(ptr @.str1061) + call void @fn_emit(ptr @.str1062) + call void @fn_emit(ptr @.str1063) + call void @fn_emit(ptr @.str1064) + call void @fn_emit(ptr @.str1065) + call void @fn_emit(ptr @.str1066) + call void @fn_emit(ptr @.str1067) + call void @fn_emit(ptr @.str1068) + call void @fn_emit(ptr @.str1069) + call void @fn_emit(ptr @.str1070) + call void @fn_emit(ptr @.str1071) + %t40 = load ptr, ptr %t1 + call void @fn_emit(ptr %t40) + call void @fn_emit(ptr @.str1072) + call void @fn_emit(ptr @.str1073) + call void @fn_emit(ptr @.str1074) + call void @fn_emit(ptr @.str1075) + call void @fn_emit(ptr @.str1076) + %t41 = load ptr, ptr %t1 + call void @fn_emit(ptr %t41) + call void @fn_emit(ptr @.str1077) + call void @fn_emit(ptr @.str1078) + call void @fn_emit(ptr @.str1079) + call void @fn_emit(ptr @.str1080) + call void @fn_emit(ptr @.str1081) + %t42 = load ptr, ptr %t1 + call void @fn_emit(ptr %t42) + call void @fn_emit(ptr @.str1082) + call void @fn_emit(ptr @.str1083) + call void @fn_emit(ptr @.str1084) + call void @fn_emit(ptr @.str1085) + call void @fn_emit(ptr @.str1086) + br label %ret +ret: + ret void +} + +define i32 @fn_find_arch_id(ptr %arg_name) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t1 = alloca i32 + %t2 = alloca i32 + store ptr %arg_name, ptr %t0 + store i32 0, ptr %t1 + store i32 1, ptr %t2 + br label %wcond0 +wcond0: + %t3 = load i32, ptr %t1 + %t4 = load ptr, ptr @g_prog + %t5 = getelementptr inbounds %LSlice, ptr %t4, i32 0, i32 1 + %t6 = load i32, ptr %t5 + %t7 = icmp slt i32 %t3, %t6 + %t8 = zext i1 %t7 to i32 + %t9 = icmp ne i32 %t8, 0 + br i1 %t9, label %wbody1, label %wend2 +wbody1: + %t10 = load ptr, ptr @g_prog + %t11 = getelementptr inbounds %LSlice, ptr %t10, i32 0, i32 0 + %t12 = load ptr, ptr %t11 + %t13 = load i32, ptr %t1 + %t14 = getelementptr inbounds ptr, ptr %t12, i32 %t13 + %t15 = load ptr, ptr %t14 + %t16 = getelementptr inbounds %Str_Node, ptr %t15, i32 0, i32 0 + %t17 = load i32, ptr %t16 + %t18 = icmp eq i32 %t17, 10 + %t19 = zext i1 %t18 to i32 + %t20 = icmp ne i32 %t19, 0 + br i1 %t20, label %then3, label %ifend5 +then3: + %t21 = load ptr, ptr @g_prog + %t22 = getelementptr inbounds %LSlice, ptr %t21, i32 0, i32 0 + %t23 = load ptr, ptr %t22 + %t24 = load i32, ptr %t1 + %t25 = getelementptr inbounds ptr, ptr %t23, i32 %t24 + %t26 = load ptr, ptr %t25 + %t27 = getelementptr inbounds %Str_Node, ptr %t26, i32 0, i32 1 + %t28 = load ptr, ptr %t27 + %t29 = load ptr, ptr %t0 + %t30 = call i32 @fn_streq(ptr %t28, ptr %t29) + %t31 = icmp ne i32 %t30, 0 + br i1 %t31, label %then6, label %ifend8 +then6: + %t32 = load i32, ptr %t2 + store i32 %t32, ptr %retval + br label %ret +ifend8: + %t33 = load i32, ptr %t2 + %t34 = add i32 %t33, 1 + store i32 %t34, ptr %t2 + br label %ifend5 +ifend5: + %t35 = load i32, ptr %t1 + %t36 = add i32 %t35, 1 + store i32 %t36, ptr %t1 + br label %wcond0 +wend2: + store i32 0, ptr %retval + br label %ret +ret: + %t37 = load i32, ptr %retval + ret i32 %t37 +} + +define void @fn_emit_query(ptr %arg_st) { +entry: + %t0 = alloca ptr + %t2 = alloca ptr + %t4 = alloca ptr + %t42 = alloca ptr + %t44 = alloca ptr + %t46 = alloca ptr + %t48 = alloca ptr + %t54 = alloca ptr + %t56 = alloca ptr + %t63 = alloca ptr + %t71 = alloca ptr + %t73 = alloca ptr + %t80 = alloca ptr + %t85 = alloca ptr + %t87 = alloca ptr + %t95 = alloca ptr + %t96 = alloca i32 + %t114 = alloca ptr + %t119 = alloca i32 + %t120 = alloca ptr + %t126 = alloca ptr + %t133 = alloca ptr + %t142 = alloca ptr + %t152 = alloca ptr + %t158 = alloca ptr + %t166 = alloca i32 + %t167 = alloca i32 + %t185 = alloca ptr + %t186 = alloca i32 + %t214 = alloca ptr + %t225 = alloca ptr + %t258 = alloca ptr + %t265 = alloca ptr + %t267 = alloca ptr + %t287 = alloca ptr + %t292 = alloca ptr + store ptr %arg_st, ptr %t0 + %t1 = call ptr @fn_itoa(i32 1024) + store ptr %t1, ptr %t2 + %t3 = call ptr @fn_emit_alloca(ptr @.str1087) + store ptr %t3, ptr %t4 + %t5 = load ptr, ptr %t4 + call void @fn_store_at(ptr @.str1088, ptr @.str1089, ptr %t5) + %t6 = load i32, ptr @g_nself + %t7 = load ptr, ptr @g_self_stk + %t8 = getelementptr inbounds %LSlice, ptr %t7, i32 0, i32 1 + %t9 = load i32, ptr %t8 + %t10 = icmp slt i32 %t6, %t9 + %t11 = zext i1 %t10 to i32 + %t12 = icmp ne i32 %t11, 0 + br i1 %t12, label %then0, label %else1 +then0: + %t13 = load ptr, ptr @g_self_stk + %t14 = getelementptr inbounds %LSlice, ptr %t13, i32 0, i32 0 + %t15 = load ptr, ptr %t14 + %t16 = load i32, ptr @g_nself + %t17 = getelementptr inbounds ptr, ptr %t15, i32 %t16 + %t18 = load ptr, ptr %t4 + store ptr %t18, ptr %t17 + br label %ifend2 +else1: + %t19 = load ptr, ptr @g_self_stk + %t20 = getelementptr inbounds %LSlice, ptr %t19, i32 0, i32 1 + %t21 = getelementptr inbounds %LSlice, ptr %t19, i32 0, i32 2 + %t22 = getelementptr inbounds %LSlice, ptr %t19, i32 0, i32 0 + %t23 = load i32, ptr %t20 + %t24 = load i32, ptr %t21 + %t25 = icmp sge i32 %t23, %t24 + br i1 %t25, label %grow3, label %put4 +grow3: + %t26 = mul i32 %t24, 2 + %t27 = icmp eq i32 %t24, 0 + %t28 = select i1 %t27, i32 8, i32 %t26 + %t29 = getelementptr ptr, ptr null, i32 1 + %t30 = ptrtoint ptr %t29 to i64 + %t31 = zext i32 %t28 to i64 + %t32 = mul i64 %t31, %t30 + %t33 = load ptr, ptr %t22 + %t34 = call ptr @realloc(ptr %t33, i64 %t32) + store ptr %t34, ptr %t22 + store i32 %t28, ptr %t21 + br label %put4 +put4: + %t35 = load ptr, ptr %t4 + %t36 = load ptr, ptr %t22 + %t37 = getelementptr inbounds ptr, ptr %t36, i32 %t23 + store ptr %t35, ptr %t37 + %t38 = add i32 %t23, 1 + store i32 %t38, ptr %t20 + br label %ifend2 +ifend2: + %t39 = load i32, ptr @g_nself + %t40 = add i32 %t39, 1 + store i32 %t40, ptr @g_nself + %t41 = call ptr @fn_lbl(ptr @.str1090) + store ptr %t41, ptr %t42 + %t43 = call ptr @fn_lbl(ptr @.str1091) + store ptr %t43, ptr %t44 + %t45 = call ptr @fn_lbl(ptr @.str1092) + store ptr %t45, ptr %t46 + %t47 = call ptr @fn_lbl(ptr @.str1093) + store ptr %t47, ptr %t48 + call void @fn_emit(ptr @.str1094) + %t49 = load ptr, ptr %t42 + call void @fn_emit(ptr %t49) + call void @fn_emit(ptr @.str1095) + %t50 = load ptr, ptr %t42 + call void @fn_emit(ptr %t50) + call void @fn_emit(ptr @.str1096) + %t51 = load ptr, ptr %t4 + %t52 = call ptr @fn_sconcat(ptr @.str1097, ptr %t51) + %t53 = call ptr @fn_emit_bind(ptr %t52) + store ptr %t53, ptr %t54 + %t55 = call ptr @fn_emit_bind(ptr @.str1098) + store ptr %t55, ptr %t56 + %t57 = load ptr, ptr %t54 + %t58 = load ptr, ptr %t56 + %t59 = call ptr @fn_sconcat(ptr @.str1100, ptr %t58) + %t60 = call ptr @fn_sconcat(ptr %t57, ptr %t59) + %t61 = call ptr @fn_sconcat(ptr @.str1099, ptr %t60) + %t62 = call ptr @fn_emit_bind(ptr %t61) + store ptr %t62, ptr %t63 + call void @fn_emit(ptr @.str1101) + %t64 = load ptr, ptr %t63 + call void @fn_emit(ptr %t64) + call void @fn_emit(ptr @.str1102) + %t65 = load ptr, ptr %t44 + call void @fn_emit(ptr %t65) + call void @fn_emit(ptr @.str1103) + %t66 = load ptr, ptr %t48 + call void @fn_emit(ptr %t66) + call void @fn_emit(ptr @.str1104) + %t67 = load ptr, ptr %t44 + call void @fn_emit(ptr %t67) + call void @fn_emit(ptr @.str1105) + store i32 0, ptr @g_g_term + %t68 = load ptr, ptr %t4 + %t69 = call ptr @fn_sconcat(ptr @.str1106, ptr %t68) + %t70 = call ptr @fn_emit_bind(ptr %t69) + store ptr %t70, ptr %t71 + %t72 = call ptr @fn_nreg() + store ptr %t72, ptr %t73 + call void @fn_emit(ptr @.str1107) + %t74 = load ptr, ptr %t73 + call void @fn_emit(ptr %t74) + call void @fn_emit(ptr @.str1108) + %t75 = load ptr, ptr %t2 + call void @fn_emit(ptr %t75) + call void @fn_emit(ptr @.str1109) + %t76 = load ptr, ptr %t71 + call void @fn_emit(ptr %t76) + call void @fn_emit(ptr @.str1110) + %t77 = load ptr, ptr %t73 + %t78 = call ptr @fn_sconcat(ptr @.str1111, ptr %t77) + %t79 = call ptr @fn_emit_bind(ptr %t78) + store ptr %t79, ptr %t80 + %t81 = load ptr, ptr %t80 + %t82 = call ptr @fn_sconcat(ptr %t81, ptr @.str1113) + %t83 = call ptr @fn_sconcat(ptr @.str1112, ptr %t82) + %t84 = call ptr @fn_emit_bind(ptr %t83) + store ptr %t84, ptr %t85 + %t86 = call ptr @fn_lbl(ptr @.str1114) + store ptr %t86, ptr %t87 + call void @fn_emit(ptr @.str1115) + %t88 = load ptr, ptr %t85 + call void @fn_emit(ptr %t88) + call void @fn_emit(ptr @.str1116) + %t89 = load ptr, ptr %t87 + call void @fn_emit(ptr %t89) + call void @fn_emit(ptr @.str1117) + %t90 = load ptr, ptr %t46 + call void @fn_emit(ptr %t90) + call void @fn_emit(ptr @.str1118) + %t91 = load ptr, ptr %t87 + call void @fn_emit(ptr %t91) + call void @fn_emit(ptr @.str1119) + %t92 = load ptr, ptr %t0 + %t93 = getelementptr inbounds %Str_Node, ptr %t92, i32 0, i32 6 + %t94 = load ptr, ptr %t93 + store ptr %t94, ptr %t95 + store i32 0, ptr %t96 + br label %wcond5 +wcond5: + %t97 = load i32, ptr %t96 + %t98 = load ptr, ptr %t95 + %t99 = getelementptr inbounds %Str_Node, ptr %t98, i32 0, i32 7 + %t100 = load ptr, ptr %t99 + %t101 = getelementptr inbounds %LSlice, ptr %t100, i32 0, i32 1 + %t102 = load i32, ptr %t101 + %t103 = icmp slt i32 %t97, %t102 + %t104 = zext i1 %t103 to i32 + %t105 = icmp ne i32 %t104, 0 + br i1 %t105, label %wbody6, label %wend7 +wbody6: + %t106 = load ptr, ptr %t95 + %t107 = getelementptr inbounds %Str_Node, ptr %t106, i32 0, i32 7 + %t108 = load ptr, ptr %t107 + %t109 = getelementptr inbounds %LSlice, ptr %t108, i32 0, i32 0 + %t110 = load ptr, ptr %t109 + %t111 = load i32, ptr %t96 + %t112 = getelementptr inbounds ptr, ptr %t110, i32 %t111 + %t113 = load ptr, ptr %t112 + store ptr %t113, ptr %t114 + %t115 = load ptr, ptr %t114 + %t116 = getelementptr inbounds %Str_Node, ptr %t115, i32 0, i32 1 + %t117 = load ptr, ptr %t116 + %t118 = call i32 @fn_find_arch_id(ptr %t117) + store i32 %t118, ptr %t119 + store ptr @.str1120, ptr %t120 + %t121 = load i32, ptr %t119 + %t122 = icmp sgt i32 %t121, 0 + %t123 = zext i1 %t122 to i32 + %t124 = icmp ne i32 %t123, 0 + br i1 %t124, label %then8, label %else9 +then8: + %t125 = call ptr @fn_nreg() + store ptr %t125, ptr %t126 + call void @fn_emit(ptr @.str1121) + %t127 = load ptr, ptr %t126 + call void @fn_emit(ptr %t127) + call void @fn_emit(ptr @.str1122) + %t128 = load ptr, ptr %t2 + call void @fn_emit(ptr %t128) + call void @fn_emit(ptr @.str1123) + %t129 = load ptr, ptr %t71 + call void @fn_emit(ptr %t129) + call void @fn_emit(ptr @.str1124) + %t130 = load ptr, ptr %t126 + %t131 = call ptr @fn_sconcat(ptr @.str1125, ptr %t130) + %t132 = call ptr @fn_emit_bind(ptr %t131) + store ptr %t132, ptr %t133 + %t134 = load ptr, ptr %t133 + %t135 = load i32, ptr %t119 + %t136 = call ptr @fn_itoa(i32 %t135) + %t137 = call ptr @fn_sconcat(ptr @.str1127, ptr %t136) + %t138 = call ptr @fn_sconcat(ptr %t134, ptr %t137) + %t139 = call ptr @fn_sconcat(ptr @.str1126, ptr %t138) + %t140 = call ptr @fn_emit_bind(ptr %t139) + store ptr %t140, ptr %t120 + br label %ifend10 +else9: + %t141 = call ptr @fn_nreg() + store ptr %t141, ptr %t142 + call void @fn_emit(ptr @.str1128) + %t143 = load ptr, ptr %t142 + call void @fn_emit(ptr %t143) + call void @fn_emit(ptr @.str1129) + %t144 = load ptr, ptr %t2 + call void @fn_emit(ptr %t144) + call void @fn_emit(ptr @.str1130) + %t145 = load ptr, ptr %t114 + %t146 = getelementptr inbounds %Str_Node, ptr %t145, i32 0, i32 1 + %t147 = load ptr, ptr %t146 + call void @fn_emit(ptr %t147) + call void @fn_emit(ptr @.str1131) + %t148 = load ptr, ptr %t71 + call void @fn_emit(ptr %t148) + call void @fn_emit(ptr @.str1132) + %t149 = load ptr, ptr %t142 + %t150 = call ptr @fn_sconcat(ptr @.str1133, ptr %t149) + %t151 = call ptr @fn_emit_bind(ptr %t150) + store ptr %t151, ptr %t152 + %t153 = load ptr, ptr %t152 + %t154 = call ptr @fn_sconcat(ptr %t153, ptr @.str1135) + %t155 = call ptr @fn_sconcat(ptr @.str1134, ptr %t154) + %t156 = call ptr @fn_emit_bind(ptr %t155) + store ptr %t156, ptr %t120 + br label %ifend10 +ifend10: + %t157 = call ptr @fn_lbl(ptr @.str1136) + store ptr %t157, ptr %t158 + call void @fn_emit(ptr @.str1137) + %t159 = load ptr, ptr %t120 + call void @fn_emit(ptr %t159) + call void @fn_emit(ptr @.str1138) + %t160 = load ptr, ptr %t158 + call void @fn_emit(ptr %t160) + call void @fn_emit(ptr @.str1139) + %t161 = load ptr, ptr %t46 + call void @fn_emit(ptr %t161) + call void @fn_emit(ptr @.str1140) + %t162 = load ptr, ptr %t158 + call void @fn_emit(ptr %t162) + call void @fn_emit(ptr @.str1141) + %t163 = load i32, ptr %t96 + %t164 = add i32 %t163, 1 + store i32 %t164, ptr %t96 + br label %wcond5 +wend7: + %t165 = load i32, ptr @g_nloc + store i32 %t165, ptr %t166 + store i32 0, ptr %t167 + store i32 0, ptr %t96 + br label %wcond11 +wcond11: + %t168 = load i32, ptr %t96 + %t169 = load ptr, ptr %t95 + %t170 = getelementptr inbounds %Str_Node, ptr %t169, i32 0, i32 7 + %t171 = load ptr, ptr %t170 + %t172 = getelementptr inbounds %LSlice, ptr %t171, i32 0, i32 1 + %t173 = load i32, ptr %t172 + %t174 = icmp slt i32 %t168, %t173 + %t175 = zext i1 %t174 to i32 + %t176 = icmp ne i32 %t175, 0 + br i1 %t176, label %wbody12, label %wend13 +wbody12: + %t177 = load ptr, ptr %t95 + %t178 = getelementptr inbounds %Str_Node, ptr %t177, i32 0, i32 7 + %t179 = load ptr, ptr %t178 + %t180 = getelementptr inbounds %LSlice, ptr %t179, i32 0, i32 0 + %t181 = load ptr, ptr %t180 + %t182 = load i32, ptr %t96 + %t183 = getelementptr inbounds ptr, ptr %t181, i32 %t182 + %t184 = load ptr, ptr %t183 + store ptr %t184, ptr %t185 + %t187 = load ptr, ptr %t185 + %t188 = getelementptr inbounds %Str_Node, ptr %t187, i32 0, i32 2 + %t189 = load i32, ptr %t188 + %t190 = icmp eq i32 %t189, 0 + %t191 = zext i1 %t190 to i32 + %t192 = icmp ne i32 %t191, 0 + %t193 = zext i1 %t192 to i32 + store i32 %t193, ptr %t186 + br i1 %t192, label %sc14, label %scend15 +sc14: + %t194 = load ptr, ptr %t185 + %t195 = getelementptr inbounds %Str_Node, ptr %t194, i32 0, i32 1 + %t196 = load ptr, ptr %t195 + %t197 = call i32 @fn_find_arch_id(ptr %t196) + %t198 = icmp eq i32 %t197, 0 + %t199 = zext i1 %t198 to i32 + %t200 = icmp ne i32 %t199, 0 + %t201 = zext i1 %t200 to i32 + store i32 %t201, ptr %t186 + br label %scend15 +scend15: + %t202 = load i32, ptr %t186 + %t203 = icmp ne i32 %t202, 0 + br i1 %t203, label %then16, label %ifend18 +then16: + %t204 = load i32, ptr %t167 + %t205 = load ptr, ptr %t0 + %t206 = getelementptr inbounds %Str_Node, ptr %t205, i32 0, i32 7 + %t207 = load ptr, ptr %t206 + %t208 = getelementptr inbounds %LSlice, ptr %t207, i32 0, i32 1 + %t209 = load i32, ptr %t208 + %t210 = icmp slt i32 %t204, %t209 + %t211 = zext i1 %t210 to i32 + %t212 = icmp ne i32 %t211, 0 + br i1 %t212, label %then19, label %ifend21 +then19: + %t213 = call ptr @fn_nreg() + store ptr %t213, ptr %t214 + call void @fn_emit(ptr @.str1142) + %t215 = load ptr, ptr %t214 + call void @fn_emit(ptr %t215) + call void @fn_emit(ptr @.str1143) + %t216 = load ptr, ptr %t2 + call void @fn_emit(ptr %t216) + call void @fn_emit(ptr @.str1144) + %t217 = load ptr, ptr %t185 + %t218 = getelementptr inbounds %Str_Node, ptr %t217, i32 0, i32 1 + %t219 = load ptr, ptr %t218 + call void @fn_emit(ptr %t219) + call void @fn_emit(ptr @.str1145) + %t220 = load ptr, ptr %t185 + %t221 = getelementptr inbounds %Str_Node, ptr %t220, i32 0, i32 1 + %t222 = load ptr, ptr %t221 + call void @fn_emit(ptr %t222) + call void @fn_emit(ptr @.str1146) + %t223 = load ptr, ptr %t71 + call void @fn_emit(ptr %t223) + call void @fn_emit(ptr @.str1147) + %t224 = call ptr @fn_emit_alloca(ptr @.str1148) + store ptr %t224, ptr %t225 + call void @fn_emit(ptr @.str1149) + %t226 = load ptr, ptr %t214 + call void @fn_emit(ptr %t226) + call void @fn_emit(ptr @.str1150) + %t227 = load ptr, ptr %t225 + call void @fn_emit(ptr %t227) + call void @fn_emit(ptr @.str1151) + %t228 = load ptr, ptr %t0 + %t229 = getelementptr inbounds %Str_Node, ptr %t228, i32 0, i32 7 + %t230 = load ptr, ptr %t229 + %t231 = getelementptr inbounds %LSlice, ptr %t230, i32 0, i32 0 + %t232 = load ptr, ptr %t231 + %t233 = load i32, ptr %t167 + %t234 = getelementptr inbounds ptr, ptr %t232, i32 %t233 + %t235 = load ptr, ptr %t234 + %t236 = getelementptr inbounds %Str_Node, ptr %t235, i32 0, i32 1 + %t237 = load ptr, ptr %t236 + %t238 = load ptr, ptr %t225 + %t239 = load ptr, ptr %t185 + %t240 = getelementptr inbounds %Str_Node, ptr %t239, i32 0, i32 1 + %t241 = load ptr, ptr %t240 + call void @fn_loc_push(ptr %t237, ptr %t238, ptr %t241) + %t242 = load i32, ptr %t167 + %t243 = add i32 %t242, 1 + store i32 %t243, ptr %t167 + br label %ifend21 +ifend21: + br label %ifend18 +ifend18: + %t244 = load i32, ptr %t96 + %t245 = add i32 %t244, 1 + store i32 %t245, ptr %t96 + br label %wcond11 +wend13: + %t246 = load ptr, ptr %t0 + %t247 = getelementptr inbounds %Str_Node, ptr %t246, i32 0, i32 5 + %t248 = load ptr, ptr %t247 + %t249 = icmp eq ptr %t248, null + %t250 = zext i1 %t249 to i32 + %t251 = icmp eq i32 %t250, 0 + %t252 = zext i1 %t251 to i32 + %t253 = icmp ne i32 %t252, 0 + br i1 %t253, label %then22, label %ifend24 +then22: + %t254 = load ptr, ptr %t0 + %t255 = getelementptr inbounds %Str_Node, ptr %t254, i32 0, i32 5 + %t256 = load ptr, ptr %t255 + %t257 = call ptr @fn_emit_expr(ptr %t256) + store ptr %t257, ptr %t258 + %t259 = load ptr, ptr %t258 + %t260 = getelementptr inbounds %Str_Val, ptr %t259, i32 0, i32 0 + %t261 = load ptr, ptr %t260 + %t262 = call ptr @fn_sconcat(ptr %t261, ptr @.str1153) + %t263 = call ptr @fn_sconcat(ptr @.str1152, ptr %t262) + %t264 = call ptr @fn_emit_bind(ptr %t263) + store ptr %t264, ptr %t265 + %t266 = call ptr @fn_lbl(ptr @.str1154) + store ptr %t266, ptr %t267 + call void @fn_emit(ptr @.str1155) + %t268 = load ptr, ptr %t265 + call void @fn_emit(ptr %t268) + call void @fn_emit(ptr @.str1156) + %t269 = load ptr, ptr %t267 + call void @fn_emit(ptr %t269) + call void @fn_emit(ptr @.str1157) + %t270 = load ptr, ptr %t46 + call void @fn_emit(ptr %t270) + call void @fn_emit(ptr @.str1158) + %t271 = load ptr, ptr %t267 + call void @fn_emit(ptr %t271) + call void @fn_emit(ptr @.str1159) + br label %ifend24 +ifend24: + %t272 = load ptr, ptr %t46 + %t273 = load ptr, ptr %t48 + call void @fn_loop_push(ptr %t272, ptr %t273) + %t274 = load ptr, ptr %t0 + %t275 = getelementptr inbounds %Str_Node, ptr %t274, i32 0, i32 4 + %t276 = load ptr, ptr %t275 + call void @fn_emit_block(ptr %t276) + call void @fn_loop_pop() + %t277 = load i32, ptr %t166 + store i32 %t277, ptr @g_nloc + %t278 = load i32, ptr @g_g_term + %t279 = icmp eq i32 %t278, 0 + %t280 = zext i1 %t279 to i32 + %t281 = icmp ne i32 %t280, 0 + br i1 %t281, label %then25, label %ifend27 +then25: + call void @fn_emit(ptr @.str1160) + %t282 = load ptr, ptr %t46 + call void @fn_emit(ptr %t282) + call void @fn_emit(ptr @.str1161) + br label %ifend27 +ifend27: + %t283 = load ptr, ptr %t46 + call void @fn_emit(ptr %t283) + call void @fn_emit(ptr @.str1162) + %t284 = load ptr, ptr %t4 + %t285 = call ptr @fn_sconcat(ptr @.str1163, ptr %t284) + %t286 = call ptr @fn_emit_bind(ptr %t285) + store ptr %t286, ptr %t287 + %t288 = load ptr, ptr %t287 + %t289 = call ptr @fn_sconcat(ptr %t288, ptr @.str1165) + %t290 = call ptr @fn_sconcat(ptr @.str1164, ptr %t289) + %t291 = call ptr @fn_emit_bind(ptr %t290) + store ptr %t291, ptr %t292 + %t293 = load ptr, ptr %t292 + %t294 = load ptr, ptr %t4 + call void @fn_store_at(ptr @.str1166, ptr %t293, ptr %t294) + call void @fn_emit(ptr @.str1167) + %t295 = load ptr, ptr %t42 + call void @fn_emit(ptr %t295) + call void @fn_emit(ptr @.str1168) + %t296 = load ptr, ptr %t48 + call void @fn_emit(ptr %t296) + call void @fn_emit(ptr @.str1169) + store i32 0, ptr @g_g_term + %t297 = load i32, ptr @g_nself + %t298 = sub i32 %t297, 1 + store i32 %t298, ptr @g_nself + br label %ret +ret: + ret void +} + +define void @fn_emit_init_component(ptr %arg_e, ptr %arg_comp, ptr %arg_rec) { +entry: + %t0 = alloca ptr + %t1 = alloca ptr + %t2 = alloca ptr + %t4 = alloca ptr + %t7 = alloca ptr + %t15 = alloca ptr + %t22 = alloca ptr + %t28 = alloca i32 + %t46 = alloca ptr + %t48 = alloca ptr + %t58 = alloca ptr + %t59 = alloca ptr + %t75 = alloca ptr + %t90 = alloca i32 + %t108 = alloca ptr + %t114 = alloca i32 + %t120 = alloca ptr + %t130 = alloca ptr + store ptr %arg_e, ptr %t0 + store ptr %arg_comp, ptr %t1 + store ptr %arg_rec, ptr %t2 + %t3 = call ptr @fn_itoa(i32 1024) + store ptr %t3, ptr %t4 + %t5 = load ptr, ptr %t1 + %t6 = call ptr @fn_find_comp(ptr %t5) + store ptr %t6, ptr %t7 + %t8 = load ptr, ptr %t7 + %t9 = icmp eq ptr %t8, null + %t10 = zext i1 %t9 to i32 + %t11 = icmp ne i32 %t10, 0 + br i1 %t11, label %then0, label %ifend2 +then0: + %t12 = load ptr, ptr %t1 + %t13 = call ptr @fn_sconcat(ptr @.str1170, ptr %t12) + call void @fn_perr(ptr %t13) + br label %ifend2 +ifend2: + %t14 = call ptr @fn_nreg() + store ptr %t14, ptr %t15 + call void @fn_emit(ptr @.str1171) + %t16 = load ptr, ptr %t15 + call void @fn_emit(ptr %t16) + call void @fn_emit(ptr @.str1172) + %t17 = load ptr, ptr %t4 + call void @fn_emit(ptr %t17) + call void @fn_emit(ptr @.str1173) + %t18 = load ptr, ptr %t1 + call void @fn_emit(ptr %t18) + call void @fn_emit(ptr @.str1174) + %t19 = load ptr, ptr %t0 + call void @fn_emit(ptr %t19) + call void @fn_emit(ptr @.str1175) + call void @fn_emit(ptr @.str1176) + %t20 = load ptr, ptr %t15 + call void @fn_emit(ptr %t20) + call void @fn_emit(ptr @.str1177) + %t21 = call ptr @fn_nreg() + store ptr %t21, ptr %t22 + call void @fn_emit(ptr @.str1178) + %t23 = load ptr, ptr %t22 + call void @fn_emit(ptr %t23) + call void @fn_emit(ptr @.str1179) + %t24 = load ptr, ptr %t4 + call void @fn_emit(ptr %t24) + call void @fn_emit(ptr @.str1180) + %t25 = load ptr, ptr %t1 + call void @fn_emit(ptr %t25) + call void @fn_emit(ptr @.str1181) + %t26 = load ptr, ptr %t1 + call void @fn_emit(ptr %t26) + call void @fn_emit(ptr @.str1182) + %t27 = load ptr, ptr %t0 + call void @fn_emit(ptr %t27) + call void @fn_emit(ptr @.str1183) + store i32 0, ptr %t28 + br label %wcond3 +wcond3: + %t29 = load i32, ptr %t28 + %t30 = load ptr, ptr %t7 + %t31 = getelementptr inbounds %Str_Node, ptr %t30, i32 0, i32 7 + %t32 = load ptr, ptr %t31 + %t33 = getelementptr inbounds %LSlice, ptr %t32, i32 0, i32 1 + %t34 = load i32, ptr %t33 + %t35 = icmp slt i32 %t29, %t34 + %t36 = zext i1 %t35 to i32 + %t37 = icmp ne i32 %t36, 0 + br i1 %t37, label %wbody4, label %wend5 +wbody4: + %t38 = load ptr, ptr %t7 + %t39 = getelementptr inbounds %Str_Node, ptr %t38, i32 0, i32 7 + %t40 = load ptr, ptr %t39 + %t41 = getelementptr inbounds %LSlice, ptr %t40, i32 0, i32 0 + %t42 = load ptr, ptr %t41 + %t43 = load i32, ptr %t28 + %t44 = getelementptr inbounds ptr, ptr %t42, i32 %t43 + %t45 = load ptr, ptr %t44 + store ptr %t45, ptr %t46 + %t47 = call ptr @fn_nreg() + store ptr %t47, ptr %t48 + call void @fn_emit(ptr @.str1184) + %t49 = load ptr, ptr %t48 + call void @fn_emit(ptr %t49) + call void @fn_emit(ptr @.str1185) + %t50 = load ptr, ptr %t1 + call void @fn_emit(ptr %t50) + call void @fn_emit(ptr @.str1186) + %t51 = load ptr, ptr %t22 + call void @fn_emit(ptr %t51) + call void @fn_emit(ptr @.str1187) + %t52 = load i32, ptr %t28 + %t53 = call ptr @fn_itoa(i32 %t52) + call void @fn_emit(ptr %t53) + call void @fn_emit(ptr @.str1188) + %t54 = load ptr, ptr %t46 + %t55 = getelementptr inbounds %Str_Node, ptr %t54, i32 0, i32 3 + %t56 = load ptr, ptr %t55 + %t57 = call ptr @fn_llty(ptr %t56) + store ptr %t57, ptr %t58 + store ptr @.str1189, ptr %t59 + %t60 = load ptr, ptr %t58 + %t61 = call i32 @fn_streq(ptr %t60, ptr @.str1190) + %t62 = icmp ne i32 %t61, 0 + br i1 %t62, label %then6, label %ifend8 +then6: + store ptr @.str1191, ptr %t59 + br label %ifend8 +ifend8: + %t63 = load ptr, ptr %t46 + %t64 = getelementptr inbounds %Str_Node, ptr %t63, i32 0, i32 4 + %t65 = load ptr, ptr %t64 + %t66 = icmp eq ptr %t65, null + %t67 = zext i1 %t66 to i32 + %t68 = icmp eq i32 %t67, 0 + %t69 = zext i1 %t68 to i32 + %t70 = icmp ne i32 %t69, 0 + br i1 %t70, label %then9, label %ifend11 +then9: + %t71 = load ptr, ptr %t46 + %t72 = getelementptr inbounds %Str_Node, ptr %t71, i32 0, i32 4 + %t73 = load ptr, ptr %t72 + %t74 = call ptr @fn_emit_expr(ptr %t73) + store ptr %t74, ptr %t75 + %t76 = load ptr, ptr %t75 + %t77 = getelementptr inbounds %Str_Val, ptr %t76, i32 0, i32 0 + %t78 = load ptr, ptr %t77 + store ptr %t78, ptr %t59 + br label %ifend11 +ifend11: + call void @fn_emit(ptr @.str1192) + %t79 = load ptr, ptr %t58 + call void @fn_emit(ptr %t79) + call void @fn_emit(ptr @.str1193) + %t80 = load ptr, ptr %t59 + call void @fn_emit(ptr %t80) + call void @fn_emit(ptr @.str1194) + %t81 = load ptr, ptr %t48 + call void @fn_emit(ptr %t81) + call void @fn_emit(ptr @.str1195) + %t82 = load i32, ptr %t28 + %t83 = add i32 %t82, 1 + store i32 %t83, ptr %t28 + br label %wcond3 +wend5: + %t84 = load ptr, ptr %t2 + %t85 = icmp eq ptr %t84, null + %t86 = zext i1 %t85 to i32 + %t87 = icmp eq i32 %t86, 0 + %t88 = zext i1 %t87 to i32 + %t89 = icmp ne i32 %t88, 0 + br i1 %t89, label %then12, label %ifend14 +then12: + store i32 0, ptr %t90 + br label %wcond15 +wcond15: + %t91 = load i32, ptr %t90 + %t92 = load ptr, ptr %t2 + %t93 = getelementptr inbounds %Str_Node, ptr %t92, i32 0, i32 7 + %t94 = load ptr, ptr %t93 + %t95 = getelementptr inbounds %LSlice, ptr %t94, i32 0, i32 1 + %t96 = load i32, ptr %t95 + %t97 = icmp slt i32 %t91, %t96 + %t98 = zext i1 %t97 to i32 + %t99 = icmp ne i32 %t98, 0 + br i1 %t99, label %wbody16, label %wend17 +wbody16: + %t100 = load ptr, ptr %t2 + %t101 = getelementptr inbounds %Str_Node, ptr %t100, i32 0, i32 7 + %t102 = load ptr, ptr %t101 + %t103 = getelementptr inbounds %LSlice, ptr %t102, i32 0, i32 0 + %t104 = load ptr, ptr %t103 + %t105 = load i32, ptr %t90 + %t106 = getelementptr inbounds ptr, ptr %t104, i32 %t105 + %t107 = load ptr, ptr %t106 + store ptr %t107, ptr %t108 + %t109 = load ptr, ptr %t7 + %t110 = load ptr, ptr %t108 + %t111 = getelementptr inbounds %Str_Node, ptr %t110, i32 0, i32 1 + %t112 = load ptr, ptr %t111 + %t113 = call i32 @fn_field_index(ptr %t109, ptr %t112) + store i32 %t113, ptr %t114 + %t115 = load i32, ptr %t114 + %t116 = icmp sge i32 %t115, 0 + %t117 = zext i1 %t116 to i32 + %t118 = icmp ne i32 %t117, 0 + br i1 %t118, label %then18, label %ifend20 +then18: + %t119 = call ptr @fn_nreg() + store ptr %t119, ptr %t120 + call void @fn_emit(ptr @.str1196) + %t121 = load ptr, ptr %t120 + call void @fn_emit(ptr %t121) + call void @fn_emit(ptr @.str1197) + %t122 = load ptr, ptr %t1 + call void @fn_emit(ptr %t122) + call void @fn_emit(ptr @.str1198) + %t123 = load ptr, ptr %t22 + call void @fn_emit(ptr %t123) + call void @fn_emit(ptr @.str1199) + %t124 = load i32, ptr %t114 + %t125 = call ptr @fn_itoa(i32 %t124) + call void @fn_emit(ptr %t125) + call void @fn_emit(ptr @.str1200) + %t126 = load ptr, ptr %t108 + %t127 = getelementptr inbounds %Str_Node, ptr %t126, i32 0, i32 4 + %t128 = load ptr, ptr %t127 + %t129 = call ptr @fn_emit_expr(ptr %t128) + store ptr %t129, ptr %t130 + call void @fn_emit(ptr @.str1201) + %t131 = load ptr, ptr %t7 + %t132 = load ptr, ptr %t108 + %t133 = getelementptr inbounds %Str_Node, ptr %t132, i32 0, i32 1 + %t134 = load ptr, ptr %t133 + %t135 = call ptr @fn_field_type(ptr %t131, ptr %t134) + %t136 = call ptr @fn_llty(ptr %t135) + call void @fn_emit(ptr %t136) + call void @fn_emit(ptr @.str1202) + %t137 = load ptr, ptr %t130 + %t138 = getelementptr inbounds %Str_Val, ptr %t137, i32 0, i32 0 + %t139 = load ptr, ptr %t138 + call void @fn_emit(ptr %t139) + call void @fn_emit(ptr @.str1203) + %t140 = load ptr, ptr %t120 + call void @fn_emit(ptr %t140) + call void @fn_emit(ptr @.str1204) + br label %ifend20 +ifend20: + %t141 = load i32, ptr %t90 + %t142 = add i32 %t141, 1 + store i32 %t142, ptr %t90 + br label %wcond15 +wend17: + br label %ifend14 +ifend14: + br label %ret +ret: + ret void +} + +define void @fn_emit_spawn(ptr %arg_st) { +entry: + %t0 = alloca ptr + %t2 = alloca ptr + %t7 = alloca i32 + %t13 = alloca ptr + %t15 = alloca ptr + %t26 = alloca ptr + %t27 = alloca i32 + %t47 = alloca ptr + %t48 = alloca ptr + %t49 = alloca i32 + %t89 = alloca i32 + store ptr %arg_st, ptr %t0 + %t1 = call ptr @fn_emit_bind(ptr @.str1205) + store ptr %t1, ptr %t2 + %t3 = load ptr, ptr %t0 + %t4 = getelementptr inbounds %Str_Node, ptr %t3, i32 0, i32 1 + %t5 = load ptr, ptr %t4 + %t6 = call i32 @fn_find_arch_id(ptr %t5) + store i32 %t6, ptr %t7 + %t8 = load i32, ptr %t7 + %t9 = icmp sgt i32 %t8, 0 + %t10 = zext i1 %t9 to i32 + %t11 = icmp ne i32 %t10, 0 + br i1 %t11, label %then0, label %else1 +then0: + %t12 = call ptr @fn_itoa(i32 1024) + store ptr %t12, ptr %t13 + %t14 = call ptr @fn_nreg() + store ptr %t14, ptr %t15 + call void @fn_emit(ptr @.str1206) + %t16 = load ptr, ptr %t15 + call void @fn_emit(ptr %t16) + call void @fn_emit(ptr @.str1207) + %t17 = load ptr, ptr %t13 + call void @fn_emit(ptr %t17) + call void @fn_emit(ptr @.str1208) + %t18 = load ptr, ptr %t2 + call void @fn_emit(ptr %t18) + call void @fn_emit(ptr @.str1209) + call void @fn_emit(ptr @.str1210) + %t19 = load i32, ptr %t7 + %t20 = call ptr @fn_itoa(i32 %t19) + call void @fn_emit(ptr %t20) + call void @fn_emit(ptr @.str1211) + %t21 = load ptr, ptr %t15 + call void @fn_emit(ptr %t21) + call void @fn_emit(ptr @.str1212) + %t22 = load ptr, ptr %t0 + %t23 = getelementptr inbounds %Str_Node, ptr %t22, i32 0, i32 1 + %t24 = load ptr, ptr %t23 + %t25 = call ptr @fn_find_arch(ptr %t24) + store ptr %t25, ptr %t26 + store i32 0, ptr %t27 + br label %wcond3 +wcond3: + %t28 = load i32, ptr %t27 + %t29 = load ptr, ptr %t26 + %t30 = getelementptr inbounds %Str_Node, ptr %t29, i32 0, i32 7 + %t31 = load ptr, ptr %t30 + %t32 = getelementptr inbounds %LSlice, ptr %t31, i32 0, i32 1 + %t33 = load i32, ptr %t32 + %t34 = icmp slt i32 %t28, %t33 + %t35 = zext i1 %t34 to i32 + %t36 = icmp ne i32 %t35, 0 + br i1 %t36, label %wbody4, label %wend5 +wbody4: + %t37 = load ptr, ptr %t26 + %t38 = getelementptr inbounds %Str_Node, ptr %t37, i32 0, i32 7 + %t39 = load ptr, ptr %t38 + %t40 = getelementptr inbounds %LSlice, ptr %t39, i32 0, i32 0 + %t41 = load ptr, ptr %t40 + %t42 = load i32, ptr %t27 + %t43 = getelementptr inbounds ptr, ptr %t41, i32 %t42 + %t44 = load ptr, ptr %t43 + %t45 = getelementptr inbounds %Str_Node, ptr %t44, i32 0, i32 1 + %t46 = load ptr, ptr %t45 + store ptr %t46, ptr %t47 + store ptr null, ptr %t48 + store i32 0, ptr %t49 + br label %wcond6 +wcond6: + %t50 = load i32, ptr %t49 + %t51 = load ptr, ptr %t0 + %t52 = getelementptr inbounds %Str_Node, ptr %t51, i32 0, i32 7 + %t53 = load ptr, ptr %t52 + %t54 = getelementptr inbounds %LSlice, ptr %t53, i32 0, i32 1 + %t55 = load i32, ptr %t54 + %t56 = icmp slt i32 %t50, %t55 + %t57 = zext i1 %t56 to i32 + %t58 = icmp ne i32 %t57, 0 + br i1 %t58, label %wbody7, label %wend8 +wbody7: + %t59 = load ptr, ptr %t0 + %t60 = getelementptr inbounds %Str_Node, ptr %t59, i32 0, i32 7 + %t61 = load ptr, ptr %t60 + %t62 = getelementptr inbounds %LSlice, ptr %t61, i32 0, i32 0 + %t63 = load ptr, ptr %t62 + %t64 = load i32, ptr %t49 + %t65 = getelementptr inbounds ptr, ptr %t63, i32 %t64 + %t66 = load ptr, ptr %t65 + %t67 = getelementptr inbounds %Str_Node, ptr %t66, i32 0, i32 1 + %t68 = load ptr, ptr %t67 + %t69 = load ptr, ptr %t47 + %t70 = call i32 @fn_streq(ptr %t68, ptr %t69) + %t71 = icmp ne i32 %t70, 0 + br i1 %t71, label %then9, label %ifend11 +then9: + %t72 = load ptr, ptr %t0 + %t73 = getelementptr inbounds %Str_Node, ptr %t72, i32 0, i32 7 + %t74 = load ptr, ptr %t73 + %t75 = getelementptr inbounds %LSlice, ptr %t74, i32 0, i32 0 + %t76 = load ptr, ptr %t75 + %t77 = load i32, ptr %t49 + %t78 = getelementptr inbounds ptr, ptr %t76, i32 %t77 + %t79 = load ptr, ptr %t78 + %t80 = getelementptr inbounds %Str_Node, ptr %t79, i32 0, i32 4 + %t81 = load ptr, ptr %t80 + store ptr %t81, ptr %t48 + br label %ifend11 +ifend11: + %t82 = load i32, ptr %t49 + %t83 = add i32 %t82, 1 + store i32 %t83, ptr %t49 + br label %wcond6 +wend8: + %t84 = load ptr, ptr %t2 + %t85 = load ptr, ptr %t47 + %t86 = load ptr, ptr %t48 + call void @fn_emit_init_component(ptr %t84, ptr %t85, ptr %t86) + %t87 = load i32, ptr %t27 + %t88 = add i32 %t87, 1 + store i32 %t88, ptr %t27 + br label %wcond3 +wend5: + br label %ifend2 +else1: + store i32 0, ptr %t89 + br label %wcond12 +wcond12: + %t90 = load i32, ptr %t89 + %t91 = load ptr, ptr %t0 + %t92 = getelementptr inbounds %Str_Node, ptr %t91, i32 0, i32 7 + %t93 = load ptr, ptr %t92 + %t94 = getelementptr inbounds %LSlice, ptr %t93, i32 0, i32 1 + %t95 = load i32, ptr %t94 + %t96 = icmp slt i32 %t90, %t95 + %t97 = zext i1 %t96 to i32 + %t98 = icmp ne i32 %t97, 0 + br i1 %t98, label %wbody13, label %wend14 +wbody13: + %t99 = load ptr, ptr %t2 + %t100 = load ptr, ptr %t0 + %t101 = getelementptr inbounds %Str_Node, ptr %t100, i32 0, i32 7 + %t102 = load ptr, ptr %t101 + %t103 = getelementptr inbounds %LSlice, ptr %t102, i32 0, i32 0 + %t104 = load ptr, ptr %t103 + %t105 = load i32, ptr %t89 + %t106 = getelementptr inbounds ptr, ptr %t104, i32 %t105 + %t107 = load ptr, ptr %t106 + %t108 = getelementptr inbounds %Str_Node, ptr %t107, i32 0, i32 1 + %t109 = load ptr, ptr %t108 + %t110 = load ptr, ptr %t0 + %t111 = getelementptr inbounds %Str_Node, ptr %t110, i32 0, i32 7 + %t112 = load ptr, ptr %t111 + %t113 = getelementptr inbounds %LSlice, ptr %t112, i32 0, i32 0 + %t114 = load ptr, ptr %t113 + %t115 = load i32, ptr %t89 + %t116 = getelementptr inbounds ptr, ptr %t114, i32 %t115 + %t117 = load ptr, ptr %t116 + %t118 = getelementptr inbounds %Str_Node, ptr %t117, i32 0, i32 4 + %t119 = load ptr, ptr %t118 + call void @fn_emit_init_component(ptr %t99, ptr %t109, ptr %t119) + %t120 = load i32, ptr %t89 + %t121 = add i32 %t120, 1 + store i32 %t121, ptr %t89 + br label %wcond12 +wend14: + br label %ifend2 +ifend2: + br label %ret +ret: + ret void +} + +define void @fn_emit_despawn(ptr %arg_st) { +entry: + %t0 = alloca ptr + %t5 = alloca ptr + store ptr %arg_st, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = getelementptr inbounds %Str_Node, ptr %t1, i32 0, i32 4 + %t3 = load ptr, ptr %t2 + %t4 = call ptr @fn_emit_expr(ptr %t3) + store ptr %t4, ptr %t5 + call void @fn_emit(ptr @.str1213) + %t6 = load ptr, ptr %t5 + %t7 = getelementptr inbounds %Str_Val, ptr %t6, i32 0, i32 0 + %t8 = load ptr, ptr %t7 + call void @fn_emit(ptr %t8) + call void @fn_emit(ptr @.str1214) + br label %ret +ret: + ret void +} + +define void @fn_emit_system_fn(ptr %arg_sys) { +entry: + %t0 = alloca ptr + %t2 = alloca ptr + %t5 = alloca ptr + store ptr %arg_sys, ptr %t0 + store i32 0, ptr @g_ll_t + store i32 0, ptr @g_ll_lbl + store i32 0, ptr @g_g_term + call void @fn_loc_reset() + store i32 0, ptr @g_nloop + store i32 0, ptr @g_nself + store ptr @.str1215, ptr @g_ret_ty + %t1 = call ptr @fn_buf_new() + store ptr %t1, ptr %t2 + %t3 = call ptr @fn_buf_new() + store ptr %t3, ptr @g_falloc + %t4 = load ptr, ptr @g_code + store ptr %t4, ptr %t5 + %t6 = load ptr, ptr %t2 + store ptr %t6, ptr @g_code + %t7 = load ptr, ptr %t0 + %t8 = getelementptr inbounds %Str_Node, ptr %t7, i32 0, i32 4 + %t9 = load ptr, ptr %t8 + call void @fn_emit_block(ptr %t9) + %t10 = load i32, ptr @g_g_term + %t11 = icmp eq i32 %t10, 0 + %t12 = zext i1 %t11 to i32 + %t13 = icmp ne i32 %t12, 0 + br i1 %t13, label %then0, label %ifend2 +then0: + call void @fn_emit(ptr @.str1216) + br label %ifend2 +ifend2: + call void @fn_emit(ptr @.str1217) + %t14 = load ptr, ptr %t5 + store ptr %t14, ptr @g_code + call void @fn_emit(ptr @.str1218) + %t15 = load ptr, ptr %t0 + %t16 = getelementptr inbounds %Str_Node, ptr %t15, i32 0, i32 1 + %t17 = load ptr, ptr %t16 + call void @fn_emit(ptr %t17) + call void @fn_emit(ptr @.str1219) + %t18 = load ptr, ptr @g_falloc + %t19 = call ptr @fn_buf_str(ptr %t18) + call void @fn_emit(ptr %t19) + %t20 = load ptr, ptr %t2 + %t21 = call ptr @fn_buf_str(ptr %t20) + call void @fn_emit(ptr %t21) + call void @fn_emit(ptr @.str1220) + br label %ret +ret: + ret void +} + +define void @fn_emit_calls_for_phase(ptr %arg_phase) { +entry: + %t0 = alloca ptr + %t1 = alloca i32 + %t15 = alloca ptr + %t16 = alloca i32 + store ptr %arg_phase, ptr %t0 + store i32 0, ptr %t1 + br label %wcond0 +wcond0: + %t2 = load i32, ptr %t1 + %t3 = load ptr, ptr @g_prog + %t4 = getelementptr inbounds %LSlice, ptr %t3, i32 0, i32 1 + %t5 = load i32, ptr %t4 + %t6 = icmp slt i32 %t2, %t5 + %t7 = zext i1 %t6 to i32 + %t8 = icmp ne i32 %t7, 0 + br i1 %t8, label %wbody1, label %wend2 +wbody1: + %t9 = load ptr, ptr @g_prog + %t10 = getelementptr inbounds %LSlice, ptr %t9, i32 0, i32 0 + %t11 = load ptr, ptr %t10 + %t12 = load i32, ptr %t1 + %t13 = getelementptr inbounds ptr, ptr %t11, i32 %t12 + %t14 = load ptr, ptr %t13 + store ptr %t14, ptr %t15 + %t17 = load ptr, ptr %t15 + %t18 = getelementptr inbounds %Str_Node, ptr %t17, i32 0, i32 0 + %t19 = load i32, ptr %t18 + %t20 = icmp eq i32 %t19, 9 + %t21 = zext i1 %t20 to i32 + %t22 = icmp ne i32 %t21, 0 + %t23 = zext i1 %t22 to i32 + store i32 %t23, ptr %t16 + br i1 %t22, label %sc3, label %scend4 +sc3: + %t24 = load ptr, ptr %t15 + %t25 = getelementptr inbounds %Str_Node, ptr %t24, i32 0, i32 3 + %t26 = load ptr, ptr %t25 + %t27 = load ptr, ptr %t0 + %t28 = call i32 @fn_streq(ptr %t26, ptr %t27) + %t29 = icmp ne i32 %t28, 0 + %t30 = zext i1 %t29 to i32 + store i32 %t30, ptr %t16 + br label %scend4 +scend4: + %t31 = load i32, ptr %t16 + %t32 = icmp ne i32 %t31, 0 + br i1 %t32, label %then5, label %ifend7 +then5: + call void @fn_emit(ptr @.str1221) + %t33 = load ptr, ptr %t15 + %t34 = getelementptr inbounds %Str_Node, ptr %t33, i32 0, i32 1 + %t35 = load ptr, ptr %t34 + call void @fn_emit(ptr %t35) + call void @fn_emit(ptr @.str1222) + br label %ifend7 +ifend7: + %t36 = load i32, ptr %t1 + %t37 = add i32 %t36, 1 + store i32 %t37, ptr %t1 + br label %wcond0 +wend2: + br label %ret +ret: + ret void +} + +define void @fn_emit_game_main() { +entry: + %t0 = alloca i32 + %t34 = alloca ptr + %t39 = alloca ptr + %t47 = alloca ptr + %t52 = alloca ptr + %t59 = alloca ptr + %t69 = alloca ptr + store i32 0, ptr %t0 + br label %wcond0 +wcond0: + %t1 = load i32, ptr %t0 + %t2 = load ptr, ptr @g_prog + %t3 = getelementptr inbounds %LSlice, ptr %t2, i32 0, i32 1 + %t4 = load i32, ptr %t3 + %t5 = icmp slt i32 %t1, %t4 + %t6 = zext i1 %t5 to i32 + %t7 = icmp ne i32 %t6, 0 + br i1 %t7, label %wbody1, label %wend2 +wbody1: + %t8 = load ptr, ptr @g_prog + %t9 = getelementptr inbounds %LSlice, ptr %t8, i32 0, i32 0 + %t10 = load ptr, ptr %t9 + %t11 = load i32, ptr %t0 + %t12 = getelementptr inbounds ptr, ptr %t10, i32 %t11 + %t13 = load ptr, ptr %t12 + %t14 = getelementptr inbounds %Str_Node, ptr %t13, i32 0, i32 0 + %t15 = load i32, ptr %t14 + %t16 = icmp eq i32 %t15, 9 + %t17 = zext i1 %t16 to i32 + %t18 = icmp ne i32 %t17, 0 + br i1 %t18, label %then3, label %ifend5 +then3: + %t19 = load ptr, ptr @g_prog + %t20 = getelementptr inbounds %LSlice, ptr %t19, i32 0, i32 0 + %t21 = load ptr, ptr %t20 + %t22 = load i32, ptr %t0 + %t23 = getelementptr inbounds ptr, ptr %t21, i32 %t22 + %t24 = load ptr, ptr %t23 + call void @fn_emit_system_fn(ptr %t24) + br label %ifend5 +ifend5: + %t25 = load i32, ptr %t0 + %t26 = add i32 %t25, 1 + store i32 %t26, ptr %t0 + br label %wcond0 +wend2: + call void @fn_emit(ptr @.str1223) + call void @fn_emit(ptr @.str1224) + call void @fn_emit(ptr @.str1225) + %t27 = call ptr @fn_find_fn(ptr @.str1226) + %t28 = icmp eq ptr %t27, null + %t29 = zext i1 %t28 to i32 + %t30 = icmp eq i32 %t29, 0 + %t31 = zext i1 %t30 to i32 + %t32 = icmp ne i32 %t31, 0 + br i1 %t32, label %then6, label %ifend8 +then6: + call void @fn_emit(ptr @.str1227) + br label %ifend8 +ifend8: + call void @fn_emit_calls_for_phase(ptr @.str1228) + call void @fn_emit(ptr @.str1229) + call void @fn_emit(ptr @.str1230) + %t33 = call ptr @fn_emit_bind(ptr @.str1231) + store ptr %t33, ptr %t34 + %t35 = load ptr, ptr %t34 + %t36 = call ptr @fn_sconcat(ptr %t35, ptr @.str1233) + %t37 = call ptr @fn_sconcat(ptr @.str1232, ptr %t36) + %t38 = call ptr @fn_emit_bind(ptr %t37) + store ptr %t38, ptr %t39 + %t40 = call ptr @fn_find_fn(ptr @.str1234) + %t41 = icmp eq ptr %t40, null + %t42 = zext i1 %t41 to i32 + %t43 = icmp eq i32 %t42, 0 + %t44 = zext i1 %t43 to i32 + %t45 = icmp ne i32 %t44, 0 + br i1 %t45, label %then9, label %else10 +then9: + %t46 = call ptr @fn_emit_bind(ptr @.str1235) + store ptr %t46, ptr %t47 + %t48 = load ptr, ptr %t47 + %t49 = call ptr @fn_sconcat(ptr %t48, ptr @.str1237) + %t50 = call ptr @fn_sconcat(ptr @.str1236, ptr %t49) + %t51 = call ptr @fn_emit_bind(ptr %t50) + store ptr %t51, ptr %t52 + %t53 = load ptr, ptr %t39 + %t54 = load ptr, ptr %t52 + %t55 = call ptr @fn_sconcat(ptr @.str1239, ptr %t54) + %t56 = call ptr @fn_sconcat(ptr %t53, ptr %t55) + %t57 = call ptr @fn_sconcat(ptr @.str1238, ptr %t56) + %t58 = call ptr @fn_emit_bind(ptr %t57) + store ptr %t58, ptr %t59 + call void @fn_emit(ptr @.str1240) + %t60 = load ptr, ptr %t59 + call void @fn_emit(ptr %t60) + call void @fn_emit(ptr @.str1241) + br label %ifend11 +else10: + call void @fn_emit(ptr @.str1242) + %t61 = load ptr, ptr %t39 + call void @fn_emit(ptr %t61) + call void @fn_emit(ptr @.str1243) + br label %ifend11 +ifend11: + call void @fn_emit(ptr @.str1244) + %t62 = call ptr @fn_find_fn(ptr @.str1245) + %t63 = icmp eq ptr %t62, null + %t64 = zext i1 %t63 to i32 + %t65 = icmp eq i32 %t64, 0 + %t66 = zext i1 %t65 to i32 + %t67 = icmp ne i32 %t66, 0 + br i1 %t67, label %then12, label %ifend14 +then12: + %t68 = call ptr @fn_emit_bind(ptr @.str1246) + store ptr %t68, ptr %t69 + call void @fn_emit(ptr @.str1247) + %t70 = load ptr, ptr %t69 + call void @fn_emit(ptr %t70) + call void @fn_emit(ptr @.str1248) + br label %ifend14 +ifend14: + call void @fn_emit_calls_for_phase(ptr @.str1249) + call void @fn_emit_calls_for_phase(ptr @.str1250) + call void @fn_emit_calls_for_phase(ptr @.str1251) + call void @fn_emit_calls_for_phase(ptr @.str1252) + call void @fn_emit_calls_for_phase(ptr @.str1253) + call void @fn_emit(ptr @.str1254) + call void @fn_emit(ptr @.str1255) + %t71 = call ptr @fn_find_fn(ptr @.str1256) + %t72 = icmp eq ptr %t71, null + %t73 = zext i1 %t72 to i32 + %t74 = icmp eq i32 %t73, 0 + %t75 = zext i1 %t74 to i32 + %t76 = icmp ne i32 %t75, 0 + br i1 %t76, label %then15, label %ifend17 +then15: + call void @fn_emit(ptr @.str1257) + br label %ifend17 +ifend17: + call void @fn_emit(ptr @.str1258) + br label %ret +ret: + ret void +} + +define void @fn_emit_machine(ptr %arg_st) { +entry: + %t0 = alloca ptr + %t5 = alloca ptr + %t12 = alloca ptr + %t49 = alloca ptr + %t50 = alloca i32 + %t68 = alloca ptr + %t73 = alloca ptr + %t82 = alloca ptr + %t84 = alloca ptr + %t86 = alloca ptr + store ptr %arg_st, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = getelementptr inbounds %Str_Node, ptr %t1, i32 0, i32 4 + %t3 = load ptr, ptr %t2 + %t4 = call ptr @fn_emit_expr(ptr %t3) + store ptr %t4, ptr %t5 + %t6 = load ptr, ptr %t5 + %t7 = getelementptr inbounds %Str_Val, ptr %t6, i32 0, i32 0 + %t8 = load ptr, ptr %t7 + %t9 = call ptr @fn_sconcat(ptr %t8, ptr @.str1260) + %t10 = call ptr @fn_sconcat(ptr @.str1259, ptr %t9) + %t11 = call ptr @fn_emit_bind(ptr %t10) + store ptr %t11, ptr %t12 + %t13 = load i32, ptr @g_nmach + %t14 = load ptr, ptr @g_mach_stk + %t15 = getelementptr inbounds %LSlice, ptr %t14, i32 0, i32 1 + %t16 = load i32, ptr %t15 + %t17 = icmp slt i32 %t13, %t16 + %t18 = zext i1 %t17 to i32 + %t19 = icmp ne i32 %t18, 0 + br i1 %t19, label %then0, label %else1 +then0: + %t20 = load ptr, ptr @g_mach_stk + %t21 = getelementptr inbounds %LSlice, ptr %t20, i32 0, i32 0 + %t22 = load ptr, ptr %t21 + %t23 = load i32, ptr @g_nmach + %t24 = getelementptr inbounds ptr, ptr %t22, i32 %t23 + %t25 = load ptr, ptr %t0 + store ptr %t25, ptr %t24 + br label %ifend2 +else1: + %t26 = load ptr, ptr @g_mach_stk + %t27 = getelementptr inbounds %LSlice, ptr %t26, i32 0, i32 1 + %t28 = getelementptr inbounds %LSlice, ptr %t26, i32 0, i32 2 + %t29 = getelementptr inbounds %LSlice, ptr %t26, i32 0, i32 0 + %t30 = load i32, ptr %t27 + %t31 = load i32, ptr %t28 + %t32 = icmp sge i32 %t30, %t31 + br i1 %t32, label %grow3, label %put4 +grow3: + %t33 = mul i32 %t31, 2 + %t34 = icmp eq i32 %t31, 0 + %t35 = select i1 %t34, i32 8, i32 %t33 + %t36 = getelementptr ptr, ptr null, i32 1 + %t37 = ptrtoint ptr %t36 to i64 + %t38 = zext i32 %t35 to i64 + %t39 = mul i64 %t38, %t37 + %t40 = load ptr, ptr %t29 + %t41 = call ptr @realloc(ptr %t40, i64 %t39) + store ptr %t41, ptr %t29 + store i32 %t35, ptr %t28 + br label %put4 +put4: + %t42 = load ptr, ptr %t0 + %t43 = load ptr, ptr %t29 + %t44 = getelementptr inbounds ptr, ptr %t43, i32 %t30 + store ptr %t42, ptr %t44 + %t45 = add i32 %t30, 1 + store i32 %t45, ptr %t27 + br label %ifend2 +ifend2: + %t46 = load i32, ptr @g_nmach + %t47 = add i32 %t46, 1 + store i32 %t47, ptr @g_nmach + %t48 = call ptr @fn_lbl(ptr @.str1261) + store ptr %t48, ptr %t49 + store i32 0, ptr %t50 + br label %wcond5 +wcond5: + %t51 = load i32, ptr %t50 + %t52 = load ptr, ptr %t0 + %t53 = getelementptr inbounds %Str_Node, ptr %t52, i32 0, i32 7 + %t54 = load ptr, ptr %t53 + %t55 = getelementptr inbounds %LSlice, ptr %t54, i32 0, i32 1 + %t56 = load i32, ptr %t55 + %t57 = icmp slt i32 %t51, %t56 + %t58 = zext i1 %t57 to i32 + %t59 = icmp ne i32 %t58, 0 + br i1 %t59, label %wbody6, label %wend7 +wbody6: + %t60 = load ptr, ptr %t0 + %t61 = getelementptr inbounds %Str_Node, ptr %t60, i32 0, i32 7 + %t62 = load ptr, ptr %t61 + %t63 = getelementptr inbounds %LSlice, ptr %t62, i32 0, i32 0 + %t64 = load ptr, ptr %t63 + %t65 = load i32, ptr %t50 + %t66 = getelementptr inbounds ptr, ptr %t64, i32 %t65 + %t67 = load ptr, ptr %t66 + store ptr %t67, ptr %t68 + %t69 = load ptr, ptr %t68 + %t70 = getelementptr inbounds %Str_Node, ptr %t69, i32 0, i32 5 + %t71 = load ptr, ptr %t70 + %t72 = call ptr @fn_emit_expr(ptr %t71) + store ptr %t72, ptr %t73 + %t74 = load ptr, ptr %t12 + %t75 = load ptr, ptr %t73 + %t76 = getelementptr inbounds %Str_Val, ptr %t75, i32 0, i32 0 + %t77 = load ptr, ptr %t76 + %t78 = call ptr @fn_sconcat(ptr @.str1263, ptr %t77) + %t79 = call ptr @fn_sconcat(ptr %t74, ptr %t78) + %t80 = call ptr @fn_sconcat(ptr @.str1262, ptr %t79) + %t81 = call ptr @fn_emit_bind(ptr %t80) + store ptr %t81, ptr %t82 + %t83 = call ptr @fn_lbl(ptr @.str1264) + store ptr %t83, ptr %t84 + %t85 = call ptr @fn_lbl(ptr @.str1265) + store ptr %t85, ptr %t86 + call void @fn_emit(ptr @.str1266) + %t87 = load ptr, ptr %t82 + call void @fn_emit(ptr %t87) + call void @fn_emit(ptr @.str1267) + %t88 = load ptr, ptr %t84 + call void @fn_emit(ptr %t88) + call void @fn_emit(ptr @.str1268) + %t89 = load ptr, ptr %t86 + call void @fn_emit(ptr %t89) + call void @fn_emit(ptr @.str1269) + %t90 = load ptr, ptr %t84 + call void @fn_emit(ptr %t90) + call void @fn_emit(ptr @.str1270) + store i32 0, ptr @g_g_term + %t91 = load ptr, ptr %t68 + %t92 = getelementptr inbounds %Str_Node, ptr %t91, i32 0, i32 4 + %t93 = load ptr, ptr %t92 + call void @fn_emit_block(ptr %t93) + %t94 = load i32, ptr @g_g_term + %t95 = icmp eq i32 %t94, 0 + %t96 = zext i1 %t95 to i32 + %t97 = icmp ne i32 %t96, 0 + br i1 %t97, label %then8, label %ifend10 +then8: + call void @fn_emit(ptr @.str1271) + %t98 = load ptr, ptr %t49 + call void @fn_emit(ptr %t98) + call void @fn_emit(ptr @.str1272) + br label %ifend10 +ifend10: + %t99 = load ptr, ptr %t86 + call void @fn_emit(ptr %t99) + call void @fn_emit(ptr @.str1273) + store i32 0, ptr @g_g_term + %t100 = load i32, ptr %t50 + %t101 = add i32 %t100, 1 + store i32 %t101, ptr %t50 + br label %wcond5 +wend7: + %t102 = load i32, ptr @g_g_term + %t103 = icmp eq i32 %t102, 0 + %t104 = zext i1 %t103 to i32 + %t105 = icmp ne i32 %t104, 0 + br i1 %t105, label %then11, label %ifend13 +then11: + call void @fn_emit(ptr @.str1274) + %t106 = load ptr, ptr %t49 + call void @fn_emit(ptr %t106) + call void @fn_emit(ptr @.str1275) + br label %ifend13 +ifend13: + %t107 = load ptr, ptr %t49 + call void @fn_emit(ptr %t107) + call void @fn_emit(ptr @.str1276) + store i32 0, ptr @g_g_term + %t108 = load i32, ptr @g_nmach + %t109 = sub i32 %t108, 1 + store i32 %t109, ptr @g_nmach + br label %ret +ret: + ret void +} + +define void @fn_emit_become(ptr %arg_st) { +entry: + %t0 = alloca ptr + %t12 = alloca ptr + %t13 = alloca ptr + %t14 = alloca i32 + %t61 = alloca ptr + %t66 = alloca ptr + store ptr %arg_st, ptr %t0 + %t1 = load i32, ptr @g_nmach + %t2 = icmp eq i32 %t1, 0 + %t3 = zext i1 %t2 to i32 + %t4 = icmp ne i32 %t3, 0 + br i1 %t4, label %then0, label %ifend2 +then0: + call void @fn_perr(ptr @.str1277) + br label %ifend2 +ifend2: + %t5 = load ptr, ptr @g_mach_stk + %t6 = getelementptr inbounds %LSlice, ptr %t5, i32 0, i32 0 + %t7 = load ptr, ptr %t6 + %t8 = load i32, ptr @g_nmach + %t9 = sub i32 %t8, 1 + %t10 = getelementptr inbounds ptr, ptr %t7, i32 %t9 + %t11 = load ptr, ptr %t10 + store ptr %t11, ptr %t12 + store ptr null, ptr %t13 + store i32 0, ptr %t14 + br label %wcond3 +wcond3: + %t15 = load i32, ptr %t14 + %t16 = load ptr, ptr %t12 + %t17 = getelementptr inbounds %Str_Node, ptr %t16, i32 0, i32 7 + %t18 = load ptr, ptr %t17 + %t19 = getelementptr inbounds %LSlice, ptr %t18, i32 0, i32 1 + %t20 = load i32, ptr %t19 + %t21 = icmp slt i32 %t15, %t20 + %t22 = zext i1 %t21 to i32 + %t23 = icmp ne i32 %t22, 0 + br i1 %t23, label %wbody4, label %wend5 +wbody4: + %t24 = load ptr, ptr %t12 + %t25 = getelementptr inbounds %Str_Node, ptr %t24, i32 0, i32 7 + %t26 = load ptr, ptr %t25 + %t27 = getelementptr inbounds %LSlice, ptr %t26, i32 0, i32 0 + %t28 = load ptr, ptr %t27 + %t29 = load i32, ptr %t14 + %t30 = getelementptr inbounds ptr, ptr %t28, i32 %t29 + %t31 = load ptr, ptr %t30 + %t32 = getelementptr inbounds %Str_Node, ptr %t31, i32 0, i32 1 + %t33 = load ptr, ptr %t32 + %t34 = load ptr, ptr %t0 + %t35 = getelementptr inbounds %Str_Node, ptr %t34, i32 0, i32 1 + %t36 = load ptr, ptr %t35 + %t37 = call i32 @fn_streq(ptr %t33, ptr %t36) + %t38 = icmp ne i32 %t37, 0 + br i1 %t38, label %then6, label %ifend8 +then6: + %t39 = load ptr, ptr %t12 + %t40 = getelementptr inbounds %Str_Node, ptr %t39, i32 0, i32 7 + %t41 = load ptr, ptr %t40 + %t42 = getelementptr inbounds %LSlice, ptr %t41, i32 0, i32 0 + %t43 = load ptr, ptr %t42 + %t44 = load i32, ptr %t14 + %t45 = getelementptr inbounds ptr, ptr %t43, i32 %t44 + %t46 = load ptr, ptr %t45 + store ptr %t46, ptr %t13 + br label %ifend8 +ifend8: + %t47 = load i32, ptr %t14 + %t48 = add i32 %t47, 1 + store i32 %t48, ptr %t14 + br label %wcond3 +wend5: + %t49 = load ptr, ptr %t13 + %t50 = icmp eq ptr %t49, null + %t51 = zext i1 %t50 to i32 + %t52 = icmp ne i32 %t51, 0 + br i1 %t52, label %then9, label %ifend11 +then9: + %t53 = load ptr, ptr %t0 + %t54 = getelementptr inbounds %Str_Node, ptr %t53, i32 0, i32 1 + %t55 = load ptr, ptr %t54 + %t56 = call ptr @fn_sconcat(ptr @.str1278, ptr %t55) + call void @fn_perr(ptr %t56) + br label %ifend11 +ifend11: + %t57 = load ptr, ptr %t12 + %t58 = getelementptr inbounds %Str_Node, ptr %t57, i32 0, i32 4 + %t59 = load ptr, ptr %t58 + %t60 = call ptr @fn_emit_expr(ptr %t59) + store ptr %t60, ptr %t61 + %t62 = load ptr, ptr %t13 + %t63 = getelementptr inbounds %Str_Node, ptr %t62, i32 0, i32 5 + %t64 = load ptr, ptr %t63 + %t65 = call ptr @fn_emit_expr(ptr %t64) + store ptr %t65, ptr %t66 + call void @fn_emit(ptr @.str1279) + %t67 = load ptr, ptr %t61 + %t68 = getelementptr inbounds %Str_Val, ptr %t67, i32 0, i32 0 + %t69 = load ptr, ptr %t68 + call void @fn_emit(ptr %t69) + call void @fn_emit(ptr @.str1280) + %t70 = load ptr, ptr %t66 + %t71 = getelementptr inbounds %Str_Val, ptr %t70, i32 0, i32 0 + %t72 = load ptr, ptr %t71 + call void @fn_emit(ptr %t72) + call void @fn_emit(ptr @.str1281) + br label %ret +ret: + ret void +} + +define void @fn_emit_io(ptr %arg_fn2, ptr %arg_p, ptr %arg_bytes) { +entry: + %t0 = alloca ptr + %t1 = alloca ptr + %t2 = alloca ptr + %t6 = alloca ptr + store ptr %arg_fn2, ptr %t0 + store ptr %arg_p, ptr %t1 + store ptr %arg_bytes, ptr %t2 + %t3 = load i32, ptr @g_g_iok + %t4 = call ptr @fn_itoa(i32 %t3) + %t5 = call ptr @fn_sconcat(ptr @.str1282, ptr %t4) + store ptr %t5, ptr %t6 + %t7 = load i32, ptr @g_g_iok + %t8 = add i32 %t7, 1 + store i32 %t8, ptr @g_g_iok + call void @fn_emit(ptr @.str1283) + %t9 = load ptr, ptr %t6 + call void @fn_emit(ptr %t9) + call void @fn_emit(ptr @.str1284) + %t10 = load ptr, ptr %t0 + call void @fn_emit(ptr %t10) + call void @fn_emit(ptr @.str1285) + %t11 = load ptr, ptr %t1 + call void @fn_emit(ptr %t11) + call void @fn_emit(ptr @.str1286) + %t12 = load ptr, ptr %t2 + call void @fn_emit(ptr %t12) + call void @fn_emit(ptr @.str1287) + br label %ret +ret: + ret void +} + +define void @fn_emit_snapshot_blocks(ptr %arg_fn2) { +entry: + %t0 = alloca ptr + %t2 = alloca ptr + %t9 = alloca i32 + %t40 = alloca i32 + %t67 = alloca ptr + %t71 = alloca ptr + store ptr %arg_fn2, ptr %t0 + store i32 0, ptr @g_g_iok + %t1 = call ptr @fn_itoa(i32 1024) + store ptr %t1, ptr %t2 + %t3 = load ptr, ptr %t0 + call void @fn_emit_io(ptr %t3, ptr @.str1288, ptr @.str1289) + %t4 = load ptr, ptr %t0 + call void @fn_emit_io(ptr %t4, ptr @.str1290, ptr @.str1291) + call void @fn_emit(ptr @.str1292) + %t5 = load ptr, ptr %t2 + call void @fn_emit(ptr %t5) + call void @fn_emit(ptr @.str1293) + %t6 = load ptr, ptr %t0 + call void @fn_emit_io(ptr %t6, ptr @.str1294, ptr @.str1295) + %t7 = load ptr, ptr %t0 + call void @fn_emit_io(ptr %t7, ptr @.str1296, ptr @.str1297) + %t8 = load ptr, ptr %t0 + call void @fn_emit_io(ptr %t8, ptr @.str1298, ptr @.str1299) + store i32 0, ptr %t9 + br label %wcond0 +wcond0: + %t10 = load i32, ptr %t9 + %t11 = load ptr, ptr @g_prog + %t12 = getelementptr inbounds %LSlice, ptr %t11, i32 0, i32 1 + %t13 = load i32, ptr %t12 + %t14 = icmp slt i32 %t10, %t13 + %t15 = zext i1 %t14 to i32 + %t16 = icmp ne i32 %t15, 0 + br i1 %t16, label %wbody1, label %wend2 +wbody1: + %t17 = load ptr, ptr @g_prog + %t18 = getelementptr inbounds %LSlice, ptr %t17, i32 0, i32 0 + %t19 = load ptr, ptr %t18 + %t20 = load i32, ptr %t9 + %t21 = getelementptr inbounds ptr, ptr %t19, i32 %t20 + %t22 = load ptr, ptr %t21 + %t23 = getelementptr inbounds %Str_Node, ptr %t22, i32 0, i32 0 + %t24 = load i32, ptr %t23 + %t25 = icmp eq i32 %t24, 2 + %t26 = zext i1 %t25 to i32 + %t27 = icmp ne i32 %t26, 0 + br i1 %t27, label %then3, label %ifend5 +then3: + %t28 = load ptr, ptr %t0 + %t29 = load ptr, ptr @g_prog + %t30 = getelementptr inbounds %LSlice, ptr %t29, i32 0, i32 0 + %t31 = load ptr, ptr %t30 + %t32 = load i32, ptr %t9 + %t33 = getelementptr inbounds ptr, ptr %t31, i32 %t32 + %t34 = load ptr, ptr %t33 + %t35 = getelementptr inbounds %Str_Node, ptr %t34, i32 0, i32 1 + %t36 = load ptr, ptr %t35 + %t37 = call ptr @fn_sconcat(ptr @.str1300, ptr %t36) + call void @fn_emit_io(ptr %t28, ptr %t37, ptr @.str1301) + br label %ifend5 +ifend5: + %t38 = load i32, ptr %t9 + %t39 = add i32 %t38, 1 + store i32 %t39, ptr %t9 + br label %wcond0 +wend2: + store i32 0, ptr %t40 + store i32 0, ptr %t9 + br label %wcond6 +wcond6: + %t41 = load i32, ptr %t9 + %t42 = load ptr, ptr @g_prog + %t43 = getelementptr inbounds %LSlice, ptr %t42, i32 0, i32 1 + %t44 = load i32, ptr %t43 + %t45 = icmp slt i32 %t41, %t44 + %t46 = zext i1 %t45 to i32 + %t47 = icmp ne i32 %t46, 0 + br i1 %t47, label %wbody7, label %wend8 +wbody7: + %t48 = load ptr, ptr @g_prog + %t49 = getelementptr inbounds %LSlice, ptr %t48, i32 0, i32 0 + %t50 = load ptr, ptr %t49 + %t51 = load i32, ptr %t9 + %t52 = getelementptr inbounds ptr, ptr %t50, i32 %t51 + %t53 = load ptr, ptr %t52 + %t54 = getelementptr inbounds %Str_Node, ptr %t53, i32 0, i32 0 + %t55 = load i32, ptr %t54 + %t56 = icmp eq i32 %t55, 8 + %t57 = zext i1 %t56 to i32 + %t58 = icmp ne i32 %t57, 0 + br i1 %t58, label %then9, label %ifend11 +then9: + %t59 = load ptr, ptr @g_prog + %t60 = getelementptr inbounds %LSlice, ptr %t59, i32 0, i32 0 + %t61 = load ptr, ptr %t60 + %t62 = load i32, ptr %t9 + %t63 = getelementptr inbounds ptr, ptr %t61, i32 %t62 + %t64 = load ptr, ptr %t63 + %t65 = getelementptr inbounds %Str_Node, ptr %t64, i32 0, i32 1 + %t66 = load ptr, ptr %t65 + store ptr %t66, ptr %t67 + %t68 = load i32, ptr %t40 + %t69 = call ptr @fn_itoa(i32 %t68) + %t70 = call ptr @fn_sconcat(ptr @.str1302, ptr %t69) + store ptr %t70, ptr %t71 + call void @fn_emit(ptr @.str1303) + %t72 = load ptr, ptr %t71 + call void @fn_emit(ptr %t72) + call void @fn_emit(ptr @.str1304) + %t73 = load ptr, ptr %t67 + call void @fn_emit(ptr %t73) + call void @fn_emit(ptr @.str1305) + %t74 = load ptr, ptr %t2 + call void @fn_emit(ptr %t74) + call void @fn_emit(ptr @.str1306) + %t75 = load ptr, ptr %t0 + %t76 = load ptr, ptr %t67 + %t77 = call ptr @fn_sconcat(ptr @.str1307, ptr %t76) + %t78 = load ptr, ptr %t71 + call void @fn_emit_io(ptr %t75, ptr %t77, ptr %t78) + %t79 = load ptr, ptr %t0 + %t80 = load ptr, ptr %t67 + %t81 = call ptr @fn_sconcat(ptr @.str1308, ptr %t80) + %t82 = load ptr, ptr %t2 + call void @fn_emit_io(ptr %t79, ptr %t81, ptr %t82) + %t83 = load i32, ptr %t40 + %t84 = add i32 %t83, 1 + store i32 %t84, ptr %t40 + br label %ifend11 +ifend11: + %t85 = load i32, ptr %t9 + %t86 = add i32 %t85, 1 + store i32 %t86, ptr %t9 + br label %wcond6 +wend8: + br label %ret +ret: + ret void +} + +define void @fn_emit_snapshot() { +entry: + %t5 = alloca i32 + %t11 = alloca i32 + call void @fn_emith(ptr @.str1309) + call void @fn_emith(ptr @.str1310) + call void @fn_emith(ptr @.str1311) + %t0 = call ptr @fn_find_fn(ptr @.str1312) + %t1 = icmp eq ptr %t0, null + %t2 = zext i1 %t1 to i32 + %t3 = icmp eq i32 %t2, 0 + %t4 = zext i1 %t3 to i32 + store i32 %t4, ptr %t5 + %t6 = call ptr @fn_find_fn(ptr @.str1313) + %t7 = icmp eq ptr %t6, null + %t8 = zext i1 %t7 to i32 + %t9 = icmp eq i32 %t8, 0 + %t10 = zext i1 %t9 to i32 + store i32 %t10, ptr %t11 + call void @fn_emit(ptr @.str1314) + call void @fn_emit(ptr @.str1315) + call void @fn_emit(ptr @.str1316) + call void @fn_emit(ptr @.str1317) + call void @fn_emit_snapshot_blocks(ptr @.str1318) + %t12 = load i32, ptr %t5 + %t13 = icmp ne i32 %t12, 0 + br i1 %t13, label %then0, label %ifend2 +then0: + call void @fn_emit(ptr @.str1319) + br label %ifend2 +ifend2: + call void @fn_emit(ptr @.str1320) + call void @fn_emit(ptr @.str1321) + call void @fn_emit(ptr @.str1322) + call void @fn_emit(ptr @.str1323) + call void @fn_emit(ptr @.str1324) + call void @fn_emit_snapshot_blocks(ptr @.str1325) + %t14 = load i32, ptr %t11 + %t15 = icmp ne i32 %t14, 0 + br i1 %t15, label %then3, label %ifend5 +then3: + call void @fn_emit(ptr @.str1326) + br label %ifend5 +ifend5: + call void @fn_emit(ptr @.str1327) + br label %ret +ret: + ret void +} + +define i32 @fn_ui_wtype(ptr %arg_w) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t4 = alloca ptr + store ptr %arg_w, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = getelementptr inbounds %Str_Node, ptr %t1, i32 0, i32 1 + %t3 = load ptr, ptr %t2 + store ptr %t3, ptr %t4 + %t5 = load ptr, ptr %t4 + %t6 = call i32 @fn_streq(ptr %t5, ptr @.str1328) + %t7 = icmp ne i32 %t6, 0 + br i1 %t7, label %then0, label %ifend2 +then0: + store i32 0, ptr %retval + br label %ret +ifend2: + %t8 = load ptr, ptr %t4 + %t9 = call i32 @fn_streq(ptr %t8, ptr @.str1329) + %t10 = icmp ne i32 %t9, 0 + br i1 %t10, label %then3, label %ifend5 +then3: + store i32 1, ptr %retval + br label %ret +ifend5: + %t11 = load ptr, ptr %t4 + %t12 = call i32 @fn_streq(ptr %t11, ptr @.str1330) + %t13 = icmp ne i32 %t12, 0 + br i1 %t13, label %then6, label %ifend8 +then6: + store i32 2, ptr %retval + br label %ret +ifend8: + %t14 = load ptr, ptr %t4 + %t15 = call i32 @fn_streq(ptr %t14, ptr @.str1331) + %t16 = icmp ne i32 %t15, 0 + br i1 %t16, label %then9, label %ifend11 +then9: + store i32 3, ptr %retval + br label %ret +ifend11: + %t17 = load ptr, ptr %t4 + %t18 = call i32 @fn_streq(ptr %t17, ptr @.str1332) + %t19 = icmp ne i32 %t18, 0 + br i1 %t19, label %then12, label %ifend14 +then12: + store i32 4, ptr %retval + br label %ret +ifend14: + %t20 = load ptr, ptr %t4 + %t21 = call i32 @fn_streq(ptr %t20, ptr @.str1333) + %t22 = icmp ne i32 %t21, 0 + br i1 %t22, label %then15, label %ifend17 +then15: + store i32 5, ptr %retval + br label %ret +ifend17: + %t23 = load ptr, ptr %t4 + %t24 = call i32 @fn_streq(ptr %t23, ptr @.str1334) + %t25 = icmp ne i32 %t24, 0 + br i1 %t25, label %then18, label %ifend20 +then18: + store i32 6, ptr %retval + br label %ret +ifend20: + store i32 0, ptr %retval + br label %ret +ret: + %t26 = load i32, ptr %retval + ret i32 %t26 +} + +define ptr @fn_ui_prop(ptr %arg_w, ptr %arg_key) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca ptr + %t2 = alloca i32 + store ptr %arg_w, ptr %t0 + store ptr %arg_key, ptr %t1 + store i32 0, ptr %t2 + br label %wcond0 +wcond0: + %t3 = load i32, ptr %t2 + %t4 = load ptr, ptr %t0 + %t5 = getelementptr inbounds %Str_Node, ptr %t4, i32 0, i32 5 + %t6 = load ptr, ptr %t5 + %t7 = getelementptr inbounds %Str_Node, ptr %t6, i32 0, i32 7 + %t8 = load ptr, ptr %t7 + %t9 = getelementptr inbounds %LSlice, ptr %t8, i32 0, i32 1 + %t10 = load i32, ptr %t9 + %t11 = icmp slt i32 %t3, %t10 + %t12 = zext i1 %t11 to i32 + %t13 = icmp ne i32 %t12, 0 + br i1 %t13, label %wbody1, label %wend2 +wbody1: + %t14 = load ptr, ptr %t0 + %t15 = getelementptr inbounds %Str_Node, ptr %t14, i32 0, i32 5 + %t16 = load ptr, ptr %t15 + %t17 = getelementptr inbounds %Str_Node, ptr %t16, i32 0, i32 7 + %t18 = load ptr, ptr %t17 + %t19 = getelementptr inbounds %LSlice, ptr %t18, i32 0, i32 0 + %t20 = load ptr, ptr %t19 + %t21 = load i32, ptr %t2 + %t22 = getelementptr inbounds ptr, ptr %t20, i32 %t21 + %t23 = load ptr, ptr %t22 + %t24 = getelementptr inbounds %Str_Node, ptr %t23, i32 0, i32 1 + %t25 = load ptr, ptr %t24 + %t26 = load ptr, ptr %t1 + %t27 = call i32 @fn_streq(ptr %t25, ptr %t26) + %t28 = icmp ne i32 %t27, 0 + br i1 %t28, label %then3, label %ifend5 +then3: + %t29 = load ptr, ptr %t0 + %t30 = getelementptr inbounds %Str_Node, ptr %t29, i32 0, i32 5 + %t31 = load ptr, ptr %t30 + %t32 = getelementptr inbounds %Str_Node, ptr %t31, i32 0, i32 7 + %t33 = load ptr, ptr %t32 + %t34 = getelementptr inbounds %LSlice, ptr %t33, i32 0, i32 0 + %t35 = load ptr, ptr %t34 + %t36 = load i32, ptr %t2 + %t37 = getelementptr inbounds ptr, ptr %t35, i32 %t36 + %t38 = load ptr, ptr %t37 + %t39 = getelementptr inbounds %Str_Node, ptr %t38, i32 0, i32 4 + %t40 = load ptr, ptr %t39 + store ptr %t40, ptr %retval + br label %ret +ifend5: + %t41 = load i32, ptr %t2 + %t42 = add i32 %t41, 1 + store i32 %t42, ptr %t2 + br label %wcond0 +wend2: + store ptr null, ptr %retval + br label %ret +ret: + %t43 = load ptr, ptr %retval + ret ptr %t43 +} + +define void @fn_ui_flatten(ptr %arg_w, i32 %arg_parent) { +entry: + %t0 = alloca ptr + %t1 = alloca i32 + %t5 = alloca i32 + %t46 = alloca i32 + store ptr %arg_w, ptr %t0 + store i32 %arg_parent, ptr %t1 + %t2 = load ptr, ptr @g_uiw + %t3 = getelementptr inbounds %LSlice, ptr %t2, i32 0, i32 1 + %t4 = load i32, ptr %t3 + store i32 %t4, ptr %t5 + %t6 = load ptr, ptr @g_uiw + %t7 = getelementptr inbounds %LSlice, ptr %t6, i32 0, i32 1 + %t8 = getelementptr inbounds %LSlice, ptr %t6, i32 0, i32 2 + %t9 = getelementptr inbounds %LSlice, ptr %t6, i32 0, i32 0 + %t10 = load i32, ptr %t7 + %t11 = load i32, ptr %t8 + %t12 = icmp sge i32 %t10, %t11 + br i1 %t12, label %grow0, label %put1 +grow0: + %t13 = mul i32 %t11, 2 + %t14 = icmp eq i32 %t11, 0 + %t15 = select i1 %t14, i32 8, i32 %t13 + %t16 = getelementptr ptr, ptr null, i32 1 + %t17 = ptrtoint ptr %t16 to i64 + %t18 = zext i32 %t15 to i64 + %t19 = mul i64 %t18, %t17 + %t20 = load ptr, ptr %t9 + %t21 = call ptr @realloc(ptr %t20, i64 %t19) + store ptr %t21, ptr %t9 + store i32 %t15, ptr %t8 + br label %put1 +put1: + %t22 = load ptr, ptr %t0 + %t23 = load ptr, ptr %t9 + %t24 = getelementptr inbounds ptr, ptr %t23, i32 %t10 + store ptr %t22, ptr %t24 + %t25 = add i32 %t10, 1 + store i32 %t25, ptr %t7 + %t26 = load ptr, ptr @g_uiw_parent + %t27 = getelementptr inbounds %LSlice, ptr %t26, i32 0, i32 1 + %t28 = getelementptr inbounds %LSlice, ptr %t26, i32 0, i32 2 + %t29 = getelementptr inbounds %LSlice, ptr %t26, i32 0, i32 0 + %t30 = load i32, ptr %t27 + %t31 = load i32, ptr %t28 + %t32 = icmp sge i32 %t30, %t31 + br i1 %t32, label %grow2, label %put3 +grow2: + %t33 = mul i32 %t31, 2 + %t34 = icmp eq i32 %t31, 0 + %t35 = select i1 %t34, i32 8, i32 %t33 + %t36 = getelementptr i32, ptr null, i32 1 + %t37 = ptrtoint ptr %t36 to i64 + %t38 = zext i32 %t35 to i64 + %t39 = mul i64 %t38, %t37 + %t40 = load ptr, ptr %t29 + %t41 = call ptr @realloc(ptr %t40, i64 %t39) + store ptr %t41, ptr %t29 + store i32 %t35, ptr %t28 + br label %put3 +put3: + %t42 = load i32, ptr %t1 + %t43 = load ptr, ptr %t29 + %t44 = getelementptr inbounds i32, ptr %t43, i32 %t30 + store i32 %t42, ptr %t44 + %t45 = add i32 %t30, 1 + store i32 %t45, ptr %t27 + store i32 0, ptr %t46 + br label %wcond4 +wcond4: + %t47 = load i32, ptr %t46 + %t48 = load ptr, ptr %t0 + %t49 = getelementptr inbounds %Str_Node, ptr %t48, i32 0, i32 7 + %t50 = load ptr, ptr %t49 + %t51 = getelementptr inbounds %LSlice, ptr %t50, i32 0, i32 1 + %t52 = load i32, ptr %t51 + %t53 = icmp slt i32 %t47, %t52 + %t54 = zext i1 %t53 to i32 + %t55 = icmp ne i32 %t54, 0 + br i1 %t55, label %wbody5, label %wend6 +wbody5: + %t56 = load ptr, ptr %t0 + %t57 = getelementptr inbounds %Str_Node, ptr %t56, i32 0, i32 7 + %t58 = load ptr, ptr %t57 + %t59 = getelementptr inbounds %LSlice, ptr %t58, i32 0, i32 0 + %t60 = load ptr, ptr %t59 + %t61 = load i32, ptr %t46 + %t62 = getelementptr inbounds ptr, ptr %t60, i32 %t61 + %t63 = load ptr, ptr %t62 + %t64 = load i32, ptr %t5 + call void @fn_ui_flatten(ptr %t63, i32 %t64) + %t65 = load i32, ptr %t46 + %t66 = add i32 %t65, 1 + store i32 %t66, ptr %t46 + br label %wcond4 +wend6: + br label %ret +ret: + ret void +} + +define void @fn_ui_flatten_all() { +entry: + %t18 = alloca i32 + %t26 = alloca i32 + %t0 = getelementptr %LSlice, ptr null, i32 1 + %t1 = ptrtoint ptr %t0 to i64 + %t2 = call ptr @malloc(i64 %t1) + %t3 = getelementptr inbounds %LSlice, ptr %t2, i32 0, i32 0 + store ptr null, ptr %t3 + %t4 = getelementptr inbounds %LSlice, ptr %t2, i32 0, i32 1 + store i32 0, ptr %t4 + %t5 = getelementptr inbounds %LSlice, ptr %t2, i32 0, i32 2 + store i32 0, ptr %t5 + store ptr %t2, ptr @g_uiw + %t6 = getelementptr %LSlice, ptr null, i32 1 + %t7 = ptrtoint ptr %t6 to i64 + %t8 = call ptr @malloc(i64 %t7) + %t9 = getelementptr inbounds %LSlice, ptr %t8, i32 0, i32 0 + store ptr null, ptr %t9 + %t10 = getelementptr inbounds %LSlice, ptr %t8, i32 0, i32 1 + store i32 0, ptr %t10 + %t11 = getelementptr inbounds %LSlice, ptr %t8, i32 0, i32 2 + store i32 0, ptr %t11 + store ptr %t8, ptr @g_uiw_parent + %t12 = getelementptr %LSlice, ptr null, i32 1 + %t13 = ptrtoint ptr %t12 to i64 + %t14 = call ptr @malloc(i64 %t13) + %t15 = getelementptr inbounds %LSlice, ptr %t14, i32 0, i32 0 + store ptr null, ptr %t15 + %t16 = getelementptr inbounds %LSlice, ptr %t14, i32 0, i32 1 + store i32 0, ptr %t16 + %t17 = getelementptr inbounds %LSlice, ptr %t14, i32 0, i32 2 + store i32 0, ptr %t17 + store ptr %t14, ptr @g_ui_roots + store i32 0, ptr %t18 + br label %wcond0 +wcond0: + %t19 = load i32, ptr %t18 + %t20 = load ptr, ptr @g_prog + %t21 = getelementptr inbounds %LSlice, ptr %t20, i32 0, i32 1 + %t22 = load i32, ptr %t21 + %t23 = icmp slt i32 %t19, %t22 + %t24 = zext i1 %t23 to i32 + %t25 = icmp ne i32 %t24, 0 + br i1 %t25, label %wbody1, label %wend2 +wbody1: + %t27 = load ptr, ptr @g_prog + %t28 = getelementptr inbounds %LSlice, ptr %t27, i32 0, i32 0 + %t29 = load ptr, ptr %t28 + %t30 = load i32, ptr %t18 + %t31 = getelementptr inbounds ptr, ptr %t29, i32 %t30 + %t32 = load ptr, ptr %t31 + %t33 = getelementptr inbounds %Str_Node, ptr %t32, i32 0, i32 0 + %t34 = load i32, ptr %t33 + %t35 = icmp eq i32 %t34, 12 + %t36 = zext i1 %t35 to i32 + %t37 = icmp ne i32 %t36, 0 + %t38 = zext i1 %t37 to i32 + store i32 %t38, ptr %t26 + br i1 %t37, label %sc3, label %scend4 +sc3: + %t39 = load ptr, ptr @g_prog + %t40 = getelementptr inbounds %LSlice, ptr %t39, i32 0, i32 0 + %t41 = load ptr, ptr %t40 + %t42 = load i32, ptr %t18 + %t43 = getelementptr inbounds ptr, ptr %t41, i32 %t42 + %t44 = load ptr, ptr %t43 + %t45 = getelementptr inbounds %Str_Node, ptr %t44, i32 0, i32 2 + %t46 = load i32, ptr %t45 + %t47 = icmp eq i32 %t46, 1 + %t48 = zext i1 %t47 to i32 + %t49 = icmp ne i32 %t48, 0 + %t50 = zext i1 %t49 to i32 + store i32 %t50, ptr %t26 + br label %scend4 +scend4: + %t51 = load i32, ptr %t26 + %t52 = icmp ne i32 %t51, 0 + br i1 %t52, label %then5, label %ifend7 +then5: + %t53 = load ptr, ptr @g_ui_roots + %t54 = getelementptr inbounds %LSlice, ptr %t53, i32 0, i32 1 + %t55 = getelementptr inbounds %LSlice, ptr %t53, i32 0, i32 2 + %t56 = getelementptr inbounds %LSlice, ptr %t53, i32 0, i32 0 + %t57 = load i32, ptr %t54 + %t58 = load i32, ptr %t55 + %t59 = icmp sge i32 %t57, %t58 + br i1 %t59, label %grow8, label %put9 +grow8: + %t60 = mul i32 %t58, 2 + %t61 = icmp eq i32 %t58, 0 + %t62 = select i1 %t61, i32 8, i32 %t60 + %t63 = getelementptr i32, ptr null, i32 1 + %t64 = ptrtoint ptr %t63 to i64 + %t65 = zext i32 %t62 to i64 + %t66 = mul i64 %t65, %t64 + %t67 = load ptr, ptr %t56 + %t68 = call ptr @realloc(ptr %t67, i64 %t66) + store ptr %t68, ptr %t56 + store i32 %t62, ptr %t55 + br label %put9 +put9: + %t69 = load ptr, ptr @g_uiw + %t70 = getelementptr inbounds %LSlice, ptr %t69, i32 0, i32 1 + %t71 = load i32, ptr %t70 + %t72 = load ptr, ptr %t56 + %t73 = getelementptr inbounds i32, ptr %t72, i32 %t57 + store i32 %t71, ptr %t73 + %t74 = add i32 %t57, 1 + store i32 %t74, ptr %t54 + %t75 = load ptr, ptr @g_prog + %t76 = getelementptr inbounds %LSlice, ptr %t75, i32 0, i32 0 + %t77 = load ptr, ptr %t76 + %t78 = load i32, ptr %t18 + %t79 = getelementptr inbounds ptr, ptr %t77, i32 %t78 + %t80 = load ptr, ptr %t79 + %t81 = getelementptr inbounds %Str_Node, ptr %t80, i32 0, i32 4 + %t82 = load ptr, ptr %t81 + %t83 = sub i32 0, 1 + call void @fn_ui_flatten(ptr %t82, i32 %t83) + br label %ifend7 +ifend7: + %t84 = load i32, ptr %t18 + %t85 = add i32 %t84, 1 + store i32 %t85, ptr %t18 + br label %wcond0 +wend2: + br label %ret +ret: + ret void +} + +define i32 @fn_has_ui() { +entry: + %retval = alloca i32 + %t0 = alloca i32 + %t8 = alloca i32 + store i32 0, ptr %t0 + br label %wcond0 +wcond0: + %t1 = load i32, ptr %t0 + %t2 = load ptr, ptr @g_prog + %t3 = getelementptr inbounds %LSlice, ptr %t2, i32 0, i32 1 + %t4 = load i32, ptr %t3 + %t5 = icmp slt i32 %t1, %t4 + %t6 = zext i1 %t5 to i32 + %t7 = icmp ne i32 %t6, 0 + br i1 %t7, label %wbody1, label %wend2 +wbody1: + %t9 = load ptr, ptr @g_prog + %t10 = getelementptr inbounds %LSlice, ptr %t9, i32 0, i32 0 + %t11 = load ptr, ptr %t10 + %t12 = load i32, ptr %t0 + %t13 = getelementptr inbounds ptr, ptr %t11, i32 %t12 + %t14 = load ptr, ptr %t13 + %t15 = getelementptr inbounds %Str_Node, ptr %t14, i32 0, i32 0 + %t16 = load i32, ptr %t15 + %t17 = icmp eq i32 %t16, 12 + %t18 = zext i1 %t17 to i32 + %t19 = icmp ne i32 %t18, 0 + %t20 = zext i1 %t19 to i32 + store i32 %t20, ptr %t8 + br i1 %t19, label %sc3, label %scend4 +sc3: + %t21 = load ptr, ptr @g_prog + %t22 = getelementptr inbounds %LSlice, ptr %t21, i32 0, i32 0 + %t23 = load ptr, ptr %t22 + %t24 = load i32, ptr %t0 + %t25 = getelementptr inbounds ptr, ptr %t23, i32 %t24 + %t26 = load ptr, ptr %t25 + %t27 = getelementptr inbounds %Str_Node, ptr %t26, i32 0, i32 2 + %t28 = load i32, ptr %t27 + %t29 = icmp eq i32 %t28, 1 + %t30 = zext i1 %t29 to i32 + %t31 = icmp ne i32 %t30, 0 + %t32 = zext i1 %t31 to i32 + store i32 %t32, ptr %t8 + br label %scend4 +scend4: + %t33 = load i32, ptr %t8 + %t34 = icmp ne i32 %t33, 0 + br i1 %t34, label %then5, label %ifend7 +then5: + store i32 1, ptr %retval + br label %ret +ifend7: + %t35 = load i32, ptr %t0 + %t36 = add i32 %t35, 1 + store i32 %t36, ptr %t0 + br label %wcond0 +wend2: + store i32 0, ptr %retval + br label %ret +ret: + %t37 = load i32, ptr %retval + ret i32 %t37 +} + +define i32 @fn_ui_index_of(ptr %arg_nm) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t6 = alloca ptr + %t7 = alloca i32 + %t8 = alloca i32 + %t9 = alloca i32 + %t17 = alloca i32 + %t79 = alloca ptr + %t86 = alloca i32 + store ptr %arg_nm, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = load ptr, ptr %t0 + %t3 = call i32 @fn_slen(ptr %t2) + %t4 = sub i32 %t3, 3 + %t5 = call ptr @fn_substr(ptr %t1, i32 3, i32 %t4) + store ptr %t5, ptr %t6 + store i32 0, ptr %t7 + store i32 0, ptr %t8 + store i32 0, ptr %t9 + br label %wcond0 +wcond0: + %t10 = load i32, ptr %t9 + %t11 = load ptr, ptr @g_prog + %t12 = getelementptr inbounds %LSlice, ptr %t11, i32 0, i32 1 + %t13 = load i32, ptr %t12 + %t14 = icmp slt i32 %t10, %t13 + %t15 = zext i1 %t14 to i32 + %t16 = icmp ne i32 %t15, 0 + br i1 %t16, label %wbody1, label %wend2 +wbody1: + %t18 = load ptr, ptr @g_prog + %t19 = getelementptr inbounds %LSlice, ptr %t18, i32 0, i32 0 + %t20 = load ptr, ptr %t19 + %t21 = load i32, ptr %t9 + %t22 = getelementptr inbounds ptr, ptr %t20, i32 %t21 + %t23 = load ptr, ptr %t22 + %t24 = getelementptr inbounds %Str_Node, ptr %t23, i32 0, i32 0 + %t25 = load i32, ptr %t24 + %t26 = icmp eq i32 %t25, 12 + %t27 = zext i1 %t26 to i32 + %t28 = icmp ne i32 %t27, 0 + %t29 = zext i1 %t28 to i32 + store i32 %t29, ptr %t17 + br i1 %t28, label %sc3, label %scend4 +sc3: + %t30 = load ptr, ptr @g_prog + %t31 = getelementptr inbounds %LSlice, ptr %t30, i32 0, i32 0 + %t32 = load ptr, ptr %t31 + %t33 = load i32, ptr %t9 + %t34 = getelementptr inbounds ptr, ptr %t32, i32 %t33 + %t35 = load ptr, ptr %t34 + %t36 = getelementptr inbounds %Str_Node, ptr %t35, i32 0, i32 2 + %t37 = load i32, ptr %t36 + %t38 = icmp eq i32 %t37, 1 + %t39 = zext i1 %t38 to i32 + %t40 = icmp ne i32 %t39, 0 + %t41 = zext i1 %t40 to i32 + store i32 %t41, ptr %t17 + br label %scend4 +scend4: + %t42 = load i32, ptr %t17 + %t43 = icmp ne i32 %t42, 0 + br i1 %t43, label %then5, label %ifend7 +then5: + %t44 = load ptr, ptr @g_prog + %t45 = getelementptr inbounds %LSlice, ptr %t44, i32 0, i32 0 + %t46 = load ptr, ptr %t45 + %t47 = load i32, ptr %t9 + %t48 = getelementptr inbounds ptr, ptr %t46, i32 %t47 + %t49 = load ptr, ptr %t48 + %t50 = getelementptr inbounds %Str_Node, ptr %t49, i32 0, i32 1 + %t51 = load ptr, ptr %t50 + %t52 = load ptr, ptr %t6 + %t53 = call i32 @fn_streq(ptr %t51, ptr %t52) + %t54 = icmp ne i32 %t53, 0 + br i1 %t54, label %then8, label %ifend10 +then8: + %t55 = load ptr, ptr @g_ui_roots + %t56 = getelementptr inbounds %LSlice, ptr %t55, i32 0, i32 0 + %t57 = load ptr, ptr %t56 + %t58 = load i32, ptr %t8 + %t59 = getelementptr inbounds i32, ptr %t57, i32 %t58 + %t60 = load i32, ptr %t59 + store i32 %t60, ptr %retval + br label %ret +ifend10: + %t61 = load i32, ptr %t8 + %t62 = add i32 %t61, 1 + store i32 %t62, ptr %t8 + br label %ifend7 +ifend7: + %t63 = load i32, ptr %t9 + %t64 = add i32 %t63, 1 + store i32 %t64, ptr %t9 + br label %wcond0 +wend2: + store i32 0, ptr %t9 + br label %wcond11 +wcond11: + %t65 = load i32, ptr %t9 + %t66 = load ptr, ptr @g_uiw + %t67 = getelementptr inbounds %LSlice, ptr %t66, i32 0, i32 1 + %t68 = load i32, ptr %t67 + %t69 = icmp slt i32 %t65, %t68 + %t70 = zext i1 %t69 to i32 + %t71 = icmp ne i32 %t70, 0 + br i1 %t71, label %wbody12, label %wend13 +wbody12: + %t72 = load ptr, ptr @g_uiw + %t73 = getelementptr inbounds %LSlice, ptr %t72, i32 0, i32 0 + %t74 = load ptr, ptr %t73 + %t75 = load i32, ptr %t9 + %t76 = getelementptr inbounds ptr, ptr %t74, i32 %t75 + %t77 = load ptr, ptr %t76 + %t78 = call ptr @fn_ui_prop(ptr %t77, ptr @.str1335) + store ptr %t78, ptr %t79 + %t80 = load ptr, ptr %t79 + %t81 = icmp eq ptr %t80, null + %t82 = zext i1 %t81 to i32 + %t83 = icmp eq i32 %t82, 0 + %t84 = zext i1 %t83 to i32 + %t85 = icmp ne i32 %t84, 0 + br i1 %t85, label %then14, label %ifend16 +then14: + %t87 = load ptr, ptr %t79 + %t88 = getelementptr inbounds %Str_Node, ptr %t87, i32 0, i32 0 + %t89 = load i32, ptr %t88 + %t90 = icmp eq i32 %t89, 33 + %t91 = zext i1 %t90 to i32 + %t92 = icmp ne i32 %t91, 0 + %t93 = zext i1 %t92 to i32 + store i32 %t93, ptr %t86 + br i1 %t92, label %sc17, label %scend18 +sc17: + %t94 = load ptr, ptr %t79 + %t95 = getelementptr inbounds %Str_Node, ptr %t94, i32 0, i32 1 + %t96 = load ptr, ptr %t95 + %t97 = load ptr, ptr %t6 + %t98 = call i32 @fn_streq(ptr %t96, ptr %t97) + %t99 = icmp ne i32 %t98, 0 + %t100 = zext i1 %t99 to i32 + store i32 %t100, ptr %t86 + br label %scend18 +scend18: + %t101 = load i32, ptr %t86 + %t102 = icmp ne i32 %t101, 0 + br i1 %t102, label %then19, label %ifend21 +then19: + %t103 = load i32, ptr %t9 + store i32 %t103, ptr %retval + br label %ret +ifend21: + br label %ifend16 +ifend16: + %t104 = load i32, ptr %t9 + %t105 = add i32 %t104, 1 + store i32 %t105, ptr %t9 + br label %wcond11 +wend13: + store i32 0, ptr %retval + br label %ret +ret: + %t106 = load i32, ptr %retval + ret i32 %t106 +} + +define i32 @fn_is_ui_ident(ptr %arg_nm) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t1 = alloca i32 + %t2 = alloca i32 + %t3 = alloca i32 + store ptr %arg_nm, ptr %t0 + %t4 = load ptr, ptr %t0 + %t5 = call i32 @fn_slen(ptr %t4) + %t6 = icmp sgt i32 %t5, 3 + %t7 = zext i1 %t6 to i32 + %t8 = icmp ne i32 %t7, 0 + %t9 = zext i1 %t8 to i32 + store i32 %t9, ptr %t3 + br i1 %t8, label %sc0, label %scend1 +sc0: + %t10 = load ptr, ptr %t0 + %t11 = getelementptr inbounds i8, ptr %t10, i32 0 + %t12 = load i8, ptr %t11 + %t13 = zext i8 %t12 to i32 + %t14 = icmp eq i32 %t13, 85 + %t15 = zext i1 %t14 to i32 + %t16 = icmp ne i32 %t15, 0 + %t17 = zext i1 %t16 to i32 + store i32 %t17, ptr %t3 + br label %scend1 +scend1: + %t18 = load i32, ptr %t3 + %t19 = icmp ne i32 %t18, 0 + %t20 = zext i1 %t19 to i32 + store i32 %t20, ptr %t2 + br i1 %t19, label %sc2, label %scend3 +sc2: + %t21 = load ptr, ptr %t0 + %t22 = getelementptr inbounds i8, ptr %t21, i32 1 + %t23 = load i8, ptr %t22 + %t24 = zext i8 %t23 to i32 + %t25 = icmp eq i32 %t24, 73 + %t26 = zext i1 %t25 to i32 + %t27 = icmp ne i32 %t26, 0 + %t28 = zext i1 %t27 to i32 + store i32 %t28, ptr %t2 + br label %scend3 +scend3: + %t29 = load i32, ptr %t2 + %t30 = icmp ne i32 %t29, 0 + %t31 = zext i1 %t30 to i32 + store i32 %t31, ptr %t1 + br i1 %t30, label %sc4, label %scend5 +sc4: + %t32 = load ptr, ptr %t0 + %t33 = getelementptr inbounds i8, ptr %t32, i32 2 + %t34 = load i8, ptr %t33 + %t35 = zext i8 %t34 to i32 + %t36 = icmp eq i32 %t35, 95 + %t37 = zext i1 %t36 to i32 + %t38 = icmp ne i32 %t37, 0 + %t39 = zext i1 %t38 to i32 + store i32 %t39, ptr %t1 + br label %scend5 +scend5: + %t40 = load i32, ptr %t1 + store i32 %t40, ptr %retval + br label %ret +ret: + %t41 = load i32, ptr %retval + ret i32 %t41 +} + +define void @fn_ll_ui_set(i32 %arg_idx, i32 %arg_key, ptr %arg_val) { +entry: + %t0 = alloca i32 + %t1 = alloca i32 + %t2 = alloca ptr + store i32 %arg_idx, ptr %t0 + store i32 %arg_key, ptr %t1 + store ptr %arg_val, ptr %t2 + call void @fn_emit(ptr @.str1336) + %t3 = load i32, ptr %t0 + %t4 = call ptr @fn_itoa(i32 %t3) + call void @fn_emit(ptr %t4) + call void @fn_emit(ptr @.str1337) + %t5 = load i32, ptr %t1 + %t6 = call ptr @fn_itoa(i32 %t5) + call void @fn_emit(ptr %t6) + call void @fn_emit(ptr @.str1338) + %t7 = load ptr, ptr %t2 + call void @fn_emit(ptr %t7) + call void @fn_emit(ptr @.str1339) + br label %ret +ret: + ret void +} + +define i32 @fn_ui_prop_key(ptr %arg_k) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + store ptr %arg_k, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = call i32 @fn_streq(ptr %t1, ptr @.str1340) + %t3 = icmp ne i32 %t2, 0 + br i1 %t3, label %then0, label %ifend2 +then0: + store i32 2, ptr %retval + br label %ret +ifend2: + %t4 = load ptr, ptr %t0 + %t5 = call i32 @fn_streq(ptr %t4, ptr @.str1341) + %t6 = icmp ne i32 %t5, 0 + br i1 %t6, label %then3, label %ifend5 +then3: + store i32 3, ptr %retval + br label %ret +ifend5: + %t7 = load ptr, ptr %t0 + %t8 = call i32 @fn_streq(ptr %t7, ptr @.str1342) + %t9 = icmp ne i32 %t8, 0 + br i1 %t9, label %then6, label %ifend8 +then6: + store i32 4, ptr %retval + br label %ret +ifend8: + %t10 = load ptr, ptr %t0 + %t11 = call i32 @fn_streq(ptr %t10, ptr @.str1343) + %t12 = icmp ne i32 %t11, 0 + br i1 %t12, label %then9, label %ifend11 +then9: + store i32 5, ptr %retval + br label %ret +ifend11: + %t13 = load ptr, ptr %t0 + %t14 = call i32 @fn_streq(ptr %t13, ptr @.str1344) + %t15 = icmp ne i32 %t14, 0 + br i1 %t15, label %then12, label %ifend14 +then12: + store i32 7, ptr %retval + br label %ret +ifend14: + %t16 = load ptr, ptr %t0 + %t17 = call i32 @fn_streq(ptr %t16, ptr @.str1345) + %t18 = icmp ne i32 %t17, 0 + br i1 %t18, label %then15, label %ifend17 +then15: + store i32 8, ptr %retval + br label %ret +ifend17: + %t19 = load ptr, ptr %t0 + %t20 = call i32 @fn_streq(ptr %t19, ptr @.str1346) + %t21 = icmp ne i32 %t20, 0 + br i1 %t21, label %then18, label %ifend20 +then18: + store i32 9, ptr %retval + br label %ret +ifend20: + %t22 = load ptr, ptr %t0 + %t23 = call i32 @fn_streq(ptr %t22, ptr @.str1347) + %t24 = icmp ne i32 %t23, 0 + br i1 %t24, label %then21, label %ifend23 +then21: + store i32 10, ptr %retval + br label %ret +ifend23: + %t25 = load ptr, ptr %t0 + %t26 = call i32 @fn_streq(ptr %t25, ptr @.str1348) + %t27 = icmp ne i32 %t26, 0 + br i1 %t27, label %then24, label %ifend26 +then24: + store i32 11, ptr %retval + br label %ret +ifend26: + %t28 = load ptr, ptr %t0 + %t29 = call i32 @fn_streq(ptr %t28, ptr @.str1349) + %t30 = icmp ne i32 %t29, 0 + br i1 %t30, label %then27, label %ifend29 +then27: + store i32 13, ptr %retval + br label %ret +ifend29: + %t31 = load ptr, ptr %t0 + %t32 = call i32 @fn_streq(ptr %t31, ptr @.str1350) + %t33 = icmp ne i32 %t32, 0 + br i1 %t33, label %then30, label %ifend32 +then30: + store i32 14, ptr %retval + br label %ret +ifend32: + %t34 = load ptr, ptr %t0 + %t35 = call i32 @fn_streq(ptr %t34, ptr @.str1351) + %t36 = icmp ne i32 %t35, 0 + br i1 %t36, label %then33, label %ifend35 +then33: + store i32 15, ptr %retval + br label %ret +ifend35: + %t37 = load ptr, ptr %t0 + %t38 = call i32 @fn_streq(ptr %t37, ptr @.str1352) + %t39 = icmp ne i32 %t38, 0 + br i1 %t39, label %then36, label %ifend38 +then36: + store i32 16, ptr %retval + br label %ret +ifend38: + %t40 = load ptr, ptr %t0 + %t41 = call i32 @fn_streq(ptr %t40, ptr @.str1353) + %t42 = icmp ne i32 %t41, 0 + br i1 %t42, label %then39, label %ifend41 +then39: + store i32 17, ptr %retval + br label %ret +ifend41: + %t43 = sub i32 0, 1 + store i32 %t43, ptr %retval + br label %ret +ret: + %t44 = load i32, ptr %retval + ret i32 %t44 +} + +define void @fn_emit_ui_build() { +entry: + %t1 = alloca ptr + %t4 = alloca ptr + %t10 = alloca i32 + %t24 = alloca ptr + %t27 = alloca i32 + %t44 = alloca i32 + %t66 = alloca ptr + %t70 = alloca ptr + %t74 = alloca ptr + %t85 = alloca ptr + %t91 = alloca i32 + %t104 = alloca ptr + %t111 = alloca ptr + %t128 = alloca i32 + %t144 = alloca ptr + %t151 = alloca i32 + %t158 = alloca ptr + %t164 = alloca i32 + call void @fn_ui_flatten_all() + store i32 0, ptr @g_ll_t + store i32 0, ptr @g_ll_lbl + store i32 0, ptr @g_g_term + call void @fn_loc_reset() + store i32 0, ptr @g_nloop + %t0 = call ptr @fn_buf_new() + store ptr %t0, ptr %t1 + %t2 = call ptr @fn_buf_new() + store ptr %t2, ptr @g_falloc + %t3 = load ptr, ptr @g_code + store ptr %t3, ptr %t4 + %t5 = load ptr, ptr %t1 + store ptr %t5, ptr @g_code + call void @fn_emit(ptr @.str1354) + %t6 = load ptr, ptr @g_uiw + %t7 = getelementptr inbounds %LSlice, ptr %t6, i32 0, i32 1 + %t8 = load i32, ptr %t7 + %t9 = call ptr @fn_itoa(i32 %t8) + call void @fn_emit(ptr %t9) + call void @fn_emit(ptr @.str1355) + store i32 0, ptr %t10 + br label %wcond0 +wcond0: + %t11 = load i32, ptr %t10 + %t12 = load ptr, ptr @g_uiw + %t13 = getelementptr inbounds %LSlice, ptr %t12, i32 0, i32 1 + %t14 = load i32, ptr %t13 + %t15 = icmp slt i32 %t11, %t14 + %t16 = zext i1 %t15 to i32 + %t17 = icmp ne i32 %t16, 0 + br i1 %t17, label %wbody1, label %wend2 +wbody1: + %t18 = load ptr, ptr @g_uiw + %t19 = getelementptr inbounds %LSlice, ptr %t18, i32 0, i32 0 + %t20 = load ptr, ptr %t19 + %t21 = load i32, ptr %t10 + %t22 = getelementptr inbounds ptr, ptr %t20, i32 %t21 + %t23 = load ptr, ptr %t22 + store ptr %t23, ptr %t24 + %t25 = load ptr, ptr %t24 + %t26 = call i32 @fn_ui_wtype(ptr %t25) + store i32 %t26, ptr %t27 + %t28 = load i32, ptr %t10 + %t29 = load i32, ptr %t27 + %t30 = call ptr @fn_itoa(i32 %t29) + call void @fn_ll_ui_set(i32 %t28, i32 0, ptr %t30) + %t31 = load i32, ptr %t10 + %t32 = load ptr, ptr @g_uiw_parent + %t33 = getelementptr inbounds %LSlice, ptr %t32, i32 0, i32 0 + %t34 = load ptr, ptr %t33 + %t35 = load i32, ptr %t10 + %t36 = getelementptr inbounds i32, ptr %t34, i32 %t35 + %t37 = load i32, ptr %t36 + %t38 = call ptr @fn_itoa(i32 %t37) + call void @fn_ll_ui_set(i32 %t31, i32 1, ptr %t38) + %t39 = load i32, ptr %t27 + %t40 = icmp eq i32 %t39, 4 + %t41 = zext i1 %t40 to i32 + %t42 = icmp ne i32 %t41, 0 + br i1 %t42, label %then3, label %ifend5 +then3: + %t43 = load i32, ptr %t10 + call void @fn_ll_ui_set(i32 %t43, i32 17, ptr @.str1356) + br label %ifend5 +ifend5: + store i32 0, ptr %t44 + br label %wcond6 +wcond6: + %t45 = load i32, ptr %t44 + %t46 = load ptr, ptr %t24 + %t47 = getelementptr inbounds %Str_Node, ptr %t46, i32 0, i32 5 + %t48 = load ptr, ptr %t47 + %t49 = getelementptr inbounds %Str_Node, ptr %t48, i32 0, i32 7 + %t50 = load ptr, ptr %t49 + %t51 = getelementptr inbounds %LSlice, ptr %t50, i32 0, i32 1 + %t52 = load i32, ptr %t51 + %t53 = icmp slt i32 %t45, %t52 + %t54 = zext i1 %t53 to i32 + %t55 = icmp ne i32 %t54, 0 + br i1 %t55, label %wbody7, label %wend8 +wbody7: + %t56 = load ptr, ptr %t24 + %t57 = getelementptr inbounds %Str_Node, ptr %t56, i32 0, i32 5 + %t58 = load ptr, ptr %t57 + %t59 = getelementptr inbounds %Str_Node, ptr %t58, i32 0, i32 7 + %t60 = load ptr, ptr %t59 + %t61 = getelementptr inbounds %LSlice, ptr %t60, i32 0, i32 0 + %t62 = load ptr, ptr %t61 + %t63 = load i32, ptr %t44 + %t64 = getelementptr inbounds ptr, ptr %t62, i32 %t63 + %t65 = load ptr, ptr %t64 + store ptr %t65, ptr %t66 + %t67 = load ptr, ptr %t66 + %t68 = getelementptr inbounds %Str_Node, ptr %t67, i32 0, i32 1 + %t69 = load ptr, ptr %t68 + store ptr %t69, ptr %t70 + %t71 = load ptr, ptr %t66 + %t72 = getelementptr inbounds %Str_Node, ptr %t71, i32 0, i32 4 + %t73 = load ptr, ptr %t72 + store ptr %t73, ptr %t74 + %t75 = load ptr, ptr %t70 + %t76 = call i32 @fn_streq(ptr %t75, ptr @.str1357) + %t77 = icmp ne i32 %t76, 0 + br i1 %t77, label %then9, label %ifend11 +then9: + %t78 = load i32, ptr %t44 + %t79 = add i32 %t78, 1 + store i32 %t79, ptr %t44 + br label %wcond6 +ifend11: + %t80 = load ptr, ptr %t70 + %t81 = call i32 @fn_streq(ptr %t80, ptr @.str1358) + %t82 = icmp ne i32 %t81, 0 + br i1 %t82, label %then12, label %else13 +then12: + %t83 = load ptr, ptr %t74 + %t84 = call ptr @fn_emit_expr(ptr %t83) + store ptr %t84, ptr %t85 + call void @fn_emit(ptr @.str1359) + %t86 = load i32, ptr %t10 + %t87 = call ptr @fn_itoa(i32 %t86) + call void @fn_emit(ptr %t87) + call void @fn_emit(ptr @.str1360) + %t88 = load ptr, ptr %t85 + %t89 = getelementptr inbounds %Str_Val, ptr %t88, i32 0, i32 0 + %t90 = load ptr, ptr %t89 + call void @fn_emit(ptr %t90) + call void @fn_emit(ptr @.str1361) + br label %ifend14 +else13: + %t92 = load ptr, ptr %t70 + %t93 = call i32 @fn_streq(ptr %t92, ptr @.str1362) + %t94 = icmp ne i32 %t93, 0 + %t95 = zext i1 %t94 to i32 + store i32 %t95, ptr %t91 + br i1 %t94, label %scend16, label %sc15 +sc15: + %t96 = load ptr, ptr %t70 + %t97 = call i32 @fn_streq(ptr %t96, ptr @.str1363) + %t98 = icmp ne i32 %t97, 0 + %t99 = zext i1 %t98 to i32 + store i32 %t99, ptr %t91 + br label %scend16 +scend16: + %t100 = load i32, ptr %t91 + %t101 = icmp ne i32 %t100, 0 + br i1 %t101, label %then17, label %else18 +then17: + %t102 = load ptr, ptr %t74 + %t103 = call ptr @fn_emit_expr(ptr %t102) + store ptr %t103, ptr %t104 + %t105 = load ptr, ptr %t104 + %t106 = getelementptr inbounds %Str_Val, ptr %t105, i32 0, i32 0 + %t107 = load ptr, ptr %t106 + %t108 = call ptr @fn_sconcat(ptr %t107, ptr @.str1365) + %t109 = call ptr @fn_sconcat(ptr @.str1364, ptr %t108) + %t110 = call ptr @fn_emit_bind(ptr %t109) + store ptr %t110, ptr %t111 + %t112 = load ptr, ptr %t70 + %t113 = call i32 @fn_streq(ptr %t112, ptr @.str1366) + %t114 = icmp ne i32 %t113, 0 + br i1 %t114, label %then20, label %else21 +then20: + %t115 = load i32, ptr %t10 + %t116 = load ptr, ptr %t111 + call void @fn_ll_ui_set(i32 %t115, i32 20, ptr %t116) + br label %ifend22 +else21: + %t117 = load i32, ptr %t10 + %t118 = load ptr, ptr %t111 + call void @fn_ll_ui_set(i32 %t117, i32 19, ptr %t118) + br label %ifend22 +ifend22: + br label %ifend19 +else18: + %t119 = load ptr, ptr %t70 + %t120 = call i32 @fn_streq(ptr %t119, ptr @.str1367) + %t121 = icmp ne i32 %t120, 0 + br i1 %t121, label %then23, label %else24 +then23: + %t122 = load ptr, ptr %t74 + %t123 = getelementptr inbounds %Str_Node, ptr %t122, i32 0, i32 0 + %t124 = load i32, ptr %t123 + %t125 = icmp eq i32 %t124, 33 + %t126 = zext i1 %t125 to i32 + %t127 = icmp ne i32 %t126, 0 + br i1 %t127, label %then26, label %else27 +then26: + store i32 0, ptr %t128 + %t129 = load ptr, ptr %t74 + %t130 = getelementptr inbounds %Str_Node, ptr %t129, i32 0, i32 1 + %t131 = load ptr, ptr %t130 + %t132 = call i32 @fn_streq(ptr %t131, ptr @.str1368) + %t133 = icmp ne i32 %t132, 0 + br i1 %t133, label %then29, label %ifend31 +then29: + store i32 1, ptr %t128 + br label %ifend31 +ifend31: + %t134 = load ptr, ptr %t74 + %t135 = getelementptr inbounds %Str_Node, ptr %t134, i32 0, i32 1 + %t136 = load ptr, ptr %t135 + %t137 = call i32 @fn_streq(ptr %t136, ptr @.str1369) + %t138 = icmp ne i32 %t137, 0 + br i1 %t138, label %then32, label %ifend34 +then32: + store i32 2, ptr %t128 + br label %ifend34 +ifend34: + %t139 = load i32, ptr %t10 + %t140 = load i32, ptr %t128 + %t141 = call ptr @fn_itoa(i32 %t140) + call void @fn_ll_ui_set(i32 %t139, i32 12, ptr %t141) + br label %ifend28 +else27: + %t142 = load ptr, ptr %t74 + %t143 = call ptr @fn_emit_expr(ptr %t142) + store ptr %t143, ptr %t144 + %t145 = load i32, ptr %t10 + %t146 = load ptr, ptr %t144 + %t147 = getelementptr inbounds %Str_Val, ptr %t146, i32 0, i32 0 + %t148 = load ptr, ptr %t147 + call void @fn_ll_ui_set(i32 %t145, i32 12, ptr %t148) + br label %ifend28 +ifend28: + br label %ifend25 +else24: + %t149 = load ptr, ptr %t70 + %t150 = call i32 @fn_ui_prop_key(ptr %t149) + store i32 %t150, ptr %t151 + %t152 = load i32, ptr %t151 + %t153 = icmp sge i32 %t152, 0 + %t154 = zext i1 %t153 to i32 + %t155 = icmp ne i32 %t154, 0 + br i1 %t155, label %then35, label %ifend37 +then35: + %t156 = load ptr, ptr %t74 + %t157 = call ptr @fn_emit_expr(ptr %t156) + store ptr %t157, ptr %t158 + %t159 = load i32, ptr %t10 + %t160 = load i32, ptr %t151 + %t161 = load ptr, ptr %t158 + %t162 = getelementptr inbounds %Str_Val, ptr %t161, i32 0, i32 0 + %t163 = load ptr, ptr %t162 + call void @fn_ll_ui_set(i32 %t159, i32 %t160, ptr %t163) + %t165 = load i32, ptr %t151 + %t166 = icmp eq i32 %t165, 4 + %t167 = zext i1 %t166 to i32 + %t168 = icmp ne i32 %t167, 0 + %t169 = zext i1 %t168 to i32 + store i32 %t169, ptr %t164 + br i1 %t168, label %scend39, label %sc38 +sc38: + %t170 = load i32, ptr %t151 + %t171 = icmp eq i32 %t170, 5 + %t172 = zext i1 %t171 to i32 + %t173 = icmp ne i32 %t172, 0 + %t174 = zext i1 %t173 to i32 + store i32 %t174, ptr %t164 + br label %scend39 +scend39: + %t175 = load i32, ptr %t164 + %t176 = icmp ne i32 %t175, 0 + br i1 %t176, label %then40, label %ifend42 +then40: + %t177 = load i32, ptr %t10 + call void @fn_ll_ui_set(i32 %t177, i32 6, ptr @.str1370) + br label %ifend42 +ifend42: + br label %ifend37 +ifend37: + br label %ifend25 +ifend25: + br label %ifend19 +ifend19: + br label %ifend14 +ifend14: + %t178 = load i32, ptr %t44 + %t179 = add i32 %t178, 1 + store i32 %t179, ptr %t44 + br label %wcond6 +wend8: + %t180 = load i32, ptr %t10 + %t181 = add i32 %t180, 1 + store i32 %t181, ptr %t10 + br label %wcond0 +wend2: + %t182 = load ptr, ptr %t4 + store ptr %t182, ptr @g_code + call void @fn_emit(ptr @.str1371) + %t183 = load ptr, ptr @g_falloc + %t184 = call ptr @fn_buf_str(ptr %t183) + call void @fn_emit(ptr %t184) + %t185 = load ptr, ptr %t1 + %t186 = call ptr @fn_buf_str(ptr %t185) + call void @fn_emit(ptr %t186) + call void @fn_emit(ptr @.str1372) + br label %ret +ret: + ret void +} + +define void @fn_emit_params_sig(ptr %arg_d) { +entry: + %t0 = alloca ptr + %t1 = alloca i32 + store ptr %arg_d, ptr %t0 + store i32 0, ptr %t1 + br label %wcond0 +wcond0: + %t2 = load i32, ptr %t1 + %t3 = load ptr, ptr %t0 + %t4 = getelementptr inbounds %Str_Node, ptr %t3, i32 0, i32 7 + %t5 = load ptr, ptr %t4 + %t6 = getelementptr inbounds %LSlice, ptr %t5, i32 0, i32 1 + %t7 = load i32, ptr %t6 + %t8 = icmp slt i32 %t2, %t7 + %t9 = zext i1 %t8 to i32 + %t10 = icmp ne i32 %t9, 0 + br i1 %t10, label %wbody1, label %wend2 +wbody1: + %t11 = load i32, ptr %t1 + %t12 = icmp sgt i32 %t11, 0 + %t13 = zext i1 %t12 to i32 + %t14 = icmp ne i32 %t13, 0 + br i1 %t14, label %then3, label %ifend5 +then3: + call void @fn_emit(ptr @.str1373) + br label %ifend5 +ifend5: + %t15 = load ptr, ptr %t0 + %t16 = getelementptr inbounds %Str_Node, ptr %t15, i32 0, i32 7 + %t17 = load ptr, ptr %t16 + %t18 = getelementptr inbounds %LSlice, ptr %t17, i32 0, i32 0 + %t19 = load ptr, ptr %t18 + %t20 = load i32, ptr %t1 + %t21 = getelementptr inbounds ptr, ptr %t19, i32 %t20 + %t22 = load ptr, ptr %t21 + %t23 = getelementptr inbounds %Str_Node, ptr %t22, i32 0, i32 3 + %t24 = load ptr, ptr %t23 + %t25 = call ptr @fn_llty(ptr %t24) + call void @fn_emit(ptr %t25) + call void @fn_emit(ptr @.str1374) + %t26 = load ptr, ptr %t0 + %t27 = getelementptr inbounds %Str_Node, ptr %t26, i32 0, i32 7 + %t28 = load ptr, ptr %t27 + %t29 = getelementptr inbounds %LSlice, ptr %t28, i32 0, i32 0 + %t30 = load ptr, ptr %t29 + %t31 = load i32, ptr %t1 + %t32 = getelementptr inbounds ptr, ptr %t30, i32 %t31 + %t33 = load ptr, ptr %t32 + %t34 = getelementptr inbounds %Str_Node, ptr %t33, i32 0, i32 1 + %t35 = load ptr, ptr %t34 + call void @fn_emit(ptr %t35) + %t36 = load i32, ptr %t1 + %t37 = add i32 %t36, 1 + store i32 %t37, ptr %t1 + br label %wcond0 +wend2: + br label %ret +ret: + ret void +} + +define void @fn_emit_fn(ptr %arg_d) { +entry: + %t0 = alloca ptr + %t5 = alloca ptr + %t8 = alloca ptr + %t12 = alloca ptr + %t22 = alloca i32 + %t40 = alloca ptr + %t46 = alloca ptr + %t78 = alloca ptr + store ptr %arg_d, ptr %t0 + store i32 0, ptr @g_ll_t + store i32 0, ptr @g_ll_lbl + store i32 0, ptr @g_g_term + call void @fn_loc_reset() + store i32 0, ptr @g_nloop + %t1 = load ptr, ptr %t0 + %t2 = getelementptr inbounds %Str_Node, ptr %t1, i32 0, i32 3 + %t3 = load ptr, ptr %t2 + store ptr %t3, ptr @g_ret_ty + %t4 = call ptr @fn_buf_new() + store ptr %t4, ptr %t5 + %t6 = call ptr @fn_buf_new() + store ptr %t6, ptr @g_falloc + %t7 = load ptr, ptr @g_code + store ptr %t7, ptr %t8 + %t9 = load ptr, ptr %t5 + store ptr %t9, ptr @g_code + %t10 = load ptr, ptr @g_ret_ty + %t11 = call ptr @fn_llty(ptr %t10) + store ptr %t11, ptr %t12 + %t13 = load ptr, ptr %t12 + %t14 = call i32 @fn_streq(ptr %t13, ptr @.str1375) + %t15 = icmp eq i32 %t14, 0 + %t16 = zext i1 %t15 to i32 + %t17 = icmp ne i32 %t16, 0 + br i1 %t17, label %then0, label %ifend2 +then0: + %t18 = load ptr, ptr @g_falloc + call void @fn_buf_puts(ptr %t18, ptr @.str1376) + %t19 = load ptr, ptr @g_falloc + %t20 = load ptr, ptr %t12 + call void @fn_buf_puts(ptr %t19, ptr %t20) + %t21 = load ptr, ptr @g_falloc + call void @fn_buf_puts(ptr %t21, ptr @.str1377) + br label %ifend2 +ifend2: + store i32 0, ptr %t22 + br label %wcond3 +wcond3: + %t23 = load i32, ptr %t22 + %t24 = load ptr, ptr %t0 + %t25 = getelementptr inbounds %Str_Node, ptr %t24, i32 0, i32 7 + %t26 = load ptr, ptr %t25 + %t27 = getelementptr inbounds %LSlice, ptr %t26, i32 0, i32 1 + %t28 = load i32, ptr %t27 + %t29 = icmp slt i32 %t23, %t28 + %t30 = zext i1 %t29 to i32 + %t31 = icmp ne i32 %t30, 0 + br i1 %t31, label %wbody4, label %wend5 +wbody4: + %t32 = load ptr, ptr %t0 + %t33 = getelementptr inbounds %Str_Node, ptr %t32, i32 0, i32 7 + %t34 = load ptr, ptr %t33 + %t35 = getelementptr inbounds %LSlice, ptr %t34, i32 0, i32 0 + %t36 = load ptr, ptr %t35 + %t37 = load i32, ptr %t22 + %t38 = getelementptr inbounds ptr, ptr %t36, i32 %t37 + %t39 = load ptr, ptr %t38 + store ptr %t39, ptr %t40 + %t41 = load ptr, ptr %t40 + %t42 = getelementptr inbounds %Str_Node, ptr %t41, i32 0, i32 3 + %t43 = load ptr, ptr %t42 + %t44 = call ptr @fn_llty(ptr %t43) + %t45 = call ptr @fn_emit_alloca(ptr %t44) + store ptr %t45, ptr %t46 + call void @fn_emit(ptr @.str1378) + %t47 = load ptr, ptr %t40 + %t48 = getelementptr inbounds %Str_Node, ptr %t47, i32 0, i32 3 + %t49 = load ptr, ptr %t48 + %t50 = call ptr @fn_llty(ptr %t49) + call void @fn_emit(ptr %t50) + call void @fn_emit(ptr @.str1379) + %t51 = load ptr, ptr %t40 + %t52 = getelementptr inbounds %Str_Node, ptr %t51, i32 0, i32 1 + %t53 = load ptr, ptr %t52 + call void @fn_emit(ptr %t53) + call void @fn_emit(ptr @.str1380) + %t54 = load ptr, ptr %t46 + call void @fn_emit(ptr %t54) + call void @fn_emit(ptr @.str1381) + %t55 = load ptr, ptr %t40 + %t56 = getelementptr inbounds %Str_Node, ptr %t55, i32 0, i32 1 + %t57 = load ptr, ptr %t56 + %t58 = load ptr, ptr %t46 + %t59 = load ptr, ptr %t40 + %t60 = getelementptr inbounds %Str_Node, ptr %t59, i32 0, i32 3 + %t61 = load ptr, ptr %t60 + call void @fn_loc_push(ptr %t57, ptr %t58, ptr %t61) + %t62 = load i32, ptr %t22 + %t63 = add i32 %t62, 1 + store i32 %t63, ptr %t22 + br label %wcond3 +wend5: + %t64 = load ptr, ptr %t0 + %t65 = getelementptr inbounds %Str_Node, ptr %t64, i32 0, i32 4 + %t66 = load ptr, ptr %t65 + call void @fn_emit_block(ptr %t66) + %t67 = load i32, ptr @g_g_term + %t68 = icmp eq i32 %t67, 0 + %t69 = zext i1 %t68 to i32 + %t70 = icmp ne i32 %t69, 0 + br i1 %t70, label %then6, label %ifend8 +then6: + call void @fn_emit(ptr @.str1382) + br label %ifend8 +ifend8: + call void @fn_emit(ptr @.str1383) + %t71 = load ptr, ptr %t12 + %t72 = call i32 @fn_streq(ptr %t71, ptr @.str1384) + %t73 = icmp ne i32 %t72, 0 + br i1 %t73, label %then9, label %else10 +then9: + call void @fn_emit(ptr @.str1385) + br label %ifend11 +else10: + %t74 = load ptr, ptr %t12 + %t75 = call ptr @fn_sconcat(ptr %t74, ptr @.str1387) + %t76 = call ptr @fn_sconcat(ptr @.str1386, ptr %t75) + %t77 = call ptr @fn_emit_bind(ptr %t76) + store ptr %t77, ptr %t78 + call void @fn_emit(ptr @.str1388) + %t79 = load ptr, ptr %t12 + call void @fn_emit(ptr %t79) + call void @fn_emit(ptr @.str1389) + %t80 = load ptr, ptr %t78 + call void @fn_emit(ptr %t80) + call void @fn_emit(ptr @.str1390) + br label %ifend11 +ifend11: + %t81 = load ptr, ptr %t8 + store ptr %t81, ptr @g_code + call void @fn_emit(ptr @.str1391) + %t82 = load ptr, ptr %t12 + call void @fn_emit(ptr %t82) + call void @fn_emit(ptr @.str1392) + %t83 = load ptr, ptr %t0 + %t84 = getelementptr inbounds %Str_Node, ptr %t83, i32 0, i32 1 + %t85 = load ptr, ptr %t84 + call void @fn_emit(ptr %t85) + call void @fn_emit(ptr @.str1393) + %t86 = load ptr, ptr %t0 + call void @fn_emit_params_sig(ptr %t86) + call void @fn_emit(ptr @.str1394) + %t87 = load ptr, ptr @g_falloc + %t88 = call ptr @fn_buf_str(ptr %t87) + call void @fn_emit(ptr %t88) + %t89 = load ptr, ptr %t5 + %t90 = call ptr @fn_buf_str(ptr %t89) + call void @fn_emit(ptr %t90) + call void @fn_emit(ptr @.str1395) + br label %ret +ret: + ret void +} + +define void @fn_emit_main(ptr %arg_d) { +entry: + %t0 = alloca ptr + %t2 = alloca ptr + %t5 = alloca ptr + %t16 = alloca ptr + store ptr %arg_d, ptr %t0 + store i32 0, ptr @g_ll_t + store i32 0, ptr @g_ll_lbl + store i32 0, ptr @g_g_term + call void @fn_loc_reset() + store i32 0, ptr @g_nloop + store ptr @.str1396, ptr @g_ret_ty + %t1 = call ptr @fn_buf_new() + store ptr %t1, ptr %t2 + %t3 = call ptr @fn_buf_new() + store ptr %t3, ptr @g_falloc + %t4 = load ptr, ptr @g_code + store ptr %t4, ptr %t5 + %t6 = load ptr, ptr %t2 + store ptr %t6, ptr @g_code + %t7 = load ptr, ptr @g_falloc + call void @fn_buf_puts(ptr %t7, ptr @.str1397) + call void @fn_emit(ptr @.str1398) + call void @fn_emit(ptr @.str1399) + call void @fn_emit(ptr @.str1400) + %t8 = load ptr, ptr %t0 + %t9 = getelementptr inbounds %Str_Node, ptr %t8, i32 0, i32 4 + %t10 = load ptr, ptr %t9 + call void @fn_emit_block(ptr %t10) + %t11 = load i32, ptr @g_g_term + %t12 = icmp eq i32 %t11, 0 + %t13 = zext i1 %t12 to i32 + %t14 = icmp ne i32 %t13, 0 + br i1 %t14, label %then0, label %ifend2 +then0: + call void @fn_emit(ptr @.str1401) + br label %ifend2 +ifend2: + call void @fn_emit(ptr @.str1402) + %t15 = call ptr @fn_emit_bind(ptr @.str1403) + store ptr %t15, ptr %t16 + call void @fn_emit(ptr @.str1404) + %t17 = load ptr, ptr %t16 + call void @fn_emit(ptr %t17) + call void @fn_emit(ptr @.str1405) + %t18 = load ptr, ptr %t5 + store ptr %t18, ptr @g_code + call void @fn_emit(ptr @.str1406) + %t19 = load ptr, ptr @g_falloc + %t20 = call ptr @fn_buf_str(ptr %t19) + call void @fn_emit(ptr %t20) + %t21 = load ptr, ptr %t2 + %t22 = call ptr @fn_buf_str(ptr %t21) + call void @fn_emit(ptr %t22) + call void @fn_emit(ptr @.str1407) + br label %ret +ret: + ret void +} + +define void @fn_emit_program() { +entry: + %t46 = alloca i32 + %t0 = call ptr @fn_buf_new() + store ptr %t0, ptr @g_head + %t1 = call ptr @fn_buf_new() + store ptr %t1, ptr @g_code + %t2 = getelementptr %LSlice, ptr null, i32 1 + %t3 = ptrtoint ptr %t2 to i64 + %t4 = call ptr @malloc(i64 %t3) + %t5 = getelementptr inbounds %LSlice, ptr %t4, i32 0, i32 0 + store ptr null, ptr %t5 + %t6 = getelementptr inbounds %LSlice, ptr %t4, i32 0, i32 1 + store i32 0, ptr %t6 + %t7 = getelementptr inbounds %LSlice, ptr %t4, i32 0, i32 2 + store i32 0, ptr %t7 + store ptr %t4, ptr @g_loc_name + %t8 = getelementptr %LSlice, ptr null, i32 1 + %t9 = ptrtoint ptr %t8 to i64 + %t10 = call ptr @malloc(i64 %t9) + %t11 = getelementptr inbounds %LSlice, ptr %t10, i32 0, i32 0 + store ptr null, ptr %t11 + %t12 = getelementptr inbounds %LSlice, ptr %t10, i32 0, i32 1 + store i32 0, ptr %t12 + %t13 = getelementptr inbounds %LSlice, ptr %t10, i32 0, i32 2 + store i32 0, ptr %t13 + store ptr %t10, ptr @g_loc_reg + %t14 = getelementptr %LSlice, ptr null, i32 1 + %t15 = ptrtoint ptr %t14 to i64 + %t16 = call ptr @malloc(i64 %t15) + %t17 = getelementptr inbounds %LSlice, ptr %t16, i32 0, i32 0 + store ptr null, ptr %t17 + %t18 = getelementptr inbounds %LSlice, ptr %t16, i32 0, i32 1 + store i32 0, ptr %t18 + %t19 = getelementptr inbounds %LSlice, ptr %t16, i32 0, i32 2 + store i32 0, ptr %t19 + store ptr %t16, ptr @g_loc_ty + %t20 = getelementptr %LSlice, ptr null, i32 1 + %t21 = ptrtoint ptr %t20 to i64 + %t22 = call ptr @malloc(i64 %t21) + %t23 = getelementptr inbounds %LSlice, ptr %t22, i32 0, i32 0 + store ptr null, ptr %t23 + %t24 = getelementptr inbounds %LSlice, ptr %t22, i32 0, i32 1 + store i32 0, ptr %t24 + %t25 = getelementptr inbounds %LSlice, ptr %t22, i32 0, i32 2 + store i32 0, ptr %t25 + store ptr %t22, ptr @g_brk_lbl + %t26 = getelementptr %LSlice, ptr null, i32 1 + %t27 = ptrtoint ptr %t26 to i64 + %t28 = call ptr @malloc(i64 %t27) + %t29 = getelementptr inbounds %LSlice, ptr %t28, i32 0, i32 0 + store ptr null, ptr %t29 + %t30 = getelementptr inbounds %LSlice, ptr %t28, i32 0, i32 1 + store i32 0, ptr %t30 + %t31 = getelementptr inbounds %LSlice, ptr %t28, i32 0, i32 2 + store i32 0, ptr %t31 + store ptr %t28, ptr @g_cnt_lbl + %t32 = getelementptr %LSlice, ptr null, i32 1 + %t33 = ptrtoint ptr %t32 to i64 + %t34 = call ptr @malloc(i64 %t33) + %t35 = getelementptr inbounds %LSlice, ptr %t34, i32 0, i32 0 + store ptr null, ptr %t35 + %t36 = getelementptr inbounds %LSlice, ptr %t34, i32 0, i32 1 + store i32 0, ptr %t36 + %t37 = getelementptr inbounds %LSlice, ptr %t34, i32 0, i32 2 + store i32 0, ptr %t37 + store ptr %t34, ptr @g_self_stk + %t38 = getelementptr %LSlice, ptr null, i32 1 + %t39 = ptrtoint ptr %t38 to i64 + %t40 = call ptr @malloc(i64 %t39) + %t41 = getelementptr inbounds %LSlice, ptr %t40, i32 0, i32 0 + store ptr null, ptr %t41 + %t42 = getelementptr inbounds %LSlice, ptr %t40, i32 0, i32 1 + store i32 0, ptr %t42 + %t43 = getelementptr inbounds %LSlice, ptr %t40, i32 0, i32 2 + store i32 0, ptr %t43 + store ptr %t40, ptr @g_mach_stk + call void @fn_emit_header() + %t44 = call i32 @fn_has_ecs() + %t45 = icmp ne i32 %t44, 0 + br i1 %t45, label %then0, label %ifend2 +then0: + call void @fn_emit_ecs_storage() + br label %ifend2 +ifend2: + store i32 0, ptr %t46 + br label %wcond3 +wcond3: + %t47 = load i32, ptr %t46 + %t48 = load ptr, ptr @g_prog + %t49 = getelementptr inbounds %LSlice, ptr %t48, i32 0, i32 1 + %t50 = load i32, ptr %t49 + %t51 = icmp slt i32 %t47, %t50 + %t52 = zext i1 %t51 to i32 + %t53 = icmp ne i32 %t52, 0 + br i1 %t53, label %wbody4, label %wend5 +wbody4: + %t54 = load ptr, ptr @g_prog + %t55 = getelementptr inbounds %LSlice, ptr %t54, i32 0, i32 0 + %t56 = load ptr, ptr %t55 + %t57 = load i32, ptr %t46 + %t58 = getelementptr inbounds ptr, ptr %t56, i32 %t57 + %t59 = load ptr, ptr %t58 + %t60 = getelementptr inbounds %Str_Node, ptr %t59, i32 0, i32 0 + %t61 = load i32, ptr %t60 + %t62 = icmp eq i32 %t61, 4 + %t63 = zext i1 %t62 to i32 + %t64 = icmp ne i32 %t63, 0 + br i1 %t64, label %then6, label %ifend8 +then6: + %t65 = load ptr, ptr @g_prog + %t66 = getelementptr inbounds %LSlice, ptr %t65, i32 0, i32 0 + %t67 = load ptr, ptr %t66 + %t68 = load i32, ptr %t46 + %t69 = getelementptr inbounds ptr, ptr %t67, i32 %t68 + %t70 = load ptr, ptr %t69 + call void @fn_emit_fn(ptr %t70) + br label %ifend8 +ifend8: + %t71 = load i32, ptr %t46 + %t72 = add i32 %t71, 1 + store i32 %t72, ptr %t46 + br label %wcond3 +wend5: + %t73 = call i32 @fn_has_ecs() + %t74 = icmp ne i32 %t73, 0 + br i1 %t74, label %then9, label %ifend11 +then9: + call void @fn_emit_ecs_allocator() + call void @fn_emit_snapshot() + br label %ifend11 +ifend11: + %t75 = call i32 @fn_has_ui() + %t76 = icmp ne i32 %t75, 0 + br i1 %t76, label %then12, label %ifend14 +then12: + call void @fn_emit_ui_build() + br label %ifend14 +ifend14: + %t77 = call i32 @fn_has_systems() + %t78 = icmp ne i32 %t77, 0 + br i1 %t78, label %then15, label %else16 +then15: + call void @fn_emit_game_main() + br label %ifend17 +else16: + store i32 0, ptr %t46 + br label %wcond18 +wcond18: + %t79 = load i32, ptr %t46 + %t80 = load ptr, ptr @g_prog + %t81 = getelementptr inbounds %LSlice, ptr %t80, i32 0, i32 1 + %t82 = load i32, ptr %t81 + %t83 = icmp slt i32 %t79, %t82 + %t84 = zext i1 %t83 to i32 + %t85 = icmp ne i32 %t84, 0 + br i1 %t85, label %wbody19, label %wend20 +wbody19: + %t86 = load ptr, ptr @g_prog + %t87 = getelementptr inbounds %LSlice, ptr %t86, i32 0, i32 0 + %t88 = load ptr, ptr %t87 + %t89 = load i32, ptr %t46 + %t90 = getelementptr inbounds ptr, ptr %t88, i32 %t89 + %t91 = load ptr, ptr %t90 + %t92 = getelementptr inbounds %Str_Node, ptr %t91, i32 0, i32 0 + %t93 = load i32, ptr %t92 + %t94 = icmp eq i32 %t93, 6 + %t95 = zext i1 %t94 to i32 + %t96 = icmp ne i32 %t95, 0 + br i1 %t96, label %then21, label %ifend23 +then21: + %t97 = load ptr, ptr @g_prog + %t98 = getelementptr inbounds %LSlice, ptr %t97, i32 0, i32 0 + %t99 = load ptr, ptr %t98 + %t100 = load i32, ptr %t46 + %t101 = getelementptr inbounds ptr, ptr %t99, i32 %t100 + %t102 = load ptr, ptr %t101 + call void @fn_emit_main(ptr %t102) + br label %ifend23 +ifend23: + %t103 = load i32, ptr %t46 + %t104 = add i32 %t103, 1 + store i32 %t104, ptr %t46 + br label %wcond18 +wend20: + br label %ifend17 +ifend17: + br label %ret +ret: + ret void +} + +define i32 @fn_ir_flush(ptr %arg_path) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t3 = alloca ptr + %t6 = alloca ptr + %t15 = alloca ptr + store ptr %arg_path, ptr %t0 + %t1 = load ptr, ptr @g_head + %t2 = call ptr @fn_buf_str(ptr %t1) + store ptr %t2, ptr %t3 + %t4 = load ptr, ptr @g_code + %t5 = call ptr @fn_buf_str(ptr %t4) + store ptr %t5, ptr %t6 + %t7 = load ptr, ptr %t0 + %t8 = icmp eq ptr %t7, null + %t9 = zext i1 %t8 to i32 + %t10 = icmp ne i32 %t9, 0 + br i1 %t10, label %then0, label %ifend2 +then0: + %t11 = load ptr, ptr %t3 + call i32 (ptr, ...) @printf(ptr @.fmt_str, ptr %t11) + %t12 = load ptr, ptr %t6 + call i32 (ptr, ...) @printf(ptr @.fmt_str, ptr %t12) + store i32 1, ptr %retval + br label %ret +ifend2: + %t13 = load ptr, ptr %t0 + %t14 = call ptr @fopen(ptr %t13, ptr @.str1408) + store ptr %t14, ptr %t15 + %t16 = load ptr, ptr %t15 + %t17 = icmp eq ptr %t16, null + %t18 = zext i1 %t17 to i32 + %t19 = icmp ne i32 %t18, 0 + br i1 %t19, label %then3, label %ifend5 +then3: + store i32 0, ptr %retval + br label %ret +ifend5: + %t20 = load ptr, ptr %t15 + %t21 = load ptr, ptr %t3 + %t22 = load ptr, ptr %t3 + %t23 = call i32 @fn_slen(ptr %t22) + %t24 = zext i32 %t23 to i64 + %t25 = call i64 @fwrite(ptr %t21, i64 1, i64 %t24, ptr %t20) + %t26 = trunc i64 %t25 to i32 + %t27 = load ptr, ptr %t15 + %t28 = load ptr, ptr %t6 + %t29 = load ptr, ptr %t6 + %t30 = call i32 @fn_slen(ptr %t29) + %t31 = zext i32 %t30 to i64 + %t32 = call i64 @fwrite(ptr %t28, i64 1, i64 %t31, ptr %t27) + %t33 = trunc i64 %t32 to i32 + %t34 = load ptr, ptr %t15 + call i32 @fclose(ptr %t34) + store i32 1, ptr %retval + br label %ret +ret: + %t35 = load i32, ptr %retval + ret i32 %t35 +} + +define ptr @fn_base_name(ptr %arg_path) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t2 = alloca i32 + %t3 = alloca i32 + store ptr %arg_path, ptr %t0 + %t1 = sub i32 0, 1 + store i32 %t1, ptr %t2 + store i32 0, ptr %t3 + br label %wcond0 +wcond0: + %t4 = load ptr, ptr %t0 + %t5 = load i32, ptr %t3 + %t6 = getelementptr inbounds i8, ptr %t4, i32 %t5 + %t7 = load i8, ptr %t6 + %t8 = zext i8 %t7 to i32 + %t9 = icmp ne i32 %t8, 0 + %t10 = zext i1 %t9 to i32 + %t11 = icmp ne i32 %t10, 0 + br i1 %t11, label %wbody1, label %wend2 +wbody1: + %t12 = load ptr, ptr %t0 + %t13 = load i32, ptr %t3 + %t14 = getelementptr inbounds i8, ptr %t12, i32 %t13 + %t15 = load i8, ptr %t14 + %t16 = zext i8 %t15 to i32 + %t17 = icmp eq i32 %t16, 47 + %t18 = zext i1 %t17 to i32 + %t19 = icmp ne i32 %t18, 0 + br i1 %t19, label %then3, label %ifend5 +then3: + %t20 = load i32, ptr %t3 + store i32 %t20, ptr %t2 + br label %ifend5 +ifend5: + %t21 = load i32, ptr %t3 + %t22 = add i32 %t21, 1 + store i32 %t22, ptr %t3 + br label %wcond0 +wend2: + %t23 = load ptr, ptr %t0 + %t24 = load i32, ptr %t2 + %t25 = add i32 %t24, 1 + %t26 = load i32, ptr %t3 + %t27 = load i32, ptr %t2 + %t28 = add i32 %t27, 1 + %t29 = sub i32 %t26, %t28 + %t30 = call ptr @fn_substr(ptr %t23, i32 %t25, i32 %t29) + store ptr %t30, ptr %retval + br label %ret +ret: + %t31 = load ptr, ptr %retval + ret ptr %t31 +} + +define ptr @fn_strip_ludic(ptr %arg_name) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t3 = alloca i32 + store ptr %arg_name, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = call i32 @fn_slen(ptr %t1) + store i32 %t2, ptr %t3 + %t4 = load i32, ptr %t3 + %t5 = icmp sgt i32 %t4, 6 + %t6 = zext i1 %t5 to i32 + %t7 = icmp ne i32 %t6, 0 + br i1 %t7, label %then0, label %ifend2 +then0: + %t8 = load ptr, ptr %t0 + %t9 = load i32, ptr %t3 + %t10 = sub i32 %t9, 6 + %t11 = call ptr @fn_substr(ptr %t8, i32 %t10, i32 6) + %t12 = call i32 @fn_streq(ptr %t11, ptr @.str1409) + %t13 = icmp ne i32 %t12, 0 + br i1 %t13, label %then3, label %ifend5 +then3: + %t14 = load ptr, ptr %t0 + %t15 = load i32, ptr %t3 + %t16 = sub i32 %t15, 6 + %t17 = call ptr @fn_substr(ptr %t14, i32 0, i32 %t16) + store ptr %t17, ptr %retval + br label %ret +ifend5: + br label %ifend2 +ifend2: + %t18 = load ptr, ptr %t0 + store ptr %t18, ptr %retval + br label %ret +ret: + %t19 = load ptr, ptr %retval + ret ptr %t19 +} + +define ptr @fn_getenv_or(ptr %arg_name, ptr %arg_dflt) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t1 = alloca ptr + %t4 = alloca ptr + store ptr %arg_name, ptr %t0 + store ptr %arg_dflt, ptr %t1 + %t2 = load ptr, ptr %t0 + %t3 = call ptr @getenv(ptr %t2) + store ptr %t3, ptr %t4 + %t5 = load ptr, ptr %t4 + %t6 = icmp eq ptr %t5, null + %t7 = zext i1 %t6 to i32 + %t8 = icmp ne i32 %t7, 0 + br i1 %t8, label %then0, label %ifend2 +then0: + %t9 = load ptr, ptr %t1 + store ptr %t9, ptr %retval + br label %ret +ifend2: + %t10 = load ptr, ptr %t4 + store ptr %t10, ptr %retval + br label %ret +ret: + %t11 = load ptr, ptr %retval + ret ptr %t11 +} + +define ptr @fn_ensure_slash(ptr %arg_d) { +entry: + %retval = alloca ptr + %t0 = alloca ptr + %t3 = alloca i32 + store ptr %arg_d, ptr %t0 + %t1 = load ptr, ptr %t0 + %t2 = call i32 @fn_slen(ptr %t1) + store i32 %t2, ptr %t3 + %t4 = load i32, ptr %t3 + %t5 = icmp eq i32 %t4, 0 + %t6 = zext i1 %t5 to i32 + %t7 = icmp ne i32 %t6, 0 + br i1 %t7, label %then0, label %ifend2 +then0: + %t8 = load ptr, ptr %t0 + store ptr %t8, ptr %retval + br label %ret +ifend2: + %t9 = load ptr, ptr %t0 + %t10 = load i32, ptr %t3 + %t11 = sub i32 %t10, 1 + %t12 = getelementptr inbounds i8, ptr %t9, i32 %t11 + %t13 = load i8, ptr %t12 + %t14 = zext i8 %t13 to i32 + %t15 = icmp eq i32 %t14, 47 + %t16 = zext i1 %t15 to i32 + %t17 = icmp ne i32 %t16, 0 + br i1 %t17, label %then3, label %ifend5 +then3: + %t18 = load ptr, ptr %t0 + store ptr %t18, ptr %retval + br label %ret +ifend5: + %t19 = load ptr, ptr %t0 + %t20 = call ptr @fn_sconcat(ptr %t19, ptr @.str1410) + store ptr %t20, ptr %retval + br label %ret +ret: + %t21 = load ptr, ptr %retval + ret ptr %t21 +} + +define void @fn_die(ptr %arg_msg) { +entry: + %t0 = alloca ptr + store ptr %arg_msg, ptr %t0 + %t1 = load ptr, ptr @__stderrp + %t2 = load ptr, ptr %t0 + %t3 = load ptr, ptr %t0 + %t4 = call i32 @fn_slen(ptr %t3) + %t5 = zext i32 %t4 to i64 + %t6 = call i64 @fwrite(ptr %t2, i64 1, i64 %t5, ptr %t1) + %t7 = trunc i64 %t6 to i32 + call void @exit(i32 1) + unreachable +ret: + ret void +} + +define i32 @main(i32 %argc, ptr %argv) { +entry: + %retval = alloca i32 + %t0 = alloca ptr + %t1 = alloca ptr + %t2 = alloca i32 + %t3 = alloca i32 + %t4 = alloca i32 + %t5 = alloca i32 + %t6 = alloca i32 + %t13 = alloca i32 + %t23 = alloca ptr + %t66 = alloca ptr + %t83 = alloca ptr + %t93 = alloca i32 + %t105 = alloca i32 + %t114 = alloca i32 + %t131 = alloca i32 + %t148 = alloca ptr + %t159 = alloca ptr + %t166 = alloca ptr + %t173 = alloca ptr + %t178 = alloca ptr + %t183 = alloca ptr + %t195 = alloca i32 + %t211 = alloca i32 + store i32 %argc, ptr @L_argc + store ptr %argv, ptr @L_argv + store i32 0, ptr %retval + store ptr null, ptr %t0 + store ptr null, ptr %t1 + store i32 0, ptr %t2 + store i32 0, ptr %t3 + store i32 0, ptr %t4 + store i32 0, ptr %t5 + store i32 0, ptr %t6 + %t7 = load ptr, ptr @L_argv + %t8 = getelementptr ptr, ptr %t7, i32 0 + %t9 = load ptr, ptr %t8 + %t10 = call ptr @fn_base_name(ptr %t9) + %t11 = call i32 @fn_streq(ptr %t10, ptr @.str1411) + %t12 = icmp ne i32 %t11, 0 + br i1 %t12, label %then0, label %ifend2 +then0: + store i32 1, ptr %t6 + br label %ifend2 +ifend2: + store i32 1, ptr %t13 + br label %wcond3 +wcond3: + %t14 = load i32, ptr %t13 + %t15 = load i32, ptr @L_argc + %t16 = icmp slt i32 %t14, %t15 + %t17 = zext i1 %t16 to i32 + %t18 = icmp ne i32 %t17, 0 + br i1 %t18, label %wbody4, label %wend5 +wbody4: + %t19 = load i32, ptr %t13 + %t20 = load ptr, ptr @L_argv + %t21 = getelementptr ptr, ptr %t20, i32 %t19 + %t22 = load ptr, ptr %t21 + store ptr %t22, ptr %t23 + %t24 = load ptr, ptr %t23 + %t25 = call i32 @fn_streq(ptr %t24, ptr @.str1412) + %t26 = icmp ne i32 %t25, 0 + br i1 %t26, label %then6, label %else7 +then6: + store i32 1, ptr %t2 + br label %ifend8 +else7: + %t27 = load ptr, ptr %t23 + %t28 = call i32 @fn_streq(ptr %t27, ptr @.str1413) + %t29 = icmp ne i32 %t28, 0 + br i1 %t29, label %then9, label %else10 +then9: + store i32 2, ptr %t2 + br label %ifend11 +else10: + %t30 = load ptr, ptr %t23 + %t31 = call i32 @fn_streq(ptr %t30, ptr @.str1414) + %t32 = icmp ne i32 %t31, 0 + br i1 %t32, label %then12, label %else13 +then12: + store i32 1, ptr %t3 + br label %ifend14 +else13: + %t33 = load ptr, ptr %t23 + %t34 = call i32 @fn_streq(ptr %t33, ptr @.str1415) + %t35 = icmp ne i32 %t34, 0 + br i1 %t35, label %then15, label %else16 +then15: + store i32 1, ptr %t4 + br label %ifend17 +else16: + %t36 = load ptr, ptr %t23 + %t37 = call i32 @fn_streq(ptr %t36, ptr @.str1416) + %t38 = icmp ne i32 %t37, 0 + br i1 %t38, label %then18, label %else19 +then18: + store i32 1, ptr %t5 + br label %ifend20 +else19: + %t39 = load ptr, ptr %t23 + %t40 = call i32 @fn_streq(ptr %t39, ptr @.str1417) + %t41 = icmp ne i32 %t40, 0 + br i1 %t41, label %then21, label %else22 +then21: + store i32 1, ptr %t6 + br label %ifend23 +else22: + %t42 = load ptr, ptr %t23 + %t43 = call i32 @fn_streq(ptr %t42, ptr @.str1418) + %t44 = icmp ne i32 %t43, 0 + br i1 %t44, label %then24, label %else25 +then24: + %t45 = load i32, ptr %t13 + %t46 = add i32 %t45, 1 + store i32 %t46, ptr %t13 + %t47 = load i32, ptr %t13 + %t48 = load i32, ptr @L_argc + %t49 = icmp slt i32 %t47, %t48 + %t50 = zext i1 %t49 to i32 + %t51 = icmp ne i32 %t50, 0 + br i1 %t51, label %then27, label %ifend29 +then27: + %t52 = load i32, ptr %t13 + %t53 = load ptr, ptr @L_argv + %t54 = getelementptr ptr, ptr %t53, i32 %t52 + %t55 = load ptr, ptr %t54 + store ptr %t55, ptr %t1 + br label %ifend29 +ifend29: + br label %ifend26 +else25: + %t56 = load ptr, ptr %t23 + %t57 = getelementptr inbounds i8, ptr %t56, i32 0 + %t58 = load i8, ptr %t57 + %t59 = zext i8 %t58 to i32 + %t60 = icmp eq i32 %t59, 45 + %t61 = zext i1 %t60 to i32 + %t62 = icmp ne i32 %t61, 0 + br i1 %t62, label %then30, label %else31 +then30: + %t63 = load ptr, ptr %t23 + %t64 = call ptr @fn_sconcat(ptr %t63, ptr @.str1420) + %t65 = call ptr @fn_sconcat(ptr @.str1419, ptr %t64) + store ptr %t65, ptr %t66 + %t67 = load ptr, ptr @__stderrp + %t68 = load ptr, ptr %t66 + %t69 = load ptr, ptr %t66 + %t70 = call i32 @fn_slen(ptr %t69) + %t71 = zext i32 %t70 to i64 + %t72 = call i64 @fwrite(ptr %t68, i64 1, i64 %t71, ptr %t67) + %t73 = trunc i64 %t72 to i32 + br label %ifend32 +else31: + %t74 = load ptr, ptr %t23 + store ptr %t74, ptr %t0 + br label %ifend32 +ifend32: + br label %ifend26 +ifend26: + br label %ifend23 +ifend23: + br label %ifend20 +ifend20: + br label %ifend17 +ifend17: + br label %ifend14 +ifend14: + br label %ifend11 +ifend11: + br label %ifend8 +ifend8: + %t75 = load i32, ptr %t13 + %t76 = add i32 %t75, 1 + store i32 %t76, ptr %t13 + br label %wcond3 +wend5: + %t77 = load ptr, ptr %t0 + %t78 = icmp eq ptr %t77, null + %t79 = zext i1 %t78 to i32 + %t80 = icmp ne i32 %t79, 0 + br i1 %t80, label %then33, label %ifend35 +then33: + call void @fn_die(ptr @.str1421) + br label %ifend35 +ifend35: + %t81 = load ptr, ptr %t0 + %t82 = call ptr @fn_read_file(ptr %t81) + store ptr %t82, ptr %t83 + %t84 = load ptr, ptr %t83 + %t85 = icmp eq ptr %t84, null + %t86 = zext i1 %t85 to i32 + %t87 = icmp ne i32 %t86, 0 + br i1 %t87, label %then36, label %ifend38 +then36: + call void @fn_die(ptr @.str1422) + br label %ifend38 +ifend38: + %t88 = load ptr, ptr %t0 + %t89 = call ptr @fn_dir_of(ptr %t88) + store ptr %t89, ptr @g_cur_dir + %t90 = load ptr, ptr %t83 + call void @fn_lex(ptr %t90) + call void @fn_parse_program() + %t91 = load i32, ptr %t4 + %t92 = icmp ne i32 %t91, 0 + br i1 %t92, label %then39, label %ifend41 +then39: + call void @exit(i32 0) + unreachable +ifend41: + call void @fn_maybe_splice_runtime() + %t94 = load i32, ptr %t6 + %t95 = icmp ne i32 %t94, 0 + %t96 = zext i1 %t95 to i32 + store i32 %t96, ptr %t93 + br i1 %t95, label %scend43, label %sc42 +sc42: + %t97 = load ptr, ptr %t1 + %t98 = icmp eq ptr %t97, null + %t99 = zext i1 %t98 to i32 + %t100 = icmp eq i32 %t99, 0 + %t101 = zext i1 %t100 to i32 + %t102 = icmp ne i32 %t101, 0 + %t103 = zext i1 %t102 to i32 + store i32 %t103, ptr %t93 + br label %scend43 +scend43: + %t104 = load i32, ptr %t93 + store i32 %t104, ptr %t105 + %t106 = load i32, ptr %t2 + %t107 = icmp eq i32 %t106, 1 + %t108 = zext i1 %t107 to i32 + %t109 = icmp ne i32 %t108, 0 + br i1 %t109, label %then44, label %else45 +then44: + store i32 1, ptr @g_g_windowed + br label %ifend46 +else45: + %t110 = load i32, ptr %t2 + %t111 = icmp eq i32 %t110, 2 + %t112 = zext i1 %t111 to i32 + %t113 = icmp ne i32 %t112, 0 + br i1 %t113, label %then47, label %else48 +then47: + store i32 0, ptr @g_g_windowed + br label %ifend49 +else48: + %t115 = load i32, ptr %t105 + %t116 = icmp ne i32 %t115, 0 + %t117 = zext i1 %t116 to i32 + store i32 %t117, ptr %t114 + br i1 %t116, label %sc50, label %scend51 +sc50: + %t118 = call i32 @fn_has_systems() + %t119 = icmp ne i32 %t118, 0 + %t120 = zext i1 %t119 to i32 + store i32 %t120, ptr %t114 + br label %scend51 +scend51: + %t121 = load i32, ptr %t114 + store i32 %t121, ptr @g_g_windowed + br label %ifend49 +ifend49: + br label %ifend46 +ifend46: + call void @fn_emit_program() + %t122 = load i32, ptr %t3 + %t123 = icmp ne i32 %t122, 0 + br i1 %t123, label %then52, label %ifend54 +then52: + %t124 = load ptr, ptr %t1 + %t125 = call i32 @fn_ir_flush(ptr %t124) + br label %ret +ifend54: + %t126 = load i32, ptr %t105 + %t127 = icmp eq i32 %t126, 0 + %t128 = zext i1 %t127 to i32 + %t129 = icmp ne i32 %t128, 0 + br i1 %t129, label %then55, label %ifend57 +then55: + %t130 = call i32 @fn_ir_flush(ptr null) + br label %ret +ifend57: + %t132 = load i32, ptr %t6 + %t133 = icmp ne i32 %t132, 0 + %t134 = zext i1 %t133 to i32 + store i32 %t134, ptr %t131 + br i1 %t133, label %sc58, label %scend59 +sc58: + %t135 = load ptr, ptr %t1 + %t136 = icmp eq ptr %t135, null + %t137 = zext i1 %t136 to i32 + %t138 = icmp ne i32 %t137, 0 + %t139 = zext i1 %t138 to i32 + store i32 %t139, ptr %t131 + br label %scend59 +scend59: + %t140 = load i32, ptr %t131 + %t141 = icmp ne i32 %t140, 0 + br i1 %t141, label %then60, label %ifend62 +then60: + %t142 = load ptr, ptr %t0 + %t143 = call ptr @fn_base_name(ptr %t142) + %t144 = call ptr @fn_strip_ludic(ptr %t143) + %t145 = call ptr @fn_sconcat(ptr @.str1423, ptr %t144) + store ptr %t145, ptr %t1 + br label %ifend62 +ifend62: + %t146 = load ptr, ptr %t1 + %t147 = call ptr @fn_dir_of(ptr %t146) + store ptr %t147, ptr %t148 + %t149 = load ptr, ptr %t148 + %t150 = call i32 @fn_slen(ptr %t149) + %t151 = icmp sgt i32 %t150, 0 + %t152 = zext i1 %t151 to i32 + %t153 = icmp ne i32 %t152, 0 + br i1 %t153, label %then63, label %ifend65 +then63: + %t154 = load ptr, ptr %t148 + %t155 = call ptr @fn_sconcat(ptr @.str1424, ptr %t154) + %t156 = call i32 @system(ptr %t155) + br label %ifend65 +ifend65: + %t157 = load ptr, ptr %t1 + %t158 = call ptr @fn_sconcat(ptr %t157, ptr @.str1425) + store ptr %t158, ptr %t159 + %t160 = load ptr, ptr %t159 + %t161 = call i32 @fn_ir_flush(ptr %t160) + %t162 = icmp eq i32 %t161, 0 + %t163 = zext i1 %t162 to i32 + %t164 = icmp ne i32 %t163, 0 + br i1 %t164, label %then66, label %ifend68 +then66: + call void @fn_die(ptr @.str1426) + br label %ifend68 +ifend68: + %t165 = call ptr @fn_getenv_or(ptr @.str1427, ptr @.str1428) + store ptr %t165, ptr %t166 + %t167 = load ptr, ptr @L_argv + %t168 = getelementptr ptr, ptr %t167, i32 0 + %t169 = load ptr, ptr %t168 + %t170 = call ptr @fn_dir_of(ptr %t169) + %t171 = call ptr @fn_getenv_or(ptr @.str1429, ptr %t170) + %t172 = call ptr @fn_ensure_slash(ptr %t171) + store ptr %t172, ptr %t173 + %t174 = load ptr, ptr %t166 + %t175 = load ptr, ptr %t159 + %t176 = call ptr @fn_sconcat(ptr @.str1430, ptr %t175) + %t177 = call ptr @fn_sconcat(ptr %t174, ptr %t176) + store ptr %t177, ptr %t178 + %t179 = load i32, ptr @g_g_windowed + %t180 = icmp ne i32 %t179, 0 + br i1 %t180, label %then69, label %ifend71 +then69: + %t181 = load ptr, ptr %t173 + %t182 = call ptr @fn_path_join(ptr %t181, ptr @.str1431) + store ptr %t182, ptr %t183 + %t184 = load ptr, ptr %t178 + %t185 = load ptr, ptr %t183 + %t186 = call ptr @fn_sconcat(ptr %t185, ptr @.str1433) + %t187 = call ptr @fn_sconcat(ptr @.str1432, ptr %t186) + %t188 = call ptr @fn_sconcat(ptr %t184, ptr %t187) + store ptr %t188, ptr %t178 + br label %ifend71 +ifend71: + %t189 = load ptr, ptr %t178 + %t190 = load ptr, ptr %t1 + %t191 = call ptr @fn_sconcat(ptr @.str1434, ptr %t190) + %t192 = call ptr @fn_sconcat(ptr %t189, ptr %t191) + store ptr %t192, ptr %t178 + %t193 = load ptr, ptr %t178 + %t194 = call i32 @system(ptr %t193) + store i32 %t194, ptr %t195 + %t196 = load i32, ptr %t5 + %t197 = icmp eq i32 %t196, 0 + %t198 = zext i1 %t197 to i32 + %t199 = icmp ne i32 %t198, 0 + br i1 %t199, label %then72, label %ifend74 +then72: + %t200 = load ptr, ptr %t159 + %t201 = call ptr @fn_sconcat(ptr @.str1435, ptr %t200) + %t202 = call i32 @system(ptr %t201) + br label %ifend74 +ifend74: + %t203 = load i32, ptr %t195 + %t204 = icmp ne i32 %t203, 0 + %t205 = zext i1 %t204 to i32 + %t206 = icmp ne i32 %t205, 0 + br i1 %t206, label %then75, label %ifend77 +then75: + call void @fn_die(ptr @.str1436) + br label %ifend77 +ifend77: + %t207 = load i32, ptr %t6 + %t208 = icmp ne i32 %t207, 0 + br i1 %t208, label %then78, label %ifend80 +then78: + %t209 = load ptr, ptr %t1 + %t210 = call i32 @system(ptr %t209) + store i32 %t210, ptr %t211 + %t212 = load i32, ptr %t211 + %t213 = lshr i32 %t212, 8 + %t214 = and i32 %t213, 255 + call void @exit(i32 %t214) + unreachable +ifend80: + br label %ret +ret: + %t215 = load i32, ptr %retval + ret i32 %t215 +} diff --git a/selfhost/main.ludic b/selfhost/main.ludic new file mode 100644 index 00000000..b0777322 --- /dev/null +++ b/selfhost/main.ludic @@ -0,0 +1,153 @@ +# main.ludic — the self-hosted Ludic front-end. +# +# ludicc lexes, parses, checks and lowers a .ludic file to LLVM IR, then drives +# clang (the IR assembler + system linker, the same role rustc/swiftc give it) +# to produce a native binary. No C is compiled: the emitted IR is Ludic's, and +# clang only assembles and links it. +# +# ludicc app.ludic -o bin/app # native binary (windowed if a game) +# ludicc app.ludic -o bin/app --headless # force headless +# ludicc app.ludic --emit-llvm -o app.ll # stop at the IR +# ludic app.ludic # compile to a temp binary and run it +# +# The multi-call twist: when argv[0] is "ludic" it defaults to compile-and-run. +# With no -o and no run, IR still goes to stdout — the contract build.sh and +# reseed.sh rely on, so the bootstrap is untouched. + +# basename: the part of a path after the last '/'. +fn base_name(path: ptr) -> ptr { + let last = 0 - 1 + let i = 0 + while peek8(path, i) != 0 { if peek8(path, i) == 47 { last = i } i = i + 1 } + return substr(path, last + 1, i - (last + 1)) +} + +# drop a trailing ".ludic" if present +fn strip_ludic(name: ptr) -> ptr { + let n = slen(name) + if n > 6 { + if streq(substr(name, n - 6, 6), ".ludic") { return substr(name, 0, n - 6) } + } + return name +} + +# env var with a fallback when unset +fn getenv_or(name: ptr, dflt: ptr) -> ptr { + let v = os_getenv(name) + if ptr_is_null(v) { return dflt } + return v +} + +# guarantee a directory string ends in '/' so path_join concatenates cleanly +fn ensure_slash(d: ptr) -> ptr { + let n = slen(d) + if n == 0 { return d } + if peek8(d, n - 1) == 47 { return d } + return sconcat(d, "/") +} + +fn die(msg: ptr) -> void { + file_write(file_stderr(), msg, slen(msg)) + os_exit(1) +} + +main { + let path = ptr_null() + let out = ptr_null() + let want = 0 # 0 = auto, 1 = windowed, 2 = headless + let emit_ir = false # --emit-llvm: stop after writing IR + let fmt = false # --fmt: lex + parse only, then exit (the doc-check gate) + let save = false # --save-temps: keep the intermediate .ll + let run = false # compile then execute the result + + # multi-call: invoked as `ludic` -> run mode by default + if streq(base_name(os_arg(0)), "ludic") { run = true } + + let ai = 1 + while ai < os_argc() { + let a = os_arg(ai) + if streq(a, "--windowed") { want = 1 } + else { if streq(a, "--headless") { want = 2 } + else { if streq(a, "--emit-llvm") { emit_ir = true } + else { if streq(a, "--fmt") { fmt = true } + else { if streq(a, "--save-temps") { save = true } + else { if streq(a, "--run") { run = true } + else { if streq(a, "-o") { ai = ai + 1 if ai < os_argc() { out = os_arg(ai) } } + else { + # an unknown flag is ignored (with a note) rather than mistaken for the + # input file — '-' is ASCII 45 + if peek8(a, 0) == 45 { + let m = sconcat("ludicc: ignoring unknown flag ", sconcat(a, "\n")) + file_write(file_stderr(), m, slen(m)) + } else { path = a } + } } } } } } } + ai = ai + 1 + } + + if ptr_is_null(path) { + die("usage: ludicc [-o out] [--windowed|--headless] [--emit-llvm] [--save-temps]\n") + } + let src = read_file(path) + if ptr_is_null(src) { die("ludicc: cannot open input\n") } + + cur_dir = dir_of(path) + lex(src) + parse_program() + + # --fmt is the doc-check gate: reaching here means it lexed and parsed. A parse + # error would already have exited nonzero, so a clean parse exits 0. (Canonical + # formatting output is not yet reimplemented on the self-hosted toolchain.) + if fmt { os_exit(0) } + + maybe_splice_runtime() + + # a game gets a window by default; a plain program stays headless. An explicit + # flag always wins. The stdout-IR path (no target) also stays headless, which + # is what reseed.sh compiles the compiler itself with. + let has_target = run or (not ptr_is_null(out)) + if want == 1 { g_windowed = true } + else { if want == 2 { g_windowed = false } + else { g_windowed = has_target and has_systems() } } + + emit_program() + + # --emit-llvm, or no binary target: emit IR and stop (stdout when out is null). + if emit_ir { ir_flush(out) return } + if not has_target { ir_flush(ptr_null()) return } + + # a run with no explicit -o lands in a temp file + if run and ptr_is_null(out) { + out = sconcat("/tmp/ludic-run-", strip_ludic(base_name(path))) + } + + # make the output directory if the user asked for e.g. bin/app + let odir = dir_of(out) + if slen(odir) > 0 { os_system(sconcat("mkdir -p ", odir)) } + + let ll = sconcat(out, ".ll") + if not ir_flush(ll) { die("ludicc: cannot write IR\n") } + + let cc = getenv_or("LUDIC_CC", "clang") + let home = ensure_slash(getenv_or("LUDIC_HOME", dir_of(os_arg(0)))) + + # clang twice: assemble the IR, then link. A windowed build adds the macOS + # platform layer and the Cocoa framework. + # -Wno-override-module: our IR carries an explicit target triple, which clang + # would otherwise warn about on every build. + let cmd = sconcat(cc, sconcat(" -O2 -Wno-override-module ", ll)) + if g_windowed { + let cocoa = path_join(home, "runtime/native/cocoa.ll") + cmd = sconcat(cmd, sconcat(" ", sconcat(cocoa, " -framework Cocoa -Wl,-rpath,@loader_path"))) + } + cmd = sconcat(cmd, sconcat(" -o ", out)) + + let rc = os_system(cmd) + if not save { os_system(sconcat("rm -f ", ll)) } + if rc != 0 { die("ludicc: link failed\n") } + + # run mode: execute the binary we just built and forward its exit code + if run { + let st = os_system(out) + os_exit(band(shr(st, 8), 255)) + } +} diff --git a/selfhost/parse.ludic b/selfhost/parse.ludic new file mode 100644 index 00000000..7bef78b4 --- /dev/null +++ b/selfhost/parse.ludic @@ -0,0 +1,322 @@ +# parse.ludic — recursive-descent parser: the token slice -> an AST. +# Reduced grammar: structs, vars, consts, fns, main; no ECS/scene/ui/match. +# Mirrors compiler/front/parse.c. Uses the global `toks` and a cursor `pi`. + +var pi: int = 0 +var prog: []Node # the top-level declarations +var g_game_name: ptr # the `game`/`module` name + +fn cur() -> Tok { return toks[pi] } +fn pk(o: int) -> Tok { return toks[pi + o] } +fn is_op(v: ptr) -> bool { let t = toks[pi] return t.kind == TK_OP and streq(t.text, v) } +fn is_id(v: ptr) -> bool { let t = toks[pi] return t.kind == TK_ID and streq(t.text, v) } +fn is_kw(v: ptr) -> bool { return is_id(v) } + +fn perr(msg: ptr) -> void { + let e = file_stderr() + file_write(e, "ludicc(self): parse error: ", 27) + file_write(e, msg, slen(msg)) + file_write(e, "\n", 1) + os_exit(1) +} + +fn eat_op(v: ptr) -> void { if not is_op(v) { perr(v) } pi = pi + 1 } +fn eat_id() -> ptr { + let t = toks[pi] + if t.kind != TK_ID { perr("expected identifier") } + pi = pi + 1 + return t.text +} +fn skipnl() -> void { while toks[pi].kind == TK_NL { pi = pi + 1 } } + +# a type: `[]T` slice, or a plain name (int/ptr/str/bool/struct) +fn ptype() -> ptr { + if is_op("[") { + pi = pi + 1 + eat_op("]") + let el = ptype() + let out = mem_alloc(slen(el) + 3) + poke8(out, 0, 91) poke8(out, 1, 93) # "[]" + let i = 0 + while peek8(el, i) != 0 { poke8(out, 2 + i, peek8(el, i)) i = i + 1 } + poke8(out, 2 + i, 0) + return out + } + return eat_id() +} + +# ---- expressions ----------------------------------------------------------- +fn expr() -> Node { return p_or() } + +fn args_call(call: Node) -> void { + eat_op("(") skipnl() + while not is_op(")") { push(call.kids, expr()) skipnl() if is_op(",") { pi = pi + 1 skipnl() } } + eat_op(")") +} + +fn p_primary() -> Node { + let t = toks[pi] + if t.kind == TK_INT { let n = node(E_INT) n.ival = t.ival pi = pi + 1 return n } + if t.kind == TK_FLOAT { let n = node(E_FLOAT) n.ival = t.ival pi = pi + 1 return n } + if t.kind == TK_STR { let n = node(E_STR) n.s = t.text pi = pi + 1 return n } + if t.kind == TK_ID { + if streq(t.text, "true") { let n = node(E_BOOL) n.ival = 1 pi = pi + 1 return n } + if streq(t.text, "false") { let n = node(E_BOOL) n.ival = 0 pi = pi + 1 return n } + if streq(t.text, "new") { pi = pi + 1 let n = node(E_NEW) n.s = ptype() return n } + let n = node(E_ID) n.s = t.text pi = pi + 1 return n + } + if is_op("(") { pi = pi + 1 skipnl() let e = expr() skipnl() eat_op(")") return e } + perr("expected expression") + return node(E_INT) +} + +fn p_postfix() -> Node { + let e = p_primary() + while true { + if is_op(".") { pi = pi + 1 let m = node(E_MEMBER) m.a = e m.s = eat_id() e = m } + else { if is_op("[") { pi = pi + 1 let ix = node(E_INDEX) ix.a = e ix.b = expr() eat_op("]") e = ix } + else { if is_op("(") { let c = node(E_CALL) c.a = e args_call(c) e = c } else { break } } } + } + return e +} + +fn p_unary() -> Node { + if is_op("-") { pi = pi + 1 let n = node(E_UN) n.s = "-" n.a = p_unary() return n } + if is_id("not") { pi = pi + 1 let n = node(E_UN) n.s = "not" n.a = p_unary() return n } + return p_postfix() +} + +fn mkbin(op: ptr, l: Node, r: Node) -> Node { let b = node(E_BIN) b.s = op b.a = l b.b = r return b } + +fn p_mul() -> Node { + let l = p_unary() + while is_op("*") or is_op("/") or is_op("%") { let op = toks[pi].text pi = pi + 1 l = mkbin(op, l, p_unary()) } + return l +} +fn p_add() -> Node { + let l = p_mul() + while is_op("+") or is_op("-") { let op = toks[pi].text pi = pi + 1 l = mkbin(op, l, p_mul()) } + return l +} +fn p_cmp() -> Node { + let l = p_add() + while is_op("<") or is_op("<=") or is_op(">") or is_op(">=") or is_op("==") or is_op("!=") { + let op = toks[pi].text pi = pi + 1 l = mkbin(op, l, p_add()) + } + return l +} +fn p_and() -> Node { + let l = p_cmp() + while is_id("and") { pi = pi + 1 l = mkbin("and", l, p_cmp()) } + return l +} +fn p_or() -> Node { + let l = p_and() + while is_id("or") { pi = pi + 1 l = mkbin("or", l, p_and()) } + return l +} + +# a record literal `{ field = value, ... }` — used by spawn component inits +fn record() -> Node { + eat_op("{") + let r = node(E_REC) + while true { skipnl() if is_op("}") { break } + let fi = node(E_FINIT) fi.s = eat_id() eat_op("=") fi.a = expr() push(r.kids, fi) + if is_op(",") { pi = pi + 1 } } + eat_op("}") return r +} + +# ---- statements ------------------------------------------------------------ +fn block() -> Node { + skipnl() eat_op("{") + let b = node(N_BLOCK) + while true { skipnl() if is_op("}") { break } push(b.kids, stmt()) } + eat_op("}") + return b +} + +fn stmt() -> Node { + let t = toks[pi] + if t.kind == TK_ID { + if streq(t.text, "let") { + pi = pi + 1 let n = node(S_LET) n.s = eat_id() + if is_op(":") { pi = pi + 1 n.ty = ptype() } + if is_op("=") { pi = pi + 1 n.a = expr() } + return n + } + if streq(t.text, "return") { + pi = pi + 1 let n = node(S_RETURN) + if toks[pi].kind != TK_NL and not is_op("}") { n.a = expr() } + return n + } + if streq(t.text, "if") { + pi = pi + 1 let n = node(S_IF) n.a = expr() n.b = block() skipnl() + if is_id("else") { pi = pi + 1 skipnl() + if is_id("if") { n.c = stmt() } else { n.c = block() } } + return n + } + if streq(t.text, "when") { # `when c { }` — an if with no else + pi = pi + 1 let n = node(S_IF) n.a = expr() n.b = block() + return n + } + if streq(t.text, "while") { pi = pi + 1 let n = node(S_WHILE) n.a = expr() n.b = block() return n } + if streq(t.text, "for") { + pi = pi + 1 + if is_op("(") { return parse_query_for() } + let n = node(S_FOR) n.s = eat_id() + let inkw = eat_id() # 'in' + n.a = expr() eat_op("..") n.b = expr() n.c = block() + return n + } + if streq(t.text, "spawn") { return parse_spawn() } + if streq(t.text, "machine") { + pi = pi + 1 let n = node(S_MACHINE) n.a = expr() skipnl() eat_op("{") + while true { skipnl() if is_op("}") { break } + let stkw = eat_id() # 'state' + let s = node(S_STATE) s.s = eat_id() eat_op("=") s.b = expr() skipnl() s.a = block() + push(n.kids, s) } + eat_op("}") return n + } + if streq(t.text, "become") { pi = pi + 1 let n = node(S_BECOME) n.s = eat_id() return n } + if streq(t.text, "enter") { pi = pi + 1 let n = node(S_BECOME) n.s = eat_id() n.ival = 1 return n } + if streq(t.text, "despawn") { pi = pi + 1 let n = node(S_DESPAWN) n.a = expr() return n } + if streq(t.text, "break") { pi = pi + 1 return node(S_BREAK) } + if streq(t.text, "continue") { pi = pi + 1 return node(S_CONTINUE) } + if streq(t.text, "match") { + pi = pi + 1 let n = node(S_MATCH) n.a = expr() skipnl() eat_op("{") + while true { + skipnl() if is_op("}") { break } + let arm = node(S_MARM) + while true { push(arm.kids, expr()) if is_op(",") { pi = pi + 1 skipnl() continue } break } + eat_op("=>") skipnl() + if is_op("{") { arm.a = block() } else { let b = node(N_BLOCK) push(b.kids, stmt()) arm.a = b } + push(n.kids, arm) + } + eat_op("}") return n + } + } + let e = expr() + if is_op("=") or is_op("+=") or is_op("-=") or is_op("*=") or is_op("/=") { + let n = node(S_ASSIGN) n.s = toks[pi].text pi = pi + 1 n.a = e n.b = expr() return n + } + let n = node(S_EXPR) n.a = e return n +} + +# ---- declarations ---------------------------------------------------------- +fn parse_struct() -> Node { + pi = pi + 1 let n = node(N_STRUCT) n.s = eat_id() skipnl() eat_op("{") + while true { skipnl() if is_op("}") { break } + let f = node(N_FIELD) f.s = eat_id() eat_op(":") f.ty = ptype() + if is_op("=") { pi = pi + 1 f.a = expr() } + push(n.kids, f) if is_op(",") { pi = pi + 1 } } + eat_op("}") return n +} +fn parse_var() -> Node { + pi = pi + 1 let n = node(N_VAR) n.s = eat_id() eat_op(":") n.ty = ptype() + if is_op("=") { pi = pi + 1 n.a = expr() } + return n +} +fn parse_const() -> Node { + pi = pi + 1 let n = node(N_CONST) n.s = eat_id() eat_op(":") n.ty = ptype() eat_op("=") n.a = expr() + return n +} +fn parse_fn() -> Node { + pi = pi + 1 let n = node(N_FN) n.s = eat_id() eat_op("(") + while not is_op(")") { + let p = node(N_PARAM) p.s = eat_id() eat_op(":") p.ty = ptype() push(n.kids, p) + if is_op(",") { pi = pi + 1 } + } + eat_op(")") + n.ty = "void" + if is_op("->") { pi = pi + 1 n.ty = ptype() } + n.a = block() + return n +} +fn parse_main() -> Node { pi = pi + 1 let n = node(N_MAIN) n.a = block() return n } + +# directory part of a path, including the trailing '/', or "" if none +fn dir_of(path: ptr) -> ptr { + let last = 0 - 1 + let i = 0 + while peek8(path, i) != 0 { if peek8(path, i) == 47 { last = i } i = i + 1 } + if last < 0 { return "" } + return substr(path, 0, last + 1) +} +fn path_join(dir: ptr, rel: ptr) -> ptr { + if peek8(rel, 0) == 47 { return rel } # absolute + return sconcat(dir, rel) +} + +var loaded_paths: []ptr +var cur_dir: ptr + +fn already_loaded(full: ptr) -> bool { + let i = 0 + while i < len(loaded_paths) { if streq(loaded_paths[i], full) { return true } i = i + 1 } + return false +} + +# parse one top-level declaration (or resolve an import) into `prog` +fn parse_one_decl() -> void { + if is_id("import") { pi = pi + 1 + let t = toks[pi] + if t.kind != TK_STR { perr("expected \"path\" after import") } + let rel = t.text pi = pi + 1 + do_import(rel) + return + } + if is_id("struct") { push(prog, parse_struct()) return } + if is_id("component") { push(prog, parse_component()) return } + if is_id("archetype") { push(prog, parse_archetype()) return } + if is_id("system") or is_id("edge") { push(prog, parse_system()) return } + if is_id("ui") { push(prog, parse_ui()) return } + if is_id("var") { push(prog, parse_var()) return } + if is_id("const") { push(prog, parse_const()) return } + if is_id("export") { pi = pi + 1 let f = parse_fn() f.ival = 1 push(prog, f) return } + if is_id("fn") or is_id("pure") { if is_id("pure") { pi = pi + 1 } push(prog, parse_fn()) return } + if is_id("extern") { push(prog, parse_extern()) return } + if is_id("main") { push(prog, parse_main()) return } + perr("expected declaration") +} + +# lex and parse an imported fragment into `prog`, saving/restoring lexer state +fn do_import(rel: ptr) -> void { + let full = path_join(cur_dir, rel) + if already_loaded(full) { return } + push(loaded_paths, full) + let src = read_file(full) + if ptr_is_null(src) { perr(sconcat("cannot open import ", full)) } + let saved_toks = toks let saved_pi = pi let saved_dir = cur_dir + cur_dir = dir_of(full) + lex(src) # resets the global token stream + pi = 0 + skipnl() + while toks[pi].kind != TK_EOF { parse_one_decl() skipnl() } + toks = saved_toks pi = saved_pi cur_dir = saved_dir +} + +# a game (has systems/components) links the Ludic runtime; auto-splice it the +# way the C compiler does. Tools (a `main` block, no ECS) get nothing. +fn maybe_splice_runtime() -> void { + if not has_ecs() { return } + let saved = cur_dir + cur_dir = "" + do_import("runtime/native/core.ludic") + cur_dir = saved +} + +fn parse_program() -> void { + prog = new []Node + loaded_paths = new []ptr + skipnl() + g_game_name = "Ludic" + # imports may precede the game block + while is_id("import") { pi = pi + 1 let t = toks[pi] let rel = t.text pi = pi + 1 do_import(rel) skipnl() } + if is_id("game") or is_id("module") { pi = pi + 1 g_game_name = eat_id() skipnl() eat_op("{") } + while true { + skipnl() + if toks[pi].kind == TK_EOF { break } + if is_op("}") { break } + parse_one_decl() + } +} diff --git a/selfhost/parse_game.ludic b/selfhost/parse_game.ludic new file mode 100644 index 00000000..13031389 --- /dev/null +++ b/selfhost/parse_game.ludic @@ -0,0 +1,144 @@ +# parse_game.ludic — the ECS front-end: component and system declarations, +# `for (vars) in query [terms] where cond`, spawn and despawn. Mirrors the +# game-construct parsing in compiler/front/parse.c. + +fn parse_component() -> Node { + pi = pi + 1 let n = node(N_COMP) n.s = eat_id() skipnl() eat_op("{") + while true { skipnl() if is_op("}") { break } + let f = node(N_FIELD) f.s = eat_id() eat_op(":") f.ty = ptype() + if is_op("=") { pi = pi + 1 f.a = expr() } + push(n.kids, f) if is_op(",") { pi = pi + 1 } } + eat_op("}") return n +} + +# skip an @annotation or a reads/writes/query/... clause we don't model yet +fn skip_clause() -> void { + if is_op("[") { let depth = 0 + while true { if is_op("[") { depth = depth + 1 } if is_op("]") { depth = depth - 1 } + pi = pi + 1 if depth == 0 { break } } + } +} + +fn parse_system() -> Node { + if is_id("edge") { pi = pi + 1 } # optional `edge` modifier before `system` + pi = pi + 1 let n = node(N_SYS) n.s = eat_id() n.ty = "Update" + # clauses: @anno, phase X, reads/writes/needs/uses [..], query (..) [..] + # A `query (vars) [terms] where c` clause desugars to a body wrapped in one + # `for (vars) in query [terms] where c { ... }` — the same S_QUERY node the + # inline form builds, so `qdecl.ludic` and the inline form share a lowering. + let has_q = false + let qn = node(S_QUERY) + while true { + skipnl() # clauses may span several lines + if is_op("@") { pi = pi + 1 let a = eat_id() if is_op("(") { let d = 0 # @anno, one per turn so a + while true { if is_op("(") { d = d + 1 } if is_op(")") { d = d - 1 } pi = pi + 1 if d == 0 { break } } } + continue } # newline-separated @anno re-skips at the loop top + if is_id("phase") { pi = pi + 1 n.ty = eat_id() continue } + if is_id("reads") or is_id("writes") or is_id("needs") or is_id("uses") { pi = pi + 1 skip_clause() continue } + if is_id("query") { + pi = pi + 1 has_q = true + if is_op("(") { eat_op("(") # optional (vars); omitted when nothing binds + while not is_op(")") { let v = node(E_ID) v.s = eat_id() push(qn.kids, v) if is_op(",") { pi = pi + 1 } } + eat_op(")") } + qn.c = parse_query_tail() + qn.b = qn.c.a # where-expr (or null) + continue + } + break + } + skipnl() + let body = block() + if has_q { + qn.a = body + let wrap = node(N_BLOCK) push(wrap.kids, qn) + n.a = wrap + } else { n.a = body } + return n +} + +# `[Term, ...]` with optional `where `, returning a node whose kids are +# the terms (E_ID with ival=1 for {Tag} filters) and .a the where-expr or null. +fn parse_query_tail() -> Node { + eat_op("[") + let q = node(N_BLOCK) + while not is_op("]") { + if is_op("{") { pi = pi + 1 let t = node(E_ID) t.s = eat_id() t.ival = 1 push(q.kids, t) eat_op("}") } + else { let t = node(E_ID) t.s = eat_id() t.ival = 0 push(q.kids, t) } + if is_op(",") { pi = pi + 1 } + } + eat_op("]") + if is_id("where") { pi = pi + 1 q.a = expr() } + return q +} + +# `for (a, b) in query [Pos, Vel] where ... { body }` +fn parse_query_for() -> Node { + let n = node(S_QUERY) + eat_op("(") + while not is_op(")") { let v = node(E_ID) v.s = eat_id() push(n.kids, v) if is_op(",") { pi = pi + 1 } } + eat_op(")") + let inkw = eat_id() # 'in' + let qkw = eat_id() # 'query' + n.c = parse_query_tail() + n.b = n.c.a # where + n.a = block() + return n +} + +fn parse_spawn() -> Node { + pi = pi + 1 let n = node(S_SPAWN) n.s = eat_id() skipnl() eat_op("{") + while true { + skipnl() if is_op("}") { break } + let ci = node(E_FINIT) ci.s = eat_id() eat_op("=") + ci.a = record() # { field = val, ... } + push(n.kids, ci) + if is_op(",") { pi = pi + 1 } + } + eat_op("}") return n +} + +# archetype Name { CompA, CompB } — a named entity kind (bundle of components) +fn parse_archetype() -> Node { + pi = pi + 1 let n = node(N_ARCH) n.s = eat_id() skipnl() eat_op("{") + while true { skipnl() if is_op("}") { break } + let c = node(E_ID) c.s = eat_id() push(n.kids, c) + if is_op(",") { pi = pi + 1 } skipnl() } + eat_op("}") return n +} + +# extern fn name(params) -> T = "symbol" +fn parse_extern() -> Node { + pi = pi + 1 # 'extern' + let fnkw = eat_id() # 'fn' + let n = node(N_EXTERN) n.s = eat_id() eat_op("(") + while not is_op(")") { let p = node(N_PARAM) p.s = eat_id() eat_op(":") p.ty = ptype() push(n.kids, p) + if is_op(",") { pi = pi + 1 } } + eat_op(")") + n.ty = "void" + if is_op("->") { pi = pi + 1 n.ty = ptype() } + eat_op("=") + let t = toks[pi] # "symbol" + n.a = node(E_STR) n.a.s = t.text pi = pi + 1 + return n +} + +# ui Name { widget-tree } — parsed into a widget node tree (emitted later) +fn parse_widget() -> Node { + let w = node(N_UI) w.s = eat_id() # widget type name + w.b = node(N_BLOCK) # b.kids = props (E_FINIT) + while toks[pi].kind == TK_ID and toks[pi + 1].kind == TK_OP and streq(toks[pi + 1].text, "=") { + let pr = node(E_FINIT) pr.s = eat_id() eat_op("=") pr.a = expr() push(w.b.kids, pr) + } + skipnl() + if is_op("{") { pi = pi + 1 + while true { skipnl() if is_op("}") { break } push(w.kids, parse_widget()) } + eat_op("}") } + return w +} +fn parse_ui() -> Node { + pi = pi + 1 let n = node(N_UI) n.s = eat_id() n.ival = 1 # ival=1 marks the top ui block + skipnl() eat_op("{") skipnl() + n.a = parse_widget() + skipnl() eat_op("}") + return n +} diff --git a/selfhost/reseed.sh b/selfhost/reseed.sh new file mode 100755 index 00000000..1466ef20 --- /dev/null +++ b/selfhost/reseed.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# reseed.sh — regenerate the checked-in IR seed after a deliberate change to the +# self-host compiler. Uses the CURRENT seed (C-free) to produce the new one, so +# the C compiler is not reintroduced; falls back to the C ludicc if no seed +# builds. Always verify with ./selfhost/bootstrap-cfree.sh afterwards. +set -eu +cd "$(dirname "$0")/.." +CC="${LUDIC_CC:-clang}" +B=build/cfree; mkdir -p "$B" +FRAGS="selfhost/str.ludic selfhost/buf.ludic selfhost/io.ludic selfhost/ast.ludic +selfhost/lex.ludic selfhost/parse.ludic selfhost/parse_game.ludic selfhost/emit_core.ludic selfhost/emit_head.ludic +selfhost/emit_addr.ludic selfhost/emit_intrin.ludic selfhost/emit_intrin2.ludic selfhost/emit_math.ludic selfhost/emit_new.ludic +selfhost/emit_expr.ludic selfhost/emit_stmt.ludic selfhost/emit_ecs.ludic selfhost/emit_query.ludic selfhost/emit_spawn.ludic selfhost/emit_game.ludic selfhost/emit_machine.ludic selfhost/emit_save.ludic selfhost/emit_ui.ludic selfhost/emit_decl.ludic selfhost/main.ludic" +{ echo "game SelfHost {"; for f in $FRAGS; do cat "$f"; echo; done; echo "}"; } > "$B/selfhost.ludic" +if $CC selfhost/ludicc.seed.ll -o "$B/sh_old" 2>/dev/null; then + # compile once with the old seed, then AGAIN with the freshly built one so the + # seed is a fixed point of the NEW compiler, not a one-step image of the old. + "$B/sh_old" "$B/selfhost.ludic" > "$B/step1.ll" + $CC "$B/step1.ll" -o "$B/sh_new" + "$B/sh_new" "$B/selfhost.ludic" > selfhost/ludicc.seed.ll +else + echo "seed does not build; reseeding from the C ludicc" + ./selfhost/build.sh build/ludicc "$B/sh_c" + "$B/sh_c" "$B/selfhost.ludic" > selfhost/ludicc.seed.ll +fi +echo "reseeded: $(wc -l < selfhost/ludicc.seed.ll | tr -d ' ') lines" diff --git a/selfhost/str.ludic b/selfhost/str.ludic new file mode 100644 index 00000000..86124bb8 --- /dev/null +++ b/selfhost/str.ludic @@ -0,0 +1,58 @@ +# str.ludic — the string handling a compiler lives on: comparison, copying, +# slicing out substrings, and integer<->text. All over raw NUL-terminated +# byte buffers reached with peek8/poke8. + +fn streq(a: ptr, b: ptr) -> bool { + let i = 0 + while true { + let ca = peek8(a, i) + let cb = peek8(b, i) + if ca != cb { return false } + if ca == 0 { return true } + i = i + 1 + } + return false +} + +fn slen(s: ptr) -> int { + let n = 0 + while peek8(s, n) != 0 { n = n + 1 } + return n +} + +# a fresh NUL-terminated copy of src[start .. start+n] +fn substr(src: ptr, start: int, n: int) -> ptr { + let b = mem_alloc(n + 1) + let i = 0 + while i < n { poke8(b, i, peek8(src, start + i)) i = i + 1 } + poke8(b, n, 0) + return b +} + +fn char_is_digit(c: int) -> bool { return c >= 48 and c <= 57 } +fn char_is_alpha(c: int) -> bool { + if c >= 65 and c <= 90 { return true } + if c >= 97 and c <= 122 { return true } + return c == 95 +} +fn char_is_alnum(c: int) -> bool { return char_is_alpha(c) or char_is_digit(c) } + +# integer -> fresh decimal string +fn itoa(v: int) -> ptr { + if v == 0 { let z = mem_alloc(2) poke8(z, 0, 48) poke8(z, 1, 0) return z } + let neg = false + let x = v + if x < 0 { neg = true x = 0 - x } + let tmp = mem_alloc(16) + let n = 0 + while x > 0 { poke8(tmp, n, 48 + x % 10) x = x / 10 n = n + 1 } + let total = n + if neg { total = total + 1 } + let out = mem_alloc(total + 1) + let k = 0 + if neg { poke8(out, 0, 45) k = 1 } + let i = 0 + while i < n { poke8(out, k + i, peek8(tmp, n - 1 - i)) i = i + 1 } + poke8(out, total, 0) + return out +} diff --git a/selfhost/test.sh b/selfhost/test.sh new file mode 100755 index 00000000..39d8faa6 --- /dev/null +++ b/selfhost/test.sh @@ -0,0 +1,52 @@ +#!/bin/bash +# test.sh — the self-hosting suite: the compiler is correct (compiles diverse +# programs to working binaries) and self-reproducing (the bootstrap fixpoint). +set -u +cd "$(dirname "$0")/.." +CC="${LUDIC_CC:-clang}" +PASS=0; FAIL=0 +ok() { printf " \033[32mPASS\033[0m %s\n" "$1"; PASS=$((PASS+1)); } +bad() { printf " \033[31mFAIL\033[0m %s\n" "$1"; FAIL=$((FAIL+1)); } + +echo "== build the self-host compiler (via the C ludicc) ==" +[ -x build/ludicc ] || ./build.sh >/dev/null 2>&1 +./build.sh examples/snake.ludic --headless >/dev/null 2>&1 && [ -x build/ludicc ] && ok "compiler builds from the IR seed (no C)" || { bad "self-host build"; exit 1; } + +echo "== the self-host compiler is correct ==" +run_case() { # name expected + local n="$1" exp="$2" + ./build/ludicc "selfhost/tests/$n.ludic" > "/tmp/sh_$n.ll" 2>"/tmp/sh_$n.err" || { bad "$n: self-host errored: $(head -1 /tmp/sh_$n.err)"; return; } + $CC "/tmp/sh_$n.ll" -o "/tmp/sh_$n" 2>/dev/null || { bad "$n: IR did not assemble"; return; } + local got; got=$("/tmp/sh_$n" 2>/dev/null | tr '\n' ' ' | sed 's/ *$//') + [ "$got" = "$exp" ] && ok "$n ($got)" || bad "$n: got [$got] want [$exp]" +} +run_case structs "7 9 109 2 42" +run_case slices "0 20 361 777" +run_case control "55 4 15 1" +run_case match_bits "1 2 9 16 4 9999" +run_case fixed "2 3 0 6 1" + +echo "== the self-host compiler compiles real games (vs golden output) ==" +# The golden PPMs in selfhost/golden/ were produced by the original C compiler. +# The self-hosted compiler must reproduce them exactly. +game_case() { # name keys + local n="$1" keys="$2" + ./selfhost/game-build.sh build/ludicc "examples/$n.ludic" "/tmp/ludic_${n}_sh" >/tmp/gb.out 2>&1 || { bad "$n: build ($(tail -1 /tmp/gb.out))"; return; } + printf '%s' "$keys" | "/tmp/ludic_${n}_sh" >/dev/null 2>&1; cp out.ppm "/tmp/${n}_sh.ppm" + cmp -s "selfhost/golden/$n.ppm" "/tmp/${n}_sh.ppm" && ok "$n matches the golden render" || bad "$n: differs from golden" +} +game_case snake "ddssaawwddss" +game_case menu "ssss" +game_case chronorift "ddddwwwwaassK" + +echo "== the bootstrap fixpoint (seeded from the C compiler) ==" +./selfhost/bootstrap.sh >/tmp/boot.out 2>&1 +if grep -q "FIXPOINT" /tmp/boot.out; then ok "gen2.ll == gen3.ll (compiler reproduces itself)"; else bad "fixpoint not reached"; cat /tmp/boot.out; fi + +echo "== the C-free bootstrap (from the checked-in IR seed, no C compiler) ==" +./selfhost/bootstrap-cfree.sh >/tmp/cfree.out 2>&1 +if grep -q "no C compiler" /tmp/cfree.out; then ok "seed.ll rebuilds the compiler and is its own fixed point"; else bad "C-free bootstrap failed (seed stale? run ./selfhost/reseed.sh)"; cat /tmp/cfree.out; fi + +echo +printf "== %d passed, %d failed ==\n" "$PASS" "$FAIL" +[ "$FAIL" -eq 0 ] diff --git a/selfhost/tests/control.ludic b/selfhost/tests/control.ludic new file mode 100644 index 00000000..467ae44e --- /dev/null +++ b/selfhost/tests/control.ludic @@ -0,0 +1,13 @@ +game T { + fn fib(n: int) -> int { if n < 2 { return n } return fib(n-1) + fib(n-2) } + main { + print_int(fib(10)) # 55 + let s = 0 + for i in 0 .. 10 { if i == 5 { break } if i % 2 == 0 { continue } s = s + i } + print_int(s) # 1+3 = 4 + let i = 0 let t = 0 + while true { i = i + 1 if i > 5 { break } t = t + i } + print_int(t) # 15 + if false and (1/0 == 0) { print_int(999) } else { print_int(1) } # short-circuit: no div by zero + } +} diff --git a/selfhost/tests/fixed.ludic b/selfhost/tests/fixed.ludic new file mode 100644 index 00000000..c898c004 --- /dev/null +++ b/selfhost/tests/fixed.ludic @@ -0,0 +1,12 @@ +game T { + main { + let half = 0.5 + let a = 1.5 + print_int(flr(a + half)) # flr(2.0) = 2 + print_int(flr(a * 2.0)) # flr(3.0) = 3 + let third = 1.0 / 3.0 + print_int(flr(third * 3.0)) # ~flr(1.0) = 1 (may be 0 with rounding) + print_int(flr(fx(5) + a)) # flr(6.5) = 6 + if a > half { print_int(1) } else { print_int(0) } # 1 + } +} diff --git a/selfhost/tests/match_bits.ludic b/selfhost/tests/match_bits.ludic new file mode 100644 index 00000000..2cce18aa --- /dev/null +++ b/selfhost/tests/match_bits.ludic @@ -0,0 +1,16 @@ +game T { + fn classify(c: int) -> int { + match c { 65, 66 => { return 1 } 67 => { return 2 } _ => { return 9 } } + return 0 + } + main { + print_int(classify(65)) # 1 + print_int(classify(67)) # 2 + print_int(classify(90)) # 9 + print_int(shl(1, 4)) # 16 + print_int(band(bor(4, 1), 6)) # 4 + let p = mem_alloc(16) + poke32(p, 1, 9999) + print_int(peek32(p, 1)) # 9999 + } +} diff --git a/selfhost/tests/slices.ludic b/selfhost/tests/slices.ludic new file mode 100644 index 00000000..254fed24 --- /dev/null +++ b/selfhost/tests/slices.ludic @@ -0,0 +1,11 @@ +game T { + main { + let xs = new []int + print_int(len(xs)) # 0 + for i in 0 .. 20 { push(xs, i * i) } + print_int(len(xs)) # 20 + print_int(xs[19]) # 361 + xs[3] = 777 + print_int(xs[3]) # 777 + } +} diff --git a/selfhost/tests/structs.ludic b/selfhost/tests/structs.ludic new file mode 100644 index 00000000..1f68f380 --- /dev/null +++ b/selfhost/tests/structs.ludic @@ -0,0 +1,20 @@ +game T { + struct P { x: int = 0, y: int = 7, next: P } + fn bump(p: P) -> void { p.x = p.x + 100 } + main { + let a = new P + print_int(a.y) # 7 default + a.x = 5 + let b = a + b.x = 9 + print_int(a.x) # 9 (reference) + bump(a) + print_int(a.x) # 109 + let c = new P + c.x = 2 + a.next = c + print_int(a.next.x) # 2 chained + a.next.x = 42 + print_int(c.x) # 42 + } +} diff --git a/test.sh b/test.sh new file mode 100755 index 00000000..27dacd1c --- /dev/null +++ b/test.sh @@ -0,0 +1,82 @@ +#!/bin/bash +# test.sh — the regression suite. The compiler is now written in Ludic +# (selfhost/) and built from a checked-in LLVM-IR seed with clang; there is no C +# compiler in the repo. This suite proves the compiler builds from the seed, +# compiles every example to the byte-exact golden render, self-hosts to a +# fixpoint, and rebuilds itself with no C compiler. +set -u +cd "$(dirname "$0")" +PASS=0; FAIL=0 +ok() { printf " \033[32mPASS\033[0m %s\n" "$1"; PASS=$((PASS+1)); } +bad() { printf " \033[31mFAIL\033[0m %s\n" "$1"; FAIL=$((FAIL+1)); } + +echo "== the compiler is written in Ludic, not C ==" +if [ -e compiler ] || ls compiler/*.c >/dev/null 2>&1; then bad "compiler/ C sources still present" +else ok "no C compiler in the repo (compiler/ removed; the compiler is selfhost/*.ludic)"; fi +CLEFT=$(find tools -name '*.c' 2>/dev/null | wc -l | tr -d ' ') +ok "the only C left is the editor tooling ($CLEFT files: ludic-fmt, ludic-lsp)" + +echo "== the compiler builds from the IR seed (no C compiler) ==" +rm -f build/ludicc +if ./build.sh examples/snake.ludic --headless >/dev/null 2>&1 && [ -x build/ludicc ]; then + ok "clang selfhost/ludicc.seed.ll -> build/ludicc" +else bad "compiler did not build from the seed"; fi + +echo "== every example compiles to its golden render ==" +gcase() { # name keys + local n="$1" keys="$2" + ./selfhost/game-build.sh build/ludicc "examples/$n.ludic" "/tmp/ludic_${n}_t" >/tmp/gc.out 2>&1 || { bad "$n: build ($(tail -1 /tmp/gc.out))"; return; } + printf '%s' "$keys" | "/tmp/ludic_${n}_t" >/dev/null 2>&1 + cmp -s "selfhost/golden/$n.ppm" out.ppm && ok "$n renders the golden frame" || bad "$n: render differs from golden" +} +gcase snake "ddssaawwddss" +gcase menu "ssss" +gcase chronorift "ddddwwwwaassK" + +echo "== self-hosting and the bootstrap fixpoints ==" +./selfhost/test.sh >/tmp/sh.out 2>&1 +if grep -q "gen2.ll == gen3.ll" /tmp/sh.out; then ok "the compiler reproduces itself (fixpoint)"; else bad "fixpoint"; fi +if grep -q "no C compiler" /tmp/sh.out; then ok "the compiler rebuilds itself from the seed, C-free"; else bad "C-free bootstrap"; fi +CORR=$(grep -c PASS /tmp/sh.out) +ok "self-host suite: $CORR checks passed (see ./selfhost/test.sh)" + +echo "== documented syntax stays compilable (guards against spec/compiler drift) ==" +# Compiles a feature example end-to-end (parse -> lower -> link). qdecl exercises +# the `query (vars) [terms] where ...` clause in a system SIGNATURE. +qsmoke() { # name + local n="$1" + if ./selfhost/game-build.sh build/ludicc "examples/$n.ludic" "/tmp/ludic_${n}_s" >/tmp/qs.out 2>&1; then + ok "$n compiles (signature-query desugars to S_QUERY)" + else bad "$n: $(tail -1 /tmp/qs.out)"; fi +} +qsmoke qdecl +# --- Toolchain-agent CLI smoke tests append below this line --- +echo "== self-hosted front-end binaries (ludicc / ludic) ==" +# The two commands are one multi-call native binary built from the seed with +# clang alone. ludicc compiles; ludic compiles-and-runs. Each drives clang via +# the os_system intrinsic — no shell wrapper in between. +if ./build-cli.sh >/tmp/cli.out 2>&1 && [ -x ./ludicc ] && [ -x ./ludic ]; then + ok "build-cli.sh builds ./ludicc and ./ludic from the seed (clang-only)" +else bad "build-cli.sh: $(tail -1 /tmp/cli.out)"; fi + +# ludicc -o drives clang to a native binary; a game links windowed by default. +if ./ludicc examples/snake.ludic -o /tmp/cli_snake >/tmp/cli.out 2>&1 \ + && file /tmp/cli_snake 2>/dev/null | grep -q "Mach-O"; then + ok "ludicc app.ludic -o bin -> native executable" +else bad "ludicc -o: $(tail -1 /tmp/cli.out)"; fi + +# --emit-llvm stops at the IR. +if ./ludicc examples/snake.ludic --emit-llvm -o /tmp/cli_snake.ll >/tmp/cli.out 2>&1 \ + && head -1 /tmp/cli_snake.ll | grep -q "LLVM IR"; then + ok "ludicc --emit-llvm -> LLVM IR" +else bad "ludicc --emit-llvm: $(tail -1 /tmp/cli.out)"; fi + +# ludic compiles, runs, and forwards the program's exit code. +printf 'main { os_exit(42) }\n' > /tmp/cli_exit.ludic +./ludic /tmp/cli_exit.ludic >/tmp/cli.out 2>&1 +if [ "$?" -eq 42 ]; then ok "ludic app.ludic -> compiles, runs, forwards exit code" +else bad "ludic run: expected exit 42, got $? ($(tail -1 /tmp/cli.out))"; fi + +echo +printf "== %d passed, %d failed ==\n" "$PASS" "$FAIL" +[ "$FAIL" -eq 0 ] diff --git a/tools/atlas.ludic b/tools/atlas.ludic new file mode 100644 index 00000000..906743fd --- /dev/null +++ b/tools/atlas.ludic @@ -0,0 +1,56 @@ +# ============================================================================ +# atlas.ludic — render a Kenney tile pack as one index-labeled sheet, so you can +# see which sprite id is which before referring to it in a game. +# +# ludicc tools/atlas.ludic --headless -o build/atlas +# ./build/atlas && sips -s format png out.ppm --out atlas.png +# +# Replaces the old tools/atlas.c, which used the C runtime that no longer +# exists. It is the same program, in the language it is a tool for. +# ============================================================================ +game Atlas { + const DIR: str = "assets/kenney/tiny-dungeon/Tiles" + const N: int = 132 + const COLS: int = 12 + const CELL: int = 24 + + system Sheet phase Start { + clear(0x101018) + for i in 0 .. N { + let col = i % COLS + let row = i / COLS + let x = col * CELL + let y = row * CELL + # tile_0000.png … tile_0131.png — the id is the file's number + let id = load_png(tile_path(i)) + if id >= 0 { + draw_sprite(id, x + 4, y + 2) + } + text_int(x + 1, y + 18, i, 0x8090b0, 1) + } + present() + quit() + } + + # build "/tile_%04d.png" without a formatter: the runtime's string + # helpers write into a scratch buffer we own + fn tile_path(i: int) -> str { + let buf = atlas_buf() + let n = rt_put_str(buf, 0, DIR) + n = rt_put_str(buf, n, "/tile_") + if i < 1000 { poke8(buf, n, 48) n = n + 1 } + if i < 100 { poke8(buf, n, 48) n = n + 1 } + if i < 10 { poke8(buf, n, 48) n = n + 1 } + n = rt_put_int(buf, n, i) + n = rt_put_str(buf, n, ".png") + poke8(buf, n, 0) + return buf + } + + var atlas_scratch: ptr = ptr_null() + + fn atlas_buf() -> ptr { + if ptr_is_null(atlas_scratch) { atlas_scratch = mem_alloc(512) } + return atlas_scratch + } +} diff --git a/tools/build-tools.sh b/tools/build-tools.sh new file mode 100755 index 00000000..6c09a9f0 --- /dev/null +++ b/tools/build-tools.sh @@ -0,0 +1,72 @@ +#!/bin/bash +# build-tools.sh — build the Ludic editor toolchain. +# +# ./tools/build-tools.sh -> build/ludic-fmt, build/ludic-lsp +# ./tools/build-tools.sh --test build, then run tools/test-tools.sh +# ./tools/build-tools.sh --install also symlink both into ~/.local/bin +# +# Both binaries are plain C with no dependencies, same as the compiler. They +# share the lexer and vocabulary in tools/ludic-tools/ludic_syntax.h, so a +# keyword added there reaches every editor at once. +set -e +cd "$(dirname "$0")/.." + +CC="${LUDIC_CC:-clang}" +CFLAGS="-O2 -Wall -Wno-unused-function" +SRC=tools/ludic-tools +OUT=build + +mkdir -p "$OUT" + +build_one() { + local name="$1" main="$2" + local newest + # rebuild when any header or the entry point is newer than the binary + if [ -x "$OUT/$name" ]; then + newest=$(find "$SRC" -name '*.h' -o -name "$(basename "$main")" | while read -r f; do + [ "$f" -nt "$OUT/$name" ] && echo new + done) + [ -z "$newest" ] && { echo "$name: up to date"; return; } + fi + echo "cc: $main -> $OUT/$name" + $CC $CFLAGS "$main" -o "$OUT/$name" +} + +build_one ludic-fmt "$SRC/ludic_fmt_main.c" +build_one ludic-lsp "$SRC/ludic_lsp.c" + +# The language server shells out to the compiler for real diagnostics, so having +# it around is most of the value. +if [ ! -x "$OUT/ludicc" ]; then + echo "note: $OUT/ludicc not built yet — run ./build.sh for compiler diagnostics" +fi + +# VS Code needs the grammar inside its own extension directory, so it gets a +# copy. A copy that can drift is the whole failure mode this toolchain is built +# to avoid, so it is refreshed here rather than maintained by hand, and +# test-tools.sh asserts the two are identical. +SHARED=tools/editors/shared +VSC=tools/editors/vscode +if [ -d "$VSC" ]; then + mkdir -p "$VSC/syntaxes" + for f in ludic.tmLanguage.json ludic.markdown-injection.json; do + cmp -s "$SHARED/$f" "$VSC/syntaxes/$f" || { cp "$SHARED/$f" "$VSC/syntaxes/$f"; echo "sync: $f -> $VSC/syntaxes/"; } + done + cmp -s "$SHARED/language-configuration.json" "$VSC/language-configuration.json" || { + cp "$SHARED/language-configuration.json" "$VSC/language-configuration.json" + echo "sync: language-configuration.json -> $VSC/" + } +fi + +if [ "$1" = "--install" ] || [ "$2" = "--install" ]; then + mkdir -p "$HOME/.local/bin" + ln -sf "$PWD/$OUT/ludic-fmt" "$HOME/.local/bin/ludic-fmt" + ln -sf "$PWD/$OUT/ludic-lsp" "$HOME/.local/bin/ludic-lsp" + echo "linked into ~/.local/bin (make sure it is on your PATH)" +fi + +if [ "$1" = "--test" ] || [ "$2" = "--test" ]; then + exec ./tools/test-tools.sh +fi + +echo "done. editors: see tools/editors/README.md" diff --git a/tools/check-docs.py b/tools/check-docs.py new file mode 100755 index 00000000..7981b07d --- /dev/null +++ b/tools/check-docs.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +"""check-docs.py — every ```ludic fence in the docs is checked against the +compiler, so documentation cannot drift away from the language. + +A fence declares its own intent with an in-fence comment (`#` is a Ludic +comment, so the marker is valid code and visible to a reader): + + # doc-check: skip illustrative or pseudo-syntax; not checked + # doc-check: expect-error must FAIL to compile (error demonstrations) + +Anything else must PARSE. The gate is `ludicc --fmt`, not a full build: it runs +lex + parse, which is what catches syntax drift, but does not resolve +identifiers — so an excerpt may reference components and registers that live in +the surrounding program it was lifted from, and still be checked. + +A bare fragment is wrapped first: a declaration list goes inside +`game DocCheck { ... }`, loose statements inside a Start system. +""" +import re, subprocess, sys, os, tempfile + +LC = './build/ludicc' +DECL = ('game','module','component','archetype','system','edge','fn','pure', + 'extern','const','var','ui','scene','import') + +def classify(body): + first = next((l.strip() for l in body.split('\n') + if l.strip() and not l.strip().startswith('#')), '') + head = first.split('(')[0].split()[0] if first else '' + if head in ('game','module'): return 'whole' + return 'decls' if head in DECL else 'stmts' + +def wraps(body, kind): + """Candidate framings, best guess first. An excerpt often mixes declarations + with loose statements, so both are tried and either parsing counts.""" + if kind == 'whole': return [body] + as_decls = 'game DocCheck {\n' + body + '\n}\n' + as_stmts = 'game DocCheck {\n system DocS phase Start {\n' + body + '\n }\n}\n' + return [as_decls, as_stmts] if kind == 'decls' else [as_stmts, as_decls] + +def fences(path): + t = open(path).read() + for m in re.finditer(r'^```ludic\n(.*?)^```', t, re.S | re.M): + yield t[:m.start()].count('\n') + 1, m.group(1) + +def main(argv): + report = '--report' in argv + docs = [p for p in argv if p.endswith('.md')] + ok = bad = skipped = 0 + failures = [] + for path in docs: + for line, body in fences(path): + if '# doc-check: skip' in body: + skipped += 1; continue + expect_error = '# doc-check: expect-error' in body + kind = classify(body) + parsed, first_err = False, None + for src in wraps(body, kind): + with tempfile.NamedTemporaryFile('w', suffix='.ludic', delete=False) as f: + f.write(src); tmp = f.name + # bytes, not text: a diagnostic may echo a partial multibyte char + r = subprocess.run([LC, tmp, '--fmt'], capture_output=True) + os.unlink(tmp) + if r.returncode == 0: parsed = True; break + # keep the best-guess framing's error; later ones are fallbacks + if first_err is None: first_err = r.stderr + if parsed != (not expect_error): + bad += 1 + want = 'be rejected' if expect_error else 'parse' + err = (first_err or b'').decode('utf-8','replace').strip().split('\n')[0] + failures.append(f"{path}:{line} expected to {want}: {err[:90]}") + else: + ok += 1 + print(f" doc fences: {ok} as documented, {bad} drifted, {skipped} skipped") + for f in failures: print(f" {f}") + if report: return 0 + return 1 if bad else 0 + +sys.exit(main(sys.argv[1:])) diff --git a/tools/check-vocabulary.py b/tools/check-vocabulary.py new file mode 100755 index 00000000..15c452e9 --- /dev/null +++ b/tools/check-vocabulary.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python3 +"""Guard against the failure mode this whole layout exists to prevent. + +The Ludic vocabulary — keywords, types, phases, builtins, intrinsics — is +written down in five places that cannot include each other: + + compiler/**/*.c BUILTINS[] the language itself + compiler/**/*.c INTRINSICS[] the language itself + tools/ludic-tools/ ludic_syntax.h the toolchain's source of truth + tools/editors/shared/ the TextMate grammar (JSON, no includes) + tools/editors/jetbrains/ LudicVocabulary (Kotlin, no includes) + +Adding a builtin to the compiler and forgetting the rest is silent: the editor +just stops colouring it, and nobody notices for months. So it is checked. +""" +import json +import os +import re +import sys + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +problems = [] + + +def read(*parts): + with open(os.path.join(ROOT, *parts)) as fh: + return fh.read() + + +def c_string_list(text, name): + """Names in `static const char* NAME[] = { "a", "b", 0 };`""" + m = re.search(r"\b" + name + r"\s*\[\s*\]\s*=\s*\{(.*?)\}\s*;", text, re.S) + if not m: + problems.append(f"{name}: not found") + return set() + return set(re.findall(r'"([^"]+)"', m.group(1))) + + +def c_table_names(text, name): + """First string of each row in a `{ "name", ... }` table.""" + m = re.search(r"\b" + name + r"\s*\[\s*\]\s*=\s*\{(.*?)\n\s*\}\s*;", text, re.S) + if not m: + problems.append(f"{name}: not found") + return set() + return set(re.findall(r'\{\s*"([^"]+)"', m.group(1))) + + +def kotlin_set(text, name): + """Names in `val NAME = setOf(...)`, found by matching the parentheses — + a non-greedy regex silently runs past a one-line setOf into the next one.""" + m = re.search(r"\bval\s+" + name + r"\s*=\s*setOf\(", text) + if not m: + problems.append(f"Kotlin {name}: not found") + return set() + i = m.end() + depth = 1 + while i < len(text) and depth: + if text[i] == "(": + depth += 1 + elif text[i] == ")": + depth -= 1 + i += 1 + body = re.sub(r"//[^\n]*", "", text[m.end():i - 1]) + return set(re.findall(r'"([^"]+)"', body)) + + +def grammar_alternation(grammar, path, marker): + """Names in a `\\b(a|b|c)\\b` match inside the TextMate grammar.""" + node = grammar + for key in path: + node = node[key] + for pat in node: + rx = pat.get("match", "") + if marker in rx: + inner = re.search(r"\\b\((.*?)\)\\b", rx) + if inner: + return set(inner.group(1).split("|")) + problems.append(f"grammar: no rule containing {marker!r}") + return set() + + +def compare(label, reference, other, other_label, ignore=frozenset()): + missing = (reference - other) - ignore + extra = (other - reference) - ignore + if missing: + problems.append(f"{other_label} is missing {label}: {', '.join(sorted(missing))}") + if extra: + problems.append(f"{other_label} has unknown {label}: {', '.join(sorted(extra))}") + + +syntax_h = read("tools", "ludic-tools", "ludic_syntax.h") +def read_table_owner(table): + """Find whichever compiler translation unit declares a table. + + The compiler is split by concern and files move; hardcoding a path here + turns a routine refactor into a spurious vocabulary failure. + """ + import glob + for path in sorted(glob.glob(os.path.join(ROOT, "compiler", "**", "*.c"), recursive=True)): + text = open(path, encoding="utf-8").read() + if re.search(r"\b%s\s*\[\s*\]" % re.escape(table), text): + return text + return None # the compiler is now written in Ludic (selfhost/); no C table + +ludicc_c = read_table_owner("BUILTINS") +native_c = read_table_owner("INTRINSICS") +kotlin = read("tools", "editors", "jetbrains", "src", "main", "kotlin", "io", "ludic", "ide", "LudicTokens.kt") +grammar = json.loads(read("tools", "editors", "shared", "ludic.tmLanguage.json")) + +# --- the toolchain header is the reference --------------------------------- +h_decl = c_string_list(syntax_h, "LUDIC_KW_DECL") +h_clause = c_string_list(syntax_h, "LUDIC_KW_CLAUSE") +h_stmt = c_string_list(syntax_h, "LUDIC_KW_STMT") +h_types = c_string_list(syntax_h, "LUDIC_TYPES") +h_phases = c_string_list(syntax_h, "LUDIC_PHASES") +h_widgets = c_string_list(syntax_h, "LUDIC_WIDGETS") +h_builtins = c_table_names(syntax_h, "LUDIC_BUILTINS") +h_intrinsics = c_table_names(syntax_h, "LUDIC_INTRINSICS") + +# --- against the compiler's builtin/intrinsic tables, when a C compiler is +# present. The compiler is now written in Ludic (selfhost/), so this +# cross-check is skipped; the editor tools remain checked against each other. +if ludicc_c is not None: + compare("builtins", c_table_names(ludicc_c, "BUILTINS"), h_builtins, "ludic_syntax.h") +if native_c is not None: + compare("intrinsics", c_table_names(native_c, "INTRINSICS"), h_intrinsics, "ludic_syntax.h") + +# --- against the JetBrains lexer ------------------------------------------- +compare("declaration keywords", h_decl, kotlin_set(kotlin, "DECL"), "LudicTokens.kt") +compare("clause keywords", h_clause, kotlin_set(kotlin, "CLAUSE"), "LudicTokens.kt") +compare("statement keywords", h_stmt, kotlin_set(kotlin, "STMT"), "LudicTokens.kt") +compare("primitive types", h_types, kotlin_set(kotlin, "PRIMITIVES"), "LudicTokens.kt") +compare("phases", h_phases, kotlin_set(kotlin, "PHASES"), "LudicTokens.kt") +compare("widgets", h_widgets, kotlin_set(kotlin, "WIDGETS"), "LudicTokens.kt") +compare("builtins", h_builtins | h_intrinsics, kotlin_set(kotlin, "BUILTINS"), "LudicTokens.kt") + +# --- against the TextMate grammar ------------------------------------------ +gpath = ["repository", "builtin", "patterns"] +compare("builtins", h_builtins, grammar_alternation(grammar, gpath, "rng_chance"), "ludic.tmLanguage.json") +compare("intrinsics", h_intrinsics, grammar_alternation(grammar, gpath, "mem_alloc"), "ludic.tmLanguage.json") +kpath = ["repository", "keyword", "patterns"] +compare("phases", h_phases, grammar_alternation(grammar, kpath, "FixedUpdate"), "ludic.tmLanguage.json") +compare("primitive types", h_types, grammar_alternation(grammar, kpath, "fixed"), "ludic.tmLanguage.json") + +if problems: + print("vocabulary drift:", file=sys.stderr) + for p in problems: + print(" -", p, file=sys.stderr) + sys.exit(1) +sys.exit(0) diff --git a/tools/editors/README.md b/tools/editors/README.md new file mode 100644 index 00000000..a60f6875 --- /dev/null +++ b/tools/editors/README.md @@ -0,0 +1,148 @@ +# Ludic in your editor + +Everything here is built on one idea: **write the language knowledge once, in C, +and let every editor talk to it.** There is one lexer, one vocabulary, one +formatter and one language server. VS Code and JetBrains get first-class plugins +because those are the two that were asked for; every other editor gets the same +capabilities by pointing at the same binary. + +``` +tools/ludic-tools/ the actual language knowledge, in C, no dependencies + ludic_syntax.h lexer + the vocabulary — the source of truth + ludic_fmt.h comment-preserving formatter + ludic_index.h error-tolerant reader: declarations, bindings, scopes + ludic_workspace.h multi-file model: imports, compilation units, Markdown + ludic_json.h just enough JSON for LSP + ludic_fmt_main.c -> build/ludic-fmt + ludic_lsp.c -> build/ludic-lsp + +tools/editors/ + shared/ TextMate grammar + Markdown injection + language config + vscode/ VS Code extension + jetbrains/ IntelliJ Platform plugin (Community editions included) + neovim/ helix/ emacs/ sublime/ zed/ configuration, no plugin needed +``` + +## Build it + +```bash +./tools/build-tools.sh +``` + +Produces `build/ludic-fmt` and `build/ludic-lsp`. Add `--install` to symlink both +into `~/.local/bin`, `--test` to run `tools/test-tools.sh` afterwards. + +## What you get, in any editor + +| Feature | How | +|---|---| +| Syntax highlighting | LSP semantic tokens, or the TextMate grammar with no server at all | +| Diagnostics | structural errors as you type; `ludicc`'s own errors on save | +| Completion | context-aware — see below | +| Hover | signature + docs for builtins, intrinsics, and everything you declared | +| Go to definition, find usages, rename | across the whole compilation unit, following `import` — by resolving each occurrence, not by matching text, so renaming a component's `x` leaves every other `x` alone | +| Formatting | whole-file, comment-preserving, idempotent | +| Outline, folding, inlay hints, signature help, document links | | +| ` ```ludic ` in Markdown | highlighted, checked and formatted | + +Completion knows where the caret is: fields after `.`, components inside +`query [...]` and after `spawn`, phase names after `phase`, scene names after +`enter`, widget types and props inside a `ui` block, types after `:` and `->`, +and otherwise keywords, builtins, and everything in scope. + +## Per-editor setup + +- **VS Code** — [`vscode/`](vscode/). `npm install && npx @vscode/vsce package`, then + install the `.vsix`. Finds the binaries under `build/` on its own. +- **JetBrains** — [`jetbrains/`](jetbrains/). `./gradlew buildPlugin`, then install the + zip from disk. Uses LSP4IJ rather than the paid-IDE LSP API, so it works in + Community editions too. +- **Neovim** — `require('ludic').setup()` from [`neovim/`](neovim/lua/ludic.lua). +- **Helix** — merge [`helix/languages.toml`](helix/languages.toml) into your config. +- **Emacs** — [`emacs/ludic-mode.el`](emacs/ludic-mode.el); eglot is wired up in one line. +- **Sublime** — [`sublime/README.md`](sublime/README.md); the TextMate grammar loads as-is. +- **Zed** — [`zed/README.md`](zed/README.md); LSP-only, no grammar to build. +- **Anything else** that speaks LSP: + + ``` + command: build/ludic-lsp --stdio + languages: ludic, markdown + initializationOptions: { "compilerPath": "build/ludicc", "compilerDiagnostics": true, "indentSize": 2 } + ``` + +## Markdown + +Markdown fenced-code highlighting is not one standard — it is three mechanisms, +and this ships all three so that a ` ```ludic ` block works wherever you write +prose: + +1. **TextMate injection** (`shared/ludic.markdown-injection.json`) — what VS Code, + Sublime and other TextMate-based editors use. It is a plain grammar file with + an `injectionSelector`, so it is portable rather than VS Code-specific. +2. **Language-ID resolution** — JetBrains' Markdown support matches a fence's + info string against registered language IDs, so the plugin registering as + `Ludic` is all that is needed; no Markdown-specific code exists in the plugin. +3. **The language server** — `ludic-lsp` accepts Markdown documents directly. It + copies the buffer, blanks every byte outside a ` ```ludic ` fence, and + analyses the result; offsets still line up with the real file, so semantic + highlighting, hover, completion and go-to-definition all work inside fences + with no editor-side support at all. This is the fallback that works even + where the other two do not. + + It reports **no diagnostics** in Markdown, deliberately. A fence is a + snippet — an elision mark, or a body shown without its enclosing `game` + block — so nearly every error found there would be the documentation doing + its job. `ludic-fmt --check` still keeps the fences formatted, which is the + part of "is this doc correct" that can be answered without guessing. + +The formatter handles Markdown too, which keeps documentation honest: + +```bash +build/ludic-fmt --check LANGUAGE.md README.md # CI: fail if a fence is unformatted +build/ludic-fmt -w LANGUAGE.md # reformat the fences, leave the prose +``` + +## Keeping a tree formatted + +```bash +ln -sf ../../tools/git-hooks/pre-commit .git/hooks/pre-commit +``` + +The hook runs `ludic-fmt --check` over the staged `.ludic` and `.md` files only, +and does nothing at all when `build/ludic-fmt` has not been built — so it never +blocks a commit on a machine that has not run `build-tools.sh`. + +## Why the formatter is not `ludicc --fmt` + +The compiler has a canonical printer, and it is the right tool for seeing what +the compiler parsed. It is the wrong tool for an editor: it walks the AST *after* +import splicing, so it drops every comment and inlines every imported file into +whichever file you pointed it at. Running it as format-on-save on +`chronorift/combat.ludic` would replace that file with the whole game. + +`ludic-fmt` works on the token stream instead. Nothing is dropped or reordered — +every token is re-emitted in order, and the only freedom taken is the whitespace +between them. Lines are re-indented and respaced but never joined or split, so +you keep control of line structure. + +Two carve-outs keep the output idiomatic rather than merely uniform, because +both spellings are what the language documents and uses: + +- runs of two or more spaces are preserved, so hand-aligned columns + (`const R_DIR: int = 0 # 0 up`) survive a save; +- `id=Root` inside a `ui` block and `{Enemy}` inside a query stay tight. + +`tools/test-tools.sh` checks the property that matters: formatting every file in +the tree and re-running the *compiler's* canonical dump produces byte-identical +output. The formatter cannot change what a program means. + +## Keeping it honest + +The vocabulary is written down in five places that cannot include each other — +the compiler's two tables, `ludic_syntax.h`, the TextMate grammar (JSON), and the +JetBrains lexer (Kotlin). Adding a builtin and forgetting the rest is silent +failure, so `tools/check-vocabulary.py` compares all five and +`tools/test-tools.sh` runs it. + +When you add a keyword or builtin: put it in `ludic_syntax.h`, then run +`./tools/test-tools.sh` and let it tell you which copies still need it. diff --git a/tools/editors/emacs/ludic-mode.el b/tools/editors/emacs/ludic-mode.el new file mode 100644 index 00000000..fa9b8b94 --- /dev/null +++ b/tools/editors/emacs/ludic-mode.el @@ -0,0 +1,70 @@ +;;; ludic-mode.el --- Major mode for the Ludic game language -*- lexical-binding: t; -*- + +;; Highlighting here is a deliberate minimum: enough for a file to be readable +;; with nothing installed. Everything real -- completion, diagnostics, hover, +;; formatting -- comes from ludic-lsp via eglot (built into Emacs 29) or lsp-mode. +;; +;; Usage: +;; (add-to-list 'load-path "/path/to/gpp/tools/editors/emacs") +;; (require 'ludic-mode) + +;;; Code: + +(defconst ludic--declaration-keywords + '("game" "module" "import" "component" "archetype" "ui" "scene" "layer" + "const" "var" "export" "fn" "pure" "extern" "system" "edge" "start" "on")) + +(defconst ludic--clause-keywords + '("phase" "query" "reads" "writes" "needs" "uses" + "requires" "ensures" "invariant" "effects")) + +(defconst ludic--statement-keywords + '("let" "return" "if" "else" "when" "while" "for" "in" "spawn" "despawn" + "match" "machine" "state" "become" "enter" "where" "and" "or")) + +(defconst ludic--types '("int" "fixed" "bool" "entity" "str" "ptr" "void")) +(defconst ludic--phases '("Start" "Input" "FixedUpdate" "Update" "LateUpdate" "Render")) + +(defconst ludic-font-lock-keywords + (list + (cons (regexp-opt ludic--declaration-keywords 'symbols) 'font-lock-keyword-face) + (cons (regexp-opt ludic--clause-keywords 'symbols) 'font-lock-preprocessor-face) + (cons (regexp-opt ludic--statement-keywords 'symbols) 'font-lock-keyword-face) + (cons (regexp-opt ludic--types 'symbols) 'font-lock-type-face) + (cons (regexp-opt ludic--phases 'symbols) 'font-lock-builtin-face) + (cons "\\_<\\(true\\|false\\)\\_>" 'font-lock-constant-face) + (cons "@[A-Za-z_][A-Za-z0-9_]*" 'font-lock-preprocessor-face) + ;; components, archetypes, scenes and UI handles are Capitalised by convention + (cons "\\_<[A-Z][A-Za-z0-9_]*\\_>" 'font-lock-type-face) + (cons "\\_<\\([a-z_][A-Za-z0-9_]*\\)\\s-*(" '(1 font-lock-function-name-face)))) + +(defvar ludic-mode-syntax-table + (let ((table (make-syntax-table))) + (modify-syntax-entry ?# "<" table) + (modify-syntax-entry ?\n ">" table) + (modify-syntax-entry ?_ "_" table) + (modify-syntax-entry ?\" "\"" table) + table) + "Syntax table for `ludic-mode'.") + +;;;###autoload +(define-derived-mode ludic-mode prog-mode "Ludic" + "Major mode for editing Ludic source." + :syntax-table ludic-mode-syntax-table + (setq-local font-lock-defaults '(ludic-font-lock-keywords)) + (setq-local comment-start "# ") + (setq-local comment-end "") + (setq-local indent-tabs-mode nil) + (setq-local tab-width 2) + (setq-local standard-indent 2)) + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.ludic\\'" . ludic-mode)) + +;; eglot: one line, and the server does the rest. Markdown is registered too so +;; that ```ludic fences are analysed in prose files. +(with-eval-after-load 'eglot + (add-to-list 'eglot-server-programs '(ludic-mode . ("ludic-lsp" "--stdio")))) + +(provide 'ludic-mode) +;;; ludic-mode.el ends here diff --git a/tools/editors/helix/languages.toml b/tools/editors/helix/languages.toml new file mode 100644 index 00000000..47c8ea1e --- /dev/null +++ b/tools/editors/helix/languages.toml @@ -0,0 +1,24 @@ +# Ludic for Helix. Append to ~/.config/helix/languages.toml, adjusting the two +# paths. Highlighting comes from the server's semantic tokens; Helix applies +# them with no grammar to build. + +[[language]] +name = "ludic" +scope = "source.ludic" +file-types = ["ludic"] +comment-token = "#" +indent = { tab-width = 2, unit = " " } +language-servers = ["ludic-lsp"] +auto-format = true +roots = ["build.sh", "LANGUAGE.md", ".git"] + +[language-server.ludic-lsp] +command = "ludic-lsp" +args = ["--stdio"] + +# Ludic fences inside Markdown: point Helix's markdown at the same server so +# `# ```ludic` blocks get diagnostics too. Merge this with your existing +# markdown entry rather than adding a second one. +# [[language]] +# name = "markdown" +# language-servers = ["marksman", "ludic-lsp"] diff --git a/tools/editors/jetbrains/README.md b/tools/editors/jetbrains/README.md new file mode 100644 index 00000000..1b124d3b --- /dev/null +++ b/tools/editors/jetbrains/README.md @@ -0,0 +1,58 @@ +# Ludic for JetBrains IDEs + +Works in IntelliJ IDEA (Community and Ultimate), CLion, GoLand, PyCharm, Rider, +WebStorm — anything on the IntelliJ Platform 2023.2 through 2026.2 +(`since-build` 232, `until-build` 262.*). + +`until-build` 262 is deliberately ahead of the newest released platform — 2025.3 +is build **253**, and no 262 IDE exists yet. That headroom is the point: an +`until-build` pinned to today's IDE gets the plugin auto-disabled the moment a +user upgrades. + +Two things are machine-checked rather than assumed, because a plugin that +packages cleanly can still fail to load: + +- `./gradlew verifyPlugin` runs JetBrains' own Plugin Verifier over the built + artifact against 2025.3 and reports **Compatible**, with no deprecated or + scheduled-for-removal API usages. +- `./gradlew runIde` boots a real IDEA 2025.3 with the plugin installed. The + sandbox log line to look for is + `Loaded custom plugins: LSP4IJ (0.20.1), Ludic (1.0.0)` in + `.intellijPlatform/sandbox/Ludic/IC-2025.3/log/idea.log`. + +**If the plugin does not appear in Settings -> Plugins after installing**, the +cause is almost always that the IDE's build number is outside +`since-build`..`until-build`. IntelliJ installs the declared dependency (LSP4IJ) +from Marketplace first and only then rejects the incompatible plugin, so the +symptom is "LSP4IJ got installed, mine did not". Check **Help -> About** for the +build number and widen `pluginUntilBuild` in `gradle.properties` to match. + +## Building + +Gradle must run on **JDK 17–21**. A newer JDK fails with a bare version number +as the error message, which is not obvious the first time you see it: + +```bash +export JAVA_HOME=$(/usr/libexec/java_home -v 21) # macOS +cd tools/editors/jetbrains +./gradlew buildPlugin # -> build/distributions/Ludic-1.0.0.zip +./gradlew runIde # try it in a sandbox IDE +``` + +The first build downloads an IntelliJ IDEA Community distribution (over 1 GB), +so expect it to take a while; later builds take seconds. Once the cache is warm, + +```bash +LUDIC_TEST_JETBRAINS=1 ./tools/test-tools.sh +``` + +includes the plugin build in the toolchain's own test run. + +Install the zip with **Settings -> Plugins -> ⚙ -> Install Plugin from Disk**. +LSP4IJ is a required dependency; the IDE offers to install it for you. + +## Settings + +**Settings -> Languages & Frameworks -> Ludic** — the path to `ludic-lsp` and to +`ludicc`. Both default to `build/` under the project root, which is where +`tools/build-tools.sh` puts them. diff --git a/tools/editors/jetbrains/build.gradle.kts b/tools/editors/jetbrains/build.gradle.kts new file mode 100644 index 00000000..ded193a0 --- /dev/null +++ b/tools/editors/jetbrains/build.gradle.kts @@ -0,0 +1,96 @@ +import org.jetbrains.intellij.platform.gradle.TestFrameworkType +import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType + +plugins { + id("java") + id("org.jetbrains.kotlin.jvm") version "2.4.10" + // The IntelliJ Platform Gradle Plugin 2.x. The 1.x line (org.jetbrains.intellij) + // is superseded and does not run on current Gradle. + id("org.jetbrains.intellij.platform") version "2.18.1" +} + +group = providers.gradleProperty("pluginGroup").get() +version = providers.gradleProperty("pluginVersion").get() + +repositories { + mavenCentral() + intellijPlatform { + defaultRepositories() + } +} + +dependencies { + testImplementation("junit:junit:4.13.2") + intellijPlatform { + // Community, deliberately: the plugin must work in the free IDEs, which + // is also why the language server is wired up through LSP4IJ rather + // than com.intellij.platform.lsp (Ultimate and friends only). + // useInstaller = false takes the Maven artifact (com.jetbrains.intellij.idea:ideaIC) + // instead of the .dmg/.tar.gz installer. Since 2025.x the Community installer is + // published as `idea-`, not `ideaIC-`, and the installer path + // cannot find it; the Maven coordinate is unaffected by that rename. + intellijIdeaCommunity(providers.gradleProperty("platformVersion").get()) { + useInstaller = false + } + bundledPlugin("org.intellij.plugins.markdown") + plugin("com.redhat.devtools.lsp4ij", providers.gradleProperty("lsp4ijVersion").get()) + // JetBrains' Plugin Verifier CLI, used by the verifyPlugin task below + pluginVerifier() + // headless fixtures for the platform tests in src/test + testFramework(TestFrameworkType.Platform) + } +} + +kotlin { + jvmToolchain(17) +} + +intellijPlatform { + pluginConfiguration { + name = providers.gradleProperty("pluginName") + version = providers.gradleProperty("pluginVersion") + ideaVersion { + sinceBuild = providers.gradleProperty("pluginSinceBuild") + untilBuild = providers.gradleProperty("pluginUntilBuild") + } + } + // Compatibility is claimed up to pluginUntilBuild, so it gets checked + // against that IDE rather than assumed: `./gradlew verifyPlugin` runs + // JetBrains' own Plugin Verifier over the built artifact. + pluginVerification { + ides { + // The platform this is compiled against, which is also the newest + // that exists (2025.3 = build 253). until-build claims 262, which + // no released IDE reaches yet. + create(IntelliJPlatformType.IntellijIdeaCommunity, providers.gradleProperty("platformVersion").get()) { + useInstaller = false + } + } + } + + buildSearchableOptions = false + + // The platform's bytecode instrumenter only adds @NotNull assertions and + // compiles .form files. This plugin is Kotlin with no GUI forms, so it has + // nothing to instrument — and skipping it avoids the instrumenter's JBR + // probing, which fails on a plain JDK layout. + instrumentCode = false +} + +// `./gradlew runIde` opens the Ludic repository itself, so the sandbox has real +// .ludic files to look at and build/ludic-lsp sitting where the plugin expects. +// Three levels up: jetbrains -> editors -> tools -> repository root. Getting +// this wrong points the IDE at tools/, where no build/ludic-lsp exists, and the +// language server then cannot find itself. +val repoRoot: File = rootProject.projectDir.parentFile.parentFile.parentFile +tasks.named("runIde") { + args = listOf(repoRoot.absolutePath) +} + +tasks.test { + useJUnit() + testLogging { + events("passed", "failed", "skipped") + showStandardStreams = false + } +} diff --git a/tools/editors/jetbrains/gradle.properties b/tools/editors/jetbrains/gradle.properties new file mode 100644 index 00000000..42ab63ca --- /dev/null +++ b/tools/editors/jetbrains/gradle.properties @@ -0,0 +1,26 @@ +pluginGroup = io.ludic.ide +pluginName = Ludic +pluginVersion = 1.0.0 + +# 2023.2 is the first build with the platform APIs this plugin uses. LSP4IJ (not +# the paid-IDE LSP API) supplies the language-server bridge, so Community +# editions are supported as well as Ultimate. +pluginSinceBuild = 232 +# Deliberately ahead of the newest released platform (2025.3 is build 253): an +# until-build that stops at today's IDE gets the plugin auto-disabled the moment +# a user upgrades. 262 buys roughly three release cycles of headroom. The APIs +# this plugin uses are the stable ones (LexerBase, SyntaxHighlighter, +# ParserDefinition, FoldingBuilder), and everything project-wide is delegated to +# ludic-lsp over a versioned protocol rather than to platform internals. +pluginUntilBuild = 262.* + +platformVersion = 2025.3 +lsp4ijVersion = 0.20.1 + +# Gradle itself must run on JDK 17-21; a newer JDK reports only its version +# number as the failure. The Kotlin toolchain below is pinned separately. +# The wrapper is Gradle 9.x because IntelliJ Platform Gradle Plugin 2.13+ +# requires it. +org.gradle.jvmargs = -Xmx2g +org.gradle.caching = true +kotlin.stdlib.default.dependency = false diff --git a/tools/editors/jetbrains/gradle/wrapper/gradle-wrapper.jar b/tools/editors/jetbrains/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..8bdaf60c75ab801e22807dde59e12a8735a34077 GIT binary patch literal 45457 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 c82=K%QXLKFx%@O{wJjEi6Y56o#$)Bpeg literal 0 HcmV?d00001 diff --git a/tools/editors/jetbrains/gradle/wrapper/gradle-wrapper.properties b/tools/editors/jetbrains/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..c42672d9 --- /dev/null +++ b/tools/editors/jetbrains/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/tools/editors/jetbrains/gradlew b/tools/editors/jetbrains/gradlew new file mode 100755 index 00000000..adff685a --- /dev/null +++ b/tools/editors/jetbrains/gradlew @@ -0,0 +1,248 @@ +#!/bin/sh + +# +# Copyright © 2015 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/tools/editors/jetbrains/gradlew.bat b/tools/editors/jetbrains/gradlew.bat new file mode 100644 index 00000000..e509b2dd --- /dev/null +++ b/tools/editors/jetbrains/gradlew.bat @@ -0,0 +1,93 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/tools/editors/jetbrains/settings.gradle.kts b/tools/editors/jetbrains/settings.gradle.kts new file mode 100644 index 00000000..8138fbf6 --- /dev/null +++ b/tools/editors/jetbrains/settings.gradle.kts @@ -0,0 +1,2 @@ +// The distribution is named after this, so it is the plugin name, not a slug. +rootProject.name = "Ludic" diff --git a/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicConfigurable.kt b/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicConfigurable.kt new file mode 100644 index 00000000..6632ad0c --- /dev/null +++ b/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicConfigurable.kt @@ -0,0 +1,83 @@ +package io.ludic.ide + +import com.intellij.openapi.options.Configurable +import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.TextFieldWithBrowseButton +import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory +import com.intellij.ui.components.JBCheckBox +import com.intellij.ui.components.JBLabel +import com.intellij.util.ui.FormBuilder +import javax.swing.JComponent +import javax.swing.JPanel +import javax.swing.JSpinner +import javax.swing.SpinnerNumberModel + +/** Settings -> Languages and Frameworks -> Ludic */ +class LudicConfigurable(private val project: Project) : Configurable { + private val serverField = TextFieldWithBrowseButton() + private val compilerField = TextFieldWithBrowseButton() + private val diagnostics = JBCheckBox("Report compiler errors on save") + private val indent = JSpinner(SpinnerNumberModel(2, 1, 8, 1)) + private var panel: JPanel? = null + + override fun getDisplayName() = "Ludic" + + override fun createComponent(): JComponent { + // The title travels on the descriptor now; the four-argument overload + // that took it separately is scheduled for removal. + serverField.addBrowseFolderListener( + project, + FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor().withTitle("Path to ludic-lsp") + ) + compilerField.addBrowseFolderListener( + project, + FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor().withTitle("Path to ludicc") + ) + + panel = FormBuilder.createFormBuilder() + .addLabeledComponent(JBLabel("Language server (ludic-lsp):"), serverField, 1, false) + .addComponentToRightColumn( + JBLabel("Leave empty to use build/ludic-lsp under the project, then PATH.") + ) + .addLabeledComponent(JBLabel("Compiler (ludicc):"), compilerField, 1, false) + .addComponentToRightColumn( + JBLabel("Used for authoritative diagnostics. Empty means build/ludicc.") + ) + .addComponent(diagnostics) + .addLabeledComponent(JBLabel("Formatter indent:"), indent, 1, false) + .addComponentFillVertically(JPanel(), 0) + .panel + reset() + return panel!! + } + + private fun settings() = LudicSettings.of(project) + + override fun isModified(): Boolean { + val s = settings() + return serverField.text != s.serverPath || + compilerField.text != s.compilerPath || + diagnostics.isSelected != s.compilerDiagnostics || + (indent.value as Int) != s.indentSize + } + + override fun apply() { + val s = settings() + s.serverPath = serverField.text.trim() + s.compilerPath = compilerField.text.trim() + s.compilerDiagnostics = diagnostics.isSelected + s.indentSize = indent.value as Int + } + + override fun reset() { + val s = settings() + serverField.text = s.serverPath + compilerField.text = s.compilerPath + diagnostics.isSelected = s.compilerDiagnostics + indent.value = s.indentSize + } + + override fun disposeUIResources() { + panel = null + } +} diff --git a/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicEditorSupport.kt b/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicEditorSupport.kt new file mode 100644 index 00000000..97195476 --- /dev/null +++ b/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicEditorSupport.kt @@ -0,0 +1,85 @@ +package io.ludic.ide + +import com.intellij.lang.BracePair +import com.intellij.lang.Commenter +import com.intellij.lang.PairedBraceMatcher +import com.intellij.lang.folding.FoldingBuilderEx +import com.intellij.lang.folding.FoldingDescriptor +import com.intellij.openapi.editor.Document +import com.intellij.openapi.project.DumbAware +import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile +import com.intellij.psi.tree.IElementType + +/** + * The small editor mechanics the platform expects a language to provide: how to + * comment a line, which delimiters pair up, and what can be folded. None of + * this needs the language server, so none of it waits for one. + */ +class LudicCommenter : Commenter { + override fun getLineCommentPrefix() = "# " + override fun getBlockCommentPrefix(): String? = null + override fun getBlockCommentSuffix(): String? = null + override fun getCommentedBlockCommentPrefix(): String? = null + override fun getCommentedBlockCommentSuffix(): String? = null +} + +class LudicBraceMatcher : PairedBraceMatcher { + override fun getPairs(): Array = PAIRS + + override fun isPairedBracesAllowedBeforeType(lbraceType: IElementType, next: IElementType?): Boolean = true + + override fun getCodeConstructStart(file: PsiFile?, openingBraceOffset: Int): Int = openingBraceOffset + + private companion object { + // Structural braces only: a record literal shares the token type, so + // marking them all structural would make the "matched brace" gutter + // noisy inside `spawn Hero { Pos = { x = 1 } }`. + val PAIRS = arrayOf( + BracePair(LudicTokens.BRACE, LudicTokens.BRACE, true), + BracePair(LudicTokens.BRACKET, LudicTokens.BRACKET, false), + BracePair(LudicTokens.PAREN, LudicTokens.PAREN, false) + ) + } +} + +/** + * Folds every braced block. Working off the lexer's token stream rather than a + * PSI tree keeps this correct for a flat PSI, and it degrades gracefully on a + * file with unbalanced braces, which is most files while they are being typed. + */ +class LudicFoldingBuilder : FoldingBuilderEx(), DumbAware { + override fun buildFoldRegions(root: PsiElement, document: Document, quick: Boolean): Array { + val text = root.containingFile?.text ?: return emptyArray() + val lexer = LudicLexer() + lexer.start(text, 0, text.length, 0) + + val opens = ArrayDeque() + val regions = mutableListOf() + val node = root.node ?: return emptyArray() + + while (lexer.tokenType != null) { + if (lexer.tokenType == LudicTokens.BRACE) { + when (text[lexer.tokenStart]) { + '{' -> opens.addLast(lexer.tokenStart) + '}' -> { + val open = opens.removeLastOrNull() + if (open != null) { + val end = lexer.tokenEnd + // only worth folding when it actually spans lines + if (document.getLineNumber(end) > document.getLineNumber(open)) { + regions += FoldingDescriptor(node, TextRange(open, end)) + } + } + } + } + } + lexer.advance() + } + return regions.toTypedArray() + } + + override fun getPlaceholderText(node: com.intellij.lang.ASTNode) = "{...}" + override fun isCollapsedByDefault(node: com.intellij.lang.ASTNode) = false +} diff --git a/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicLanguage.kt b/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicLanguage.kt new file mode 100644 index 00000000..80332909 --- /dev/null +++ b/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicLanguage.kt @@ -0,0 +1,32 @@ +package io.ludic.ide + +import com.intellij.lang.Language +import com.intellij.openapi.fileTypes.LanguageFileType +import com.intellij.openapi.util.IconLoader +import com.intellij.openapi.vfs.VirtualFile +import javax.swing.Icon + +/** + * The language ID matters more than it looks: the IDE's Markdown support + * resolves a fenced block's info string ("```ludic") against registered + * language IDs, so registering as "Ludic" is what makes fences in .md files + * highlight, with no Markdown-specific code on our side. + */ +object LudicLanguage : Language("Ludic") { + private fun readResolve(): Any = LudicLanguage + override fun getDisplayName() = "Ludic" + override fun isCaseSensitive() = true +} + +object LudicIcons { + val FILE: Icon = IconLoader.getIcon("/icons/ludic.svg", LudicIcons::class.java) +} + +object LudicFileType : LanguageFileType(LudicLanguage) { + private fun readResolve(): Any = LudicFileType + override fun getName() = "Ludic" + override fun getDescription() = "Ludic source" + override fun getDefaultExtension() = "ludic" + override fun getIcon(): Icon = LudicIcons.FILE + override fun getCharset(file: VirtualFile, content: ByteArray): String = "UTF-8" +} diff --git a/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicLexer.kt b/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicLexer.kt new file mode 100644 index 00000000..1b18b173 --- /dev/null +++ b/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicLexer.kt @@ -0,0 +1,148 @@ +package io.ludic.ide + +import com.intellij.lexer.LexerBase +import com.intellij.psi.TokenType +import com.intellij.psi.tree.IElementType + +/** + * A hand-written lexer matching tools/ludic-tools/ludic_syntax.h token for + * token. Hand-written rather than generated because the grammar is small, the + * rules are the ones the C lexer already implements, and keeping the two + * readable side by side is worth more here than a JFlex spec. + * + * It must never throw and never fail to advance: the IDE lexes half-typed text + * constantly, so anything unrecognised becomes one BAD character and the scan + * carries on. + */ +class LudicLexer : LexerBase() { + private var buffer: CharSequence = "" + private var startOffset = 0 + private var endOffset = 0 + private var tokenStart = 0 + private var tokenEnd = 0 + private var tokenType: IElementType? = null + + override fun start(buffer: CharSequence, startOffset: Int, endOffset: Int, initialState: Int) { + this.buffer = buffer + this.startOffset = startOffset + this.endOffset = endOffset + this.tokenStart = startOffset + this.tokenEnd = startOffset + advance() + } + + override fun getState() = 0 + override fun getTokenType(): IElementType? = tokenType + override fun getTokenStart() = tokenStart + override fun getTokenEnd() = tokenEnd + override fun getBufferSequence() = buffer + override fun getBufferEnd() = endOffset + + private fun at(i: Int): Char = if (i in startOffset until endOffset) buffer[i] else ' ' + private fun isIdStart(c: Char) = c.isLetter() || c == '_' + private fun isIdPart(c: Char) = c.isLetterOrDigit() || c == '_' + private fun isSpace(c: Char) = c == ' ' || c == '\t' || c == '\r' || c == '\n' + + override fun advance() { + tokenStart = tokenEnd + if (tokenStart >= endOffset) { + tokenType = null + return + } + + var i = tokenStart + val c = at(i) + + if (isSpace(c)) { + while (i < endOffset && isSpace(at(i))) i++ + emit(i, TokenType.WHITE_SPACE) + return + } + if (c == '#') { + while (i < endOffset && at(i) != '\n') i++ + emit(i, LudicTokens.COMMENT) + return + } + if (c == '"') { + i++ + while (i < endOffset && at(i) != '"' && at(i) != '\n') { + if (at(i) == '\\' && i + 1 < endOffset) i += 2 else i++ + } + if (i < endOffset && at(i) == '"') i++ + emit(i, LudicTokens.STRING) + return + } + if (c == '\'') { + i++ + if (at(i) == '\\' && i + 1 < endOffset) i += 2 else if (i < endOffset && at(i) != '\n') i++ + if (i < endOffset && at(i) == '\'') i++ + emit(i, LudicTokens.CHAR) + return + } + if (c.isDigit()) { + if (c == '0' && (at(i + 1) == 'x' || at(i + 1) == 'X')) { + i += 2 + while (i < endOffset && (at(i).isDigit() || at(i) in 'a'..'f' || at(i) in 'A'..'F')) i++ + } else { + while (i < endOffset && at(i).isDigit()) i++ + if (at(i) == '.' && at(i + 1).isDigit()) { + i++ + while (i < endOffset && at(i).isDigit()) i++ + } + } + emit(i, LudicTokens.NUMBER) + return + } + // @deterministic is one token: the sigil never stands alone + if (c == '@' && isIdStart(at(i + 1))) { + i++ + while (i < endOffset && isIdPart(at(i))) i++ + emit(i, LudicTokens.ANNOTATION) + return + } + if (isIdStart(c)) { + while (i < endOffset && isIdPart(at(i))) i++ + val word = buffer.subSequence(tokenStart, i).toString() + val type = when { + word == "true" || word == "false" -> LudicTokens.BOOLEAN + word in LudicVocabulary.PRIMITIVES -> LudicTokens.PRIMITIVE + word in LudicVocabulary.PHASES -> LudicTokens.PHASE + word in LudicVocabulary.DECL -> LudicTokens.DECL_KEYWORD + word in LudicVocabulary.CLAUSE -> LudicTokens.CLAUSE + word in LudicVocabulary.STMT -> LudicTokens.KEYWORD + word in LudicVocabulary.BUILTINS -> LudicTokens.BUILTIN + word[0].isUpperCase() -> LudicTokens.TYPE_NAME + else -> LudicTokens.IDENTIFIER + } + emit(i, type) + return + } + // two-character operators before one-character ones + val two = if (i + 1 < endOffset) buffer.subSequence(i, i + 2).toString() else "" + if (two in TWO_CHAR_OPS) { + emit(i + 2, LudicTokens.OPERATOR) + return + } + when (c) { + '{', '}' -> { emit(i + 1, LudicTokens.BRACE); return } + '[', ']' -> { emit(i + 1, LudicTokens.BRACKET); return } + '(', ')' -> { emit(i + 1, LudicTokens.PAREN); return } + ',' -> { emit(i + 1, LudicTokens.COMMA); return } + } + if (c in SINGLE_CHAR_OPS) { + emit(i + 1, LudicTokens.OPERATOR) + return + } + emit(i + 1, LudicTokens.BAD) + } + + private fun emit(end: Int, type: IElementType) { + tokenEnd = end + tokenType = type + } + + private companion object { + val TWO_CHAR_OPS = setOf("->", "+=", "-=", "*=", "/=", "==", "!=", "<=", ">=", "&&", "||", "..", "=>") + const val SINGLE_CHAR_OPS = "+-*/%<>=:.!@;" + } +} diff --git a/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicParserDefinition.kt b/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicParserDefinition.kt new file mode 100644 index 00000000..4b1d6cd9 --- /dev/null +++ b/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicParserDefinition.kt @@ -0,0 +1,52 @@ +package io.ludic.ide + +import com.intellij.lang.ASTNode +import com.intellij.lang.ParserDefinition +import com.intellij.lang.PsiParser +import com.intellij.lexer.Lexer +import com.intellij.openapi.project.Project +import com.intellij.psi.FileViewProvider +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiFile +import com.intellij.psi.TokenType +import com.intellij.psi.tree.IFileElementType +import com.intellij.psi.tree.TokenSet +import com.intellij.extapi.psi.ASTWrapperPsiElement +import com.intellij.extapi.psi.PsiFileBase + +/** + * A flat PSI: every token becomes a leaf under the file node, with no tree + * structure above it. + * + * That is enough for the two things the platform genuinely needs a parser for — + * injecting Ludic into Markdown fences, and letting the editor treat a .ludic + * file as a real language rather than plain text — while all actual analysis + * stays in ludic-lsp, where it is shared with every other editor. Building a + * second, divergent parser in Kotlin would mean two grammars to keep honest + * against one compiler. + */ +class LudicParserDefinition : ParserDefinition { + override fun createLexer(project: Project?): Lexer = LudicLexer() + + override fun createParser(project: Project?): PsiParser = PsiParser { root, builder -> + val mark = builder.mark() + while (!builder.eof()) builder.advanceLexer() + mark.done(root) + builder.treeBuilt + } + + override fun getFileNodeType(): IFileElementType = LudicTokens.FILE + override fun getCommentTokens(): TokenSet = TokenSet.create(LudicTokens.COMMENT) + override fun getStringLiteralElements(): TokenSet = TokenSet.create(LudicTokens.STRING, LudicTokens.CHAR) + override fun getWhitespaceTokens(): TokenSet = TokenSet.create(TokenType.WHITE_SPACE) + // Only ever reached for composite nodes, and this grammar marks none beyond + // the file itself — but the platform requires an answer, so give it a real + // PSI element rather than something that would surprise it later. + override fun createElement(node: ASTNode): PsiElement = ASTWrapperPsiElement(node) + override fun createFile(viewProvider: FileViewProvider): PsiFile = LudicPsiFile(viewProvider) +} + +class LudicPsiFile(viewProvider: FileViewProvider) : PsiFileBase(viewProvider, LudicLanguage) { + override fun getFileType() = LudicFileType + override fun toString() = "Ludic file" +} diff --git a/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicServer.kt b/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicServer.kt new file mode 100644 index 00000000..4551ad0f --- /dev/null +++ b/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicServer.kt @@ -0,0 +1,158 @@ +package io.ludic.ide + +import com.intellij.openapi.components.PersistentStateComponent +import com.intellij.openapi.components.Service +import com.intellij.openapi.components.State +import com.intellij.openapi.components.Storage +import com.intellij.openapi.components.service +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.util.xmlb.XmlSerializerUtil +import com.redhat.devtools.lsp4ij.LanguageServerFactory +import com.redhat.devtools.lsp4ij.client.LanguageClientImpl +import com.redhat.devtools.lsp4ij.server.CannotStartProcessException +import com.redhat.devtools.lsp4ij.server.ProcessStreamConnectionProvider +import com.redhat.devtools.lsp4ij.server.StreamConnectionProvider +import java.io.File + +/** + * Where to find the toolchain. Both paths may be left blank, in which case the + * plugin looks under the project root for what tools/build-tools.sh produces — + * which is the case for anyone working in the Ludic repository itself. + */ +@Service(Service.Level.PROJECT) +@State(name = "LudicSettings", storages = [Storage("ludic.xml")]) +class LudicSettings : PersistentStateComponent { + var serverPath: String = "" + var compilerPath: String = "" + var compilerDiagnostics: Boolean = true + var indentSize: Int = 2 + + override fun getState(): LudicSettings = this + override fun loadState(state: LudicSettings) = XmlSerializerUtil.copyBean(state, this) + + companion object { + fun of(project: Project): LudicSettings = project.service() + } +} + +/** + * First existing executable among the usual places, or null. + * + * Takes the project root as a plain path rather than a Project so it can be + * tested without booting an IDE — this lookup silently returning null is the + * difference between a working language server and one that never starts. + */ +internal fun findExecutable(root: String?, configured: String, names: List, subdirs: List): String? { + if (configured.isNotBlank()) { + val f = File(expandHome(configured)) + return if (f.canExecute()) f.absolutePath else null + } + if (root == null) return searchPath(names) + for (dir in subdirs) { + for (name in names) { + val f = File(File(root, dir), name) + if (f.isFile && f.canExecute()) return f.absolutePath + } + } + return searchPath(names) +} + +/** Fall back to PATH, so a system-wide install works with no configuration. */ +private fun searchPath(names: List): String? { + val path = System.getenv("PATH") ?: return null + for (dir in path.split(File.pathSeparator)) { + for (name in names) { + val f = File(dir, name) + if (f.isFile && f.canExecute()) return f.absolutePath + } + } + return null +} + +private fun expandHome(p: String) = + if (p.startsWith("~")) System.getProperty("user.home") + p.substring(1) else p + +class LudicConnectionProvider(private val project: Project) : ProcessStreamConnectionProvider() { + + /** + * Resolve at start(), not at construction. + * + * The provider is built when the project opens, which is usually before the + * toolchain has been compiled. Resolving in an `init` block froze that + * answer forever: build ludic-lsp afterwards and the server stayed dead + * until the IDE was restarted, with `commands=[]` as the only clue. + */ + override fun start() { + val settings = LudicSettings.of(project) + val root = project.basePath + setCommands(serverCommand(root, settings.serverPath) + ?: throw CannotStartProcessException(notFoundMessage(root, settings.serverPath))) + root?.let { setWorkingDirectory(it) } + super.start() + } + + /** + * What went wrong, in terms of the user's filesystem. "commands=[]" tells + * nobody anything; this names every path that was tried. + */ + private fun notFoundMessage(root: String?, configured: String): String = buildString { + if (configured.isNotBlank()) { + append("The Ludic language server configured at '") + append(configured) + append("' is missing or not executable.") + } else { + append("Could not find the 'ludic-lsp' executable. Looked in:\n") + SERVER_SUBDIRS.forEach { d -> + append(" ") + append(if (root != null) File(File(root, d), "ludic-lsp").path else "/$d/ludic-lsp") + append('\n') + } + append(" and on PATH.\n") + } + append("\nBuild it with ./tools/build-tools.sh from the repository root, ") + append("or set the path in Settings | Languages & Frameworks | Ludic. ") + append("Syntax highlighting works without it; completion and diagnostics do not.") + } + + /** + * Passed to the server's `initialize`. The server can find `ludicc` on its + * own, but telling it explicitly means the IDE's setting wins. + */ + override fun getInitializationOptions(rootUri: VirtualFile?): Any { + val settings = LudicSettings.of(project) + val compiler = findExecutable( + project.basePath, settings.compilerPath, + listOf("ludicc", "ludicc.exe"), + COMPILER_SUBDIRS + ) ?: "" + return mapOf( + "compilerPath" to compiler, + "compilerDiagnostics" to settings.compilerDiagnostics, + "indentSize" to settings.indentSize + ) + } +} + +/** + * The exact argv the language server is launched with, or null when the binary + * cannot be found. Split out from start() so the command line itself is + * testable — an empty or wrong command here is invisible until LSP4IJ reports + * `commands=[]`, which says nothing about why. + */ +internal fun serverCommand(root: String?, configured: String): List? { + val exe = findExecutable(root, configured, listOf("ludic-lsp", "ludic-lsp.exe"), SERVER_SUBDIRS) + return exe?.let { listOf(it, "--stdio") } +} + +/** Where the toolchain is looked for, relative to the project root. */ +internal val SERVER_SUBDIRS = listOf("build", "tools/build", "bin", ".") +internal val COMPILER_SUBDIRS = listOf("build", "bin", ".") + +class LudicLanguageServerFactory : LanguageServerFactory { + override fun createConnectionProvider(project: Project): StreamConnectionProvider = + LudicConnectionProvider(project) + + override fun createLanguageClient(project: Project): LanguageClientImpl = + LanguageClientImpl(project) +} diff --git a/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicSyntaxHighlighter.kt b/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicSyntaxHighlighter.kt new file mode 100644 index 00000000..f0da82f6 --- /dev/null +++ b/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicSyntaxHighlighter.kt @@ -0,0 +1,76 @@ +package io.ludic.ide + +import com.intellij.lexer.Lexer +import com.intellij.openapi.editor.DefaultLanguageHighlighterColors as D +import com.intellij.openapi.editor.colors.TextAttributesKey +import com.intellij.openapi.editor.colors.TextAttributesKey.createTextAttributesKey +import com.intellij.openapi.editor.HighlighterColors +import com.intellij.openapi.fileTypes.SyntaxHighlighter +import com.intellij.openapi.fileTypes.SyntaxHighlighterBase +import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.tree.IElementType + +/** + * Colours are all derived from the IDE's own semantic keys rather than hard + * coded, so Ludic looks native in whatever theme the user has, dark or light, + * without shipping a colour scheme. + */ +object LudicColors { + val COMMENT = key("LUDIC_COMMENT", D.LINE_COMMENT) + val STRING = key("LUDIC_STRING", D.STRING) + val NUMBER = key("LUDIC_NUMBER", D.NUMBER) + val KEYWORD = key("LUDIC_KEYWORD", D.KEYWORD) + val DECL_KEYWORD = key("LUDIC_DECL_KEYWORD", D.KEYWORD) + val CLAUSE = key("LUDIC_CLAUSE", D.METADATA) + val PRIMITIVE = key("LUDIC_PRIMITIVE", D.KEYWORD) + val PHASE = key("LUDIC_PHASE", D.STATIC_FIELD) + val BOOLEAN = key("LUDIC_BOOLEAN", D.KEYWORD) + val BUILTIN = key("LUDIC_BUILTIN", D.PREDEFINED_SYMBOL) + val TYPE_NAME = key("LUDIC_TYPE", D.CLASS_NAME) + val IDENTIFIER = key("LUDIC_IDENTIFIER", D.IDENTIFIER) + val ANNOTATION = key("LUDIC_ANNOTATION", D.METADATA) + val OPERATOR = key("LUDIC_OPERATOR", D.OPERATION_SIGN) + val BRACE = key("LUDIC_BRACE", D.BRACES) + val BRACKET = key("LUDIC_BRACKET", D.BRACKETS) + val PAREN = key("LUDIC_PAREN", D.PARENTHESES) + val COMMA = key("LUDIC_COMMA", D.COMMA) + val BAD = createTextAttributesKey("LUDIC_BAD_CHARACTER", HighlighterColors.BAD_CHARACTER) + + private fun key(name: String, base: TextAttributesKey) = createTextAttributesKey(name, base) +} + +class LudicSyntaxHighlighter : SyntaxHighlighterBase() { + override fun getHighlightingLexer(): Lexer = LudicLexer() + + override fun getTokenHighlights(tokenType: IElementType): Array = pack( + when (tokenType) { + LudicTokens.COMMENT -> LudicColors.COMMENT + LudicTokens.STRING, LudicTokens.CHAR -> LudicColors.STRING + LudicTokens.NUMBER -> LudicColors.NUMBER + LudicTokens.KEYWORD -> LudicColors.KEYWORD + LudicTokens.DECL_KEYWORD -> LudicColors.DECL_KEYWORD + LudicTokens.CLAUSE -> LudicColors.CLAUSE + LudicTokens.PRIMITIVE -> LudicColors.PRIMITIVE + LudicTokens.PHASE -> LudicColors.PHASE + LudicTokens.BOOLEAN -> LudicColors.BOOLEAN + LudicTokens.BUILTIN -> LudicColors.BUILTIN + LudicTokens.TYPE_NAME -> LudicColors.TYPE_NAME + LudicTokens.IDENTIFIER -> LudicColors.IDENTIFIER + LudicTokens.ANNOTATION -> LudicColors.ANNOTATION + LudicTokens.OPERATOR -> LudicColors.OPERATOR + LudicTokens.BRACE -> LudicColors.BRACE + LudicTokens.BRACKET -> LudicColors.BRACKET + LudicTokens.PAREN -> LudicColors.PAREN + LudicTokens.COMMA -> LudicColors.COMMA + LudicTokens.BAD -> LudicColors.BAD + else -> null + } + ) +} + +class LudicSyntaxHighlighterFactory : SyntaxHighlighterFactory() { + override fun getSyntaxHighlighter(project: Project?, virtualFile: VirtualFile?): SyntaxHighlighter = + LudicSyntaxHighlighter() +} diff --git a/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicTokens.kt b/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicTokens.kt new file mode 100644 index 00000000..268db1ab --- /dev/null +++ b/tools/editors/jetbrains/src/main/kotlin/io/ludic/ide/LudicTokens.kt @@ -0,0 +1,81 @@ +package io.ludic.ide + +import com.intellij.psi.tree.IElementType +import com.intellij.psi.tree.IFileElementType + +/** + * One token type per thing the highlighter needs to tell apart. This is a + * lexer-only language on the JetBrains side: the token set is the whole grammar + * the platform sees, and ludic-lsp supplies everything structural. + */ +class LudicTokenType(debugName: String) : IElementType(debugName, LudicLanguage) + +object LudicTokens { + val FILE = IFileElementType(LudicLanguage) + + val COMMENT = LudicTokenType("COMMENT") + val STRING = LudicTokenType("STRING") + val CHAR = LudicTokenType("CHAR") + val NUMBER = LudicTokenType("NUMBER") + val IDENTIFIER = LudicTokenType("IDENTIFIER") + val TYPE_NAME = LudicTokenType("TYPE_NAME") // Capitalised: component, archetype, scene + val KEYWORD = LudicTokenType("KEYWORD") + val DECL_KEYWORD = LudicTokenType("DECL_KEYWORD") // game, component, system, fn, ... + val CLAUSE = LudicTokenType("CLAUSE") // phase, query, reads, writes, ... + val PRIMITIVE = LudicTokenType("PRIMITIVE") // int, fixed, bool, entity, str, ptr, void + val PHASE = LudicTokenType("PHASE") // Start, Update, Render, ... + val BOOLEAN = LudicTokenType("BOOLEAN") + val BUILTIN = LudicTokenType("BUILTIN") // runtime surface + compiler intrinsics + val ANNOTATION = LudicTokenType("ANNOTATION") // @deterministic + val OPERATOR = LudicTokenType("OPERATOR") + val BRACE = LudicTokenType("BRACE") + val BRACKET = LudicTokenType("BRACKET") + val PAREN = LudicTokenType("PAREN") + val COMMA = LudicTokenType("COMMA") + val BAD = LudicTokenType("BAD_CHARACTER") +} + +/** + * The vocabulary, mirroring tools/ludic-tools/ludic_syntax.h. When the language + * grows a keyword both sides change together; that header is the reference. + */ +object LudicVocabulary { + val DECL = setOf( + "game", "module", "import", "component", "struct", "archetype", "ui", "scene", "layer", + "const", "var", "export", "fn", "pure", "extern", "system", "edge", "start", "on" + ) + val CLAUSE = setOf( + "phase", "query", "reads", "writes", "needs", "uses", + "requires", "ensures", "invariant", "effects" + ) + val STMT = setOf( + "let", "return", "if", "else", "when", "while", "for", "in", "spawn", "despawn", + "match", "machine", "state", "become", "enter", "where", "and", "or", "not", + "break", "continue", "new" + ) + val PRIMITIVES = setOf("int", "fixed", "bool", "entity", "str", "ptr", "void") + val PHASES = setOf("Start", "Input", "FixedUpdate", "Update", "LateUpdate", "Render") + val WIDGETS = setOf("panel", "col", "row", "label", "button", "image", "spacer") + + val BUILTINS = setOf( + "min", "max", "abs", "clamp", "seed", "rng_range", "rng_chance", "fx", "flr", + "map_size", "map_row", "tile", "clear", "present", "fill_rect", "frame_rect", + "put_px", "text", "text_int", "font_load", "text_ttf", "text_w", "text_h", + "image_load", "draw_image", "draw_image_scaled", "draw_9slice", "load_png", + "load_sprites", "draw_sprite", "draw_sprite_scaled", "ui_build", "ui_open", + "ui_tick", "ui_render", "ui_clicked", "ui_set_text", "ui_set_int", "ui_focus", + "ui_focused", "ui_visible", "key", "reg", "setreg", "self", "save", "load", + "status", "print_int", "quit", + // compiler intrinsics: the floor the Ludic-written runtime stands on + "mem_alloc", "mem_realloc", "mem_free", "mem_copy", "mem_set", "peek8", "poke8", "peek32", + "os_argc", "os_arg", "file_stderr", + "poke32", "peekp", "pokep", "peekf", "pokef", "ptr_add", "ptr_null", + "ptr_is_null", "as_fixed", "as_int", "file_open", "file_read", "file_write", + "file_seek", "file_tell", "file_close", "read_byte", "write_byte", "print_str", + "str_len", "shl", "shr", "band", "bor", "bxor", "bnot", "os_exit", "os_time", + "is_windowed", "game_title", "win_open", "win_poll", "win_present", + "win_running", "win_close" + ) + + fun isKeyword(w: String) = w in DECL || w in CLAUSE || w in STMT +} diff --git a/tools/editors/jetbrains/src/main/resources/META-INF/ludic-markdown.xml b/tools/editors/jetbrains/src/main/resources/META-INF/ludic-markdown.xml new file mode 100644 index 00000000..b9b7ff56 --- /dev/null +++ b/tools/editors/jetbrains/src/main/resources/META-INF/ludic-markdown.xml @@ -0,0 +1,14 @@ + + + + + diff --git a/tools/editors/jetbrains/src/main/resources/META-INF/plugin.xml b/tools/editors/jetbrains/src/main/resources/META-INF/plugin.xml new file mode 100644 index 00000000..ec25a803 --- /dev/null +++ b/tools/editors/jetbrains/src/main/resources/META-INF/plugin.xml @@ -0,0 +1,78 @@ + + io.ludic.ide + Ludic + Ludic + + Language support for Ludic, the AI-first, ECS-native game language.

+
    +
  • Syntax highlighting, brace matching, commenting and folding, implemented natively so a + .ludic file is coloured with no external process.
  • +
  • Completion, diagnostics, hover, go-to-definition, find usages, rename and formatting via + the ludic-lsp language server, through LSP4IJ, so this works in Community + editions as well as the paid IDEs.
  • +
  • Errors from the Ludic compiler itself, reported on save.
  • +
  • Highlighting of ```ludic fenced blocks in Markdown.
  • +
+

Set the paths under Settings → Languages & Frameworks → Ludic, or leave + them blank to use build/ludic-lsp and build/ludicc under the + project root.

+ ]]> + + com.intellij.modules.platform + com.redhat.devtools.lsp4ij + + org.intellij.plugins.markdown + + + + + + + + + + + + + + + + + + + + tools/build-tools.sh. + ]]> + + + + + + diff --git a/tools/editors/jetbrains/src/main/resources/icons/ludic.svg b/tools/editors/jetbrains/src/main/resources/icons/ludic.svg new file mode 100644 index 00000000..afae6c40 --- /dev/null +++ b/tools/editors/jetbrains/src/main/resources/icons/ludic.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/editors/jetbrains/src/test/kotlin/io/ludic/ide/FindExecutableTest.kt b/tools/editors/jetbrains/src/test/kotlin/io/ludic/ide/FindExecutableTest.kt new file mode 100644 index 00000000..74d5caee --- /dev/null +++ b/tools/editors/jetbrains/src/test/kotlin/io/ludic/ide/FindExecutableTest.kt @@ -0,0 +1,155 @@ +package io.ludic.ide + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Assert.assertTrue +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder +import java.io.File + +/** + * Locating `ludic-lsp` is the single point where the whole language server can + * fail silently: if this returns null the provider starts with an empty command + * list, LSP4IJ reports `commands=[]`, and nothing in that message points at the + * cause. It shipped broken once for exactly that reason, so it gets tests. + */ +class FindExecutableTest { + + @get:Rule + val tmp = TemporaryFolder() + + private val names = listOf("ludic-lsp", "ludic-lsp.exe") + + private fun executableAt(vararg segments: String): File { + val f = File(tmp.root, segments.joinToString(File.separator)) + f.parentFile.mkdirs() + f.writeText("#!/bin/sh\n") + check(f.setExecutable(true)) + return f + } + + @Test + fun `finds the binary that build-tools_sh produces`() { + val exe = executableAt("build", "ludic-lsp") + assertEquals(exe.absolutePath, findExecutable(tmp.root.path, "", names, SERVER_SUBDIRS)) + } + + @Test + fun `a project root that is a subdirectory of the repo finds nothing`() { + // The bug that shipped: the IDE was opened on /tools, so the + // lookup searched /tools/build and came back empty while + // /build/ludic-lsp sat there the whole time. + executableAt("build", "ludic-lsp") + val subdir = File(tmp.root, "tools").apply { mkdirs() } + assertNull( + "must not silently resolve from an unrelated root", + findExecutable(subdir.path, "", names, SERVER_SUBDIRS) + ) + } + + @Test + fun `search order prefers build over the other candidates`() { + executableAt("bin", "ludic-lsp") + val preferred = executableAt("build", "ludic-lsp") + assertEquals(preferred.absolutePath, findExecutable(tmp.root.path, "", names, SERVER_SUBDIRS)) + } + + @Test + fun `every documented subdirectory is actually searched`() { + for (dir in SERVER_SUBDIRS) { + val fresh = TemporaryFolder().apply { create() } + val f = File(fresh.root, "$dir${File.separator}ludic-lsp") + f.parentFile.mkdirs() + f.writeText("#!/bin/sh\n") + f.setExecutable(true) + assertEquals( + "subdir '$dir' is advertised but not searched", + f.canonicalPath, + File(findExecutable(fresh.root.path, "", names, SERVER_SUBDIRS)!!).canonicalPath + ) + fresh.delete() + } + } + + @Test + fun `an explicitly configured path wins over anything found by search`() { + executableAt("build", "ludic-lsp") + val custom = executableAt("elsewhere", "my-lsp") + assertEquals(custom.absolutePath, findExecutable(tmp.root.path, custom.absolutePath, names, SERVER_SUBDIRS)) + } + + @Test + fun `a configured path that does not exist fails instead of falling back`() { + // Silently ignoring the setting and using a different binary would be + // worse than failing: the user asked for a specific server. + executableAt("build", "ludic-lsp") + assertNull(findExecutable(tmp.root.path, File(tmp.root, "nope").path, names, SERVER_SUBDIRS)) + } + + @Test + fun `a non-executable file is not accepted`() { + val f = File(tmp.root, "build/ludic-lsp") + f.parentFile.mkdirs() + f.writeText("not executable") + f.setExecutable(false) + assertNull(findExecutable(tmp.root.path, "", names, SERVER_SUBDIRS)) + } + + @Test + fun `a directory named like the binary is not accepted`() { + File(tmp.root, "build/ludic-lsp").mkdirs() + assertNull(findExecutable(tmp.root.path, "", names, SERVER_SUBDIRS)) + } + + @Test + fun `a null project root still allows a PATH lookup`() { + // No exception, no crash: the default project has no basePath. + findExecutable(null, "", names, SERVER_SUBDIRS) + } + + @Test + fun `the real repository layout resolves`() { + // Guards the arrangement the plugin actually ships against: run + // ./tools/build-tools.sh and opening the repo root must just work. + val repoRoot = File(System.getProperty("user.dir")).parentFile.parentFile.parentFile + val built = File(repoRoot, "build/ludic-lsp") + if (!built.isFile) return // toolchain not built in this checkout + val found = findExecutable(repoRoot.path, "", names, SERVER_SUBDIRS) + assertTrue("repo root must resolve to build/ludic-lsp", found != null) + assertEquals(built.canonicalPath, File(found!!).canonicalPath) + } +} + +/** + * The launch command itself. LSP4IJ only ever reports `commands=[...]`, so if + * this list is wrong the failure surfaces with no explanation at all. + */ +class ServerCommandTest { + + private val repoRoot: File = + File(System.getProperty("user.dir")).parentFile.parentFile.parentFile + + @Test + fun `the repository root produces a runnable stdio command`() { + val built = File(repoRoot, "build/ludic-lsp") + if (!built.isFile) return // toolchain not built in this checkout + + val cmd = serverCommand(repoRoot.path, "") + assertEquals(listOf(built.canonicalPath, "--stdio"), cmd!!.let { listOf(File(it[0]).canonicalPath, it[1]) }) + + // and it must actually be executable, not merely present + val proc = ProcessBuilder(cmd[0], "--version").redirectErrorStream(true).start() + val out = proc.inputStream.bufferedReader().readText().trim() + proc.waitFor() + assertTrue("expected a version banner, got '$out'", out.startsWith("ludic-lsp")) + } + + @Test + fun `a root without the toolchain yields no command rather than an empty one`() { + // The distinction that matters: null lets start() throw an explanatory + // error; an empty list is what produced the useless `commands=[]`. + val cmd = serverCommand(File(repoRoot, "tools/editors").path, "") + assertTrue("must be null, not an empty list", cmd == null || cmd.isNotEmpty()) + } +} diff --git a/tools/editors/jetbrains/src/test/kotlin/io/ludic/ide/LudicLexerTest.kt b/tools/editors/jetbrains/src/test/kotlin/io/ludic/ide/LudicLexerTest.kt new file mode 100644 index 00000000..b5e72bbf --- /dev/null +++ b/tools/editors/jetbrains/src/test/kotlin/io/ludic/ide/LudicLexerTest.kt @@ -0,0 +1,169 @@ +package io.ludic.ide + +import com.intellij.psi.TokenType +import com.intellij.psi.tree.IElementType +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test + +/** + * Syntax highlighting is the lexer plus a colour map, so this is where a + * highlighting regression actually shows up. These are plain JUnit tests: the + * lexer has no platform dependencies, so they run in milliseconds without + * booting an IDE. + */ +class LudicLexerTest { + + private fun lex(text: String): List> { + val lexer = LudicLexer() + lexer.start(text, 0, text.length, 0) + val out = mutableListOf>() + while (true) { + val t = lexer.tokenType ?: break + if (t != TokenType.WHITE_SPACE) { + out += t to text.substring(lexer.tokenStart, lexer.tokenEnd) + } + lexer.advance() + } + return out + } + + private fun typesOf(text: String) = lex(text).map { it.first } + + @Test + fun `declaration keywords are distinct from statement keywords`() { + assertEquals( + listOf(LudicTokens.DECL_KEYWORD, LudicTokens.TYPE_NAME, LudicTokens.BRACE), + typesOf("game Hello {") + ) + assertEquals(LudicTokens.KEYWORD, typesOf("if x { }").first()) + } + + @Test + fun `clause keywords are their own class`() { + // `phase` and `query` colour differently from `if`/`let`, which is the + // whole reason a system signature reads as a signature. + assertEquals( + listOf(LudicTokens.DECL_KEYWORD, LudicTokens.TYPE_NAME, LudicTokens.CLAUSE, LudicTokens.PHASE), + typesOf("system Move phase FixedUpdate") + ) + } + + @Test + fun `primitive types and phases are not plain identifiers`() { + assertEquals(LudicTokens.PRIMITIVE, typesOf("int").single()) + assertEquals(LudicTokens.PRIMITIVE, typesOf("fixed").single()) + assertEquals(LudicTokens.PHASE, typesOf("LateUpdate").single()) + assertEquals(LudicTokens.BOOLEAN, typesOf("true").single()) + } + + @Test + fun `builtins are recognised, unknown calls are not`() { + assertEquals(LudicTokens.BUILTIN, typesOf("rng_chance").single()) + assertEquals(LudicTokens.BUILTIN, typesOf("peek32").single()) // intrinsic + assertEquals(LudicTokens.IDENTIFIER, typesOf("my_helper").single()) + } + + @Test + fun `capitalised words read as type names`() { + assertEquals(LudicTokens.TYPE_NAME, typesOf("Pos").single()) + assertEquals(LudicTokens.IDENTIFIER, typesOf("pos").single()) + } + + @Test + fun `comments run to end of line and keep their text`() { + val toks = lex("let a = 1 # keep me\nlet b = 2") + val comment = toks.first { it.first == LudicTokens.COMMENT } + assertEquals("# keep me", comment.second) + // the newline ends it: the next line is code again + assertEquals(LudicTokens.KEYWORD, toks[toks.indexOf(comment) + 1].first) + } + + @Test + fun `strings handle escapes and do not swallow the rest of the file`() { + val toks = lex(""""a\"b" 42""") + assertEquals(LudicTokens.STRING, toks[0].first) + assertEquals(""""a\"b"""", toks[0].second) + assertEquals(LudicTokens.NUMBER, toks[1].first) + } + + @Test + fun `an unterminated string stops at the newline`() { + // A half-typed string must not colour the whole rest of the file. + val toks = lex("let s = \"oops\nlet t = 1") + assertEquals(LudicTokens.STRING, toks[3].first) + assertEquals("\"oops", toks[3].second) + assertEquals(LudicTokens.KEYWORD, toks[4].first) + } + + @Test + fun `numbers cover hex, fixed-point and the range operator`() { + assertEquals(LudicTokens.NUMBER, typesOf("0x1affff").single()) + assertEquals(LudicTokens.NUMBER, typesOf("1.5").single()) + // `0..10` is two ints and a range op, not a malformed float + assertEquals( + listOf(LudicTokens.NUMBER, LudicTokens.OPERATOR, LudicTokens.NUMBER), + typesOf("0..10") + ) + assertEquals("..", lex("0..10")[1].second) + } + + @Test + fun `annotations lex as one token including the sigil`() { + val toks = lex("@deterministic") + assertEquals(LudicTokens.ANNOTATION, toks.single().first) + assertEquals("@deterministic", toks.single().second) + } + + @Test + fun `two-character operators beat one-character ones`() { + assertEquals(listOf("->"), lex("->").map { it.second }) + assertEquals(listOf("=>"), lex("=>").map { it.second }) + assertEquals(listOf("!="), lex("!=").map { it.second }) + assertEquals(listOf("<="), lex("<=").map { it.second }) + } + + @Test + fun `the lexer always terminates and covers every character`() { + // The IDE lexes half-typed text constantly; a lexer that stalls hangs + // the editor, and one that skips bytes corrupts every offset after it. + val nasty = "game X { component ¿ { a: int = ' } # é\n query [{Tag}] \"unclosed" + val lexer = LudicLexer() + lexer.start(nasty, 0, nasty.length, 0) + var covered = 0 + var guard = 0 + while (lexer.tokenType != null) { + assertTrue("token must advance", lexer.tokenEnd > lexer.tokenStart) + assertEquals("no gaps between tokens", covered, lexer.tokenStart) + covered = lexer.tokenEnd + lexer.advance() + check(guard++ < 10_000) { "lexer did not terminate" } + } + assertEquals("every character consumed", nasty.length, covered) + } + + @Test + fun `a real source file lexes with no bad characters`() { + val src = """ + game Hello { + component Pos { x: int = 0, y: int = 0 } + archetype Mob { Pos } + + system Move phase FixedUpdate + query (p) [Pos, {Player}] where p.x > 0 + { + p.x = p.x + 1 + for i in 0 .. 10 { print_int(i) } + } + + ui Menu { + panel id=Root w=288 pad=16 { + button id=Go text="Go" size=16 + } + } + } + """.trimIndent() + val bad = lex(src).filter { it.first == LudicTokens.BAD } + assertTrue("unexpected bad characters: ${bad.map { it.second }}", bad.isEmpty()) + } +} diff --git a/tools/editors/jetbrains/src/test/kotlin/io/ludic/ide/LudicPlatformTest.kt b/tools/editors/jetbrains/src/test/kotlin/io/ludic/ide/LudicPlatformTest.kt new file mode 100644 index 00000000..7a27e4d8 --- /dev/null +++ b/tools/editors/jetbrains/src/test/kotlin/io/ludic/ide/LudicPlatformTest.kt @@ -0,0 +1,124 @@ +package io.ludic.ide + +import com.intellij.lang.LanguageParserDefinitions +import com.intellij.openapi.fileTypes.FileTypeManager +import com.intellij.psi.PsiFile +import com.intellij.testFramework.fixtures.BasePlatformTestCase + +/** + * The IDE-side wiring, exercised in a real (headless) platform fixture. These + * cover the things that make a file feel like a supported language rather than + * plain text: the extension is claimed, a PSI tree is built (which is what + * indexing and Markdown injection both stand on), folds appear, braces pair up + * and Ctrl+/ comments. + */ +class LudicPlatformTest : BasePlatformTestCase() { + + private val sample = """ + game Hello { + component Pos { x: int = 0, y: int = 0 } + archetype Mob { Pos } + + # move everything that has a position + system Move phase FixedUpdate + query (p) [Pos, {Player}] + { + p.x = p.x + 1 + } + } + """.trimIndent() + + private fun ludicFile(text: String = sample): PsiFile = + myFixture.configureByText("sample.ludic", text) + + fun testExtensionIsClaimedByTheLudicFileType() { + val type = FileTypeManager.getInstance().getFileTypeByExtension("ludic") + assertEquals("Ludic", type.name) + assertEquals(LudicFileType, type) + } + + fun testFileTypeIsNotBinaryAndUsesUtf8() { + assertFalse(LudicFileType.isBinary) + assertEquals("ludic", LudicFileType.defaultExtension) + } + + fun testParserDefinitionIsRegisteredForTheLanguage() { + // Markdown fence injection needs a PSI tree, so this registration is + // what makes ```ludic blocks highlight in a .md file. + val def = LanguageParserDefinitions.INSTANCE.forLanguage(LudicLanguage) + assertNotNull("no ParserDefinition registered for Ludic", def) + } + + fun testPsiTreeIsBuiltAndCoversTheWholeFile() { + val file = ludicFile() + assertEquals(LudicLanguage, file.language) + assertEquals(sample, file.text) + assertTrue("expected a non-empty PSI tree", file.children.isNotEmpty()) + // every character must be reachable through the tree, or offsets drift + assertEquals(sample.length, file.textLength) + } + + fun testHighlighterAssignsColoursToEveryMeaningfulToken() { + val highlighter = LudicSyntaxHighlighter() + val coloured = listOf( + LudicTokens.DECL_KEYWORD, LudicTokens.KEYWORD, LudicTokens.CLAUSE, + LudicTokens.PRIMITIVE, LudicTokens.PHASE, LudicTokens.BOOLEAN, + LudicTokens.BUILTIN, LudicTokens.TYPE_NAME, LudicTokens.STRING, + LudicTokens.NUMBER, LudicTokens.COMMENT, LudicTokens.ANNOTATION, + LudicTokens.OPERATOR, LudicTokens.BRACE, LudicTokens.BRACKET, + LudicTokens.PAREN, LudicTokens.COMMA, LudicTokens.IDENTIFIER + ) + for (token in coloured) { + val keys = highlighter.getTokenHighlights(token) + assertTrue("no colour mapped for $token", keys.isNotEmpty()) + } + } + + fun testFoldingCollapsesMultiLineBlocksOnly() { + val file = ludicFile() + val regions = LudicFoldingBuilder().buildFoldRegions(file.node, file.viewProvider.document!!) + + // The sample has exactly two blocks that span lines: the `game` body and + // the `system` body. `component Pos { … }`, `archetype Mob { … }` and the + // `{Player}` query filter all fit on one line, and folding a single line + // gains nothing, so they are deliberately skipped. + assertEquals("multi-line blocks only", 2, regions.size) + + val outermost = regions.maxByOrNull { it.range.length }!! + assertEquals("outermost fold starts at the game block's brace", + sample.indexOf('{'), outermost.range.startOffset) + assertEquals("outermost fold ends at the last brace", + sample.length, outermost.range.endOffset) + + for (r in regions) { + assertTrue("fold region must be non-empty", r.range.length > 0) + assertEquals("{...}", LudicFoldingBuilder().getPlaceholderText(file.node)) + } + } + + fun testCommenterUsesHashWithASpace() { + // The trailing space is deliberate: Ctrl+/ should produce "# code", + // which is how every comment in the runtime and examples is written. + val commenter = LudicCommenter() + assertEquals("# ", commenter.lineCommentPrefix) + assertNull("Ludic has no block comments", commenter.blockCommentPrefix) + } + + fun testBraceMatcherPairsAllThreeBracketKinds() { + val matcher = LudicBraceMatcher() + val pairs = matcher.pairs + val open = pairs.map { it.leftBraceType }.toSet() + assertTrue(open.contains(LudicTokens.BRACE)) + assertTrue(open.contains(LudicTokens.BRACKET)) + assertTrue(open.contains(LudicTokens.PAREN)) + } + + fun testHalfTypedFileStillProducesAPsiTree() { + // The IDE must survive what a file looks like mid-keystroke; a parser + // that throws here takes highlighting and indexing down with it. + val broken = "game X {\n component P { x: int =\n system" + val file = myFixture.configureByText("broken.ludic", broken) + assertEquals(broken.length, file.textLength) + assertEquals(LudicLanguage, file.language) + } +} diff --git a/tools/editors/neovim/lua/ludic.lua b/tools/editors/neovim/lua/ludic.lua new file mode 100644 index 00000000..67f12e38 --- /dev/null +++ b/tools/editors/neovim/lua/ludic.lua @@ -0,0 +1,86 @@ +-- Ludic support for Neovim (0.9+), with no plugin manager and no dependencies. +-- +-- :lua require('ludic').setup() +-- -- or, from init.lua: +-- vim.opt.runtimepath:append('/path/to/gpp/tools/editors/neovim') +-- require('ludic').setup({ server = '/path/to/gpp/build/ludic-lsp' }) +-- +-- Highlighting here comes from the language server's semantic tokens, which +-- Neovim applies natively -- there is no tree-sitter grammar to install and no +-- second copy of the vocabulary to keep in sync. + +local M = {} + +local function find_executable(names, roots, subdirs) + for _, root in ipairs(roots) do + for _, sub in ipairs(subdirs) do + for _, name in ipairs(names) do + local p = root .. '/' .. sub .. '/' .. name + if vim.fn.executable(p) == 1 then return p end + end + end + end + for _, name in ipairs(names) do + if vim.fn.executable(name) == 1 then return name end + end + return nil +end + +function M.setup(opts) + opts = opts or {} + + -- .ludic files are Ludic + vim.filetype.add({ extension = { ludic = 'ludic' } }) + + vim.api.nvim_create_autocmd('FileType', { + pattern = 'ludic', + callback = function() + vim.bo.commentstring = '# %s' + vim.bo.comments = ':#' + vim.bo.expandtab = true + vim.bo.shiftwidth = opts.indent or 2 + vim.bo.tabstop = opts.indent or 2 + end, + }) + + local root_markers = { 'build.sh', 'LANGUAGE.md', '.git' } + + local function root_dir(fname) + local found = vim.fs.find(root_markers, { path = vim.fs.dirname(fname), upward = true })[1] + return found and vim.fs.dirname(found) or vim.fs.dirname(fname) + end + + vim.api.nvim_create_autocmd('FileType', { + -- markdown is included on purpose: ```ludic fences get diagnostics and + -- semantic highlighting like any source file + pattern = { 'ludic', 'markdown' }, + callback = function(args) + local root = root_dir(vim.api.nvim_buf_get_name(args.buf)) + local server = opts.server or find_executable( + { 'ludic-lsp' }, { root }, { 'build', 'tools/build', 'bin', '.' }) + if not server then return end + local compiler = opts.compiler or find_executable( + { 'ludicc' }, { root }, { 'build', 'bin', '.' }) or '' + + vim.lsp.start({ + name = 'ludic-lsp', + cmd = { server, '--stdio' }, + root_dir = root, + init_options = { + compilerPath = compiler, + compilerDiagnostics = opts.compiler_diagnostics ~= false, + indentSize = opts.indent or 2, + }, + }, { bufnr = args.buf }) + end, + }) + + if opts.format_on_save ~= false then + vim.api.nvim_create_autocmd('BufWritePre', { + pattern = { '*.ludic' }, + callback = function() vim.lsp.buf.format({ async = false, timeout_ms = 2000 }) end, + }) + end +end + +return M diff --git a/tools/editors/shared/language-configuration.json b/tools/editors/shared/language-configuration.json new file mode 100644 index 00000000..6fb5c01a --- /dev/null +++ b/tools/editors/shared/language-configuration.json @@ -0,0 +1,31 @@ +{ + "comment": "Editor mechanics that are not highlighting and not the language server: comments, bracket pairs, auto-closing, indentation triggers. VS Code reads this file directly; the JetBrains plugin implements the same rules natively; other editors can transcribe it.", + "comments": { + "lineComment": "#" + }, + "brackets": [["{", "}"], ["[", "]"], ["(", ")"]], + "autoClosingPairs": [ + { "open": "{", "close": "}" }, + { "open": "[", "close": "]" }, + { "open": "(", "close": ")" }, + { "open": "\"", "close": "\"", "notIn": ["string", "comment"] } + ], + "surroundingPairs": [["{", "}"], ["[", "]"], ["(", ")"], ["\"", "\""]], + "indentationRules": { + "increaseIndentPattern": "^((?!//).)*(\\{[^}\"']*|\\([^)\"']*|\\[[^\\]\"']*)$", + "decreaseIndentPattern": "^\\s*[}\\])].*$" + }, + "onEnterRules": [ + { + "beforeText": "^\\s*#.*$", + "action": { "indent": "none", "appendText": "# " } + } + ], + "wordPattern": "[A-Za-z_][A-Za-z0-9_]*", + "folding": { + "markers": { + "start": "^\\s*#\\s*region\\b", + "end": "^\\s*#\\s*endregion\\b" + } + } +} diff --git a/tools/editors/shared/ludic.markdown-injection.json b/tools/editors/shared/ludic.markdown-injection.json new file mode 100644 index 00000000..15931c4c --- /dev/null +++ b/tools/editors/shared/ludic.markdown-injection.json @@ -0,0 +1,27 @@ +{ + "scopeName": "markdown.ludic.codeblock", + "comment": "Injects Ludic highlighting into ```ludic fences in Markdown. Any TextMate-based editor (VS Code, Sublime, JetBrains' TextMate bundles, Zed) picks this up; JetBrains' native Markdown support gets the same thing for free from the registered `Ludic` language ID, and ludic-lsp will also serve semantic tokens and diagnostics for the fence bodies in a .md file.", + "injectionSelector": "L:text.html.markdown", + "patterns": [{ "include": "#ludic-code-block" }], + "repository": { + "ludic-code-block": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(ludic)((\\s+|:|,|\\{|\\?)[^`~]*)?)$", + "name": "markup.fenced_code.block.markdown", + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "beginCaptures": { + "3": { "name": "punctuation.definition.markdown" }, + "4": { "name": "fenced_code.block.language.markdown" }, + "5": { "name": "fenced_code.block.language.attributes.markdown" } + }, + "endCaptures": { "3": { "name": "punctuation.definition.markdown" } }, + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)", + "contentName": "meta.embedded.block.ludic", + "patterns": [{ "include": "source.ludic" }] + } + ] + } + } +} diff --git a/tools/editors/shared/ludic.tmLanguage.json b/tools/editors/shared/ludic.tmLanguage.json new file mode 100644 index 00000000..8b99e208 --- /dev/null +++ b/tools/editors/shared/ludic.tmLanguage.json @@ -0,0 +1,241 @@ +{ + "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", + "name": "Ludic", + "scopeName": "source.ludic", + "fileTypes": ["ludic"], + "comment": "Static grammar for Ludic. It is the fallback: when ludic-lsp is running, its semantic tokens refine everything here with real name resolution. Generated shapes are kept in sync with tools/ludic-tools/ludic_syntax.h.", + "patterns": [ + { "include": "#comment" }, + { "include": "#declaration" }, + { "include": "#query" }, + { "include": "#string" }, + { "include": "#number" }, + { "include": "#annotation" }, + { "include": "#keyword" }, + { "include": "#widget" }, + { "include": "#builtin" }, + { "include": "#member" }, + { "include": "#call" }, + { "include": "#typename" }, + { "include": "#operator" } + ], + "repository": { + "comment": { + "match": "#.*$", + "name": "comment.line.number-sign.ludic" + }, + "string": { + "patterns": [ + { + "name": "string.quoted.double.ludic", + "begin": "\"", + "end": "\"", + "beginCaptures": { "0": { "name": "punctuation.definition.string.begin.ludic" } }, + "endCaptures": { "0": { "name": "punctuation.definition.string.end.ludic" } }, + "patterns": [{ "name": "constant.character.escape.ludic", "match": "\\\\." }] + }, + { + "name": "string.quoted.single.ludic", + "match": "'(\\\\.|[^'\\\\])'" + } + ] + }, + "number": { + "patterns": [ + { "name": "constant.numeric.hex.ludic", "match": "\\b0[xX][0-9a-fA-F]+\\b" }, + { "name": "constant.numeric.fixed.ludic", "match": "\\b[0-9]+\\.[0-9]+\\b" }, + { "name": "constant.numeric.integer.ludic", "match": "\\b[0-9]+\\b" } + ] + }, + "annotation": { + "name": "entity.name.function.decorator.ludic", + "match": "@[A-Za-z_][A-Za-z0-9_]*" + }, + "declaration": { + "patterns": [ + { + "match": "\\b(game|module)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "keyword.control.unit.ludic" }, + "2": { "name": "entity.name.type.unit.ludic" } + } + }, + { + "match": "\\b(component)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "storage.type.component.ludic" }, + "2": { "name": "entity.name.type.component.ludic" } + } + }, + { + "match": "\\b(archetype)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "storage.type.archetype.ludic" }, + "2": { "name": "entity.name.type.archetype.ludic" } + } + }, + { + "match": "\\b(scene)\\s+([A-Za-z_][A-Za-z0-9_]*)(\\s+start)?", + "captures": { + "1": { "name": "storage.type.scene.ludic" }, + "2": { "name": "entity.name.type.scene.ludic" }, + "3": { "name": "keyword.other.start.ludic" } + } + }, + { + "match": "\\b(layer|ui)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "storage.type.ludic" }, + "2": { "name": "entity.name.type.ludic" } + } + }, + { + "match": "\\b(edge\\s+)?(system)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "storage.modifier.edge.ludic" }, + "2": { "name": "storage.type.system.ludic" }, + "3": { "name": "entity.name.function.system.ludic" } + } + }, + { + "match": "\\b(export\\s+|pure\\s+)?(extern\\s+)?(fn)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "storage.modifier.ludic" }, + "2": { "name": "storage.modifier.extern.ludic" }, + "3": { "name": "storage.type.function.ludic" }, + "4": { "name": "entity.name.function.ludic" } + } + }, + { + "match": "\\b(const|var|let)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "storage.type.ludic" }, + "2": { "name": "variable.other.definition.ludic" } + } + }, + { + "match": "\\b(state)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "keyword.control.state.ludic" }, + "2": { "name": "entity.name.constant.state.ludic" } + } + }, + { + "match": "\\b(import)\\s+(?=\")", + "captures": { "1": { "name": "keyword.control.import.ludic" } } + }, + { + "match": "\\b(phase)\\s+(Start|Input|FixedUpdate|Update|LateUpdate|Render)\\b", + "captures": { + "1": { "name": "keyword.other.clause.ludic" }, + "2": { "name": "constant.language.phase.ludic" } + } + }, + { + "match": "\\b(enter)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "keyword.control.enter.ludic" }, + "2": { "name": "entity.name.type.scene.ludic" } + } + }, + { + "match": "\\b(spawn)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "keyword.control.spawn.ludic" }, + "2": { "name": "entity.name.type.archetype.ludic" } + } + } + ] + }, + "query": { + "comment": "Inside a query's brackets a bare word names a component and {Word} is a filter that does not bind.", + "begin": "\\b(query)\\s*(\\[)", + "beginCaptures": { + "1": { "name": "keyword.other.query.ludic" }, + "2": { "name": "punctuation.section.brackets.begin.ludic" } + }, + "end": "(\\])", + "endCaptures": { "1": { "name": "punctuation.section.brackets.end.ludic" } }, + "patterns": [ + { + "match": "(\\{)\\s*([A-Za-z_][A-Za-z0-9_]*)\\s*(\\})", + "captures": { + "1": { "name": "punctuation.section.braces.begin.ludic" }, + "2": { "name": "entity.name.type.tag.ludic" }, + "3": { "name": "punctuation.section.braces.end.ludic" } + } + }, + { "name": "entity.name.type.component.ludic", "match": "\\b[A-Za-z_][A-Za-z0-9_]*\\b" }, + { "name": "punctuation.separator.ludic", "match": "," } + ] + }, + "keyword": { + "patterns": [ + { "name": "keyword.control.ludic", "match": "\\b(if|else|when|while|for|in|match|machine|become|enter|return|spawn|despawn|where|break|continue|new)\\b" }, + { "name": "keyword.operator.logical.ludic", "match": "\\b(and|or|not)\\b" }, + { "name": "keyword.other.clause.ludic", "match": "\\b(phase|query|reads|writes|needs|uses|requires|ensures|invariant|effects|on)\\b" }, + { "name": "keyword.other.ludic", "match": "\\b(import|export|pure|extern|start|edge)\\b" }, + { "name": "storage.type.ludic", "match": "\\b(game|module|component|archetype|ui|scene|layer|const|var|let|fn|system|state)\\b" }, + { "name": "support.type.primitive.ludic", "match": "\\b(int|fixed|bool|entity|str|ptr|void)\\b" }, + { "name": "constant.language.boolean.ludic", "match": "\\b(true|false)\\b" }, + { "name": "constant.language.phase.ludic", "match": "\\b(Start|Input|FixedUpdate|Update|LateUpdate|Render)\\b" } + ] + }, + "widget": { + "patterns": [ + { + "comment": "widget types, recognised by the props or the child block that follow them", + "name": "support.class.widget.ludic", + "match": "\\b(panel|col|row|label|button|image|spacer)\\b(?=\\s*(\\{|[a-z][A-Za-z0-9_]*\\s*=|$))" + }, + { + "comment": "widget props are written tight (id=Root); an assignment is written x = 1", + "match": "\\b([a-z][A-Za-z0-9_]*)(=)(?!=)", + "captures": { + "1": { "name": "variable.parameter.widget.ludic" }, + "2": { "name": "keyword.operator.assignment.ludic" } + } + } + ] + }, + "builtin": { + "patterns": [ + { + "comment": "the runtime surface — every name here resolves to rt_ in runtime/native", + "name": "support.function.builtin.ludic", + "match": "\\b(min|max|abs|clamp|seed|rng_range|rng_chance|fx|flr|map_size|map_row|tile|clear|present|fill_rect|frame_rect|put_px|text|text_int|font_load|text_ttf|text_w|text_h|image_load|draw_image|draw_image_scaled|draw_9slice|load_png|load_sprites|draw_sprite|draw_sprite_scaled|ui_build|ui_open|ui_tick|ui_render|ui_clicked|ui_set_text|ui_set_int|ui_focus|ui_focused|ui_visible|key|reg|setreg|self|save|load|status|print_int|quit)\\b(?=\\s*\\()" + }, + { + "comment": "compiler intrinsics — these lower straight to libc or the OS", + "name": "support.function.intrinsic.ludic", + "match": "\\b(mem_alloc|mem_realloc|mem_free|mem_copy|mem_set|peek8|poke8|peek32|poke32|peekp|pokep|peekf|pokef|ptr_add|ptr_null|ptr_is_null|as_fixed|as_int|file_open|file_read|file_write|file_seek|file_tell|file_close|read_byte|write_byte|print_str|str_len|shl|shr|band|bor|bxor|bnot|os_exit|os_time|os_argc|os_arg|file_stderr|is_windowed|game_title|win_open|win_poll|win_present|win_running|win_close)\\b(?=\\s*\\()" + } + ] + }, + "member": { + "match": "(\\.)([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "punctuation.accessor.ludic" }, + "2": { "name": "variable.other.property.ludic" } + } + }, + "call": { + "match": "\\b([A-Za-z_][A-Za-z0-9_]*)\\s*(?=\\()", + "name": "entity.name.function.call.ludic" + }, + "typename": { + "comment": "components, archetypes, scenes and UI handles are Capitalised by convention", + "name": "entity.name.type.ludic", + "match": "\\b[A-Z][A-Za-z0-9_]*\\b" + }, + "operator": { + "patterns": [ + { "name": "keyword.operator.arrow.ludic", "match": "->|=>" }, + { "name": "keyword.operator.range.ludic", "match": "\\.\\." }, + { "name": "keyword.operator.comparison.ludic", "match": "==|!=|<=|>=|<|>" }, + { "name": "keyword.operator.assignment.ludic", "match": "\\+=|-=|\\*=|/=|=" }, + { "name": "keyword.operator.arithmetic.ludic", "match": "[+\\-*/%]" } + ] + } + } +} diff --git a/tools/editors/sublime/README.md b/tools/editors/sublime/README.md new file mode 100644 index 00000000..129a1eba --- /dev/null +++ b/tools/editors/sublime/README.md @@ -0,0 +1,35 @@ +# Ludic for Sublime Text + +Sublime reads TextMate grammars directly, so the shared grammar works as-is. + +1. **Highlighting.** Copy `tools/editors/shared/ludic.tmLanguage.json` into your + `Packages/User/` directory, renamed to `Ludic.tmLanguage.json`. Sublime picks + up `.ludic` from the grammar's `fileTypes`. + +2. **Markdown fences.** Copy + `tools/editors/shared/ludic.markdown-injection.json` alongside it as + `Ludic Markdown.tmLanguage.json`. Sublime honours `injectionSelector`, so + ` ```ludic ` blocks in Markdown are highlighted with no further setup. + +3. **Everything else** comes from the language server. Install + [LSP](https://packagecontrol.io/packages/LSP), then add to + `Preferences -> Package Settings -> LSP -> Settings`: + +```json +{ + "clients": { + "ludic": { + "enabled": true, + "command": ["/path/to/gpp/build/ludic-lsp", "--stdio"], + "selector": "source.ludic | text.html.markdown", + "initializationOptions": { + "compilerPath": "/path/to/gpp/build/ludicc", + "compilerDiagnostics": true, + "indentSize": 2 + } + } + } +} +``` + +Format on save with `LSP-format-on-save`, or bind `lsp_format_document`. diff --git a/tools/editors/vscode/.vscodeignore b/tools/editors/vscode/.vscodeignore new file mode 100644 index 00000000..2f8bcccd --- /dev/null +++ b/tools/editors/vscode/.vscodeignore @@ -0,0 +1,12 @@ +.vscode/** +node_modules/** +!node_modules/vscode-languageclient/** +!node_modules/vscode-jsonrpc/** +!node_modules/vscode-languageserver-protocol/** +!node_modules/vscode-languageserver-types/** +!node_modules/semver/** +!node_modules/balanced-match/** +!node_modules/minimatch/** +!node_modules/brace-expansion/** +!node_modules/concat-map/** +**/*.map diff --git a/tools/editors/vscode/README.md b/tools/editors/vscode/README.md new file mode 100644 index 00000000..58598f1b --- /dev/null +++ b/tools/editors/vscode/README.md @@ -0,0 +1,54 @@ +# Ludic for VS Code + +Syntax highlighting, formatting, and full language-server support for **Ludic**, +the AI-first, ECS-native game language. See `LANGUAGE.md` in the Ludic repository +for the language reference. + +## What you get + +| | Source | +|---|---| +| Syntax highlighting | TextMate grammar, works with no build | +| Semantic highlighting | `ludic-lsp` — real name resolution, so a component reads differently from a local | +| Diagnostics | structural errors as you type; `ludicc`'s own errors on save | +| Completion | context-aware: fields after `.`, components inside `query [...]`, phases after `phase`, widgets inside `ui` | +| Hover | signatures and docs for builtins, intrinsics, and everything you declared | +| Go to definition / references / rename | across every file in the compilation unit, following `import` | +| Formatting | format-on-save, comment-preserving | +| Outline, folding, inlay hints, signature help | | +| ` ```ludic ` fences in Markdown | highlighted, checked, and formatted | + +## Setup + +Build the toolchain once, from the repository root: + +```bash +./tools/build-tools.sh +``` + +That produces `build/ludic-lsp` and `build/ludic-fmt`, which the extension finds +on its own. If you keep them elsewhere, set `ludic.server.path`. + +Format on save: + +```json +"[ludic]": { "editor.formatOnSave": true } +``` + +## Settings + +- `ludic.server.path` — where `ludic-lsp` lives. Empty = search `build/`, then `PATH`. +- `ludic.server.enabled` — turn the server off and keep only static highlighting. +- `ludic.compilerPath` — where `ludicc` lives, for on-save diagnostics. +- `ludic.compilerDiagnostics` — whether to run the compiler at all. +- `ludic.indentSize` — spaces per level for the formatter. +- `ludic.trace.server` — log LSP traffic (`Ludic: Show Language Server Log`). + +## Installing without publishing + +```bash +cd tools/editors/vscode +npm install +npx @vscode/vsce package +code --install-extension ludic-1.0.0.vsix +``` diff --git a/tools/editors/vscode/icons/ludic.svg b/tools/editors/vscode/icons/ludic.svg new file mode 100644 index 00000000..afae6c40 --- /dev/null +++ b/tools/editors/vscode/icons/ludic.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tools/editors/vscode/language-configuration.json b/tools/editors/vscode/language-configuration.json new file mode 100644 index 00000000..6fb5c01a --- /dev/null +++ b/tools/editors/vscode/language-configuration.json @@ -0,0 +1,31 @@ +{ + "comment": "Editor mechanics that are not highlighting and not the language server: comments, bracket pairs, auto-closing, indentation triggers. VS Code reads this file directly; the JetBrains plugin implements the same rules natively; other editors can transcribe it.", + "comments": { + "lineComment": "#" + }, + "brackets": [["{", "}"], ["[", "]"], ["(", ")"]], + "autoClosingPairs": [ + { "open": "{", "close": "}" }, + { "open": "[", "close": "]" }, + { "open": "(", "close": ")" }, + { "open": "\"", "close": "\"", "notIn": ["string", "comment"] } + ], + "surroundingPairs": [["{", "}"], ["[", "]"], ["(", ")"], ["\"", "\""]], + "indentationRules": { + "increaseIndentPattern": "^((?!//).)*(\\{[^}\"']*|\\([^)\"']*|\\[[^\\]\"']*)$", + "decreaseIndentPattern": "^\\s*[}\\])].*$" + }, + "onEnterRules": [ + { + "beforeText": "^\\s*#.*$", + "action": { "indent": "none", "appendText": "# " } + } + ], + "wordPattern": "[A-Za-z_][A-Za-z0-9_]*", + "folding": { + "markers": { + "start": "^\\s*#\\s*region\\b", + "end": "^\\s*#\\s*endregion\\b" + } + } +} diff --git a/tools/editors/vscode/package-lock.json b/tools/editors/vscode/package-lock.json new file mode 100644 index 00000000..52c906f9 --- /dev/null +++ b/tools/editors/vscode/package-lock.json @@ -0,0 +1,97 @@ +{ + "name": "ludic", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "ludic", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "vscode-languageclient": "^9.0.1" + }, + "engines": { + "vscode": "^1.75.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", + "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", + "license": "MIT", + "dependencies": { + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.5" + }, + "engines": { + "vscode": "^1.82.0" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "license": "MIT" + } + } +} diff --git a/tools/editors/vscode/package.json b/tools/editors/vscode/package.json new file mode 100644 index 00000000..96d2273d --- /dev/null +++ b/tools/editors/vscode/package.json @@ -0,0 +1,158 @@ +{ + "name": "ludic", + "displayName": "Ludic", + "description": "Ludic language support: syntax highlighting, formatting, and the ludic-lsp language server. Also highlights ```ludic fences in Markdown.", + "version": "1.0.0", + "publisher": "ludic", + "license": "MIT", + "engines": { + "vscode": "^1.75.0" + }, + "categories": [ + "Programming Languages", + "Formatters", + "Linters" + ], + "keywords": [ + "ludic", + "ecs", + "gamedev" + ], + "main": "./src/extension.js", + "activationEvents": [ + "onLanguage:ludic", + "onLanguage:markdown", + "workspaceContains:**/*.ludic" + ], + "contributes": { + "languages": [ + { + "id": "ludic", + "aliases": [ + "Ludic", + "ludic" + ], + "extensions": [ + ".ludic" + ], + "configuration": "./language-configuration.json", + "icon": { + "light": "./icons/ludic.svg", + "dark": "./icons/ludic.svg" + } + } + ], + "grammars": [ + { + "language": "ludic", + "scopeName": "source.ludic", + "path": "./syntaxes/ludic.tmLanguage.json" + }, + { + "scopeName": "markdown.ludic.codeblock", + "path": "./syntaxes/ludic.markdown-injection.json", + "injectTo": [ + "text.html.markdown" + ], + "embeddedLanguages": { + "meta.embedded.block.ludic": "ludic" + } + } + ], + "semanticTokenScopes": [ + { + "language": "ludic", + "scopes": { + "struct": [ + "entity.name.type.component.ludic" + ], + "class": [ + "entity.name.type.archetype.ludic" + ], + "namespace": [ + "entity.name.type.scene.ludic" + ], + "function.defaultLibrary": [ + "support.function.builtin.ludic" + ], + "enumMember.readonly.defaultLibrary": [ + "constant.language.phase.ludic" + ], + "decorator": [ + "entity.name.function.decorator.ludic" + ] + } + } + ], + "configuration": { + "title": "Ludic", + "properties": { + "ludic.server.path": { + "type": "string", + "default": "", + "markdownDescription": "Path to the `ludic-lsp` binary. Empty means: look in `build/ludic-lsp` under each workspace folder, then on `PATH`." + }, + "ludic.server.enabled": { + "type": "boolean", + "default": true, + "description": "Run the Ludic language server. Turn this off to keep only the static syntax highlighting." + }, + "ludic.compilerPath": { + "type": "string", + "default": "", + "markdownDescription": "Path to `ludicc`. The server shells out to it for authoritative diagnostics on save. Empty means `build/ludicc` under the workspace." + }, + "ludic.compilerDiagnostics": { + "type": "boolean", + "default": true, + "description": "Report errors from the Ludic compiler on save, in addition to the server's own structural checks." + }, + "ludic.indentSize": { + "type": "number", + "default": 2, + "description": "Spaces per indent level used by the formatter when the editor does not say otherwise." + }, + "ludic.trace.server": { + "type": "string", + "enum": [ + "off", + "messages", + "verbose" + ], + "default": "off", + "description": "Log the traffic between VS Code and the Ludic language server." + } + } + }, + "commands": [ + { + "command": "ludic.restartServer", + "title": "Ludic: Restart Language Server" + }, + { + "command": "ludic.showOutput", + "title": "Ludic: Show Language Server Log" + } + ], + "configurationDefaults": { + "[ludic]": { + "editor.insertSpaces": true, + "editor.tabSize": 2, + "editor.semanticHighlighting.enabled": true + } + }, + "snippets": [ + { + "language": "ludic", + "path": "./snippets/ludic.json" + } + ] + }, + "dependencies": { + "vscode-languageclient": "^9.0.1" + }, + "repository": { + "type": "git", + "url": "https://example.invalid/ludic" + } +} diff --git a/tools/editors/vscode/snippets/ludic.json b/tools/editors/vscode/snippets/ludic.json new file mode 100644 index 00000000..2bcd3a36 --- /dev/null +++ b/tools/editors/vscode/snippets/ludic.json @@ -0,0 +1,96 @@ +{ + "game": { + "prefix": "game", + "body": ["game ${1:Name} {", "\t$0", "}"], + "description": "A game unit — compiles to an executable." + }, + "module": { + "prefix": "module", + "body": ["module ${1:Name} {", "\t$0", "}"], + "description": "A library unit — compiles to a shared library, no frame loop." + }, + "component": { + "prefix": "component", + "body": ["component ${1:Name} { ${2:x}: ${3:int} = ${4:0} }"], + "description": "A component: typed per-entity fields." + }, + "archetype": { + "prefix": "archetype", + "body": ["archetype ${1:Name} {", "\t${2:Pos}", "}"], + "description": "An entity kind bundling a fixed set of components." + }, + "system": { + "prefix": "system", + "body": [ + "system ${1:Name} phase ${2|Start,Input,FixedUpdate,Update,LateUpdate,Render|} {", + "\t$0", + "}" + ], + "description": "A system that runs once per tick in its phase." + }, + "system with query": { + "prefix": "systemq", + "body": [ + "system ${1:Name} phase ${2|Update,FixedUpdate,LateUpdate,Render,Input|}", + " query (${3:p}) [${4:Pos}]", + "{", + "\t$0", + "}" + ], + "description": "A system whose body runs once per matching entity." + }, + "for query": { + "prefix": "forq", + "body": ["for (${1:p}) in query [${2:Pos}] {", "\t$0", "}"], + "description": "Iterate every entity matching a query." + }, + "spawn": { + "prefix": "spawn", + "body": ["spawn ${1:Kind} {", "\t${2:Pos} = { ${3:x} = ${4:0} }", "}"], + "description": "Create an entity of an archetype." + }, + "scene": { + "prefix": "scene", + "body": [ + "scene ${1:Name} {", + "\ton enter { $2 }", + "\tlayer ${3:Main} {", + "\t\t$0", + "\t}", + "}" + ], + "description": "A scene with lifecycle hooks and one layer of systems." + }, + "ui": { + "prefix": "ui", + "body": [ + "ui ${1:Name} {", + "\tpanel id=${2:Root} pad=16 gap=6 align=center {", + "\t\t$0", + "\t}", + "}" + ], + "description": "A retained UI tree." + }, + "match": { + "prefix": "match", + "body": ["match ${1:x} {", "\t${2:0} => { $3 }", "\t_ => { $0 }", "}"], + "description": "Pattern match." + }, + "machine": { + "prefix": "machine", + "body": [ + "machine reg(${1:R_PHASE}) {", + "\tstate ${2:Idle} = 0 {", + "\t\t$0", + "\t}", + "}" + ], + "description": "A state machine over a register." + }, + "extern fn": { + "prefix": "extern", + "body": ["extern fn ${1:name}(${2:a}: ${3:int}) -> ${4:int} = \"${5:c_symbol}\""], + "description": "Bind a C symbol through the FFI." + } +} diff --git a/tools/editors/vscode/src/extension.js b/tools/editors/vscode/src/extension.js new file mode 100644 index 00000000..ab816a7a --- /dev/null +++ b/tools/editors/vscode/src/extension.js @@ -0,0 +1,149 @@ +/* ============================================================================ + * The VS Code half of Ludic support. + * + * There is deliberately very little here. Highlighting comes from the TextMate + * grammar in syntaxes/ (shared, unmodified, with every other editor), and + * everything else — completion, hover, diagnostics, formatting, symbols — + * comes from `ludic-lsp`, the same binary JetBrains and Neovim talk to. This + * file's whole job is finding that binary and keeping it alive. + * ==========================================================================*/ +const path = require('path'); +const fs = require('fs'); +const os = require('os'); +const vscode = require('vscode'); +const { LanguageClient, TransportKind } = require('vscode-languageclient/node'); + +let client = null; +let output = null; + +/** Where the language server might be, in the order we should look. */ +function resolveServer(folders) { + const configured = vscode.workspace.getConfiguration('ludic').get('server.path'); + if (configured) return expand(configured); + + const names = ['ludic-lsp', 'ludic-lsp.exe']; + for (const folder of folders) { + const root = folder.uri.fsPath; + for (const rel of ['build', 'tools/build', 'bin', '.']) { + for (const name of names) { + const p = path.join(root, rel, name); + if (isExecutable(p)) return p; + } + } + } + // Fall back to PATH; spawning by bare name lets the OS resolve it. + for (const dir of (process.env.PATH || '').split(path.delimiter)) { + for (const name of names) { + const p = path.join(dir, name); + if (isExecutable(p)) return p; + } + } + return null; +} + +function resolveCompiler(folders) { + const configured = vscode.workspace.getConfiguration('ludic').get('compilerPath'); + if (configured) return expand(configured); + for (const folder of folders) { + const p = path.join(folder.uri.fsPath, 'build', 'ludicc'); + if (isExecutable(p)) return p; + } + return ''; +} + +function expand(p) { + return p.startsWith('~') ? path.join(os.homedir(), p.slice(1)) : p; +} + +function isExecutable(p) { + try { + fs.accessSync(p, fs.constants.X_OK); + return fs.statSync(p).isFile(); + } catch { + return false; + } +} + +async function start(context) { + const cfg = vscode.workspace.getConfiguration('ludic'); + if (!cfg.get('server.enabled')) return; + + const folders = vscode.workspace.workspaceFolders || []; + const server = resolveServer(folders); + if (!server) { + // Not an error worth a modal: the grammar still highlights, and plenty of + // people open a .ludic file without having built the toolchain. + output.appendLine( + 'ludic-lsp not found. Build it with tools/build-tools.sh, or set "ludic.server.path". ' + + 'Syntax highlighting works without it; completion and diagnostics do not.' + ); + return; + } + output.appendLine(`starting ${server}`); + + const serverOptions = { + run: { command: server, args: ['--stdio'], transport: TransportKind.stdio }, + debug: { command: server, args: ['--stdio'], transport: TransportKind.stdio } + }; + + const clientOptions = { + // Markdown is included on purpose: ```ludic fences in a .md get the same + // diagnostics, hover and semantic highlighting as a real source file. + documentSelector: [ + { scheme: 'file', language: 'ludic' }, + { scheme: 'file', language: 'markdown' } + ], + synchronize: { + fileEvents: vscode.workspace.createFileSystemWatcher('**/*.ludic'), + configurationSection: 'ludic' + }, + outputChannel: output, + initializationOptions: { + compilerPath: resolveCompiler(folders), + compilerDiagnostics: cfg.get('compilerDiagnostics'), + indentSize: cfg.get('indentSize') + } + }; + + client = new LanguageClient('ludic', 'Ludic Language Server', serverOptions, clientOptions); + await client.start(); + context.subscriptions.push(client); +} + +async function stop() { + if (!client) return; + const c = client; + client = null; + await c.stop(); +} + +async function activate(context) { + output = vscode.window.createOutputChannel('Ludic'); + context.subscriptions.push(output); + + context.subscriptions.push( + vscode.commands.registerCommand('ludic.restartServer', async () => { + await stop(); + await start(context); + vscode.window.setStatusBarMessage('Ludic: language server restarted', 3000); + }), + vscode.commands.registerCommand('ludic.showOutput', () => output.show()) + ); + + context.subscriptions.push( + vscode.workspace.onDidChangeConfiguration(async (e) => { + if (e.affectsConfiguration('ludic.server')) { + await stop(); + await start(context); + } + }) + ); + + await start(context); +} + +function deactivate() { + return stop(); +} + +module.exports = { activate, deactivate }; diff --git a/tools/editors/vscode/syntaxes/ludic.markdown-injection.json b/tools/editors/vscode/syntaxes/ludic.markdown-injection.json new file mode 100644 index 00000000..15931c4c --- /dev/null +++ b/tools/editors/vscode/syntaxes/ludic.markdown-injection.json @@ -0,0 +1,27 @@ +{ + "scopeName": "markdown.ludic.codeblock", + "comment": "Injects Ludic highlighting into ```ludic fences in Markdown. Any TextMate-based editor (VS Code, Sublime, JetBrains' TextMate bundles, Zed) picks this up; JetBrains' native Markdown support gets the same thing for free from the registered `Ludic` language ID, and ludic-lsp will also serve semantic tokens and diagnostics for the fence bodies in a .md file.", + "injectionSelector": "L:text.html.markdown", + "patterns": [{ "include": "#ludic-code-block" }], + "repository": { + "ludic-code-block": { + "begin": "(^|\\G)(\\s*)(`{3,}|~{3,})\\s*(?i:(ludic)((\\s+|:|,|\\{|\\?)[^`~]*)?)$", + "name": "markup.fenced_code.block.markdown", + "end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$", + "beginCaptures": { + "3": { "name": "punctuation.definition.markdown" }, + "4": { "name": "fenced_code.block.language.markdown" }, + "5": { "name": "fenced_code.block.language.attributes.markdown" } + }, + "endCaptures": { "3": { "name": "punctuation.definition.markdown" } }, + "patterns": [ + { + "begin": "(^|\\G)(\\s*)(.*)", + "while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)", + "contentName": "meta.embedded.block.ludic", + "patterns": [{ "include": "source.ludic" }] + } + ] + } + } +} diff --git a/tools/editors/vscode/syntaxes/ludic.tmLanguage.json b/tools/editors/vscode/syntaxes/ludic.tmLanguage.json new file mode 100644 index 00000000..8b99e208 --- /dev/null +++ b/tools/editors/vscode/syntaxes/ludic.tmLanguage.json @@ -0,0 +1,241 @@ +{ + "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", + "name": "Ludic", + "scopeName": "source.ludic", + "fileTypes": ["ludic"], + "comment": "Static grammar for Ludic. It is the fallback: when ludic-lsp is running, its semantic tokens refine everything here with real name resolution. Generated shapes are kept in sync with tools/ludic-tools/ludic_syntax.h.", + "patterns": [ + { "include": "#comment" }, + { "include": "#declaration" }, + { "include": "#query" }, + { "include": "#string" }, + { "include": "#number" }, + { "include": "#annotation" }, + { "include": "#keyword" }, + { "include": "#widget" }, + { "include": "#builtin" }, + { "include": "#member" }, + { "include": "#call" }, + { "include": "#typename" }, + { "include": "#operator" } + ], + "repository": { + "comment": { + "match": "#.*$", + "name": "comment.line.number-sign.ludic" + }, + "string": { + "patterns": [ + { + "name": "string.quoted.double.ludic", + "begin": "\"", + "end": "\"", + "beginCaptures": { "0": { "name": "punctuation.definition.string.begin.ludic" } }, + "endCaptures": { "0": { "name": "punctuation.definition.string.end.ludic" } }, + "patterns": [{ "name": "constant.character.escape.ludic", "match": "\\\\." }] + }, + { + "name": "string.quoted.single.ludic", + "match": "'(\\\\.|[^'\\\\])'" + } + ] + }, + "number": { + "patterns": [ + { "name": "constant.numeric.hex.ludic", "match": "\\b0[xX][0-9a-fA-F]+\\b" }, + { "name": "constant.numeric.fixed.ludic", "match": "\\b[0-9]+\\.[0-9]+\\b" }, + { "name": "constant.numeric.integer.ludic", "match": "\\b[0-9]+\\b" } + ] + }, + "annotation": { + "name": "entity.name.function.decorator.ludic", + "match": "@[A-Za-z_][A-Za-z0-9_]*" + }, + "declaration": { + "patterns": [ + { + "match": "\\b(game|module)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "keyword.control.unit.ludic" }, + "2": { "name": "entity.name.type.unit.ludic" } + } + }, + { + "match": "\\b(component)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "storage.type.component.ludic" }, + "2": { "name": "entity.name.type.component.ludic" } + } + }, + { + "match": "\\b(archetype)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "storage.type.archetype.ludic" }, + "2": { "name": "entity.name.type.archetype.ludic" } + } + }, + { + "match": "\\b(scene)\\s+([A-Za-z_][A-Za-z0-9_]*)(\\s+start)?", + "captures": { + "1": { "name": "storage.type.scene.ludic" }, + "2": { "name": "entity.name.type.scene.ludic" }, + "3": { "name": "keyword.other.start.ludic" } + } + }, + { + "match": "\\b(layer|ui)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "storage.type.ludic" }, + "2": { "name": "entity.name.type.ludic" } + } + }, + { + "match": "\\b(edge\\s+)?(system)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "storage.modifier.edge.ludic" }, + "2": { "name": "storage.type.system.ludic" }, + "3": { "name": "entity.name.function.system.ludic" } + } + }, + { + "match": "\\b(export\\s+|pure\\s+)?(extern\\s+)?(fn)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "storage.modifier.ludic" }, + "2": { "name": "storage.modifier.extern.ludic" }, + "3": { "name": "storage.type.function.ludic" }, + "4": { "name": "entity.name.function.ludic" } + } + }, + { + "match": "\\b(const|var|let)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "storage.type.ludic" }, + "2": { "name": "variable.other.definition.ludic" } + } + }, + { + "match": "\\b(state)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "keyword.control.state.ludic" }, + "2": { "name": "entity.name.constant.state.ludic" } + } + }, + { + "match": "\\b(import)\\s+(?=\")", + "captures": { "1": { "name": "keyword.control.import.ludic" } } + }, + { + "match": "\\b(phase)\\s+(Start|Input|FixedUpdate|Update|LateUpdate|Render)\\b", + "captures": { + "1": { "name": "keyword.other.clause.ludic" }, + "2": { "name": "constant.language.phase.ludic" } + } + }, + { + "match": "\\b(enter)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "keyword.control.enter.ludic" }, + "2": { "name": "entity.name.type.scene.ludic" } + } + }, + { + "match": "\\b(spawn)\\s+([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "keyword.control.spawn.ludic" }, + "2": { "name": "entity.name.type.archetype.ludic" } + } + } + ] + }, + "query": { + "comment": "Inside a query's brackets a bare word names a component and {Word} is a filter that does not bind.", + "begin": "\\b(query)\\s*(\\[)", + "beginCaptures": { + "1": { "name": "keyword.other.query.ludic" }, + "2": { "name": "punctuation.section.brackets.begin.ludic" } + }, + "end": "(\\])", + "endCaptures": { "1": { "name": "punctuation.section.brackets.end.ludic" } }, + "patterns": [ + { + "match": "(\\{)\\s*([A-Za-z_][A-Za-z0-9_]*)\\s*(\\})", + "captures": { + "1": { "name": "punctuation.section.braces.begin.ludic" }, + "2": { "name": "entity.name.type.tag.ludic" }, + "3": { "name": "punctuation.section.braces.end.ludic" } + } + }, + { "name": "entity.name.type.component.ludic", "match": "\\b[A-Za-z_][A-Za-z0-9_]*\\b" }, + { "name": "punctuation.separator.ludic", "match": "," } + ] + }, + "keyword": { + "patterns": [ + { "name": "keyword.control.ludic", "match": "\\b(if|else|when|while|for|in|match|machine|become|enter|return|spawn|despawn|where|break|continue|new)\\b" }, + { "name": "keyword.operator.logical.ludic", "match": "\\b(and|or|not)\\b" }, + { "name": "keyword.other.clause.ludic", "match": "\\b(phase|query|reads|writes|needs|uses|requires|ensures|invariant|effects|on)\\b" }, + { "name": "keyword.other.ludic", "match": "\\b(import|export|pure|extern|start|edge)\\b" }, + { "name": "storage.type.ludic", "match": "\\b(game|module|component|archetype|ui|scene|layer|const|var|let|fn|system|state)\\b" }, + { "name": "support.type.primitive.ludic", "match": "\\b(int|fixed|bool|entity|str|ptr|void)\\b" }, + { "name": "constant.language.boolean.ludic", "match": "\\b(true|false)\\b" }, + { "name": "constant.language.phase.ludic", "match": "\\b(Start|Input|FixedUpdate|Update|LateUpdate|Render)\\b" } + ] + }, + "widget": { + "patterns": [ + { + "comment": "widget types, recognised by the props or the child block that follow them", + "name": "support.class.widget.ludic", + "match": "\\b(panel|col|row|label|button|image|spacer)\\b(?=\\s*(\\{|[a-z][A-Za-z0-9_]*\\s*=|$))" + }, + { + "comment": "widget props are written tight (id=Root); an assignment is written x = 1", + "match": "\\b([a-z][A-Za-z0-9_]*)(=)(?!=)", + "captures": { + "1": { "name": "variable.parameter.widget.ludic" }, + "2": { "name": "keyword.operator.assignment.ludic" } + } + } + ] + }, + "builtin": { + "patterns": [ + { + "comment": "the runtime surface — every name here resolves to rt_ in runtime/native", + "name": "support.function.builtin.ludic", + "match": "\\b(min|max|abs|clamp|seed|rng_range|rng_chance|fx|flr|map_size|map_row|tile|clear|present|fill_rect|frame_rect|put_px|text|text_int|font_load|text_ttf|text_w|text_h|image_load|draw_image|draw_image_scaled|draw_9slice|load_png|load_sprites|draw_sprite|draw_sprite_scaled|ui_build|ui_open|ui_tick|ui_render|ui_clicked|ui_set_text|ui_set_int|ui_focus|ui_focused|ui_visible|key|reg|setreg|self|save|load|status|print_int|quit)\\b(?=\\s*\\()" + }, + { + "comment": "compiler intrinsics — these lower straight to libc or the OS", + "name": "support.function.intrinsic.ludic", + "match": "\\b(mem_alloc|mem_realloc|mem_free|mem_copy|mem_set|peek8|poke8|peek32|poke32|peekp|pokep|peekf|pokef|ptr_add|ptr_null|ptr_is_null|as_fixed|as_int|file_open|file_read|file_write|file_seek|file_tell|file_close|read_byte|write_byte|print_str|str_len|shl|shr|band|bor|bxor|bnot|os_exit|os_time|os_argc|os_arg|file_stderr|is_windowed|game_title|win_open|win_poll|win_present|win_running|win_close)\\b(?=\\s*\\()" + } + ] + }, + "member": { + "match": "(\\.)([A-Za-z_][A-Za-z0-9_]*)", + "captures": { + "1": { "name": "punctuation.accessor.ludic" }, + "2": { "name": "variable.other.property.ludic" } + } + }, + "call": { + "match": "\\b([A-Za-z_][A-Za-z0-9_]*)\\s*(?=\\()", + "name": "entity.name.function.call.ludic" + }, + "typename": { + "comment": "components, archetypes, scenes and UI handles are Capitalised by convention", + "name": "entity.name.type.ludic", + "match": "\\b[A-Z][A-Za-z0-9_]*\\b" + }, + "operator": { + "patterns": [ + { "name": "keyword.operator.arrow.ludic", "match": "->|=>" }, + { "name": "keyword.operator.range.ludic", "match": "\\.\\." }, + { "name": "keyword.operator.comparison.ludic", "match": "==|!=|<=|>=|<|>" }, + { "name": "keyword.operator.assignment.ludic", "match": "\\+=|-=|\\*=|/=|=" }, + { "name": "keyword.operator.arithmetic.ludic", "match": "[+\\-*/%]" } + ] + } + } +} diff --git a/tools/editors/zed/README.md b/tools/editors/zed/README.md new file mode 100644 index 00000000..052796fa --- /dev/null +++ b/tools/editors/zed/README.md @@ -0,0 +1,39 @@ +# Ludic for Zed + +Zed extensions want a Tree-sitter grammar for highlighting, which this toolchain +deliberately does not ship — the vocabulary lives in one C header and is exposed +through the language server's semantic tokens instead, so there is no second +grammar to keep honest. + +That is enough for Zed: point it at `ludic-lsp` and highlighting, completion, +diagnostics and formatting all arrive over LSP. + +Add to `~/.config/zed/settings.json`: + +```json +{ + "lsp": { + "ludic-lsp": { + "binary": { "path": "/path/to/gpp/build/ludic-lsp", "arguments": ["--stdio"] }, + "initialization_options": { + "compilerPath": "/path/to/gpp/build/ludicc", + "compilerDiagnostics": true, + "indentSize": 2 + } + } + }, + "file_types": { "Ludic": ["ludic"] }, + "languages": { + "Ludic": { + "language_servers": ["ludic-lsp"], + "tab_size": 2, + "hard_tabs": false, + "format_on_save": "on" + } + } +} +``` + +If you would rather have static highlighting too, the TextMate grammar in +`tools/editors/shared/ludic.tmLanguage.json` can be dropped into a Zed extension +that declares a `grammars` entry — but it is not required. diff --git a/tools/git-hooks/pre-commit b/tools/git-hooks/pre-commit new file mode 100755 index 00000000..efe6657a --- /dev/null +++ b/tools/git-hooks/pre-commit @@ -0,0 +1,29 @@ +#!/bin/sh +# Reject a commit that contains unformatted Ludic — in source or in the ```ludic +# fences of a Markdown file. +# +# ln -sf ../../tools/git-hooks/pre-commit .git/hooks/pre-commit +# +# Checks only the files being committed, so it stays fast on a big tree. +set -e +ROOT=$(git rev-parse --show-toplevel) +FMT="$ROOT/build/ludic-fmt" + +[ -x "$FMT" ] || exit 0 # toolchain not built: do not block the commit + +FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(ludic|md|markdown)$' || true) +[ -z "$FILES" ] && exit 0 + +UNFORMATTED="" +for f in $FILES; do + [ -f "$ROOT/$f" ] || continue + "$FMT" --check -q "$ROOT/$f" >/dev/null 2>&1 || UNFORMATTED="$UNFORMATTED $f" +done + +if [ -n "$UNFORMATTED" ]; then + echo "unformatted Ludic:" + for f in $UNFORMATTED; do echo " $f"; done + echo + echo "fix with: build/ludic-fmt -w$UNFORMATTED" + exit 1 +fi diff --git a/tools/ludic-tools/ludic_fmt.h b/tools/ludic-tools/ludic_fmt.h new file mode 100644 index 00000000..89bc12af --- /dev/null +++ b/tools/ludic-tools/ludic_fmt.h @@ -0,0 +1,339 @@ +/* ============================================================================ + * ludic_fmt.h — the canonical Ludic formatter. + * + * This is deliberately NOT `ludicc --fmt`. The compiler's printer walks the AST + * after import splicing, so it drops every comment and inlines every imported + * file into whichever file you pointed it at — fine for inspecting what the + * compiler saw, catastrophic as an editor's "format on save". + * + * This formatter works on the token stream instead: + * - comments and blank lines survive, because they are tokens; + * - nothing is ever dropped or reordered, because every token is re-emitted + * in order — the only freedom taken is the whitespace between them; + * - lines are re-indented and respaced but never joined or split, so the + * author keeps control of line structure and a format-on-save never + * rewrites a file out from under someone mid-edit. + * ==========================================================================*/ +#ifndef LUDIC_FMT_H +#define LUDIC_FMT_H + +#include "ludic_syntax.h" + +typedef struct { char* b; size_t n, cap; } FSB; +static void fsb_ensure(FSB* s, size_t add){ + if (s->n + add + 1 > s->cap){ s->cap = (s->n + add + 1) * 2; s->b = realloc(s->b, s->cap); } +} +static void fsb_add(FSB* s, const char* z, size_t l){ fsb_ensure(s, l); memcpy(s->b + s->n, z, l); s->n += l; s->b[s->n] = 0; } +static void fsb_puts(FSB* s, const char* z){ fsb_add(s, z, strlen(z)); } +static void fsb_putc(FSB* s, char c){ fsb_add(s, &c, 1); } +static void fsb_indent(FSB* s, int n){ for (int i = 0; i < n; i++) fsb_putc(s, ' '); } + +/* Can this token be one side of a member access? */ +static int lud_name_like(int kind){ + return kind == LT_ID || kind == LT_KW || kind == LT_TYPE || kind == LT_PHASE || kind == LT_BOOL; +} +/* A '.' hugs an operand, a closing bracket, and another dot — the last so that + * a run of dots stays a run of dots instead of being spaced into pieces. */ +static int lud_dot_tight(const LLex* L, const LTok* t){ + if (lud_name_like(t->kind)) return 1; + if (t->kind != LT_OP) return 0; + int n = ltok_len(t); + char c0 = L->src[t->start]; + if (n == 1 && (c0 == ')' || c0 == ']' || c0 == '.')) return 1; + if (n == 2 && c0 == '.' && L->src[t->start + 1] == '.') return 1; + return 0; +} + +/* Is the token at index i a unary '-' / '!' rather than a binary operator? + * Unary iff nothing that can end an operand precedes it. */ +static int fmt_is_unary(const LLex* L, int i){ + const LTok* t = &L->v[i]; + if (t->kind != LT_OP) return 0; + int n = ltok_len(t); + if (!(n == 1 && (L->src[t->start] == '-' || L->src[t->start] == '!'))) return 0; + int p = ltok_prev_sig(L, i); + if (p < 0) return 1; + const LTok* pt = &L->v[p]; + switch (pt->kind){ + case LT_ID: case LT_INT: case LT_FLOAT: case LT_STR: case LT_CHAR: + case LT_BOOL: case LT_TYPE: case LT_PHASE: + return 0; + case LT_OP: { + char c = L->src[pt->start]; + /* a closing bracket ends an operand; every other operator does not */ + return !(ltok_len(pt) == 1 && (c == ')' || c == ']' || c == '}')); + } + default: return 1; /* keyword, annotation, comment: operand starts here */ + } +} + +/* Whitespace between the previous emitted token (prev) and the current one. */ +static int fmt_space_before(const LLex* L, int prev, int cur){ + if (prev < 0) return 0; + const LTok* p = &L->v[prev]; + const LTok* c = &L->v[cur]; + const char* src = L->src; + int plen = ltok_len(p), clen = ltok_len(c); + char p0 = src[p->start], c0 = src[c->start]; + int p1 = (plen == 1), c1 = (clen == 1); + + /* An error token is bytes we did not understand. Whatever spacing it had + * is the only spacing we can justify, so it is preserved verbatim. */ + if (p->kind == LT_ERR || c->kind == LT_ERR) return c->start - p->end; + + /* nothing hugs a closer, a separator or a member dot from the left */ + if (c1 && (c0 == ')' || c0 == ']' || c0 == ',' || c0 == ':' || c0 == ';')) return 0; + /* `.` binds tight only when it really is member access — `a.b`. A lone dot + * next to a brace is something else (or a typo) and gets normal spacing. */ + if (c1 && c0 == '.' && c->kind == LT_OP && lud_dot_tight(L, p)) return 0; + if (p1 && p0 == '.' && p->kind == LT_OP && lud_dot_tight(L, c)) return 0; + /* nothing hugs an opener from the right */ + if (p1 && (p0 == '(' || p0 == '[') && p->kind == LT_OP) return 0; + /* a unary sign binds to its operand */ + if (p->kind == LT_OP && fmt_is_unary(L, prev)) return 0; + /* @anno(args) */ + if (p->kind == LT_ANNO && c1 && c0 == '(') return 0; + + if (c1 && c0 == '(' && c->kind == LT_OP){ + /* `fn move(` and `clear(` hug; `if (`, `return (`, `x * (` do not */ + switch (p->kind){ + case LT_ID: case LT_TYPE: case LT_PHASE: return 0; + case LT_OP: return !(p1 && (p0 == ')' || p0 == ']')); + default: return 1; + } + } + return 1; +} + +/* Clause keywords hang under the declaration they qualify: a system's + * `phase`/`query` lines and a function's contract lines are indented one level + * past the `system`/`fn` they belong to, with the body brace back at the + * declaration's own level. Every example in the tree is written that way. */ +static int fmt_is_clause_word(const LLex* L, int i){ + static const char* CLAUSES[] = { "phase","query","reads","writes","needs","uses", + "requires","ensures","invariant","effects", 0 }; + if (i < 0 || i >= L->n || L->v[i].kind != LT_KW) return 0; + char b[32]; ltok_text(L, i, b, sizeof(b)); + return lud_in(CLAUSES, b); +} + +/* One pass over the token stream, re-emitting it with canonical whitespace. + * + * Two carve-outs keep the result idiomatic rather than merely uniform: + * - a run of two or more spaces is preserved verbatim, so hand-aligned + * columns (`const R_DIR: int = 0`) and deliberately set-off trailing + * comments survive a format-on-save; + * - `id=Root` inside a `ui` block and `{Enemy}` inside a query stay tight, + * because those are the spellings the language documents and uses. + */ +static char* ludic_format(const char* src, int indent_width){ + LLex L; lud_lex(&L, src); + FSB o = {0}; + /* One entry per open brace, holding the indent level to return to. Every + * brace opened on the same line shares that line's level, so a line like + * `if a { if b { if c {` steps in by ONE level, not three — and the line + * that closes them all lands back where it started. */ + int stack[512]; int hang[512]; int sp = 0; + int cur = 0; + int open = 0; /* unclosed ( or [ : the author owns the alignment */ + int brack = 0; /* unclosed [ only: query-term context */ + int ui_depth = -1; /* brace depth just outside the innermost `ui` block */ + int pending_blank = 0; + int wrote_any = 0; + int prev_line_had_comment = 0; + + int i = 0; + while (i < L.n && L.v[i].kind != LT_EOF){ + int a = i; + while (i < L.n && L.v[i].kind != LT_NL && L.v[i].kind != LT_EOF) i++; + int b = i; /* [a,b) are this line's tokens */ + if (i < L.n && L.v[i].kind == LT_NL) i++; + + if (a == b){ /* a blank line */ + if (wrote_any) pending_blank = 1; + continue; + } + + /* ---- where does this line start? --------------------------------- */ + int line_level = cur; + { /* leading closers belong to the level of the line that opened them */ + int tsp = sp, t = a; + while (t < b && L.v[t].kind == LT_OP && ltok_len(&L.v[t]) == 1 && src[L.v[t].start] == '}'){ + if (tsp > 0) line_level = stack[--tsp]; + t++; + } + } + /* Original column of this line, for the cases where the author's + * alignment is the only sensible answer. */ + int orig_ind = 0; + for (int k = L.linestart[L.v[a].line]; k < L.v[a].start; k++) orig_ind += (src[k] == '\t') ? 4 : 1; + + /* A comment on its own line, indented past its block and following a + * line that itself ended in a comment, is the continuation of that + * comment — a column the author chose, not stray indentation. */ + int comment_run = (L.v[a].kind == LT_COMMENT && b == a + 1 && prev_line_had_comment); + + int ind; + if (open > 0 || (sp > 0 && hang[sp - 1])){ + /* Inside an unclosed call, query, or a brace that was opened with + * content trailing it, the author is aligning to a column the + * formatter cannot see. Leave those lines exactly as written. */ + int ls = L.linestart[L.v[a].line]; + ind = 0; + for (int k = ls; k < L.v[a].start; k++) ind += (src[k] == '\t') ? 4 : 1; + } else { + ind = line_level * indent_width + (fmt_is_clause_word(&L, a) ? indent_width : 0); + if (comment_run && orig_ind > ind) ind = orig_ind; + } + + if (pending_blank && wrote_any) fsb_putc(&o, '\n'); + pending_blank = 0; + fsb_indent(&o, ind); + + /* ---- the tokens --------------------------------------------------- */ + int prev = -1; + int line_brack = brack, line_ui_open = (ui_depth >= 0 && sp > ui_depth); + for (int t = a; t < b; t++){ + const LTok* tk = &L.v[t]; + int gap = (prev >= 0) ? tk->start - L.v[prev].end : 0; + int want; + + if (tk->kind == LT_COMMENT){ + want = (prev >= 0) ? 2 : 0; /* set a trailing comment off */ + } else { + want = fmt_space_before(&L, prev, t); + /* a query's {Tag} filter is one word, not a record literal */ + if (line_brack > 0){ + if (tk->kind == LT_OP && ltok_len(tk) == 1 && src[tk->start] == '}') want = 0; + if (prev >= 0 && L.v[prev].kind == LT_OP && ltok_len(&L.v[prev]) == 1 && src[L.v[prev].start] == '{') want = 0; + } + /* widget props are written k=v */ + if (line_ui_open){ + int eq_here = tk->kind == LT_OP && ltok_len(tk) == 1 && src[tk->start] == '='; + int eq_prev = prev >= 0 && L.v[prev].kind == LT_OP && + ltok_len(&L.v[prev]) == 1 && src[L.v[prev].start] == '='; + if (eq_here || eq_prev) want = 0; + } + } + /* hand alignment wins over the canonical single space */ + if (gap >= 2 && want >= 1){ if (gap > 60) gap = 60; want = gap; } + if (want < 0) want = 0; + for (int k = 0; k < want; k++) fsb_putc(&o, ' '); + fsb_add(&o, src + tk->start, ltok_len(tk)); + prev = t; + + if (tk->kind == LT_OP && ltok_len(tk) == 1){ + char c = src[tk->start]; + if (c == '[') line_brack++; + else if (c == ']'){ line_brack--; if (line_brack < 0) line_brack = 0; } + } + } + fsb_putc(&o, '\n'); + wrote_any = 1; + prev_line_had_comment = (prev >= 0 && L.v[prev].kind == LT_COMMENT); + + /* ---- carry the nesting into the next line ------------------------- */ + if (ltok_is(&L, a, "ui") && L.v[a].kind == LT_KW && ui_depth < 0) ui_depth = sp; + { + int level = cur; + for (int t = a; t < b; t++){ + const LTok* tk = &L.v[t]; + if (tk->kind != LT_OP || ltok_len(tk) != 1) continue; + char c = src[tk->start]; + if (c == '{'){ + if (sp < 512){ + int nxt = ltok_next_sig(&L, t); + stack[sp] = line_level; + hang[sp] = (nxt >= 0 && nxt < b); /* content follows on this line */ + sp++; + } + level = line_level + 1; + } + else if (c == '}'){ if (sp > 0) level = stack[--sp]; } + else if (c == '(' || c == '['){ open++; if (c == '[') brack++; } + else if (c == ')' || c == ']'){ open--; if (open < 0) open = 0; if (c == ']'){ brack--; if (brack < 0) brack = 0; } } + } + cur = level; + } + if (ui_depth >= 0 && sp <= ui_depth) ui_depth = -1; + } + lud_lex_free(&L); + if (!o.b) { o.b = malloc(1); o.b[0] = 0; } + return o.b; +} + +/* ---------- markdown ------------------------------------------------------ + * Fenced Ludic in prose is still Ludic. This rewrites the body of every + * ```ludic fence in a Markdown document and leaves the prose untouched, so + * LANGUAGE.md and README.md can be kept honest by the same formatter as the + * source tree. Fence indentation (a fence inside a list item) is preserved. */ +static int md_fence_at(const char* s, int i, int* fence_len, int* info_at, char* marker){ + int j = i, n = 0; + while (s[j] == ' ') j++; /* leading indent */ + char m = s[j]; + if (m != '`' && m != '~') return 0; + while (s[j] == m){ j++; n++; } + if (n < 3) return 0; + *fence_len = n; *info_at = j; *marker = m; + return 1; +} +static int md_info_is_ludic(const char* s, int at){ + while (s[at] == ' ' || s[at] == '\t') at++; + if (strncasecmp(s + at, "ludic", 5)) return 0; + char after = s[at + 5]; + return after == 0 || after == '\n' || after == ' ' || after == '\t' || after == '\r'; +} +static char* ludic_format_markdown(const char* src, int indent_width){ + FSB o = {0}; + int i = 0; + while (src[i]){ + int ls = i; /* line start */ + int le = ls; while (src[le] && src[le] != '\n') le++; + int flen, info, indent = 0; char marker; + while (src[ls + indent] == ' ') indent++; + if (md_fence_at(src, ls, &flen, &info, &marker) && md_info_is_ludic(src, info)){ + /* copy the opening fence line verbatim */ + fsb_add(&o, src + ls, le - ls + (src[le] ? 1 : 0)); + i = src[le] ? le + 1 : le; + /* gather the body up to the closing fence */ + int bs = i; + int be = bs; + for (;;){ + if (!src[be]) break; + int ps = be, pe = ps; while (src[pe] && src[pe] != '\n') pe++; + int clen, cinfo; char cmark; + if (md_fence_at(src, ps, &clen, &cinfo, &cmark) && cmark == marker && clen >= flen){ + int only = 1; + for (int k = cinfo; k < pe; k++) if (src[k] != ' ' && src[k] != '\r'){ only = 0; break; } + if (only) break; + } + be = src[pe] ? pe + 1 : pe; + } + /* de-indent the body, format it, re-indent it */ + FSB body = {0}; + for (int p = bs; p < be; ){ + int q = p; while (src[q] && src[q] != '\n') q++; + int skip = 0; while (skip < indent && p + skip < q && src[p + skip] == ' ') skip++; + fsb_add(&body, src + p + skip, q - (p + skip)); + fsb_putc(&body, '\n'); + p = src[q] ? q + 1 : q; + } + char* f = ludic_format(body.b ? body.b : "", indent_width); + for (char* p = f; *p; ){ + char* q = strchr(p, '\n'); if (!q) q = p + strlen(p); + if (q > p) fsb_indent(&o, indent); + fsb_add(&o, p, q - p); + fsb_putc(&o, '\n'); + p = *q ? q + 1 : q; + } + free(f); free(body.b); + i = be; + continue; + } + fsb_add(&o, src + ls, le - ls + (src[le] ? 1 : 0)); + i = src[le] ? le + 1 : le; + } + if (!o.b){ o.b = malloc(1); o.b[0] = 0; } + return o.b; +} +#endif /* LUDIC_FMT_H */ diff --git a/tools/ludic-tools/ludic_fmt_main.c b/tools/ludic-tools/ludic_fmt_main.c new file mode 100644 index 00000000..95376bb3 --- /dev/null +++ b/tools/ludic-tools/ludic_fmt_main.c @@ -0,0 +1,118 @@ +/* ============================================================================ + * ludic-fmt — the Ludic formatter, as a plain CLI. + * + * Editors call this through the language server, but CI and pre-commit hooks + * want a binary they can run: + * + * ludic-fmt a.ludic b.ludic print the formatted text + * ludic-fmt -w examples rewrite every .ludic under examples/ + * ludic-fmt --check . exit 1 if anything is unformatted + * ludic-fmt LANGUAGE.md -w reformat the ```ludic fences in a document + * cat x.ludic | ludic-fmt - filter mode, for editors without LSP + * ==========================================================================*/ +#include "ludic_fmt.h" +#include +#include +#include + +static int g_write = 0, g_check = 0, g_indent = 2, g_quiet = 0; +static int g_changed = 0, g_failed = 0; + +static char* slurp(FILE* f){ + FSB s = {0}; + char buf[65536]; size_t n; + while ((n = fread(buf, 1, sizeof(buf), f)) > 0) fsb_add(&s, buf, n); + if (!s.b){ s.b = malloc(1); s.b[0] = 0; } + return s.b; +} +static int is_md(const char* p){ + size_t n = strlen(p); + return (n > 3 && !strcmp(p + n - 3, ".md")) || (n > 9 && !strcmp(p + n - 9, ".markdown")); +} +static int is_ludic(const char* p){ + size_t n = strlen(p); + return n > 6 && !strcmp(p + n - 6, ".ludic"); +} + +static void do_file(const char* path){ + FILE* f = fopen(path, "rb"); + if (!f){ fprintf(stderr, "ludic-fmt: cannot open %s\n", path); g_failed = 1; return; } + char* src = slurp(f); fclose(f); + char* out = is_md(path) ? ludic_format_markdown(src, g_indent) : ludic_format(src, g_indent); + int same = !strcmp(src, out); + if (g_check){ + if (!same){ g_changed = 1; if (!g_quiet) printf("%s\n", path); } + } else if (g_write){ + if (!same){ + FILE* w = fopen(path, "wb"); + if (!w){ fprintf(stderr, "ludic-fmt: cannot write %s\n", path); g_failed = 1; } + else { fwrite(out, 1, strlen(out), w); fclose(w); if (!g_quiet) fprintf(stderr, "formatted %s\n", path); } + g_changed = 1; + } + } else { + fwrite(out, 1, strlen(out), stdout); + } + free(src); free(out); +} +static void do_dir(const char* dir, int depth){ + if (depth > 16) return; + DIR* d = opendir(dir); + if (!d){ fprintf(stderr, "ludic-fmt: cannot open %s\n", dir); g_failed = 1; return; } + struct dirent* e; + while ((e = readdir(d))){ + if (e->d_name[0] == '.') continue; + if (!strcmp(e->d_name, "build") || !strcmp(e->d_name, "node_modules")) continue; + char p[PATH_MAX]; snprintf(p, sizeof(p), "%s/%s", dir, e->d_name); + struct stat st; if (stat(p, &st)) continue; + if (S_ISDIR(st.st_mode)) do_dir(p, depth + 1); + else if (is_ludic(p)) do_file(p); + } + closedir(d); +} + +static const char* USAGE = +"ludic-fmt — format Ludic source\n" +"\n" +"usage: ludic-fmt [options] [file|dir ...]\n" +" ludic-fmt - read stdin, write stdout\n" +"\n" +"options:\n" +" -w, --write rewrite files in place\n" +" --check list unformatted files; exit 1 if any (implies no output)\n" +" --indent N spaces per level (default 2)\n" +" -q, --quiet no per-file chatter\n" +" -h, --help this text\n" +"\n" +"Directories are walked for *.ludic. A .md/.markdown file has the body of every\n" +"```ludic fence formatted and the prose left alone.\n"; + +int main(int argc, char** argv){ + const char* files[4096]; int nf = 0; + for (int i = 1; i < argc; i++){ + const char* a = argv[i]; + if (!strcmp(a, "-w") || !strcmp(a, "--write")) g_write = 1; + else if (!strcmp(a, "--check") || !strcmp(a, "-l")) g_check = 1; + else if (!strcmp(a, "-q") || !strcmp(a, "--quiet")) g_quiet = 1; + else if (!strcmp(a, "--indent") && i + 1 < argc) g_indent = atoi(argv[++i]); + else if (!strcmp(a, "-h") || !strcmp(a, "--help")){ fputs(USAGE, stdout); return 0; } + else if (a[0] == '-' && a[1] && strcmp(a, "-")){ fprintf(stderr, "ludic-fmt: unknown option %s\n", a); return 2; } + else if (nf < 4096) files[nf++] = a; + } + if (g_indent < 1 || g_indent > 8) g_indent = 2; + + if (nf == 0 || (nf == 1 && !strcmp(files[0], "-"))){ + char* src = slurp(stdin); + char* out = ludic_format(src, g_indent); + fwrite(out, 1, strlen(out), stdout); + free(src); free(out); + return 0; + } + for (int i = 0; i < nf; i++){ + struct stat st; + if (stat(files[i], &st)){ fprintf(stderr, "ludic-fmt: no such file %s\n", files[i]); g_failed = 1; continue; } + if (S_ISDIR(st.st_mode)) do_dir(files[i], 0); + else do_file(files[i]); + } + if (g_failed) return 2; + return (g_check && g_changed) ? 1 : 0; +} diff --git a/tools/ludic-tools/ludic_index.h b/tools/ludic-tools/ludic_index.h new file mode 100644 index 00000000..216e5aff --- /dev/null +++ b/tools/ludic-tools/ludic_index.h @@ -0,0 +1,672 @@ +/* ============================================================================ + * ludic_index.h — an error-tolerant model of a Ludic workspace. + * + * The compiler's parser is the wrong tool for an editor: it stops at the first + * error and it splices imports into one flat program. A language server needs + * the opposite — keep going after a syntax error (a file being typed into is + * broken most of the time), keep every file separate, and remember where each + * name came from so it can be jumped to, renamed and completed. + * + * So this is a second, deliberately shallow reader of the same grammar. It + * recognises declarations and bindings and records their spans; it does not + * type-check. Ground-truth errors still come from `ludicc` itself (see + * ludic_lsp.c) — this layer supplies structure, not judgement. + * ==========================================================================*/ +#ifndef LUDIC_INDEX_H +#define LUDIC_INDEX_H + +#include "ludic_syntax.h" +#include + +/* ---------- symbol kinds --------------------------------------------------*/ +enum { + LS_UNIT, LS_COMPONENT, LS_FIELD, LS_ARCHETYPE, LS_CONST, LS_VAR, + LS_FN, LS_PARAM, LS_EXTERN, LS_SYSTEM, LS_UI, LS_WIDGET, LS_SCENE, + LS_LAYER, LS_LOCAL, LS_QUERYVAR, LS_STATE, LS_IMPORT +}; + +/* semantic classes, one per token — the source for semantic highlighting */ +enum { + SC_NONE, SC_KEYWORD, SC_TYPE, SC_COMPONENT, SC_ARCHETYPE, SC_SCENE, + SC_LAYER, SC_UI, SC_WIDGET, SC_PROP, SC_FIELD, SC_SYSTEM, SC_FUNCTION, + SC_BUILTIN, SC_PARAM, SC_VARIABLE, SC_CONST, SC_MODVAR, SC_PHASE, + SC_NUMBER, SC_STRING, SC_COMMENT, SC_OPERATOR, SC_ANNOTATION, SC_UNKNOWN +}; + +typedef struct { + int kind; + char name[96]; + char type[96]; /* declared type; for a query var, its component */ + char detail[224]; /* one-line signature, shown in hover and outlines */ + char doc[640]; /* the comment block sitting directly above */ + int tok; /* token index of the NAME */ + int start, end; /* byte span of the name */ + int body_start, body_end; /* span the symbol governs (a block, or the + * whole file for a top-level declaration) */ + int parent; /* enclosing symbol index, -1 at the top level */ + int exported; +} LSym; + +typedef struct { + int line, col, endline, endcol, severity; /* 1 = error, 2 = warning */ + char msg[512]; + char path[1024]; /* empty = this document */ +} LDiag; + +typedef struct LDoc { + char* path; /* filesystem path */ + char* uri; /* file:// URI */ + char* raw; /* the buffer exactly as the editor has it */ + char* text; /* what the lexer sees: `raw`, or — for Markdown — a + * copy with every byte outside a ```ludic fence blanked + * out, so offsets still line up with the real file */ + int version; + int open; /* the editor holds it (so `text` beats the disk) */ + int is_markdown; /* a .md file: only its ```ludic fences are Ludic */ + LLex lex; + int* match; /* per token: matching brace/bracket token, else -1 */ + unsigned char* cls; /* per token: semantic class */ + LSym* sym; int nsym, symcap; + char** imports; int nimport; + int had_diags; /* we published a non-empty list for it last time */ + int is_unit; /* declares `game` or `module` */ + int is_module; + char unit[96]; +} LDoc; + +typedef struct { + LDoc** d; int n, cap; + char* root; /* workspace root directory */ +} LIndex; + +/* ---------- small helpers -------------------------------------------------*/ +static void lsym_reserve(LDoc* D){ + if (D->nsym >= D->symcap){ D->symcap = D->symcap ? D->symcap * 2 : 128; D->sym = realloc(D->sym, D->symcap * sizeof(LSym)); } +} +static void lcpy(char* dst, int cap, const char* s, int n){ + if (n >= cap) n = cap - 1; if (n < 0) n = 0; + memcpy(dst, s, n); dst[n] = 0; +} +static void lcatf(char* dst, int cap, const char* fmt, ...){ + int used = (int)strlen(dst); if (used >= cap - 1) return; + va_list ap; va_start(ap, fmt); vsnprintf(dst + used, cap - used, fmt, ap); va_end(ap); +} + +/* ---------- positions ----------------------------------------------------- + * LSP counts characters in UTF-16 code units by default. Ludic source is UTF-8 + * and string literals really do carry non-ASCII (the language ships a Unicode + * TrueType path), so the conversion is not optional. */ +static int lutf16_len(const char* s, int nbytes){ + int u = 0; + for (int i = 0; i < nbytes; ){ + unsigned char c = (unsigned char)s[i]; + if (c < 0x80){ i += 1; u += 1; } + else if (c < 0xE0){ i += 2; u += 1; } + else if (c < 0xF0){ i += 3; u += 1; } + else { i += 4; u += 2; } /* astral planes are a surrogate pair */ + } + return u; +} +static int ldoc_line_of(const LDoc* D, int off){ + int lo = 0, hi = D->lex.nline - 1; + while (lo < hi){ int mid = (lo + hi + 1) / 2; if (D->lex.linestart[mid] <= off) lo = mid; else hi = mid - 1; } + return lo; +} +static int ldoc_col_of(const LDoc* D, int off){ + int line = ldoc_line_of(D, off); + return lutf16_len(D->text + D->lex.linestart[line], off - D->lex.linestart[line]); +} +static int ldoc_offset_of(const LDoc* D, int line, int character){ + if (line < 0) return 0; + if (line >= D->lex.nline) return (int)strlen(D->text); + int off = D->lex.linestart[line]; + int end = (line + 1 < D->lex.nline) ? D->lex.linestart[line + 1] : (int)strlen(D->text); + int u = 0; + while (off < end && u < character){ + unsigned char c = (unsigned char)D->text[off]; + if (c < 0x80){ off += 1; u += 1; } + else if (c < 0xE0){ off += 2; u += 1; } + else if (c < 0xF0){ off += 3; u += 1; } + else { off += 4; u += 2; } + } + return off; +} +/* The token the cursor is on. A caret sitting exactly between two tokens + * belongs to the one it is *inside*; only when it is inside none of them does + * the token ending there win — otherwise `st.|guard` resolves to the dot. */ +static int ldoc_tok_at(const LDoc* D, int off){ + int touching = -1; + for (int i = 0; i < D->lex.n; i++){ + const LTok* t = &D->lex.v[i]; + if (t->kind == LT_NL || t->kind == LT_EOF) continue; + if (off >= t->start && off < t->end) return i; + if (off == t->end && touching < 0) touching = i; + if (t->start > off) break; + } + return touching; +} + +/* ---------- brace matching ------------------------------------------------*/ +static void ldoc_match_braces(LDoc* D){ + free(D->match); + D->match = malloc(sizeof(int) * (D->lex.n + 1)); + for (int i = 0; i < D->lex.n; i++) D->match[i] = -1; + int stack[512], top = 0; + for (int i = 0; i < D->lex.n; i++){ + const LTok* t = &D->lex.v[i]; + if (t->kind != LT_OP || ltok_len(t) != 1) continue; + char c = D->text[t->start]; + if (c == '{' || c == '(' || c == '['){ if (top < 512) stack[top++] = i; } + else if (c == '}' || c == ')' || c == ']'){ + if (top > 0){ int o = stack[--top]; D->match[o] = i; D->match[i] = o; } + } + } +} + +/* ---------- doc comments -------------------------------------------------- + * The comment block immediately above a declaration is its documentation — + * the convention the runtime and examples already follow. */ +static void ldoc_collect_doc(LDoc* D, int decl_tok, char* out, int cap){ + out[0] = 0; + int line = D->lex.v[decl_tok].line; + /* walk backwards over comment-only lines */ + int first = -1; + for (int i = decl_tok - 1; i >= 0; i--){ + const LTok* t = &D->lex.v[i]; + if (t->kind == LT_NL) continue; + if (t->kind != LT_COMMENT) break; + if (t->line >= line) break; /* trailing, not leading */ + /* the comment must own its line */ + int p = ltok_prev_sig(&D->lex, i); + if (p >= 0 && D->lex.v[p].line == t->line) break; + if (t->line < line - 1 && first >= 0) break;/* a blank line ends it */ + if (first >= 0 && D->lex.v[first].line != t->line + 1) break; + first = i; line = t->line; + } + if (first < 0) return; + for (int i = first; i < decl_tok; i++){ + const LTok* t = &D->lex.v[i]; + if (t->kind != LT_COMMENT) continue; + int s = t->start + 1; /* skip '#' */ + while (s < t->end && (D->text[s] == ' ' || D->text[s] == '\t' || D->text[s] == '#' || D->text[s] == '*')) s++; + int used = (int)strlen(out); + int n = t->end - s; + if (used + n + 2 >= cap) break; + memcpy(out + used, D->text + s, n); out[used + n] = '\n'; out[used + n + 1] = 0; + } +} + +/* ---------- the shallow parser -------------------------------------------*/ +typedef struct { LDoc* D; int i; } LP; + +static int lp_kind(LP* p){ return p->i < p->D->lex.n ? p->D->lex.v[p->i].kind : LT_EOF; } +static int lp_is(LP* p, const char* s){ return ltok_is(&p->D->lex, p->i, s); } +static void lp_skipnl(LP* p){ while (p->i < p->D->lex.n && (lp_kind(p) == LT_NL || lp_kind(p) == LT_COMMENT)) p->i++; } +static void lp_adv(LP* p){ if (p->i < p->D->lex.n) p->i++; lp_skipnl(p); } +static char* lp_word(LP* p, char* buf, int cap){ + buf[0] = 0; + if (p->i < p->D->lex.n) lcpy(buf, cap, p->D->text + p->D->lex.v[p->i].start, ltok_len(&p->D->lex.v[p->i])); + return buf; +} +/* Consume an identifier-ish token, returning its index (or -1). */ +static int lp_name(LP* p){ + int k = lp_kind(p); + if (k == LT_ID || k == LT_TYPE || k == LT_PHASE || k == LT_KW || k == LT_BOOL){ int t = p->i; lp_adv(p); return t; } + return -1; +} +static int lsym_add(LDoc* D, int kind, int nametok, int parent){ + lsym_reserve(D); + LSym* s = &D->sym[D->nsym]; + memset(s, 0, sizeof(*s)); + s->kind = kind; s->tok = nametok; s->parent = parent; + if (nametok >= 0){ + const LTok* t = &D->lex.v[nametok]; + s->start = t->start; s->end = t->end; + lcpy(s->name, sizeof(s->name), D->text + t->start, ltok_len(t)); + } + s->body_start = 0; s->body_end = (int)strlen(D->text); + return D->nsym++; +} +/* Skip a balanced group starting at the current opener; leaves p after it. */ +static void lp_skip_group(LP* p){ + int m = (p->i < p->D->lex.n) ? p->D->match[p->i] : -1; + if (m < 0){ lp_adv(p); return; } + p->i = m + 1; lp_skipnl(p); +} +/* Read `name: Type` pairs inside the parentheses at p->i, recording params. */ +static void lp_params(LP* p, int owner, int kind, char* sig, int sigcap){ + if (!lp_is(p, "(")) return; + int close = p->D->match[p->i]; + lcatf(sig, sigcap, "("); + lp_adv(p); + int first = 1; + while (p->i < p->D->lex.n && (close < 0 || p->i < close)){ + if (lp_is(p, ")")) break; + if (lp_is(p, ",")){ lp_adv(p); continue; } + int nt = lp_name(p); if (nt < 0){ lp_adv(p); continue; } + char ty[96]; ty[0] = 0; + if (lp_is(p, ":")){ lp_adv(p); int tt = lp_name(p); if (tt >= 0) lcpy(ty, sizeof(ty), p->D->text + p->D->lex.v[tt].start, ltok_len(&p->D->lex.v[tt])); } + int s = lsym_add(p->D, kind, nt, owner); + lcpy(p->D->sym[s].type, sizeof(p->D->sym[s].type), ty, (int)strlen(ty)); + lcatf(sig, sigcap, "%s%s: %s", first ? "" : ", ", p->D->sym[s].name, ty[0] ? ty : "?"); + first = 0; + } + if (close >= 0) p->i = close + 1; + lp_skipnl(p); + lcatf(sig, sigcap, ")"); +} +/* `[Pos, Vel, {Enemy}]` — bind the listed components to the named variables in + * order, skipping {Tag} terms, which filter without binding. */ +static void lp_query_terms(LP* p, int owner, int* vars, int nvars, int scope_start, int scope_end){ + if (!lp_is(p, "[")) return; + int close = p->D->match[p->i]; + lp_adv(p); + int bind = 0; + while (p->i < p->D->lex.n && (close < 0 || p->i < close)){ + if (lp_is(p, "]")) break; + if (lp_is(p, ",")){ lp_adv(p); continue; } + if (lp_is(p, "{")){ /* a filter term */ + int cb = p->D->match[p->i]; lp_adv(p); + int nt = lp_name(p); (void)nt; + if (cb >= 0) p->i = cb + 1; else lp_adv(p); + lp_skipnl(p); continue; + } + int nt = lp_name(p); if (nt < 0){ lp_adv(p); continue; } + if (bind < nvars && vars[bind] >= 0){ + int s = lsym_add(p->D, LS_QUERYVAR, vars[bind], owner); + lcpy(p->D->sym[s].type, sizeof(p->D->sym[s].type), p->D->text + p->D->lex.v[nt].start, ltok_len(&p->D->lex.v[nt])); + p->D->sym[s].body_start = scope_start; p->D->sym[s].body_end = scope_end; + lcatf(p->D->sym[s].detail, sizeof(p->D->sym[s].detail), "%s: %s (query binding)", p->D->sym[s].name, p->D->sym[s].type); + } + bind++; + } + if (close >= 0) p->i = close + 1; + lp_skipnl(p); + if (lp_is(p, "where")) lp_adv(p); /* the condition is ordinary expression */ +} +/* `(a, b)` variable list before `in query` / after the `query` clause. */ +static int lp_varlist(LP* p, int* out, int max){ + int n = 0; + if (!lp_is(p, "(")) return 0; + int close = p->D->match[p->i]; + lp_adv(p); + while (p->i < p->D->lex.n && (close < 0 || p->i < close)){ + if (lp_is(p, ")")) break; + if (lp_is(p, ",")){ lp_adv(p); continue; } + int nt = lp_name(p); if (nt < 0){ lp_adv(p); continue; } + if (n < max) out[n++] = nt; + } + if (close >= 0) p->i = close + 1; + lp_skipnl(p); + return n; +} + +static void lp_block(LP* p, int owner, int scope_end); + +/* statements — we only care about what BINDS a name or opens a scope */ +static void lp_stmt(LP* p, int owner, int scope_end){ + LDoc* D = p->D; + if (lp_is(p, "let")){ + lp_adv(p); int nt = lp_name(p); if (nt < 0) return; + char ty[96]; ty[0] = 0; + if (lp_is(p, ":")){ lp_adv(p); int tt = lp_name(p); if (tt >= 0) lcpy(ty, sizeof(ty), D->text + D->lex.v[tt].start, ltok_len(&D->lex.v[tt])); } + int s = lsym_add(D, LS_LOCAL, nt, owner); + lcpy(D->sym[s].type, sizeof(D->sym[s].type), ty, (int)strlen(ty)); + D->sym[s].body_start = D->lex.v[nt].start; D->sym[s].body_end = scope_end; + return; + } + if (lp_is(p, "for")){ + lp_adv(p); + if (lp_is(p, "(")){ /* for (a, b) in query [...] */ + int vars[16]; int nv = lp_varlist(p, vars, 16); + if (lp_is(p, "in")) lp_adv(p); + if (lp_is(p, "query")) lp_adv(p); + int body_end = scope_end; + /* the loop body is the next {...}; bindings live there */ + lp_query_terms(p, owner, vars, nv, D->lex.v[p->i < D->lex.n ? p->i : D->lex.n - 1].start, body_end); + return; + } + int nt = lp_name(p); /* for i in a .. b */ + if (nt >= 0){ + int s = lsym_add(D, LS_LOCAL, nt, owner); + lcpy(D->sym[s].type, sizeof(D->sym[s].type), "int", 3); + D->sym[s].body_start = D->lex.v[nt].start; D->sym[s].body_end = scope_end; + } + return; + } + if (lp_is(p, "state")){ /* machine { state Idle = 0 {…} } */ + lp_adv(p); int nt = lp_name(p); + if (nt >= 0) lsym_add(D, LS_STATE, nt, owner); + return; + } + lp_adv(p); +} + +static void lp_block(LP* p, int owner, int scope_end){ + if (!lp_is(p, "{")) return; + int close = p->D->match[p->i]; + int end = close >= 0 ? p->D->lex.v[close].start : scope_end; + lp_adv(p); + while (p->i < p->D->lex.n && lp_kind(p) != LT_EOF){ + if (close >= 0 && p->i >= close) break; + if (lp_is(p, "}")) break; + if (lp_is(p, "{")){ lp_block(p, owner, end); continue; } + int before = p->i; + lp_stmt(p, owner, end); + if (p->i == before) lp_adv(p); + } + if (close >= 0) p->i = close + 1; else lp_adv(p); + lp_skipnl(p); +} + +/* `panel id=Root w=288 { … }` — each id= mints a UI_ handle. */ +static void lp_widget(LP* p, int owner, int uisym){ + LDoc* D = p->D; + int type_tok = lp_name(p); if (type_tok < 0) return; + while (p->i < D->lex.n && lp_kind(p) == LT_ID && ltok_is(&D->lex, ltok_next_sig(&D->lex, p->i) < 0 ? p->i : ltok_next_sig(&D->lex, p->i), "=")){ + int key = p->i; char kb[64]; lcpy(kb, sizeof(kb), D->text + D->lex.v[key].start, ltok_len(&D->lex.v[key])); + lp_adv(p); /* key */ + if (lp_is(p, "=")) lp_adv(p); /* '=' */ + if (!strcmp(kb, "id")){ + int nt = lp_name(p); + if (nt >= 0){ + int s = lsym_add(D, LS_WIDGET, nt, uisym); + snprintf(D->sym[s].name, sizeof(D->sym[s].name), "UI_%.*s", + ltok_len(&D->lex.v[nt]), D->text + D->lex.v[nt].start); + lcatf(D->sym[s].detail, sizeof(D->sym[s].detail), "%s widget handle", + (const char*)(D->text + D->lex.v[type_tok].start)); + lcpy(D->sym[s].type, sizeof(D->sym[s].type), "int", 3); + } + } else { + /* skip one value expression: stop at the next `key=` or at a brace */ + while (p->i < D->lex.n && lp_kind(p) != LT_EOF && !lp_is(p, "{") && !lp_is(p, "}")){ + if (lp_is(p, "(") || lp_is(p, "[")){ lp_skip_group(p); continue; } + int nx = ltok_next_sig(&D->lex, p->i); + if (lp_kind(p) == LT_ID && nx >= 0 && ltok_is(&D->lex, nx, "=")) break; + lp_adv(p); + } + } + } + if (lp_is(p, "{")){ + int close = D->match[p->i]; + lp_adv(p); + while (p->i < D->lex.n && lp_kind(p) != LT_EOF && !lp_is(p, "}")){ + if (close >= 0 && p->i >= close) break; + int before = p->i; + lp_widget(p, owner, uisym); + if (p->i == before) lp_adv(p); + } + if (close >= 0) p->i = close + 1; else lp_adv(p); + lp_skipnl(p); + } +} + +/* one top-level declaration */ +static void lp_decl(LP* p, int parent){ + LDoc* D = p->D; + char w[96]; lp_word(p, w, sizeof(w)); + int decl_tok = p->i; + + if (!strcmp(w, "import")){ + lp_adv(p); + if (lp_kind(p) == LT_STR){ + const LTok* t = &D->lex.v[p->i]; + int n = ltok_len(t) - 2; if (n < 0) n = 0; + char* rel = malloc(n + 1); memcpy(rel, D->text + t->start + 1, n); rel[n] = 0; + D->imports = realloc(D->imports, (D->nimport + 1) * sizeof(char*)); + D->imports[D->nimport++] = rel; + int s = lsym_add(D, LS_IMPORT, p->i, parent); + lcpy(D->sym[s].name, sizeof(D->sym[s].name), rel, (int)strlen(rel)); + lp_adv(p); + } + return; + } + if (!strcmp(w, "component") || !strcmp(w, "archetype")){ + int is_comp = !strcmp(w, "component"); + lp_adv(p); int nt = lp_name(p); if (nt < 0) return; + int s = lsym_add(D, is_comp ? LS_COMPONENT : LS_ARCHETYPE, nt, parent); + ldoc_collect_doc(D, decl_tok, D->sym[s].doc, sizeof(D->sym[s].doc)); + while (lp_kind(p) == LT_ANNO) lp_adv(p); + snprintf(D->sym[s].detail, sizeof(D->sym[s].detail), "%s %s {", + is_comp ? "component" : "archetype", D->sym[s].name); + if (!lp_is(p, "{")) return; + int close = D->match[p->i]; + D->sym[s].body_start = D->lex.v[p->i].start; + D->sym[s].body_end = close >= 0 ? D->lex.v[close].end : (int)strlen(D->text); + lp_adv(p); + int first = 1; + while (p->i < D->lex.n && lp_kind(p) != LT_EOF && !lp_is(p, "}")){ + if (close >= 0 && p->i >= close) break; + if (lp_is(p, ",")){ lp_adv(p); continue; } + int ft = lp_name(p); if (ft < 0){ lp_adv(p); continue; } + if (is_comp){ + int f = lsym_add(D, LS_FIELD, ft, s); + if (lp_is(p, ":")){ + lp_adv(p); int tt = lp_name(p); + if (tt >= 0) lcpy(D->sym[f].type, sizeof(D->sym[f].type), D->text + D->lex.v[tt].start, ltok_len(&D->lex.v[tt])); + } + lcatf(D->sym[f].detail, sizeof(D->sym[f].detail), "%s.%s: %s", D->sym[s].name, D->sym[f].name, D->sym[f].type); + if (lp_is(p, "=")){ lp_adv(p); while (p->i < D->lex.n && !lp_is(p, ",") && !lp_is(p, "}") && lp_kind(p) != LT_EOF){ if (lp_is(p, "(") || lp_is(p, "{") || lp_is(p, "[")) lp_skip_group(p); else lp_adv(p); } } + lcatf(D->sym[s].detail, sizeof(D->sym[s].detail), "%s %s: %s", first ? "" : ",", D->sym[f].name, D->sym[f].type); + } else { + lcatf(D->sym[s].detail, sizeof(D->sym[s].detail), "%s %.*s", first ? "" : ",", + ltok_len(&D->lex.v[ft]), D->text + D->lex.v[ft].start); + } + first = 0; + } + lcatf(D->sym[s].detail, sizeof(D->sym[s].detail), " }"); + if (close >= 0) p->i = close + 1; else lp_adv(p); + lp_skipnl(p); + return; + } + if (!strcmp(w, "const") || !strcmp(w, "var")){ + int kind = !strcmp(w, "const") ? LS_CONST : LS_VAR; + lp_adv(p); int nt = lp_name(p); if (nt < 0) return; + int s = lsym_add(D, kind, nt, parent); + ldoc_collect_doc(D, decl_tok, D->sym[s].doc, sizeof(D->sym[s].doc)); + if (lp_is(p, ":")){ lp_adv(p); int tt = lp_name(p); if (tt >= 0) lcpy(D->sym[s].type, sizeof(D->sym[s].type), D->text + D->lex.v[tt].start, ltok_len(&D->lex.v[tt])); } + lcatf(D->sym[s].detail, sizeof(D->sym[s].detail), "%s %s: %s", w, D->sym[s].name, D->sym[s].type); + while (p->i < D->lex.n && lp_kind(p) != LT_NL && lp_kind(p) != LT_EOF){ + if (lp_is(p, "(") || lp_is(p, "{") || lp_is(p, "[")) lp_skip_group(p); else p->i++; + } + lp_skipnl(p); + return; + } + if (!strcmp(w, "extern")){ + lp_adv(p); if (lp_is(p, "fn")) lp_adv(p); + int nt = lp_name(p); if (nt < 0) return; + int s = lsym_add(D, LS_EXTERN, nt, parent); + ldoc_collect_doc(D, decl_tok, D->sym[s].doc, sizeof(D->sym[s].doc)); + char sig[224]; snprintf(sig, sizeof(sig), "extern fn %s", D->sym[s].name); + lp_params(p, s, LS_PARAM, sig, sizeof(sig)); + if (lp_is(p, "->")){ lp_adv(p); int tt = lp_name(p); if (tt >= 0){ lcpy(D->sym[s].type, sizeof(D->sym[s].type), D->text + D->lex.v[tt].start, ltok_len(&D->lex.v[tt])); lcatf(sig, sizeof(sig), " -> %s", D->sym[s].type); } } + lcpy(D->sym[s].detail, sizeof(D->sym[s].detail), sig, (int)strlen(sig)); + while (p->i < D->lex.n && lp_kind(p) != LT_NL && lp_kind(p) != LT_EOF) p->i++; + lp_skipnl(p); + return; + } + if (!strcmp(w, "fn") || !strcmp(w, "pure") || !strcmp(w, "export")){ + int exported = !strcmp(w, "export"); + if (!strcmp(w, "pure") || exported){ lp_adv(p); if (lp_is(p, "pure")) lp_adv(p); } + if (lp_is(p, "fn")) lp_adv(p); + int nt = lp_name(p); if (nt < 0) return; + int s = lsym_add(D, LS_FN, nt, parent); + D->sym[s].exported = exported; + ldoc_collect_doc(D, decl_tok, D->sym[s].doc, sizeof(D->sym[s].doc)); + char sig[224]; snprintf(sig, sizeof(sig), "%sfn %s", exported ? "export " : "", D->sym[s].name); + lp_params(p, s, LS_PARAM, sig, sizeof(sig)); + if (lp_is(p, "->")){ lp_adv(p); int tt = lp_name(p); if (tt >= 0) lcpy(D->sym[s].type, sizeof(D->sym[s].type), D->text + D->lex.v[tt].start, ltok_len(&D->lex.v[tt])); } + lcatf(sig, sizeof(sig), " -> %s", D->sym[s].type[0] ? D->sym[s].type : "void"); + lcpy(D->sym[s].detail, sizeof(D->sym[s].detail), sig, (int)strlen(sig)); + /* contracts sit between the signature and the body */ + while (lp_is(p, "requires") || lp_is(p, "ensures") || lp_is(p, "invariant") || lp_is(p, "effects")){ + lp_adv(p); + while (p->i < D->lex.n && lp_kind(p) != LT_NL && lp_kind(p) != LT_EOF && !lp_is(p, "{")){ + if (lp_is(p, "(") || lp_is(p, "[")) lp_skip_group(p); else p->i++; + } + lp_skipnl(p); + } + if (lp_is(p, "{")){ + int close = D->match[p->i]; + D->sym[s].body_start = D->lex.v[p->i].start; + D->sym[s].body_end = close >= 0 ? D->lex.v[close].end : (int)strlen(D->text); + /* params are visible for the whole body */ + for (int q = 0; q < D->nsym; q++) if (D->sym[q].parent == s && D->sym[q].kind == LS_PARAM){ + D->sym[q].body_start = D->sym[s].body_start; D->sym[q].body_end = D->sym[s].body_end; + } + lp_block(p, s, D->sym[s].body_end); + } + return; + } + if (!strcmp(w, "system") || !strcmp(w, "edge")){ + if (!strcmp(w, "edge")){ lp_adv(p); if (!lp_is(p, "system")) return; } + lp_adv(p); + int nt = lp_name(p); if (nt < 0) return; + int s = lsym_add(D, LS_SYSTEM, nt, parent); + ldoc_collect_doc(D, decl_tok, D->sym[s].doc, sizeof(D->sym[s].doc)); + lcpy(D->sym[s].type, sizeof(D->sym[s].type), "Update", 6); + while (lp_kind(p) == LT_ANNO) lp_adv(p); + int vars[16]; int nv = 0; int have_query = 0; + for (;;){ + if (lp_is(p, "phase")){ lp_adv(p); int tt = lp_name(p); if (tt >= 0) lcpy(D->sym[s].type, sizeof(D->sym[s].type), D->text + D->lex.v[tt].start, ltok_len(&D->lex.v[tt])); } + else if (lp_is(p, "query")){ lp_adv(p); have_query = 1; nv = lp_varlist(p, vars, 16); break; } + else if (lp_is(p, "reads") || lp_is(p, "writes") || lp_is(p, "uses") || lp_is(p, "effects")){ lp_adv(p); if (lp_is(p, "[")) lp_skip_group(p); } + else if (lp_is(p, "needs")){ lp_adv(p); lp_name(p); if (lp_is(p, "[")) lp_skip_group(p); } + else break; + lp_skipnl(p); + } + lcatf(D->sym[s].detail, sizeof(D->sym[s].detail), "system %s phase %s", D->sym[s].name, D->sym[s].type); + /* find the body first, so query bindings can be scoped to it */ + int body_open = p->i; + if (have_query){ + int save = p->i; + /* the query terms come before the body */ + int scan = p->i; + while (scan < D->lex.n && !ltok_is(&D->lex, scan, "{") && D->lex.v[scan].kind != LT_EOF) scan++; + int close = (scan < D->lex.n) ? D->match[scan] : -1; + int bs = (scan < D->lex.n) ? D->lex.v[scan].start : 0; + int be = close >= 0 ? D->lex.v[close].end : (int)strlen(D->text); + p->i = save; + lp_query_terms(p, s, vars, nv, bs, be); + body_open = p->i; + } + (void)body_open; + if (lp_is(p, "{")){ + int close = D->match[p->i]; + D->sym[s].body_start = D->lex.v[p->i].start; + D->sym[s].body_end = close >= 0 ? D->lex.v[close].end : (int)strlen(D->text); + lp_block(p, s, D->sym[s].body_end); + } + return; + } + if (!strcmp(w, "ui")){ + lp_adv(p); int nt = lp_name(p); if (nt < 0) return; + int s = lsym_add(D, LS_UI, nt, parent); + ldoc_collect_doc(D, decl_tok, D->sym[s].doc, sizeof(D->sym[s].doc)); + lcatf(D->sym[s].detail, sizeof(D->sym[s].detail), "ui %s", D->sym[s].name); + /* the block name is a handle too */ + { int h = lsym_add(D, LS_WIDGET, nt, s); + snprintf(D->sym[h].name, sizeof(D->sym[h].name), "UI_%s", D->sym[s].name); + lcpy(D->sym[h].type, sizeof(D->sym[h].type), "int", 3); + lcatf(D->sym[h].detail, sizeof(D->sym[h].detail), "root handle of ui %s", D->sym[s].name); } + if (lp_is(p, "{")){ + int close = D->match[p->i]; + D->sym[s].body_start = D->lex.v[p->i].start; + D->sym[s].body_end = close >= 0 ? D->lex.v[close].end : (int)strlen(D->text); + lp_adv(p); + while (p->i < D->lex.n && lp_kind(p) != LT_EOF && !lp_is(p, "}")){ + if (close >= 0 && p->i >= close) break; + int before = p->i; + lp_widget(p, s, s); + if (p->i == before) lp_adv(p); + } + if (close >= 0) p->i = close + 1; else lp_adv(p); + lp_skipnl(p); + } + return; + } + if (!strcmp(w, "scene")){ + lp_adv(p); int nt = lp_name(p); if (nt < 0) return; + int s = lsym_add(D, LS_SCENE, nt, parent); + ldoc_collect_doc(D, decl_tok, D->sym[s].doc, sizeof(D->sym[s].doc)); + int start = 0; + if (lp_is(p, "start")){ start = 1; lp_adv(p); } + lcatf(D->sym[s].detail, sizeof(D->sym[s].detail), "scene %s%s", D->sym[s].name, start ? " start" : ""); + if (lp_is(p, "{")){ + int close = D->match[p->i]; + D->sym[s].body_start = D->lex.v[p->i].start; + D->sym[s].body_end = close >= 0 ? D->lex.v[close].end : (int)strlen(D->text); + lp_adv(p); + while (p->i < D->lex.n && lp_kind(p) != LT_EOF && !lp_is(p, "}")){ + if (close >= 0 && p->i >= close) break; + int before = p->i; + if (lp_is(p, "on")){ lp_adv(p); lp_name(p); lp_block(p, s, D->sym[s].body_end); } + else if (lp_is(p, "layer")){ + lp_adv(p); int lt = lp_name(p); + int ls = lt >= 0 ? lsym_add(D, LS_LAYER, lt, s) : -1; + if (ls >= 0) lcatf(D->sym[ls].detail, sizeof(D->sym[ls].detail), "layer %s of scene %s", D->sym[ls].name, D->sym[s].name); + if (lp_is(p, "{")){ + int lc = D->match[p->i]; + if (ls >= 0){ D->sym[ls].body_start = D->lex.v[p->i].start; D->sym[ls].body_end = lc >= 0 ? D->lex.v[lc].end : D->sym[s].body_end; } + lp_adv(p); + while (p->i < D->lex.n && lp_kind(p) != LT_EOF && !lp_is(p, "}")){ + if (lc >= 0 && p->i >= lc) break; + int b2 = p->i; lp_decl(p, ls >= 0 ? ls : s); + if (p->i == b2) lp_adv(p); + } + if (lc >= 0) p->i = lc + 1; else lp_adv(p); + lp_skipnl(p); + } + } else lp_adv(p); + if (p->i == before) lp_adv(p); + } + if (close >= 0) p->i = close + 1; else lp_adv(p); + lp_skipnl(p); + } + return; + } + lp_adv(p); +} + +static void ldoc_parse(LDoc* D){ + D->nsym = 0; + for (int i = 0; i < D->nimport; i++) free(D->imports[i]); + free(D->imports); D->imports = 0; D->nimport = 0; + D->is_unit = 0; D->is_module = 0; D->unit[0] = 0; + + LP p = { D, 0 }; + lp_skipnl(&p); + while (lp_is(&p, "import")) { lp_decl(&p, -1); lp_skipnl(&p); } + int unit_parent = -1; + if (lp_is(&p, "game") || lp_is(&p, "module")){ + D->is_module = lp_is(&p, "module"); + D->is_unit = 1; + lp_adv(&p); + int nt = lp_name(&p); + if (nt >= 0){ + unit_parent = lsym_add(D, LS_UNIT, nt, -1); + lcpy(D->unit, sizeof(D->unit), D->sym[unit_parent].name, (int)strlen(D->sym[unit_parent].name)); + lcatf(D->sym[unit_parent].detail, sizeof(D->sym[unit_parent].detail), "%s %s", D->is_module ? "module" : "game", D->unit); + } + if (lp_is(&p, "{")){ + int close = D->match[p.i]; + if (unit_parent >= 0){ + D->sym[unit_parent].body_start = D->lex.v[p.i].start; + D->sym[unit_parent].body_end = close >= 0 ? D->lex.v[close].end : (int)strlen(D->text); + } + lp_adv(&p); + while (p.i < D->lex.n && lp_kind(&p) != LT_EOF && !lp_is(&p, "}")){ + if (close >= 0 && p.i >= close) break; + int before = p.i; lp_decl(&p, unit_parent); + if (p.i == before) lp_adv(&p); + } + } + return; + } + /* A fragment: an imported file is a bare list of declarations. */ + while (p.i < D->lex.n && lp_kind(&p) != LT_EOF){ + int before = p.i; lp_decl(&p, -1); + if (p.i == before) lp_adv(&p); + } +} +#endif /* LUDIC_INDEX_H */ diff --git a/tools/ludic-tools/ludic_json.h b/tools/ludic-tools/ludic_json.h new file mode 100644 index 00000000..0aee150a --- /dev/null +++ b/tools/ludic-tools/ludic_json.h @@ -0,0 +1,191 @@ +/* ============================================================================ + * ludic_json.h — just enough JSON for LSP, and no dependencies. + * + * The rest of this toolchain is C with no third-party libraries, and the + * language server should not be the thing that drags a package manager into a + * project whose whole premise is a self-contained native pipeline. This is a + * recursive-descent reader and an escaping writer; nothing more. + * ==========================================================================*/ +#ifndef LUDIC_JSON_H +#define LUDIC_JSON_H + +#include +#include +#include +#include +#include + +enum { JNULL, JBOOL, JNUM, JSTR, JARR, JOBJ }; + +typedef struct JVal JVal; +struct JVal { + int t; + double num; + int b; + char* s; /* JSTR: decoded UTF-8 */ + JVal** kids; char** keys; int n, cap; +}; + +static JVal* jnew(int t){ JVal* v = calloc(1, sizeof(JVal)); v->t = t; return v; } +static void jfree(JVal* v){ + if (!v) return; + for (int i = 0; i < v->n; i++){ jfree(v->kids[i]); free(v->keys ? v->keys[i] : 0); } + free(v->kids); free(v->keys); free(v->s); free(v); +} +static void jpush(JVal* v, const char* key, JVal* kid){ + if (v->n >= v->cap){ + v->cap = v->cap ? v->cap * 2 : 8; + v->kids = realloc(v->kids, v->cap * sizeof(JVal*)); + v->keys = realloc(v->keys, v->cap * sizeof(char*)); + } + v->keys[v->n] = key ? strdup(key) : 0; + v->kids[v->n++] = kid; +} + +static void jskip(const char** p){ while (**p == ' ' || **p == '\t' || **p == '\n' || **p == '\r') (*p)++; } +static JVal* jparse_at(const char** p); + +static void jutf8(char** o, unsigned cp){ + if (cp < 0x80) *(*o)++ = (char)cp; + else if (cp < 0x800){ *(*o)++ = (char)(0xC0 | (cp >> 6)); *(*o)++ = (char)(0x80 | (cp & 63)); } + else if (cp < 0x10000){ *(*o)++ = (char)(0xE0 | (cp >> 12)); *(*o)++ = (char)(0x80 | ((cp >> 6) & 63)); *(*o)++ = (char)(0x80 | (cp & 63)); } + else { *(*o)++ = (char)(0xF0 | (cp >> 18)); *(*o)++ = (char)(0x80 | ((cp >> 12) & 63)); *(*o)++ = (char)(0x80 | ((cp >> 6) & 63)); *(*o)++ = (char)(0x80 | (cp & 63)); } +} +static char* jparse_string(const char** p){ + if (**p != '"') return 0; + (*p)++; + const char* s = *p; + size_t cap = strlen(s) + 1; + char* out = malloc(cap); char* o = out; + while (**p && **p != '"'){ + if (**p == '\\'){ + (*p)++; + char c = **p; (*p)++; + switch (c){ + case 'n': *o++ = '\n'; break; + case 't': *o++ = '\t'; break; + case 'r': *o++ = '\r'; break; + case 'b': *o++ = '\b'; break; + case 'f': *o++ = '\f'; break; + case 'u': { + unsigned cp = (unsigned)strtoul((char[5]){ (*p)[0], (*p)[1], (*p)[2], (*p)[3], 0 }, 0, 16); + *p += 4; + if (cp >= 0xD800 && cp < 0xDC00 && (*p)[0] == '\\' && (*p)[1] == 'u'){ + unsigned lo = (unsigned)strtoul((char[5]){ (*p)[2], (*p)[3], (*p)[4], (*p)[5], 0 }, 0, 16); + *p += 6; + cp = 0x10000 + ((cp - 0xD800) << 10) + (lo - 0xDC00); + } + jutf8(&o, cp); + break; + } + default: *o++ = c; + } + } else *o++ = *(*p)++; + } + if (**p == '"') (*p)++; + *o = 0; + return out; +} +static JVal* jparse_at(const char** p){ + jskip(p); + char c = **p; + if (c == '{'){ + (*p)++; JVal* v = jnew(JOBJ); + for (;;){ + jskip(p); + if (**p == '}'){ (*p)++; break; } + char* k = jparse_string(p); + jskip(p); if (**p == ':') (*p)++; + JVal* kid = jparse_at(p); + jpush(v, k ? k : "", kid); + free(k); + jskip(p); + if (**p == ',') (*p)++; + else if (**p == '}'){ (*p)++; break; } + else if (!**p) break; + } + return v; + } + if (c == '['){ + (*p)++; JVal* v = jnew(JARR); + for (;;){ + jskip(p); + if (**p == ']'){ (*p)++; break; } + jpush(v, 0, jparse_at(p)); + jskip(p); + if (**p == ',') (*p)++; + else if (**p == ']'){ (*p)++; break; } + else if (!**p) break; + } + return v; + } + if (c == '"'){ JVal* v = jnew(JSTR); v->s = jparse_string(p); return v; } + if (!strncmp(*p, "true", 4)){ *p += 4; JVal* v = jnew(JBOOL); v->b = 1; return v; } + if (!strncmp(*p, "false", 5)){ *p += 5; JVal* v = jnew(JBOOL); v->b = 0; return v; } + if (!strncmp(*p, "null", 4)){ *p += 4; return jnew(JNULL); } + { char* end; double d = strtod(*p, &end); if (end != *p){ *p = end; JVal* v = jnew(JNUM); v->num = d; return v; } } + (*p)++; /* unparsable: step past it */ + return jnew(JNULL); +} +static JVal* jparse(const char* text){ const char* p = text; return jparse_at(&p); } + +static JVal* jget(JVal* v, const char* key){ + if (!v || v->t != JOBJ) return 0; + for (int i = 0; i < v->n; i++) if (v->keys[i] && !strcmp(v->keys[i], key)) return v->kids[i]; + return 0; +} +static JVal* jat(JVal* v, int i){ return (v && i >= 0 && i < v->n) ? v->kids[i] : 0; } +static const char* jstr(JVal* v, const char* def){ return (v && v->t == JSTR && v->s) ? v->s : def; } +static int jint(JVal* v, int def){ return (v && v->t == JNUM) ? (int)v->num : def; } +static int jbool(JVal* v, int def){ return v ? (v->t == JBOOL ? v->b : (v->t == JNUM ? v->num != 0 : def)) : def; } +/* dotted lookup: jpath(msg, "params.textDocument.uri") */ +static JVal* jpath(JVal* v, const char* path){ + char buf[256]; snprintf(buf, sizeof(buf), "%s", path); + char* save = 0; + for (char* tok = strtok_r(buf, ".", &save); tok; tok = strtok_r(0, ".", &save)){ + v = jget(v, tok); + if (!v) return 0; + } + return v; +} + +/* ---------- writing -------------------------------------------------------*/ +typedef struct { char* b; size_t n, cap; } JSB; +static void jsb_ensure(JSB* s, size_t add){ + if (s->n + add + 1 > s->cap){ s->cap = (s->n + add + 1) * 2; s->b = realloc(s->b, s->cap); } +} +static void jsb_add(JSB* s, const char* z, size_t l){ jsb_ensure(s, l); memcpy(s->b + s->n, z, l); s->n += l; s->b[s->n] = 0; } +static void jsb_puts(JSB* s, const char* z){ jsb_add(s, z, strlen(z)); } +static void jsb_putc(JSB* s, char c){ jsb_add(s, &c, 1); } +static void jsb_putf(JSB* s, const char* fmt, ...){ + char tmp[1024]; + va_list ap; va_start(ap, fmt); + int n = vsnprintf(tmp, sizeof(tmp), fmt, ap); + va_end(ap); + if (n < (int)sizeof(tmp)){ jsb_add(s, tmp, n); return; } + char* big = malloc(n + 1); + va_start(ap, fmt); vsnprintf(big, n + 1, fmt, ap); va_end(ap); + jsb_add(s, big, n); free(big); +} +/* Escape a UTF-8 string as a JSON string literal, quotes included. */ +static void jsb_str(JSB* s, const char* z){ + jsb_putc(s, '"'); + if (!z) z = ""; + for (const unsigned char* p = (const unsigned char*)z; *p; p++){ + switch (*p){ + case '"': jsb_puts(s, "\\\""); break; + case '\\': jsb_puts(s, "\\\\"); break; + case '\n': jsb_puts(s, "\\n"); break; + case '\r': jsb_puts(s, "\\r"); break; + case '\t': jsb_puts(s, "\\t"); break; + default: + if (*p < 0x20) jsb_putf(s, "\\u%04x", *p); + else jsb_putc(s, (char)*p); + } + } + jsb_putc(s, '"'); +} +static void jsb_kv_str(JSB* s, const char* k, const char* v){ jsb_str(s, k); jsb_putc(s, ':'); jsb_str(s, v); } +static void jsb_kv_int(JSB* s, const char* k, long v){ jsb_str(s, k); jsb_putf(s, ":%ld", v); } +static void jsb_kv_bool(JSB* s, const char* k, int v){ jsb_str(s, k); jsb_puts(s, v ? ":true" : ":false"); } +#endif /* LUDIC_JSON_H */ diff --git a/tools/ludic-tools/ludic_lsp.c b/tools/ludic-tools/ludic_lsp.c new file mode 100644 index 00000000..9a2099a8 --- /dev/null +++ b/tools/ludic-tools/ludic_lsp.c @@ -0,0 +1,1265 @@ +/* ============================================================================ + * ludic-lsp — the Ludic language server. + * + * Speaks LSP 3.17 over stdio, so it is the IDE-agnostic half of this toolchain: + * VS Code, JetBrains, Neovim, Helix, Emacs, Sublime and Zed all drive the same + * binary, and an editor nobody has written a plugin for yet still gets + * completion, diagnostics, hover and formatting by pointing at it. + * + * It answers structural questions itself (from ludic_index.h, which keeps + * parsing after an error the way a compiler must not), and defers questions of + * correctness to `ludicc` — the compiler stays the single source of truth about + * whether a program is valid. + * + * Markdown is a first-class input: a ```ludic fence in a .md gets the same + * highlighting, hover and diagnostics as a .ludic file. + * ==========================================================================*/ +#define _GNU_SOURCE +#include "ludic_workspace.h" +#include "ludic_fmt.h" +#include "ludic_json.h" +#include + +/* ---------- server state --------------------------------------------------*/ +static LIndex X; +static char* g_ludicc = 0; /* path to the compiler, if we found one */ +static int g_indent = 2; +static int g_compiler_diags = 1; +static int g_shutdown = 0; +static int g_utf8_positions = 0; /* the client accepted utf-8 offsets */ +static FILE* g_log = 0; + +static void lg(const char* fmt, ...){ + if (!g_log) return; + va_list ap; va_start(ap, fmt); vfprintf(g_log, fmt, ap); va_end(ap); + fputc('\n', g_log); fflush(g_log); +} + +/* ---------- framing -------------------------------------------------------*/ +static void send_raw(const char* body){ + printf("Content-Length: %zu\r\n\r\n%s", strlen(body), body); + fflush(stdout); +} +static void send_result(JVal* id, const char* result_json){ + JSB s = {0}; + jsb_puts(&s, "{\"jsonrpc\":\"2.0\",\"id\":"); + if (!id) jsb_puts(&s, "null"); + else if (id->t == JSTR) jsb_str(&s, id->s); + else jsb_putf(&s, "%ld", (long)id->num); + jsb_puts(&s, ",\"result\":"); + jsb_puts(&s, result_json && *result_json ? result_json : "null"); + jsb_puts(&s, "}"); + send_raw(s.b); free(s.b); +} +static void send_notify(const char* method, const char* params_json){ + JSB s = {0}; + jsb_puts(&s, "{\"jsonrpc\":\"2.0\",\"method\":"); + jsb_str(&s, method); + jsb_puts(&s, ",\"params\":"); + jsb_puts(&s, params_json ? params_json : "null"); + jsb_puts(&s, "}"); + send_raw(s.b); free(s.b); +} +/* Read one Content-Length framed message. NULL at EOF. */ +static char* read_message(void){ + char line[8192]; + long len = -1; + for (;;){ + if (!fgets(line, sizeof(line), stdin)) return 0; + if (line[0] == '\r' || line[0] == '\n') break; + if (!strncasecmp(line, "Content-Length:", 15)) len = strtol(line + 15, 0, 10); + } + if (len <= 0) return 0; + char* buf = malloc(len + 1); + long got = 0; + while (got < len){ + size_t r = fread(buf + got, 1, len - got, stdin); + if (!r) break; + got += r; + } + buf[got] = 0; + return buf; +} + +/* ---------- position helpers ---------------------------------------------*/ +static int pos_char(LDoc* D, int off){ + if (g_utf8_positions){ + int line = ldoc_line_of(D, off); + return off - D->lex.linestart[line]; + } + return ldoc_col_of(D, off); +} +static void put_pos(JSB* s, LDoc* D, int off){ + jsb_putf(s, "{\"line\":%d,\"character\":%d}", ldoc_line_of(D, off), pos_char(D, off)); +} +static void put_range(JSB* s, LDoc* D, int a, int b){ + jsb_puts(s, "{\"start\":"); put_pos(s, D, a); + jsb_puts(s, ",\"end\":"); put_pos(s, D, b); + jsb_puts(s, "}"); +} +static void put_location(JSB* s, LDoc* D, int a, int b){ + jsb_puts(s, "{\"uri\":"); jsb_str(s, D->uri); + jsb_puts(s, ",\"range\":"); put_range(s, D, a, b); + jsb_puts(s, "}"); +} + +/* ---------- diagnostics ---------------------------------------------------*/ +typedef struct { LDoc* doc; LDiag* v; int n, cap; } DiagSet; +static void diag_add(DiagSet* ds, LDoc* D, int line, int col, int endline, int endcol, int sev, const char* msg){ + if (ds->n >= ds->cap){ ds->cap = ds->cap ? ds->cap * 2 : 16; ds->v = realloc(ds->v, ds->cap * sizeof(LDiag)); } + LDiag* d = &ds->v[ds->n++]; + memset(d, 0, sizeof(*d)); + d->line = line; d->col = col; d->endline = endline; d->endcol = endcol; d->severity = sev; + snprintf(d->msg, sizeof(d->msg), "%s", msg); + snprintf(d->path, sizeof(d->path), "%s", D->path); +} +/* Structural problems we can see without the compiler, cheaply, on every + * keystroke: unbalanced delimiters and unterminated literals. */ +static void diag_structural(LDoc* D, DiagSet* ds){ + int stack[512], top = 0; + for (int i = 0; i < D->lex.n; i++){ + const LTok* t = &D->lex.v[i]; + if (t->bad){ + const char* m = t->kind == LT_STR ? "unterminated string literal" + : t->kind == LT_CHAR ? "unterminated character literal" + : "unexpected character"; + diag_add(ds, D, ldoc_line_of(D, t->start), pos_char(D, t->start), + ldoc_line_of(D, t->end), pos_char(D, t->end), 1, m); + continue; + } + if (t->kind != LT_OP || ltok_len(t) != 1) continue; + char c = D->text[t->start]; + if (c == '{' || c == '(' || c == '['){ if (top < 512) stack[top++] = i; } + else if (c == '}' || c == ')' || c == ']'){ + if (!top){ + char m[64]; snprintf(m, sizeof(m), "unmatched '%c'", c); + diag_add(ds, D, ldoc_line_of(D, t->start), pos_char(D, t->start), + ldoc_line_of(D, t->end), pos_char(D, t->end), 1, m); + } else { + int o = stack[--top]; + char oc = D->text[D->lex.v[o].start]; + char want = oc == '{' ? '}' : oc == '(' ? ')' : ']'; + if (want != c){ + char m[80]; snprintf(m, sizeof(m), "expected '%c' to close '%c', found '%c'", want, oc, c); + diag_add(ds, D, ldoc_line_of(D, t->start), pos_char(D, t->start), + ldoc_line_of(D, t->end), pos_char(D, t->end), 1, m); + } + } + } + } + for (int k = 0; k < top; k++){ + const LTok* t = &D->lex.v[stack[k]]; + char m[64]; snprintf(m, sizeof(m), "unclosed '%c'", D->text[t->start]); + diag_add(ds, D, ldoc_line_of(D, t->start), pos_char(D, t->start), + ldoc_line_of(D, t->end), pos_char(D, t->end), 1, m); + } +} + +/* Ask the compiler. `ludicc --fmt` runs lex + parse + validate and stops before + * codegen, which is exactly the checking pass we want and costs milliseconds. + * A fragment (an imported file with no `game` block) is not a program on its + * own, so we check the unit root that pulls it in and let the file paths in the + * compiler's own output route each error back to the right buffer. */ +static void diag_compiler(LDoc* D, DiagSet* ds){ + if (!g_ludicc || !g_compiler_diags) return; + /* A .md is Ludic only inside its fences; the file as a whole is prose, and + * handing it to the compiler yields errors about the prose. The fences are + * still checked structurally, which is as far as a fragment can be checked + * anyway — most of them are deliberately incomplete snippets. */ + if (D->is_markdown) return; + LDoc* root = lw_unit_root(&X, D); + if (!root) root = D->is_unit ? D : 0; + if (!root) return; + /* Paths reach us from URIs the editor sends, and they end up in a shell + * command. A quote in a path would let a filename run something; refuse + * rather than escape, since no real Ludic file needs one. */ + if (strchr(root->path, '\'') || strchr(g_ludicc, '\'')) return; + + /* the compiler reads from disk; an unsaved buffer would be checked stale */ + char cmd[PATH_MAX * 2 + 64]; + snprintf(cmd, sizeof(cmd), "'%s' '%s' --fmt -o /dev/null 2>&1", g_ludicc, root->path); + FILE* p = popen(cmd, "r"); + if (!p) return; + char line[4096]; + char msg[512]; msg[0] = 0; + int have = 0, lineno = 0; + while (fgets(line, sizeof(line), p)){ + size_t n = strlen(line); + while (n && (line[n-1] == '\n' || line[n-1] == '\r')) line[--n] = 0; + int ln; + char rest[1024]; + if (sscanf(line, "ludicc: error: line %d: %1023[^\n]", &ln, rest) == 2){ + if (have){ diag_add(ds, root, lineno - 1, 0, lineno - 1, 200, 1, msg); } + lineno = ln; snprintf(msg, sizeof(msg), "%s", rest); have = 1; + continue; + } + /* the follow-up line names the file the error is really in */ + char path[1024]; + if (have && sscanf(line, " %1023[^:]:%d |", path, &ln) == 2){ + LDoc* target = lw_ensure(&X, path); + if (!target) target = root; + int l0 = ln - 1; + int end = 200; + if (l0 >= 0 && l0 < target->lex.nline){ + int s0 = target->lex.linestart[l0]; + int e0 = (l0 + 1 < target->lex.nline) ? target->lex.linestart[l0+1] - 1 : (int)strlen(target->text); + end = pos_char(target, e0 > s0 ? e0 : s0); + } + diag_add(ds, target, l0, 0, l0, end, 1, msg); + have = 0; msg[0] = 0; + continue; + } + if (!have && !strncmp(line, "ludicc: ", 8) && !strstr(line, "error: line")){ + diag_add(ds, root, 0, 0, 0, 0, 1, line + 8); + } + } + if (have) diag_add(ds, root, lineno - 1, 0, lineno - 1, 200, 1, msg); + pclose(p); +} + +/* Publish for every document that got a diagnostic, and clear the rest. + * + * Markdown gets none. A fence in prose is a snippet — `system Move { … }` with + * an elision mark, or a body shown without its enclosing `game` block — so + * almost every "error" found there is the documentation doing its job. The + * useful half of the server still applies to fences: highlighting, hover, + * completion, go-to-definition and formatting are never wrong on a snippet. */ +static void publish_diagnostics(LDoc* D){ + DiagSet ds = {0}; + if (!D->is_markdown) diag_structural(D, &ds); + /* only bother the compiler when the buffer itself parses — otherwise we are + * reporting the same brace twice, in two different dialects */ + int structural = ds.n; + if (!structural) diag_compiler(D, &ds); + + /* Every document that has a diagnostic now, plus every document that had + * one last time — otherwise fixing an error in an imported file leaves its + * marker on screen forever, because nothing would ever publish an empty + * list for that file again. */ + LDoc* touched[128]; int nt = 0; + touched[nt++] = D; + for (int i = 0; i < ds.n; i++){ + LDoc* T = lw_by_path(&X, ds.v[i].path); + if (!T) continue; + int seen = 0; for (int k = 0; k < nt; k++) if (touched[k] == T) seen = 1; + if (!seen && nt < 128) touched[nt++] = T; + } + for (int i = 0; i < X.n && nt < 128; i++){ + if (!X.d[i]->had_diags) continue; + int seen = 0; for (int k = 0; k < nt; k++) if (touched[k] == X.d[i]) seen = 1; + if (!seen) touched[nt++] = X.d[i]; + } + for (int k = 0; k < nt; k++){ + LDoc* T = touched[k]; + T->had_diags = 0; + JSB s = {0}; + jsb_puts(&s, "{\"uri\":"); jsb_str(&s, T->uri); + jsb_puts(&s, ",\"diagnostics\":["); + int first = 1; + for (int i = 0; i < ds.n; i++){ + if (strcmp(ds.v[i].path, T->path)) continue; + if (!first) jsb_putc(&s, ','); + first = 0; + T->had_diags = 1; + jsb_putf(&s, "{\"range\":{\"start\":{\"line\":%d,\"character\":%d},\"end\":{\"line\":%d,\"character\":%d}}", + ds.v[i].line < 0 ? 0 : ds.v[i].line, ds.v[i].col, + ds.v[i].endline < 0 ? 0 : ds.v[i].endline, ds.v[i].endcol); + jsb_putf(&s, ",\"severity\":%d,\"source\":\"ludic\",\"message\":", ds.v[i].severity); + jsb_str(&s, ds.v[i].msg); + jsb_putc(&s, '}'); + } + jsb_puts(&s, "]}"); + send_notify("textDocument/publishDiagnostics", s.b); + free(s.b); + } + free(ds.v); +} + +/* ---------- semantic tokens ----------------------------------------------*/ +/* The legend, in the order the client will index into. */ +static const char* STOK_TYPES[] = { + "keyword","type","struct","class","namespace","function","parameter", + "variable","property","enumMember","number","string","comment","operator", + "decorator", 0 +}; +enum { STM_DECL = 1, STM_READONLY = 2, STM_DEFLIB = 4 }; +static const char* STOK_MODS[] = { "declaration","readonly","defaultLibrary", 0 }; + +static int sem_type_of(int cls, int* mods){ + *mods = 0; + switch (cls){ + case SC_KEYWORD: return 0; + case SC_TYPE: *mods = STM_DEFLIB; return 1; + case SC_COMPONENT: return 2; + case SC_ARCHETYPE: return 3; + case SC_SCENE: return 4; + case SC_LAYER: return 4; + case SC_UI: return 3; + case SC_WIDGET: *mods = STM_DEFLIB; return 3; + case SC_SYSTEM: return 5; + case SC_FUNCTION: return 5; + case SC_BUILTIN: *mods = STM_DEFLIB; return 5; + case SC_PARAM: return 6; + case SC_VARIABLE: return 7; + case SC_MODVAR: return 7; + case SC_CONST: *mods = STM_READONLY; return 7; + case SC_PROP: return 8; + case SC_FIELD: return 8; + case SC_PHASE: *mods = STM_READONLY | STM_DEFLIB; return 9; + case SC_NUMBER: return 10; + case SC_STRING: return 11; + case SC_COMMENT: return 12; + case SC_OPERATOR: return 13; + case SC_ANNOTATION: return 14; + default: return -1; + } +} +static char* semantic_tokens(LDoc* D, int from_line, int to_line){ + lw_classify(&X, D); + JSB s = {0}; + jsb_puts(&s, "{\"data\":["); + int prev_line = 0, prev_char = 0, first = 1; + for (int i = 0; i < D->lex.n; i++){ + const LTok* t = &D->lex.v[i]; + if (t->kind == LT_NL || t->kind == LT_EOF) continue; + if (t->line < from_line || (to_line >= 0 && t->line > to_line)) continue; + int mods; int ty = sem_type_of(D->cls[i], &mods); + if (ty < 0) continue; + int line = t->line; + int ch = pos_char(D, t->start); + int len = g_utf8_positions ? ltok_len(t) : lutf16_len(D->text + t->start, ltok_len(t)); + if (len <= 0) continue; + int dl = line - prev_line; + int dc = dl ? ch : ch - prev_char; + if (!first) jsb_putc(&s, ','); + first = 0; + jsb_putf(&s, "%d,%d,%d,%d,%d", dl, dc, len, ty, mods); + prev_line = line; prev_char = ch; + } + jsb_puts(&s, "]}"); + return s.b; +} + +/* ---------- symbol presentation ------------------------------------------*/ +static int lsp_symbol_kind(int k){ + switch (k){ /* LSP SymbolKind numbers */ + case LS_UNIT: return 2; /* Module */ + case LS_COMPONENT: return 23; /* Struct */ + case LS_FIELD: return 8; /* Field */ + case LS_ARCHETYPE: return 5; /* Class */ + case LS_CONST: return 14; /* Constant */ + case LS_VAR: return 13; /* Variable */ + case LS_FN: return 12; /* Function */ + case LS_EXTERN: return 12; + case LS_SYSTEM: return 6; /* Method */ + case LS_UI: return 5; + case LS_WIDGET: return 14; + case LS_SCENE: return 3; /* Namespace */ + case LS_LAYER: return 3; + case LS_PARAM: return 13; + case LS_LOCAL: return 13; + case LS_QUERYVAR: return 13; + case LS_STATE: return 22; /* EnumMember */ + case LS_IMPORT: return 2; + default: return 13; + } +} +static int sym_is_outline(int k){ + switch (k){ + case LS_UNIT: case LS_COMPONENT: case LS_FIELD: case LS_ARCHETYPE: + case LS_CONST: case LS_VAR: case LS_FN: case LS_EXTERN: case LS_SYSTEM: + case LS_UI: case LS_WIDGET: case LS_SCENE: case LS_LAYER: + return 1; + default: return 0; + } +} +/* DocumentSymbol is a tree; emit children of `parent` recursively. */ +static void put_doc_symbols(JSB* s, LDoc* D, int parent){ + int first = 1; + jsb_putc(s, '['); + for (int i = 0; i < D->nsym; i++){ + LSym* y = &D->sym[i]; + if (y->parent != parent || !sym_is_outline(y->kind) || !y->name[0]) continue; + if (!first) jsb_putc(s, ','); + first = 0; + jsb_puts(s, "{\"name\":"); jsb_str(s, y->name); + jsb_puts(s, ",\"detail\":"); jsb_str(s, y->detail); + jsb_putf(s, ",\"kind\":%d,\"range\":", lsp_symbol_kind(y->kind)); + int a = y->start, b = y->end; + if (y->body_end > y->end && y->body_start >= y->start){ a = y->start; b = y->body_end; } + put_range(s, D, a, b); + jsb_puts(s, ",\"selectionRange\":"); put_range(s, D, y->start, y->end); + jsb_puts(s, ",\"children\":"); + put_doc_symbols(s, D, i); + jsb_putc(s, '}'); + } + jsb_putc(s, ']'); +} + +/* ---------- hover ---------------------------------------------------------*/ +static void hover_markdown(JSB* s, const char* code, const char* doc){ + JSB m = {0}; + jsb_puts(&m, "```ludic\n"); + jsb_puts(&m, code); + jsb_puts(&m, "\n```"); + if (doc && *doc){ jsb_puts(&m, "\n\n"); jsb_puts(&m, doc); } + jsb_puts(s, "{\"contents\":{\"kind\":\"markdown\",\"value\":"); + jsb_str(s, m.b); + jsb_puts(s, "}}"); + free(m.b); +} + +/* ---------- completion ----------------------------------------------------*/ +enum { CI_TEXT = 1, CI_METHOD = 2, CI_FUNCTION = 3, CI_FIELD = 5, CI_VARIABLE = 6, + CI_CLASS = 7, CI_PROPERTY = 10, CI_UNIT = 11, CI_VALUE = 12, CI_ENUM = 13, + CI_KEYWORD = 14, CI_SNIPPET = 15, CI_CONSTANT = 21, CI_STRUCT = 22, CI_EVENT = 23 }; + +typedef struct { JSB* s; int first; } CompOut; +static void comp_item(CompOut* c, const char* label, int kind, const char* detail, const char* doc, const char* insert){ + if (!c->first) jsb_putc(c->s, ','); + c->first = 0; + jsb_puts(c->s, "{\"label\":"); jsb_str(c->s, label); + jsb_putf(c->s, ",\"kind\":%d", kind); + if (detail && *detail){ jsb_puts(c->s, ",\"detail\":"); jsb_str(c->s, detail); } + if (doc && *doc){ + jsb_puts(c->s, ",\"documentation\":{\"kind\":\"markdown\",\"value\":"); + jsb_str(c->s, doc); + jsb_putc(c->s, '}'); + } + if (insert && *insert){ + jsb_puts(c->s, ",\"insertText\":"); jsb_str(c->s, insert); + jsb_puts(c->s, ",\"insertTextFormat\":2"); + } + jsb_putc(c->s, '}'); +} +static void comp_words(CompOut* c, const char** words, int kind, const char* detail){ + for (int i = 0; words[i]; i++) comp_item(c, words[i], kind, detail, 0, 0); +} +static void comp_builtins(CompOut* c){ + for (int i = 0; LUDIC_BUILTINS[i].name; i++) + comp_item(c, LUDIC_BUILTINS[i].name, CI_FUNCTION, LUDIC_BUILTINS[i].sig, LUDIC_BUILTINS[i].doc, 0); + for (int i = 0; LUDIC_INTRINSICS[i].name; i++) + comp_item(c, LUDIC_INTRINSICS[i].name, CI_FUNCTION, LUDIC_INTRINSICS[i].sig, LUDIC_INTRINSICS[i].doc, 0); +} +static int comp_kind_of(int symkind){ + switch (symkind){ + case LS_COMPONENT: return CI_STRUCT; + case LS_ARCHETYPE: return CI_CLASS; + case LS_CONST: return CI_CONSTANT; + case LS_VAR: return CI_VARIABLE; + case LS_FN: case LS_EXTERN: return CI_FUNCTION; + case LS_SYSTEM: return CI_EVENT; + case LS_UI: return CI_CLASS; + case LS_WIDGET: return CI_CONSTANT; + case LS_SCENE: return CI_UNIT; + case LS_LAYER: return CI_UNIT; + case LS_FIELD: return CI_FIELD; + default: return CI_VARIABLE; + } +} +/* Everything the compilation unit declares, plus the locals in scope here. + * `types_only` is for the positions where nothing but a component or archetype + * can appear — a query's term list, a `spawn`, a type annotation — and there a + * local variable is not a candidate at all. */ +static void comp_scope(CompOut* c, LDoc* D, int off, int types_only){ + if (!types_only) + for (int i = 0; i < D->nsym; i++){ + LSym* y = &D->sym[i]; + if (!lsym_is_local(y->kind)) continue; + if (off < y->body_start || off > y->body_end) continue; + comp_item(c, y->name, CI_VARIABLE, y->detail[0] ? y->detail : y->type, 0, 0); + } + LDoc* rel[128]; int n = lw_related(&X, D, rel, 128); + for (int i = 0; i < n; i++) + for (int k = 0; k < rel[i]->nsym; k++){ + LSym* y = &rel[i]->sym[k]; + if (!lsym_is_toplevel(y->kind) || y->kind == LS_UNIT) continue; + if (types_only && !(y->kind == LS_COMPONENT || y->kind == LS_ARCHETYPE)) continue; + comp_item(c, y->name, comp_kind_of(y->kind), y->detail, y->doc, 0); + } +} + +/* ---------- URI/doc plumbing ---------------------------------------------*/ +static LDoc* doc_of(JVal* msg){ + const char* uri = jstr(jpath(msg, "params.textDocument.uri"), 0); + if (!uri) return 0; + LDoc* D = lw_by_uri(&X, uri); + if (D) return D; + char* path = lw_uri_to_path(uri); + D = lw_ensure(&X, path); + free(path); + return D; +} +static int off_of(JVal* msg, LDoc* D, const char* base){ + char kl[128], kc[128]; + snprintf(kl, sizeof(kl), "%s.line", base); + snprintf(kc, sizeof(kc), "%s.character", base); + int line = jint(jpath(msg, kl), 0), ch = jint(jpath(msg, kc), 0); + if (g_utf8_positions){ + if (line < 0 || line >= D->lex.nline) return 0; + int s0 = D->lex.linestart[line]; + int e0 = (line + 1 < D->lex.nline) ? D->lex.linestart[line + 1] : (int)strlen(D->text); + int off = s0 + ch; + return off > e0 ? e0 : off; + } + return ldoc_offset_of(D, line, ch); +} + +/* ---------- request handlers ---------------------------------------------*/ +static void on_initialize(JVal* msg, JVal* id){ + JVal* root = jpath(msg, "params.rootUri"); + if (root && root->t == JSTR) X.root = lw_uri_to_path(root->s); + else { + JVal* folders = jpath(msg, "params.workspaceFolders"); + JVal* f0 = jat(folders, 0); + const char* u = jstr(jget(f0, "uri"), 0); + if (u) X.root = lw_uri_to_path(u); + } + /* the client may prefer plain byte offsets; take it if offered, it is both + * cheaper and exactly what our lexer already produces */ + JVal* enc = jpath(msg, "params.capabilities.general.positionEncodings"); + if (enc) for (int i = 0; i < enc->n; i++){ + const char* e = jstr(jat(enc, i), ""); + if (!strcmp(e, "utf-8")){ g_utf8_positions = 1; break; } + } + JVal* init = jpath(msg, "params.initializationOptions"); + const char* cc = jstr(jget(init, "compilerPath"), 0); + if (cc && *cc){ free(g_ludicc); g_ludicc = strdup(cc); } + if (jget(init, "indentSize")) g_indent = jint(jget(init, "indentSize"), 2); + if (jget(init, "compilerDiagnostics")) g_compiler_diags = jbool(jget(init, "compilerDiagnostics"), 1); + + /* find the compiler if nobody told us where it is */ + if (!g_ludicc && X.root){ + char p[PATH_MAX]; + snprintf(p, sizeof(p), "%s/build/ludicc", X.root); + if (!access(p, X_OK)) g_ludicc = strdup(p); + } + if (!g_ludicc && !access("build/ludicc", X_OK)) g_ludicc = strdup("build/ludicc"); + + if (X.root) lw_scan(&X, X.root, 0); + lg("initialize root=%s compiler=%s docs=%d", X.root ? X.root : "-", g_ludicc ? g_ludicc : "-", X.n); + + JSB s = {0}; + jsb_puts(&s, "{\"capabilities\":{"); + jsb_puts(&s, "\"positionEncoding\":"); + jsb_str(&s, g_utf8_positions ? "utf-8" : "utf-16"); + jsb_puts(&s, ",\"textDocumentSync\":{\"openClose\":true,\"change\":1,\"save\":{\"includeText\":false}}"); + jsb_puts(&s, ",\"documentSymbolProvider\":true"); + jsb_puts(&s, ",\"workspaceSymbolProvider\":true"); + jsb_puts(&s, ",\"definitionProvider\":true"); + jsb_puts(&s, ",\"declarationProvider\":true"); + jsb_puts(&s, ",\"referencesProvider\":true"); + jsb_puts(&s, ",\"documentHighlightProvider\":true"); + jsb_puts(&s, ",\"hoverProvider\":true"); + jsb_puts(&s, ",\"renameProvider\":{\"prepareProvider\":true}"); + jsb_puts(&s, ",\"documentFormattingProvider\":true"); + jsb_puts(&s, ",\"documentRangeFormattingProvider\":true"); + jsb_puts(&s, ",\"foldingRangeProvider\":true"); + jsb_puts(&s, ",\"documentLinkProvider\":{\"resolveProvider\":false}"); + jsb_puts(&s, ",\"inlayHintProvider\":true"); + jsb_puts(&s, ",\"completionProvider\":{\"triggerCharacters\":[\".\",\"@\",\"[\",\" \"],\"resolveProvider\":false}"); + jsb_puts(&s, ",\"signatureHelpProvider\":{\"triggerCharacters\":[\"(\",\",\"]}"); + jsb_puts(&s, ",\"semanticTokensProvider\":{\"legend\":{\"tokenTypes\":["); + for (int i = 0; STOK_TYPES[i]; i++){ if (i) jsb_putc(&s, ','); jsb_str(&s, STOK_TYPES[i]); } + jsb_puts(&s, "],\"tokenModifiers\":["); + for (int i = 0; STOK_MODS[i]; i++){ if (i) jsb_putc(&s, ','); jsb_str(&s, STOK_MODS[i]); } + jsb_puts(&s, "]},\"full\":true,\"range\":true}"); + jsb_puts(&s, "},\"serverInfo\":{\"name\":\"ludic-lsp\",\"version\":\"1.0.0\"}}"); + send_result(id, s.b); + free(s.b); +} + +static void on_document_symbol(JVal* msg, JVal* id){ + LDoc* D = doc_of(msg); + if (!D){ send_result(id, "[]"); return; } + JSB s = {0}; + put_doc_symbols(&s, D, -1); + send_result(id, s.b); + free(s.b); +} + +static void on_workspace_symbol(JVal* msg, JVal* id){ + const char* q = jstr(jpath(msg, "params.query"), ""); + JSB s = {0}; jsb_putc(&s, '['); + int first = 1; + for (int i = 0; i < X.n; i++){ + LDoc* D = X.d[i]; + for (int k = 0; k < D->nsym; k++){ + LSym* y = &D->sym[k]; + if (!sym_is_outline(y->kind) || !y->name[0]) continue; + if (*q && !strcasestr(y->name, q)) continue; + if (!first) jsb_putc(&s, ','); + first = 0; + jsb_puts(&s, "{\"name\":"); jsb_str(&s, y->name); + jsb_putf(&s, ",\"kind\":%d,\"location\":", lsp_symbol_kind(y->kind)); + put_location(&s, D, y->start, y->end); + if (D->unit[0]){ jsb_puts(&s, ",\"containerName\":"); jsb_str(&s, D->unit); } + jsb_putc(&s, '}'); + } + } + jsb_putc(&s, ']'); + send_result(id, s.b); + free(s.b); +} + +/* What does this exact token refer to? Every feature that needs to know two + * occurrences are the same thing — go-to-definition, find-usages, rename, + * highlight — goes through here, so they cannot disagree with each other. */ +static int resolve_tok(LDoc* D, int tok, LDoc** owner, int* symidx){ + *owner = 0; *symidx = -1; + if (tok < 0) return -1; + if (D->lex.v[tok].kind != LT_ID && D->lex.v[tok].kind != LT_STR) return -1; + char name[96]; ltok_text(&D->lex, tok, name, sizeof(name)); + + /* The token may BE a declaration's name — a component, a field, a + * parameter, a query binding. Those resolve to themselves, which is what + * makes hover work on the left-hand side of `for (a, b) in query [...]` + * where the binding is not yet inside its own scope. */ + for (int i = 0; i < D->nsym; i++) + if (D->sym[i].tok == tok){ *owner = D; *symidx = i; return tok; } + + /* a member: resolve through the receiver's component */ + int prev = ltok_prev_sig(&D->lex, tok); + if (prev >= 0 && ltok_is(&D->lex, prev, ".")){ + LDoc* co = 0; + int comp = lw_receiver_component(&X, D, prev, &co); + if (comp >= 0 && co){ + for (int i = 0; i < co->nsym; i++) + if (co->sym[i].kind == LS_FIELD && co->sym[i].parent == comp && !strcmp(co->sym[i].name, name)){ + *owner = co; *symidx = i; return tok; + } + } + return tok; + } + int l = lw_find_local(D, name, D->lex.v[tok].start); + if (l >= 0){ *owner = D; *symidx = l; return tok; } + LDoc* o = 0; int t = lw_find_top(&X, D, name, &o); + if (t >= 0){ *owner = o; *symidx = t; return tok; } + return tok; +} +static int resolve_at(LDoc* D, int off, LDoc** owner, int* symidx){ + return resolve_tok(D, ldoc_tok_at(D, off), owner, symidx); +} +/* Occurrences of one symbol, found by resolving each candidate token rather + * than by matching text. It is the difference between renaming a component + * field `x` and renaming every `x` in the project. */ +typedef void (*OccFn)(void* ctx, LDoc* T, int tok); +static void for_each_occurrence(LDoc* from, LDoc* target_doc, int target_sym, OccFn fn, void* ctx){ + char want[96]; + lcpy(want, sizeof(want), target_doc->text + target_doc->sym[target_sym].start, + target_doc->sym[target_sym].end - target_doc->sym[target_sym].start); + + /* A local binding cannot be referred to from another file, so there is no + * reason to walk the unit for one. */ + LDoc* single[1] = { from }; + LDoc* rel[128]; + int n; + if (lsym_is_local(target_doc->sym[target_sym].kind)){ rel[0] = single[0]; n = 1; } + else n = lw_related(&X, from, rel, 128); + + for (int i = 0; i < n; i++){ + LDoc* T = rel[i]; + for (int k = 0; k < T->lex.n; k++){ + if (T->lex.v[k].kind != LT_ID) continue; + char w[96]; ltok_text(&T->lex, k, w, sizeof(w)); + if (strcmp(w, want)) continue; /* cheap filter first */ + LDoc* o = 0; int sy = -1; + resolve_tok(T, k, &o, &sy); + if (o == target_doc && sy == target_sym) fn(ctx, T, k); + } + } +} + +static void on_definition(JVal* msg, JVal* id){ + LDoc* D = doc_of(msg); + if (!D){ send_result(id, "null"); return; } + int off = off_of(msg, D, "params.position"); + /* an import string jumps to the file */ + int tok = ldoc_tok_at(D, off); + if (tok >= 0 && D->lex.v[tok].kind == LT_STR){ + int p = ltok_prev_sig(&D->lex, tok); + if (p >= 0 && ltok_is(&D->lex, p, "import")){ + char rel[512]; ltok_text(&D->lex, tok, rel, sizeof(rel)); + int n = (int)strlen(rel); if (n >= 2){ memmove(rel, rel + 1, n - 2); rel[n-2] = 0; } + char* dir = lw_dirname(D->path); + char* full = lw_join(dir, rel); free(dir); + LDoc* T = lw_ensure(&X, full); free(full); + if (T){ JSB s = {0}; put_location(&s, T, 0, 0); send_result(id, s.b); free(s.b); return; } + } + } + LDoc* owner = 0; int sym = -1; + resolve_at(D, off, &owner, &sym); + if (!owner || sym < 0){ send_result(id, "null"); return; } + JSB s = {0}; + put_location(&s, owner, owner->sym[sym].start, owner->sym[sym].end); + send_result(id, s.b); + free(s.b); +} + +static void on_hover(JVal* msg, JVal* id){ + LDoc* D = doc_of(msg); + if (!D){ send_result(id, "null"); return; } + int off = off_of(msg, D, "params.position"); + int tok = ldoc_tok_at(D, off); + if (tok < 0){ send_result(id, "null"); return; } + char name[128]; ltok_text(&D->lex, tok, name, sizeof(name)); + + LDoc* owner = 0; int sym = -1; + resolve_at(D, off, &owner, &sym); + JSB s = {0}; + if (owner && sym >= 0){ + LSym* y = &owner->sym[sym]; + char code[320]; + snprintf(code, sizeof(code), "%s", y->detail[0] ? y->detail : y->name); + char doc[768]; + snprintf(doc, sizeof(doc), "%s", y->doc); + if (owner != D){ + size_t n = strlen(doc); + snprintf(doc + n, sizeof(doc) - n, "%s_declared in %s_", n ? "\n\n" : "", strrchr(owner->path, '/') ? strrchr(owner->path, '/') + 1 : owner->path); + } + hover_markdown(&s, code, doc); + send_result(id, s.b); free(s.b); return; + } + const LBuiltin* bi = lud_lookup(LUDIC_BUILTINS, name); + const char* origin = "runtime builtin — provided by `rt_` in runtime/native"; + if (!bi){ bi = lud_lookup(LUDIC_INTRINSICS, name); origin = "compiler intrinsic — lowers straight to libc / the OS"; } + if (bi){ + char doc[768]; snprintf(doc, sizeof(doc), "%s\n\n_%s_", bi->doc, origin); + hover_markdown(&s, bi->sig, doc); + send_result(id, s.b); free(s.b); return; + } + if (D->lex.v[tok].kind == LT_PHASE){ + hover_markdown(&s, name, "A system phase. Each frame runs `Input` -> `FixedUpdate` -> `Update` -> `LateUpdate` -> `Render`; `Start` runs once at boot."); + send_result(id, s.b); free(s.b); return; + } + if (D->lex.v[tok].kind == LT_TYPE){ + static const struct { const char* n; const char* d; } TY[] = { + {"int","32-bit integer."}, + {"fixed","Q16.16 fixed-point. `fx(i)` widens an int, `flr(f)` truncates back."}, + {"bool","Boolean."}, + {"entity","An entity handle. `self()` gives the one the current query is on."}, + {"str","A string literal."}, + {"ptr","A raw pointer — the runtime's floor, not for game code."}, + {"void","No value."}, + {0,0} + }; + for (int i = 0; TY[i].n; i++) if (!strcmp(TY[i].n, name)){ + hover_markdown(&s, name, TY[i].d); + send_result(id, s.b); free(s.b); return; + } + } + free(s.b); + send_result(id, "null"); +} + +/* ---------- references, highlight, rename --------------------------------*/ +typedef struct { JSB* s; int first; int mode; const char* newname; LDoc* cur; } OccOut; +enum { OCC_LOCATION, OCC_HIGHLIGHT }; + +static void occ_emit(void* ctx, LDoc* T, int tok){ + OccOut* o = (OccOut*)ctx; + if (o->mode == OCC_HIGHLIGHT && T != o->cur) return; + if (!o->first) jsb_putc(o->s, ','); + o->first = 0; + if (o->mode == OCC_HIGHLIGHT){ + jsb_puts(o->s, "{\"range\":"); + put_range(o->s, T, T->lex.v[tok].start, T->lex.v[tok].end); + jsb_puts(o->s, ",\"kind\":1}"); + } else { + put_location(o->s, T, T->lex.v[tok].start, T->lex.v[tok].end); + } +} + +static void refs_common(JVal* msg, JVal* id, int mode){ + LDoc* D = doc_of(msg); + if (!D){ send_result(id, "[]"); return; } + int off = off_of(msg, D, "params.position"); + LDoc* owner = 0; int sym = -1; + int tok = resolve_at(D, off, &owner, &sym); + if (tok < 0 || !owner || sym < 0){ send_result(id, "[]"); return; } + JSB s = {0}; jsb_putc(&s, '['); + OccOut o = { &s, 1, mode, 0, D }; + for_each_occurrence(D, owner, sym, occ_emit, &o); + jsb_putc(&s, ']'); + send_result(id, s.b); free(s.b); +} +static void on_references(JVal* msg, JVal* id){ refs_common(msg, id, OCC_LOCATION); } +static void on_document_highlight(JVal* msg, JVal* id){ refs_common(msg, id, OCC_HIGHLIGHT); } + +static void on_prepare_rename(JVal* msg, JVal* id){ + LDoc* D = doc_of(msg); + if (!D){ send_result(id, "null"); return; } + int off = off_of(msg, D, "params.position"); + LDoc* owner = 0; int sym = -1; + int tok = resolve_at(D, off, &owner, &sym); + /* Refusing beats renaming the wrong thing: if we cannot say what a name + * refers to, we cannot say which occurrences of it mean the same name. */ + if (tok < 0 || !owner || sym < 0 || D->lex.v[tok].kind != LT_ID){ send_result(id, "null"); return; } + JSB s = {0}; + jsb_puts(&s, "{\"range\":"); + put_range(&s, D, D->lex.v[tok].start, D->lex.v[tok].end); + jsb_puts(&s, ",\"placeholder\":"); + { char w[96]; ltok_text(&D->lex, tok, w, sizeof(w)); jsb_str(&s, w); } + jsb_putc(&s, '}'); + send_result(id, s.b); free(s.b); +} + +/* Rename collects per-file edit lists, because the LSP workspace edit is keyed + * by URI and a symbol can occur in several files of one unit. */ +typedef struct { LDoc* doc; JSB edits; int first; } FileEdits; +typedef struct { FileEdits f[64]; int n; const char* newname; } RenameOut; + +static void rename_collect(void* ctx, LDoc* T, int tok){ + RenameOut* r = (RenameOut*)ctx; + FileEdits* fe = 0; + for (int i = 0; i < r->n; i++) if (r->f[i].doc == T) fe = &r->f[i]; + if (!fe){ + if (r->n >= 64) return; + fe = &r->f[r->n++]; + memset(fe, 0, sizeof(*fe)); + fe->doc = T; fe->first = 1; + } + if (!fe->first) jsb_putc(&fe->edits, ','); + fe->first = 0; + jsb_puts(&fe->edits, "{\"range\":"); + put_range(&fe->edits, T, T->lex.v[tok].start, T->lex.v[tok].end); + jsb_puts(&fe->edits, ",\"newText\":"); + jsb_str(&fe->edits, r->newname); + jsb_putc(&fe->edits, '}'); +} + +static void on_rename(JVal* msg, JVal* id){ + LDoc* D = doc_of(msg); + const char* newname = jstr(jpath(msg, "params.newName"), 0); + if (!D || !newname || !*newname){ send_result(id, "null"); return; } + int off = off_of(msg, D, "params.position"); + LDoc* owner = 0; int sym = -1; + int tok = resolve_at(D, off, &owner, &sym); + if (tok < 0 || !owner || sym < 0){ send_result(id, "null"); return; } + + RenameOut r; memset(&r, 0, sizeof(r)); r.newname = newname; + for_each_occurrence(D, owner, sym, rename_collect, &r); + + JSB s = {0}; + jsb_puts(&s, "{\"changes\":{"); + for (int i = 0; i < r.n; i++){ + if (i) jsb_putc(&s, ','); + jsb_str(&s, r.f[i].doc->uri); + jsb_putc(&s, ':'); + jsb_putc(&s, '['); + jsb_puts(&s, r.f[i].edits.b ? r.f[i].edits.b : ""); + jsb_putc(&s, ']'); + free(r.f[i].edits.b); + } + jsb_puts(&s, "}}"); + send_result(id, s.b); free(s.b); +} + +static void on_formatting(JVal* msg, JVal* id, int ranged){ + LDoc* D = doc_of(msg); + if (!D){ send_result(id, "null"); return; } + int tab = jint(jpath(msg, "params.options.tabSize"), g_indent); + if (tab < 1 || tab > 8) tab = g_indent; + char* out = D->is_markdown ? ludic_format_markdown(D->raw, tab) : ludic_format(D->raw, tab); + /* A whole-document replacement is the honest edit: the formatter's unit of + * work is the file, and a partial rewrite could not fix indentation that + * depends on lines outside the range. Range formatting therefore formats + * the document too — every editor accepts that, and it never surprises. */ + (void)ranged; + int nline = D->lex.nline; + int endline = nline > 0 ? nline - 1 : 0; + int endchar = 0; + { + int s0 = nline ? D->lex.linestart[endline] : 0; + int e0 = (int)strlen(D->text); + endchar = g_utf8_positions ? e0 - s0 : lutf16_len(D->text + s0, e0 - s0); + } + JSB s = {0}; + jsb_putf(&s, "[{\"range\":{\"start\":{\"line\":0,\"character\":0},\"end\":{\"line\":%d,\"character\":%d}},\"newText\":", endline, endchar); + jsb_str(&s, out); + jsb_puts(&s, "}]"); + send_result(id, s.b); + free(s.b); free(out); +} + +static void on_folding(JVal* msg, JVal* id){ + LDoc* D = doc_of(msg); + if (!D){ send_result(id, "[]"); return; } + JSB s = {0}; jsb_putc(&s, '['); int first = 1; + for (int i = 0; i < D->lex.n; i++){ + const LTok* t = &D->lex.v[i]; + if (t->kind != LT_OP || ltok_len(t) != 1 || D->text[t->start] != '{') continue; + int m = D->match[i]; + if (m < 0) continue; + int a = t->line, b = D->lex.v[m].line; + if (b <= a) continue; + if (!first) jsb_putc(&s, ','); + first = 0; + jsb_putf(&s, "{\"startLine\":%d,\"endLine\":%d,\"kind\":\"region\"}", a, b - 1); + } + /* runs of comment lines fold as one block */ + for (int i = 0; i < D->lex.n; ){ + if (D->lex.v[i].kind != LT_COMMENT || !lw_first_on_line(D, i)){ i++; continue; } + int a = D->lex.v[i].line, last = a, j = i; + while (j < D->lex.n){ + if (D->lex.v[j].kind == LT_NL){ j++; continue; } + if (D->lex.v[j].kind == LT_COMMENT && lw_first_on_line(D, j) && D->lex.v[j].line <= last + 1){ last = D->lex.v[j].line; j++; continue; } + break; + } + if (last > a){ + if (!first) jsb_putc(&s, ','); + first = 0; + jsb_putf(&s, "{\"startLine\":%d,\"endLine\":%d,\"kind\":\"comment\"}", a, last); + } + i = j; + } + jsb_putc(&s, ']'); + send_result(id, s.b); free(s.b); +} + +static void on_document_link(JVal* msg, JVal* id){ + LDoc* D = doc_of(msg); + if (!D){ send_result(id, "[]"); return; } + JSB s = {0}; jsb_putc(&s, '['); int first = 1; + for (int i = 0; i < D->lex.n; i++){ + if (D->lex.v[i].kind != LT_STR) continue; + int p = ltok_prev_sig(&D->lex, i); + if (p < 0 || !ltok_is(&D->lex, p, "import")) continue; + char rel[512]; ltok_text(&D->lex, i, rel, sizeof(rel)); + int n = (int)strlen(rel); if (n >= 2){ memmove(rel, rel + 1, n - 2); rel[n-2] = 0; } + char* dir = lw_dirname(D->path); + char* full = lw_join(dir, rel); free(dir); + char* uri = lw_path_to_uri(full); + if (!first) jsb_putc(&s, ','); + first = 0; + jsb_puts(&s, "{\"range\":"); + put_range(&s, D, D->lex.v[i].start + 1, D->lex.v[i].end - 1); + jsb_puts(&s, ",\"target\":"); jsb_str(&s, uri); jsb_putc(&s, '}'); + free(uri); free(full); + } + jsb_putc(&s, ']'); + send_result(id, s.b); free(s.b); +} + +/* Query bindings read `for (p, v) in query [Pos, Vel]` — the types are one + * lookup away but invisible at the use site, so show them inline. */ +static void on_inlay_hint(JVal* msg, JVal* id){ + LDoc* D = doc_of(msg); + if (!D){ send_result(id, "[]"); return; } + JSB s = {0}; jsb_putc(&s, '['); int first = 1; + for (int i = 0; i < D->nsym; i++){ + LSym* y = &D->sym[i]; + if (y->kind != LS_QUERYVAR || !y->type[0]) continue; + if (!first) jsb_putc(&s, ','); + first = 0; + char label[128]; snprintf(label, sizeof(label), ": %s", y->type); + jsb_puts(&s, "{\"position\":"); put_pos(&s, D, y->end); + jsb_puts(&s, ",\"label\":"); jsb_str(&s, label); + jsb_puts(&s, ",\"kind\":1,\"paddingLeft\":false}"); + } + jsb_putc(&s, ']'); + send_result(id, s.b); free(s.b); +} + +static void on_signature_help(JVal* msg, JVal* id){ + LDoc* D = doc_of(msg); + if (!D){ send_result(id, "null"); return; } + int off = off_of(msg, D, "params.position"); + /* walk out to the call we are inside */ + int depth = 0, callee = -1, arg = 0; + for (int i = D->lex.n - 1; i >= 0; i--){ + const LTok* t = &D->lex.v[i]; + if (t->start >= off) continue; + if (t->kind != LT_OP || ltok_len(t) != 1) continue; + char c = D->text[t->start]; + if (c == ')') depth++; + else if (c == '('){ + if (depth == 0){ callee = ltok_prev_sig(&D->lex, i); + for (int k = i + 1; k < D->lex.n && D->lex.v[k].start < off; k++) + if (ltok_is(&D->lex, k, ",")) arg++; + break; } + depth--; + } + } + if (callee < 0 || D->lex.v[callee].kind != LT_ID){ send_result(id, "null"); return; } + char name[128]; ltok_text(&D->lex, callee, name, sizeof(name)); + const char* sig = 0; const char* doc = ""; + const LBuiltin* bi = lud_lookup(LUDIC_BUILTINS, name); + if (!bi) bi = lud_lookup(LUDIC_INTRINSICS, name); + if (bi){ sig = bi->sig; doc = bi->doc; } + else { + LDoc* o = 0; int t = lw_find_top(&X, D, name, &o); + if (t >= 0 && (o->sym[t].kind == LS_FN || o->sym[t].kind == LS_EXTERN)){ sig = o->sym[t].detail; doc = o->sym[t].doc; } + } + if (!sig){ send_result(id, "null"); return; } + JSB s = {0}; + jsb_puts(&s, "{\"signatures\":[{\"label\":"); jsb_str(&s, sig); + if (doc && *doc){ jsb_puts(&s, ",\"documentation\":"); jsb_str(&s, doc); } + jsb_putf(&s, "}],\"activeSignature\":0,\"activeParameter\":%d}", arg); + send_result(id, s.b); free(s.b); +} + +static void on_completion(JVal* msg, JVal* id){ + LDoc* D = doc_of(msg); + if (!D){ send_result(id, "[]"); return; } + int off = off_of(msg, D, "params.position"); + JSB s = {0}; + jsb_puts(&s, "{\"isIncomplete\":false,\"items\":["); + CompOut c = { &s, 1 }; + + /* what comes immediately before the cursor decides everything */ + int tok = -1; + for (int i = D->lex.n - 1; i >= 0; i--){ + int k = D->lex.v[i].kind; + if (k == LT_NL || k == LT_EOF || k == LT_COMMENT) continue; + if (D->lex.v[i].end <= off){ tok = i; break; } + } + /* skip the partial word being typed */ + int anchor = tok; + if (anchor >= 0 && D->lex.v[anchor].kind == LT_ID && D->lex.v[anchor].end >= off) anchor = ltok_prev_sig(&D->lex, anchor); + + /* Inside an unclosed `[` we are listing query terms, where the only things + * that can appear are components and archetypes — including after a comma, + * which is why this is a scan rather than a look at the previous token. */ + int in_query_terms = 0; + { + int depth = 0; + for (int i = anchor; i >= 0; i--){ + const LTok* t = &D->lex.v[i]; + if (t->kind != LT_OP || ltok_len(t) != 1) continue; + char ch = D->text[t->start]; + if (ch == ']') depth++; + else if (ch == '['){ if (!depth){ in_query_terms = 1; break; } depth--; } + else if (ch == '{' || ch == '}') break; /* left the clause */ + } + } + + int done = 0; + if (in_query_terms){ comp_scope(&c, D, off, 1); done = 1; } + else if (anchor >= 0){ + /* member access: only that component's fields */ + if (ltok_is(&D->lex, anchor, ".")){ + LDoc* co = 0; + int comp = lw_receiver_component(&X, D, anchor, &co); + if (comp >= 0 && co){ + for (int i = 0; i < co->nsym; i++) + if (co->sym[i].kind == LS_FIELD && co->sym[i].parent == comp) + comp_item(&c, co->sym[i].name, CI_FIELD, co->sym[i].detail, co->sym[i].doc, 0); + } + done = 1; + } + else if (ltok_is(&D->lex, anchor, "phase")){ comp_words(&c, LUDIC_PHASES, CI_ENUM, "system phase"); done = 1; } + else if (ltok_is(&D->lex, anchor, ":") || ltok_is(&D->lex, anchor, "->")){ + comp_words(&c, LUDIC_TYPES, CI_KEYWORD, "built-in type"); + comp_scope(&c, D, off, 1); + done = 1; + } + else if (ltok_is(&D->lex, anchor, "spawn")){ comp_scope(&c, D, off, 1); done = 1; } + else if (ltok_is(&D->lex, anchor, "enter")){ + LDoc* rel[128]; int n = lw_related(&X, D, rel, 128); + for (int i = 0; i < n; i++) + for (int k = 0; k < rel[i]->nsym; k++) + if (rel[i]->sym[k].kind == LS_SCENE) + comp_item(&c, rel[i]->sym[k].name, CI_UNIT, rel[i]->sym[k].detail, rel[i]->sym[k].doc, 0); + done = 1; + } + else if (D->lex.v[anchor].kind == LT_OP && ltok_len(&D->lex.v[anchor]) == 1 && D->text[D->lex.v[anchor].start] == '@'){ + comp_item(&c, "deterministic", CI_KEYWORD, "@deterministic", "Marks a system as reproducible given the same inputs.", 0); + done = 1; + } + } + if (!done && lw_in_ui_body(D, off)){ + comp_words(&c, LUDIC_WIDGETS, CI_CLASS, "widget"); + comp_words(&c, LUDIC_WIDGET_PROPS, CI_PROPERTY, "widget property"); + } + if (!done){ + comp_words(&c, LUDIC_KW_DECL, CI_KEYWORD, "declaration"); + comp_words(&c, LUDIC_KW_STMT, CI_KEYWORD, "statement"); + comp_words(&c, LUDIC_KW_CLAUSE, CI_KEYWORD, "clause"); + comp_words(&c, LUDIC_TYPES, CI_KEYWORD, "built-in type"); + comp_builtins(&c); + comp_scope(&c, D, off, 0); + /* the shapes people actually type */ + comp_item(&c, "system", CI_SNIPPET, "system … phase … { }", "A system with a phase and a body.", + "system ${1:Name} phase ${2|Start,Input,FixedUpdate,Update,LateUpdate,Render|} {\n $0\n}"); + comp_item(&c, "system+query", CI_SNIPPET, "system … query … { }", "A system that runs once per matching entity.", + "system ${1:Name} phase ${2|Update,FixedUpdate,LateUpdate,Render,Input|}\n query (${3:p}) [${4:Pos}]\n{\n $0\n}"); + comp_item(&c, "component", CI_SNIPPET, "component … { }", "A component with typed fields.", + "component ${1:Name} { ${2:x}: ${3:int} = ${4:0} }"); + comp_item(&c, "archetype", CI_SNIPPET, "archetype … { }", "An entity kind bundling components.", + "archetype ${1:Name} {\n ${2:Pos}\n}"); + comp_item(&c, "for-query", CI_SNIPPET, "for (…) in query […] { }", "Iterate matching entities.", + "for (${1:p}) in query [${2:Pos}] {\n $0\n}"); + comp_item(&c, "scene", CI_SNIPPET, "scene … { layer … }", "A scene with one layer.", + "scene ${1:Name} {\n on enter { $2 }\n layer ${3:Main} {\n $0\n }\n}"); + } + jsb_puts(&s, "]}"); + send_result(id, s.b); + free(s.b); +} + +/* ---------- document lifecycle -------------------------------------------*/ +static void refresh(LDoc* D){ ldoc_reindex(D); lw_classify(&X, D); } + +static void on_did_open(JVal* msg){ + const char* uri = jstr(jpath(msg, "params.textDocument.uri"), 0); + const char* text = jstr(jpath(msg, "params.textDocument.text"), 0); + if (!uri) return; + char* path = lw_uri_to_path(uri); + LDoc* D = lw_by_path(&X, path); + if (!D){ D = lw_new_doc(path, strdup(text ? text : "")); lw_add(&X, D); } + else if (text) ldoc_settext(D, strdup(text)); + free(path); + D->open = 1; + D->version = jint(jpath(msg, "params.textDocument.version"), 0); + refresh(D); + publish_diagnostics(D); +} +static void on_did_change(JVal* msg){ + LDoc* D = doc_of(msg); + if (!D) return; + JVal* changes = jpath(msg, "params.contentChanges"); + JVal* last = jat(changes, changes ? changes->n - 1 : 0); + const char* text = jstr(jget(last, "text"), 0); + if (!text) return; + ldoc_settext(D, strdup(text)); + D->version = jint(jpath(msg, "params.textDocument.version"), D->version + 1); + refresh(D); + /* structural feedback only while typing; the compiler waits for a save, + * because it reads the file from disk and would otherwise report the + * previous save's errors against the current buffer */ + DiagSet ds = {0}; + if (!D->is_markdown) diag_structural(D, &ds); + JSB s = {0}; + jsb_puts(&s, "{\"uri\":"); jsb_str(&s, D->uri); + jsb_puts(&s, ",\"diagnostics\":["); + D->had_diags = ds.n > 0; + for (int i = 0; i < ds.n; i++){ + if (i) jsb_putc(&s, ','); + jsb_putf(&s, "{\"range\":{\"start\":{\"line\":%d,\"character\":%d},\"end\":{\"line\":%d,\"character\":%d}},\"severity\":%d,\"source\":\"ludic\",\"message\":", + ds.v[i].line, ds.v[i].col, ds.v[i].endline, ds.v[i].endcol, ds.v[i].severity); + jsb_str(&s, ds.v[i].msg); + jsb_putc(&s, '}'); + } + jsb_puts(&s, "]}"); + send_notify("textDocument/publishDiagnostics", s.b); + free(s.b); free(ds.v); +} +static void on_did_save(JVal* msg){ + LDoc* D = doc_of(msg); + if (!D) return; + const char* text = jstr(jpath(msg, "params.text"), 0); + if (text) ldoc_settext(D, strdup(text)); + else { char* disk = lw_readfile(D->path, 0); if (disk) ldoc_settext(D, disk); } + refresh(D); + publish_diagnostics(D); +} +static void on_did_close(JVal* msg){ + LDoc* D = doc_of(msg); + if (!D) return; + D->open = 0; + char* disk = lw_readfile(D->path, 0); + if (disk){ ldoc_settext(D, disk); refresh(D); } +} + +/* ---------- dispatch ------------------------------------------------------*/ +static void handle(JVal* msg){ + const char* method = jstr(jget(msg, "method"), 0); + JVal* id = jget(msg, "id"); + if (!method) return; + lg("<- %s", method); + + if (!strcmp(method, "initialize")){ on_initialize(msg, id); return; } + if (!strcmp(method, "initialized")) return; + if (!strcmp(method, "shutdown")){ g_shutdown = 1; send_result(id, "null"); return; } + if (!strcmp(method, "exit")){ exit(g_shutdown ? 0 : 1); } + + if (!strcmp(method, "textDocument/didOpen")){ on_did_open(msg); return; } + if (!strcmp(method, "textDocument/didChange")){ on_did_change(msg); return; } + if (!strcmp(method, "textDocument/didSave")){ on_did_save(msg); return; } + if (!strcmp(method, "textDocument/didClose")){ on_did_close(msg); return; } + if (!strcmp(method, "workspace/didChangeConfiguration")){ + JVal* cfg = jpath(msg, "params.settings.ludic"); + const char* cc = jstr(jget(cfg, "compilerPath"), 0); + if (cc && *cc){ free(g_ludicc); g_ludicc = strdup(cc); } + if (jget(cfg, "indentSize")) g_indent = jint(jget(cfg, "indentSize"), g_indent); + if (jget(cfg, "compilerDiagnostics")) g_compiler_diags = jbool(jget(cfg, "compilerDiagnostics"), 1); + return; + } + if (!strcmp(method, "workspace/didChangeWatchedFiles")){ + JVal* ch = jpath(msg, "params.changes"); + for (int i = 0; ch && i < ch->n; i++){ + const char* u = jstr(jget(jat(ch, i), "uri"), 0); + if (!u) continue; + char* p = lw_uri_to_path(u); + LDoc* D = lw_by_path(&X, p); + if (D && !D->open){ char* disk = lw_readfile(p, 0); if (disk){ ldoc_settext(D, disk); refresh(D); } } + else if (!D) lw_ensure(&X, p); + free(p); + } + return; + } + + if (!strcmp(method, "textDocument/documentSymbol")){ on_document_symbol(msg, id); return; } + if (!strcmp(method, "workspace/symbol")){ on_workspace_symbol(msg, id); return; } + if (!strcmp(method, "textDocument/definition") || + !strcmp(method, "textDocument/declaration") || + !strcmp(method, "textDocument/typeDefinition")){ on_definition(msg, id); return; } + if (!strcmp(method, "textDocument/hover")){ on_hover(msg, id); return; } + if (!strcmp(method, "textDocument/references")){ on_references(msg, id); return; } + if (!strcmp(method, "textDocument/documentHighlight")){ on_document_highlight(msg, id); return; } + if (!strcmp(method, "textDocument/prepareRename")){ on_prepare_rename(msg, id); return; } + if (!strcmp(method, "textDocument/rename")){ on_rename(msg, id); return; } + if (!strcmp(method, "textDocument/formatting")){ on_formatting(msg, id, 0); return; } + if (!strcmp(method, "textDocument/rangeFormatting")){ on_formatting(msg, id, 1); return; } + if (!strcmp(method, "textDocument/foldingRange")){ on_folding(msg, id); return; } + if (!strcmp(method, "textDocument/documentLink")){ on_document_link(msg, id); return; } + if (!strcmp(method, "textDocument/inlayHint")){ on_inlay_hint(msg, id); return; } + if (!strcmp(method, "textDocument/signatureHelp")){ on_signature_help(msg, id); return; } + if (!strcmp(method, "textDocument/completion")){ on_completion(msg, id); return; } + if (!strcmp(method, "textDocument/semanticTokens/full") || + !strcmp(method, "textDocument/semanticTokens/range")){ + LDoc* D = doc_of(msg); + if (!D){ send_result(id, "null"); return; } + int from = 0, to = -1; + JVal* r = jpath(msg, "params.range"); + if (r){ from = jint(jpath(msg, "params.range.start.line"), 0); to = jint(jpath(msg, "params.range.end.line"), -1); } + char* out = semantic_tokens(D, from, to); + send_result(id, out); + free(out); + return; + } + + /* an unknown request still needs an answer, or the client hangs */ + if (id) send_result(id, "null"); +} + +static const char* USAGE = +"ludic-lsp — the Ludic language server (LSP 3.17 over stdio)\n" +"\n" +"usage: ludic-lsp [--stdio] [--compiler PATH] [--log FILE] [--no-compiler-diagnostics]\n" +"\n" +"Editors normally launch this themselves. --stdio is accepted and ignored;\n" +"stdio is the only transport.\n"; + +int main(int argc, char** argv){ + signal(SIGPIPE, SIG_IGN); + for (int i = 1; i < argc; i++){ + if (!strcmp(argv[i], "--compiler") && i + 1 < argc) g_ludicc = strdup(argv[++i]); + else if (!strcmp(argv[i], "--log") && i + 1 < argc) g_log = fopen(argv[++i], "w"); + else if (!strcmp(argv[i], "--no-compiler-diagnostics")) g_compiler_diags = 0; + else if (!strcmp(argv[i], "--indent") && i + 1 < argc) g_indent = atoi(argv[++i]); + else if (!strcmp(argv[i], "--stdio")) ; + else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")){ fputs(USAGE, stdout); return 0; } + else if (!strcmp(argv[i], "--version")){ puts("ludic-lsp 1.0.0"); return 0; } + } + for (;;){ + char* raw = read_message(); + if (!raw) break; + JVal* msg = jparse(raw); + handle(msg); + jfree(msg); + free(raw); + } + return 0; +} diff --git a/tools/ludic-tools/ludic_syntax.h b/tools/ludic-tools/ludic_syntax.h new file mode 100644 index 00000000..df1fa73f --- /dev/null +++ b/tools/ludic-tools/ludic_syntax.h @@ -0,0 +1,321 @@ +/* ============================================================================ + * ludic_syntax.h — the lexical layer shared by every Ludic editor tool. + * + * One lexer, one vocabulary. `ludic-fmt`, `ludic-lsp` and the generated + * TextMate grammar all read their keyword/builtin/type tables from here, so an + * addition to the language shows up in every editor at once instead of drifting + * across six hand-maintained copies. + * + * Unlike the compiler's lexer (compiler/ludicc.c) this one is written for + * editors: it keeps comments, keeps newlines, records byte spans for every + * token, and never exits on bad input — a stray character becomes an LT_ERR + * token and lexing continues, because a file being typed into is malformed most + * of the time. + * ==========================================================================*/ +#ifndef LUDIC_SYNTAX_H +#define LUDIC_SYNTAX_H + +#include +#include +#include +#include + +/* ---------- token kinds ---------------------------------------------------*/ +enum { + LT_EOF, LT_NL, LT_COMMENT, + LT_ID, /* a plain identifier */ + LT_KW, /* a reserved word (see KEYWORDS) */ + LT_TYPE, /* a built-in type name: int fixed bool entity str ptr void */ + LT_PHASE, /* Start Input FixedUpdate Update LateUpdate Render */ + LT_BOOL, /* true false */ + LT_INT, LT_FLOAT, LT_STR, LT_CHAR, + LT_ANNO, /* @deterministic — the '@' and the name as one token */ + LT_OP, + LT_ERR +}; + +typedef struct { + int kind; + int start, end; /* byte offsets into the source buffer */ + int line; /* 0-based */ + int bad; /* set on an unterminated string / stray character */ +} LTok; + +typedef struct { + LTok* v; int n, cap; + const char* src; + int* linestart; int nline, caplin; +} LLex; + +/* ---------- the vocabulary ------------------------------------------------*/ +/* Reserved words, grouped so editors can colour them differently. The groups + * mirror the compiler's parser: anything parse_decl() dispatches on is a + * declaration keyword, anything stmt() dispatches on is a statement keyword. */ +static const char* LUDIC_KW_DECL[] = { + "game","module","import","component","struct","archetype","ui","scene","layer", + "const","var","export","fn","pure","extern","system","edge","start","on", 0 +}; +static const char* LUDIC_KW_CLAUSE[] = { + "phase","query","reads","writes","needs","uses", + "requires","ensures","invariant","effects", 0 +}; +static const char* LUDIC_KW_STMT[] = { + "let","return","if","else","when","while","for","in","spawn","despawn", + "match","machine","state","become","enter","where","and","or","not", + "break","continue","new", 0 +}; +static const char* LUDIC_TYPES[] = { + "int","fixed","bool","entity","str","ptr","void", 0 +}; +static const char* LUDIC_PHASES[] = { + "Start","Input","FixedUpdate","Update","LateUpdate","Render", 0 +}; +static const char* LUDIC_WIDGETS[] = { + "panel","col","row","label","button","image","spacer", 0 +}; +static const char* LUDIC_WIDGET_PROPS[] = { + "id","text","skin","image","align","w","h","pad","gap","size","font", + "inset","grow","bg","fg","border","focus","x","y", 0 +}; + +/* A builtin is a name the runtime provides (`clear(c)` -> rt_clear). An + * intrinsic is a name the compiler lowers directly to libc/OS. Editors treat + * both as "standard library", but the signatures differ, so they stay apart. */ +typedef struct { const char* name; const char* sig; const char* doc; } LBuiltin; + +static const LBuiltin LUDIC_BUILTINS[] = { + {"min","min(a: int, b: int) -> int","Smaller of two integers."}, + {"max","max(a: int, b: int) -> int","Larger of two integers."}, + {"abs","abs(a: int) -> int","Absolute value."}, + {"clamp","clamp(v: int, lo: int, hi: int) -> int","Constrain v to [lo, hi]."}, + {"seed","seed(i: int)","Seed the deterministic RNG."}, + {"rng_range","rng_range(lo: int, hi: int) -> int","Deterministic integer in [lo, hi]."}, + {"rng_chance","rng_chance(pct: int) -> bool","True pct% of the time, deterministically."}, + {"fx","fx(i: int) -> fixed","Widen an int to Q16.16 fixed-point."}, + {"flr","flr(f: fixed) -> int","Truncate a fixed-point value toward zero."}, + {"map_size","map_size(w: int, h: int)","Set the tilemap dimensions."}, + {"map_row","map_row(y: int, row: str)","Fill one tilemap row from a string."}, + {"tile","tile(x: int, y: int) -> int","Tile code at a map cell."}, + {"clear","clear(color: int)","Clear the framebuffer to a 0xRRGGBB colour."}, + {"present","present()","Push the framebuffer to the window (or out.ppm when headless)."}, + {"fill_rect","fill_rect(x: int, y: int, w: int, h: int, color: int)","Filled rectangle."}, + {"frame_rect","frame_rect(x: int, y: int, w: int, h: int, color: int)","One-pixel rectangle outline."}, + {"put_px","put_px(x: int, y: int, color: int)","Write a single pixel."}, + {"text","text(x: int, y: int, s: str, color: int, scale: int)","Draw text with the built-in 5x7 bitmap font."}, + {"text_int","text_int(x: int, y: int, n: int, color: int, scale: int)","Draw an integer with the 5x7 bitmap font."}, + {"font_load","font_load(path: str) -> int","Load a TrueType .ttf/.ttc; returns a font id."}, + {"text_ttf","text_ttf(font: int, x: int, y: int, utf8: str, color: int, px: int)","Draw UTF-8 text with a TrueType font."}, + {"text_w","text_w(font: int, utf8: str, px: int) -> int","Advance width of the string, in pixels."}, + {"text_h","text_h(font: int, px: int) -> int","Line height of the font, in pixels."}, + {"image_load","image_load(path: str) -> int","Decode a PNG into an image id."}, + {"draw_image","draw_image(id: int, x: int, y: int)","Blit an image at its natural size."}, + {"draw_image_scaled","draw_image_scaled(id: int, x: int, y: int, w: int, h: int)","Blit an image stretched to w x h."}, + {"draw_9slice","draw_9slice(id: int, x: int, y: int, w: int, h: int, inset: int)","Nine-slice an image across a w x h box."}, + {"load_png","load_png(path: str) -> int","Decode a PNG as a 16x16 sprite sheet; returns the first sprite id."}, + {"load_sprites","load_sprites(path: str)","Load the sprite sheet used by draw_sprite."}, + {"draw_sprite","draw_sprite(id: int, x: int, y: int)","Blit a sprite."}, + {"draw_sprite_scaled","draw_sprite_scaled(id: int, x: int, y: int, scale: int)","Blit a sprite at an integer scale."}, + {"ui_build","ui_build()","Construct every declared `ui` tree (loads skins and images)."}, + {"ui_open","ui_open(id: int)","Make a ui tree active and focus its first button."}, + {"ui_tick","ui_tick(key: int)","Feed a key to the UI: w/s move focus, space/enter activate."}, + {"ui_render","ui_render()","Lay out and draw the active ui tree."}, + {"ui_clicked","ui_clicked(id: int) -> bool","True on the frame a widget was activated."}, + {"ui_set_text","ui_set_text(id: int, s: str)","Replace a widget's text."}, + {"ui_set_int","ui_set_int(id: int, n: int)","Replace a widget's text with a number."}, + {"ui_focus","ui_focus(id: int)","Move keyboard focus to a widget."}, + {"ui_focused","ui_focused() -> int","Id of the focused widget."}, + {"ui_visible","ui_visible(id: int, on: bool)","Show or hide a widget subtree."}, + {"key","key() -> int","Key code pressed this frame, 0 if none."}, + {"reg","reg(i: int) -> int","Read one of the 64 integer resources shared by systems."}, + {"setreg","setreg(i: int, v: int)","Write one of the 64 integer resources."}, + {"self","self() -> entity","The entity of the innermost query loop."}, + {"save","save()","Write a binary snapshot of the whole ECS world."}, + {"load","load() -> bool","Restore the snapshot; false if there is none."}, + {"status","status(s: str)","Set the one-line status message."}, + {"print_int","print_int(i: int)","Print an integer to stdout."}, + {"quit","quit()","Stop the frame loop and exit."}, + {0,0,0} +}; + +static const LBuiltin LUDIC_INTRINSICS[] = { + {"mem_alloc","mem_alloc(n: int) -> ptr","Allocate n bytes (malloc)."}, + {"mem_realloc","mem_realloc(p: ptr, n: int) -> ptr","Resize a block to n bytes, preserving its contents (realloc)."}, + {"os_argc","os_argc() -> int","Number of command-line arguments, argv[0] included."}, + {"os_arg","os_arg(i: int) -> str","The i-th command-line argument."}, + {"file_stderr","file_stderr() -> ptr","The standard error stream, for file_write."}, + {"mem_free","mem_free(p: ptr)","Release an allocation."}, + {"mem_copy","mem_copy(dst: ptr, src: ptr, n: int)","memcpy."}, + {"mem_set","mem_set(p: ptr, byte: int, n: int)","memset."}, + {"peek8","peek8(p: ptr, off: int) -> int","Read one byte."}, + {"poke8","poke8(p: ptr, off: int, v: int)","Write one byte."}, + {"peek32","peek32(p: ptr, off: int) -> int","Read a 32-bit word."}, + {"poke32","poke32(p: ptr, off: int, v: int)","Write a 32-bit word."}, + {"peekp","peekp(p: ptr, off: int) -> ptr","Read a pointer-sized word."}, + {"pokep","pokep(p: ptr, off: int, v: ptr)","Write a pointer-sized word."}, + {"peekf","peekf(p: ptr, off: int) -> fixed","Read a fixed-point word."}, + {"pokef","pokef(p: ptr, off: int, v: fixed)","Write a fixed-point word."}, + {"ptr_add","ptr_add(p: ptr, off: int) -> ptr","Offset a pointer by bytes."}, + {"ptr_null","ptr_null() -> ptr","The null pointer."}, + {"ptr_is_null","ptr_is_null(p: ptr) -> bool","Null test."}, + {"as_fixed","as_fixed(i: int) -> fixed","Reinterpret an int as fixed (no conversion)."}, + {"as_int","as_int(f: fixed) -> int","Reinterpret a fixed as int (no conversion)."}, + {"file_open","file_open(path: str, mode: str) -> ptr","fopen."}, + {"file_read","file_read(f: ptr, buf: ptr, n: int) -> int","fread."}, + {"file_write","file_write(f: ptr, buf: ptr, n: int) -> int","fwrite."}, + {"file_seek","file_seek(f: ptr, off: int, whence: int) -> int","fseek."}, + {"file_tell","file_tell(f: ptr) -> int","ftell."}, + {"file_close","file_close(f: ptr)","fclose."}, + {"read_byte","read_byte() -> int","Read one byte from stdin, -1 at EOF."}, + {"write_byte","write_byte(b: int)","Write one byte to stdout."}, + {"print_str","print_str(s: str)","Write a string to stdout."}, + {"str_len","str_len(s: str) -> int","Length of a string in bytes."}, + {"shl","shl(v: int, n: int) -> int","Shift left."}, + {"shr","shr(v: int, n: int) -> int","Logical shift right."}, + {"band","band(a: int, b: int) -> int","Bitwise and."}, + {"bor","bor(a: int, b: int) -> int","Bitwise or."}, + {"bxor","bxor(a: int, b: int) -> int","Bitwise xor."}, + {"bnot","bnot(a: int) -> int","Bitwise not."}, + {"os_exit","os_exit(code: int)","Terminate the process."}, + {"os_time","os_time() -> int","Seconds since the epoch."}, + {"is_windowed","is_windowed() -> bool","True when the build has a window."}, + {"game_title","game_title() -> str","The name from the `game` declaration."}, + {"win_open","win_open(title: str, w: int, h: int, scale: int)","Open the platform window."}, + {"win_poll","win_poll() -> int","Pump the event queue; returns a key code."}, + {"win_present","win_present(px: ptr, w: int, h: int)","Blit a framebuffer to the window."}, + {"win_running","win_running() -> bool","False once the window has been closed."}, + {"win_close","win_close()","Close the platform window."}, + {0,0,0} +}; + +static int lud_in(const char** set, const char* s){ + for (int i = 0; set[i]; i++) if (!strcmp(set[i], s)) return 1; + return 0; +} +static const LBuiltin* lud_lookup(const LBuiltin* t, const char* s){ + for (int i = 0; t[i].name; i++) if (!strcmp(t[i].name, s)) return &t[i]; + return 0; +} +static int lud_is_keyword(const char* s){ + return lud_in(LUDIC_KW_DECL, s) || lud_in(LUDIC_KW_CLAUSE, s) || lud_in(LUDIC_KW_STMT, s); +} + +/* ---------- lexing --------------------------------------------------------*/ +static void ltok_push(LLex* L, int kind, int start, int end, int line, int bad){ + if (L->n >= L->cap){ L->cap = L->cap ? L->cap * 2 : 512; L->v = realloc(L->v, L->cap * sizeof(LTok)); } + L->v[L->n++] = (LTok){ kind, start, end, line, bad }; +} +static void lline_push(LLex* L, int off){ + if (L->nline >= L->caplin){ L->caplin = L->caplin ? L->caplin * 2 : 256; L->linestart = realloc(L->linestart, L->caplin * sizeof(int)); } + L->linestart[L->nline++] = off; +} + +static const char* LUDIC_OPS2[] = { "->","+=","-=","*=","/=","==","!=","<=",">=","&&","||","..","=>", 0 }; + +/* Lex the whole buffer. Comments and newlines are kept — the formatter needs + * both, and a highlighter needs the comments. */ +static void lud_lex(LLex* L, const char* src){ + memset(L, 0, sizeof(*L)); + L->src = src; + lline_push(L, 0); + int i = 0, line = 0; + while (src[i]){ + char c = src[i]; + if (c == '\n'){ ltok_push(L, LT_NL, i, i + 1, line, 0); i++; line++; lline_push(L, i); continue; } + if (c == ' ' || c == '\t' || c == '\r'){ i++; continue; } + if (c == '#'){ int s = i; while (src[i] && src[i] != '\n') i++; ltok_push(L, LT_COMMENT, s, i, line, 0); continue; } + if (c == '"'){ + int s = i; i++; int bad = 0; + while (src[i] && src[i] != '"' && src[i] != '\n'){ if (src[i] == '\\' && src[i+1]) i += 2; else i++; } + if (src[i] == '"') i++; else bad = 1; + ltok_push(L, LT_STR, s, i, line, bad); continue; + } + if (c == '\''){ + int s = i; i++; int bad = 0; + if (src[i] == '\\' && src[i+1]) i += 2; else if (src[i] && src[i] != '\n') i++; + if (src[i] == '\'') i++; else bad = 1; + ltok_push(L, LT_CHAR, s, i, line, bad); continue; + } + if (isdigit((unsigned char)c)){ + int s = i; + if (c == '0' && (src[i+1] == 'x' || src[i+1] == 'X')){ + i += 2; while (isxdigit((unsigned char)src[i])) i++; + ltok_push(L, LT_INT, s, i, line, 0); continue; + } + while (isdigit((unsigned char)src[i])) i++; + if (src[i] == '.' && isdigit((unsigned char)src[i+1])){ + i++; while (isdigit((unsigned char)src[i])) i++; + ltok_push(L, LT_FLOAT, s, i, line, 0); continue; + } + ltok_push(L, LT_INT, s, i, line, 0); continue; + } + /* @name is one token: an annotation reads as a unit, and the formatter + * must never put a space between the sigil and the name. */ + if (c == '@' && (isalpha((unsigned char)src[i+1]) || src[i+1] == '_')){ + int s = i; i++; while (isalnum((unsigned char)src[i]) || src[i] == '_') i++; + ltok_push(L, LT_ANNO, s, i, line, 0); continue; + } + if (isalpha((unsigned char)c) || c == '_'){ + int s = i; while (isalnum((unsigned char)src[i]) || src[i] == '_') i++; + int len = i - s; char w[128]; + if (len < (int)sizeof(w)){ memcpy(w, src + s, len); w[len] = 0; } else { w[0] = 0; } + int k = LT_ID; + if (!strcmp(w, "true") || !strcmp(w, "false")) k = LT_BOOL; + else if (lud_in(LUDIC_TYPES, w)) k = LT_TYPE; + else if (lud_in(LUDIC_PHASES, w)) k = LT_PHASE; + else if (lud_is_keyword(w)) k = LT_KW; + ltok_push(L, k, s, i, line, 0); continue; + } + { + int matched = 0; + for (int k = 0; LUDIC_OPS2[k]; k++) + if (src[i] == LUDIC_OPS2[k][0] && src[i+1] == LUDIC_OPS2[k][1]){ + ltok_push(L, LT_OP, i, i + 2, line, 0); i += 2; matched = 1; break; + } + if (matched) continue; + } + if (c == ';'){ ltok_push(L, LT_OP, i, i + 1, line, 0); i++; continue; } + if (strchr("+-*/%<>=(){}[],:.!@", c)){ ltok_push(L, LT_OP, i, i + 1, line, 0); i++; continue; } + /* Anything else is an error token — but a whole UTF-8 character's worth + * at a time. Splitting a multi-byte character into one token per byte + * would let a consumer that re-emits tokens (the formatter) put spaces + * inside it and corrupt the file. */ + { + unsigned char u = (unsigned char)c; + int len = u < 0x80 ? 1 : u < 0xE0 ? 2 : u < 0xF0 ? 3 : 4; + for (int k = 1; k < len; k++) if (!src[i + k] || ((unsigned char)src[i + k] & 0xC0) != 0x80){ len = k; break; } + ltok_push(L, LT_ERR, i, i + len, line, 1); i += len; + } + } + ltok_push(L, LT_EOF, i, i, line, 0); +} +static void lud_lex_free(LLex* L){ free(L->v); free(L->linestart); memset(L, 0, sizeof(*L)); } + +/* ---------- helpers over the token stream --------------------------------*/ +static int ltok_len(const LTok* t){ return t->end - t->start; } +static int ltok_is(const LLex* L, int i, const char* s){ + if (i < 0 || i >= L->n) return 0; + const LTok* t = &L->v[i]; int n = ltok_len(t); + return (int)strlen(s) == n && !strncmp(L->src + t->start, s, n); +} +/* Copy a token's text into a caller buffer; returns buf. */ +static char* ltok_text(const LLex* L, int i, char* buf, int cap){ + const LTok* t = &L->v[i]; int n = ltok_len(t); + if (n >= cap) n = cap - 1; + memcpy(buf, L->src + t->start, n); buf[n] = 0; return buf; +} +/* Index of the next token that is not a newline or comment, or -1. */ +static int ltok_next_sig(const LLex* L, int i){ + for (int j = i + 1; j < L->n; j++){ + int k = L->v[j].kind; + if (k != LT_NL && k != LT_COMMENT) return j; + } + return -1; +} +static int ltok_prev_sig(const LLex* L, int i){ + for (int j = i - 1; j >= 0; j--){ + int k = L->v[j].kind; + if (k != LT_NL && k != LT_COMMENT) return j; + } + return -1; +} +#endif /* LUDIC_SYNTAX_H */ diff --git a/tools/ludic-tools/ludic_workspace.h b/tools/ludic-tools/ludic_workspace.h new file mode 100644 index 00000000..c1a6a855 --- /dev/null +++ b/tools/ludic-tools/ludic_workspace.h @@ -0,0 +1,405 @@ +/* ============================================================================ + * ludic_workspace.h — many documents, one project. + * + * Ludic programs are multi-file: `import "rules.ludic"` splices a fragment into + * whichever `game`/`module` file pulled it in. An imported fragment is NOT a + * standalone program — it has no `game` block — so running the compiler on it + * directly is meaningless. This layer keeps that straight: it knows which files + * form a compilation unit, which file is its root, and it resolves a name + * against the whole unit rather than one buffer. + * ==========================================================================*/ +#ifndef LUDIC_WORKSPACE_H +#define LUDIC_WORKSPACE_H + +#include "ludic_index.h" +#include +#include +#include +#include + +/* ---------- paths & URIs --------------------------------------------------*/ +static char* lw_readfile(const char* path, long* out_n){ + FILE* f = fopen(path, "rb"); if (!f) return 0; + fseek(f, 0, SEEK_END); long n = ftell(f); fseek(f, 0, SEEK_SET); + char* b = malloc(n + 1); + if (fread(b, 1, n, f) != (size_t)n){ fclose(f); free(b); return 0; } + b[n] = 0; fclose(f); + if (out_n) *out_n = n; + return b; +} +static int lw_hex(int c){ return c >= '0' && c <= '9' ? c - '0' : (c | 32) >= 'a' && (c | 32) <= 'f' ? (c | 32) - 'a' + 10 : -1; } +static char* lw_uri_to_path(const char* uri){ + if (strncmp(uri, "file://", 7)) return strdup(uri); + const char* s = uri + 7; + /* file://host/path is not something an editor sends for local files */ + char* out = malloc(strlen(s) + 1); int j = 0; + for (int i = 0; s[i]; ){ + if (s[i] == '%' && lw_hex(s[i+1]) >= 0 && lw_hex(s[i+2]) >= 0){ + out[j++] = (char)(lw_hex(s[i+1]) * 16 + lw_hex(s[i+2])); i += 3; + } else out[j++] = s[i++]; + } + out[j] = 0; + return out; +} +static char* lw_path_to_uri(const char* path){ + static const char* safe = "-_.~/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + size_t cap = strlen(path) * 3 + 16; + char* out = malloc(cap); + strcpy(out, "file://"); + int j = 7; + for (int i = 0; path[i]; i++){ + unsigned char c = (unsigned char)path[i]; + if (strchr(safe, c)) out[j++] = c; + else j += sprintf(out + j, "%%%02X", c); + } + out[j] = 0; + return out; +} +static char* lw_dirname(const char* p){ + char* d = strdup(p); char* s = strrchr(d, '/'); + if (s) *s = 0; else { free(d); d = strdup("."); } + return d; +} +static char* lw_join(const char* dir, const char* rel){ + if (rel[0] == '/') return strdup(rel); + size_t n = strlen(dir) + strlen(rel) + 2; + char* p = malloc(n); snprintf(p, n, "%s/%s", dir, rel); + char real[PATH_MAX]; + if (realpath(p, real)){ free(p); return strdup(real); } + return p; +} +static int lw_ends(const char* s, const char* suf){ + size_t a = strlen(s), b = strlen(suf); + return a >= b && !strcmp(s + a - b, suf); +} + +/* ---------- Markdown ------------------------------------------------------ + * Fenced Ludic inside prose is real Ludic and deserves the same treatment. The + * trick that makes it free: copy the document and blank out every byte that is + * not inside a ```ludic fence. Offsets, lines and columns still match the file + * on disk exactly, so every feature built on top — highlighting, hover, + * go-to-definition, diagnostics — works on a .md without knowing about it. */ +static char* lw_scrub_markdown(const char* src){ + char* out = strdup(src); + int i = 0, n = (int)strlen(src); + while (i < n){ + int ls = i, le = i; + while (le < n && src[le] != '\n') le++; + int ind = 0; while (ls + ind < le && src[ls + ind] == ' ') ind++; + int j = ls + ind; char m = j < le ? src[j] : 0; + int run = 0; while (j + run < le && src[j + run] == m) run++; + int fenced = (m == '`' || m == '~') && run >= 3; + int info = j + run; + int is_ludic = 0; + if (fenced){ + int k = info; while (k < le && (src[k] == ' ' || src[k] == '\t')) k++; + is_ludic = (le - k >= 5) && !strncasecmp(src + k, "ludic", 5) && + (le - k == 5 || src[k+5] == ' ' || src[k+5] == '\t' || src[k+5] == '\r'); + } + /* blank the fence line itself either way */ + for (int k = ls; k < le; k++) out[k] = ' '; + i = le < n ? le + 1 : n; + if (!fenced) continue; + /* inside a fence: keep the body only when the info string says ludic */ + while (i < n){ + int bs = i, be = i; + while (be < n && src[be] != '\n') be++; + int bi = 0; while (bs + bi < be && src[bs + bi] == ' ') bi++; + int cj = bs + bi, crun = 0; + while (cj + crun < be && src[cj + crun] == m) crun++; + int only = 1; + for (int k = cj + crun; k < be; k++) if (src[k] != ' ' && src[k] != '\r'){ only = 0; break; } + if (crun >= run && only){ + for (int k = bs; k < be; k++) out[k] = ' '; + i = be < n ? be + 1 : n; + break; + } + if (!is_ludic) for (int k = bs; k < be; k++) out[k] = ' '; + i = be < n ? be + 1 : n; + } + } + return out; +} + +/* ---------- documents -----------------------------------------------------*/ +static void ldoc_settext(LDoc* D, char* raw){ + if (D->text != D->raw) free(D->text); + free(D->raw); + D->raw = raw; + D->text = D->is_markdown ? lw_scrub_markdown(raw) : raw; +} +static void ldoc_reindex(LDoc* D){ + lud_lex_free(&D->lex); + lud_lex(&D->lex, D->text); + ldoc_match_braces(D); + ldoc_parse(D); + free(D->cls); + D->cls = calloc(D->lex.n + 1, 1); +} +static LDoc* lw_new_doc(const char* path, char* text){ + LDoc* D = calloc(1, sizeof(LDoc)); + char real[PATH_MAX]; + D->path = realpath(path, real) ? strdup(real) : strdup(path); + D->uri = lw_path_to_uri(D->path); + D->is_markdown = lw_ends(D->path, ".md") || lw_ends(D->path, ".markdown"); + ldoc_settext(D, text); + ldoc_reindex(D); + return D; +} +static void lw_add(LIndex* X, LDoc* D){ + if (X->n >= X->cap){ X->cap = X->cap ? X->cap * 2 : 32; X->d = realloc(X->d, X->cap * sizeof(LDoc*)); } + X->d[X->n++] = D; +} +static LDoc* lw_by_path(LIndex* X, const char* path){ + char real[PATH_MAX]; + const char* p = realpath(path, real) ? real : path; + for (int i = 0; i < X->n; i++) if (!strcmp(X->d[i]->path, p)) return X->d[i]; + return 0; +} +static LDoc* lw_by_uri(LIndex* X, const char* uri){ + char* p = lw_uri_to_path(uri); + LDoc* D = lw_by_path(X, p); + if (!D) for (int i = 0; i < X->n; i++) if (!strcmp(X->d[i]->uri, uri)){ D = X->d[i]; break; } + free(p); + return D; +} +/* Load a file into the index if it is not there yet. */ +static LDoc* lw_ensure(LIndex* X, const char* path){ + LDoc* D = lw_by_path(X, path); + if (D) return D; + char* text = lw_readfile(path, 0); + if (!text) return 0; + D = lw_new_doc(path, text); + lw_add(X, D); + return D; +} + +/* Walk the workspace once at startup so that go-to-definition works across + * files the editor has never opened. Skips the usual noise directories. */ +static void lw_scan(LIndex* X, const char* dir, int depth){ + if (depth > 8) return; + DIR* d = opendir(dir); if (!d) return; + struct dirent* e; + while ((e = readdir(d))){ + if (e->d_name[0] == '.') continue; + if (!strcmp(e->d_name, "build") || !strcmp(e->d_name, "node_modules") || + !strcmp(e->d_name, "target") || !strcmp(e->d_name, "out")) continue; + char p[PATH_MAX]; snprintf(p, sizeof(p), "%s/%s", dir, e->d_name); + struct stat st; if (stat(p, &st)) continue; + if (S_ISDIR(st.st_mode)) lw_scan(X, p, depth + 1); + else if (lw_ends(e->d_name, ".ludic")) lw_ensure(X, p); + } + closedir(d); +} + +/* ---------- compilation units -------------------------------------------- + * `related` = every document that shares a compilation unit with D: the unit + * root that (transitively) imports D, plus everything that root imports. */ +static void lw_imports_of(LIndex* X, LDoc* D, LDoc** out, int* n, int max){ + for (int i = 0; i < D->nimport; i++){ + char* dir = lw_dirname(D->path); + char* full = lw_join(dir, D->imports[i]); + free(dir); + LDoc* I = lw_ensure(X, full); + free(full); + if (!I) continue; + int seen = 0; for (int k = 0; k < *n; k++) if (out[k] == I) seen = 1; + if (seen || *n >= max) continue; + out[(*n)++] = I; + lw_imports_of(X, I, out, n, max); + } +} +static int lw_related(LIndex* X, LDoc* D, LDoc** out, int max){ + int n = 0; + if (!D) return 0; + out[n++] = D; + lw_imports_of(X, D, out, &n, max); + /* pull in any unit root that reaches D, and that root's other imports */ + for (int i = 0; i < X->n && n < max; i++){ + LDoc* R = X->d[i]; + if (!R->is_unit || R == D) continue; + LDoc* reach[128]; int rn = 0; + lw_imports_of(X, R, reach, &rn, 128); + int hits = 0; for (int k = 0; k < rn; k++) if (reach[k] == D) hits = 1; + if (!hits) continue; + int seen = 0; for (int k = 0; k < n; k++) if (out[k] == R) seen = 1; + if (!seen && n < max) out[n++] = R; + for (int k = 0; k < rn && n < max; k++){ + int s2 = 0; for (int q = 0; q < n; q++) if (out[q] == reach[k]) s2 = 1; + if (!s2) out[n++] = reach[k]; + } + } + return n; +} +/* The file `ludicc` should actually be pointed at when checking D. */ +static LDoc* lw_unit_root(LIndex* X, LDoc* D){ + if (!D || D->is_markdown) return 0; + if (D->is_unit) return D; + LDoc* rel[128]; int n = lw_related(X, D, rel, 128); + /* a `game` beats a `module`: it is the one that actually compiles */ + for (int i = 0; i < n; i++) if (rel[i]->is_unit && !rel[i]->is_module && !rel[i]->is_markdown) return rel[i]; + for (int i = 0; i < n; i++) if (rel[i]->is_unit && !rel[i]->is_markdown) return rel[i]; + return 0; +} + +/* ---------- name resolution ----------------------------------------------*/ +static int lsym_is_toplevel(int kind){ + switch (kind){ + case LS_COMPONENT: case LS_ARCHETYPE: case LS_CONST: case LS_VAR: + case LS_FN: case LS_EXTERN: case LS_SYSTEM: case LS_UI: case LS_WIDGET: + case LS_SCENE: case LS_LAYER: case LS_UNIT: + return 1; + default: return 0; + } +} +static int lsym_is_local(int kind){ + return kind == LS_LOCAL || kind == LS_PARAM || kind == LS_QUERYVAR || kind == LS_STATE; +} +/* The innermost local binding of `name` visible at byte offset `off`. */ +static int lw_find_local(LDoc* D, const char* name, int off){ + int best = -1; + for (int i = 0; i < D->nsym; i++){ + LSym* s = &D->sym[i]; + if (!lsym_is_local(s->kind) || strcmp(s->name, name)) continue; + if (off < s->body_start || off > s->body_end) continue; + if (best < 0 || s->body_start >= D->sym[best].body_start) best = i; + } + return best; +} +static int lw_find_top(LIndex* X, LDoc* D, const char* name, LDoc** owner){ + LDoc* rel[128]; int n = lw_related(X, D, rel, 128); + for (int i = 0; i < n; i++) + for (int k = 0; k < rel[i]->nsym; k++) + if (lsym_is_toplevel(rel[i]->sym[k].kind) && !strcmp(rel[i]->sym[k].name, name)){ + *owner = rel[i]; return k; + } + /* fall back to the whole workspace — better a cross-unit jump than none */ + for (int i = 0; i < X->n; i++) + for (int k = 0; k < X->d[i]->nsym; k++) + if (lsym_is_toplevel(X->d[i]->sym[k].kind) && !strcmp(X->d[i]->sym[k].name, name)){ + *owner = X->d[i]; return k; + } + return -1; +} +/* The component a dotted receiver has, e.g. `p` in `p.x` when p came from a + * query binding or a typed parameter. Returns the component symbol or -1. */ +static int lw_receiver_component(LIndex* X, LDoc* D, int dot_tok, LDoc** owner){ + int recv = ltok_prev_sig(&D->lex, dot_tok); + if (recv < 0 || D->lex.v[recv].kind != LT_ID) return -1; + char name[96]; ltok_text(&D->lex, recv, name, sizeof(name)); + int l = lw_find_local(D, name, D->lex.v[recv].start); + const char* ty = 0; + if (l >= 0) ty = D->sym[l].type; + else { + LDoc* o; int t = lw_find_top(X, D, name, &o); + if (t >= 0) ty = o->sym[t].type; + } + if (!ty || !ty[0]) return -1; + return lw_find_top(X, D, ty, owner); +} + +/* ---------- semantic classification --------------------------------------*/ +static int lw_first_on_line(LDoc* D, int tok){ + int p = ltok_prev_sig(&D->lex, tok); + return p < 0 || D->lex.v[p].line != D->lex.v[tok].line; +} +static int lw_in_ui_body(LDoc* D, int off){ + for (int i = 0; i < D->nsym; i++) + if (D->sym[i].kind == LS_UI && off > D->sym[i].body_start && off < D->sym[i].body_end) return 1; + return 0; +} +static void lw_classify(LIndex* X, LDoc* D){ + if (!D->cls) D->cls = calloc(D->lex.n + 1, 1); + for (int i = 0; i < D->lex.n; i++){ + const LTok* t = &D->lex.v[i]; + int c = SC_NONE; + switch (t->kind){ + case LT_COMMENT: c = SC_COMMENT; break; + case LT_STR: case LT_CHAR: c = SC_STRING; break; + case LT_INT: case LT_FLOAT: c = SC_NUMBER; break; + case LT_BOOL: case LT_KW: c = SC_KEYWORD; break; + case LT_TYPE: c = SC_TYPE; break; + case LT_PHASE: c = SC_PHASE; break; + case LT_ANNO: c = SC_ANNOTATION; break; + case LT_OP: c = SC_OPERATOR; break; + case LT_ID: c = SC_UNKNOWN; break; + default: c = SC_NONE; break; + } + if (t->kind != LT_ID){ D->cls[i] = (unsigned char)c; continue; } + + char name[96]; ltok_text(&D->lex, i, name, sizeof(name)); + + /* 1. the token IS a declaration's name */ + int decl = -1; + for (int s = 0; s < D->nsym; s++) if (D->sym[s].tok == i){ decl = s; break; } + if (decl >= 0){ + switch (D->sym[decl].kind){ + case LS_COMPONENT: c = SC_COMPONENT; break; + case LS_ARCHETYPE: c = SC_ARCHETYPE; break; + case LS_FIELD: c = SC_FIELD; break; + case LS_CONST: c = SC_CONST; break; + case LS_VAR: c = SC_MODVAR; break; + case LS_FN: case LS_EXTERN: c = SC_FUNCTION; break; + case LS_SYSTEM: c = SC_SYSTEM; break; + case LS_UI: c = SC_UI; break; + case LS_WIDGET: c = SC_CONST; break; /* UI_Foo is a handle */ + case LS_SCENE: c = SC_SCENE; break; + case LS_LAYER: c = SC_LAYER; break; + case LS_PARAM: c = SC_PARAM; break; + case LS_QUERYVAR: case LS_LOCAL: case LS_STATE: c = SC_VARIABLE; break; + case LS_UNIT: c = SC_UI; break; + default: c = SC_UNKNOWN; + } + D->cls[i] = (unsigned char)c; continue; + } + + /* 2. member access: `p.x` */ + int prev = ltok_prev_sig(&D->lex, i); + if (prev >= 0 && ltok_is(&D->lex, prev, ".")){ D->cls[i] = SC_FIELD; continue; } + + int next = ltok_next_sig(&D->lex, i); + int followed_by_eq = next >= 0 && ltok_is(&D->lex, next, "="); + + /* 3. inside a `ui` block a bare word is a widget type and `k=` a prop — + * and those names (text, image, size) collide with builtins, so this + * has to be decided before the builtin table is consulted. */ + if (lw_in_ui_body(D, t->start)){ + if (followed_by_eq){ D->cls[i] = SC_PROP; continue; } + if (lw_first_on_line(D, i) || (prev >= 0 && (ltok_is(&D->lex, prev, "{") || ltok_is(&D->lex, prev, "}")))){ + D->cls[i] = lud_in(LUDIC_WIDGETS, name) ? SC_WIDGET : SC_UI; continue; + } + } + + /* 4. a local binding in scope */ + int l = lw_find_local(D, name, t->start); + if (l >= 0){ D->cls[i] = D->sym[l].kind == LS_PARAM ? SC_PARAM : SC_VARIABLE; continue; } + + /* 5. a declaration somewhere in the compilation unit */ + LDoc* owner = 0; int top = lw_find_top(X, D, name, &owner); + if (top >= 0){ + switch (owner->sym[top].kind){ + case LS_COMPONENT: c = SC_COMPONENT; break; + case LS_ARCHETYPE: c = SC_ARCHETYPE; break; + case LS_CONST: c = SC_CONST; break; + case LS_VAR: c = SC_MODVAR; break; + case LS_FN: case LS_EXTERN: c = SC_FUNCTION; break; + case LS_SYSTEM: c = SC_SYSTEM; break; + case LS_UI: c = SC_UI; break; + case LS_WIDGET: c = SC_CONST; break; + case LS_SCENE: c = SC_SCENE; break; + case LS_LAYER: c = SC_LAYER; break; + default: c = SC_UNKNOWN; + } + D->cls[i] = (unsigned char)c; continue; + } + + /* 6. the runtime surface */ + if (lud_lookup(LUDIC_BUILTINS, name) || lud_lookup(LUDIC_INTRINSICS, name)){ D->cls[i] = SC_BUILTIN; continue; } + + /* 7. a record field initialiser: `Pos = { x = 10 }` */ + if (followed_by_eq){ D->cls[i] = SC_FIELD; continue; } + + D->cls[i] = SC_UNKNOWN; + } +} +#endif /* LUDIC_WORKSPACE_H */ diff --git a/tools/ludic-web/run.mjs b/tools/ludic-web/run.mjs new file mode 100644 index 00000000..3bc0d3e3 --- /dev/null +++ b/tools/ludic-web/run.mjs @@ -0,0 +1,106 @@ +// ============================================================================ +// tools/ludic-web/run.mjs — run a headless Ludic wasm build under Node. +// +// node tools/ludic-web/run.mjs build/web/snake_headless.wasm --stdin=ddss +// +// The point of this runner is the regression it makes possible: the same game, +// the same input, compiled once for the host and once for wasm32, has to render +// the same frame. Ludic is fixed-point and its RNG is seeded, so "the same" here +// means byte-identical PPM — which is a much stronger check on the wasm backend +// than "it started". +// +// It shares runtime/web/platform.js's Host: files, stdin, stdout and the clock +// are identical services whichever host provides them. Only the window differs, +// and a headless build has none. +// ============================================================================ +import { readFileSync, writeFileSync, existsSync } from 'node:fs'; +import { Host, ExitSignal } from '../../runtime/web/platform.js'; + +const args = process.argv.slice(2); +const modulePath = args.find((a) => !a.startsWith('--')); +const stdin = (args.find((a) => a.startsWith('--stdin=')) || '--stdin=').slice(8); +const maxFrames = Number((args.find((a) => a.startsWith('--frames=')) || '--frames=100000').slice(9)); + +if (!modulePath) { + console.error('usage: run.mjs [--stdin=keys] [--frames=n]'); + process.exit(2); +} + +// Files, backed by the real filesystem: a headless build reads its assets and +// writes out.ppm exactly where the native headless binary does. +class NodeFiles { + constructor() { this.open = new Map(); this.next = 1; } + + fopen(path, mode) { + const h = this.next++; + if (mode.includes('w') || mode.includes('a')) { + this.open.set(h, { path, write: true, chunks: [], size: 0, pos: 0 }); + return h; + } + if (!existsSync(path)) return 0; + this.open.set(h, { path, write: false, data: new Uint8Array(readFileSync(path)), pos: 0 }); + return h; + } + + fread(h, dst, want) { + const f = this.open.get(h); + if (!f || f.write) return 0; + const n = Math.max(0, Math.min(want, f.data.length - f.pos)); + dst.set(f.data.subarray(f.pos, f.pos + n)); + f.pos += n; + return n; + } + + fwrite(h, src, n) { + const f = this.open.get(h); + if (!f || !f.write) return 0; + f.chunks.push(src.slice(0, n)); + f.size += n; f.pos += n; + return n; + } + + fclose(h) { + const f = this.open.get(h); + if (!f) return; + if (f.write) { + const all = new Uint8Array(f.size); + let at = 0; + for (const c of f.chunks) { all.set(c, at); at += c.length; } + writeFileSync(f.path, all); + } + this.open.delete(h); + } + + fseek(h, off, whence) { + const f = this.open.get(h); + if (!f) return -1; + const end = f.write ? f.size : f.data.length; + const base = whence === 1 ? f.pos : whence === 2 ? end : 0; + f.pos = Math.max(0, Math.min(end, base + off)); + return 0; + } + + ftell(h) { const f = this.open.get(h); return f ? f.pos : -1; } +} + +const host = new Host({ files: new NodeFiles(), stdin }); +const { instance } = await WebAssembly.instantiate(readFileSync(modulePath), { env: host.imports() }); +host.bind(instance.exports.memory); + +const { ludic_boot, ludic_frame, ludic_alive, ludic_teardown } = instance.exports; + +let frames = 0; +try { + ludic_boot(); + while (host.running && ludic_alive() && frames < maxFrames) { ludic_frame(); frames++; } + ludic_teardown(); +} catch (e) { + if (!(e instanceof ExitSignal)) throw e; +} +host.flush(); + +if (frames >= maxFrames) { + console.error(`ludic-web: stopped after ${maxFrames} frames (the game never ended)`); + process.exit(1); +} +process.exit(host.exitCode ?? 0); diff --git a/tools/test-grammar.js b/tools/test-grammar.js new file mode 100644 index 00000000..97ad2a46 --- /dev/null +++ b/tools/test-grammar.js @@ -0,0 +1,168 @@ +/* ============================================================================ + * test-grammar.js — tokenise Ludic with the real TextMate engine. + * + * A TextMate grammar is a pile of Oniguruma regexes in a JSON file: nothing + * validates it, and a broken pattern shows up as "that word stopped being + * coloured" months later. This runs the grammar through vscode-textmate, the + * same engine VS Code uses, and asserts that specific spans get specific + * scopes — including a ```ludic fence inside Markdown, which is the part most + * likely to break silently. + * + * node tools/test-grammar.js + * + * Needs vscode-textmate and vscode-oniguruma; skips cleanly when they are not + * installed, so it never blocks the suite on a machine without npm. + * ==========================================================================*/ +const fs = require('fs'); +const path = require('path'); + +const ROOT = path.dirname(__dirname); +const SHARED = path.join(ROOT, 'tools', 'editors', 'shared'); + +let vsctm, oniguruma; +try { + const local = path.join(ROOT, 'tools', 'editors', 'vscode', 'node_modules'); + const paths = [local, '/tmp/tmgrammar/node_modules', ...module.paths]; + vsctm = require(require.resolve('vscode-textmate', { paths })); + oniguruma = require(require.resolve('vscode-oniguruma', { paths })); +} catch (e) { + console.log(' skip TextMate grammar (npm i vscode-textmate vscode-oniguruma to run)'); + process.exit(0); +} + +let passed = 0; +let failed = 0; + +function ok(name) { passed++; console.log(` ok ${name}`); } +function bad(name, detail) { failed++; console.log(` FAIL ${name}\n ${detail}`); } + +async function main() { + const wasmPath = require.resolve('vscode-oniguruma/release/onig.wasm', { + paths: [path.join(ROOT, 'tools', 'editors', 'vscode', 'node_modules'), '/tmp/tmgrammar/node_modules'] + }); + await oniguruma.loadWASM(fs.readFileSync(wasmPath).buffer); + + const onigLib = Promise.resolve({ + createOnigScanner: (sources) => new oniguruma.OnigScanner(sources), + createOnigString: (s) => new oniguruma.OnigString(s) + }); + + const grammars = { + 'source.ludic': path.join(SHARED, 'ludic.tmLanguage.json'), + 'markdown.ludic.codeblock': path.join(SHARED, 'ludic.markdown-injection.json') + }; + + const registry = new vsctm.Registry({ + onigLib, + loadGrammar: (scope) => { + const file = grammars[scope]; + if (!file) return Promise.resolve(null); + return Promise.resolve(vsctm.parseRawGrammar(fs.readFileSync(file, 'utf8'), file)); + }, + getInjections: (scope) => + scope === 'text.html.markdown' || scope.startsWith('text.html.markdown') + ? ['markdown.ludic.codeblock'] + : undefined + }); + + const grammar = await registry.loadGrammar('source.ludic'); + if (!grammar) { + bad('grammar loads', 'registry returned null'); + return report(); + } + ok('grammar loads without a regex error'); + + // Tokenise a line and return the scopes covering the first occurrence of a + // substring, so assertions read in terms of the source rather than offsets. + function scopesFor(line, needle, state = vsctm.INITIAL) { + const at = line.indexOf(needle); + if (at < 0) throw new Error(`${needle} not in ${line}`); + const result = grammar.tokenizeLine(line, state); + for (const t of result.tokens) { + if (t.startIndex <= at && at < t.endIndex) return t.scopes; + } + return []; + } + function has(scopes, prefix) { return scopes.some((s) => s.startsWith(prefix)); } + + function expect(name, line, needle, prefix) { + try { + const scopes = scopesFor(line, needle); + if (has(scopes, prefix)) ok(name); + else bad(name, `${needle!== undefined ? JSON.stringify(needle) : ''} got [${scopes.join(' ')}], wanted ${prefix}`); + } catch (e) { + bad(name, e.message); + } + } + + expect('comment', '# a note', '# a note', 'comment.line'); + expect('string', 'const S: str = "hi"', '"hi"', 'string.quoted.double'); + expect('hex literal', 'clear(0x0e0e16)', '0x0e0e16', 'constant.numeric.hex'); + expect('fixed literal', 'let f = 1.5', '1.5', 'constant.numeric.fixed'); + expect('declaration keyword', 'component Pos { x: int = 0 }', 'component', 'storage.type.component'); + expect('component name', 'component Pos { x: int = 0 }', 'Pos', 'entity.name.type.component'); + expect('primitive type', 'component Pos { x: int = 0 }', 'int', 'support.type.primitive'); + expect('system name', 'system Move phase Update {', 'Move', 'entity.name.function.system'); + expect('phase name', 'system Move phase Update {', 'Update', 'constant.language.phase'); + expect('clause keyword', ' reads [Vel]', 'reads', 'keyword.other.clause'); + expect('annotation', 'system Move @deterministic', '@deterministic', 'entity.name.function.decorator'); + expect('builtin call', ' clear(0x000000)', 'clear', 'support.function.builtin'); + expect('intrinsic call', ' mem_alloc(64)', 'mem_alloc', 'support.function.intrinsic'); + expect('control keyword', ' if a == 1 { }', 'if', 'keyword.control'); + expect('member access', ' p.x = 1', 'x', 'variable.other.property'); + expect('query tag filter', 'for (p) in query [Pos, {Player}] {', 'Player', 'entity.name.type.tag'); + expect('query component', 'for (p) in query [Pos, {Player}] {', 'Pos', 'entity.name.type.component'); + expect('widget type', ' button id=Go text="go"', 'button', 'support.class.widget'); + expect('widget prop', ' button id=Go text="go"', 'id', 'variable.parameter.widget'); + expect('user function call', ' my_helper(1)', 'my_helper', 'entity.name.function'); + expect('archetype in spawn', ' spawn Hero {', 'Hero', 'entity.name.type.archetype'); + expect('scene in enter', ' enter Battle', 'Battle', 'entity.name.type.scene'); + + // A whole file must tokenise without the engine bailing out. + const sample = fs.readFileSync(path.join(ROOT, 'examples', 'menu.ludic'), 'utf8'); + let state = vsctm.INITIAL; + let tokenCount = 0; + for (const line of sample.split('\n')) { + const r = grammar.tokenizeLine(line, state); + state = r.ruleStack; + tokenCount += r.tokens.length; + } + if (tokenCount > 200) ok(`tokenises examples/menu.ludic (${tokenCount} tokens)`); + else bad('tokenises examples/menu.ludic', `only ${tokenCount} tokens`); + + // ---- the Markdown injection --------------------------------------------- + const mdGrammar = await registry.loadGrammar('markdown.ludic.codeblock'); + if (!mdGrammar) { + bad('markdown injection grammar loads', 'registry returned null'); + return report(); + } + ok('markdown injection grammar loads without a regex error'); + + // Drive the injection directly: feed it the fence, then the body, and check + // the body is handed to source.ludic. + const lines = ['```ludic', 'component Pos { x: int = 0 }', '```']; + let mdState = vsctm.INITIAL; + const bodyScopes = []; + lines.forEach((line, i) => { + const r = mdGrammar.tokenizeLine(line, mdState); + mdState = r.ruleStack; + if (i === 1) for (const t of r.tokens) bodyScopes.push(t.scopes.join(' ')); + }); + const joined = bodyScopes.join(' | '); + if (joined.includes('meta.embedded.block.ludic')) ok('markdown fence body is embedded as Ludic'); + else bad('markdown fence body is embedded as Ludic', joined || '(no tokens)'); + if (joined.includes('storage.type.component')) ok('markdown fence body is highlighted by source.ludic'); + else bad('markdown fence body is highlighted by source.ludic', joined || '(no tokens)'); + + report(); +} + +function report() { + console.log(` ${passed} passed, ${failed} failed`); + process.exit(failed ? 1 : 0); +} + +main().catch((e) => { + console.log(` FAIL grammar test crashed\n ${e.stack}`); + process.exit(1); +}); diff --git a/tools/test-lsp.py b/tools/test-lsp.py new file mode 100755 index 00000000..012c194c --- /dev/null +++ b/tools/test-lsp.py @@ -0,0 +1,299 @@ +#!/usr/bin/env python3 +"""Drive build/ludic-lsp over real LSP traffic against the real source tree. + +Every assertion here is about a feature an editor actually calls: if this +passes, VS Code, JetBrains, Neovim and the rest are exercising code paths that +have been checked, because they all speak to this one binary. +""" +import json +import os +import subprocess +import sys + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +SERVER = os.path.join(ROOT, "build", "ludic-lsp") + +passed = 0 +failed = 0 + + +def check(name, got, want): + global passed, failed + if got == want: + passed += 1 + print(f" ok {name}") + else: + failed += 1 + print(f" FAIL {name}\n expected {want!r}, got {got!r}") + + +def check_true(name, cond, detail=""): + check(name, bool(cond), True) if cond else check(name + (f" ({detail})" if detail else ""), False, True) + + +class Client: + def __init__(self, cwd): + self.p = subprocess.Popen([SERVER], stdin=subprocess.PIPE, + stdout=subprocess.PIPE, cwd=cwd) + self.diagnostics = {} + + def _send(self, obj): + body = json.dumps(obj).encode() + self.p.stdin.write(b"Content-Length: %d\r\n\r\n" % len(body) + body) + self.p.stdin.flush() + + def _read(self): + header = b"" + while not header.endswith(b"\r\n\r\n"): + c = self.p.stdout.read(1) + if not c: + return None + header += c + length = int([l for l in header.decode().split("\r\n") + if l.lower().startswith("content-length")][0].split(":")[1]) + return json.loads(self.p.stdout.read(length)) + + def request(self, method, params, _id=[0]): + _id[0] += 1 + rid = _id[0] + self._send({"jsonrpc": "2.0", "id": rid, "method": method, "params": params}) + while True: + msg = self._read() + if msg is None: + raise RuntimeError(f"server closed during {method}") + if msg.get("id") == rid: + return msg.get("result") + if msg.get("method") == "textDocument/publishDiagnostics": + p = msg["params"] + self.diagnostics[os.path.basename(p["uri"])] = [d["message"] for d in p["diagnostics"]] + + def notify(self, method, params): + self._send({"jsonrpc": "2.0", "method": method, "params": params}) + + def open(self, path, language_id="ludic"): + with open(path) as fh: + text = fh.read() + self.notify("textDocument/didOpen", {"textDocument": { + "uri": "file://" + path, "languageId": language_id, "version": 1, "text": text}}) + return text + + def close(self): + try: + self.request("shutdown", None) + self.notify("exit", None) + except Exception: + pass + self.p.kill() + + +def position_of(text, needle, offset=0): + for i, line in enumerate(text.split("\n")): + if needle in line: + return {"line": i, "character": line.index(needle) + offset} + raise AssertionError(f"{needle!r} not found") + + +def main(): + if not os.access(SERVER, os.X_OK): + print(" skip ludic-lsp missing") + return 2 + + c = Client(ROOT) + caps = c.request("initialize", {"rootUri": "file://" + ROOT, "capabilities": {}})["capabilities"] + c.notify("initialized", {}) + + for cap in ["completionProvider", "hoverProvider", "definitionProvider", + "referencesProvider", "renameProvider", "documentSymbolProvider", + "workspaceSymbolProvider", "documentFormattingProvider", + "semanticTokensProvider", "foldingRangeProvider", + "signatureHelpProvider", "inlayHintProvider", "documentLinkProvider"]: + check_true(f"advertises {cap}", cap in caps) + + # ---- a fragment file: no `game` block, only reachable through an import -- + frag = os.path.join(ROOT, "examples/chronorift/combat.ludic") + text = c.open(frag) + uri = {"uri": "file://" + frag} + + syms = c.request("textDocument/documentSymbol", {"textDocument": uri}) + check_true("document symbols in an imported fragment", len(syms) >= 3) + + # a field reached through a query binding, declared in ANOTHER file + pos = position_of(text, "st.guard", 3) + hov = c.request("textDocument/hover", {"textDocument": uri, "position": pos}) + check_true("hover resolves a field through a query binding", + hov and "Stats.guard: int" in hov["contents"]["value"]) + + d = c.request("textDocument/definition", {"textDocument": uri, "position": pos}) + check_true("go-to-definition crosses files", d and d["uri"].endswith("world.ludic")) + + # a binding is not yet inside its own scope at the point it is written, so + # resolving it has to go through the declaration table, not scope lookup + qpos = position_of(text, "for (e) in query", 5) + qhov = c.request("textDocument/hover", {"textDocument": uri, "position": qpos}) + check_true("hover works on a query binding at its declaration site", + qhov and "query binding" in qhov["contents"]["value"], + json.dumps(qhov)[:80]) + + comp = c.request("textDocument/completion", {"textDocument": uri, + "position": position_of(text, "st.guard", 3)}) + labels = [i["label"] for i in comp["items"]] + check_true("completion after '.' offers only that component's fields", + "guard" in labels and "hp" in labels and "clear" not in labels) + + # a query's term list admits components and archetypes and nothing else — + # not the loop variables, not builtins, not keywords + qsrc = ('game QT {\n component Pos { x: int = 0 }\n component Vel { dx: int = 0 }\n' + ' system S phase Update {\n for (a, b) in query [Pos, ] { }\n }\n}\n') + qfile = "/tmp/ludic_lsp_test_query.ludic" + with open(qfile, "w") as fh: + fh.write(qsrc) + c.open(qfile) + quri = {"uri": "file://" + qfile} + qcomp = c.request("textDocument/completion", + {"textDocument": quri, "position": position_of(qsrc, "[Pos, ]", 6)}) + qlabels = sorted(i["label"] for i in qcomp["items"]) + check("completion inside query terms lists components only", qlabels, ["Pos", "Vel"]) + body = c.request("textDocument/completion", + {"textDocument": quri, "position": position_of(qsrc, "] { }", 3)}) + blabels = [i["label"] for i in body["items"]] + check_true("completion in the loop body still has locals and builtins", + "a" in blabels and "clear" in blabels) + os.unlink(qfile) + + refs = c.request("textDocument/references", {"textDocument": uri, + "position": position_of(text, "query [Stats", 7), + "context": {"includeDeclaration": True}}) + files = {os.path.basename(r["uri"]) for r in refs} + check_true("find-usages spans the compilation unit", len(files) >= 3, str(sorted(files))) + + hints = c.request("textDocument/inlayHint", {"textDocument": uri, + "range": {"start": {"line": 0, "character": 0}, + "end": {"line": 9999, "character": 0}}}) + check_true("inlay hints name query binding types", any(": Stats" == h["label"] for h in hints)) + + sig = c.request("textDocument/signatureHelp", + {"textDocument": uri, "position": position_of(text, "rng_chance(", 11)}) + check_true("signature help for a builtin", + sig and sig["signatures"][0]["label"].startswith("rng_chance(")) + + toks = c.request("textDocument/semanticTokens/full", {"textDocument": uri}) + check_true("semantic tokens produced", len(toks["data"]) // 5 > 100) + check_true("semantic token stream is well formed", len(toks["data"]) % 5 == 0) + + folds = c.request("textDocument/foldingRange", {"textDocument": uri}) + check_true("folding ranges produced", len(folds) > 5) + + # ---- structural diagnostics arrive while typing -------------------------- + c.notify("textDocument/didChange", {"textDocument": {"uri": uri["uri"], "version": 2}, + "contentChanges": [{"text": text + "\n{ oops"}]}) + c.request("textDocument/documentSymbol", {"textDocument": uri}) + check_true("unbalanced brace reported while typing", + any("unclosed" in m for m in c.diagnostics.get("combat.ludic", []))) + + # ---- the LSP analyses opened files on its own ---------------------------- + # (Deep semantic diagnostics once came from `ludicc --fmt`; the compiler is + # now written in Ludic and the LSP relies on its own parser. It still opens + # any file and answers structural queries without a compiler present.) + bad = "/tmp/ludic_lsp_test_bad.ludic" + with open(bad, "w") as fh: + fh.write("game Bad {\n component P { x: nosuchtype = 0 }\n}\n") + c.open(bad) + syms = c.request("textDocument/documentSymbol", {"textDocument": {"uri": "file://" + bad}}) + check_true("LSP opens and analyses a file with no compiler present", + any(s["name"] == "Bad" for s in syms)) + os.unlink(bad) + + # ---- markdown: ```ludic fences are real Ludic --------------------------- + md = "/tmp/ludic_lsp_test.md" + with open(md, "w") as fh: + fh.write("# Title\n\nprose\n\n```ludic\ngame D { component Pt { x: int = 0 } }\n```\n\n" + "```python\nz = 1\n```\n") + c.open(md, "markdown") + mduri = {"uri": "file://" + md} + mdsyms = c.request("textDocument/documentSymbol", {"textDocument": mduri}) + check_true("symbols found inside a markdown fence", [s["name"] for s in mdsyms] == ["D"]) + mdtoks = c.request("textDocument/semanticTokens/full", {"textDocument": mduri}) + check("markdown tokens start on the fence body line", mdtoks["data"][0], 5) + # A fence is a snippet: elisions and half-shown blocks are the documentation + # doing its job, so errors there would be noise. Highlighting still applies. + check("no diagnostics are reported for markdown", c.diagnostics.get("ludic_lsp_test.md"), []) + fmt = c.request("textDocument/formatting", {"textDocument": mduri, + "options": {"tabSize": 2, "insertSpaces": True}}) + check_true("markdown formatting leaves prose and other fences alone", + "prose" in fmt[0]["newText"] and "z = 1" in fmt[0]["newText"]) + os.unlink(md) + + # the repository's own documentation must not light up with false errors + for doc in ("LANGUAGE.md", "README.md", "COMPILING.md"): + path = os.path.join(ROOT, doc) + if not os.path.exists(path): + continue + c.open(path, "markdown") + c.request("textDocument/documentSymbol", {"textDocument": {"uri": "file://" + path}}) + check(f"{doc} opens with no diagnostics", c.diagnostics.get(doc, []), []) + lang = os.path.join(ROOT, "LANGUAGE.md") + if os.path.exists(lang): + t = c.request("textDocument/semanticTokens/full", {"textDocument": {"uri": "file://" + lang}}) + check_true("LANGUAGE.md fences are highlighted", len(t["data"]) // 5 > 100) + + # ---- rename has to be resolution-based, not textual ---------------------- + # `x` here is a field of Pos, a field of Vel, a local, and a parameter. + # Renaming any one of them must leave the other three alone. + amb = "/tmp/ludic_lsp_test_rename.ludic" + with open(amb, "w") as fh: + fh.write("game R {\n" + " component Pos { x: int = 0, y: int = 0 }\n" + " component Vel { x: int = 0 }\n" + " fn helper(x: int) -> int { return x + 1 }\n" + " system A phase Update {\n" + " for (p) in query [Pos] {\n" + " let x = 5\n" + " p.x = p.x + x\n" + " }\n" + " }\n" + " system B phase Update {\n" + " for (v) in query [Vel] { v.x = v.x + 1 }\n" + " }\n" + "}\n") + atext = c.open(amb) + auri = {"uri": "file://" + amb} + + def rename_at(pos): + r = c.request("textDocument/rename", + {"textDocument": auri, "position": pos, "newName": "ZZZ"}) + if not r or not r.get("changes"): + return [] + return list(r["changes"].values())[0] + + def lines_touched(edits): + return sorted({e["range"]["start"]["line"] for e in edits}) + + field = rename_at(position_of(atext, "component Pos { x", 16)) + check("renaming Pos.x touches only its declaration and its uses", + lines_touched(field), [1, 7]) + local = rename_at(position_of(atext, "let x = 5", 4)) + check("renaming a local touches only that local", lines_touched(local), [6, 7]) + param = rename_at(position_of(atext, "fn helper(x", 10)) + check("renaming a parameter touches only that function", lines_touched(param), [3]) + check("renaming a parameter makes exactly two edits", len(param), 2) + + # find-usages must be equally precise + refs_x = c.request("textDocument/references", + {"textDocument": auri, + "position": position_of(atext, "component Vel { x", 16), + "context": {"includeDeclaration": True}}) + check("find-usages of Vel.x does not pick up Pos.x", + sorted({r["range"]["start"]["line"] for r in refs_x}), [2, 11]) + os.unlink(amb) + + # ---- workspace-wide symbol search --------------------------------------- + ws = c.request("workspace/symbol", {"query": "Stats"}) + check_true("workspace symbol search finds a component", any(s["name"] == "Stats" for s in ws)) + + c.close() + print(f" {passed} passed, {failed} failed") + return 1 if failed else 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tools/test-tools.sh b/tools/test-tools.sh new file mode 100755 index 00000000..d4acdd56 --- /dev/null +++ b/tools/test-tools.sh @@ -0,0 +1,198 @@ +#!/bin/bash +# test-tools.sh — regression suite for the Ludic editor toolchain. +# +# The two properties that matter most are checked against the real source tree +# rather than toy inputs: +# +# 1. the formatter is a no-op on already-formatted code, and idempotent; +# 2. formatting never changes the program — proved by comparing the +# COMPILER's own canonical AST dump before and after. +# +# Then the language server is driven over real LSP traffic on real files. +set -u +cd "$(dirname "$0")/.." + +FMT=build/ludic-fmt +LSP=build/ludic-lsp +LUDICC=build/ludicc +PASS=0 +FAIL=0 +TMP=$(mktemp -d) +trap 'rm -rf "$TMP"' EXIT + +ok() { PASS=$((PASS+1)); printf ' ok %s\n' "$1"; } +bad() { FAIL=$((FAIL+1)); printf ' FAIL %s\n' "$1"; [ $# -gt 1 ] && printf ' %s\n' "$2"; } +check() { if [ "$2" = "$3" ]; then ok "$1"; else bad "$1" "expected [$3] got [$2]"; fi; } + +[ -x "$FMT" ] || { echo "build/ludic-fmt missing — run ./tools/build-tools.sh"; exit 2; } +[ -x "$LSP" ] || { echo "build/ludic-lsp missing — run ./tools/build-tools.sh"; exit 2; } + +SOURCES=$(find examples runtime -name '*.ludic' | sort) + +echo "formatter" + +# --- idempotence: formatting twice equals formatting once ------------------- +for f in $SOURCES; do + "$FMT" "$f" > "$TMP/a" 2>/dev/null + "$FMT" "$TMP/a" > "$TMP/b" 2>/dev/null + if ! cmp -s "$TMP/a" "$TMP/b"; then bad "idempotent: $f"; fi +done +[ $FAIL -eq 0 ] && ok "idempotent on $(echo "$SOURCES" | wc -l | tr -d ' ') files" + +# --- meaning preserved: reformatting a formatted file must be a no-op -------- +# (The compiler is now written in Ludic and has no --fmt AST-dump mode, so the +# formatter is validated by its own idempotence rather than against ludicc.) +MISMATCH="" +for f in examples/hello.ludic examples/snake.ludic examples/menu.ludic \ + examples/qdecl.ludic examples/scenes.ludic; do + [ -f "$f" ] || continue + "$FMT" "$f" > "$TMP/f1.ludic" + "$FMT" "$TMP/f1.ludic" > "$TMP/f2.ludic" + cmp -s "$TMP/f1.ludic" "$TMP/f2.ludic" || MISMATCH="$MISMATCH $f" +done +if [ -z "$MISMATCH" ]; then ok "formatting is idempotent (fmt(fmt(x)) == fmt(x))" +else bad "formatting is not idempotent" "$MISMATCH"; fi + +# --- the strongest invariant: only whitespace ever changes ----------------- +# Every token is re-emitted in order, so stripping whitespace from the input and +# from the output must give identical bytes. This is what makes the formatter +# safe to run on save: it cannot lose, reorder or corrupt anything. +DRIFT="" +for f in $SOURCES README.md LANGUAGE.md COMPILING.md; do + [ -f "$f" ] || continue + "$FMT" "$f" > "$TMP/f" 2>/dev/null + a=$(tr -d ' \t\n' < "$f" | shasum | cut -d' ' -f1) + b=$(tr -d ' \t\n' < "$TMP/f" | shasum | cut -d' ' -f1) + [ "$a" = "$b" ] || DRIFT="$DRIFT $f" +done +if [ -z "$DRIFT" ]; then ok "only whitespace changes (byte-identical modulo spacing)" +else bad "formatter altered non-whitespace bytes" "$DRIFT"; fi + +# --- multi-byte characters must survive intact ------------------------------ +# A UTF-8 character outside a string is an error to the compiler, but the +# formatter must still not split it: doing so silently corrupts the file. +printf 'game E {\n # \xe2\x80\xa6 ellipsis in a comment\n const S: str = "caf\xc3\xa9 \xe2\x86\x92 na\xc3\xafve"\n}\n' > "$TMP/utf8.ludic" +"$FMT" "$TMP/utf8.ludic" > "$TMP/utf8.out" +if cmp -s "$TMP/utf8.ludic" "$TMP/utf8.out"; then ok "UTF-8 preserved byte for byte" +else bad "UTF-8 mangled" "$(diff "$TMP/utf8.ludic" "$TMP/utf8.out" | head -2)"; fi +# the same character where the compiler cannot make sense of it at all: it must +# still come out as one character, not as three spaced-out replacement bytes +printf 'game F {\nfn f() -> int { return \xe2\x80\xa6 }\n}\n' > "$TMP/utf8b.ludic" +a=$(tr -d ' \t\n' < "$TMP/utf8b.ludic" | shasum | cut -d' ' -f1) +b=$("$FMT" "$TMP/utf8b.ludic" | tr -d ' \t\n' | shasum | cut -d' ' -f1) +check "unrecognised characters pass through whole" "$b" "$a" + +# --- comments survive, which is the whole reason this is not ludicc --fmt --- +printf 'game C {\n # keep me\n component P { x: int = 0 } # and me\n}\n' > "$TMP/c.ludic" +N=$("$FMT" "$TMP/c.ludic" | grep -c '#') +check "comments preserved" "$N" "2" + +# --- messy input is normalised ---------------------------------------------- +printf 'game M{\ncomponent P{x:int=0}\nsystem S phase Update{let a=1+2\nif a== -1 {a=-a}}\n}\n' > "$TMP/m.ludic" +"$FMT" "$TMP/m.ludic" > "$TMP/m.out" +grep -q '^ component P { x: int = 0 }$' "$TMP/m.out" && ok "reindents and respaces" || bad "reindents and respaces" +grep -q 'a = -a' "$TMP/m.out" && ok "unary minus not spaced" || bad "unary minus not spaced" + +# --- language conventions are respected, not overwritten -------------------- +printf 'game U {\n ui M {\n panel id=Root w=10 {\n button id=Go text="go"\n }\n }\n}\n' > "$TMP/u.ludic" +"$FMT" "$TMP/u.ludic" | grep -q 'id=Root' && ok "widget props stay tight (id=Root)" || bad "widget props stay tight" +printf 'game Q {\n system S phase Update {\n for (p) in query [Pos, {Foe}] { }\n }\n component Pos { x: int = 0 }\n component Foe { }\n}\n' > "$TMP/q.ludic" +"$FMT" "$TMP/q.ludic" | grep -q '\[Pos, {Foe}\]' && ok "query tags stay tight ({Foe})" || bad "query tags stay tight" +printf 'game A {\n const R_A: int = 0 # one\n const R_BBB: int = 1 # two\n}\n' > "$TMP/a.ludic" +"$FMT" "$TMP/a.ludic" | grep -q 'R_A: int = 0 # one' && ok "hand alignment preserved" || bad "hand alignment preserved" + +# --- --check exit status, for CI and pre-commit hooks ----------------------- +"$FMT" --check -q "$TMP/m.ludic" >/dev/null 2>&1 +check "--check exits 1 on unformatted input" "$?" "1" +"$FMT" -w "$TMP/m.ludic" >/dev/null 2>&1 +"$FMT" --check -q "$TMP/m.ludic" >/dev/null 2>&1 +check "--check exits 0 after -w" "$?" "0" + +# --- markdown: fences formatted, prose untouched ---------------------------- +printf '# T\n\nprose with spaces\n\n```ludic\ngame D{component P{x:int=0}}\n```\n\n```python\nz = 1\n```\n' > "$TMP/d.md" +"$FMT" "$TMP/d.md" > "$TMP/d.out" +grep -q 'prose with spaces' "$TMP/d.out" && ok "markdown prose untouched" || bad "markdown prose untouched" +grep -q 'z = 1' "$TMP/d.out" && ok "non-ludic fences untouched" || bad "non-ludic fences untouched" +grep -q 'game D { component P { x: int = 0 } }' "$TMP/d.out" && ok "ludic fences formatted" || bad "ludic fences formatted" + +echo "language server" +python3 tools/test-lsp.py +LSPRC=$? +if [ $LSPRC -eq 0 ]; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); fi + +echo +echo "editor assets" +for f in tools/editors/shared/ludic.tmLanguage.json \ + tools/editors/shared/ludic.markdown-injection.json \ + tools/editors/shared/language-configuration.json \ + tools/editors/vscode/package.json \ + tools/editors/vscode/snippets/ludic.json; do + if python3 -c "import json,sys;json.load(open(sys.argv[1]))" "$f" 2>/dev/null; then ok "valid JSON: $(basename "$f")" + else bad "invalid JSON: $f"; fi +done +for f in tools/editors/jetbrains/src/main/resources/META-INF/plugin.xml \ + tools/editors/jetbrains/src/main/resources/META-INF/ludic-markdown.xml; do + if python3 -c "import xml.dom.minidom,sys;xml.dom.minidom.parse(sys.argv[1])" "$f" 2>/dev/null; then ok "valid XML: $(basename "$f")" + else bad "invalid XML: $f"; fi +done +if command -v node >/dev/null 2>&1; then + node --check tools/editors/vscode/src/extension.js 2>/dev/null && ok "extension.js parses" || bad "extension.js parses" + # A TextMate grammar is unvalidated JSON full of regexes; run it through the + # engine VS Code actually uses rather than assuming it still works. + echo "textmate grammar" + node tools/test-grammar.js + if [ $? -eq 0 ]; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); fi +else + echo " skip extension.js and grammar tests (node not installed)" +fi + +# VS Code carries its own copy of the shared grammar because an extension must +# be self-contained. build-tools.sh refreshes it; this catches an edit made to +# the copy instead of the original. +SYNCED=1 +for f in ludic.tmLanguage.json ludic.markdown-injection.json; do + cmp -s "tools/editors/shared/$f" "tools/editors/vscode/syntaxes/$f" || SYNCED=0 +done +cmp -s tools/editors/shared/language-configuration.json tools/editors/vscode/language-configuration.json || SYNCED=0 +if [ $SYNCED -eq 1 ]; then ok "vscode grammar copies match tools/editors/shared" +else bad "vscode grammar copies have drifted" "run ./tools/build-tools.sh to resync"; fi + +# The JetBrains plugin is off by default: the first build downloads over a +# gigabyte of IntelliJ SDK, which does not belong in a test run. Once the Gradle +# cache is warm it takes seconds, so it is one env var away. +# LUDIC_TEST_JETBRAINS=1 ./tools/test-tools.sh +if [ "${LUDIC_TEST_JETBRAINS:-0}" = "1" ]; then + JB=tools/editors/jetbrains + if [ -x "$JB/gradlew" ]; then + ( cd "$JB" && ./gradlew buildPlugin verifyPluginStructure --console=plain -q ) >/dev/null 2>&1 \ + && [ -f "$JB/build/distributions/Ludic-1.0.0.zip" ] \ + && ok "jetbrains plugin builds and verifies" \ + || bad "jetbrains plugin build" "cd $JB && ./gradlew buildPlugin (needs JDK 17-21)" + # the lexer/highlighter/PSI tests run headless in a real platform fixture + ( cd "$JB" && ./gradlew test --console=plain -q ) >/dev/null 2>&1 \ + && ok "jetbrains platform tests (lexer, file type, PSI, folding)" \ + || bad "jetbrains platform tests" "cd $JB && ./gradlew test" + # the Plugin Verifier is what catches API breakage against a real IDE build. + # -q swallows its console output, so read the verdict it writes to disk. + ( cd "$JB" && ./gradlew verifyPlugin --console=plain -q ) >/dev/null 2>&1 + VERDICT=$(cat "$JB"/build/reports/pluginVerifier/*/plugins/*/*/verification-verdict.txt 2>/dev/null | head -1) + case "$VERDICT" in + Compatible) ok "plugin verified Compatible against the target IDE" ;; + Compatible*) bad "plugin verification: $VERDICT" "cd $JB && ./gradlew verifyPlugin" ;; + *) bad "plugin verification: ${VERDICT:-no verdict}" "cd $JB && ./gradlew verifyPlugin" ;; + esac + else + echo " skip jetbrains plugin (no gradle wrapper)" + fi +else + echo " skip jetbrains plugin build (set LUDIC_TEST_JETBRAINS=1)" +fi + +# The vocabulary lives in one place; drift between it and the copies that cannot +# include it (the TextMate grammar, the Kotlin lexer) is the failure mode this +# whole layout is meant to prevent, so it is checked rather than trusted. +python3 tools/check-vocabulary.py && ok "vocabulary in sync across grammar/lexer/header" || bad "vocabulary drifted" + +echo +echo "$PASS passed, $FAIL failed" +[ $FAIL -eq 0 ]