├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── examples ├── bin-test.rs ├── branch.rio ├── hi.rio ├── out │ ├── branch.wat │ ├── branch │ │ ├── branch.norm.txt │ │ ├── branch.parse.txt │ │ └── branch.run.txt │ ├── core │ │ ├── core.norm.txt │ │ ├── core.parse.txt │ │ └── core.run.txt │ ├── hi.wat │ ├── hi │ │ ├── hi.norm.txt │ │ ├── hi.parse.txt │ │ └── hi.run.txt │ ├── recurse.wat │ ├── recurse │ │ ├── recurse.norm.txt │ │ ├── recurse.parse.txt │ │ └── recurse.run.txt │ ├── struct.wat │ ├── struct │ │ ├── struct.norm.txt │ │ ├── struct.parse.txt │ │ └── struct.run.txt │ ├── wild.wat │ └── wild │ │ ├── wild.norm.txt │ │ ├── wild.parse.txt │ │ └── wild.run.txt ├── recurse.rio ├── struct.rio └── wild.rio ├── logos ├── rio-logo-round.svg ├── rio-logo-square.svg ├── rio-logo-stream-2.svg └── rio-logo-stream.svg ├── other └── fib.wat └── src ├── core.rio ├── core.rs ├── lex.rs ├── link.rs ├── main.rs ├── norm.rs ├── parse.rs ├── run.rs ├── tree.rs ├── typ.rs ├── util.rs └── wasm.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /examples/out/*.wasm 2 | /explore/*.wasm 3 | /explore/*-out.txt 4 | /explore/*-out.wat 5 | /notes/ 6 | /target/ 7 | /.vs/ 8 | /.vscode/ 9 | *.swp 10 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "ahash" 7 | version = "0.8.3" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" 10 | dependencies = [ 11 | "cfg-if", 12 | "once_cell", 13 | "version_check", 14 | ] 15 | 16 | [[package]] 17 | name = "aho-corasick" 18 | version = "1.0.2" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" 21 | dependencies = [ 22 | "memchr", 23 | ] 24 | 25 | [[package]] 26 | name = "anstream" 27 | version = "0.3.2" 28 | source = "registry+https://github.com/rust-lang/crates.io-index" 29 | checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" 30 | dependencies = [ 31 | "anstyle", 32 | "anstyle-parse", 33 | "anstyle-query", 34 | "anstyle-wincon", 35 | "colorchoice", 36 | "is-terminal", 37 | "utf8parse", 38 | ] 39 | 40 | [[package]] 41 | name = "anstyle" 42 | version = "1.0.1" 43 | source = "registry+https://github.com/rust-lang/crates.io-index" 44 | checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" 45 | 46 | [[package]] 47 | name = "anstyle-parse" 48 | version = "0.2.1" 49 | source = "registry+https://github.com/rust-lang/crates.io-index" 50 | checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" 51 | dependencies = [ 52 | "utf8parse", 53 | ] 54 | 55 | [[package]] 56 | name = "anstyle-query" 57 | version = "1.0.0" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" 60 | dependencies = [ 61 | "windows-sys", 62 | ] 63 | 64 | [[package]] 65 | name = "anstyle-wincon" 66 | version = "1.0.1" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" 69 | dependencies = [ 70 | "anstyle", 71 | "windows-sys", 72 | ] 73 | 74 | [[package]] 75 | name = "anyhow" 76 | version = "1.0.72" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" 79 | 80 | [[package]] 81 | name = "autocfg" 82 | version = "1.1.0" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 85 | 86 | [[package]] 87 | name = "bitflags" 88 | version = "1.3.2" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 91 | 92 | [[package]] 93 | name = "bitflags" 94 | version = "2.3.3" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" 97 | 98 | [[package]] 99 | name = "cc" 100 | version = "1.0.79" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" 103 | 104 | [[package]] 105 | name = "cfg-if" 106 | version = "1.0.0" 107 | source = "registry+https://github.com/rust-lang/crates.io-index" 108 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 109 | 110 | [[package]] 111 | name = "clap" 112 | version = "4.3.12" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | checksum = "3eab9e8ceb9afdade1ab3f0fd8dbce5b1b2f468ad653baf10e771781b2b67b73" 115 | dependencies = [ 116 | "clap_builder", 117 | "clap_derive", 118 | "once_cell", 119 | ] 120 | 121 | [[package]] 122 | name = "clap_builder" 123 | version = "4.3.12" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "9f2763db829349bf00cfc06251268865ed4363b93a943174f638daf3ecdba2cd" 126 | dependencies = [ 127 | "anstream", 128 | "anstyle", 129 | "clap_lex", 130 | "strsim", 131 | ] 132 | 133 | [[package]] 134 | name = "clap_derive" 135 | version = "4.3.12" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" 138 | dependencies = [ 139 | "heck", 140 | "proc-macro2", 141 | "quote", 142 | "syn", 143 | ] 144 | 145 | [[package]] 146 | name = "clap_lex" 147 | version = "0.5.0" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" 150 | 151 | [[package]] 152 | name = "colorchoice" 153 | version = "1.0.0" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" 156 | 157 | [[package]] 158 | name = "dashmap" 159 | version = "5.5.0" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d" 162 | dependencies = [ 163 | "cfg-if", 164 | "hashbrown 0.14.0", 165 | "lock_api", 166 | "once_cell", 167 | "parking_lot_core", 168 | ] 169 | 170 | [[package]] 171 | name = "env_logger" 172 | version = "0.10.0" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" 175 | dependencies = [ 176 | "humantime", 177 | "is-terminal", 178 | "log", 179 | "regex", 180 | "termcolor", 181 | ] 182 | 183 | [[package]] 184 | name = "errno" 185 | version = "0.3.1" 186 | source = "registry+https://github.com/rust-lang/crates.io-index" 187 | checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" 188 | dependencies = [ 189 | "errno-dragonfly", 190 | "libc", 191 | "windows-sys", 192 | ] 193 | 194 | [[package]] 195 | name = "errno-dragonfly" 196 | version = "0.1.2" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" 199 | dependencies = [ 200 | "cc", 201 | "libc", 202 | ] 203 | 204 | [[package]] 205 | name = "hashbrown" 206 | version = "0.13.2" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" 209 | dependencies = [ 210 | "ahash", 211 | ] 212 | 213 | [[package]] 214 | name = "hashbrown" 215 | version = "0.14.0" 216 | source = "registry+https://github.com/rust-lang/crates.io-index" 217 | checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" 218 | 219 | [[package]] 220 | name = "heck" 221 | version = "0.4.1" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 224 | 225 | [[package]] 226 | name = "hermit-abi" 227 | version = "0.3.2" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" 230 | 231 | [[package]] 232 | name = "humantime" 233 | version = "2.1.0" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" 236 | 237 | [[package]] 238 | name = "is-terminal" 239 | version = "0.4.9" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" 242 | dependencies = [ 243 | "hermit-abi", 244 | "rustix", 245 | "windows-sys", 246 | ] 247 | 248 | [[package]] 249 | name = "lasso" 250 | version = "0.7.2" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "4644821e1c3d7a560fe13d842d13f587c07348a1a05d3a797152d41c90c56df2" 253 | dependencies = [ 254 | "dashmap", 255 | "hashbrown 0.13.2", 256 | ] 257 | 258 | [[package]] 259 | name = "leb128" 260 | version = "0.2.5" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" 263 | 264 | [[package]] 265 | name = "libc" 266 | version = "0.2.147" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" 269 | 270 | [[package]] 271 | name = "linux-raw-sys" 272 | version = "0.4.3" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" 275 | 276 | [[package]] 277 | name = "lock_api" 278 | version = "0.4.10" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" 281 | dependencies = [ 282 | "autocfg", 283 | "scopeguard", 284 | ] 285 | 286 | [[package]] 287 | name = "log" 288 | version = "0.4.19" 289 | source = "registry+https://github.com/rust-lang/crates.io-index" 290 | checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" 291 | 292 | [[package]] 293 | name = "memchr" 294 | version = "2.5.0" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 297 | 298 | [[package]] 299 | name = "once_cell" 300 | version = "1.18.0" 301 | source = "registry+https://github.com/rust-lang/crates.io-index" 302 | checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" 303 | 304 | [[package]] 305 | name = "parking_lot_core" 306 | version = "0.9.8" 307 | source = "registry+https://github.com/rust-lang/crates.io-index" 308 | checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" 309 | dependencies = [ 310 | "cfg-if", 311 | "libc", 312 | "redox_syscall", 313 | "smallvec", 314 | "windows-targets", 315 | ] 316 | 317 | [[package]] 318 | name = "proc-macro2" 319 | version = "1.0.66" 320 | source = "registry+https://github.com/rust-lang/crates.io-index" 321 | checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" 322 | dependencies = [ 323 | "unicode-ident", 324 | ] 325 | 326 | [[package]] 327 | name = "quote" 328 | version = "1.0.31" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0" 331 | dependencies = [ 332 | "proc-macro2", 333 | ] 334 | 335 | [[package]] 336 | name = "redox_syscall" 337 | version = "0.3.5" 338 | source = "registry+https://github.com/rust-lang/crates.io-index" 339 | checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" 340 | dependencies = [ 341 | "bitflags 1.3.2", 342 | ] 343 | 344 | [[package]] 345 | name = "regex" 346 | version = "1.9.1" 347 | source = "registry+https://github.com/rust-lang/crates.io-index" 348 | checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" 349 | dependencies = [ 350 | "aho-corasick", 351 | "memchr", 352 | "regex-automata", 353 | "regex-syntax", 354 | ] 355 | 356 | [[package]] 357 | name = "regex-automata" 358 | version = "0.3.3" 359 | source = "registry+https://github.com/rust-lang/crates.io-index" 360 | checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" 361 | dependencies = [ 362 | "aho-corasick", 363 | "memchr", 364 | "regex-syntax", 365 | ] 366 | 367 | [[package]] 368 | name = "regex-syntax" 369 | version = "0.7.4" 370 | source = "registry+https://github.com/rust-lang/crates.io-index" 371 | checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" 372 | 373 | [[package]] 374 | name = "rio" 375 | version = "0.1.0" 376 | dependencies = [ 377 | "anyhow", 378 | "clap", 379 | "env_logger", 380 | "lasso", 381 | "log", 382 | "wasm-encoder", 383 | ] 384 | 385 | [[package]] 386 | name = "rustix" 387 | version = "0.38.4" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" 390 | dependencies = [ 391 | "bitflags 2.3.3", 392 | "errno", 393 | "libc", 394 | "linux-raw-sys", 395 | "windows-sys", 396 | ] 397 | 398 | [[package]] 399 | name = "scopeguard" 400 | version = "1.1.0" 401 | source = "registry+https://github.com/rust-lang/crates.io-index" 402 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 403 | 404 | [[package]] 405 | name = "smallvec" 406 | version = "1.11.1" 407 | source = "registry+https://github.com/rust-lang/crates.io-index" 408 | checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" 409 | 410 | [[package]] 411 | name = "strsim" 412 | version = "0.10.0" 413 | source = "registry+https://github.com/rust-lang/crates.io-index" 414 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 415 | 416 | [[package]] 417 | name = "syn" 418 | version = "2.0.26" 419 | source = "registry+https://github.com/rust-lang/crates.io-index" 420 | checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970" 421 | dependencies = [ 422 | "proc-macro2", 423 | "quote", 424 | "unicode-ident", 425 | ] 426 | 427 | [[package]] 428 | name = "termcolor" 429 | version = "1.2.0" 430 | source = "registry+https://github.com/rust-lang/crates.io-index" 431 | checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" 432 | dependencies = [ 433 | "winapi-util", 434 | ] 435 | 436 | [[package]] 437 | name = "unicode-ident" 438 | version = "1.0.11" 439 | source = "registry+https://github.com/rust-lang/crates.io-index" 440 | checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" 441 | 442 | [[package]] 443 | name = "utf8parse" 444 | version = "0.2.1" 445 | source = "registry+https://github.com/rust-lang/crates.io-index" 446 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" 447 | 448 | [[package]] 449 | name = "version_check" 450 | version = "0.9.4" 451 | source = "registry+https://github.com/rust-lang/crates.io-index" 452 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 453 | 454 | [[package]] 455 | name = "wasm-encoder" 456 | version = "0.36.1" 457 | source = "registry+https://github.com/rust-lang/crates.io-index" 458 | checksum = "53ae0be20bf87918df4fa831bfbbd0b491d24aee407ed86360eae4c2c5608d38" 459 | dependencies = [ 460 | "leb128", 461 | ] 462 | 463 | [[package]] 464 | name = "winapi" 465 | version = "0.3.9" 466 | source = "registry+https://github.com/rust-lang/crates.io-index" 467 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 468 | dependencies = [ 469 | "winapi-i686-pc-windows-gnu", 470 | "winapi-x86_64-pc-windows-gnu", 471 | ] 472 | 473 | [[package]] 474 | name = "winapi-i686-pc-windows-gnu" 475 | version = "0.4.0" 476 | source = "registry+https://github.com/rust-lang/crates.io-index" 477 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 478 | 479 | [[package]] 480 | name = "winapi-util" 481 | version = "0.1.5" 482 | source = "registry+https://github.com/rust-lang/crates.io-index" 483 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 484 | dependencies = [ 485 | "winapi", 486 | ] 487 | 488 | [[package]] 489 | name = "winapi-x86_64-pc-windows-gnu" 490 | version = "0.4.0" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 493 | 494 | [[package]] 495 | name = "windows-sys" 496 | version = "0.48.0" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 499 | dependencies = [ 500 | "windows-targets", 501 | ] 502 | 503 | [[package]] 504 | name = "windows-targets" 505 | version = "0.48.1" 506 | source = "registry+https://github.com/rust-lang/crates.io-index" 507 | checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" 508 | dependencies = [ 509 | "windows_aarch64_gnullvm", 510 | "windows_aarch64_msvc", 511 | "windows_i686_gnu", 512 | "windows_i686_msvc", 513 | "windows_x86_64_gnu", 514 | "windows_x86_64_gnullvm", 515 | "windows_x86_64_msvc", 516 | ] 517 | 518 | [[package]] 519 | name = "windows_aarch64_gnullvm" 520 | version = "0.48.0" 521 | source = "registry+https://github.com/rust-lang/crates.io-index" 522 | checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" 523 | 524 | [[package]] 525 | name = "windows_aarch64_msvc" 526 | version = "0.48.0" 527 | source = "registry+https://github.com/rust-lang/crates.io-index" 528 | checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" 529 | 530 | [[package]] 531 | name = "windows_i686_gnu" 532 | version = "0.48.0" 533 | source = "registry+https://github.com/rust-lang/crates.io-index" 534 | checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" 535 | 536 | [[package]] 537 | name = "windows_i686_msvc" 538 | version = "0.48.0" 539 | source = "registry+https://github.com/rust-lang/crates.io-index" 540 | checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" 541 | 542 | [[package]] 543 | name = "windows_x86_64_gnu" 544 | version = "0.48.0" 545 | source = "registry+https://github.com/rust-lang/crates.io-index" 546 | checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" 547 | 548 | [[package]] 549 | name = "windows_x86_64_gnullvm" 550 | version = "0.48.0" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" 553 | 554 | [[package]] 555 | name = "windows_x86_64_msvc" 556 | version = "0.48.0" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" 559 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rio" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | anyhow = "1.0.72" 8 | clap = { version = "4.3.12", features = ["derive"] } 9 | env_logger = "0.10.0" 10 | lasso = { version = "0.7.2", features = ["multi-threaded"] } 11 | log = { version = "0.4.19", features = ["release_max_level_warn"] } 12 | wasm-encoder = "0.36.1" 13 | 14 | [profile.release] 15 | # Got smaller with s than z in a quick check. 16 | opt-level = "s" 17 | strip = true 18 | 19 | [profile.release-lto] 20 | # Shrink more per https://github.com/johnthagen/min-sized-rust 21 | codegen-units = 1 22 | inherits = "release" 23 | lto = true 24 | panic = "abort" 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rio 2 | 3 | A programming language someday maybe. 4 | 5 | Try this for now: 6 | 7 | ```sh 8 | cargo run -- build examples/hi.rio 9 | ``` 10 | 11 | Or for more fun, which cargo installs wasm-tools and wasmi_cli then builds and 12 | runs rio and so on: 13 | 14 | ```sh 15 | cargo run --example bin-test 16 | ``` 17 | 18 | Or for smaller binary size and maybe faster, though I don't have large enough 19 | rio examples yet to know: 20 | 21 | ```sh 22 | cargo run --example bin-test -- --profile release-lto 23 | ``` 24 | 25 | Example usage of wasm-opt: 26 | 27 | ```sh 28 | wasm-opt -O3 --enable-multivalue --enable-bulk-memory \ 29 | examples/out/branch.wasm -o examples/out/branch-opt.wasm 30 | ``` 31 | -------------------------------------------------------------------------------- /examples/bin-test.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | fs, 3 | path::{Path, PathBuf}, 4 | process::Command, 5 | time::{Duration, Instant}, 6 | }; 7 | 8 | use clap::Parser; 9 | 10 | #[derive(clap::Parser)] 11 | struct Cli { 12 | #[arg(long)] 13 | profile: Option, 14 | #[arg(long)] 15 | quick: bool, 16 | } 17 | 18 | fn main() { 19 | let cli = Cli::parse(); 20 | install_tools(); 21 | let profile = cli.profile.clone().unwrap_or("release".into()); 22 | build_and_run(&profile, &cli); 23 | } 24 | 25 | fn build_and_run(profile: &str, cli: &Cli) { 26 | // Build 27 | println!("building profile {profile} ..."); 28 | let profile_args = match profile { 29 | "debug" => vec![], 30 | "release" => vec![format!("--{profile}")], 31 | _ => ["--profile", profile].iter().map(|s| (*s).into()).collect(), 32 | }; 33 | let start = Instant::now(); 34 | Command::new(CARGO) 35 | .arg("build") 36 | .args(profile_args) 37 | .status() 38 | .unwrap(); 39 | let mut rio = PathBuf::new().join("target").join(profile).join("rio"); 40 | if cfg!(target_os = "windows") { 41 | rio.set_extension("exe"); 42 | } 43 | // Report 44 | report_build(&rio, start.elapsed()); 45 | // Run 46 | let examples = ["branch", "hi", "recurse", "struct", "wild"]; 47 | // let examples = ["struct"]; 48 | for example in examples { 49 | run_example(&rio, example, cli); 50 | } 51 | } 52 | 53 | fn install_if_missing(command: &str) { 54 | let Ok(_) = Command::new(command).arg("-h").output() else { 55 | println!("{command} not found; installing ..."); 56 | Command::new(CARGO) 57 | .args(["install", command]) 58 | .status() 59 | .unwrap(); 60 | return; 61 | }; 62 | } 63 | 64 | fn install_tools() { 65 | install_if_missing(WASM_TOOLS); 66 | // install_if_missing("wasmi_cli"); 67 | } 68 | 69 | fn report_build>(path: P, duration: Duration) { 70 | let path = path.as_ref(); 71 | let Ok(metadata) = fs::metadata(path) else { 72 | panic!() 73 | }; 74 | println!( 75 | "built {} in {:.1?}: {} bytes ({:.2} MB)", 76 | path.to_str().unwrap(), 77 | duration, 78 | metadata.len(), 79 | metadata.len() as f64 / (1 << 20) as f64 80 | ); 81 | } 82 | 83 | fn run_example(rio: &PathBuf, example: &str, cli: &Cli) { 84 | let examples = "examples"; 85 | let examples_out = format!("{examples}/out"); 86 | let example_path = format!("{examples}/{example}.rio"); 87 | // Wasm 88 | let start = Instant::now(); 89 | let status = Command::new(rio) 90 | .args(["build", &example_path]) 91 | .args(if cli.quick { 92 | vec![] 93 | } else { 94 | vec!["--dump", "trees"] 95 | }) 96 | .args(["--outdir", &examples_out]) 97 | .arg("--time") 98 | .env("RUST_BACKTRACE", "1") 99 | .status() 100 | .unwrap(); 101 | if !status.success() { 102 | println!("build failed"); 103 | return; 104 | } 105 | let wasm = format!("{examples_out}/{example}.wasm"); 106 | report_build(Path::new(&wasm), start.elapsed()); 107 | // Wat 108 | Command::new(WASM_TOOLS) 109 | .args(["print", &wasm]) 110 | .args(["--output", &format!("{examples_out}/{example}.wat")]) 111 | .status() 112 | .unwrap(); 113 | // TODO Run 114 | } 115 | 116 | const CARGO: &str = "cargo"; 117 | const WASM_TOOLS: &str = "wasm-tools"; 118 | -------------------------------------------------------------------------------- /examples/branch.rio: -------------------------------------------------------------------------------- 1 | main* = for() be 2 | describe(2) 3 | describe(-1) 4 | describe(0) 5 | end 6 | 7 | describe = for(i: Int32) be 8 | print description(i) 9 | end 10 | 11 | description = for(i: Int32) be 12 | message = branch with 13 | i < 0 to "negative" 14 | i > 0 to "positive" 15 | else "zero" 16 | end 17 | message 18 | end 19 | 20 | less = for(i: Int32, j: Int32) be i < j 21 | -------------------------------------------------------------------------------- /examples/hi.rio: -------------------------------------------------------------------------------- 1 | main* = for() be 2 | message = "I say \"Hi!\"" 3 | printTwice(message, "") 4 | end 5 | 6 | printTwice = for(message: Text, middle: Text): Void be 7 | # Both call syntax forms below mean the same thing. 8 | print(message) 9 | print(middle) 10 | print message 11 | end 12 | -------------------------------------------------------------------------------- /examples/out/branch.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (type (;0;) (func (param i32 i32 i32 i32) (result i32))) 3 | (type (;1;) (func (param i32) (result i32 i32))) 4 | (type (;2;) (func (param i32))) 5 | (type (;3;) (func (param i32 i32))) 6 | (type (;4;) (func (param i32) (result i32))) 7 | (type (;5;) (func (param i32 i32 i32) (result i32 i32 i32))) 8 | (type (;6;) (func (param i32 i32) (result i32 i32))) 9 | (type (;7;) (func (result i32))) 10 | (type (;8;) (func)) 11 | (type (;9;) (func (result i32 i32))) 12 | (type (;10;) (func (param i32 i32))) 13 | (type (;11;) (func (param i32))) 14 | (type (;12;) (func (param i32 i32 i32 i32))) 15 | (type (;13;) (func (param i32 i32) (result i32))) 16 | (type (;14;) (func (param i32) (result i32 i32))) 17 | (import "wasi_snapshot_preview1" "fd_write" (func (;0;) (type 0))) 18 | (func $-i32.dup (;1;) (type 1) (param i32) (result i32 i32) 19 | local.get 0 20 | local.get 0 21 | ) 22 | (func $core::print (;2;) (type 3) (param i32 i32) 23 | local.get 0 24 | local.get 1 25 | call $-printInline 26 | i32.const 1 27 | i32.const 4096 28 | call $-printInline 29 | ) 30 | (func $-printInline (;3;) (type 3) (param i32 i32) 31 | (local i32 i32) 32 | i32.const 8 33 | call $-push 34 | local.set 2 35 | i32.const 4 36 | call $-push 37 | local.set 3 38 | local.get 2 39 | local.get 1 40 | i32.store align=1 41 | local.get 2 42 | i32.const 4 43 | i32.add 44 | local.get 0 45 | i32.store 46 | i32.const 1 47 | local.get 2 48 | i32.const 1 49 | local.get 3 50 | call 0 51 | drop 52 | i32.const 12 53 | call $-pop 54 | ) 55 | (func $-pop (;4;) (type 2) (param i32) 56 | global.get 0 57 | local.get 0 58 | i32.add 59 | global.set 0 60 | ) 61 | (func $-push (;5;) (type 4) (param i32) (result i32) 62 | (local i32) 63 | global.get 0 64 | local.get 0 65 | i32.sub 66 | local.tee 1 67 | global.set 0 68 | local.get 1 69 | ) 70 | (func $-rot3 (;6;) (type 5) (param i32 i32 i32) (result i32 i32 i32) 71 | local.get 2 72 | local.get 0 73 | local.get 1 74 | ) 75 | (func $-swap (;7;) (type 6) (param i32 i32) (result i32 i32) 76 | local.get 1 77 | local.get 0 78 | ) 79 | (func $main (;8;) (type 8) 80 | i32.const 2 81 | call $describe 82 | i32.const -1 83 | call $describe 84 | i32.const 0 85 | call $describe 86 | ) 87 | (func $describe (;9;) (type 11) (param i32) 88 | local.get 0 89 | call $description 90 | call $core::print 91 | ) 92 | (func $description (;10;) (type 14) (param i32) (result i32 i32) 93 | (local i32 i32) 94 | local.get 0 95 | i32.const 0 96 | i32.lt_s 97 | if (type 9) (result i32 i32) ;; label = @1 98 | i32.const 8 99 | i32.const 4098 100 | else 101 | local.get 0 102 | i32.const 0 103 | i32.gt_s 104 | if (type 9) (result i32 i32) ;; label = @2 105 | i32.const 8 106 | i32.const 4107 107 | else 108 | i32.const 4 109 | i32.const 4116 110 | end 111 | end 112 | local.set 2 113 | local.set 1 114 | local.get 1 115 | local.get 2 116 | ) 117 | (func $less (;11;) (type 13) (param i32 i32) (result i32) 118 | local.get 0 119 | local.get 1 120 | i32.lt_s 121 | ) 122 | (memory (;0;) 1) 123 | (global (;0;) (mut i32) i32.const 4096) 124 | (export "memory" (memory 0)) 125 | (export "_start" (func $main)) 126 | (data (;0;) (i32.const 4096) "\0a\00") 127 | (data (;1;) (i32.const 4098) "negative\00") 128 | (data (;2;) (i32.const 4107) "positive\00") 129 | (data (;3;) (i32.const 4116) "zero\00") 130 | ) 131 | -------------------------------------------------------------------------------- /examples/out/branch/branch.norm.txt: -------------------------------------------------------------------------------- 1 | Block 2 | Def 3 | Pub 4 | Id "main" 5 | None 6 | Fun 7 | Params 8 | Params 9 | Block 10 | Call 11 | Id "describe" 12 | Int32 2 13 | /Call 14 | Call 15 | Id "describe" 16 | Int32 -1 17 | /Call 18 | Call 19 | Id "describe" 20 | Int32 0 21 | /Call 22 | /Block 23 | /Fun 24 | /Def 25 | Def 26 | Id "describe" 27 | None 28 | Fun 29 | Params 30 | Def 31 | Id "i" 32 | Id "Int32" 33 | None 34 | /Def 35 | /Params 36 | Params 37 | Call 38 | Id "print" 39 | Call 40 | Id "description" 41 | Id "i" 42 | /Call 43 | /Call 44 | /Fun 45 | /Def 46 | Def 47 | Id "description" 48 | None 49 | Fun 50 | Params 51 | Def 52 | Id "i" 53 | Id "Int32" 54 | None 55 | /Def 56 | /Params 57 | Params 58 | Block 59 | Def 60 | Id "message" 61 | None 62 | Call 63 | Id "branch" 64 | List 65 | Call 66 | Id "Pair" 67 | Call 68 | Id "lt" 69 | Id "i" 70 | Int32 0 71 | /Call 72 | String "negative" 73 | /Call 74 | Call 75 | Id "Pair" 76 | Call 77 | Id "gt" 78 | Id "i" 79 | Int32 0 80 | /Call 81 | String "positive" 82 | /Call 83 | Call 84 | Id "else" 85 | String "zero" 86 | /Call 87 | /List 88 | /Call 89 | /Def 90 | Id "message" 91 | /Block 92 | /Fun 93 | /Def 94 | Def 95 | Id "less" 96 | None 97 | Fun 98 | Params 99 | Def 100 | Id "i" 101 | Id "Int32" 102 | None 103 | /Def 104 | Def 105 | Id "j" 106 | Id "Int32" 107 | None 108 | /Def 109 | /Params 110 | Params 111 | Call 112 | Id "lt" 113 | Id "i" 114 | Id "j" 115 | /Call 116 | /Fun 117 | /Def 118 | /Block 119 | 120 | Node size: 20 121 | Tree len: 86 122 | -------------------------------------------------------------------------------- /examples/out/branch/branch.parse.txt: -------------------------------------------------------------------------------- 1 | Block 2 | Def 3 | Pub 4 | Id "main" 5 | Star "*" 6 | /Pub 7 | HSpace " " 8 | Define "=" 9 | HSpace " " 10 | Fun 11 | Fun "for" 12 | Params 13 | RoundOpen "(" 14 | RoundClose ")" 15 | /Params 16 | HSpace " " 17 | Params 18 | Block 19 | Be "be" 20 | VSpace "\n" 21 | HSpace " " 22 | Call 23 | Id "describe" 24 | RoundOpen "(" 25 | Int "2" 26 | RoundClose ")" 27 | /Call 28 | VSpace "\n" 29 | HSpace " " 30 | Call 31 | Id "describe" 32 | RoundOpen "(" 33 | Int "-1" 34 | RoundClose ")" 35 | /Call 36 | VSpace "\n" 37 | HSpace " " 38 | Call 39 | Id "describe" 40 | RoundOpen "(" 41 | Int "0" 42 | RoundClose ")" 43 | /Call 44 | VSpace "\n" 45 | End "end" 46 | /Block 47 | /Fun 48 | /Def 49 | VSpace "\n" 50 | VSpace "\n" 51 | Def 52 | Id "describe" 53 | HSpace " " 54 | Define "=" 55 | HSpace " " 56 | Fun 57 | Fun "for" 58 | Params 59 | RoundOpen "(" 60 | Typed 61 | Id "i" 62 | Colon ":" 63 | HSpace " " 64 | Id "Int32" 65 | /Typed 66 | RoundClose ")" 67 | /Params 68 | HSpace " " 69 | Params 70 | Block 71 | Be "be" 72 | VSpace "\n" 73 | HSpace " " 74 | Call 75 | Id "print" 76 | HSpace " " 77 | Call 78 | Id "description" 79 | RoundOpen "(" 80 | Id "i" 81 | RoundClose ")" 82 | /Call 83 | /Call 84 | VSpace "\n" 85 | End "end" 86 | /Block 87 | /Fun 88 | /Def 89 | VSpace "\n" 90 | VSpace "\n" 91 | Def 92 | Id "description" 93 | HSpace " " 94 | Define "=" 95 | HSpace " " 96 | Fun 97 | Fun "for" 98 | Params 99 | RoundOpen "(" 100 | Typed 101 | Id "i" 102 | Colon ":" 103 | HSpace " " 104 | Id "Int32" 105 | /Typed 106 | RoundClose ")" 107 | /Params 108 | HSpace " " 109 | Params 110 | Block 111 | Be "be" 112 | VSpace "\n" 113 | HSpace " " 114 | Def 115 | Id "message" 116 | HSpace " " 117 | Define "=" 118 | HSpace " " 119 | Call 120 | Id "branch" 121 | HSpace " " 122 | Block 123 | With "with" 124 | VSpace "\n" 125 | HSpace " " 126 | Infix 127 | Infix 128 | Id "i" 129 | HSpace " " 130 | AngleOpen "<" 131 | HSpace " " 132 | Int "0" 133 | HSpace " " 134 | /Infix 135 | To "to" 136 | HSpace " " 137 | StringParts 138 | StringEdge "\"" 139 | String "negative" 140 | StringEdge "\"" 141 | /StringParts 142 | /Infix 143 | VSpace "\n" 144 | HSpace " " 145 | Infix 146 | Infix 147 | Id "i" 148 | HSpace " " 149 | AngleClose ">" 150 | HSpace " " 151 | Int "0" 152 | HSpace " " 153 | /Infix 154 | To "to" 155 | HSpace " " 156 | StringParts 157 | StringEdge "\"" 158 | String "positive" 159 | StringEdge "\"" 160 | /StringParts 161 | /Infix 162 | VSpace "\n" 163 | HSpace " " 164 | Call 165 | Id "else" 166 | HSpace " " 167 | StringParts 168 | StringEdge "\"" 169 | String "zero" 170 | StringEdge "\"" 171 | /StringParts 172 | /Call 173 | VSpace "\n" 174 | HSpace " " 175 | End "end" 176 | /Block 177 | /Call 178 | /Def 179 | VSpace "\n" 180 | HSpace " " 181 | Id "message" 182 | VSpace "\n" 183 | End "end" 184 | /Block 185 | /Fun 186 | /Def 187 | VSpace "\n" 188 | VSpace "\n" 189 | Def 190 | Id "less" 191 | HSpace " " 192 | Define "=" 193 | HSpace " " 194 | Fun 195 | Fun "for" 196 | Params 197 | RoundOpen "(" 198 | Typed 199 | Id "i" 200 | Colon ":" 201 | HSpace " " 202 | Id "Int32" 203 | /Typed 204 | Comma "," 205 | HSpace " " 206 | Typed 207 | Id "j" 208 | Colon ":" 209 | HSpace " " 210 | Id "Int32" 211 | /Typed 212 | RoundClose ")" 213 | /Params 214 | HSpace " " 215 | Params 216 | Block 217 | Be "be" 218 | HSpace " " 219 | Infix 220 | Id "i" 221 | HSpace " " 222 | AngleOpen "<" 223 | HSpace " " 224 | Id "j" 225 | /Infix 226 | /Block 227 | /Fun 228 | /Def 229 | VSpace "\n" 230 | /Block 231 | 232 | Node size: 12 233 | Tree len: 191 234 | -------------------------------------------------------------------------------- /examples/out/branch/branch.run.txt: -------------------------------------------------------------------------------- 1 | Block 2 | Module "examples/branch.rio" 2 3 | Def@107 :@105 4 | Uid main@107* :@105 5 | None 6 | Fun :@105 7 | Params 8 | Params 9 | Block :@95 10 | Call :@95 11 | Uid describe@108 :@104 12 | Int32 2 :@93 13 | /Call 14 | Call :@95 15 | Uid describe@108 :@104 16 | Int32 -1 :@93 17 | /Call 18 | Call :@95 19 | Uid describe@108 :@104 20 | Int32 0 :@93 21 | /Call 22 | /Block 23 | /Fun 24 | /Def 25 | Def@108 :@104 26 | Uid describe@108 :@104 27 | None 28 | Fun :@104 29 | Params 30 | Def@19 :@93 31 | Uid i@19 :@93 32 | Uid Int32@1@635 33 | None :@93 34 | /Def 35 | /Params 36 | Params 37 | Call :@95 38 | Uid print@1@662 :@97 39 | Call :@96 40 | Uid description@109 :@102 41 | Uid i@19 :@93 42 | /Call 43 | /Call 44 | /Fun 45 | /Def 46 | Def@109 :@102 47 | Uid description@109 :@102 48 | None 49 | Fun :@102 50 | Params 51 | Def@33 :@93 52 | Uid i@33 :@93 53 | Uid Int32@1@635 54 | None :@93 55 | /Def 56 | /Params 57 | Params 58 | Block :@96 59 | Def@56 :@96 60 | Uid message@56 :@96 61 | None 62 | Call :@96 63 | Uid branch@1@653 64 | List 65 | Call 66 | Uid Pair@1@648 :@99 67 | Call :@100 68 | Uid lt@1@641 :@101 69 | Uid i@33 :@93 70 | Int32 0 :@93 71 | /Call 72 | String "negative" :@96 73 | /Call 74 | Call 75 | Uid Pair@1@648 :@99 76 | Call :@100 77 | Uid gt@1@639 :@101 78 | Uid i@33 :@93 79 | Int32 0 :@93 80 | /Call 81 | String "positive" :@96 82 | /Call 83 | Call 84 | Uid else@1@656 85 | String "zero" :@96 86 | /Call 87 | /List 88 | /Call 89 | /Def 90 | Uid message@56 :@96 91 | /Block 92 | /Fun 93 | /Def 94 | Def@110 :@101 95 | Uid less@110 :@101 96 | None 97 | Fun :@101 98 | Params 99 | Def@70 :@93 100 | Uid i@70 :@93 101 | Uid Int32@1@635 102 | None :@93 103 | /Def 104 | Def@71 :@93 105 | Uid j@71 :@93 106 | Uid Int32@1@635 107 | None :@93 108 | /Def 109 | /Params 110 | Params 111 | Call :@100 112 | Uid lt@1@641 :@101 113 | Uid i@70 :@93 114 | Uid j@71 :@93 115 | /Call 116 | /Fun 117 | /Def 118 | Types 119 | Uid@93 Int32@1@635 120 | FunType@94 121 | Uid@95 Void@1@651 122 | Uid@96 Text@1@649 123 | FunType@97 :@95 124 | None :@96 125 | FunType@98 126 | None :@93 127 | FunType@99 128 | None 129 | None 130 | None 131 | None 132 | /FunType 133 | Uid@100 Claim@1@632 134 | FunType@101 :@100 135 | None :@93 136 | None :@93 137 | /FunType 138 | FunType@102 :@96 139 | None :@93 140 | FunType@103 141 | None :@93 142 | None :@93 143 | /FunType 144 | FunType@104 :@95 145 | None :@93 146 | FunType@105 :@95 147 | /Types 148 | /Block 149 | 150 | Node size: 20 151 | Tree len: 112 152 | -------------------------------------------------------------------------------- /examples/out/core/core.norm.txt: -------------------------------------------------------------------------------- 1 | Block 2 | Def 3 | Pub 4 | Id "Case" 5 | None 6 | Fun 7 | Params 8 | AngleOpen "<" 9 | Id "Value" 10 | AngleClose ">" 11 | /Params 12 | Params 13 | Call 14 | Id "Pair" 15 | AngleOpen "<" 16 | Call 17 | Id "Lazy" 18 | AngleOpen "<" 19 | Id "Claim" 20 | AngleClose ">" 21 | /Call 22 | Call 23 | Id "Lazy" 24 | AngleOpen "<" 25 | Id "Value" 26 | AngleClose ">" 27 | /Call 28 | AngleClose ">" 29 | /Call 30 | /Fun 31 | /Def 32 | Def 33 | Pub 34 | Id "Claim" 35 | None 36 | Call 37 | Id "Either" 38 | AngleOpen "<" 39 | Id "Void" 40 | Id "Void" 41 | AngleClose ">" 42 | /Call 43 | /Def 44 | Def 45 | Pub 46 | Id "Either" 47 | None 48 | Fun 49 | Params 50 | AngleOpen "<" 51 | Id "YesValue" 52 | Id "NoValue" 53 | AngleClose ">" 54 | /Params 55 | Params 56 | Call 57 | Call 58 | Id "Yes" 59 | AngleOpen "<" 60 | Id "YesValue" 61 | AngleClose ">" 62 | /Call 63 | Id "|" 64 | Call 65 | Id "No" 66 | AngleOpen "<" 67 | Id "NoValue" 68 | AngleClose ">" 69 | /Call 70 | /Call 71 | /Fun 72 | /Def 73 | Def 74 | Pub 75 | Id "Function" 76 | None 77 | Fun 78 | Params 79 | AngleOpen "<" 80 | Def 81 | Id "ArgTypes" 82 | Call 83 | Id "List" 84 | AngleOpen "<" 85 | Id "Type" 86 | AngleClose ">" 87 | /Call 88 | None 89 | /Def 90 | Id "ReturnType" 91 | AngleClose ">" 92 | /Params 93 | Params 94 | Call 95 | Id "class" 96 | Of "of" 97 | /Call 98 | /Fun 99 | /Def 100 | Def 101 | Pub 102 | Id "Int32" 103 | None 104 | Call 105 | Id "class" 106 | Struct 107 | Def 108 | Pub 109 | Id "add" 110 | None 111 | Fun 112 | Params 113 | Def 114 | Id "other" 115 | Id "Int32" 116 | None 117 | /Def 118 | /Params 119 | Params 120 | Def 121 | None 122 | Id "Int32" 123 | None 124 | /Def 125 | /Params 126 | Call 127 | Id "native" 128 | /Fun 129 | /Def 130 | Def 131 | Pub 132 | Id "gt" 133 | None 134 | Fun 135 | Params 136 | Def 137 | Id "other" 138 | Id "Int32" 139 | None 140 | /Def 141 | /Params 142 | Params 143 | Def 144 | None 145 | Id "Claim" 146 | None 147 | /Def 148 | /Params 149 | Call 150 | Id "native" 151 | /Fun 152 | /Def 153 | Def 154 | Pub 155 | Id "lt" 156 | None 157 | Fun 158 | Params 159 | Def 160 | Id "other" 161 | Id "Int32" 162 | None 163 | /Def 164 | /Params 165 | Params 166 | Def 167 | None 168 | Id "Claim" 169 | None 170 | /Def 171 | /Params 172 | Call 173 | Id "native" 174 | /Fun 175 | /Def 176 | Def 177 | Pub 178 | Id "eq" 179 | None 180 | Fun 181 | Params 182 | Def 183 | Id "other" 184 | Id "Int32" 185 | None 186 | /Def 187 | /Params 188 | Params 189 | Def 190 | None 191 | Id "Claim" 192 | None 193 | /Def 194 | /Params 195 | Call 196 | Id "native" 197 | /Fun 198 | /Def 199 | /Struct 200 | /Call 201 | /Def 202 | Def 203 | Pub 204 | Id "add" 205 | None 206 | Fun 207 | Params 208 | Def 209 | Id "a" 210 | Id "Int32" 211 | None 212 | /Def 213 | Def 214 | Id "b" 215 | Id "Int32" 216 | None 217 | /Def 218 | /Params 219 | Params 220 | Def 221 | None 222 | Id "Int32" 223 | None 224 | /Def 225 | /Params 226 | Call 227 | Id "native" 228 | /Fun 229 | /Def 230 | Def 231 | Pub 232 | Id "eq" 233 | None 234 | Fun 235 | Params 236 | Def 237 | Id "a" 238 | Id "Int32" 239 | None 240 | /Def 241 | Def 242 | Id "b" 243 | Id "Int32" 244 | None 245 | /Def 246 | /Params 247 | Params 248 | Def 249 | None 250 | Id "Claim" 251 | None 252 | /Def 253 | /Params 254 | Call 255 | Id "native" 256 | /Fun 257 | /Def 258 | Def 259 | Pub 260 | Id "ge" 261 | None 262 | Fun 263 | Params 264 | Def 265 | Id "a" 266 | Id "Int32" 267 | None 268 | /Def 269 | Def 270 | Id "b" 271 | Id "Int32" 272 | None 273 | /Def 274 | /Params 275 | Params 276 | Def 277 | None 278 | Id "Claim" 279 | None 280 | /Def 281 | /Params 282 | Call 283 | Id "native" 284 | /Fun 285 | /Def 286 | Def 287 | Pub 288 | Id "gt" 289 | None 290 | Fun 291 | Params 292 | Def 293 | Id "a" 294 | Id "Int32" 295 | None 296 | /Def 297 | Def 298 | Id "b" 299 | Id "Int32" 300 | None 301 | /Def 302 | /Params 303 | Params 304 | Def 305 | None 306 | Id "Claim" 307 | None 308 | /Def 309 | /Params 310 | Call 311 | Id "native" 312 | /Fun 313 | /Def 314 | Def 315 | Pub 316 | Id "le" 317 | None 318 | Fun 319 | Params 320 | Def 321 | Id "a" 322 | Id "Int32" 323 | None 324 | /Def 325 | Def 326 | Id "b" 327 | Id "Int32" 328 | None 329 | /Def 330 | /Params 331 | Params 332 | Def 333 | None 334 | Id "Claim" 335 | None 336 | /Def 337 | /Params 338 | Call 339 | Id "native" 340 | /Fun 341 | /Def 342 | Def 343 | Pub 344 | Id "lt" 345 | None 346 | Fun 347 | Params 348 | Def 349 | Id "a" 350 | Id "Int32" 351 | None 352 | /Def 353 | Def 354 | Id "b" 355 | Id "Int32" 356 | None 357 | /Def 358 | /Params 359 | Params 360 | Def 361 | None 362 | Id "Claim" 363 | None 364 | /Def 365 | /Params 366 | Call 367 | Id "native" 368 | /Fun 369 | /Def 370 | Def 371 | Pub 372 | Id "ne" 373 | None 374 | Fun 375 | Params 376 | Def 377 | Id "a" 378 | Id "Int32" 379 | None 380 | /Def 381 | Def 382 | Id "b" 383 | Id "Int32" 384 | None 385 | /Def 386 | /Params 387 | Params 388 | Def 389 | None 390 | Id "Claim" 391 | None 392 | /Def 393 | /Params 394 | Call 395 | Id "native" 396 | /Fun 397 | /Def 398 | Def 399 | Pub 400 | Id "sub" 401 | None 402 | Fun 403 | Params 404 | Def 405 | Id "a" 406 | Id "Int32" 407 | None 408 | /Def 409 | Def 410 | Id "b" 411 | Id "Int32" 412 | None 413 | /Def 414 | /Params 415 | Params 416 | Def 417 | None 418 | Id "Int32" 419 | None 420 | /Def 421 | /Params 422 | Call 423 | Id "native" 424 | /Fun 425 | /Def 426 | Def 427 | Pub 428 | Id "Lazy" 429 | None 430 | Fun 431 | Params 432 | AngleOpen "<" 433 | Id "Value" 434 | AngleClose ">" 435 | /Params 436 | Params 437 | Call 438 | Call 439 | Id "class" 440 | Struct 441 | Def 442 | Id "builder" 443 | Call 444 | Id "Function" 445 | AngleOpen "<" 446 | Id "[]" 447 | Id "Value" 448 | AngleClose ">" 449 | /Call 450 | None 451 | /Def 452 | /Struct 453 | /Call 454 | List 455 | Def 456 | Pub 457 | Id "value" 458 | None 459 | Fun 460 | Params 461 | Params 462 | Block 463 | Call 464 | Id "if" 465 | Call 466 | Id "not" 467 | Id "maybe" 468 | /Call 469 | Def 470 | Id "maybe" 471 | Call 472 | None 473 | Call 474 | Id "Yes" 475 | Call 476 | Id "builder" 477 | /Call 478 | /Call 479 | None 480 | /Def 481 | /Call 482 | Dot 483 | Call 484 | Id "maybe" 485 | Id "as" 486 | Id "Yes" 487 | /Call 488 | Id "value" 489 | /Dot 490 | /Block 491 | /Fun 492 | /Def 493 | Def 494 | Id "maybe" 495 | Call 496 | Id "Maybe" 497 | AngleOpen "<" 498 | Id "Value" 499 | AngleClose ">" 500 | /Call 501 | Id "false" 502 | /Def 503 | /List 504 | /Call 505 | /Fun 506 | /Def 507 | Def 508 | Pub 509 | Id "List" 510 | None 511 | Fun 512 | Params 513 | AngleOpen "<" 514 | Id "Item" 515 | AngleClose ">" 516 | /Params 517 | Params 518 | Call 519 | Id "class" 520 | Of "of" 521 | /Call 522 | /Fun 523 | /Def 524 | Def 525 | Pub 526 | Id "Maybe" 527 | None 528 | Fun 529 | Params 530 | AngleOpen "<" 531 | Id "Value" 532 | AngleClose ">" 533 | /Params 534 | Params 535 | Call 536 | Id "Either" 537 | AngleOpen "<" 538 | Id "Value" 539 | Id "Void" 540 | AngleClose ">" 541 | /Call 542 | /Fun 543 | /Def 544 | Def 545 | Pub 546 | Id "No" 547 | None 548 | Fun 549 | Params 550 | AngleOpen "<" 551 | Id "Value" 552 | AngleClose ">" 553 | /Params 554 | Params 555 | Call 556 | Id "ordered" 557 | Call 558 | Id "struct" 559 | Struct 560 | Def 561 | Id "value" 562 | Id "Value" 563 | None 564 | /Def 565 | /Struct 566 | /Call 567 | /Call 568 | /Fun 569 | /Def 570 | Def 571 | Pub 572 | Id "Pair" 573 | None 574 | Fun 575 | Params 576 | AngleOpen "<" 577 | Id "Key" 578 | Id "Value" 579 | AngleClose ">" 580 | /Params 581 | Params 582 | Call 583 | Id "ordered" 584 | Call 585 | Id "struct" 586 | Struct 587 | Def 588 | Id "key" 589 | Id "Key" 590 | None 591 | /Def 592 | Def 593 | Id "value" 594 | Id "Value" 595 | None 596 | /Def 597 | /Struct 598 | /Call 599 | /Call 600 | /Fun 601 | /Def 602 | Def 603 | Pub 604 | Id "Text" 605 | Id "Type" 606 | Call 607 | Id "native" 608 | /Def 609 | Def 610 | Pub 611 | Id "Type" 612 | None 613 | Call 614 | Id "class" 615 | Struct 616 | Def 617 | Pub 618 | Id "union" 619 | None 620 | Fun 621 | Params 622 | Def 623 | Id "a" 624 | Id "Type" 625 | None 626 | /Def 627 | Def 628 | Id "b" 629 | Id "Type" 630 | None 631 | /Def 632 | /Params 633 | Params 634 | Def 635 | None 636 | Id "Type" 637 | None 638 | /Def 639 | /Params 640 | Call 641 | Id "native" 642 | /Fun 643 | /Def 644 | /Struct 645 | /Call 646 | /Def 647 | Def 648 | Pub 649 | Id "Void" 650 | Id "Type" 651 | Call 652 | Id "native" 653 | /Def 654 | Def 655 | Pub 656 | Id "Yes" 657 | None 658 | Fun 659 | Params 660 | AngleOpen "<" 661 | Id "Value" 662 | AngleClose ">" 663 | /Params 664 | Params 665 | Call 666 | Id "ordered" 667 | Call 668 | Id "struct" 669 | Struct 670 | Def 671 | Id "value" 672 | Id "Value" 673 | None 674 | /Def 675 | /Struct 676 | /Call 677 | /Call 678 | /Fun 679 | /Def 680 | Def 681 | Pub 682 | Id "branch" 683 | None 684 | Def 685 | Fun 686 | Params 687 | AngleOpen "<" 688 | Id "Value" 689 | AngleClose ">" 690 | /Params 691 | Params 692 | Def 693 | Id "cases" 694 | Call 695 | Id "List" 696 | AngleOpen "<" 697 | Call 698 | Id "Case" 699 | AngleOpen "<" 700 | Id "Value" 701 | AngleClose ">" 702 | /Call 703 | AngleClose ">" 704 | /Call 705 | None 706 | /Def 707 | /Fun 708 | Id "Value" 709 | None 710 | /Def 711 | /Def 712 | Call 713 | Id "native" 714 | Def 715 | Pub 716 | Id "class" 717 | None 718 | Fun 719 | Params 720 | Params 721 | Call 722 | Id "native" 723 | /Fun 724 | /Def 725 | Def 726 | Pub 727 | Id "else" 728 | None 729 | Def 730 | Fun 731 | Params 732 | AngleOpen "<" 733 | Id "Value" 734 | AngleClose ">" 735 | /Params 736 | Params 737 | Def 738 | Id "value" 739 | Call 740 | Id "Lazy" 741 | AngleOpen "<" 742 | Id "Value" 743 | AngleClose ">" 744 | /Call 745 | None 746 | /Def 747 | /Fun 748 | Call 749 | Id "Case" 750 | AngleOpen "<" 751 | Id "Value" 752 | AngleClose ">" 753 | /Call 754 | None 755 | /Def 756 | /Def 757 | Call 758 | Id "Pair" 759 | Id "true" 760 | Id "value" 761 | /Call 762 | Def 763 | Pub 764 | Id "false" 765 | Id "Claim" 766 | Call 767 | Id "No" 768 | Id "void" 769 | /Call 770 | /Def 771 | Def 772 | Pub 773 | Id "native" 774 | None 775 | Fun 776 | Params 777 | Params 778 | Call 779 | Id "native" 780 | /Fun 781 | /Def 782 | Def 783 | Pub 784 | Id "not" 785 | None 786 | Fun 787 | Params 788 | Def 789 | Id "claim" 790 | Id "Claim" 791 | None 792 | /Def 793 | /Params 794 | Params 795 | Def 796 | None 797 | Id "Claim" 798 | None 799 | /Def 800 | /Params 801 | Call 802 | Id "branch" 803 | List 804 | Call 805 | Id "Pair" 806 | Id "claim" 807 | Id "false" 808 | /Call 809 | Call 810 | Id "else" 811 | Id "true" 812 | /Call 813 | /List 814 | /Call 815 | /Fun 816 | /Def 817 | Def 818 | Pub 819 | Id "ordered" 820 | None 821 | Fun 822 | Params 823 | Params 824 | Call 825 | Id "native" 826 | /Fun 827 | /Def 828 | Def 829 | Pub 830 | Id "print" 831 | None 832 | Fun 833 | Params 834 | Def 835 | Id "text" 836 | Id "Text" 837 | None 838 | /Def 839 | /Params 840 | Params 841 | Def 842 | None 843 | Id "Void" 844 | None 845 | /Def 846 | /Params 847 | Call 848 | Id "native" 849 | /Fun 850 | /Def 851 | Def 852 | Pub 853 | Id "struct" 854 | None 855 | Fun 856 | Params 857 | Params 858 | Def 859 | None 860 | Id "Type" 861 | None 862 | /Def 863 | /Params 864 | Call 865 | Id "native" 866 | /Fun 867 | /Def 868 | Def 869 | Pub 870 | Id "true" 871 | Id "Claim" 872 | Call 873 | Id "Yes" 874 | Id "void" 875 | /Call 876 | /Def 877 | Def 878 | Pub 879 | Id "void" 880 | Id "Void" 881 | Call 882 | Id "native" 883 | /Def 884 | /Block 885 | 886 | Node size: 20 887 | Tree len: 671 888 | -------------------------------------------------------------------------------- /examples/out/hi.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (type (;0;) (func (param i32 i32 i32 i32) (result i32))) 3 | (type (;1;) (func (param i32) (result i32 i32))) 4 | (type (;2;) (func (param i32))) 5 | (type (;3;) (func (param i32 i32))) 6 | (type (;4;) (func (param i32) (result i32))) 7 | (type (;5;) (func (param i32 i32 i32) (result i32 i32 i32))) 8 | (type (;6;) (func (param i32 i32) (result i32 i32))) 9 | (type (;7;) (func (result i32 i32))) 10 | (type (;8;) (func)) 11 | (type (;9;) (func (result i32))) 12 | (type (;10;) (func (param i32 i32))) 13 | (type (;11;) (func (param i32 i32 i32 i32))) 14 | (import "wasi_snapshot_preview1" "fd_write" (func (;0;) (type 0))) 15 | (func $-i32.dup (;1;) (type 1) (param i32) (result i32 i32) 16 | local.get 0 17 | local.get 0 18 | ) 19 | (func $core::print (;2;) (type 3) (param i32 i32) 20 | local.get 0 21 | local.get 1 22 | call $-printInline 23 | i32.const 1 24 | i32.const 4096 25 | call $-printInline 26 | ) 27 | (func $-printInline (;3;) (type 3) (param i32 i32) 28 | (local i32 i32) 29 | i32.const 8 30 | call $-push 31 | local.set 2 32 | i32.const 4 33 | call $-push 34 | local.set 3 35 | local.get 2 36 | local.get 1 37 | i32.store align=1 38 | local.get 2 39 | i32.const 4 40 | i32.add 41 | local.get 0 42 | i32.store 43 | i32.const 1 44 | local.get 2 45 | i32.const 1 46 | local.get 3 47 | call 0 48 | drop 49 | i32.const 12 50 | call $-pop 51 | ) 52 | (func $-pop (;4;) (type 2) (param i32) 53 | global.get 0 54 | local.get 0 55 | i32.add 56 | global.set 0 57 | ) 58 | (func $-push (;5;) (type 4) (param i32) (result i32) 59 | (local i32) 60 | global.get 0 61 | local.get 0 62 | i32.sub 63 | local.tee 1 64 | global.set 0 65 | local.get 1 66 | ) 67 | (func $-rot3 (;6;) (type 5) (param i32 i32 i32) (result i32 i32 i32) 68 | local.get 2 69 | local.get 0 70 | local.get 1 71 | ) 72 | (func $-swap (;7;) (type 6) (param i32 i32) (result i32 i32) 73 | local.get 1 74 | local.get 0 75 | ) 76 | (func $main (;8;) (type 8) 77 | (local i32 i32) 78 | i32.const 11 79 | i32.const 4098 80 | local.set 1 81 | local.set 0 82 | local.get 0 83 | local.get 1 84 | i32.const 0 85 | i32.const 4110 86 | call $printTwice 87 | ) 88 | (func $printTwice (;9;) (type 11) (param i32 i32 i32 i32) 89 | local.get 0 90 | local.get 1 91 | call $core::print 92 | local.get 2 93 | local.get 3 94 | call $core::print 95 | local.get 0 96 | local.get 1 97 | call $core::print 98 | ) 99 | (memory (;0;) 1) 100 | (global (;0;) (mut i32) i32.const 4096) 101 | (export "memory" (memory 0)) 102 | (export "_start" (func $main)) 103 | (data (;0;) (i32.const 4096) "\0a\00") 104 | (data (;1;) (i32.const 4098) "I say \22Hi!\22\00") 105 | (data (;2;) (i32.const 4110) "\00") 106 | ) 107 | -------------------------------------------------------------------------------- /examples/out/hi/hi.norm.txt: -------------------------------------------------------------------------------- 1 | Block 2 | Def 3 | Pub 4 | Id "main" 5 | None 6 | Fun 7 | Params 8 | Params 9 | Block 10 | Def 11 | Id "message" 12 | None 13 | String "I say \"Hi!\"" 14 | /Def 15 | Call 16 | Id "printTwice" 17 | Id "message" 18 | String "" 19 | /Call 20 | /Block 21 | /Fun 22 | /Def 23 | Def 24 | Id "printTwice" 25 | None 26 | Fun 27 | Params 28 | Def 29 | Id "message" 30 | Id "Text" 31 | None 32 | /Def 33 | Def 34 | Id "middle" 35 | Id "Text" 36 | None 37 | /Def 38 | /Params 39 | Params 40 | Def 41 | None 42 | Id "Void" 43 | None 44 | /Def 45 | /Params 46 | Block 47 | Call 48 | Id "print" 49 | Id "message" 50 | /Call 51 | Call 52 | Id "print" 53 | Id "middle" 54 | /Call 55 | Call 56 | Id "print" 57 | Id "message" 58 | /Call 59 | /Block 60 | /Fun 61 | /Def 62 | /Block 63 | 64 | Node size: 20 65 | Tree len: 45 66 | -------------------------------------------------------------------------------- /examples/out/hi/hi.parse.txt: -------------------------------------------------------------------------------- 1 | Block 2 | Def 3 | Pub 4 | Id "main" 5 | Star "*" 6 | /Pub 7 | HSpace " " 8 | Define "=" 9 | HSpace " " 10 | Fun 11 | Fun "for" 12 | Params 13 | RoundOpen "(" 14 | RoundClose ")" 15 | /Params 16 | HSpace " " 17 | Params 18 | Block 19 | Be "be" 20 | VSpace "\n" 21 | HSpace " " 22 | Def 23 | Id "message" 24 | HSpace " " 25 | Define "=" 26 | HSpace " " 27 | StringParts 28 | StringEdge "\"" 29 | String "I say " 30 | StringEscaper "\\" 31 | StringEscape "\"" 32 | String "Hi!" 33 | StringEscaper "\\" 34 | StringEscape "\"" 35 | StringEdge "\"" 36 | /StringParts 37 | /Def 38 | VSpace "\n" 39 | HSpace " " 40 | Call 41 | Id "printTwice" 42 | RoundOpen "(" 43 | Id "message" 44 | Comma "," 45 | HSpace " " 46 | StringParts 47 | StringEdge "\"" 48 | StringEdge "\"" 49 | /StringParts 50 | RoundClose ")" 51 | /Call 52 | VSpace "\n" 53 | End "end" 54 | /Block 55 | /Fun 56 | /Def 57 | VSpace "\n" 58 | VSpace "\n" 59 | Def 60 | Id "printTwice" 61 | HSpace " " 62 | Define "=" 63 | HSpace " " 64 | Fun 65 | Fun "for" 66 | Params 67 | RoundOpen "(" 68 | Typed 69 | Id "message" 70 | Colon ":" 71 | HSpace " " 72 | Id "Text" 73 | /Typed 74 | Comma "," 75 | HSpace " " 76 | Typed 77 | Id "middle" 78 | Colon ":" 79 | HSpace " " 80 | Id "Text" 81 | /Typed 82 | RoundClose ")" 83 | /Params 84 | Colon ":" 85 | HSpace " " 86 | Params 87 | Typed 88 | None 89 | Id "Void" 90 | HSpace " " 91 | /Typed 92 | /Params 93 | Block 94 | Be "be" 95 | VSpace "\n" 96 | HSpace " " 97 | Comment "# Both call syntax forms below mean the same thing." 98 | VSpace "\n" 99 | HSpace " " 100 | Call 101 | Id "print" 102 | RoundOpen "(" 103 | Id "message" 104 | RoundClose ")" 105 | /Call 106 | VSpace "\n" 107 | HSpace " " 108 | Call 109 | Id "print" 110 | RoundOpen "(" 111 | Id "middle" 112 | RoundClose ")" 113 | /Call 114 | VSpace "\n" 115 | HSpace " " 116 | Call 117 | Id "print" 118 | HSpace " " 119 | Id "message" 120 | /Call 121 | VSpace "\n" 122 | End "end" 123 | /Block 124 | /Fun 125 | /Def 126 | VSpace "\n" 127 | /Block 128 | 129 | Node size: 12 130 | Tree len: 106 131 | -------------------------------------------------------------------------------- /examples/out/hi/hi.run.txt: -------------------------------------------------------------------------------- 1 | Block 2 | Module "examples/hi.rio" 2 3 | Def@53 :@51 4 | Uid main@53* :@51 5 | None 6 | Fun :@51 7 | Params 8 | Params 9 | Block :@48 10 | Def@7 :@45 11 | Uid message@7 :@45 12 | None 13 | String "I say \"Hi!\"" :@45 14 | /Def 15 | Call :@48 16 | Uid printTwice@54 :@50 17 | Uid message@7 :@45 18 | String "" :@45 19 | /Call 20 | /Block 21 | /Fun 22 | /Def 23 | Def@54 :@50 24 | Uid printTwice@54 :@50 25 | None 26 | Fun :@50 27 | Params 28 | Def@21 :@45 29 | Uid message@21 :@45 30 | Uid Text@1@649 :@47 31 | None :@45 32 | /Def 33 | Def@22 :@45 34 | Uid middle@22 :@45 35 | Uid Text@1@649 :@47 36 | None :@45 37 | /Def 38 | /Params 39 | Params 40 | Def@26 :@48 41 | None :@48 42 | Uid Void@1@651 :@47 43 | None :@48 44 | /Def 45 | /Params 46 | Block :@48 47 | Call :@48 48 | Uid print@1@662 :@49 49 | Uid message@21 :@45 50 | /Call 51 | Call :@48 52 | Uid print@1@662 :@49 53 | Uid middle@22 :@45 54 | /Call 55 | Call :@48 56 | Uid print@1@662 :@49 57 | Uid message@21 :@45 58 | /Call 59 | /Block 60 | /Fun 61 | /Def 62 | Types 63 | Uid@45 Text@1@649 64 | FunType@46 65 | Uid@47 Type@1@650 66 | Uid@48 Void@1@651 67 | FunType@49 :@48 68 | None :@45 69 | FunType@50 :@48 70 | None :@45 71 | None :@45 72 | /FunType 73 | FunType@51 :@48 74 | /Types 75 | /Block 76 | 77 | Node size: 20 78 | Tree len: 56 79 | -------------------------------------------------------------------------------- /examples/out/recurse.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (type (;0;) (func (param i32 i32 i32 i32) (result i32))) 3 | (type (;1;) (func (param i32) (result i32 i32))) 4 | (type (;2;) (func (param i32))) 5 | (type (;3;) (func (param i32 i32))) 6 | (type (;4;) (func (param i32) (result i32))) 7 | (type (;5;) (func (param i32 i32 i32) (result i32 i32 i32))) 8 | (type (;6;) (func (param i32 i32) (result i32 i32))) 9 | (type (;7;) (func (result i32))) 10 | (type (;8;) (func)) 11 | (type (;9;) (func (result i32 i32))) 12 | (type (;10;) (func (param i32 i32))) 13 | (type (;11;) (func (param i32 i32) (result i32))) 14 | (type (;12;) (func (param i32 i32 i32 i32))) 15 | (type (;13;) (func (param i32))) 16 | (type (;14;) (func (param i32) (result i32))) 17 | (type (;15;) (func (param i32) (result i32 i32))) 18 | (import "wasi_snapshot_preview1" "fd_write" (func (;0;) (type 0))) 19 | (func $-i32.dup (;1;) (type 1) (param i32) (result i32 i32) 20 | local.get 0 21 | local.get 0 22 | ) 23 | (func $core::print (;2;) (type 3) (param i32 i32) 24 | local.get 0 25 | local.get 1 26 | call $-printInline 27 | i32.const 1 28 | i32.const 4096 29 | call $-printInline 30 | ) 31 | (func $-printInline (;3;) (type 3) (param i32 i32) 32 | (local i32 i32) 33 | i32.const 8 34 | call $-push 35 | local.set 2 36 | i32.const 4 37 | call $-push 38 | local.set 3 39 | local.get 2 40 | local.get 1 41 | i32.store align=1 42 | local.get 2 43 | i32.const 4 44 | i32.add 45 | local.get 0 46 | i32.store 47 | i32.const 1 48 | local.get 2 49 | i32.const 1 50 | local.get 3 51 | call 0 52 | drop 53 | i32.const 12 54 | call $-pop 55 | ) 56 | (func $-pop (;4;) (type 2) (param i32) 57 | global.get 0 58 | local.get 0 59 | i32.add 60 | global.set 0 61 | ) 62 | (func $-push (;5;) (type 4) (param i32) (result i32) 63 | (local i32) 64 | global.get 0 65 | local.get 0 66 | i32.sub 67 | local.tee 1 68 | global.set 0 69 | local.get 1 70 | ) 71 | (func $-rot3 (;6;) (type 5) (param i32 i32 i32) (result i32 i32 i32) 72 | local.get 2 73 | local.get 0 74 | local.get 1 75 | ) 76 | (func $-swap (;7;) (type 6) (param i32 i32) (result i32 i32) 77 | local.get 1 78 | local.get 0 79 | ) 80 | (func $main (;8;) (type 8) 81 | (local i32) 82 | i32.const 3 83 | local.set 0 84 | local.get 0 85 | call $countDown 86 | local.get 0 87 | call $oddness 88 | call $core::print 89 | local.get 0 90 | i32.const 1 91 | i32.add 92 | call $oddness 93 | call $core::print 94 | ) 95 | (func $countDown (;9;) (type 13) (param i32) 96 | i32.const 12 97 | i32.const 4098 98 | call $core::print 99 | local.get 0 100 | i32.const 1 101 | i32.gt_s 102 | if ;; label = @1 103 | local.get 0 104 | i32.const 1 105 | i32.sub 106 | call $countDown 107 | else 108 | i32.const 4 109 | i32.const 4111 110 | call $core::print 111 | end 112 | ) 113 | (func $isEven (;10;) (type 14) (param i32) (result i32) 114 | local.get 0 115 | i32.const 0 116 | i32.gt_s 117 | if (type 7) (result i32) ;; label = @1 118 | local.get 0 119 | i32.const 1 120 | i32.sub 121 | call $isOdd 122 | else 123 | i32.const 1 124 | end 125 | ) 126 | (func $isOdd (;11;) (type 14) (param i32) (result i32) 127 | local.get 0 128 | i32.const 0 129 | i32.gt_s 130 | if (type 7) (result i32) ;; label = @1 131 | local.get 0 132 | i32.const 1 133 | i32.sub 134 | call $isEven 135 | else 136 | i32.const 0 137 | end 138 | ) 139 | (func $oddness (;12;) (type 15) (param i32) (result i32 i32) 140 | local.get 0 141 | call $isEven 142 | if (type 9) (result i32 i32) ;; label = @1 143 | i32.const 4 144 | i32.const 4116 145 | else 146 | i32.const 3 147 | i32.const 4121 148 | end 149 | ) 150 | (memory (;0;) 1) 151 | (global (;0;) (mut i32) i32.const 4096) 152 | (export "memory" (memory 0)) 153 | (export "_start" (func $main)) 154 | (data (;0;) (i32.const 4096) "\0a\00") 155 | (data (;1;) (i32.const 4098) "counting ...\00") 156 | (data (;2;) (i32.const 4111) "done\00") 157 | (data (;3;) (i32.const 4116) "even\00") 158 | (data (;4;) (i32.const 4121) "odd\00") 159 | ) 160 | -------------------------------------------------------------------------------- /examples/out/recurse/recurse.norm.txt: -------------------------------------------------------------------------------- 1 | Block 2 | Def 3 | Pub 4 | Id "main" 5 | None 6 | Fun 7 | Params 8 | Params 9 | Block 10 | Def 11 | Id "i" 12 | None 13 | Int32 3 14 | /Def 15 | Call 16 | Id "countDown" 17 | Id "i" 18 | /Call 19 | Call 20 | Id "print" 21 | Call 22 | Id "oddness" 23 | Id "i" 24 | /Call 25 | /Call 26 | Call 27 | Id "print" 28 | Call 29 | Id "oddness" 30 | Call 31 | Id "add" 32 | Id "i" 33 | Int32 1 34 | /Call 35 | /Call 36 | /Call 37 | /Block 38 | /Fun 39 | /Def 40 | Def 41 | Id "countDown" 42 | None 43 | Fun 44 | Params 45 | Def 46 | Id "count" 47 | Id "Int32" 48 | None 49 | /Def 50 | /Params 51 | Params 52 | Block 53 | Call 54 | Id "print" 55 | String "counting ..." 56 | /Call 57 | Call 58 | Id "branch" 59 | List 60 | Call 61 | Id "Pair" 62 | Call 63 | Id "gt" 64 | Id "count" 65 | Int32 1 66 | /Call 67 | Call 68 | Id "countDown" 69 | Call 70 | Id "sub" 71 | Id "count" 72 | Int32 1 73 | /Call 74 | /Call 75 | /Call 76 | Call 77 | Id "else" 78 | Call 79 | Id "print" 80 | String "done" 81 | /Call 82 | /Call 83 | /List 84 | /Call 85 | /Block 86 | /Fun 87 | /Def 88 | Def 89 | Id "isEven" 90 | None 91 | Fun 92 | Params 93 | Def 94 | Id "i" 95 | Id "Int32" 96 | None 97 | /Def 98 | /Params 99 | Params 100 | Def 101 | None 102 | Id "Claim" 103 | None 104 | /Def 105 | /Params 106 | Call 107 | Id "branch" 108 | List 109 | Call 110 | Id "Pair" 111 | Call 112 | Id "gt" 113 | Id "i" 114 | Int32 0 115 | /Call 116 | Call 117 | Id "isOdd" 118 | Call 119 | Id "sub" 120 | Id "i" 121 | Int32 1 122 | /Call 123 | /Call 124 | /Call 125 | Call 126 | Id "else" 127 | Id "true" 128 | /Call 129 | /List 130 | /Call 131 | /Fun 132 | /Def 133 | Def 134 | Id "isOdd" 135 | None 136 | Fun 137 | Params 138 | Def 139 | Id "i" 140 | Id "Int32" 141 | None 142 | /Def 143 | /Params 144 | Params 145 | Def 146 | None 147 | Id "Claim" 148 | None 149 | /Def 150 | /Params 151 | Call 152 | Id "branch" 153 | List 154 | Call 155 | Id "Pair" 156 | Call 157 | Id "gt" 158 | Id "i" 159 | Int32 0 160 | /Call 161 | Call 162 | Id "isEven" 163 | Call 164 | Id "sub" 165 | Id "i" 166 | Int32 1 167 | /Call 168 | /Call 169 | /Call 170 | Call 171 | Id "else" 172 | Id "false" 173 | /Call 174 | /List 175 | /Call 176 | /Fun 177 | /Def 178 | Def 179 | Id "oddness" 180 | None 181 | Fun 182 | Params 183 | Def 184 | Id "i" 185 | Id "Int32" 186 | None 187 | /Def 188 | /Params 189 | Params 190 | Call 191 | Id "branch" 192 | List 193 | Call 194 | Id "Pair" 195 | Call 196 | Id "isEven" 197 | Id "i" 198 | /Call 199 | String "even" 200 | /Call 201 | Call 202 | Id "else" 203 | String "odd" 204 | /Call 205 | /List 206 | /Call 207 | /Fun 208 | /Def 209 | /Block 210 | 211 | Node size: 20 212 | Tree len: 149 213 | -------------------------------------------------------------------------------- /examples/out/recurse/recurse.parse.txt: -------------------------------------------------------------------------------- 1 | Block 2 | Def 3 | Pub 4 | Id "main" 5 | Star "*" 6 | /Pub 7 | HSpace " " 8 | Define "=" 9 | HSpace " " 10 | Fun 11 | Fun "for" 12 | Params 13 | RoundOpen "(" 14 | RoundClose ")" 15 | /Params 16 | HSpace " " 17 | Params 18 | Block 19 | Be "be" 20 | VSpace "\n" 21 | HSpace " " 22 | Def 23 | Id "i" 24 | HSpace " " 25 | Define "=" 26 | HSpace " " 27 | Int "3" 28 | /Def 29 | VSpace "\n" 30 | HSpace " " 31 | Call 32 | Id "countDown" 33 | RoundOpen "(" 34 | Id "i" 35 | RoundClose ")" 36 | /Call 37 | VSpace "\n" 38 | HSpace " " 39 | Call 40 | Id "print" 41 | HSpace " " 42 | Call 43 | Id "oddness" 44 | RoundOpen "(" 45 | Id "i" 46 | RoundClose ")" 47 | /Call 48 | /Call 49 | VSpace "\n" 50 | HSpace " " 51 | Call 52 | Id "print" 53 | HSpace " " 54 | Call 55 | Id "oddness" 56 | RoundOpen "(" 57 | Infix 58 | Id "i" 59 | HSpace " " 60 | Plus "+" 61 | HSpace " " 62 | Int "1" 63 | /Infix 64 | RoundClose ")" 65 | /Call 66 | /Call 67 | VSpace "\n" 68 | End "end" 69 | /Block 70 | /Fun 71 | /Def 72 | VSpace "\n" 73 | VSpace "\n" 74 | Def 75 | Id "countDown" 76 | HSpace " " 77 | Define "=" 78 | HSpace " " 79 | Fun 80 | Fun "for" 81 | Params 82 | RoundOpen "(" 83 | Typed 84 | Id "count" 85 | Colon ":" 86 | HSpace " " 87 | Id "Int32" 88 | /Typed 89 | RoundClose ")" 90 | /Params 91 | HSpace " " 92 | Params 93 | Block 94 | Be "be" 95 | VSpace "\n" 96 | HSpace " " 97 | Call 98 | Id "print" 99 | HSpace " " 100 | StringParts 101 | StringEdge "\"" 102 | String "counting ..." 103 | StringEdge "\"" 104 | /StringParts 105 | /Call 106 | VSpace "\n" 107 | HSpace " " 108 | Call 109 | Id "branch" 110 | HSpace " " 111 | Block 112 | With "with" 113 | VSpace "\n" 114 | HSpace " " 115 | Infix 116 | Infix 117 | Id "count" 118 | HSpace " " 119 | AngleClose ">" 120 | HSpace " " 121 | Int "1" 122 | HSpace " " 123 | /Infix 124 | To "to" 125 | HSpace " " 126 | Call 127 | Id "countDown" 128 | RoundOpen "(" 129 | Infix 130 | Id "count" 131 | HSpace " " 132 | Minus "-" 133 | HSpace " " 134 | Int "1" 135 | /Infix 136 | RoundClose ")" 137 | /Call 138 | /Infix 139 | VSpace "\n" 140 | HSpace " " 141 | Call 142 | Id "else" 143 | HSpace " " 144 | Block 145 | Be "be" 146 | HSpace " " 147 | Call 148 | Id "print" 149 | HSpace " " 150 | StringParts 151 | StringEdge "\"" 152 | String "done" 153 | StringEdge "\"" 154 | /StringParts 155 | /Call 156 | /Block 157 | /Call 158 | VSpace "\n" 159 | HSpace " " 160 | End "end" 161 | /Block 162 | /Call 163 | VSpace "\n" 164 | End "end" 165 | /Block 166 | /Fun 167 | /Def 168 | VSpace "\n" 169 | VSpace "\n" 170 | Def 171 | Id "isEven" 172 | HSpace " " 173 | Define "=" 174 | HSpace " " 175 | Fun 176 | Fun "for" 177 | Params 178 | RoundOpen "(" 179 | Typed 180 | Id "i" 181 | Colon ":" 182 | HSpace " " 183 | Id "Int32" 184 | /Typed 185 | RoundClose ")" 186 | /Params 187 | Colon ":" 188 | HSpace " " 189 | Params 190 | Typed 191 | None 192 | Id "Claim" 193 | HSpace " " 194 | /Typed 195 | /Params 196 | Block 197 | Be "be" 198 | HSpace " " 199 | Call 200 | Id "branch" 201 | HSpace " " 202 | Block 203 | With "with" 204 | VSpace "\n" 205 | HSpace " " 206 | Infix 207 | Infix 208 | Id "i" 209 | HSpace " " 210 | AngleClose ">" 211 | HSpace " " 212 | Int "0" 213 | HSpace " " 214 | /Infix 215 | To "to" 216 | HSpace " " 217 | Call 218 | Id "isOdd" 219 | RoundOpen "(" 220 | Infix 221 | Id "i" 222 | HSpace " " 223 | Minus "-" 224 | HSpace " " 225 | Int "1" 226 | /Infix 227 | RoundClose ")" 228 | /Call 229 | /Infix 230 | VSpace "\n" 231 | HSpace " " 232 | Call 233 | Id "else" 234 | HSpace " " 235 | Id "true" 236 | /Call 237 | VSpace "\n" 238 | End "end" 239 | /Block 240 | /Call 241 | /Block 242 | /Fun 243 | /Def 244 | VSpace "\n" 245 | VSpace "\n" 246 | Def 247 | Id "isOdd" 248 | HSpace " " 249 | Define "=" 250 | HSpace " " 251 | Fun 252 | Fun "for" 253 | Params 254 | RoundOpen "(" 255 | Typed 256 | Id "i" 257 | Colon ":" 258 | HSpace " " 259 | Id "Int32" 260 | /Typed 261 | RoundClose ")" 262 | /Params 263 | Colon ":" 264 | HSpace " " 265 | Params 266 | Typed 267 | None 268 | Id "Claim" 269 | HSpace " " 270 | /Typed 271 | /Params 272 | Block 273 | Be "be" 274 | HSpace " " 275 | Call 276 | Id "branch" 277 | HSpace " " 278 | Block 279 | With "with" 280 | VSpace "\n" 281 | HSpace " " 282 | Infix 283 | Infix 284 | Id "i" 285 | HSpace " " 286 | AngleClose ">" 287 | HSpace " " 288 | Int "0" 289 | HSpace " " 290 | /Infix 291 | To "to" 292 | HSpace " " 293 | Call 294 | Id "isEven" 295 | RoundOpen "(" 296 | Infix 297 | Id "i" 298 | HSpace " " 299 | Minus "-" 300 | HSpace " " 301 | Int "1" 302 | /Infix 303 | RoundClose ")" 304 | /Call 305 | /Infix 306 | VSpace "\n" 307 | HSpace " " 308 | Call 309 | Id "else" 310 | HSpace " " 311 | Id "false" 312 | /Call 313 | VSpace "\n" 314 | End "end" 315 | /Block 316 | /Call 317 | /Block 318 | /Fun 319 | /Def 320 | VSpace "\n" 321 | VSpace "\n" 322 | Def 323 | Id "oddness" 324 | HSpace " " 325 | Define "=" 326 | HSpace " " 327 | Fun 328 | Fun "for" 329 | Params 330 | RoundOpen "(" 331 | Typed 332 | Id "i" 333 | Colon ":" 334 | HSpace " " 335 | Id "Int32" 336 | /Typed 337 | RoundClose ")" 338 | /Params 339 | HSpace " " 340 | Params 341 | Block 342 | Be "be" 343 | HSpace " " 344 | Call 345 | Id "branch" 346 | HSpace " " 347 | Block 348 | With "with" 349 | VSpace "\n" 350 | HSpace " " 351 | Infix 352 | Call 353 | Id "isEven" 354 | RoundOpen "(" 355 | Id "i" 356 | RoundClose ")" 357 | /Call 358 | HSpace " " 359 | To "to" 360 | HSpace " " 361 | StringParts 362 | StringEdge "\"" 363 | String "even" 364 | StringEdge "\"" 365 | /StringParts 366 | /Infix 367 | VSpace "\n" 368 | HSpace " " 369 | Call 370 | Id "else" 371 | HSpace " " 372 | StringParts 373 | StringEdge "\"" 374 | String "odd" 375 | StringEdge "\"" 376 | /StringParts 377 | /Call 378 | VSpace "\n" 379 | End "end" 380 | /Block 381 | /Call 382 | /Block 383 | /Fun 384 | /Def 385 | VSpace "\n" 386 | /Block 387 | 388 | Node size: 12 389 | Tree len: 316 390 | -------------------------------------------------------------------------------- /examples/out/recurse/recurse.run.txt: -------------------------------------------------------------------------------- 1 | Block 2 | Module "examples/recurse.rio" 2 3 | Def@169 :@167 4 | Uid main@169* :@167 5 | None 6 | Fun :@167 7 | Params 8 | Params 9 | Block :@156 10 | Def@17 :@155 11 | Uid i@17 :@155 12 | None 13 | Int32 3 :@155 14 | /Def 15 | Call 16 | Uid countDown@170 :@164 17 | Uid i@17 :@155 18 | /Call 19 | Call :@156 20 | Uid print@1@662 :@158 21 | Call :@157 22 | Uid oddness@173 :@166 23 | Uid i@17 :@155 24 | /Call 25 | /Call 26 | Call :@156 27 | Uid print@1@662 :@158 28 | Call :@157 29 | Uid oddness@173 :@166 30 | Call :@155 31 | Uid add@1@636 :@159 32 | Uid i@17 :@155 33 | Int32 1 :@155 34 | /Call 35 | /Call 36 | /Call 37 | /Block 38 | /Fun 39 | /Def 40 | Def@170 :@164 41 | Uid countDown@170 :@164 42 | None 43 | Fun :@164 44 | Params 45 | Def@30 :@155 46 | Uid count@30 :@155 47 | Uid Int32@1@635 48 | None :@155 49 | /Def 50 | /Params 51 | Params 52 | Block 53 | Call :@156 54 | Uid print@1@662 :@158 55 | String "counting ..." :@157 56 | /Call 57 | Call 58 | Uid branch@1@653 59 | List 60 | Call 61 | Uid Pair@1@648 :@161 62 | Call :@162 63 | Uid gt@1@639 :@163 64 | Uid count@30 :@155 65 | Int32 1 :@155 66 | /Call 67 | Call 68 | Uid countDown@170 :@164 69 | Call :@155 70 | Uid sub@1@643 :@159 71 | Uid count@30 :@155 72 | Int32 1 :@155 73 | /Call 74 | /Call 75 | /Call 76 | Call 77 | Uid else@1@656 78 | Call :@156 79 | Uid print@1@662 :@158 80 | String "done" :@157 81 | /Call 82 | /Call 83 | /List 84 | /Call 85 | /Block 86 | /Fun 87 | /Def 88 | Def@171 :@165 89 | Uid isEven@171 :@165 90 | None 91 | Fun :@165 92 | Params 93 | Def@63 :@155 94 | Uid i@63 :@155 95 | Uid Int32@1@635 96 | None :@155 97 | /Def 98 | /Params 99 | Params 100 | Def@67 :@162 101 | None :@162 102 | Uid Claim@1@632 103 | None :@162 104 | /Def 105 | /Params 106 | Call :@162 107 | Uid branch@1@653 108 | List 109 | Call 110 | Uid Pair@1@648 :@161 111 | Call :@162 112 | Uid gt@1@639 :@163 113 | Uid i@63 :@155 114 | Int32 0 :@155 115 | /Call 116 | Call :@162 117 | Uid isOdd@172 :@165 118 | Call :@155 119 | Uid sub@1@643 :@159 120 | Uid i@63 :@155 121 | Int32 1 :@155 122 | /Call 123 | /Call 124 | /Call 125 | Call 126 | Uid else@1@656 127 | Uid true@1@664 :@162 128 | /Call 129 | /List 130 | /Call 131 | /Fun 132 | /Def 133 | Def@172 :@165 134 | Uid isOdd@172 :@165 135 | None 136 | Fun :@165 137 | Params 138 | Def@94 :@155 139 | Uid i@94 :@155 140 | Uid Int32@1@635 141 | None :@155 142 | /Def 143 | /Params 144 | Params 145 | Def@98 :@162 146 | None :@162 147 | Uid Claim@1@632 148 | None :@162 149 | /Def 150 | /Params 151 | Call :@162 152 | Uid branch@1@653 153 | List 154 | Call 155 | Uid Pair@1@648 :@161 156 | Call :@162 157 | Uid gt@1@639 :@163 158 | Uid i@94 :@155 159 | Int32 0 :@155 160 | /Call 161 | Call :@162 162 | Uid isEven@171 :@165 163 | Call :@155 164 | Uid sub@1@643 :@159 165 | Uid i@94 :@155 166 | Int32 1 :@155 167 | /Call 168 | /Call 169 | /Call 170 | Call 171 | Uid else@1@656 172 | Uid false@1@658 :@162 173 | /Call 174 | /List 175 | /Call 176 | /Fun 177 | /Def 178 | Def@173 :@166 179 | Uid oddness@173 :@166 180 | None 181 | Fun :@166 182 | Params 183 | Def@125 :@155 184 | Uid i@125 :@155 185 | Uid Int32@1@635 186 | None :@155 187 | /Def 188 | /Params 189 | Params 190 | Call :@157 191 | Uid branch@1@653 192 | List 193 | Call 194 | Uid Pair@1@648 :@161 195 | Call :@162 196 | Uid isEven@171 :@165 197 | Uid i@125 :@155 198 | /Call 199 | String "even" :@157 200 | /Call 201 | Call 202 | Uid else@1@656 203 | String "odd" :@157 204 | /Call 205 | /List 206 | /Call 207 | /Fun 208 | /Def 209 | Types 210 | Uid@155 Int32@1@635 211 | Uid@156 Void@1@651 212 | Uid@157 Text@1@649 213 | FunType@158 :@156 214 | None :@157 215 | FunType@159 :@155 216 | None :@155 217 | None :@155 218 | /FunType 219 | FunType@160 220 | FunType@161 221 | None 222 | None 223 | None 224 | None 225 | /FunType 226 | Uid@162 Claim@1@632 227 | FunType@163 :@162 228 | None :@155 229 | None :@155 230 | /FunType 231 | FunType@164 232 | None :@155 233 | FunType@165 :@162 234 | None :@155 235 | FunType@166 :@157 236 | None :@155 237 | FunType@167 :@156 238 | /Types 239 | /Block 240 | 241 | Node size: 20 242 | Tree len: 175 243 | -------------------------------------------------------------------------------- /examples/out/struct.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (type (;0;) (func (param i32 i32 i32 i32) (result i32))) 3 | (type (;1;) (func (param i32) (result i32 i32))) 4 | (type (;2;) (func (param i32))) 5 | (type (;3;) (func (param i32 i32))) 6 | (type (;4;) (func (param i32) (result i32))) 7 | (type (;5;) (func (param i32 i32 i32) (result i32 i32 i32))) 8 | (type (;6;) (func (param i32 i32) (result i32 i32))) 9 | (type (;7;) (func (result i32 i32))) 10 | (type (;8;) (func (result i32))) 11 | (type (;9;) (func)) 12 | (type (;10;) (func (param i32))) 13 | (type (;11;) (func (param i32 i32 i32 i32))) 14 | (type (;12;) (func (param i32 i32))) 15 | (type (;13;) (func (param i32 i32) (result i32))) 16 | (import "wasi_snapshot_preview1" "fd_write" (func (;0;) (type 0))) 17 | (func $-i32.dup (;1;) (type 1) (param i32) (result i32 i32) 18 | local.get 0 19 | local.get 0 20 | ) 21 | (func $core::print (;2;) (type 3) (param i32 i32) 22 | local.get 0 23 | local.get 1 24 | call $-printInline 25 | i32.const 1 26 | i32.const 4096 27 | call $-printInline 28 | ) 29 | (func $-printInline (;3;) (type 3) (param i32 i32) 30 | (local i32 i32) 31 | i32.const 8 32 | call $-push 33 | local.set 2 34 | i32.const 4 35 | call $-push 36 | local.set 3 37 | local.get 2 38 | local.get 1 39 | i32.store align=1 40 | local.get 2 41 | i32.const 4 42 | i32.add 43 | local.get 0 44 | i32.store 45 | i32.const 1 46 | local.get 2 47 | i32.const 1 48 | local.get 3 49 | call 0 50 | drop 51 | i32.const 12 52 | call $-pop 53 | ) 54 | (func $-pop (;4;) (type 2) (param i32) 55 | global.get 0 56 | local.get 0 57 | i32.add 58 | global.set 0 59 | ) 60 | (func $-push (;5;) (type 4) (param i32) (result i32) 61 | (local i32) 62 | global.get 0 63 | local.get 0 64 | i32.sub 65 | local.tee 1 66 | global.set 0 67 | local.get 1 68 | ) 69 | (func $-rot3 (;6;) (type 5) (param i32 i32 i32) (result i32 i32 i32) 70 | local.get 2 71 | local.get 0 72 | local.get 1 73 | ) 74 | (func $-swap (;7;) (type 6) (param i32 i32) (result i32 i32) 75 | local.get 1 76 | local.get 0 77 | ) 78 | (func $main (;8;) (type 9) 79 | (local i32 i32 i32) 80 | i32.const 5 81 | i32.const 4098 82 | local.set 1 83 | local.set 0 84 | i32.const 12 85 | call $-push 86 | call $-i32.dup 87 | call $-i32.dup 88 | local.get 0 89 | local.get 1 90 | call $-rot3 91 | i32.store 92 | i32.store offset=4 93 | call $-i32.dup 94 | i32.const 40 95 | i32.store offset=8 96 | local.set 2 97 | local.get 2 98 | call $describe 99 | i32.const 12 100 | call $-push 101 | call $-i32.dup 102 | local.get 2 103 | i32.const 8 104 | i32.add 105 | i32.load 106 | i32.store offset=8 107 | call $-i32.dup 108 | call $-i32.dup 109 | i32.const 3 110 | i32.const 4104 111 | call $-rot3 112 | i32.store 113 | i32.store offset=4 114 | call $describe 115 | i32.const 12 116 | call $-pop 117 | i32.const 12 118 | call $-push 119 | call $-i32.dup 120 | i32.const 4 121 | i32.const 4108 122 | i32.const 10 123 | call $build 124 | call $describe 125 | i32.const 12 126 | call $-pop 127 | i32.const 12 128 | call $-push 129 | call $-i32.dup 130 | i32.const 9 131 | i32.store offset=8 132 | call $-i32.dup 133 | call $-i32.dup 134 | i32.const 6 135 | i32.const 4113 136 | call $-rot3 137 | i32.store 138 | i32.store offset=4 139 | call $describe 140 | i32.const 12 141 | call $-pop 142 | i32.const 12 143 | call $-pop 144 | ) 145 | (func $build (;9;) (type 11) (param i32 i32 i32 i32) 146 | i32.const 12 147 | call $-push 148 | call $-i32.dup 149 | call $-i32.dup 150 | local.get 1 151 | local.get 2 152 | call $-rot3 153 | i32.store 154 | i32.store offset=4 155 | call $-i32.dup 156 | local.get 3 157 | i32.store offset=8 158 | local.get 0 159 | call $-swap 160 | i32.const 12 161 | memory.copy 162 | i32.const 12 163 | call $-pop 164 | ) 165 | (func $describe (;10;) (type 10) (param i32) 166 | i32.const 7 167 | i32.const 4120 168 | call $core::print 169 | local.get 0 170 | call $-i32.dup 171 | i32.load 172 | call $-swap 173 | i32.load offset=4 174 | call $core::print 175 | local.get 0 176 | i32.const 8 177 | i32.add 178 | i32.load 179 | i32.const 18 180 | i32.ge_s 181 | if (type 7) (result i32 i32) ;; label = @1 182 | i32.const 5 183 | i32.const 4128 184 | else 185 | i32.const 5 186 | i32.const 4134 187 | end 188 | call $core::print 189 | i32.const 0 190 | i32.const 4140 191 | call $core::print 192 | ) 193 | (memory (;0;) 1) 194 | (global (;0;) (mut i32) i32.const 4096) 195 | (export "memory" (memory 0)) 196 | (export "_start" (func $main)) 197 | (data (;0;) (i32.const 4096) "\0a\00") 198 | (data (;1;) (i32.const 4098) "Alice\00") 199 | (data (;2;) (i32.const 4104) "Bob\00") 200 | (data (;3;) (i32.const 4108) "Carl\00") 201 | (data (;4;) (i32.const 4113) "Denise\00") 202 | (data (;5;) (i32.const 4120) "Person:\00") 203 | (data (;6;) (i32.const 4128) "adult\00") 204 | (data (;7;) (i32.const 4134) "minor\00") 205 | (data (;8;) (i32.const 4140) "\00") 206 | ) 207 | -------------------------------------------------------------------------------- /examples/out/struct/struct.norm.txt: -------------------------------------------------------------------------------- 1 | Block 2 | Def 3 | Pub 4 | Id "main" 5 | None 6 | Fun 7 | Params 8 | Params 9 | Block 10 | Def 11 | Id "name" 12 | None 13 | String "Alice" 14 | /Def 15 | Def 16 | Id "alice" 17 | None 18 | Call 19 | Id "Person" 20 | Struct 21 | Def 22 | Id "name" 23 | None 24 | Id "name" 25 | /Def 26 | Def 27 | Id "age" 28 | None 29 | Int32 40 30 | /Def 31 | /Struct 32 | /Call 33 | /Def 34 | Call 35 | Id "describe" 36 | Id "alice" 37 | /Call 38 | Call 39 | Id "describe" 40 | Struct 41 | Def 42 | Id "age" 43 | None 44 | Dot 45 | Id "alice" 46 | Id "age" 47 | /Dot 48 | /Def 49 | Def 50 | Id "name" 51 | None 52 | String "Bob" 53 | /Def 54 | /Struct 55 | /Call 56 | Call 57 | Id "describe" 58 | Call 59 | Id "build" 60 | String "Carl" 61 | Int32 10 62 | /Call 63 | /Call 64 | Call 65 | Id "describe" 66 | Struct 67 | Def 68 | Id "age" 69 | None 70 | Int32 9 71 | /Def 72 | Def 73 | Id "name" 74 | None 75 | String "Denise" 76 | /Def 77 | /Struct 78 | /Call 79 | /Block 80 | /Fun 81 | /Def 82 | Def 83 | Id "Person" 84 | None 85 | Call 86 | Id "struct" 87 | Struct 88 | Def 89 | Id "name" 90 | Id "Text" 91 | None 92 | /Def 93 | Def 94 | Id "age" 95 | Id "Int32" 96 | None 97 | /Def 98 | /Struct 99 | /Call 100 | /Def 101 | Def 102 | Id "build" 103 | None 104 | Fun 105 | Params 106 | Def 107 | Id "name" 108 | Id "Text" 109 | None 110 | /Def 111 | Def 112 | Id "age" 113 | Id "Int32" 114 | None 115 | /Def 116 | /Params 117 | Params 118 | Def 119 | None 120 | Id "Person" 121 | None 122 | /Def 123 | /Params 124 | Struct 125 | Def 126 | Id "name" 127 | None 128 | Id "name" 129 | /Def 130 | Def 131 | Id "age" 132 | None 133 | Id "age" 134 | /Def 135 | /Struct 136 | /Fun 137 | /Def 138 | Def 139 | Id "describe" 140 | None 141 | Fun 142 | Params 143 | Def 144 | Id "person" 145 | Id "Person" 146 | None 147 | /Def 148 | /Params 149 | Params 150 | Block 151 | Call 152 | Id "print" 153 | String "Person:" 154 | /Call 155 | Call 156 | Id "print" 157 | Dot 158 | Id "person" 159 | Id "name" 160 | /Dot 161 | /Call 162 | Call 163 | Id "print" 164 | Call 165 | Id "branch" 166 | List 167 | Call 168 | Id "Pair" 169 | Call 170 | Id "ge" 171 | Dot 172 | Id "person" 173 | Id "age" 174 | /Dot 175 | Int32 18 176 | /Call 177 | String "adult" 178 | /Call 179 | Call 180 | Id "else" 181 | String "minor" 182 | /Call 183 | /List 184 | /Call 185 | /Call 186 | Call 187 | Id "print" 188 | String "" 189 | /Call 190 | /Block 191 | /Fun 192 | /Def 193 | /Block 194 | 195 | Node size: 20 196 | Tree len: 140 197 | -------------------------------------------------------------------------------- /examples/out/struct/struct.parse.txt: -------------------------------------------------------------------------------- 1 | Block 2 | Def 3 | Pub 4 | Id "main" 5 | Star "*" 6 | /Pub 7 | HSpace " " 8 | Define "=" 9 | HSpace " " 10 | Fun 11 | Fun "for" 12 | Params 13 | RoundOpen "(" 14 | RoundClose ")" 15 | /Params 16 | HSpace " " 17 | Params 18 | Block 19 | Be "be" 20 | VSpace "\n" 21 | HSpace " " 22 | Def 23 | Id "name" 24 | HSpace " " 25 | Define "=" 26 | HSpace " " 27 | StringParts 28 | StringEdge "\"" 29 | String "Alice" 30 | StringEdge "\"" 31 | /StringParts 32 | /Def 33 | VSpace "\n" 34 | HSpace " " 35 | Def 36 | Id "alice" 37 | HSpace " " 38 | Define "=" 39 | HSpace " " 40 | Call 41 | Id "Person" 42 | Block 43 | CurlyOpen "{" 44 | Id "name" 45 | Comma "," 46 | HSpace " " 47 | Def 48 | Id "age" 49 | HSpace " " 50 | Define "=" 51 | HSpace " " 52 | Int "40" 53 | /Def 54 | CurlyClose "}" 55 | /Block 56 | /Call 57 | /Def 58 | VSpace "\n" 59 | HSpace " " 60 | Call 61 | Id "describe" 62 | RoundOpen "(" 63 | Id "alice" 64 | RoundClose ")" 65 | /Call 66 | VSpace "\n" 67 | HSpace " " 68 | Call 69 | Id "describe" 70 | Block 71 | CurlyOpen "{" 72 | Infix 73 | Id "alice" 74 | Dot "." 75 | Id "age" 76 | /Infix 77 | Comma "," 78 | HSpace " " 79 | Def 80 | Id "name" 81 | HSpace " " 82 | Define "=" 83 | HSpace " " 84 | StringParts 85 | StringEdge "\"" 86 | String "Bob" 87 | StringEdge "\"" 88 | /StringParts 89 | /Def 90 | CurlyClose "}" 91 | /Block 92 | /Call 93 | VSpace "\n" 94 | HSpace " " 95 | Call 96 | Id "describe" 97 | HSpace " " 98 | Call 99 | Id "build" 100 | RoundOpen "(" 101 | StringParts 102 | StringEdge "\"" 103 | String "Carl" 104 | StringEdge "\"" 105 | /StringParts 106 | Comma "," 107 | HSpace " " 108 | Int "10" 109 | RoundClose ")" 110 | /Call 111 | /Call 112 | VSpace "\n" 113 | HSpace " " 114 | Call 115 | Id "describe" 116 | HSpace " " 117 | Block 118 | Of "of" 119 | VSpace "\n" 120 | HSpace " " 121 | Def 122 | Id "age" 123 | HSpace " " 124 | Define "=" 125 | HSpace " " 126 | Int "9" 127 | /Def 128 | VSpace "\n" 129 | HSpace " " 130 | Def 131 | Id "name" 132 | HSpace " " 133 | Define "=" 134 | HSpace " " 135 | StringParts 136 | StringEdge "\"" 137 | String "Denise" 138 | StringEdge "\"" 139 | /StringParts 140 | /Def 141 | VSpace "\n" 142 | HSpace " " 143 | End "end" 144 | /Block 145 | /Call 146 | VSpace "\n" 147 | End "end" 148 | /Block 149 | /Fun 150 | /Def 151 | VSpace "\n" 152 | VSpace "\n" 153 | Def 154 | Id "Person" 155 | HSpace " " 156 | Define "=" 157 | HSpace " " 158 | Call 159 | Id "struct" 160 | HSpace " " 161 | Block 162 | Of "of" 163 | VSpace "\n" 164 | HSpace " " 165 | Typed 166 | Id "name" 167 | Colon ":" 168 | HSpace " " 169 | Id "Text" 170 | /Typed 171 | VSpace "\n" 172 | HSpace " " 173 | Typed 174 | Id "age" 175 | Colon ":" 176 | HSpace " " 177 | Id "Int32" 178 | /Typed 179 | VSpace "\n" 180 | End "end" 181 | /Block 182 | /Call 183 | /Def 184 | VSpace "\n" 185 | VSpace "\n" 186 | Def 187 | Id "build" 188 | HSpace " " 189 | Define "=" 190 | HSpace " " 191 | Fun 192 | Fun "for" 193 | Params 194 | RoundOpen "(" 195 | Typed 196 | Id "name" 197 | Colon ":" 198 | HSpace " " 199 | Id "Text" 200 | /Typed 201 | Comma "," 202 | HSpace " " 203 | Typed 204 | Id "age" 205 | Colon ":" 206 | HSpace " " 207 | Id "Int32" 208 | /Typed 209 | RoundClose ")" 210 | /Params 211 | Colon ":" 212 | HSpace " " 213 | Params 214 | Typed 215 | None 216 | Id "Person" 217 | HSpace " " 218 | /Typed 219 | /Params 220 | Block 221 | Be "be" 222 | HSpace " " 223 | Block 224 | CurlyOpen "{" 225 | Id "name" 226 | Comma "," 227 | HSpace " " 228 | Id "age" 229 | CurlyClose "}" 230 | /Block 231 | /Block 232 | /Fun 233 | /Def 234 | VSpace "\n" 235 | VSpace "\n" 236 | Def 237 | Id "describe" 238 | HSpace " " 239 | Define "=" 240 | HSpace " " 241 | Fun 242 | Fun "for" 243 | Params 244 | RoundOpen "(" 245 | Typed 246 | Id "person" 247 | Colon ":" 248 | HSpace " " 249 | Id "Person" 250 | /Typed 251 | RoundClose ")" 252 | /Params 253 | HSpace " " 254 | Params 255 | Block 256 | Be "be" 257 | VSpace "\n" 258 | HSpace " " 259 | Comment "# TODO Text interp and auto struct printing." 260 | VSpace "\n" 261 | HSpace " " 262 | Call 263 | Id "print" 264 | HSpace " " 265 | StringParts 266 | StringEdge "\"" 267 | String "Person:" 268 | StringEdge "\"" 269 | /StringParts 270 | /Call 271 | VSpace "\n" 272 | HSpace " " 273 | Call 274 | Id "print" 275 | HSpace " " 276 | Infix 277 | Id "person" 278 | Dot "." 279 | Id "name" 280 | /Infix 281 | /Call 282 | VSpace "\n" 283 | HSpace " " 284 | Call 285 | Id "print" 286 | HSpace " " 287 | Block 288 | Be "be" 289 | HSpace " " 290 | Call 291 | Id "branch" 292 | HSpace " " 293 | Block 294 | With "with" 295 | VSpace "\n" 296 | HSpace " " 297 | Infix 298 | Infix 299 | Infix 300 | Id "person" 301 | Dot "." 302 | Id "age" 303 | /Infix 304 | HSpace " " 305 | GreaterEq ">=" 306 | HSpace " " 307 | Int "18" 308 | HSpace " " 309 | /Infix 310 | To "to" 311 | HSpace " " 312 | StringParts 313 | StringEdge "\"" 314 | String "adult" 315 | StringEdge "\"" 316 | /StringParts 317 | /Infix 318 | VSpace "\n" 319 | HSpace " " 320 | Call 321 | Id "else" 322 | HSpace " " 323 | StringParts 324 | StringEdge "\"" 325 | String "minor" 326 | StringEdge "\"" 327 | /StringParts 328 | /Call 329 | VSpace "\n" 330 | HSpace " " 331 | End "end" 332 | /Block 333 | /Call 334 | /Block 335 | /Call 336 | VSpace "\n" 337 | HSpace " " 338 | Call 339 | Id "print" 340 | HSpace " " 341 | StringParts 342 | StringEdge "\"" 343 | StringEdge "\"" 344 | /StringParts 345 | /Call 346 | VSpace "\n" 347 | End "end" 348 | /Block 349 | /Fun 350 | /Def 351 | VSpace "\n" 352 | /Block 353 | 354 | Node size: 12 355 | Tree len: 291 356 | -------------------------------------------------------------------------------- /examples/out/struct/struct.run.txt: -------------------------------------------------------------------------------- 1 | Block 2 | Module "examples/struct.rio" 2 3 | Def@160 :@158 4 | Uid main@160* :@158 5 | None 6 | Fun :@158 7 | Params 8 | Params 9 | Block :@151 10 | Def@44 :@144 11 | Uid name@44 :@144 12 | None 13 | String "Alice" :@144 14 | /Def 15 | Def@45 :@149 16 | Uid alice@45 :@149 17 | None 18 | Struct :@149 19 | Field :@144 20 | Sid name@0 :@144 21 | None 22 | Uid name@44 :@144 23 | /Field 24 | Field :@145 25 | Sid age@1 :@145 26 | None 27 | Int32 40 :@145 28 | /Field 29 | /Struct 30 | /Def 31 | Call :@151 32 | Uid describe@163 :@157 33 | Uid alice@45 :@149 34 | /Call 35 | Call :@151 36 | Uid describe@163 :@157 37 | Struct :@149 38 | Field :@145 39 | Sid age@1 :@145 40 | None 41 | Dot :@145 42 | Uid alice@45 :@149 43 | Sid age@1 :@145 44 | /Dot 45 | /Field 46 | Field :@144 47 | Sid name@0 :@144 48 | None 49 | String "Bob" :@144 50 | /Field 51 | /Struct 52 | /Call 53 | Call :@151 54 | Uid describe@163 :@157 55 | Call :@149 56 | Uid build@162 :@150 57 | String "Carl" :@144 58 | Int32 10 :@145 59 | /Call 60 | /Call 61 | Call :@151 62 | Uid describe@163 :@157 63 | Struct :@149 64 | Field :@145 65 | Sid age@1 :@145 66 | None 67 | Int32 9 :@145 68 | /Field 69 | Field :@144 70 | Sid name@0 :@144 71 | None 72 | String "Denise" :@144 73 | /Field 74 | /Struct 75 | /Call 76 | /Block 77 | /Fun 78 | /Def 79 | Def@161 :@147 80 | Uid Person@161 :@147 81 | None 82 | Call :@147 83 | Uid struct@1@663 :@148 84 | StructDef 85 | Def@62 :@144 86 | Uid name@62 :@144 87 | Uid Text@1@649 :@147 88 | None :@144 89 | /Def 90 | Def@63 :@145 91 | Uid age@63 :@145 92 | Uid Int32@1@635 93 | None :@145 94 | /Def 95 | /StructDef 96 | /Call 97 | /Def 98 | Def@162 :@150 99 | Uid build@162 :@150 100 | None 101 | Fun :@150 102 | Params 103 | Def@75 :@144 104 | Uid name@75 :@144 105 | Uid Text@1@649 :@147 106 | None :@144 107 | /Def 108 | Def@76 :@145 109 | Uid age@76 :@145 110 | Uid Int32@1@635 111 | None :@145 112 | /Def 113 | /Params 114 | Params 115 | Def@80 :@149 116 | None :@149 117 | Uid Person@161 :@147 118 | None :@149 119 | /Def 120 | /Params 121 | Struct :@149 122 | Field :@144 123 | Sid name@0 :@144 124 | None 125 | Uid name@75 :@144 126 | /Field 127 | Field :@145 128 | Sid age@1 :@145 129 | None 130 | Uid age@76 :@145 131 | /Field 132 | /Struct 133 | /Fun 134 | /Def 135 | Def@163 :@157 136 | Uid describe@163 :@157 137 | None 138 | Fun :@157 139 | Params 140 | Def@98 :@149 141 | Uid person@98 :@149 142 | Uid Person@161 :@147 143 | None :@149 144 | /Def 145 | /Params 146 | Params 147 | Block :@151 148 | Call :@151 149 | Uid print@1@662 :@152 150 | String "Person:" :@144 151 | /Call 152 | Call :@151 153 | Uid print@1@662 :@152 154 | Dot :@144 155 | Uid person@98 :@149 156 | Sid name@0 :@144 157 | /Dot 158 | /Call 159 | Call :@151 160 | Uid print@1@662 :@152 161 | Call :@144 162 | Uid branch@1@653 163 | List 164 | Call 165 | Uid Pair@1@648 :@153 166 | Call :@154 167 | Uid ge@1@638 :@155 168 | Dot :@145 169 | Uid person@98 :@149 170 | Sid age@1 :@145 171 | /Dot 172 | Int32 18 :@145 173 | /Call 174 | String "adult" :@144 175 | /Call 176 | Call 177 | Uid else@1@656 178 | String "minor" :@144 179 | /Call 180 | /List 181 | /Call 182 | /Call 183 | Call :@151 184 | Uid print@1@662 :@152 185 | String "" :@144 186 | /Call 187 | /Block 188 | /Fun 189 | /Def 190 | Types 191 | Uid@144 Text@1@649 192 | Uid@145 Int32@1@635 193 | FunType@146 194 | Uid@147 Type@1@650 195 | FunType@148 :@147 196 | Uid@149 Person@161 197 | FunType@150 :@149 198 | None :@144 199 | None :@145 200 | /FunType 201 | Uid@151 Void@1@651 202 | FunType@152 :@151 203 | None :@144 204 | FunType@153 205 | None 206 | None 207 | None 208 | None 209 | /FunType 210 | Uid@154 Claim@1@632 211 | FunType@155 :@154 212 | None :@145 213 | None :@145 214 | /FunType 215 | FunType@156 216 | None :@149 217 | FunType@157 :@151 218 | None :@149 219 | FunType@158 :@151 220 | /Types 221 | /Block 222 | 223 | Node size: 20 224 | Tree len: 165 225 | -------------------------------------------------------------------------------- /examples/out/wild.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (type (;0;) (func (param i32 i32 i32 i32) (result i32))) 3 | (type (;1;) (func (param i32) (result i32 i32))) 4 | (type (;2;) (func (param i32))) 5 | (type (;3;) (func (param i32 i32))) 6 | (type (;4;) (func (param i32) (result i32))) 7 | (type (;5;) (func (param i32 i32 i32) (result i32 i32 i32))) 8 | (type (;6;) (func (param i32 i32) (result i32 i32))) 9 | (type (;7;) (func (result i32))) 10 | (type (;8;) (func (param i32))) 11 | (type (;9;) (func)) 12 | (type (;10;) (func (result i32 i32))) 13 | (type (;11;) (func (param i32 i32))) 14 | (type (;12;) (func (param i32 i32 i32 i32))) 15 | (type (;13;) (func (param i32 i32) (result i32))) 16 | (import "wasi_snapshot_preview1" "fd_write" (func (;0;) (type 0))) 17 | (func $-i32.dup (;1;) (type 1) (param i32) (result i32 i32) 18 | local.get 0 19 | local.get 0 20 | ) 21 | (func $core::print (;2;) (type 3) (param i32 i32) 22 | local.get 0 23 | local.get 1 24 | call $-printInline 25 | i32.const 1 26 | i32.const 4096 27 | call $-printInline 28 | ) 29 | (func $-printInline (;3;) (type 3) (param i32 i32) 30 | (local i32 i32) 31 | i32.const 8 32 | call $-push 33 | local.set 2 34 | i32.const 4 35 | call $-push 36 | local.set 3 37 | local.get 2 38 | local.get 1 39 | i32.store align=1 40 | local.get 2 41 | i32.const 4 42 | i32.add 43 | local.get 0 44 | i32.store 45 | i32.const 1 46 | local.get 2 47 | i32.const 1 48 | local.get 3 49 | call 0 50 | drop 51 | i32.const 12 52 | call $-pop 53 | ) 54 | (func $-pop (;4;) (type 2) (param i32) 55 | global.get 0 56 | local.get 0 57 | i32.add 58 | global.set 0 59 | ) 60 | (func $-push (;5;) (type 4) (param i32) (result i32) 61 | (local i32) 62 | global.get 0 63 | local.get 0 64 | i32.sub 65 | local.tee 1 66 | global.set 0 67 | local.get 1 68 | ) 69 | (func $-rot3 (;6;) (type 5) (param i32 i32 i32) (result i32 i32 i32) 70 | local.get 2 71 | local.get 0 72 | local.get 1 73 | ) 74 | (func $-swap (;7;) (type 6) (param i32 i32) (result i32 i32) 75 | local.get 1 76 | local.get 0 77 | ) 78 | (func (;8;) (type 8) (param i32)) 79 | (func (;9;) (type 9)) 80 | (func (;10;) (type 9)) 81 | (func (;11;) (type 9)) 82 | (func (;12;) (type 8) (param i32)) 83 | (func (;13;) (type 8) (param i32)) 84 | (func (;14;) (type 8) (param i32)) 85 | (func (;15;) (type 8) (param i32)) 86 | (func (;16;) (type 8) (param i32)) 87 | (memory (;0;) 1) 88 | (global (;0;) (mut i32) i32.const 4096) 89 | (export "memory" (memory 0)) 90 | (data (;0;) (i32.const 4096) "\0a\00") 91 | (data (;1;) (i32.const 4098) "no\00") 92 | (data (;2;) (i32.const 4101) "a single\00") 93 | (data (;3;) (i32.const 4110) "a couple of\00") 94 | (data (;4;) (i32.const 4122) "a few of\00") 95 | (data (;5;) (i32.const 4131) "negative\00") 96 | (data (;6;) (i32.const 4140) "several\00") 97 | ) 98 | -------------------------------------------------------------------------------- /examples/out/wild/wild.norm.txt: -------------------------------------------------------------------------------- 1 | Block 2 | Def 3 | Id "b" 4 | None 5 | Int32 2 6 | /Def 7 | Dot 8 | Id "a" 9 | Id "b" 10 | /Dot 11 | Dot 12 | Id "a" 13 | Call 14 | Id "b" 15 | Id "there" 16 | /Call 17 | /Dot 18 | Call 19 | Call 20 | Id "a" 21 | /Call 22 | Call 23 | Call 24 | Id "a" 25 | Block 26 | /Call 27 | Call 28 | Call 29 | Id "say" 30 | Id "a" 31 | Id "b" 32 | /Call 33 | List 34 | Id "c" 35 | Id "d" 36 | /List 37 | /Call 38 | Call 39 | Call 40 | Id "say" 41 | Id "a" 42 | Id "b" 43 | /Call 44 | List 45 | Id "c" 46 | Id "d" 47 | /List 48 | /Call 49 | Id "e" 50 | Id "f" 51 | List 52 | Id "hi" 53 | Call 54 | Id "blah" 55 | Id "something" 56 | List 57 | Id "a" 58 | Id "b" 59 | /List 60 | Fun 61 | Params 62 | Id "something" 63 | Params 64 | Id "c" 65 | /Fun 66 | /Call 67 | Call 68 | Minus "-" 69 | Int32 5 70 | /Call 71 | Call 72 | Minus "-" 73 | Int32 5 74 | /Call 75 | Fun 76 | Params 77 | Params 78 | /Fun 79 | Fun 80 | Params 81 | Params 82 | /Fun 83 | Fun 84 | Params 85 | Params 86 | /Fun 87 | Int32 5 88 | Call 89 | Int32 5 90 | Fun 91 | Params 92 | Struct 93 | Def 94 | Id "a" 95 | Id "A" 96 | Int32 1 97 | /Def 98 | Def 99 | Id "b" 100 | Id "B" 101 | None 102 | /Def 103 | /Struct 104 | /Params 105 | Params 106 | Def 107 | None 108 | Id "C" 109 | None 110 | /Def 111 | /Params 112 | Id "a" 113 | /Fun 114 | Fun 115 | Params 116 | Struct 117 | Def 118 | Id "a" 119 | Id "A" 120 | None 121 | /Def 122 | Def 123 | Id "b" 124 | Id "B" 125 | None 126 | /Def 127 | /Struct 128 | /Params 129 | Params 130 | Def 131 | None 132 | Id "C" 133 | None 134 | /Def 135 | /Params 136 | Id "a" 137 | /Fun 138 | Fun 139 | Params 140 | Id "a" 141 | Params 142 | Def 143 | None 144 | Id "B" 145 | None 146 | /Def 147 | /Params 148 | Id "a" 149 | /Fun 150 | Call 151 | Id "match" 152 | Id "a" 153 | Id "on" 154 | /Call 155 | Id "b" 156 | Id "c" 157 | Call 158 | Id "f" 159 | Struct 160 | Def 161 | Id "a" 162 | None 163 | Call 164 | Id "g" 165 | Id "b" 166 | /Call 167 | /Def 168 | Def 169 | Id "c" 170 | None 171 | Id "d" 172 | /Def 173 | /Struct 174 | Id "[e" 175 | /Call 176 | Call 177 | Id "x]" 178 | Fun 179 | Params 180 | Id "y" 181 | Params 182 | Call 183 | Id "blah" 184 | Id "y" 185 | /Call 186 | /Fun 187 | /Call 188 | Call 189 | Call 190 | Id "f" 191 | Struct 192 | Def 193 | Id "a" 194 | None 195 | Call 196 | Id "g" 197 | Id "b" 198 | /Call 199 | /Def 200 | Def 201 | Id "c" 202 | None 203 | Id "d" 204 | /Def 205 | Def 206 | Id "on" 207 | None 208 | Id "on" 209 | /Def 210 | Def 211 | Id "e" 212 | None 213 | Id "e" 214 | /Def 215 | Def 216 | Id "x" 217 | None 218 | Id "x" 219 | /Def 220 | /Struct 221 | /Call 222 | List 223 | Fun 224 | Params 225 | Id "y" 226 | Params 227 | Call 228 | Id "blah" 229 | Id "y" 230 | /Call 231 | /Fun 232 | /List 233 | /Call 234 | Call 235 | Id "await" 236 | Struct 237 | Call 238 | Id "request" 239 | Id "something" 240 | /Call 241 | /Struct 242 | /Call 243 | Def 244 | Call 245 | Id "f" 246 | Id "a" 247 | List 248 | Id "b" 249 | /Call 250 | None 251 | Call 252 | Id "g" 253 | Id "c" 254 | /Call 255 | /Def 256 | Call 257 | Id "f" 258 | Id "a" 259 | Struct 260 | Def 261 | Id "b" 262 | None 263 | Call 264 | Id "g" 265 | Id "c" 266 | /Call 267 | /Def 268 | Def 269 | Id "d" 270 | None 271 | Id "e" 272 | /Def 273 | /Struct 274 | /Call 275 | Call 276 | Id "f" 277 | Id "a" 278 | List 279 | Def 280 | Id "b" 281 | None 282 | Call 283 | Id "g" 284 | Id "c" 285 | /Call 286 | /Def 287 | Def 288 | Id "d" 289 | None 290 | Id "e" 291 | /Def 292 | /List 293 | /Call 294 | Call 295 | Id "item" 296 | Id "from" 297 | Dot 298 | Id "items" 299 | Id "each" 300 | /Dot 301 | /Call 302 | Call 303 | Id "print" 304 | Id "item" 305 | /Call 306 | Call 307 | Id "match" 308 | Id "x" 309 | List 310 | Call 311 | Id "Pair" 312 | Int32 0 313 | String "no" 314 | /Call 315 | Call 316 | Id "Pair" 317 | Int32 1 318 | String "a single" 319 | /Call 320 | Call 321 | Id "Pair" 322 | Int32 2 323 | String "a couple of" 324 | /Call 325 | Call 326 | Id "any" 327 | Id "[3" 328 | /Call 329 | Int32 4 330 | Int32 5 331 | Int32 6 332 | Call 333 | Id "Pair" 334 | Id "]" 335 | String "a few of" 336 | /Call 337 | Call 338 | Id "case" 339 | Call 340 | Id "lt" 341 | Id "x" 342 | Int32 0 343 | /Call 344 | String "negative" 345 | /Call 346 | Call 347 | Id "else" 348 | String "several" 349 | /Call 350 | /List 351 | /Call 352 | Call 353 | To "to" 354 | Id "dog" 355 | /Call 356 | Call 357 | Id "Pair" 358 | Call 359 | Id "Pair" 360 | Id "a" 361 | Id "b" 362 | /Call 363 | Id "c" 364 | /Call 365 | Call 366 | Call 367 | Id "Pair" 368 | Id "a" 369 | To "to" 370 | /Call 371 | Id "eggplant" 372 | /Call 373 | Call 374 | Call 375 | Id "Pair" 376 | Id "fish" 377 | To "to" 378 | /Call 379 | Id "giraffe" 380 | /Call 381 | Call 382 | Id "Pair" 383 | To "to" 384 | Id "hyena" 385 | /Call 386 | Call 387 | To "to" 388 | Block 389 | /Call 390 | /Block 391 | 392 | Node size: 20 393 | Tree len: 293 394 | -------------------------------------------------------------------------------- /examples/out/wild/wild.parse.txt: -------------------------------------------------------------------------------- 1 | Block 2 | Def 3 | Id "b" 4 | HSpace " " 5 | Define "=" 6 | HSpace " " 7 | Int "2" 8 | /Def 9 | VSpace "\n" 10 | VSpace "\n" 11 | Infix 12 | Id "a" 13 | Dot "." 14 | Id "b" 15 | /Infix 16 | VSpace "\n" 17 | Infix 18 | Id "a" 19 | Dot "." 20 | Block 21 | RoundOpen "(" 22 | Call 23 | Id "b" 24 | HSpace " " 25 | Id "there" 26 | /Call 27 | RoundClose ")" 28 | /Block 29 | /Infix 30 | VSpace "\n" 31 | VSpace "\n" 32 | Call 33 | Call 34 | Id "a" 35 | RoundOpen "(" 36 | RoundClose ")" 37 | /Call 38 | RoundOpen "(" 39 | RoundClose ")" 40 | /Call 41 | VSpace "\n" 42 | Call 43 | Call 44 | Id "a" 45 | RoundOpen "(" 46 | RoundClose ")" 47 | /Call 48 | HSpace " " 49 | Block 50 | RoundOpen "(" 51 | RoundClose ")" 52 | /Block 53 | /Call 54 | VSpace "\n" 55 | VSpace "\n" 56 | Call 57 | Call 58 | Id "say" 59 | RoundOpen "(" 60 | VSpace "\n" 61 | HSpace " " 62 | Id "a" 63 | VSpace "\n" 64 | HSpace " " 65 | Id "b" 66 | VSpace "\n" 67 | RoundClose ")" 68 | /Call 69 | HSpace " " 70 | Block 71 | With "with" 72 | VSpace "\n" 73 | HSpace " " 74 | Id "c" 75 | VSpace "\n" 76 | HSpace " " 77 | Id "d" 78 | VSpace "\n" 79 | End "end" 80 | /Block 81 | /Call 82 | VSpace "\n" 83 | VSpace "\n" 84 | Call 85 | Call 86 | Id "say" 87 | RoundOpen "(" 88 | VSpace "\n" 89 | HSpace " " 90 | Id "a" 91 | VSpace "\n" 92 | HSpace " " 93 | Id "b" 94 | VSpace "\n" 95 | HSpace " " 96 | /Call 97 | Block 98 | With "with" 99 | HSpace " " 100 | Comment "# TODO Don't exit parens" 101 | VSpace "\n" 102 | HSpace " " 103 | Id "c" 104 | VSpace "\n" 105 | HSpace " " 106 | Id "d" 107 | VSpace "\n" 108 | HSpace " " 109 | End "end" 110 | /Block 111 | /Call 112 | VSpace "\n" 113 | HSpace " " 114 | End "end" 115 | HSpace " " 116 | Comment "# TODO Don't exit parens" 117 | VSpace "\n" 118 | HSpace " " 119 | Id "e" 120 | VSpace "\n" 121 | HSpace " " 122 | Id "f" 123 | VSpace "\n" 124 | RoundClose ")" 125 | VSpace "\n" 126 | VSpace "\n" 127 | Block 128 | With "with" 129 | VSpace "\n" 130 | HSpace " " 131 | Id "hi" 132 | VSpace "\n" 133 | End "end" 134 | /Block 135 | VSpace "\n" 136 | VSpace "\n" 137 | Call 138 | Id "blah" 139 | HSpace " " 140 | Id "something" 141 | HSpace " " 142 | Block 143 | With "with" 144 | VSpace "\n" 145 | HSpace " " 146 | Id "a" 147 | VSpace "\n" 148 | HSpace " " 149 | Id "b" 150 | VSpace "\n" 151 | End "end" 152 | /Block 153 | HSpace " " 154 | Fun 155 | Fun "for" 156 | HSpace " " 157 | Params 158 | Id "something" 159 | HSpace " " 160 | /Params 161 | Params 162 | Block 163 | Be "be" 164 | HSpace " " 165 | Comment "# TODO with for? also for?" 166 | VSpace "\n" 167 | HSpace " " 168 | Id "c" 169 | VSpace "\n" 170 | End "end" 171 | /Block 172 | /Fun 173 | /Call 174 | VSpace "\n" 175 | VSpace "\n" 176 | Call 177 | Minus "-" 178 | HSpace " " 179 | Int "5" 180 | /Call 181 | Comma ";" 182 | HSpace " " 183 | Call 184 | Minus "-" 185 | RoundOpen "(" 186 | Int "5" 187 | RoundClose ")" 188 | /Call 189 | VSpace "\n" 190 | VSpace "\n" 191 | Fun 192 | Fun "for" 193 | Params 194 | RoundOpen "(" 195 | RoundClose ")" 196 | /Params 197 | Params 198 | /Fun 199 | Comma ";" 200 | HSpace " " 201 | Fun 202 | Fun "for" 203 | Params 204 | RoundOpen "(" 205 | RoundClose ")" 206 | /Params 207 | Params 208 | /Fun 209 | Comma ";" 210 | HSpace " " 211 | Fun 212 | Fun "for" 213 | Params 214 | RoundOpen "(" 215 | RoundClose ")" 216 | /Params 217 | Params 218 | /Fun 219 | VSpace "\n" 220 | VSpace "\n" 221 | Comment "# Some of these might need improved handling" 222 | VSpace "\n" 223 | Fun "for" 224 | VSpace "\n" 225 | Fun "for" 226 | HSpace " " 227 | Int "5" 228 | VSpace "\n" 229 | Call 230 | Fun "for" 231 | HSpace " " 232 | Block 233 | Be "be" 234 | HSpace " " 235 | Int "5" 236 | /Block 237 | /Call 238 | VSpace "\n" 239 | VSpace "\n" 240 | Fun 241 | Fun "for" 242 | HSpace " " 243 | Params 244 | Block 245 | CurlyOpen "{" 246 | HSpace " " 247 | Def 248 | Typed 249 | Id "a" 250 | Colon ":" 251 | HSpace " " 252 | Id "A" 253 | HSpace " " 254 | /Typed 255 | Define "=" 256 | HSpace " " 257 | Int "1" 258 | /Def 259 | Comma "," 260 | HSpace " " 261 | Typed 262 | Id "b" 263 | Colon ":" 264 | HSpace " " 265 | Id "B" 266 | HSpace " " 267 | /Typed 268 | CurlyClose "}" 269 | /Block 270 | /Params 271 | Colon ":" 272 | HSpace " " 273 | Params 274 | Typed 275 | None 276 | Id "C" 277 | HSpace " " 278 | /Typed 279 | /Params 280 | Block 281 | Be "be" 282 | VSpace "\n" 283 | HSpace " " 284 | Id "a" 285 | VSpace "\n" 286 | End "end" 287 | /Block 288 | /Fun 289 | VSpace "\n" 290 | VSpace "\n" 291 | Fun 292 | Fun "for" 293 | Params 294 | RoundOpen "(" 295 | Block 296 | CurlyOpen "{" 297 | HSpace " " 298 | Typed 299 | Id "a" 300 | Colon ":" 301 | HSpace " " 302 | Id "A" 303 | /Typed 304 | Comma "," 305 | HSpace " " 306 | Typed 307 | Id "b" 308 | Colon ":" 309 | HSpace " " 310 | Id "B" 311 | HSpace " " 312 | /Typed 313 | CurlyClose "}" 314 | /Block 315 | RoundClose ")" 316 | /Params 317 | Colon ":" 318 | HSpace " " 319 | Params 320 | Typed 321 | None 322 | Id "C" 323 | HSpace " " 324 | /Typed 325 | /Params 326 | Block 327 | Be "be" 328 | VSpace "\n" 329 | HSpace " " 330 | Id "a" 331 | VSpace "\n" 332 | End "end" 333 | /Block 334 | /Fun 335 | VSpace "\n" 336 | VSpace "\n" 337 | Fun 338 | Fun "for" 339 | HSpace " " 340 | Params 341 | Id "a" 342 | Colon ":" 343 | HSpace " " 344 | Params 345 | Typed 346 | None 347 | Id "B" 348 | HSpace " " 349 | /Typed 350 | /Params 351 | Block 352 | Be "be" 353 | HSpace " " 354 | Id "a" 355 | /Block 356 | /Fun 357 | VSpace "\n" 358 | VSpace "\n" 359 | Comment "# match a [b, c]" 360 | VSpace "\n" 361 | Call 362 | Id "match" 363 | HSpace " " 364 | Id "a" 365 | HSpace " " 366 | Id "on" 367 | /Call 368 | VSpace "\n" 369 | HSpace " " 370 | Id "b" 371 | VSpace "\n" 372 | HSpace " " 373 | Id "c" 374 | VSpace "\n" 375 | End "end" 376 | VSpace "\n" 377 | VSpace "\n" 378 | Call 379 | Id "f" 380 | HSpace " " 381 | Block 382 | CurlyOpen "{" 383 | HSpace " " 384 | Def 385 | Id "a" 386 | HSpace " " 387 | Define "=" 388 | HSpace " " 389 | Call 390 | Id "g" 391 | HSpace " " 392 | Id "b" 393 | /Call 394 | /Def 395 | Comma "," 396 | HSpace " " 397 | Def 398 | Id "c" 399 | HSpace " " 400 | Define "=" 401 | HSpace " " 402 | Id "d" 403 | HSpace " " 404 | /Def 405 | CurlyClose "}" 406 | /Block 407 | HSpace " " 408 | Id "[e" 409 | /Call 410 | Comma "," 411 | HSpace " " 412 | Call 413 | Id "x]" 414 | HSpace " " 415 | Fun 416 | Fun "for" 417 | HSpace " " 418 | Params 419 | Id "y" 420 | HSpace " " 421 | /Params 422 | Params 423 | Block 424 | Be "be" 425 | HSpace " " 426 | Call 427 | Id "blah" 428 | HSpace " " 429 | Id "y" 430 | /Call 431 | /Block 432 | /Fun 433 | /Call 434 | VSpace "\n" 435 | Call 436 | Call 437 | Id "f" 438 | HSpace " " 439 | Block 440 | Of "of" 441 | VSpace "\n" 442 | HSpace " " 443 | Def 444 | Id "a" 445 | HSpace " " 446 | Define "=" 447 | HSpace " " 448 | Call 449 | Id "g" 450 | HSpace " " 451 | Id "b" 452 | /Call 453 | /Def 454 | VSpace "\n" 455 | HSpace " " 456 | Def 457 | Id "c" 458 | HSpace " " 459 | Define "=" 460 | HSpace " " 461 | Id "d" 462 | /Def 463 | VSpace "\n" 464 | Id "on" 465 | VSpace "\n" 466 | HSpace " " 467 | Id "e" 468 | VSpace "\n" 469 | HSpace " " 470 | Id "x" 471 | VSpace "\n" 472 | /Block 473 | /Call 474 | Block 475 | With "with" 476 | HSpace " " 477 | Fun 478 | Fun "for" 479 | HSpace " " 480 | Params 481 | Id "y" 482 | HSpace " " 483 | /Params 484 | Params 485 | Block 486 | Be "be" 487 | VSpace "\n" 488 | HSpace " " 489 | Call 490 | Id "blah" 491 | HSpace " " 492 | Id "y" 493 | /Call 494 | VSpace "\n" 495 | End "end" 496 | /Block 497 | /Fun 498 | /Block 499 | /Call 500 | VSpace "\n" 501 | Call 502 | Id "await" 503 | HSpace " " 504 | Block 505 | Of "of" 506 | HSpace " " 507 | Call 508 | Id "request" 509 | HSpace " " 510 | Id "something" 511 | /Call 512 | /Block 513 | /Call 514 | VSpace "\n" 515 | VSpace "\n" 516 | Def 517 | Call 518 | Id "f" 519 | HSpace " " 520 | Id "a" 521 | HSpace " " 522 | Block 523 | With "with" 524 | HSpace " " 525 | Id "b" 526 | HSpace " " 527 | /Block 528 | /Call 529 | Define "=" 530 | HSpace " " 531 | Call 532 | Id "g" 533 | HSpace " " 534 | Id "c" 535 | /Call 536 | /Def 537 | VSpace "\n" 538 | Call 539 | Id "f" 540 | HSpace " " 541 | Id "a" 542 | HSpace " " 543 | Block 544 | CurlyOpen "{" 545 | HSpace " " 546 | Def 547 | Id "b" 548 | HSpace " " 549 | Define "=" 550 | HSpace " " 551 | Call 552 | Id "g" 553 | HSpace " " 554 | Id "c" 555 | /Call 556 | /Def 557 | Comma "," 558 | HSpace " " 559 | Def 560 | Id "d" 561 | HSpace " " 562 | Define "=" 563 | HSpace " " 564 | Id "e" 565 | HSpace " " 566 | /Def 567 | CurlyClose "}" 568 | /Block 569 | /Call 570 | VSpace "\n" 571 | Call 572 | Id "f" 573 | HSpace " " 574 | Id "a" 575 | HSpace " " 576 | Block 577 | With "with" 578 | VSpace "\n" 579 | HSpace " " 580 | Def 581 | Id "b" 582 | HSpace " " 583 | Define "=" 584 | HSpace " " 585 | Call 586 | Id "g" 587 | HSpace " " 588 | Id "c" 589 | /Call 590 | /Def 591 | VSpace "\n" 592 | HSpace " " 593 | Def 594 | Id "d" 595 | HSpace " " 596 | Define "=" 597 | HSpace " " 598 | Id "e" 599 | /Def 600 | VSpace "\n" 601 | End "end" 602 | /Block 603 | /Call 604 | VSpace "\n" 605 | VSpace "\n" 606 | Call 607 | Id "item" 608 | HSpace " " 609 | Id "from" 610 | HSpace " " 611 | Infix 612 | Id "items" 613 | Dot "." 614 | Id "each" 615 | /Infix 616 | /Call 617 | VSpace "\n" 618 | Call 619 | Id "print" 620 | HSpace " " 621 | Id "item" 622 | /Call 623 | VSpace "\n" 624 | VSpace "\n" 625 | Call 626 | Id "match" 627 | HSpace " " 628 | Id "x" 629 | HSpace " " 630 | Block 631 | With "with" 632 | VSpace "\n" 633 | HSpace " " 634 | Infix 635 | Int "0" 636 | HSpace " " 637 | To "to" 638 | HSpace " " 639 | StringParts 640 | StringEdge "\"" 641 | String "no" 642 | StringEdge "\"" 643 | /StringParts 644 | /Infix 645 | VSpace "\n" 646 | HSpace " " 647 | Infix 648 | Int "1" 649 | HSpace " " 650 | To "to" 651 | HSpace " " 652 | StringParts 653 | StringEdge "\"" 654 | String "a single" 655 | StringEdge "\"" 656 | /StringParts 657 | /Infix 658 | VSpace "\n" 659 | HSpace " " 660 | Infix 661 | Int "2" 662 | HSpace " " 663 | To "to" 664 | HSpace " " 665 | StringParts 666 | StringEdge "\"" 667 | String "a couple of" 668 | StringEdge "\"" 669 | /StringParts 670 | /Infix 671 | VSpace "\n" 672 | HSpace " " 673 | Call 674 | Id "any" 675 | HSpace " " 676 | Id "[3" 677 | /Call 678 | Comma "," 679 | HSpace " " 680 | Int "4" 681 | Comma "," 682 | HSpace " " 683 | Int "5" 684 | Comma "," 685 | HSpace " " 686 | Int "6" 687 | Infix 688 | Id "]" 689 | HSpace " " 690 | To "to" 691 | HSpace " " 692 | StringParts 693 | StringEdge "\"" 694 | String "a few of" 695 | StringEdge "\"" 696 | /StringParts 697 | /Infix 698 | VSpace "\n" 699 | HSpace " " 700 | Call 701 | Id "case" 702 | HSpace " " 703 | Infix 704 | Id "x" 705 | HSpace " " 706 | AngleOpen "<" 707 | HSpace " " 708 | Int "0" 709 | HSpace " " 710 | /Infix 711 | StringParts 712 | StringEdge "\"" 713 | String "negative" 714 | StringEdge "\"" 715 | /StringParts 716 | /Call 717 | VSpace "\n" 718 | HSpace " " 719 | Call 720 | Id "else" 721 | HSpace " " 722 | StringParts 723 | StringEdge "\"" 724 | String "several" 725 | StringEdge "\"" 726 | /StringParts 727 | /Call 728 | VSpace "\n" 729 | End "end" 730 | /Block 731 | /Call 732 | VSpace "\n" 733 | VSpace "\n" 734 | Call 735 | To "to" 736 | HSpace " " 737 | Id "dog" 738 | /Call 739 | VSpace "\n" 740 | Infix 741 | Infix 742 | Id "a" 743 | HSpace " " 744 | To "to" 745 | HSpace " " 746 | Id "b" 747 | HSpace " " 748 | /Infix 749 | To "to" 750 | HSpace " " 751 | Id "c" 752 | /Infix 753 | VSpace "\n" 754 | Call 755 | Infix 756 | Id "a" 757 | HSpace " " 758 | To "to" 759 | VSpace "\n" 760 | To "to" 761 | HSpace " " 762 | /Infix 763 | Id "eggplant" 764 | /Call 765 | VSpace "\n" 766 | Call 767 | Infix 768 | Id "fish" 769 | HSpace " " 770 | To "to" 771 | HSpace " " 772 | To "to" 773 | HSpace " " 774 | /Infix 775 | Id "giraffe" 776 | /Call 777 | VSpace "\n" 778 | Infix 779 | To "to" 780 | HSpace " " 781 | To "to" 782 | HSpace " " 783 | Id "hyena" 784 | /Infix 785 | VSpace "\n" 786 | End "end" 787 | HSpace " " 788 | Call 789 | To "to" 790 | HSpace " " 791 | Block 792 | Be "be" 793 | VSpace "\n" 794 | /Block 795 | /Call 796 | /Block 797 | 798 | Node size: 12 799 | Tree len: 674 800 | -------------------------------------------------------------------------------- /examples/out/wild/wild.run.txt: -------------------------------------------------------------------------------- 1 | Block 2 | Module "examples/wild.rio" 2 3 | Def@271 :@261 4 | Uid b@271 :@261 5 | None 6 | Int32 2 :@261 7 | /Def 8 | Dot 9 | Id "a" 10 | Id "b" 11 | /Dot 12 | Dot 13 | Id "a" 14 | Call 15 | Uid b@271 :@261 16 | Id "there" 17 | /Call 18 | /Dot 19 | Call 20 | Call 21 | Id "a" 22 | /Call 23 | Call 24 | Call 25 | Id "a" 26 | Block 27 | /Call 28 | Call 29 | Call 30 | Id "say" 31 | Id "a" 32 | Uid b@271 :@261 33 | /Call 34 | List 35 | Id "c" 36 | Id "d" 37 | /List 38 | /Call 39 | Call 40 | Call 41 | Id "say" 42 | Id "a" 43 | Uid b@271 :@261 44 | /Call 45 | List 46 | Id "c" 47 | Id "d" 48 | /List 49 | /Call 50 | Id "e" 51 | Id "f" 52 | List 53 | Id "hi" 54 | Call 55 | Id "blah" 56 | Id "something" 57 | List 58 | Id "a" 59 | Uid b@271 :@261 60 | /List 61 | Fun :@262 62 | Params 63 | Id "something" 64 | Params 65 | Id "c" 66 | /Fun 67 | /Call 68 | Call 69 | Minus "-" 70 | Int32 5 :@261 71 | /Call 72 | Call 73 | Minus "-" 74 | Int32 5 :@261 75 | /Call 76 | Fun :@264 77 | Params 78 | Params 79 | /Fun 80 | Fun :@264 81 | Params 82 | Params 83 | /Fun 84 | Fun :@264 85 | Params 86 | Params 87 | /Fun 88 | Int32 5 :@261 89 | Call 90 | Int32 5 :@261 91 | Fun :@262 92 | Params 93 | Struct 94 | Field :@261 95 | Uid a@57 :@261 96 | Id "A" 97 | Int32 1 :@261 98 | /Field 99 | Field 100 | Uid b@58 101 | Id "B" 102 | None 103 | /Field 104 | /Struct 105 | /Params 106 | Params 107 | Def@63 108 | None 109 | Id "C" 110 | None 111 | /Def 112 | /Params 113 | Id "a" 114 | /Fun 115 | Fun :@262 116 | Params 117 | Struct 118 | Field 119 | Uid a@73 120 | Id "A" 121 | None 122 | /Field 123 | Field 124 | Uid b@74 125 | Id "B" 126 | None 127 | /Field 128 | /Struct 129 | /Params 130 | Params 131 | Def@79 132 | None 133 | Id "C" 134 | None 135 | /Def 136 | /Params 137 | Id "a" 138 | /Fun 139 | Fun :@262 140 | Params 141 | Id "a" 142 | Params 143 | Def@87 144 | None 145 | Id "B" 146 | None 147 | /Def 148 | /Params 149 | Id "a" 150 | /Fun 151 | Call 152 | Id "match" 153 | Id "a" 154 | Id "on" 155 | /Call 156 | Uid b@271 :@261 157 | Id "c" 158 | Call 159 | Id "f" 160 | Struct 161 | Field 162 | Uid a@102 163 | None 164 | Call 165 | Id "g" 166 | Uid b@271 :@261 167 | /Call 168 | /Field 169 | Field 170 | Uid c@103 171 | None 172 | Id "d" 173 | /Field 174 | /Struct 175 | Id "[e" 176 | /Call 177 | Call 178 | Id "x]" 179 | Fun :@262 180 | Params 181 | Id "y" 182 | Params 183 | Call 184 | Id "blah" 185 | Id "y" 186 | /Call 187 | /Fun 188 | /Call 189 | Call 190 | Call 191 | Id "f" 192 | Struct 193 | Field 194 | Uid a@132 195 | None 196 | Call 197 | Id "g" 198 | Uid b@271 :@261 199 | /Call 200 | /Field 201 | Field 202 | Uid c@133 203 | None 204 | Id "d" 205 | /Field 206 | Field 207 | Uid on@134 208 | None 209 | Id "on" 210 | /Field 211 | Field 212 | Uid e@135 213 | None 214 | Id "e" 215 | /Field 216 | Field 217 | Uid x@136 218 | None 219 | Id "x" 220 | /Field 221 | /Struct 222 | /Call 223 | List 224 | Fun :@262 225 | Params 226 | Id "y" 227 | Params 228 | Call 229 | Id "blah" 230 | Id "y" 231 | /Call 232 | /Fun 233 | /List 234 | /Call 235 | Call 236 | Id "await" 237 | Struct 238 | Call 239 | Id "request" 240 | Id "something" 241 | /Call 242 | /Struct 243 | /Call 244 | Def@299 245 | Call 246 | Id "f" 247 | Id "a" 248 | List 249 | Uid b@271 :@261 250 | /Call 251 | None 252 | Call 253 | Id "g" 254 | Id "c" 255 | /Call 256 | /Def 257 | Call 258 | Id "f" 259 | Id "a" 260 | Struct 261 | Field 262 | Uid b@170 263 | None 264 | Call 265 | Id "g" 266 | Id "c" 267 | /Call 268 | /Field 269 | Field 270 | Uid d@171 271 | None 272 | Id "e" 273 | /Field 274 | /Struct 275 | /Call 276 | Call 277 | Id "f" 278 | Id "a" 279 | List 280 | Def@183 281 | Uid b@183 282 | None 283 | Call 284 | Id "g" 285 | Id "c" 286 | /Call 287 | /Def 288 | Def@184 289 | Uid d@184 290 | None 291 | Id "e" 292 | /Def 293 | /List 294 | /Call 295 | Call 296 | Id "item" 297 | Id "from" 298 | Dot 299 | Id "items" 300 | Id "each" 301 | /Dot 302 | /Call 303 | Call :@263 304 | Uid print@1@662 :@266 305 | Id "item" :@265 306 | /Call 307 | Call 308 | Id "match" 309 | Id "x" 310 | List 311 | Call 312 | Uid Pair@1@648 :@267 313 | Int32 0 :@261 314 | String "no" :@265 315 | /Call 316 | Call 317 | Uid Pair@1@648 :@267 318 | Int32 1 :@261 319 | String "a single" :@265 320 | /Call 321 | Call 322 | Uid Pair@1@648 :@267 323 | Int32 2 :@261 324 | String "a couple of" :@265 325 | /Call 326 | Call 327 | Id "any" 328 | Id "[3" 329 | /Call 330 | Int32 4 :@261 331 | Int32 5 :@261 332 | Int32 6 :@261 333 | Call 334 | Uid Pair@1@648 :@267 335 | Id "]" 336 | String "a few of" :@265 337 | /Call 338 | Call 339 | Id "case" 340 | Call :@268 341 | Uid lt@1@641 :@269 342 | Id "x" :@261 343 | Int32 0 :@261 344 | /Call 345 | String "negative" :@265 346 | /Call 347 | Call 348 | Uid else@1@656 349 | String "several" :@265 350 | /Call 351 | /List 352 | /Call 353 | Call 354 | To "to" 355 | Id "dog" 356 | /Call 357 | Call 358 | Uid Pair@1@648 :@267 359 | Call 360 | Uid Pair@1@648 :@267 361 | Id "a" 362 | Uid b@271 :@261 363 | /Call 364 | Id "c" 365 | /Call 366 | Call 367 | Call 368 | Uid Pair@1@648 :@267 369 | Id "a" 370 | To "to" 371 | /Call 372 | Id "eggplant" 373 | /Call 374 | Call 375 | Call 376 | Uid Pair@1@648 :@267 377 | Id "fish" 378 | To "to" 379 | /Call 380 | Id "giraffe" 381 | /Call 382 | Call 383 | Uid Pair@1@648 :@267 384 | To "to" 385 | Id "hyena" 386 | /Call 387 | Call 388 | To "to" 389 | Block 390 | /Call 391 | Types 392 | Uid@261 Int32@1@635 393 | FunType@262 394 | None 395 | Uid@263 Void@1@651 396 | FunType@264 :@263 397 | Uid@265 Text@1@649 398 | FunType@266 :@263 399 | None :@265 400 | FunType@267 401 | None 402 | None 403 | None 404 | None 405 | /FunType 406 | Uid@268 Claim@1@632 407 | FunType@269 :@268 408 | None :@261 409 | None :@261 410 | /FunType 411 | /Types 412 | /Block 413 | 414 | Node size: 20 415 | Tree len: 312 416 | -------------------------------------------------------------------------------- /examples/recurse.rio: -------------------------------------------------------------------------------- 1 | main* = for() be 2 | i = 3 3 | countDown(i) 4 | print oddness(i) 5 | print oddness(i + 1) 6 | end 7 | 8 | countDown = for(count: Int32) be 9 | print "counting ..." 10 | branch with 11 | count > 1 to countDown(count - 1) 12 | else be print "done" 13 | end 14 | end 15 | 16 | isEven = for(i: Int32): Claim be branch with 17 | i > 0 to isOdd(i - 1) 18 | else true 19 | end 20 | 21 | isOdd = for(i: Int32): Claim be branch with 22 | i > 0 to isEven(i - 1) 23 | else false 24 | end 25 | 26 | oddness = for(i: Int32) be branch with 27 | isEven(i) to "even" 28 | else "odd" 29 | end 30 | -------------------------------------------------------------------------------- /examples/struct.rio: -------------------------------------------------------------------------------- 1 | main* = for() be 2 | name = "Alice" 3 | alice = Person{name, age = 40} 4 | describe(alice) 5 | describe{alice.age, name = "Bob"} 6 | describe build("Carl", 10) 7 | describe of 8 | age = 9 9 | name = "Denise" 10 | end 11 | end 12 | 13 | Person = struct of 14 | name: Text 15 | age: Int32 16 | end 17 | 18 | build = for(name: Text, age: Int32): Person be {name, age} 19 | 20 | describe = for(person: Person) be 21 | # TODO Text interp and auto struct printing. 22 | print "Person:" 23 | print person.name 24 | print be branch with 25 | person.age >= 18 to "adult" 26 | else "minor" 27 | end 28 | print "" 29 | end 30 | -------------------------------------------------------------------------------- /examples/wild.rio: -------------------------------------------------------------------------------- 1 | b = 2 2 | 3 | a.b 4 | a.(b there) 5 | 6 | a()() 7 | a() () 8 | 9 | say( 10 | a 11 | b 12 | ) with 13 | c 14 | d 15 | end 16 | 17 | say( 18 | a 19 | b 20 | with # TODO Don't exit parens 21 | c 22 | d 23 | end 24 | end # TODO Don't exit parens 25 | e 26 | f 27 | ) 28 | 29 | with 30 | hi 31 | end 32 | 33 | blah something with 34 | a 35 | b 36 | end for something be # TODO with for? also for? 37 | c 38 | end 39 | 40 | - 5; -(5) 41 | 42 | for(); for(); for() 43 | 44 | # Some of these might need improved handling 45 | for 46 | for 5 47 | for be 5 48 | 49 | for { a: A = 1, b: B }: C be 50 | a 51 | end 52 | 53 | for({ a: A, b: B }): C be 54 | a 55 | end 56 | 57 | for a: B be a 58 | 59 | # match a [b, c] 60 | match a on 61 | b 62 | c 63 | end 64 | 65 | f { a = g b, c = d } [e, x] for y be blah y 66 | f of 67 | a = g b 68 | c = d 69 | on 70 | e 71 | x 72 | with for y be 73 | blah y 74 | end 75 | await of request something 76 | 77 | f a with b = g c 78 | f a { b = g c, d = e } 79 | f a with 80 | b = g c 81 | d = e 82 | end 83 | 84 | item from items.each 85 | print item 86 | 87 | match x with 88 | 0 to "no" 89 | 1 to "a single" 90 | 2 to "a couple of" 91 | any [3, 4, 5, 6] to "a few of" 92 | case x < 0 "negative" 93 | else "several" 94 | end 95 | 96 | to dog 97 | a to b to c 98 | a to 99 | to eggplant 100 | fish to to giraffe 101 | to to hyena 102 | end to be 103 | -------------------------------------------------------------------------------- /logos/rio-logo-round.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 13 | 17 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /logos/rio-logo-square.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /logos/rio-logo-stream-2.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 16 | 36 | 37 | 39 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /logos/rio-logo-stream.svg: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 13 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /other/fib.wat: -------------------------------------------------------------------------------- 1 | ;; wat2wasm fib.wat && wasm2wat --fold-exprs --generate-names -v fib.wasm -o fib-out.wat 2> fib-out.txt && wasmer run fib.wasm 2 | 3 | (import "wasi_snapshot_preview1" "fd_write" 4 | (func $fd-write 5 | (param $fd i32) 6 | (param $iovec i32) 7 | (param $len i32) 8 | (param $written i32) 9 | (result i32) 10 | ) 11 | ) 12 | 13 | (memory (export "memory") 1) 14 | 15 | (global $stack-top (mut i32) (i32.const 1024)) 16 | 17 | (func $main (export "_start") 18 | (local $n i32) 19 | loop $each 20 | (call $print (i32.const 1024)) 21 | (call $print-i32 (local.get $n)) 22 | (call $print (i32.const 1032)) 23 | (call $print-i32 (call $fib (local.get $n))) 24 | (call $print (i32.const 1040)) 25 | (local.tee $n (i32.add (local.get $n) (i32.const 1))) 26 | (i32.le_s (i32.const 9)) 27 | br_if $each 28 | end 29 | ) 30 | 31 | (func $fib (param $n i32) (result i32) 32 | (local $result i32) 33 | (i32.le_s (local.get $n) (i32.const 0)) 34 | if 35 | (local.set $result (i32.const 0)) 36 | else 37 | (i32.eq (local.get $n) (i32.const 1)) 38 | if (result i32) 39 | i32.const 1 40 | else 41 | (i32.add 42 | (call $fib (i32.sub (local.get $n) (i32.const 2))) 43 | (call $fib (i32.sub (local.get $n) (i32.const 1))) 44 | ) 45 | end 46 | local.set $result 47 | end 48 | local.get $result 49 | ) 50 | 51 | (func $print (param $text i32) 52 | (local $iovec i32) 53 | (local $nwritten i32) 54 | (local.set $iovec (call $stack-push (i32.const 8))) 55 | (local.set $nwritten (call $stack-push (i32.const 4))) 56 | (i32.store (local.get $iovec) (i32.add (local.get $text) (i32.const 4))) 57 | (i32.store 58 | (i32.add (local.get $iovec) (i32.const 4)) (i32.load (local.get $text)) 59 | ) 60 | (call $fd-write 61 | (i32.const 1) (local.get $iovec) (i32.const 1) (local.get $nwritten) 62 | ) 63 | drop 64 | (call $stack-pop (i32.const 12)) 65 | ) 66 | 67 | (func $print-i32 (export "print-i32") (param $n i32) 68 | (local $temp i32) 69 | (local $neg i32) 70 | (local $text i32) 71 | (local $buffer i32) 72 | (local $cursor i32) 73 | ;; Need 4 bytes for size and up to 11 bytes for signed 32-bit in base 10. 74 | ;; Round up to 12 just nice alignment. 75 | (local.set $text (call $stack-push (i32.const 16))) 76 | (local.set $buffer (i32.add (local.get $text) (i32.const 4))) 77 | (local.set $cursor (local.get $buffer)) 78 | ;; Put in a dash for negative. 79 | (local.tee $neg (i32.lt_s (local.get $n) (i32.const 0))) 80 | if 81 | (i32.store8 (local.get $cursor) (i32.const 0x2d)) 82 | (local.set $cursor (i32.add (local.get $cursor) (i32.const 1))) 83 | (local.set $n (i32.sub (i32.const 0) (local.get $n))) 84 | end 85 | ;; Figure out where to start writing digits. 86 | ;; This presumes it's easier and/or faster to calculate twice than to reverse 87 | ;; an array. 88 | (local.set $temp (local.get $n)) 89 | loop $size 90 | (local.set $cursor (i32.add (local.get $cursor) (i32.const 1))) 91 | ;; Divide by 10. 92 | (local.tee $temp (i32.div_u (local.get $temp) (i32.const 10))) 93 | (i32.ne (i32.const 0)) 94 | br_if $size 95 | end 96 | ;; Store the size before we start moving the cursor back. 97 | (i32.store (local.get $text) 98 | (i32.sub (local.get $cursor) (local.get $buffer)) 99 | ) 100 | ;; Now start putting in the digits in order from back to front. 101 | loop $digits 102 | ;; We'd have advanced past our last digit above, so subtract first. 103 | (local.set $cursor (i32.sub (local.get $cursor) (i32.const 1))) 104 | ;; Add the digit to ascii '0' 0x30. 105 | (i32.store8 (local.get $cursor) 106 | (i32.add (i32.rem_u (local.get $n) (i32.const 10)) (i32.const 0x30)) 107 | ) 108 | ;; Divide by 10. 109 | (local.tee $n (i32.div_u (local.get $n) (i32.const 10))) 110 | ;; Break if done. We get at least one digit above. 111 | (i32.ne (i32.const 0)) 112 | br_if $digits 113 | end 114 | ;; Print and done. 115 | (call $print (local.get $text)) 116 | (call $stack-pop (i32.const 16)) 117 | ) 118 | 119 | (func $stack-pop (param $n i32) 120 | (global.set $stack-top (i32.add (global.get $stack-top) (local.get $n))) 121 | ) 122 | 123 | (func $stack-push (param $n i32) (result i32) 124 | (local $address i32) 125 | (global.set $stack-top 126 | (local.tee $address (i32.sub (global.get $stack-top) (local.get $n))) 127 | ) 128 | local.get $address 129 | ) 130 | 131 | (data $message0 (i32.const 1024) "\04\00\00\00fib(") 132 | (data $message1 (i32.const 1032) "\04\00\00\00) = ") 133 | (data $message2 (i32.const 1040) "\01\00\00\00\n\00\00\00") 134 | -------------------------------------------------------------------------------- /src/core.rio: -------------------------------------------------------------------------------- 1 | # TODO Array of fixed size? Static size? 2 | 3 | Case* = for be Pair, Lazy> 4 | 5 | Claim* = Either 6 | 7 | Either* = for be Yes | No 8 | 9 | Function* = for, ReturnType> be class of 10 | # TODO 11 | end 12 | 13 | Int32* = class of 14 | add* = for(other: Int32): Int32 be native() 15 | gt* = for(other: Int32): Claim be native() 16 | lt* = for(other: Int32): Claim be native() 17 | eq* = for(other: Int32): Claim be native() 18 | end 19 | 20 | # Probably temporary until member access is implemented. 21 | add* = for(a: Int32, b: Int32): Int32 be native() 22 | eq* = for(a: Int32, b: Int32): Claim be native() 23 | ge* = for(a: Int32, b: Int32): Claim be native() 24 | gt* = for(a: Int32, b: Int32): Claim be native() 25 | le* = for(a: Int32, b: Int32): Claim be native() 26 | lt* = for(a: Int32, b: Int32): Claim be native() 27 | ne* = for(a: Int32, b: Int32): Claim be native() 28 | sub* = for(a: Int32, b: Int32): Int32 be native() 29 | 30 | Lazy* = for be class of 31 | builder: Function<[], Value> 32 | with 33 | value* = for() be 34 | if (not maybe) be 35 | # TODO If this/self is a box, maybe such mutation has meaning? 36 | # This mutation is implementation, although builder has to be 37 | # immutable or else time of build could make a difference. 38 | maybe := Yes(builder()) 39 | end 40 | (maybe as Yes).value 41 | end 42 | 43 | maybe: Maybe = false 44 | end 45 | 46 | List* = for be class of 47 | # TODO 48 | end 49 | 50 | Maybe* = for be Either 51 | 52 | No* = for be ordered struct of 53 | value: Value 54 | end 55 | 56 | # Ordered class with greaterOrEquals, ... 57 | 58 | Pair* = for be ordered struct of 59 | key: Key 60 | value: Value 61 | end 62 | 63 | Text*: Type = native() 64 | 65 | Type* = class of 66 | union* = for(a: Type, b: Type): Type be native() 67 | end 68 | 69 | Void*: Type = native() 70 | 71 | Yes* = for be ordered struct of 72 | value: Value 73 | end 74 | 75 | branch* = for(cases: List>): Value be native() 76 | 77 | class* = for() be native() 78 | 79 | else* = for(value: Lazy): Case be true to value 80 | 81 | # TODO No type annotation needed once we process types more. 82 | false*: Claim = No(void) 83 | 84 | native* = for() be native() 85 | 86 | not* = for(claim: Claim): Claim be branch with 87 | claim to false 88 | else true 89 | end 90 | 91 | ordered* = for() be native() 92 | 93 | # print*: Function<[Text], Void> = native() 94 | print* = for(text: Text): Void be native() 95 | 96 | struct* = for(): Type be native() 97 | 98 | # TODO No type annotation needed once we process types more. 99 | true*: Claim = Yes(void) 100 | 101 | void*: Void = native() 102 | -------------------------------------------------------------------------------- /src/core.rs: -------------------------------------------------------------------------------- 1 | use std::{collections::HashMap, fmt::Debug}; 2 | 3 | use crate::lex::{Intern, Interner}; 4 | 5 | pub struct Core { 6 | pub members: HashMap, 7 | } 8 | 9 | pub enum NativeDef { 10 | Fun(NativeFun), 11 | Type(NativeType), 12 | } 13 | 14 | pub struct NativeFun { 15 | pub name: &'static str, 16 | pub fun: Box Vec>, 17 | pub params_in: Vec, 18 | pub params_out: Vec, 19 | } 20 | 21 | impl Debug for NativeFun { 22 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 23 | f.debug_struct("NativeFun") 24 | .field("name", &self.name) 25 | // .field("fun", &self.fun) 26 | .field("params_in", &self.params_in) 27 | .field("params_out", &self.params_out) 28 | .finish() 29 | } 30 | } 31 | 32 | #[derive(Debug)] 33 | pub struct NativeParam { 34 | pub name: &'static str, 35 | pub typ: NativeType, 36 | } 37 | 38 | #[derive(Clone, Copy, Debug)] 39 | pub struct NativeType { 40 | pub name: &'static str, 41 | } 42 | 43 | #[derive(Debug)] 44 | pub enum Value { 45 | Fun(NativeFun), 46 | Null(), 47 | Text(String), 48 | } 49 | 50 | pub fn make_core(interner: Interner) -> Core { 51 | let mut members = HashMap::::new(); 52 | let null_typ = add_type(&mut members, &interner, "Null"); 53 | add_type(&mut members, &interner, "Text"); 54 | { 55 | let name = "print"; 56 | members.insert( 57 | interner.get_or_intern(name), 58 | NativeDef::Fun(NativeFun { 59 | name, 60 | fun: Box::new(&print_fun), 61 | params_in: vec![], 62 | params_out: vec![NativeParam { 63 | name: "", 64 | typ: null_typ, 65 | }], 66 | }), 67 | ); 68 | } 69 | Core { members } 70 | } 71 | 72 | fn add_type( 73 | members: &mut HashMap, 74 | interner: &Interner, 75 | name: &'static str, 76 | ) -> NativeType { 77 | let typ = NativeType { name }; 78 | members.insert(interner.get_or_intern(name), NativeDef::Type(typ)); 79 | typ 80 | } 81 | 82 | fn print_fun(args_in: &[Value]) -> Vec { 83 | assert_eq!(1, args_in.len()); 84 | if let Value::Text(text) = &args_in[0] { 85 | println!("{text}"); 86 | } else { 87 | panic!("bad value: {:?}", &args_in[0]); 88 | } 89 | vec![] 90 | } 91 | -------------------------------------------------------------------------------- /src/lex.rs: -------------------------------------------------------------------------------- 1 | use std::{fmt::Debug, iter::Peekable, str::Chars, sync::Arc}; 2 | 3 | use lasso::{Spur, ThreadedRodeo}; 4 | 5 | use crate::Cart; 6 | 7 | pub type Intern = Spur; 8 | pub type Interner = Arc; 9 | 10 | #[derive(Clone, Copy, Eq, Hash, PartialEq)] 11 | pub struct Token { 12 | pub kind: TokenKind, 13 | pub intern: Intern, 14 | } 15 | 16 | impl Debug for Token { 17 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 18 | f.write_fmt(format_args!("{:?}:{}", self.kind, self.intern.into_inner())) 19 | } 20 | } 21 | 22 | impl Token { 23 | pub fn new(kind: TokenKind, intern: Intern) -> Self { 24 | Self { kind, intern } 25 | } 26 | } 27 | 28 | #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] 29 | pub enum TokenKind { 30 | Also, 31 | AngleClose, 32 | AngleOpen, 33 | Be, 34 | Colon, 35 | Comma, 36 | Comment, 37 | CurlyClose, 38 | CurlyOpen, 39 | Define, 40 | Dot, 41 | End, 42 | Eq, 43 | Fun, 44 | GreaterEq, 45 | HSpace, 46 | Id, 47 | Int, 48 | LessEq, 49 | Minus, 50 | None, 51 | NotEq, 52 | Of, 53 | Plus, 54 | RoundClose, 55 | RoundOpen, 56 | Star, 57 | // TODO String parts and lex mode stack. Is call stack good enough? 58 | String, 59 | StringEdge, 60 | StringEscape, 61 | StringEscaper, 62 | To, 63 | VSpace, 64 | With, 65 | } 66 | 67 | pub struct Lexer<'a> { 68 | pub cart: &'a mut Cart, 69 | pub tokens: Vec, 70 | } 71 | 72 | impl<'a> Lexer<'a> { 73 | pub fn new(cart: &'a mut Cart) -> Self { 74 | Self { 75 | cart, 76 | tokens: vec![], 77 | } 78 | } 79 | 80 | pub fn lex(&mut self, source: &str) { 81 | self.buffer().clear(); 82 | self.tokens.clear(); 83 | let mut source = source.chars().peekable(); 84 | loop { 85 | match source.peek() { 86 | Some(c) => match c { 87 | ' ' | '\t' => self.hspace(&mut source), 88 | '\n' => { 89 | self.trim(&mut source); 90 | self.push(TokenKind::VSpace); 91 | } 92 | '\r' => { 93 | self.trim(&mut source); 94 | if source.peek() == Some(&'\n') { 95 | self.next(&mut source); 96 | } 97 | self.push(TokenKind::VSpace); 98 | } 99 | '#' => self.comment(&mut source), 100 | '"' => self.string(&mut source), 101 | ':' => self.trim_push(&mut source, TokenKind::Colon), 102 | ',' | ';' => self.trim_push(&mut source, TokenKind::Comma), 103 | '<' => { 104 | self.trim(&mut source); 105 | match source.peek() { 106 | Some('=') => { 107 | self.next(&mut source); 108 | self.push(TokenKind::LessEq); 109 | } 110 | _ => self.push(TokenKind::AngleOpen), 111 | } 112 | } 113 | '>' => { 114 | self.trim(&mut source); 115 | match source.peek() { 116 | Some('=') => { 117 | self.next(&mut source); 118 | self.push(TokenKind::GreaterEq); 119 | } 120 | _ => self.push(TokenKind::AngleClose), 121 | } 122 | } 123 | '{' => self.trim_push(&mut source, TokenKind::CurlyOpen), 124 | '}' => self.trim_push(&mut source, TokenKind::CurlyClose), 125 | '(' => self.trim_push(&mut source, TokenKind::RoundOpen), 126 | ')' => self.trim_push(&mut source, TokenKind::RoundClose), 127 | '.' => self.trim_push(&mut source, TokenKind::Dot), 128 | '=' => { 129 | self.trim(&mut source); 130 | match source.peek() { 131 | Some('=') => { 132 | self.next(&mut source); 133 | self.push(TokenKind::Eq); 134 | } 135 | _ => self.push(TokenKind::Define), 136 | } 137 | } 138 | '!' => { 139 | self.trim(&mut source); 140 | match source.peek() { 141 | Some('=') => { 142 | self.next(&mut source); 143 | self.push(TokenKind::NotEq); 144 | } 145 | _ => {} 146 | } 147 | } 148 | '*' => self.trim_push(&mut source, TokenKind::Star), 149 | '+' => self.trim_push(&mut source, TokenKind::Plus), 150 | '-' | '0'..='9' if self.buffer().is_empty() => self.number(&mut source), 151 | _ => { 152 | self.next(&mut source); 153 | } 154 | }, 155 | None => break, 156 | } 157 | } 158 | self.trim(&mut source); 159 | } 160 | 161 | fn buffer(&mut self) -> &mut String { 162 | &mut self.cart.buffer 163 | } 164 | 165 | fn comment(&mut self, source: &mut Peekable) { 166 | self.trim(source); 167 | loop { 168 | match source.peek() { 169 | Some('\r' | '\n') | None => break, 170 | _ => {} 171 | } 172 | self.next(source); 173 | } 174 | self.push(TokenKind::Comment); 175 | } 176 | 177 | fn hspace(&mut self, source: &mut Peekable) { 178 | self.trim(source); 179 | loop { 180 | match source.peek() { 181 | Some(' ' | '\t') => {} 182 | _ => break, 183 | } 184 | self.next(source); 185 | } 186 | self.push(TokenKind::HSpace); 187 | } 188 | 189 | fn next(&mut self, source: &mut Peekable) -> Option { 190 | let next = source.next(); 191 | if let Some(c) = next { 192 | self.buffer().push(c); 193 | } 194 | next 195 | } 196 | 197 | fn number(&mut self, source: &mut Peekable) { 198 | let negative = *source.peek().unwrap() == '-'; 199 | self.trim(source); 200 | loop { 201 | match source.peek() { 202 | Some('0'..='9') => {} 203 | _ => break, 204 | } 205 | self.next(source); 206 | } 207 | if negative && self.buffer().len() < 2 { 208 | // Disconnected minus. 209 | self.push(TokenKind::Minus); 210 | return; 211 | } 212 | self.push(TokenKind::Int); 213 | } 214 | 215 | fn push(&mut self, kind: TokenKind) { 216 | let val = self.cart.buffer.as_str(); 217 | let intern = self.cart.interner.get_or_intern(val); 218 | self.buffer().clear(); 219 | self.tokens.push(Token::new(kind, intern)); 220 | } 221 | 222 | fn push_maybe(&mut self, kind: TokenKind) { 223 | if !self.buffer().is_empty() { 224 | self.push(kind); 225 | } 226 | } 227 | 228 | fn string(&mut self, source: &mut Peekable) { 229 | self.trim_push(source, TokenKind::StringEdge); 230 | // TODO Better string lexing. 231 | loop { 232 | match source.peek() { 233 | Some('\\') => { 234 | self.push_maybe(TokenKind::String); 235 | self.next(source); 236 | self.push(TokenKind::StringEscaper); 237 | if let Some(_) = source.peek() { 238 | self.next(source); 239 | self.push(TokenKind::StringEscape); 240 | } 241 | } 242 | Some('"') | None => { 243 | self.push_maybe(TokenKind::String); 244 | self.next(source); 245 | break; 246 | } 247 | _ => { 248 | self.next(source); 249 | } 250 | } 251 | } 252 | self.push(TokenKind::StringEdge); 253 | } 254 | 255 | fn trim(&mut self, source: &mut Peekable) { 256 | if !self.buffer().is_empty() { 257 | let kind = match self.buffer().as_str() { 258 | "also" => TokenKind::Also, 259 | "be" => TokenKind::Be, 260 | "end" => TokenKind::End, 261 | "for" => TokenKind::Fun, 262 | "of" => TokenKind::Of, 263 | "to" => TokenKind::To, 264 | "with" => TokenKind::With, 265 | _ => TokenKind::Id, 266 | }; 267 | self.push(kind); 268 | } 269 | self.next(source); 270 | } 271 | 272 | fn trim_push(&mut self, source: &mut Peekable, kind: TokenKind) { 273 | self.trim(source); 274 | self.push(kind); 275 | } 276 | } 277 | -------------------------------------------------------------------------------- /src/link.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Range; 2 | 3 | use crate::{ 4 | tree::{BranchKind, Nod, TreeBuilder}, 5 | Cart, 6 | }; 7 | 8 | pub fn link_modules(cart: &Cart) { 9 | let nodes = TreeBuilder::default(); 10 | // Presume we might add more before types sometime. 11 | fun_name(nodes, cart); 12 | // TODO Find referenced uids. 13 | // TODO Remove unused defs. Validation should happen before removal? 14 | // TODO Build lookup table. 15 | // TODO Flatten type aliases and equivalent types. 16 | // TODO Merge common types into new module, pointing all types there. 17 | // TODO Ensure all type uids in new module are global uids. 18 | } 19 | 20 | fn fun_name(nodes: TreeBuilder, cart: &Cart) { 21 | let types_start = nodes.pos(); 22 | let _ = types_start; 23 | for module in &cart.modules { 24 | let Nod::Branch { range, .. } = module.tree.last().unwrap().nod else { 25 | panic!() 26 | }; 27 | let range: Range = range.into(); 28 | for index in range { 29 | let node = module.tree[index]; 30 | match node.nod { 31 | Nod::Branch { 32 | kind: BranchKind::Types, 33 | range: types_range, 34 | } => { 35 | let _ = types_range; 36 | // TODO Extract each type into `types`. 37 | } 38 | _ => {} 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | collections::HashMap, 3 | fs::{create_dir_all, File}, 4 | io::{BufWriter, Read, Write}, 5 | ops::Index, 6 | path::Path, 7 | sync::Arc, 8 | time::Instant, 9 | }; 10 | 11 | use anyhow::{Error, Result}; 12 | use clap::{Args, Parser, Subcommand, ValueEnum}; 13 | use lasso::ThreadedRodeo; 14 | use lex::{Intern, Interner, Token}; 15 | use link::link_modules; 16 | use norm::{CoreInterns, Normer}; 17 | use run::{CoreExports, Module, Runner}; 18 | use tree::{write_tree, Nod, Node, Nody, TreeBuilder}; 19 | use wasm::write_wasm; 20 | 21 | use crate::lex::Lexer; 22 | 23 | // mod core; 24 | mod lex; 25 | mod link; 26 | mod norm; 27 | mod parse; 28 | mod run; 29 | mod tree; 30 | mod typ; 31 | mod util; 32 | mod wasm; 33 | 34 | #[derive(clap::Parser)] 35 | #[command(about, version, long_about = None)] 36 | struct Cli { 37 | #[command(subcommand)] 38 | command: Commands, 39 | } 40 | 41 | #[derive(Subcommand)] 42 | enum Commands { 43 | Build(BuildArgs), 44 | } 45 | 46 | #[derive(Args)] 47 | pub struct BuildArgs { 48 | app: String, 49 | #[arg(long)] 50 | dump: Vec, 51 | #[arg(long)] 52 | outdir: Option, 53 | #[arg(long)] 54 | time: bool, 55 | } 56 | 57 | #[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd, ValueEnum)] 58 | enum DumpOption { 59 | Trees, 60 | } 61 | 62 | fn main() -> Result<()> { 63 | env_logger::init(); 64 | let cli = Cli::parse(); 65 | match &cli.command { 66 | Commands::Build(args) => run_app(args), 67 | } 68 | } 69 | 70 | pub struct Cart { 71 | pub buffer: String, 72 | pub core_exports: CoreExports, 73 | pub core_interns: CoreInterns, 74 | pub interner: Interner, 75 | pub modules: Vec, 76 | pub module_map: HashMap, 77 | pub tree_builder: TreeBuilder, 78 | } 79 | 80 | fn run_app(args: &BuildArgs) -> Result<()> { 81 | let start = Instant::now(); 82 | // Resources 83 | let interner = Arc::new(ThreadedRodeo::default()); 84 | // Reserve first slot for empty. TODO Reserve others? 85 | interner.get_or_intern(""); 86 | let tree_builder = TreeBuilder::default(); 87 | let cart = Cart { 88 | buffer: String::new(), 89 | core_exports: Default::default(), 90 | core_interns: CoreInterns::new(&interner), 91 | interner: interner.clone(), 92 | modules: vec![], 93 | module_map: HashMap::new(), 94 | tree_builder, 95 | }; 96 | // Process 97 | let mut cart = build(args, "core", cart)?; 98 | cart = build(args, args.app.as_str(), cart)?; 99 | // Link 100 | link_modules(&cart); 101 | let prewasm = start.elapsed(); 102 | // Write 103 | let prewrite = write_wasm(args, &cart, start)?; 104 | // println!("type tree size: {}", std::mem::size_of::()); 105 | if args.time { 106 | println!( 107 | "built from {}: main {:.1?}, wasm {:.1?}, write {:.1?}", 108 | args.app.as_str(), 109 | prewasm, 110 | prewrite, 111 | start.elapsed() 112 | ); 113 | } 114 | Ok(()) 115 | } 116 | 117 | fn build(args: &BuildArgs, name: &str, mut cart: Cart) -> Result { 118 | let interner = cart.interner.clone(); 119 | // Lex 120 | // TODO Reserver lexer somewhere to reuse its resources? 121 | let mut lexer = Lexer::new(&mut cart); 122 | lex(name, &mut lexer)?; 123 | let tokens = lexer.tokens; 124 | // Parse 125 | let (parsed_tree, cart) = parse(cart, &tokens); 126 | dump_tree("parse", args, name, &parsed_tree, interner.as_ref())?; 127 | // Norm 128 | let (mut tree, mut cart) = norm(cart, parsed_tree); 129 | dump_tree("norm", args, name, &tree, interner.as_ref())?; 130 | // Run 131 | // TODO Keep runner to reuse resources, or move them into module? 132 | let runner = Runner::new(&mut cart); 133 | let module = runner.run(interner.get_or_intern(name), &mut tree); 134 | // if name == "core" { 135 | // cart.core_exports = CoreExports::extract(&module, &cart.interner); 136 | // // println!("{:?}", cart.core_exports); 137 | // } 138 | cart.module_map 139 | .insert(module.name, cart.modules.len() as u16 + 1); 140 | cart.modules.push(module); 141 | dump_tree("run", args, name, &tree, interner.as_ref())?; 142 | // Done 143 | Ok(cart) 144 | } 145 | 146 | fn lex(name: &str, lexer: &mut Lexer) -> Result<(), Error> { 147 | match name { 148 | "core" => lexer.lex(include_str!("core.rio")), 149 | _ => { 150 | let mut file = File::open(name)?; 151 | let mut source = String::new(); 152 | file.read_to_string(&mut source)?; 153 | lexer.lex(&source); 154 | } 155 | }; 156 | Ok(()) 157 | } 158 | 159 | fn parse(cart: Cart, tokens: &[Token]) -> (Vec, Cart) { 160 | let mut parser = parse::Parser::new(cart); 161 | parser.parse(tokens); 162 | let mut parsed_tree = Vec::::with_capacity(parser.cart.tree_builder.nodes.len()); 163 | parsed_tree.extend(parser.cart.tree_builder.nodes.iter().map(|n| n.nod())); 164 | (parsed_tree, parser.cart) 165 | } 166 | 167 | fn norm(cart: Cart, parsed_tree: Vec) -> (Vec, Cart) { 168 | let mut tree = Vec::::new(); 169 | let mut normer = Normer::new(cart); 170 | normer.norm(&parsed_tree, &mut tree); 171 | (tree, normer.cart) 172 | } 173 | 174 | fn dump_tree( 175 | stage: &str, 176 | args: &BuildArgs, 177 | name: &str, 178 | tree: &[Node], 179 | map: &Map, 180 | ) -> Result<()> 181 | where 182 | Map: Index, 183 | Node: Nody, 184 | { 185 | if args 186 | .dump 187 | .iter() 188 | .any(|dump| matches!(dump, DumpOption::Trees)) 189 | { 190 | if let Some(outdir) = &args.outdir { 191 | let name = Path::new(name) 192 | .file_stem() 193 | .ok_or(Error::msg("no name"))? 194 | .to_str() 195 | .ok_or(Error::msg("bad name"))?; 196 | let subdir = Path::new(outdir).join(name); 197 | create_dir_all(subdir.clone())?; 198 | let path = subdir.join(format!("{name}.{stage}.txt")); 199 | let file = File::create(path)?; 200 | let mut buf = BufWriter::new(file); 201 | write_tree(&mut buf, &tree, map)?; 202 | writeln!(&mut buf, "")?; 203 | writeln!(&mut buf, "Node size: {}", std::mem::size_of::())?; 204 | writeln!(&mut buf, "Tree len: {}", tree.len())?; 205 | } 206 | } 207 | Ok(()) 208 | } 209 | -------------------------------------------------------------------------------- /src/norm.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Range; 2 | 3 | use crate::{ 4 | lex::{Intern, Interner, Token, TokenKind}, 5 | tree::{BranchKind, Nod, Node, Nody, TreeBuilder, Type}, 6 | Cart, 7 | }; 8 | 9 | pub struct Normer { 10 | pub cart: Cart, 11 | } 12 | 13 | /// Provide easy access for comparing resolutions to core native definitions. 14 | #[derive(Clone, Copy, Debug, Default)] 15 | pub struct CoreInterns { 16 | add: Intern, 17 | eq: Intern, 18 | ge: Intern, 19 | gt: Intern, 20 | le: Intern, 21 | lt: Intern, 22 | ne: Intern, 23 | pair: Intern, 24 | sub: Intern, 25 | } 26 | 27 | impl CoreInterns { 28 | pub fn new(interner: &Interner) -> Self { 29 | Self { 30 | add: interner.get_or_intern("add"), 31 | eq: interner.get_or_intern("eq"), 32 | ge: interner.get_or_intern("ge"), 33 | gt: interner.get_or_intern("gt"), 34 | le: interner.get_or_intern("le"), 35 | lt: interner.get_or_intern("lt"), 36 | ne: interner.get_or_intern("ne"), 37 | pair: interner.get_or_intern("Pair"), 38 | sub: interner.get_or_intern("sub"), 39 | } 40 | } 41 | } 42 | 43 | impl Normer { 44 | pub fn new(cart: Cart) -> Self { 45 | Self { cart } 46 | } 47 | 48 | pub fn norm(&mut self, parsed_tree: &[Nod], tree: &mut Vec) { 49 | self.trim(parsed_tree, tree); 50 | self.rebranch(tree); 51 | self.define(tree); 52 | } 53 | 54 | fn builder(&mut self) -> &mut TreeBuilder { 55 | &mut self.cart.tree_builder 56 | } 57 | 58 | fn define(&mut self, tree: &mut Vec) { 59 | self.builder().clear(); 60 | self.define_at(&tree); 61 | self.builder() 62 | .wrap(BranchKind::Block, 0, Type::default(), 0); 63 | self.builder().drain_into(tree); 64 | } 65 | 66 | fn define_at(&mut self, tree: &[Node]) -> Option<()> { 67 | let node = *tree.last()?; 68 | match node.nod { 69 | Nod::Branch { kind, range, .. } => { 70 | let start = self.builder().pos(); 71 | let range: Range = range.into(); 72 | // Maybe handle some kids in custom fashion. 73 | let range = match kind { 74 | BranchKind::Def => { 75 | let kid = tree[range.start]; 76 | // We can't parse a Def of range len 0. 77 | match kid.nod { 78 | Nod::Branch { 79 | kind: BranchKind::Typed, 80 | range: first_range, 81 | .. 82 | } => { 83 | // Expand typed in place. 84 | let first_range: Range = first_range.into(); 85 | for kid_index in first_range.clone() { 86 | // TODO Why recurse instead of special handling? 87 | self.define_at(&tree[..=kid_index]); 88 | } 89 | range.start + 1..range.end 90 | } 91 | _ => { 92 | // TODO Why recurse instead of special handling? 93 | self.define_at(&tree[..=range.start]); 94 | // Untyped, so push empty type after id. 95 | self.builder().push_none(kid.source); 96 | range.start + 1..range.end 97 | } 98 | } 99 | } 100 | _ => range, 101 | }; 102 | // Loop remaining kids. 103 | for kid_index in range.clone() { 104 | // TODO If we're a params, turn kid Ids to Defs. 105 | self.define_at(&tree[..=kid_index]); 106 | } 107 | // Finalize. 108 | let kind = match kind { 109 | BranchKind::Typed => { 110 | // This typed wasn't the lead of a def, or we'd have handled it in that branch. 111 | // No value, so push empty value after type. 112 | self.builder().push_none(node.source); 113 | // And make a def out of it. 114 | BranchKind::Def 115 | } 116 | _ => kind, 117 | }; 118 | self.builder() 119 | .wrap(kind, start, Type::default(), node.source); 120 | } 121 | _ => self.builder().push(node), 122 | } 123 | Some(()) 124 | } 125 | 126 | fn rebranch(&mut self, tree: &mut Vec) { 127 | self.builder().clear(); 128 | self.rebranch_at(&tree); 129 | self.builder() 130 | .wrap(BranchKind::Block, 0, Type::default(), 0); 131 | self.builder().drain_into(tree); 132 | } 133 | 134 | fn rebranch_at(&mut self, tree: &[Node]) -> Option<()> { 135 | let node = *tree.last()?; 136 | match node.nod { 137 | Nod::Branch { kind, range, .. } => { 138 | let mut kind = kind; 139 | let start = self.builder().pos(); 140 | let mut range: Range = range.into(); 141 | let done = match kind { 142 | BranchKind::Block => { 143 | if range.len() == 1 { 144 | self.rebranch_at(&tree[..=range.start]); 145 | return Some(()); 146 | } else if !range.is_empty() { 147 | if let Nod::Leaf { token } = tree[range.start].nod { 148 | let new_kind = match token.kind { 149 | TokenKind::CurlyOpen | TokenKind::Of => { 150 | // Special handling for struct field punning. 151 | for kid_index in range.start + 1..range.end { 152 | let kid = tree[kid_index]; 153 | match kid.nod { 154 | Nod::Branch { 155 | kind: BranchKind::Def, 156 | .. 157 | } => { 158 | // Already a def, so keep it as is. 159 | self.rebranch_at(&tree[..=kid_index]); 160 | } 161 | _ => { 162 | // See if we have a relevant id to pun. 163 | let id_node = find_id(&tree[..=kid_index]); 164 | if let Some(id_node) = id_node { 165 | // Got an id to work with, so pun it. 166 | let kid_start = self.builder().pos(); 167 | self.builder() 168 | .push_at(id_node, id_node.source); 169 | // self.builder().push_none(kid.source); 170 | self.rebranch_at(&tree[..=kid_index]); 171 | self.builder().wrap( 172 | BranchKind::Def, 173 | kid_start, 174 | Type::default(), 175 | kid.source, 176 | ); 177 | } else { 178 | // Nope, so don't bother. 179 | // TODO Always make defs in structs, but with some blank ("_") id? 180 | self.rebranch_at(&tree[..=kid_index]); 181 | } 182 | } 183 | } 184 | } 185 | self.builder().wrap( 186 | BranchKind::Struct, 187 | start, 188 | Type::default(), 189 | node.source, 190 | ); 191 | return Some(()); 192 | } 193 | TokenKind::With => Some(BranchKind::List), 194 | _ => None, 195 | }; 196 | if let Some(new_kind) = new_kind { 197 | range = range.start + 1..range.end; 198 | kind = new_kind; 199 | } 200 | } 201 | } 202 | false 203 | } 204 | BranchKind::Infix => { 205 | let Nod::Leaf { token: op } = tree[range.start + 1].nod else { 206 | panic!() 207 | }; 208 | (|| { 209 | let (new_kind, intern) = match op.kind { 210 | TokenKind::Dot => (BranchKind::Dot, None), 211 | _ => { 212 | let intern = match op.kind { 213 | TokenKind::AngleClose => self.cart.core_interns.gt, 214 | TokenKind::AngleOpen => self.cart.core_interns.lt, 215 | TokenKind::Eq => self.cart.core_interns.eq, 216 | TokenKind::GreaterEq => self.cart.core_interns.ge, 217 | TokenKind::LessEq => self.cart.core_interns.le, 218 | TokenKind::Minus => self.cart.core_interns.sub, 219 | TokenKind::NotEq => self.cart.core_interns.ne, 220 | TokenKind::Plus => self.cart.core_interns.add, 221 | TokenKind::To => self.cart.core_interns.pair, 222 | _ => return false, 223 | }; 224 | (BranchKind::Call, Some(intern)) 225 | } 226 | }; 227 | if let Some(intern) = intern { 228 | self.builder() 229 | .push_at(Token::new(TokenKind::Id, intern), node.source); 230 | } 231 | self.rebranch_at(&tree[..=range.start]); 232 | if range.len() > 2 { 233 | self.rebranch_at(&tree[..range.end]); 234 | } 235 | self.builder() 236 | .wrap(new_kind, start, Type::default(), node.source); 237 | true 238 | })() 239 | } 240 | _ => false, 241 | }; 242 | if !done { 243 | for kid_index in range.clone() { 244 | self.rebranch_at(&tree[..=kid_index]); 245 | } 246 | self.builder() 247 | .wrap(kind, start, Type::default(), node.source); 248 | } 249 | } 250 | _ => self.builder().push(node), 251 | } 252 | Some(()) 253 | } 254 | 255 | fn trim(&mut self, parsed_tree: &[Nod], tree: &mut Vec) { 256 | self.builder().clear(); 257 | self.trim_at(&parsed_tree, 0); 258 | self.builder() 259 | .wrap(BranchKind::Block, 0, Type::default(), tree.len()); 260 | self.builder().drain_into(tree); 261 | } 262 | 263 | fn trim_at(&mut self, tree: &[Nod], index: usize) -> Option<()> { 264 | let root = *tree.last()?; 265 | match root { 266 | Nod::Branch { 267 | kind: BranchKind::StringParts, 268 | range, 269 | } => { 270 | let range: Range = range.into(); 271 | let buffer = &mut self.cart.buffer; 272 | buffer.clear(); 273 | for kid_index in range.clone() { 274 | if let Nod::Leaf { token } = tree[kid_index].nod() { 275 | match token { 276 | Token { 277 | kind: TokenKind::StringEscape, 278 | intern, 279 | } => { 280 | let value = match self.cart.interner[intern].chars().next().unwrap() 281 | { 282 | 'n' => '\n', 283 | ch => ch, 284 | }; 285 | buffer.push(value); 286 | } 287 | Token { 288 | kind: TokenKind::String, 289 | intern, 290 | } => { 291 | buffer.push_str(&self.cart.interner[intern]); 292 | } 293 | // Skip others. 294 | _ => {} 295 | } 296 | } 297 | } 298 | let intern = self.cart.interner.get_or_intern(&buffer); 299 | buffer.clear(); 300 | self.builder() 301 | .push_at(Token::new(TokenKind::String, intern), tree.len()); 302 | } 303 | Nod::Branch { kind, range, .. } => { 304 | // TODO Change Typed to Def with separate type? 305 | // TODO Change all Def to triples? Quads? Kids with meta lists? 306 | let start = self.builder().pos(); 307 | let range: Range = range.into(); 308 | for kid_index in range.clone() { 309 | self.trim_at(&tree[..=kid_index], kid_index - range.start); 310 | } 311 | self.builder() 312 | .wrap(kind, start, Type::default(), tree.len()); 313 | } 314 | Nod::Leaf { token, .. } => match token.kind { 315 | TokenKind::Colon | TokenKind::Define => { 316 | // Keep binaries in their place. 317 | if index == 0 { 318 | self.builder().push_none(tree.len()); 319 | } 320 | } 321 | TokenKind::Int => { 322 | let _ = self.cart.interner[token.intern].parse().map(|value: i32| { 323 | self.builder().push(Node { 324 | nod: Nod::Int32 { value }, 325 | source: tree.len().into(), 326 | typ: Type(0), 327 | }); 328 | }); 329 | } 330 | TokenKind::Be 331 | | TokenKind::Comma 332 | | TokenKind::Comment 333 | | TokenKind::CurlyClose 334 | | TokenKind::End 335 | | TokenKind::Fun 336 | | TokenKind::HSpace 337 | | TokenKind::RoundClose 338 | | TokenKind::RoundOpen 339 | | TokenKind::Star 340 | | TokenKind::VSpace => {} 341 | _ => self.builder().push_at(token, tree.len()), 342 | }, 343 | _ => todo!(), 344 | } 345 | Some(()) 346 | } 347 | } 348 | 349 | /// Find an id for punning purposes. 350 | fn find_id(tree: &[Node]) -> Option { 351 | let node = *tree.last()?; 352 | match node.nod { 353 | // Dig into dots. 354 | Nod::Branch { 355 | kind: BranchKind::Infix, 356 | range, 357 | } => { 358 | let range: Range = range.into(); 359 | if range.len() > 2 360 | && matches!( 361 | tree[range.end - 2].nod, 362 | Nod::Leaf { 363 | token: Token { 364 | kind: TokenKind::Dot, 365 | .. 366 | } 367 | } 368 | ) 369 | { 370 | find_id(&tree[..range.end]) 371 | } else { 372 | None 373 | } 374 | } 375 | // Simple id. 376 | Nod::Leaf { 377 | token: Token { 378 | kind: TokenKind::Id, 379 | .. 380 | }, 381 | } => Some(node), 382 | _ => None, 383 | } 384 | } 385 | -------------------------------------------------------------------------------- /src/parse.rs: -------------------------------------------------------------------------------- 1 | use std::{iter::Peekable, slice::Iter}; 2 | 3 | use log::debug; 4 | 5 | use crate::{ 6 | lex::{Token, TokenKind}, 7 | tree::{BranchKind, TreeBuilder, Type}, 8 | Cart, 9 | }; 10 | 11 | macro_rules! define_infix { 12 | ($name:ident, $next:ident, $must_space:expr, $pattern:pat $(if $guard:expr)? $(,)?) => { 13 | fn $name(&mut self, source: &mut Tokens) -> Option { 14 | debug!("{}", stringify!($name)); 15 | let start = self.builder().pos(); 16 | let mut skipped = self.$next(source)?; 17 | loop { 18 | let pre_space = self.builder().pos(); 19 | self.skip_h(source); 20 | let did_space = skipped || self.builder().pos() > pre_space; 21 | if ($must_space && !did_space) || !matches!(peek(source)?, $pattern $(if $guard)?) { 22 | debug!("/{}", stringify!($name)); 23 | return Some(did_space); 24 | } 25 | self.advance(source); 26 | self.skip_hv(source); 27 | let maybe_skipped = self.$next(source); 28 | self.wrap(BranchKind::Infix, start); 29 | skipped = maybe_skipped?; 30 | } 31 | } 32 | }; 33 | } 34 | 35 | macro_rules! loop_some { 36 | {$t:tt} => {(|| -> Option<()> { 37 | loop { 38 | $t 39 | } 40 | })()}; 41 | } 42 | 43 | type Tokens<'a> = Peekable>; 44 | 45 | pub struct Parser { 46 | pub cart: Cart, 47 | } 48 | 49 | impl Parser { 50 | pub fn new(cart: Cart) -> Self { 51 | Self { cart } 52 | } 53 | 54 | pub fn parse(&mut self, tokens: &[Token]) { 55 | self.builder().clear(); 56 | let mut source = tokens.iter().peekable(); 57 | self.block_top(&mut source); 58 | self.wrap(BranchKind::Block, 0); 59 | } 60 | 61 | fn builder(&mut self) -> &mut TreeBuilder { 62 | &mut self.cart.tree_builder 63 | } 64 | 65 | fn advance(&mut self, source: &mut Tokens) { 66 | let next = source.next(); 67 | debug!("Advance past {:?}", next); 68 | if let Some(token) = next { 69 | self.builder().push_at(token, 0); 70 | } 71 | } 72 | 73 | define_infix!(add, call_tight, true, TokenKind::Minus | TokenKind::Plus); 74 | 75 | fn atom(&mut self, source: &mut Tokens) -> Option<()> { 76 | debug!("atom"); 77 | self.skip_h(source); 78 | match peek(source)? { 79 | TokenKind::Colon | TokenKind::Comma | TokenKind::VSpace => {} 80 | TokenKind::Be 81 | | TokenKind::CurlyOpen 82 | | TokenKind::Of 83 | | TokenKind::RoundOpen 84 | | TokenKind::With => self.block(source)?, 85 | TokenKind::Fun => self.fun(source)?, 86 | TokenKind::Id => self.advance(source), 87 | TokenKind::StringEdge => self.string(source), 88 | _ => self.advance(source), 89 | } 90 | debug!("/atom"); 91 | Some(()) 92 | } 93 | 94 | fn block(&mut self, source: &mut Tokens) -> Option<()> { 95 | debug!("block"); 96 | let start = self.builder().pos(); 97 | let ender = choose_ender(peek(source)?); 98 | self.advance(source); 99 | self.skip_h(source); 100 | if ender == TokenKind::End && peek(source)? != TokenKind::VSpace { 101 | // Inline be ... 102 | self.call(source, true); 103 | } else { 104 | // Actually wrapped block. 105 | loop_some!({ 106 | self.block_content(source); 107 | let kind = peek(source)?; 108 | if kind != TokenKind::With { 109 | self.advance(source); 110 | } 111 | if kind == ender || (ender == TokenKind::End && kind == TokenKind::With) { 112 | None? 113 | } 114 | }); 115 | } 116 | if self.builder().pos() > start { 117 | self.wrap(BranchKind::Block, start); 118 | } 119 | debug!("/block"); 120 | Some(()) 121 | } 122 | 123 | fn block_content(&mut self, source: &mut Tokens) -> Option<()> { 124 | debug!("block_content"); 125 | loop_some!({ 126 | self.skip_hv(source); 127 | match peek(source)? { 128 | TokenKind::Comma => self.advance(source), 129 | TokenKind::AngleClose 130 | | TokenKind::CurlyClose 131 | | TokenKind::End 132 | | TokenKind::RoundClose 133 | | TokenKind::With => None?, 134 | _ => { 135 | self.def(source); 136 | } 137 | } 138 | }); 139 | debug!("/block_content"); 140 | self.skip_hv(source); 141 | Some(()) 142 | } 143 | 144 | fn block_top(&mut self, source: &mut Tokens) { 145 | let start = self.builder().pos(); 146 | loop_some!({ 147 | debug!("block_top: {:?}", peek(source)); 148 | self.block_content(source)?; 149 | match peek(source)? { 150 | TokenKind::AngleClose 151 | | TokenKind::CurlyClose 152 | | TokenKind::End 153 | | TokenKind::RoundClose => { 154 | // Eat trash. TODO Avoid ever getting here. 155 | self.advance(source); 156 | self.skip_hv(source); 157 | } 158 | TokenKind::With => { 159 | // Also trash, but be nicer. 160 | self.atom(source); 161 | } 162 | _ => {} 163 | } 164 | }); 165 | if self.builder().pos() > start { 166 | self.wrap(BranchKind::Block, start); 167 | } 168 | } 169 | 170 | fn call(&mut self, source: &mut Tokens, allow_block: bool) -> Option<()> { 171 | self.call_maybe_spaced(source, allow_block) 172 | } 173 | 174 | fn call_maybe_spaced(&mut self, source: &mut Tokens, allow_block: bool) -> Option<()> { 175 | debug!("call"); 176 | self.skip_h(source); 177 | let start = self.builder().pos(); 178 | let had_space = self.pair(source)?; 179 | loop { 180 | debug!("call loop: {:?}", peek(source)); 181 | let mut post = self.builder().pos(); 182 | if post <= start { 183 | break; 184 | } 185 | // TODO Can we leaving trailing hspace, or do we need to have an indicator? 186 | let peeked = peek(source)?; 187 | if had_space 188 | || matches!( 189 | peeked, 190 | TokenKind::HSpace | TokenKind::Be | TokenKind::CurlyOpen | TokenKind::With 191 | ) 192 | { 193 | self.skip_h(source); 194 | if !allow_block 195 | && matches!( 196 | peek(source)?, 197 | TokenKind::Be | TokenKind::CurlyOpen | TokenKind::With 198 | ) 199 | { 200 | break; 201 | } 202 | post = self.builder().pos(); 203 | self.spaced(source); 204 | } else { 205 | break; 206 | } 207 | if self.builder().pos() <= post { 208 | // TODO What does this mean??? 209 | break; 210 | } 211 | self.wrap(BranchKind::Call, start); 212 | debug!("/call loop"); 213 | } 214 | debug!("/call"); 215 | Some(()) 216 | } 217 | 218 | fn call_tight(&mut self, source: &mut Tokens) -> Option { 219 | debug!("call_tight"); 220 | let start = self.builder().pos(); 221 | let mut skipped = self.dot(source)?; 222 | loop { 223 | let peeked = peek(source)?; 224 | match peeked { 225 | TokenKind::AngleOpen | TokenKind::RoundOpen if !skipped => { 226 | // Unspaced open brackets bind tightly. 227 | // self.call_maybe_spaced(source, false, false, Some(start)); 228 | // TODO Below instead of `call_maybe_spaced` above. 229 | // TODO Expand paren-comma args. 230 | self.advance(source); 231 | self.block_content(source); 232 | if peek(source)? == choose_ender(peeked) { 233 | self.advance(source); 234 | } 235 | } 236 | _ => { 237 | match peek(source)? { 238 | // Of blocks bind tightly. 239 | TokenKind::Of => { 240 | skipped = self.dot(source)?; 241 | } 242 | _ => break, 243 | } 244 | } 245 | }; 246 | self.wrap(BranchKind::Call, start); 247 | } 248 | debug!("/call_tight"); 249 | Some(skipped) 250 | } 251 | 252 | define_infix!( 253 | compare, 254 | add, 255 | true, 256 | TokenKind::AngleClose 257 | | TokenKind::AngleOpen 258 | | TokenKind::Eq 259 | | TokenKind::GreaterEq 260 | | TokenKind::LessEq 261 | | TokenKind::NotEq, 262 | ); 263 | 264 | fn def(&mut self, source: &mut Tokens) -> Option<()> { 265 | debug!("def"); 266 | self.skip_h(source); 267 | let start = self.builder().pos(); 268 | self.typed(source); 269 | if self.builder().pos() > start { 270 | self.skip_h(source); 271 | if peek(source)? == TokenKind::Define { 272 | self.advance(source); 273 | self.skip_hv(source); 274 | // Right-side descent. 275 | self.def(source); 276 | self.wrap(BranchKind::Def, start); 277 | self.skip_hv(source)?; 278 | } 279 | } 280 | debug!("/def"); 281 | Some(()) 282 | } 283 | 284 | define_infix!(dot, starred, false, TokenKind::Dot,); 285 | 286 | fn fun(&mut self, source: &mut Tokens) -> Option<()> { 287 | debug!("fun"); 288 | let start = self.builder().pos(); 289 | self.advance(source); 290 | self.skip_h(source); 291 | // TODO Type params 292 | // In params 293 | let in_params_start = self.builder().pos(); 294 | let start_kind = peek(source)?; 295 | match start_kind { 296 | TokenKind::CurlyOpen | TokenKind::Id => { 297 | self.atom(source); 298 | self.skip_h(source); 299 | } 300 | // TODO If angle, also try paren afterward. If so, nested funs. 301 | TokenKind::AngleOpen | TokenKind::RoundOpen => { 302 | self.advance(source); 303 | // TODO Call it Params. 304 | self.block_content(source); 305 | if peek(source)? == choose_ender(start_kind) { 306 | self.advance(source); 307 | } 308 | } 309 | _ => return Some(()), 310 | } 311 | self.wrap(BranchKind::Params, in_params_start); 312 | self.skip_h(source); 313 | // Out params 314 | let has_out = peek(source)? == TokenKind::Colon; 315 | if has_out { 316 | self.advance(source); 317 | self.skip_hv(source); 318 | } 319 | let out_params_start = self.builder().pos(); 320 | if has_out { 321 | match peek(source)? { 322 | TokenKind::RoundOpen => { 323 | // Explicit return vars. 324 | self.advance(source); 325 | self.block_content(source); 326 | if peek(source)? == TokenKind::RoundClose { 327 | self.advance(source); 328 | } 329 | } 330 | _ => { 331 | // Implied anonymous return var. 332 | let typed_start = self.builder().pos(); 333 | self.builder().push_none(0); 334 | self.call(source, false); 335 | self.wrap(BranchKind::Typed, typed_start); 336 | } 337 | } 338 | } 339 | self.wrap(BranchKind::Params, out_params_start); 340 | self.skip_h(source); 341 | // Body 342 | self.atom(source); 343 | self.wrap(BranchKind::Fun, start); 344 | debug!("/fun"); 345 | Some(()) 346 | } 347 | 348 | define_infix!(pair, compare, false, TokenKind::To); 349 | 350 | fn skip(&mut self, source: &mut Tokens, skipping: F) -> Option 351 | where 352 | F: Fn(TokenKind) -> bool, 353 | { 354 | let mut skipped = false; 355 | loop { 356 | let token = peek_token(source)?; 357 | if skipping(token.kind) { 358 | debug!("Skipping {:?}", token); 359 | skipped = true; 360 | source.next(); 361 | self.builder().push_at(token, 0); 362 | } else { 363 | break; 364 | } 365 | } 366 | Some(skipped) 367 | } 368 | 369 | fn skip_h(&mut self, source: &mut Tokens) -> Option { 370 | self.skip(source, |kind| { 371 | matches!(kind, TokenKind::Comment | TokenKind::HSpace) 372 | }) 373 | } 374 | 375 | fn skip_hv(&mut self, source: &mut Tokens) -> Option { 376 | self.skip(source, |kind| { 377 | matches!( 378 | kind, 379 | TokenKind::Comment | TokenKind::HSpace | TokenKind::VSpace 380 | ) 381 | }) 382 | } 383 | 384 | fn spaced(&mut self, source: &mut Tokens) -> Option<()> { 385 | loop { 386 | self.skip_h(source); 387 | let next = peek(source)?; 388 | debug!("spaced: {next:?}"); 389 | match next { 390 | TokenKind::AngleClose 391 | | TokenKind::Comma 392 | | TokenKind::Colon 393 | | TokenKind::CurlyClose 394 | | TokenKind::Define 395 | | TokenKind::End 396 | | TokenKind::RoundClose 397 | | TokenKind::VSpace => break, 398 | _ => self.pair(source), 399 | }; 400 | debug!("/spaced"); 401 | } 402 | Some(()) 403 | } 404 | 405 | fn starred(&mut self, source: &mut Tokens) -> Option { 406 | debug!("starred"); 407 | let start = self.builder().pos(); 408 | self.atom(source); 409 | if peek(source)? == TokenKind::Star { 410 | self.advance(source); 411 | self.wrap(BranchKind::Pub, start); 412 | } 413 | debug!("/starred"); 414 | Some(false) 415 | } 416 | 417 | fn string(&mut self, source: &mut Peekable>) { 418 | debug!("string"); 419 | let start = self.builder().pos(); 420 | self.advance(source); 421 | loop_some!({ 422 | let next = peek(source)?; 423 | self.advance(source); 424 | if next == TokenKind::StringEdge { 425 | None?; 426 | } 427 | }); 428 | self.wrap(BranchKind::StringParts, start); 429 | debug!("/string"); 430 | } 431 | 432 | fn typed(&mut self, source: &mut Tokens) -> Option<()> { 433 | debug!("typed"); 434 | self.skip_h(source); 435 | let start = self.builder().pos(); 436 | self.call(source, true); 437 | self.skip_h(source); 438 | loop { 439 | debug!("typed loop: {:?}", peek(source)?); 440 | if peek(source)? != TokenKind::Colon { 441 | break; 442 | } 443 | self.advance(source); 444 | self.skip_hv(source); 445 | self.call(source, false); 446 | self.wrap(BranchKind::Typed, start); 447 | } 448 | debug!("/typed"); 449 | Some(()) 450 | } 451 | 452 | fn wrap(&mut self, kind: BranchKind, start: u32) { 453 | self.builder().wrap(kind, start, Type::default(), 0); 454 | } 455 | } 456 | 457 | fn choose_ender(token_kind: TokenKind) -> TokenKind { 458 | match token_kind { 459 | TokenKind::AngleOpen => TokenKind::AngleClose, 460 | TokenKind::Be | TokenKind::Of | TokenKind::With => TokenKind::End, 461 | TokenKind::CurlyOpen => TokenKind::CurlyClose, 462 | TokenKind::RoundOpen => TokenKind::RoundClose, 463 | _ => panic!(), 464 | } 465 | } 466 | 467 | fn peek(source: &mut Tokens) -> Option { 468 | source.peek().map(|it| it.kind) 469 | } 470 | 471 | fn peek_token(source: &mut Tokens) -> Option { 472 | source.peek().copied().copied() 473 | } 474 | -------------------------------------------------------------------------------- /src/util.rs: -------------------------------------------------------------------------------- 1 | use std::{collections::HashMap, hash::Hash}; 2 | 3 | pub struct MultiMap 4 | where 5 | K: Copy + Hash + Eq + Ord, 6 | V: MultiMapEntry, 7 | { 8 | pub map: HashMap, 9 | // Single vector to limit allocations. 10 | pub values: Vec, 11 | } 12 | 13 | pub trait MultiMapEntry { 14 | fn key(&self) -> K; 15 | } 16 | 17 | impl MultiMap 18 | where 19 | K: Copy + Hash + Eq + Ord, 20 | V: MultiMapEntry, 21 | { 22 | pub fn new() -> Self { 23 | Self { 24 | map: HashMap::new(), 25 | values: vec![], 26 | } 27 | } 28 | 29 | pub fn get<'a>(&'a self, key: K) -> MultiMapIterator<'a, K, V> { 30 | match self.map.get(&key) { 31 | Some(index) => MultiMapIterator { 32 | index: *index as usize, 33 | key: key.clone(), 34 | values: &self.values, 35 | }, 36 | None => MultiMapIterator { 37 | index: 0, 38 | key: key.clone(), 39 | values: &[], 40 | }, 41 | } 42 | } 43 | 44 | pub fn update(&mut self, sort_map: bool) { 45 | if sort_map { 46 | self.values.sort_by_key(|value| value.key()) 47 | } 48 | self.map.clear(); 49 | let Some(first) = self.values.first() else { 50 | return; 51 | }; 52 | let mut last_key = first.key().clone(); 53 | self.map.insert(last_key, 0); 54 | for (index, value) in self.values.iter().enumerate().skip(1) { 55 | let key = value.key(); 56 | if key != last_key { 57 | self.map.insert(key, index as u32); 58 | last_key = key; 59 | } 60 | } 61 | } 62 | } 63 | 64 | pub struct MultiMapIterator<'a, K, V> { 65 | index: usize, 66 | key: K, 67 | values: &'a [V], 68 | } 69 | 70 | impl<'a, K, V> Iterator for MultiMapIterator<'a, K, V> 71 | where 72 | K: Copy + Hash + Eq + Ord, 73 | V: MultiMapEntry, 74 | { 75 | type Item = &'a V; 76 | 77 | fn next(&mut self) -> Option { 78 | let value = self.values.get(self.index)?; 79 | if value.key() == self.key { 80 | self.index += 1; 81 | Some(value) 82 | } else { 83 | None 84 | } 85 | } 86 | } 87 | --------------------------------------------------------------------------------