From 066e5d03e0bf422575c6dafb28d835d764c0f005 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Thu, 16 Dec 2021 18:23:02 +0000 Subject: [PATCH] ??? --- .gitignore | 1 + Cargo.lock | 557 ++++++++++++++++++++++++++++++ Cargo.toml | 14 + build.rs | 6 + schemes.md | 22 ++ src/grammar.lalrpop | 33 ++ src/grammar.rs | 767 ++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 146 ++++++++ test/fail/l.scm | 1 + test/pass/math.scm | 1 + test/pass/real-i0.scm | 6 + 11 files changed, 1554 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 build.rs create mode 100644 schemes.md create mode 100644 src/grammar.lalrpop create mode 100644 src/grammar.rs create mode 100644 src/main.rs create mode 100644 test/fail/l.scm create mode 100644 test/pass/math.scm create mode 100644 test/pass/real-i0.scm diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..2ae1a50 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,557 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" +dependencies = [ + "const-random", +] + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "ascii-canvas" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +dependencies = [ + "term", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "beef" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bed554bd50246729a1ec158d08aa3235d1b69d94ad120ebe187e28894787e736" + +[[package]] +name = "bit-set" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chumsky" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75efcada9a5471698704a9518888b76c7f363a086357f86671d7c84d54671eb1" +dependencies = [ + "ahash", +] + +[[package]] +name = "const-random" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f590d95d011aa80b063ffe3253422ed5aa462af4e9867d43ce8337562bac77c4" +dependencies = [ + "const-random-macro", + "proc-macro-hack", +] + +[[package]] +name = "const-random-macro" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "615f6e27d000a2bffbc7f2f6a8669179378fa27ee4d0a509e985dfc0a7defb40" +dependencies = [ + "getrandom", + "lazy_static", + "proc-macro-hack", + "tiny-keccak", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "diff" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "ena" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7402b94a93c24e742487327a7cd839dc9d36fec9de9fb25b09f2dae459f36c3" +dependencies = [ + "log", +] + +[[package]] +name = "fixedbitset" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "handball" +version = "0.1.0" +dependencies = [ + "chumsky", + "lalrpop", + "lalrpop-util", + "logos", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "indexmap" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "itertools" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" +dependencies = [ + "either", +] + +[[package]] +name = "lalrpop" +version = "0.19.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15174f1c529af5bf1283c3bc0058266b483a67156f79589fab2a25e23cf8988" +dependencies = [ + "ascii-canvas", + "atty", + "bit-set", + "diff", + "ena", + "itertools", + "lalrpop-util", + "petgraph", + "pico-args", + "regex", + "regex-syntax", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", +] + +[[package]] +name = "lalrpop-util" +version = "0.19.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e58cce361efcc90ba8a0a5f982c741ff86b603495bb15a998412e957dcd278" +dependencies = [ + "regex", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119" + +[[package]] +name = "lock_api" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "logos" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427e2abca5be13136da9afdbf874e6b34ad9001dd70f2b103b083a85daa7b345" +dependencies = [ + "logos-derive", +] + +[[package]] +name = "logos-derive" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56a7d287fd2ac3f75b11f19a1c8a874a7d55744bd91f7a1b3e7cf87d4343c36d" +dependencies = [ + "beef", + "fnv", + "proc-macro2", + "quote", + "regex-syntax", + "syn", + "utf8-ranges", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + +[[package]] +name = "petgraph" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pico-args" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "proc-macro-hack" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" + +[[package]] +name = "proc-macro2" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +dependencies = [ + "getrandom", + "redox_syscall", +] + +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "rustversion" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "siphasher" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" + +[[package]] +name = "smallvec" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" + +[[package]] +name = "string_cache" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "923f0f39b6267d37d23ce71ae7235602134b250ace715dd2c90421998ddac0c6" +dependencies = [ + "lazy_static", + "new_debug_unreachable", + "parking_lot", + "phf_shared", + "precomputed-hash", +] + +[[package]] +name = "syn" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "utf8-ranges" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a14c188 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "handball" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +chumsky = "0.6.0" +lalrpop-util = "0.19.6" +logos = "0.12.0" + +[build-dependencies] +lalrpop = "0.19.6" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..228a429 --- /dev/null +++ b/build.rs @@ -0,0 +1,6 @@ +fn main() { + lalrpop::Configuration::new() + .generate_in_source_tree() + .process() + .unwrap(); +} diff --git a/schemes.md b/schemes.md new file mode 100644 index 0000000..e0b7191 --- /dev/null +++ b/schemes.md @@ -0,0 +1,22 @@ +chicken +guile + +https://small.r7rs.org/wiki/ImplementationSupport/ + + +chezscheme ✔ gambit-scheme ✔ mit-scheme ✔ scheme48 ✔ +chibi-scheme ✔ gerbil-scheme ✔ sagittarius-scheme ✔ sisc-scheme ✔ + + +csi (GOOD) +guile + +chez +chibi-scheme + +/usr/local/Cellar/gambit-scheme/4.9.3_2/v4.9.3/bin/gsi +gxi +mit-scheme (GOOD) +sash +scheme48 (GOOD) +sisc-scheme (GOOD) \ No newline at end of file diff --git a/src/grammar.lalrpop b/src/grammar.lalrpop new file mode 100644 index 0000000..ce98100 --- /dev/null +++ b/src/grammar.lalrpop @@ -0,0 +1,33 @@ +use crate::{Token, Tree, Val}; + + +grammar<'s>(); + + +pub(crate) Trees = Tree*; + +Tree: Tree<'s> = { + "(" ")" => Tree::Branch(<>), + Val => Tree::Leaf(<>) + +} + +Val: Val<'s> = { + "@int" => Val::Int(<>), + "@float" => Val::Float(<>), + "@id" => Val::Ident(<>), +} + + +extern { + type Location = usize; + type Error = crate::LexError; + + enum Token<'s> { + "(" => Token::Lparen, + ")" => Token::Rparen, + "@id" => Token::Ident(<&'s str>), + "@int" => Token::Int(), + "@float" => Token::Float(), + } +} \ No newline at end of file diff --git a/src/grammar.rs b/src/grammar.rs new file mode 100644 index 0000000..4d9370f --- /dev/null +++ b/src/grammar.rs @@ -0,0 +1,767 @@ +// auto-generated: "lalrpop 0.19.6" +// sha3: b4e129326576b92bdcb244ce79862d1fd8d25830fd43a283867e772251d1f229 +use crate::{Token, Tree, Val}; +#[allow(unused_extern_crates)] +extern crate lalrpop_util as __lalrpop_util; +#[allow(unused_imports)] +use self::__lalrpop_util::state_machine as __state_machine; +extern crate core; +extern crate alloc; + +#[cfg_attr(rustfmt, rustfmt_skip)] +mod __parse__Trees { + #![allow(non_snake_case, non_camel_case_types, unused_mut, unused_variables, unused_imports, unused_parens)] + + use crate::{Token, Tree, Val}; + #[allow(unused_extern_crates)] + extern crate lalrpop_util as __lalrpop_util; + #[allow(unused_imports)] + use self::__lalrpop_util::state_machine as __state_machine; + extern crate core; + extern crate alloc; + use super::__ToTriple; + #[allow(dead_code)] + pub(crate) enum __Symbol<'s> + { + Variant0(Token<'s>), + Variant1(f64), + Variant2(&'s str), + Variant3(i64), + Variant4(Tree<'s>), + Variant5(alloc::vec::Vec>), + Variant6(Val<'s>), + } + const __ACTION: &[i8] = &[ + // State 0 + 3, 0, 7, 8, 9, + // State 1 + 3, -8, 7, 8, 9, + // State 2 + 3, -7, 7, 8, 9, + // State 3 + -5, -5, -5, -5, -5, + // State 4 + 0, 0, 0, 0, 0, + // State 5 + -2, -2, -2, -2, -2, + // State 6 + -10, -10, -10, -10, -10, + // State 7 + -11, -11, -11, -11, -11, + // State 8 + -9, -9, -9, -9, -9, + // State 9 + -6, -6, -6, -6, -6, + // State 10 + 0, 12, 0, 0, 0, + // State 11 + -1, -1, -1, -1, -1, + ]; + fn __action(state: i8, integer: usize) -> i8 { + __ACTION[(state as usize) * 5 + integer] + } + const __EOF_ACTION: &[i8] = &[ + // State 0 + -7, + // State 1 + -8, + // State 2 + 0, + // State 3 + -5, + // State 4 + -12, + // State 5 + -2, + // State 6 + -10, + // State 7 + -11, + // State 8 + -9, + // State 9 + -6, + // State 10 + 0, + // State 11 + -1, + ]; + fn __goto(state: i8, nt: usize) -> i8 { + match nt { + 0 => match state { + 1 => 9, + _ => 3, + }, + 2 => 1, + 3 => match state { + 2 => 10, + _ => 4, + }, + 4 => 5, + _ => 0, + } + } + fn __expected_tokens(__state: i8) -> alloc::vec::Vec { + const __TERMINAL: &[&str] = &[ + r###""(""###, + r###"")""###, + r###""@float""###, + r###""@id""###, + r###""@int""###, + ]; + __TERMINAL.iter().enumerate().filter_map(|(index, terminal)| { + let next_state = __action(__state, index); + if next_state == 0 { + None + } else { + Some(alloc::string::ToString::to_string(terminal)) + } + }).collect() + } + pub(crate) struct __StateMachine<'s> + where + { + __phantom: core::marker::PhantomData<(&'s ())>, + } + impl<'s> __state_machine::ParserDefinition for __StateMachine<'s> + where + { + type Location = usize; + type Error = crate::LexError; + type Token = Token<'s>; + type TokenIndex = usize; + type Symbol = __Symbol<'s>; + type Success = alloc::vec::Vec>; + type StateIndex = i8; + type Action = i8; + type ReduceIndex = i8; + type NonterminalIndex = usize; + + #[inline] + fn start_location(&self) -> Self::Location { + Default::default() + } + + #[inline] + fn start_state(&self) -> Self::StateIndex { + 0 + } + + #[inline] + fn token_to_index(&self, token: &Self::Token) -> Option { + __token_to_integer(token, core::marker::PhantomData::<(&())>) + } + + #[inline] + fn action(&self, state: i8, integer: usize) -> i8 { + __action(state, integer) + } + + #[inline] + fn error_action(&self, state: i8) -> i8 { + __action(state, 5 - 1) + } + + #[inline] + fn eof_action(&self, state: i8) -> i8 { + __EOF_ACTION[state as usize] + } + + #[inline] + fn goto(&self, state: i8, nt: usize) -> i8 { + __goto(state, nt) + } + + fn token_to_symbol(&self, token_index: usize, token: Self::Token) -> Self::Symbol { + __token_to_symbol(token_index, token, core::marker::PhantomData::<(&())>) + } + + fn expected_tokens(&self, state: i8) -> alloc::vec::Vec { + __expected_tokens(state) + } + + #[inline] + fn uses_error_recovery(&self) -> bool { + false + } + + #[inline] + fn error_recovery_symbol( + &self, + recovery: __state_machine::ErrorRecovery, + ) -> Self::Symbol { + panic!("error recovery not enabled for this grammar") + } + + fn reduce( + &mut self, + action: i8, + start_location: Option<&Self::Location>, + states: &mut alloc::vec::Vec, + symbols: &mut alloc::vec::Vec<__state_machine::SymbolTriple>, + ) -> Option<__state_machine::ParseResult> { + __reduce( + action, + start_location, + states, + symbols, + core::marker::PhantomData::<(&())>, + ) + } + + fn simulate_reduce(&self, action: i8) -> __state_machine::SimulatedReduce { + panic!("error recovery not enabled for this grammar") + } + } + fn __token_to_integer< + 's, + >( + __token: &Token<'s>, + _: core::marker::PhantomData<(&'s ())>, + ) -> Option + { + match *__token { + Token::Lparen if true => Some(0), + Token::Rparen if true => Some(1), + Token::Float(_) if true => Some(2), + Token::Ident(_) if true => Some(3), + Token::Int(_) if true => Some(4), + _ => None, + } + } + fn __token_to_symbol< + 's, + >( + __token_index: usize, + __token: Token<'s>, + _: core::marker::PhantomData<(&'s ())>, + ) -> __Symbol<'s> + { + match __token_index { + 0 | 1 => __Symbol::Variant0(__token), + 2 => match __token { + Token::Float(__tok0) if true => __Symbol::Variant1(__tok0), + _ => unreachable!(), + }, + 3 => match __token { + Token::Ident(__tok0) if true => __Symbol::Variant2(__tok0), + _ => unreachable!(), + }, + 4 => match __token { + Token::Int(__tok0) if true => __Symbol::Variant3(__tok0), + _ => unreachable!(), + }, + _ => unreachable!(), + } + } + pub(crate) struct TreesParser { + _priv: (), + } + + impl TreesParser { + pub(crate) fn new() -> TreesParser { + TreesParser { + _priv: (), + } + } + + #[allow(dead_code)] + pub(crate) fn parse< + 's, + __TOKEN: __ToTriple<'s, >, + __TOKENS: IntoIterator, + >( + &self, + __tokens0: __TOKENS, + ) -> Result>, __lalrpop_util::ParseError, crate::LexError>> + { + let __tokens = __tokens0.into_iter(); + let mut __tokens = __tokens.map(|t| __ToTriple::to_triple(t)); + __state_machine::Parser::drive( + __StateMachine { + __phantom: core::marker::PhantomData::<(&())>, + }, + __tokens, + ) + } + } + pub(crate) fn __reduce< + 's, + >( + __action: i8, + __lookahead_start: Option<&usize>, + __states: &mut alloc::vec::Vec, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)>, + _: core::marker::PhantomData<(&'s ())>, + ) -> Option>,__lalrpop_util::ParseError, crate::LexError>>> + { + let (__pop_states, __nonterminal) = match __action { + 0 => { + __reduce0(__lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 1 => { + __reduce1(__lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 2 => { + __reduce2(__lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 3 => { + __reduce3(__lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 4 => { + __reduce4(__lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 5 => { + __reduce5(__lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 6 => { + __reduce6(__lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 7 => { + __reduce7(__lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 8 => { + __reduce8(__lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 9 => { + __reduce9(__lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 10 => { + __reduce10(__lookahead_start, __symbols, core::marker::PhantomData::<(&())>) + } + 11 => { + // __Trees = Trees => ActionFn(0); + let __sym0 = __pop_Variant5(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action0::<>(__sym0); + return Some(Ok(__nt)); + } + _ => panic!("invalid action code {}", __action) + }; + let __states_len = __states.len(); + __states.truncate(__states_len - __pop_states); + let __state = *__states.last().unwrap(); + let __next_state = __goto(__state, __nonterminal); + __states.push(__next_state); + None + } + #[inline(never)] + fn __symbol_type_mismatch() -> ! { + panic!("symbol type mismatch") + } + fn __pop_Variant0< + 's, + >( + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)> + ) -> (usize, Token<'s>, usize) + { + match __symbols.pop() { + Some((__l, __Symbol::Variant0(__v), __r)) => (__l, __v, __r), + _ => __symbol_type_mismatch() + } + } + fn __pop_Variant4< + 's, + >( + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)> + ) -> (usize, Tree<'s>, usize) + { + match __symbols.pop() { + Some((__l, __Symbol::Variant4(__v), __r)) => (__l, __v, __r), + _ => __symbol_type_mismatch() + } + } + fn __pop_Variant6< + 's, + >( + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)> + ) -> (usize, Val<'s>, usize) + { + match __symbols.pop() { + Some((__l, __Symbol::Variant6(__v), __r)) => (__l, __v, __r), + _ => __symbol_type_mismatch() + } + } + fn __pop_Variant5< + 's, + >( + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)> + ) -> (usize, alloc::vec::Vec>, usize) + { + match __symbols.pop() { + Some((__l, __Symbol::Variant5(__v), __r)) => (__l, __v, __r), + _ => __symbol_type_mismatch() + } + } + fn __pop_Variant1< + 's, + >( + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)> + ) -> (usize, f64, usize) + { + match __symbols.pop() { + Some((__l, __Symbol::Variant1(__v), __r)) => (__l, __v, __r), + _ => __symbol_type_mismatch() + } + } + fn __pop_Variant3< + 's, + >( + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)> + ) -> (usize, i64, usize) + { + match __symbols.pop() { + Some((__l, __Symbol::Variant3(__v), __r)) => (__l, __v, __r), + _ => __symbol_type_mismatch() + } + } + fn __pop_Variant2< + 's, + >( + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)> + ) -> (usize, &'s str, usize) + { + match __symbols.pop() { + Some((__l, __Symbol::Variant2(__v), __r)) => (__l, __v, __r), + _ => __symbol_type_mismatch() + } + } + pub(crate) fn __reduce0< + 's, + >( + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)>, + _: core::marker::PhantomData<(&'s ())>, + ) -> (usize, usize) + { + // Tree = "(", Trees, ")" => ActionFn(2); + assert!(__symbols.len() >= 3); + let __sym2 = __pop_Variant0(__symbols); + let __sym1 = __pop_Variant5(__symbols); + let __sym0 = __pop_Variant0(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym2.2.clone(); + let __nt = super::__action2::<>(__sym0, __sym1, __sym2); + __symbols.push((__start, __Symbol::Variant4(__nt), __end)); + (3, 0) + } + pub(crate) fn __reduce1< + 's, + >( + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)>, + _: core::marker::PhantomData<(&'s ())>, + ) -> (usize, usize) + { + // Tree = Val => ActionFn(3); + let __sym0 = __pop_Variant6(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action3::<>(__sym0); + __symbols.push((__start, __Symbol::Variant4(__nt), __end)); + (1, 0) + } + pub(crate) fn __reduce2< + 's, + >( + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)>, + _: core::marker::PhantomData<(&'s ())>, + ) -> (usize, usize) + { + // Tree* = => ActionFn(7); + let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); + let __end = __start.clone(); + let __nt = super::__action7::<>(&__start, &__end); + __symbols.push((__start, __Symbol::Variant5(__nt), __end)); + (0, 1) + } + pub(crate) fn __reduce3< + 's, + >( + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)>, + _: core::marker::PhantomData<(&'s ())>, + ) -> (usize, usize) + { + // Tree* = Tree+ => ActionFn(8); + let __sym0 = __pop_Variant5(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action8::<>(__sym0); + __symbols.push((__start, __Symbol::Variant5(__nt), __end)); + (1, 1) + } + pub(crate) fn __reduce4< + 's, + >( + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)>, + _: core::marker::PhantomData<(&'s ())>, + ) -> (usize, usize) + { + // Tree+ = Tree => ActionFn(9); + let __sym0 = __pop_Variant4(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action9::<>(__sym0); + __symbols.push((__start, __Symbol::Variant5(__nt), __end)); + (1, 2) + } + pub(crate) fn __reduce5< + 's, + >( + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)>, + _: core::marker::PhantomData<(&'s ())>, + ) -> (usize, usize) + { + // Tree+ = Tree+, Tree => ActionFn(10); + assert!(__symbols.len() >= 2); + let __sym1 = __pop_Variant4(__symbols); + let __sym0 = __pop_Variant5(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym1.2.clone(); + let __nt = super::__action10::<>(__sym0, __sym1); + __symbols.push((__start, __Symbol::Variant5(__nt), __end)); + (2, 2) + } + pub(crate) fn __reduce6< + 's, + >( + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)>, + _: core::marker::PhantomData<(&'s ())>, + ) -> (usize, usize) + { + // Trees = => ActionFn(11); + let __start = __lookahead_start.cloned().or_else(|| __symbols.last().map(|s| s.2.clone())).unwrap_or_default(); + let __end = __start.clone(); + let __nt = super::__action11::<>(&__start, &__end); + __symbols.push((__start, __Symbol::Variant5(__nt), __end)); + (0, 3) + } + pub(crate) fn __reduce7< + 's, + >( + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)>, + _: core::marker::PhantomData<(&'s ())>, + ) -> (usize, usize) + { + // Trees = Tree+ => ActionFn(12); + let __sym0 = __pop_Variant5(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action12::<>(__sym0); + __symbols.push((__start, __Symbol::Variant5(__nt), __end)); + (1, 3) + } + pub(crate) fn __reduce8< + 's, + >( + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)>, + _: core::marker::PhantomData<(&'s ())>, + ) -> (usize, usize) + { + // Val = "@int" => ActionFn(4); + let __sym0 = __pop_Variant3(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action4::<>(__sym0); + __symbols.push((__start, __Symbol::Variant6(__nt), __end)); + (1, 4) + } + pub(crate) fn __reduce9< + 's, + >( + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)>, + _: core::marker::PhantomData<(&'s ())>, + ) -> (usize, usize) + { + // Val = "@float" => ActionFn(5); + let __sym0 = __pop_Variant1(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action5::<>(__sym0); + __symbols.push((__start, __Symbol::Variant6(__nt), __end)); + (1, 4) + } + pub(crate) fn __reduce10< + 's, + >( + __lookahead_start: Option<&usize>, + __symbols: &mut alloc::vec::Vec<(usize,__Symbol<'s>,usize)>, + _: core::marker::PhantomData<(&'s ())>, + ) -> (usize, usize) + { + // Val = "@id" => ActionFn(6); + let __sym0 = __pop_Variant2(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::__action6::<>(__sym0); + __symbols.push((__start, __Symbol::Variant6(__nt), __end)); + (1, 4) + } +} +pub(crate) use self::__parse__Trees::TreesParser; + +fn __action0< + 's, +>( + (_, __0, _): (usize, alloc::vec::Vec>, usize), +) -> alloc::vec::Vec> +{ + __0 +} + +fn __action1< + 's, +>( + (_, __0, _): (usize, alloc::vec::Vec>, usize), +) -> alloc::vec::Vec> +{ + __0 +} + +fn __action2< + 's, +>( + (_, _, _): (usize, Token<'s>, usize), + (_, __0, _): (usize, alloc::vec::Vec>, usize), + (_, _, _): (usize, Token<'s>, usize), +) -> Tree<'s> +{ + Tree::Branch(__0) +} + +fn __action3< + 's, +>( + (_, __0, _): (usize, Val<'s>, usize), +) -> Tree<'s> +{ + Tree::Leaf(__0) +} + +fn __action4< + 's, +>( + (_, __0, _): (usize, i64, usize), +) -> Val<'s> +{ + Val::Int(__0) +} + +fn __action5< + 's, +>( + (_, __0, _): (usize, f64, usize), +) -> Val<'s> +{ + Val::Float(__0) +} + +fn __action6< + 's, +>( + (_, __0, _): (usize, &'s str, usize), +) -> Val<'s> +{ + Val::Ident(__0) +} + +fn __action7< + 's, +>( + __lookbehind: &usize, + __lookahead: &usize, +) -> alloc::vec::Vec> +{ + alloc::vec![] +} + +fn __action8< + 's, +>( + (_, v, _): (usize, alloc::vec::Vec>, usize), +) -> alloc::vec::Vec> +{ + v +} + +fn __action9< + 's, +>( + (_, __0, _): (usize, Tree<'s>, usize), +) -> alloc::vec::Vec> +{ + alloc::vec![__0] +} + +fn __action10< + 's, +>( + (_, v, _): (usize, alloc::vec::Vec>, usize), + (_, e, _): (usize, Tree<'s>, usize), +) -> alloc::vec::Vec> +{ + { let mut v = v; v.push(e); v } +} + +fn __action11< + 's, +>( + __lookbehind: &usize, + __lookahead: &usize, +) -> alloc::vec::Vec> +{ + let __start0 = __lookbehind.clone(); + let __end0 = __lookahead.clone(); + let __temp0 = __action7( + &__start0, + &__end0, + ); + let __temp0 = (__start0, __temp0, __end0); + __action1( + __temp0, + ) +} + +fn __action12< + 's, +>( + __0: (usize, alloc::vec::Vec>, usize), +) -> alloc::vec::Vec> +{ + let __start0 = __0.0.clone(); + let __end0 = __0.2.clone(); + let __temp0 = __action8( + __0, + ); + let __temp0 = (__start0, __temp0, __end0); + __action1( + __temp0, + ) +} + +pub trait __ToTriple<'s, > { + fn to_triple(value: Self) -> Result<(usize,Token<'s>,usize), __lalrpop_util::ParseError, crate::LexError>>; +} + +impl<'s, > __ToTriple<'s, > for (usize, Token<'s>, usize) { + fn to_triple(value: Self) -> Result<(usize,Token<'s>,usize), __lalrpop_util::ParseError, crate::LexError>> { + Ok(value) + } +} +impl<'s, > __ToTriple<'s, > for Result<(usize, Token<'s>, usize), crate::LexError> { + fn to_triple(value: Self) -> Result<(usize,Token<'s>,usize), __lalrpop_util::ParseError, crate::LexError>> { + match value { + Ok(v) => Ok(v), + Err(error) => Err(__lalrpop_util::ParseError::User { error }), + } + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..02a19c4 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,146 @@ +use logos::Logos; + +mod grammar; + +#[derive(Logos, Debug, PartialEq)] +enum LogosToken { + #[regex(r"[0-9]+", priority = 2)] + Int, + + #[regex(r"[0-9]+(\\.[0-9]+)?")] + Float, + + #[regex(r"[A-Za-z0-9!$%&*+\-./:<=>?@^_~]+")] + Ident, + + #[error] + #[regex(r"[ \t\n\f]+", logos::skip)] + Error, + + #[token(r"(")] + Lparen, + + #[token(r")")] + Rparen, +} +#[derive(Debug)] +pub struct LexError; + +type Spanned = Result<(Loc, Tok, Loc), Error>; + +struct Lexer<'a>(logos::Lexer<'a, LogosToken>); + +impl<'a> Lexer<'a> { + fn new(src: &'a str) -> Self { + Self(LogosToken::lexer(src)) + } +} + +#[derive(Clone, Debug)] +pub enum Token<'s> { + Int(i64), + Float(f64), + Ident(&'s str), + Lparen, + Rparen, +} + +impl<'a> Iterator for Lexer<'a> { + type Item = Spanned, usize, LexError>; + + fn next(&mut self) -> Option { + let kind = self.0.next()?; + let span = self.0.span(); + let text = self.0.slice(); + + let t = match kind { + LogosToken::Int => Token::Int(text.parse().unwrap()), + LogosToken::Float => Token::Float(text.parse().unwrap()), + LogosToken::Ident => Token::Ident(text), + LogosToken::Lparen => Token::Lparen, + LogosToken::Rparen => Token::Rparen, + LogosToken::Error => return Some(Err(LexError)), + }; + + Some(Ok((span.start, t, span.end))) + } +} + +#[derive(Clone, Debug)] +pub enum Tree<'s> { + Leaf(Val<'s>), + Branch(Vec>), +} + +#[derive(Clone, Debug)] +pub enum Val<'s> { + Int(i64), + Float(f64), + Ident(&'s str), +} + +enum Func {} + +enum RVal { + Func(Func), + Num(f64), +} + +enum Op { + Push(RVal), + Call(u8), + Print, +} + +fn comp_to(t: &Tree) + +fn eval(t: &Tree<'_>) -> f64 { + match t { + Tree::Leaf(Val::Ident(_)) => panic!("Need number got {:?}", t), + Tree::Leaf(Val::Float(f)) => *f, + Tree::Leaf(Val::Int(i)) => *i as f64, + Tree::Branch(v) => { + if let Tree::Leaf(Val::Ident(f)) = v[0] { + match f { + "min" => v[1..].iter().map(eval).reduce(f64::min).unwrap(), + "max" => v[1..].iter().map(eval).reduce(f64::max).unwrap(), + "+" => v[1..].iter().map(eval).sum(), + "*" => v[1..].iter().map(eval).product(), + "/" => eval(&v[1]) / v[2..].iter().map(eval).product::(), + "-" => eval(&v[1]) - v[2..].iter().map(eval).sum::(), + _ => panic!("Unknown func {:?}", f), + } + } else { + panic!("Not a function") + } + } + } +} + +fn main() { + let src = std::fs::read_to_string(std::env::args().nth(1).unwrap()).unwrap(); + + let tree = grammar::TreesParser::new().parse(Lexer::new(&src)); + + let t = dbg!(tree).unwrap(); + + dbg!(eval(&t[0])); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn math_exprs() { + fn test(s: &str, v: f64) { + let tree = grammar::TreesParser::new().parse(Lexer::new(s)).unwrap(); + assert_eq!(tree.len(), 1); + assert_eq!(eval(&tree[0]), v); + } + + test("1", 1.0); + test("(+ 1 2)", 3.0); + test("(+ 1 2 (/ 2 3 4 5))", 3.033333333333333); + } +} diff --git a/test/fail/l.scm b/test/fail/l.scm new file mode 100644 index 0000000..59312f4 --- /dev/null +++ b/test/fail/l.scm @@ -0,0 +1 @@ +((()) \ No newline at end of file diff --git a/test/pass/math.scm b/test/pass/math.scm new file mode 100644 index 0000000..593de37 --- /dev/null +++ b/test/pass/math.scm @@ -0,0 +1 @@ +(+ 1 2 (/ 2 3 4 5)) \ No newline at end of file diff --git a/test/pass/real-i0.scm b/test/pass/real-i0.scm new file mode 100644 index 0000000..c722861 --- /dev/null +++ b/test/pass/real-i0.scm @@ -0,0 +1,6 @@ +(display (real? 2.5+0.0i)) +(newline) +(display (real? 2.5+0i)) +(newline) + +;; Chicken semantics seem nicer \ No newline at end of file