diff --git a/Cargo.lock b/Cargo.lock index 964cdf7..22ee2f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -28,9 +28,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" dependencies = [ "anstyle", "anstyle-parse", @@ -43,43 +43,44 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" dependencies = [ "windows-sys", ] [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" dependencies = [ "anstyle", + "once_cell_polyfill", "windows-sys", ] [[package]] name = "assert_cmd" -version = "2.0.16" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1835b7f27878de8525dc71410b5a31cdcc5f230aed5ba5df968e09c201b23d" +checksum = "2bd389a4b2970a01282ee455294913c0a43724daedcd1a24c3eb0ec1c1320b66" dependencies = [ "anstyle", "bstr", @@ -91,12 +92,6 @@ dependencies = [ "wait-timeout", ] -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - [[package]] name = "backtrace" version = "0.3.74" @@ -129,9 +124,9 @@ checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "bstr" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786a307d683a5bf92e6fd5fd69a7eb613751668d1d8d67d802846dfe367c62c8" +checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" dependencies = [ "memchr", "regex-automata", @@ -146,9 +141,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.23" +version = "4.5.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +checksum = "ed87a9d530bb41a67537289bafcac159cb3ee28460e0a4571123d2a778a6a882" dependencies = [ "clap_builder", "clap_derive", @@ -156,9 +151,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.23" +version = "4.5.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +checksum = "64f4f3f3c77c94aff3c7e9aac9a2ca1974a5adf392a8bb751e827d6d127ab966" dependencies = [ "anstream", "anstyle", @@ -168,9 +163,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491" dependencies = [ "heck", "proc-macro2", @@ -180,21 +175,21 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "console" -version = "0.15.10" +version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" dependencies = [ "encode_unicode", "libc", @@ -222,9 +217,9 @@ checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" @@ -345,9 +340,9 @@ checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" [[package]] name = "heck" @@ -357,9 +352,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "indexmap" -version = "2.7.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", "hashbrown", @@ -367,13 +362,12 @@ dependencies = [ [[package]] name = "insta" -version = "1.41.1" +version = "1.43.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9ffc4d4892617c50a928c52b2961cb5174b6fc6ebf252b2fac9d21955c48b8" +checksum = "154934ea70c58054b556dd430b99a98c2a7ff5309ac9891597e339b5c28f4371" dependencies = [ "console", - "lazy_static", - "linked-hash-map", + "once_cell", "serde", "similar", ] @@ -391,10 +385,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +name = "lexer" +version = "0.1.0" +dependencies = [ + "insta", + "miette", + "rstest", +] [[package]] name = "libc" @@ -402,12 +399,6 @@ version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - [[package]] name = "linux-raw-sys" version = "0.4.14" @@ -421,7 +412,9 @@ dependencies = [ "assert_cmd", "clap", "insta", + "lexer", "miette", + "parser", "rstest", ] @@ -482,9 +475,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.2" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" [[package]] name = "owo-colors" @@ -492,11 +491,20 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb37767f6569cd834a413442455e0f066d0d522de8630436e2a1761d9726ba56" +[[package]] +name = "parser" +version = "0.1.0" +dependencies = [ + "insta", + "lexer", + "rstest", +] + [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -533,9 +541,9 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" dependencies = [ "toml_edit", ] @@ -653,24 +661,24 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.24" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", @@ -679,18 +687,15 @@ dependencies = [ [[package]] name = "similar" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" [[package]] name = "slab" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" [[package]] name = "strsim" @@ -778,15 +783,15 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" [[package]] name = "toml_edit" -version = "0.22.22" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "toml_datetime", @@ -819,9 +824,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "wait-timeout" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" dependencies = [ "libc", ] @@ -901,9 +906,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.20" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 91f988d..8d58a72 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,9 @@ -[package] -name = "loxide" +[workspace] +resolver = "3" +members = ["crates/lexer", "./", "crates/parser", "crates/loxide"] + + +[workspace.package] version = "0.1.0" authors = ["Rob Hand <146272+sinon@users.noreply.github.com>"] edition = "2024" @@ -9,15 +13,17 @@ keywords = ["rust", "lox", "interpreter"] homepage = "https://github.com/sinon/loxide" repository = "https://github.com/sinon/loxide" -[dependencies] -clap = { version = "4.5.23", features = ["derive"] } +[workspace.dependencies] miette = { version = "7.4.0", features = ["fancy"] } - -[dev-dependencies] rstest = "0.23.0" assert_cmd = "2.0.14" insta = { version = "1.41.1", features = ["yaml"] } +# [dependencies] +# clap = { version = "4.5.23", features = ["derive"] } +# miette = { version = "7.4.0", features = ["fancy"] } + + [profile.dev.package] insta.opt-level = 3 similar.opt-level = 3 diff --git a/crates/lexer/Cargo.toml b/crates/lexer/Cargo.toml new file mode 100644 index 0000000..8d1b3fb --- /dev/null +++ b/crates/lexer/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "lexer" +version = "0.1.0" +edition = "2024" + +[dependencies] +miette = { workspace = true } + + +[dev-dependencies] +rstest = "0.23.0" +insta = { version = "1.41.1", features = ["yaml"] } diff --git a/src/lexer.rs b/crates/lexer/src/lib.rs similarity index 97% rename from src/lexer.rs rename to crates/lexer/src/lib.rs index 66089e6..cfd2e7c 100644 --- a/src/lexer.rs +++ b/crates/lexer/src/lib.rs @@ -1,8 +1,9 @@ //! Lexer //! //! Responsible for transforming a given input str into a Iterator of `Result` +#![allow(clippy::too_many_lines)] -use std::{fmt, process::ExitCode}; +use std::fmt; use miette::{Error, LabeledSpan, Result, miette}; @@ -12,7 +13,7 @@ pub struct Token<'de> { /// The `TokenType` of `Token` pub token_type: TokenType, /// The text reference from the source code - pub origin: &'de str, + pub origin: &'de str, // TODO: Replace this with Span to avoid the lifetime /// The line number where the token was parsed from pub line: usize, } @@ -140,20 +141,6 @@ impl<'de> Lexer<'de> { at_eof: false, } } - /// Start lexing on `Lexer` used by `tokenize` command. - pub fn tokenize_lex(&mut self) -> ExitCode { - let mut exit_code = 0; - for t in self { - match t { - Ok(token) => println!("{token}"), - Err(e) => { - eprintln!("{e}"); - exit_code = 65; - } - } - } - ExitCode::from(exit_code) - } fn match_reserved_word(c_str: &str) -> TokenType { match c_str { "and" => TokenType::And, diff --git a/tests/lexer_test.rs b/crates/lexer/tests/lexer_test.rs similarity index 98% rename from tests/lexer_test.rs rename to crates/lexer/tests/lexer_test.rs index 6b10125..086a22c 100644 --- a/tests/lexer_test.rs +++ b/crates/lexer/tests/lexer_test.rs @@ -1,5 +1,5 @@ use insta::assert_yaml_snapshot; -use loxide::lexer::{Lexer, Token}; +use lexer::{Lexer, Token}; use miette::Error; use std::fmt::Write; diff --git a/tests/snapshots/lexer_test__empty_handling.snap b/crates/lexer/tests/snapshots/lexer_test__empty_handling.snap similarity index 100% rename from tests/snapshots/lexer_test__empty_handling.snap rename to crates/lexer/tests/snapshots/lexer_test__empty_handling.snap diff --git a/tests/snapshots/lexer_test__identifiers.snap b/crates/lexer/tests/snapshots/lexer_test__identifiers.snap similarity index 100% rename from tests/snapshots/lexer_test__identifiers.snap rename to crates/lexer/tests/snapshots/lexer_test__identifiers.snap diff --git a/tests/snapshots/lexer_test__keywords.snap b/crates/lexer/tests/snapshots/lexer_test__keywords.snap similarity index 100% rename from tests/snapshots/lexer_test__keywords.snap rename to crates/lexer/tests/snapshots/lexer_test__keywords.snap diff --git a/tests/snapshots/lexer_test__numbers.snap b/crates/lexer/tests/snapshots/lexer_test__numbers.snap similarity index 100% rename from tests/snapshots/lexer_test__numbers.snap rename to crates/lexer/tests/snapshots/lexer_test__numbers.snap diff --git a/tests/snapshots/lexer_test__punctuators.snap b/crates/lexer/tests/snapshots/lexer_test__punctuators.snap similarity index 100% rename from tests/snapshots/lexer_test__punctuators.snap rename to crates/lexer/tests/snapshots/lexer_test__punctuators.snap diff --git a/tests/snapshots/lexer_test__strings.snap b/crates/lexer/tests/snapshots/lexer_test__strings.snap similarity index 100% rename from tests/snapshots/lexer_test__strings.snap rename to crates/lexer/tests/snapshots/lexer_test__strings.snap diff --git a/tests/snapshots/lexer_test__whitespace.snap b/crates/lexer/tests/snapshots/lexer_test__whitespace.snap similarity index 100% rename from tests/snapshots/lexer_test__whitespace.snap rename to crates/lexer/tests/snapshots/lexer_test__whitespace.snap diff --git a/crates/loxide/Cargo.toml b/crates/loxide/Cargo.toml new file mode 100644 index 0000000..dcc12ab --- /dev/null +++ b/crates/loxide/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "loxide" +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +keywords.workspace = true +homepage.workspace = true +repository.workspace = true + +[dependencies] +clap = { version = "4.5.23", features = ["derive"] } +lexer = { path = "../lexer" } +parser = { path = "../parser" } +miette = { workspace = true } + +[dev-dependencies] +rstest = "0.23.0" +assert_cmd = "2.0.14" +insta = { version = "1.41.1", features = ["yaml"] } diff --git a/src/builtins.rs b/crates/loxide/src/builtins.rs similarity index 100% rename from src/builtins.rs rename to crates/loxide/src/builtins.rs diff --git a/src/interpreter.rs b/crates/loxide/src/interpreter.rs similarity index 93% rename from src/interpreter.rs rename to crates/loxide/src/interpreter.rs index 76e5903..c8643d7 100644 --- a/src/interpreter.rs +++ b/crates/loxide/src/interpreter.rs @@ -5,12 +5,9 @@ use std::{cell::RefCell, collections::HashMap, fmt, rc::Rc}; -use crate::{ - builtins, - lexer::{Token, TokenType}, - parser::{Expr, LiteralAtom, Parser, Stmt}, - value::EvaluatedValue, -}; +use crate::{builtins, value::EvaluatedValue}; +use lexer::{Token, TokenType}; +use parser::{Expr, LiteralAtom, Parser, Stmt}; /// `NativeFunction` is used to represent builtin native functions #[derive(Clone)] @@ -30,7 +27,7 @@ impl fmt::Debug for NativeFunction { } impl NativeFunction { - fn arity(&self, _interpreter: &Interpreter) -> u8 { + const fn arity(&self, _interpreter: &Interpreter) -> u8 { self.arity } fn call( @@ -54,10 +51,11 @@ pub struct LoxFunction<'de> { } impl<'de> LoxFunction<'de> { + #[allow(dead_code)] fn arity(&self) -> u8 { u8::try_from(self.parameters.len()).expect("arity < 255 is enforced by parser") } - + #[allow(dead_code)] fn call( &self, interpreter: &mut Interpreter<'de>, @@ -67,7 +65,7 @@ impl<'de> LoxFunction<'de> { .parameters .iter() .zip(args.iter()) - .map(|(param, arg)| (param.origin.clone(), (Some(arg.clone()),))) + .map(|(param, arg)| (param.origin, (Some(arg.clone()),))) .collect(); let saved_env = interpreter.environment.clone(); let block = Stmt::Block(self.body.clone()); @@ -128,17 +126,16 @@ impl<'de> Environment<'de> { self.data.insert(key, value.clone()); Ok(()) } - None => match &self.enclosing { - Some(parent) => { + None => { + if let Some(parent) = &self.enclosing { let mut p = parent.borrow_mut(); p.assign(key, value)?; Ok(()) - } - None => { + } else { self.data.insert(key, value.clone()); Ok(()) } - }, + } } } fn var_assign(&mut self, key: &'de str, value: &EvaluatedValue) { @@ -177,10 +174,10 @@ impl<'de> Interpreter<'de> { } pub(crate) fn get_lox_fn(&self, id: u64) -> &LoxFunction { - match self.lox_functions.get(&id) { - Some(func) => func, - None => panic!("# TODO Improve error handling for `get_lox_fn`",), - } + self.lox_functions.get(&id).map_or_else( + || panic!("# TODO Improve error handling for `get_lox_fn`",), + |func| func, + ) } const fn alloc_id(&mut self) -> u64 { self.counter += 1; @@ -268,10 +265,10 @@ fn evaluate_statement<'de>( }; interpreter.lox_functions.insert(func_id, lox_fun); interpreter.environment.assign( - &name.origin, + name.origin, &EvaluatedValue::LoxFunction { name: name.to_string(), - func_id: func_id, + func_id, }, )?; // interpreter.globals.data.insert(&name.to_string(), lox_fun); @@ -472,12 +469,18 @@ fn evaluate_expression<'de>( } match &callee_fn { - EvaluatedValue::NativeFunction(f) => f.call(interpreter, &args), - EvaluatedValue::LoxFunction { func_id, .. } => { - let f = interpreter.get_lox_fn(*func_id); - // todo!("Fix lifetime issue with f.call") + EvaluatedValue::NativeFunction(f) => { + if f.arity(interpreter) as usize != args.len() { + eprintln!("Expected {} arguments but got {}.", f.arity, args.len()); + return Err("Incorrect arity".to_string()); + } f.call(interpreter, &args) } + EvaluatedValue::LoxFunction { func_id, .. } => { + let _ = interpreter.get_lox_fn(*func_id); + todo!("Fix lifetime issue with f.call") + // f.call(interpreter, &args) + } _ => Err("not callable".to_string()), } } diff --git a/src/lib.rs b/crates/loxide/src/lib.rs similarity index 82% rename from src/lib.rs rename to crates/loxide/src/lib.rs index d57be5b..248b449 100644 --- a/src/lib.rs +++ b/crates/loxide/src/lib.rs @@ -8,9 +8,5 @@ #![allow(clippy::too_many_lines)] #![warn(missing_docs)] mod builtins; -pub mod eval; -pub mod eval_parser; pub mod interpreter; -pub mod lexer; -mod parser; mod value; diff --git a/crates/loxide/src/main.rs b/crates/loxide/src/main.rs new file mode 100644 index 0000000..2f75227 --- /dev/null +++ b/crates/loxide/src/main.rs @@ -0,0 +1,41 @@ +use clap::Subcommand; +use loxide::interpreter::Interpreter; +use miette::{IntoDiagnostic, Result, WrapErr}; +use std::fs; +use std::path::PathBuf; +use std::process::ExitCode; + +use clap::Parser as ClapParser; + +#[derive(ClapParser, Debug)] +#[command(version, about, long_about = None)] +struct Args { + #[command(subcommand)] + commands: Commands, +} +#[derive(Subcommand, Debug)] +enum Commands { + Run { filename: PathBuf }, +} + +fn main() -> Result { + let args = Args::parse(); + match args.commands { + Commands::Run { filename } => { + let input = fs::read_to_string(filename) + .into_diagnostic() + .wrap_err_with(|| "reading file".to_string())?; + let mut exit_code = 0; + for res in Interpreter::new(&input) { + match res { + Ok(()) => {} + Err(err_code) => { + exit_code = err_code; + break; + } + } + } + Ok(ExitCode::from(exit_code)) + } + } +} diff --git a/src/value.rs b/crates/loxide/src/value.rs similarity index 100% rename from src/value.rs rename to crates/loxide/src/value.rs diff --git a/tests/fixtures/evaluate.lox b/crates/loxide/tests/fixtures/evaluate.lox similarity index 100% rename from tests/fixtures/evaluate.lox rename to crates/loxide/tests/fixtures/evaluate.lox diff --git a/tests/fixtures/evaluate_error.lox b/crates/loxide/tests/fixtures/evaluate_error.lox similarity index 100% rename from tests/fixtures/evaluate_error.lox rename to crates/loxide/tests/fixtures/evaluate_error.lox diff --git a/tests/fixtures/lexer.lox b/crates/loxide/tests/fixtures/lexer.lox similarity index 100% rename from tests/fixtures/lexer.lox rename to crates/loxide/tests/fixtures/lexer.lox diff --git a/tests/fixtures/lexer_error.lox b/crates/loxide/tests/fixtures/lexer_error.lox similarity index 100% rename from tests/fixtures/lexer_error.lox rename to crates/loxide/tests/fixtures/lexer_error.lox diff --git a/tests/fixtures/parser.lox b/crates/loxide/tests/fixtures/parser.lox similarity index 100% rename from tests/fixtures/parser.lox rename to crates/loxide/tests/fixtures/parser.lox diff --git a/tests/fixtures/parser_error.lox b/crates/loxide/tests/fixtures/parser_error.lox similarity index 100% rename from tests/fixtures/parser_error.lox rename to crates/loxide/tests/fixtures/parser_error.lox diff --git a/tests/fixtures/run.lox b/crates/loxide/tests/fixtures/run.lox similarity index 100% rename from tests/fixtures/run.lox rename to crates/loxide/tests/fixtures/run.lox diff --git a/tests/fixtures/run_error.lox b/crates/loxide/tests/fixtures/run_error.lox similarity index 100% rename from tests/fixtures/run_error.lox rename to crates/loxide/tests/fixtures/run_error.lox diff --git a/tests/fixtures/run_error_illegal_call.lox b/crates/loxide/tests/fixtures/run_error_illegal_call.lox similarity index 100% rename from tests/fixtures/run_error_illegal_call.lox rename to crates/loxide/tests/fixtures/run_error_illegal_call.lox diff --git a/tests/fixtures/run_error_incorrect_arity.lox b/crates/loxide/tests/fixtures/run_error_incorrect_arity.lox similarity index 100% rename from tests/fixtures/run_error_incorrect_arity.lox rename to crates/loxide/tests/fixtures/run_error_incorrect_arity.lox diff --git a/tests/fixtures/run_error_must_be_a_number.lox b/crates/loxide/tests/fixtures/run_error_must_be_a_number.lox similarity index 100% rename from tests/fixtures/run_error_must_be_a_number.lox rename to crates/loxide/tests/fixtures/run_error_must_be_a_number.lox diff --git a/tests/fixtures/run_error_undefined_var.lox b/crates/loxide/tests/fixtures/run_error_undefined_var.lox similarity index 100% rename from tests/fixtures/run_error_undefined_var.lox rename to crates/loxide/tests/fixtures/run_error_undefined_var.lox diff --git a/tests/fixtures/run_error_var.lox b/crates/loxide/tests/fixtures/run_error_var.lox similarity index 100% rename from tests/fixtures/run_error_var.lox rename to crates/loxide/tests/fixtures/run_error_var.lox diff --git a/tests/fixtures/run_error_var_assign.lox b/crates/loxide/tests/fixtures/run_error_var_assign.lox similarity index 100% rename from tests/fixtures/run_error_var_assign.lox rename to crates/loxide/tests/fixtures/run_error_var_assign.lox diff --git a/tests/fixtures/run_for.lox b/crates/loxide/tests/fixtures/run_for.lox similarity index 100% rename from tests/fixtures/run_for.lox rename to crates/loxide/tests/fixtures/run_for.lox diff --git a/tests/fixtures/run_if.lox b/crates/loxide/tests/fixtures/run_if.lox similarity index 100% rename from tests/fixtures/run_if.lox rename to crates/loxide/tests/fixtures/run_if.lox diff --git a/tests/fixtures/run_logical.lox b/crates/loxide/tests/fixtures/run_logical.lox similarity index 100% rename from tests/fixtures/run_logical.lox rename to crates/loxide/tests/fixtures/run_logical.lox diff --git a/tests/fixtures/run_while.lox b/crates/loxide/tests/fixtures/run_while.lox similarity index 100% rename from tests/fixtures/run_while.lox rename to crates/loxide/tests/fixtures/run_while.lox diff --git a/crates/loxide/tests/main_test.rs b/crates/loxide/tests/main_test.rs new file mode 100644 index 0000000..42b4a05 --- /dev/null +++ b/crates/loxide/tests/main_test.rs @@ -0,0 +1,116 @@ +use assert_cmd::Command; +use rstest::rstest; + +#[test] +fn test_cli_version() { + Command::cargo_bin("loxide") + .unwrap() + .arg("--version") + .assert() + .success() + .code(0) + .stdout("loxide 0.1.0\n".to_string()) + .stderr(""); + + Command::cargo_bin("loxide") + .unwrap() + .arg("-V") + .assert() + .success() + .code(0) + .stdout("loxide 0.1.0\n".to_string()) + .stderr(""); +} + +#[test] +fn test_run_no_file() { + Command::cargo_bin("loxide") + .unwrap() + .arg("run") + .arg("text.lox") + .assert() + .failure() + .code(1); +} + +#[rstest] +#[case("run", "true\ntrue\ntrue\nthe expression below is invalid\n3\nsomething\ntrue\ntrue\ntrue\nfalse\nnil\nnil\n98\n98\nbefore\nafter\nafter\nbefore +inner world\nouter baz\nglobal quz\nouter world\nouter baz\nglobal quz\nglobal world\nglobal baz\nglobal quz\n", )] +#[case( + "run_if", + "bar\nblock body\ntrue\nadult\neligible for voting: true\nif\nelse\n" +)] +#[case( + "run_logical", + "baz\nbaz\nworld\nbar\nbar\n41\n41\ntrue\nfalse\nfalse\ntrue\nfalse\ntrue\n" +)] +#[case( + "run_while", + "1\n2\n3\n0\n1\n2\nProduct of numbers 1 to 5: \n120\n0\n1\n1\n2\n3\n5\n8\n13\n21\n34\n" +)] +#[case("run_for", "1\n2\n3\n0\n1\n2\n0\n1\n0\n1\n0\n-1\nafter\n0\n")] +fn test_run_with_file(#[case] file_name: &str, #[case] expected_stdout: &str) { + let path = format!("tests/fixtures/{file_name}.lox"); + Command::cargo_bin("loxide") + .unwrap() + .arg("run") + .arg(path) + .assert() + .success() + .code(0) + .stdout(expected_stdout.to_string()); +} + +#[rstest] +#[case("run_error", "Operand must be a number.\n[line 1]\n", "", 70)] +#[case("run_error_var", "Undefined variable 'x'.\n", "", 70)] +#[case( + "run_error_var_assign", + "[line 1] Error at \';\': Expect expression.\n", + "", + 65 +)] +#[case( + "run_error_undefined_var", + "Undefined variable `quz`.\n[line 17]\n", + "modified foo\ninner quz\nmodified foo\nouter quz\n", + 70 +)] +#[case( + "run_error_must_be_a_number", + "Operand must be a number.\n[line 1]\n", + "", + 70 +)] +// TODO: Re-enable these test cases when +// #[case( +// "run_error_illegal_call", +// "Can only call function and classes.\n", +// "", +// 70 +// )] +// #[case( +// "run_error_incorrect_arity", +// "Expected 0 arguments but got 3.\n", +// "", +// 70 +// )] +fn test_run_with_file_error( + #[case] file_name: &str, + #[case] expected_err: &str, + #[case] expected_stdout: &str, + #[case] expected_code: i32, +) { + let err = expected_err.to_string(); + let out = expected_stdout.to_string(); + let path = format!("tests/fixtures/{file_name}.lox"); + Command::cargo_bin("loxide") + .unwrap() + .arg("run") + .arg(path) + .assert() + .failure() + .code(expected_code) + .stderr(err) + .stdout(out); +} diff --git a/crates/parser/Cargo.toml b/crates/parser/Cargo.toml new file mode 100644 index 0000000..fa05b58 --- /dev/null +++ b/crates/parser/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "parser" +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +keywords.workspace = true +homepage.workspace = true +repository.workspace = true + +[dependencies] +lexer = { path = "../lexer" } + + +[dev-dependencies] +rstest = "0.23.0" +insta = { version = "1.41.1", features = ["yaml"] } diff --git a/src/parser.rs b/crates/parser/src/lib.rs similarity index 99% rename from src/parser.rs rename to crates/parser/src/lib.rs index b9effc5..1c95951 100644 --- a/src/parser.rs +++ b/crates/parser/src/lib.rs @@ -4,7 +4,7 @@ //! //! Uses a recursive desecent parser. To transform the token stream into //! `Expr` -use crate::lexer::{Lexer, Token, TokenType}; +use lexer::{Lexer, Token, TokenType}; /// `Parser` is responsible for iterating over the token stream from `Lexer` /// and converting the lexed `Token` into `Expr` which represent an Abstract Syntax Tree (AST) diff --git a/tests/eval_parser_test.rs b/crates/parser/tests/eval_parser_test.rs similarity index 56% rename from tests/eval_parser_test.rs rename to crates/parser/tests/eval_parser_test.rs index 02b9c6f..fcf0245 100644 --- a/tests/eval_parser_test.rs +++ b/crates/parser/tests/eval_parser_test.rs @@ -1,5 +1,5 @@ use insta::assert_snapshot; -use loxide::eval_parser::Parser; +use parser::Parser; use rstest::*; macro_rules! set_snapshot_suffix { @@ -13,47 +13,47 @@ macro_rules! set_snapshot_suffix { } #[rstest] -#[case("true")] -#[case("false")] -#[case("nil")] +#[case("true;")] +#[case("false;")] +#[case("nil;")] fn test_parser_literals(#[case] input: &str) { set_snapshot_suffix!("{}", input); - let exprs: Vec = Parser::new(input) - .take_while(std::result::Result::is_ok) + let stmts: Vec = Parser::new(input) + .take_while(|_| true) .map(|e| match e { - Ok(exp) => format!("{exp}"), + Ok(stmt) => format!("{stmt:?}"), Err(_) => String::new(), }) .collect(); - assert_snapshot!(exprs.join("\n")); + assert_snapshot!(stmts.join("\n")); } #[rstest] -#[case("(\"foo\")")] -#[case("(1)")] -#[case("((true))")] +#[case("(\"foo\");")] +#[case("(1);")] +#[case("((true));")] fn test_parser_parentheses(#[case] input: &str) { set_snapshot_suffix!("{}", input); - let exprs: Vec = Parser::new(input) - .take_while(std::result::Result::is_ok) + let stmts: Vec = Parser::new(input) + .take_while(|_| true) .map(|e| match e { - Ok(exp) => format!("{exp}"), + Ok(exp) => format!("{exp:?}"), Err(_) => String::new(), }) .collect(); - assert_snapshot!(exprs.join("\n")); + assert_snapshot!(stmts.join("\n")); } #[rstest] -#[case("!true")] -#[case("!false")] -#[case("-10")] +#[case("!true;")] +#[case("!false;")] +#[case("-10;")] fn test_parser_unary(#[case] input: &str) { set_snapshot_suffix!("{}", input); - let exprs: Vec = Parser::new(input) - .take_while(std::result::Result::is_ok) + let stmts: Vec = Parser::new(input) + .take_while(|_| true) .map(|e| match e { - Ok(exp) => format!("{exp}"), + Ok(exp) => format!("{exp:?}"), Err(_) => String::new(), }) .collect(); @@ -61,68 +61,68 @@ fn test_parser_unary(#[case] input: &str) { description => input, // the template source code omit_expression => true // do not include the default expression }, { - assert_snapshot!(exprs.join("\n")); + assert_snapshot!(stmts.join("\n")); }); } #[rstest] -#[case("16 * 38 / 58")] -#[case("52 + 80 - 94")] +#[case("16 * 38 / 58;")] +#[case("52 + 80 - 94;")] fn test_parser_arimethic(#[case] input: &str) { set_snapshot_suffix!("{}", input); - let exprs: Vec = Parser::new(input) - .take_while(std::result::Result::is_ok) + let stmts: Vec = Parser::new(input) + .take_while(|_| true) .map(|e| match e { - Ok(exp) => format!("{exp}"), + Ok(exp) => format!("{exp:?}"), Err(_) => String::new(), }) .collect(); - assert_snapshot!(exprs.join("\n")); + assert_snapshot!(stmts.join("\n")); } #[rstest] -#[case("83 < 99 > 115")] -#[case("52 <= 80 >= 94")] +#[case("83 < 99 > 115;")] +#[case("52 <= 80 >= 94;")] fn test_parser_comparison(#[case] input: &str) { set_snapshot_suffix!("{}", input); - let exprs: Vec = Parser::new(input) - .take_while(std::result::Result::is_ok) + let stmts: Vec = Parser::new(input) + .take_while(|_| true) .map(|e| match e { - Ok(exp) => format!("{exp}"), + Ok(stmt) => format!("{stmt:?}"), Err(_) => String::new(), }) .collect(); insta::with_settings!({ description => input, // the template source code - omit_expression => true // do not include the default expression + omit_expression => true // do not include the default stmtession }, { - assert_snapshot!(exprs.join("\n")); + assert_snapshot!(stmts.join("\n")); }); } #[rstest] -#[case("\"baz\" == \"baz\"")] -#[case("10 != 9")] +#[case("\"baz\" == \"baz\";")] +#[case("10 != 9;")] fn test_parser_equality(#[case] input: &str) { set_snapshot_suffix!("{}", input); - let exprs: Vec = Parser::new(input) - .take_while(std::result::Result::is_ok) + let stmts: Vec = Parser::new(input) + .take_while(|_| true) .map(|e| match e { - Ok(exp) => format!("{exp}"), + Ok(exp) => format!("{exp:?}"), Err(_) => String::new(), }) .collect(); - assert_snapshot!(exprs.join("\n")); + assert_snapshot!(stmts.join("\n")); } #[rstest] -#[case("(72 +)")] -#[case("\"foo")] +#[case("(72 +);")] +#[case("\"foo;")] fn test_parser_error(#[case] input: &str) { set_snapshot_suffix!("{}", input); - for expr in Parser::new(input) { - match expr { + for stmt in Parser::new(input) { + match stmt { Ok(_) => todo!(), Err(err) => { assert_snapshot!(err); diff --git a/crates/parser/tests/snapshots/eval_parser_test__parser_arimethic@16 * 38 __ 58;.snap b/crates/parser/tests/snapshots/eval_parser_test__parser_arimethic@16 * 38 __ 58;.snap new file mode 100644 index 0000000..53b79b3 --- /dev/null +++ b/crates/parser/tests/snapshots/eval_parser_test__parser_arimethic@16 * 38 __ 58;.snap @@ -0,0 +1,5 @@ +--- +source: crates/parser/tests/eval_parser_test.rs +description: 16 * 38 / 58; +--- +ExpressionStatement(Binary { left: Binary { left: Literal(Number(16.0)), operator: Token { token_type: Star, origin: "*", line: 1 }, right: Literal(Number(38.0)) }, operator: Token { token_type: Slash, origin: "/", line: 1 }, right: Literal(Number(58.0)) }) diff --git a/crates/parser/tests/snapshots/eval_parser_test__parser_arimethic@52 + 80 - 94;.snap b/crates/parser/tests/snapshots/eval_parser_test__parser_arimethic@52 + 80 - 94;.snap new file mode 100644 index 0000000..0dca37c --- /dev/null +++ b/crates/parser/tests/snapshots/eval_parser_test__parser_arimethic@52 + 80 - 94;.snap @@ -0,0 +1,5 @@ +--- +source: crates/parser/tests/eval_parser_test.rs +description: 52 + 80 - 94; +--- +ExpressionStatement(Binary { left: Binary { left: Literal(Number(52.0)), operator: Token { token_type: Plus, origin: "+", line: 1 }, right: Literal(Number(80.0)) }, operator: Token { token_type: Minus, origin: "-", line: 1 }, right: Literal(Number(94.0)) }) diff --git a/crates/parser/tests/snapshots/eval_parser_test__parser_comparison@52 <= 80 >= 94;.snap b/crates/parser/tests/snapshots/eval_parser_test__parser_comparison@52 <= 80 >= 94;.snap new file mode 100644 index 0000000..c7ab012 --- /dev/null +++ b/crates/parser/tests/snapshots/eval_parser_test__parser_comparison@52 <= 80 >= 94;.snap @@ -0,0 +1,5 @@ +--- +source: crates/parser/tests/eval_parser_test.rs +description: 52 <= 80 >= 94; +--- +ExpressionStatement(Binary { left: Binary { left: Literal(Number(52.0)), operator: Token { token_type: LessEqual, origin: "<=", line: 1 }, right: Literal(Number(80.0)) }, operator: Token { token_type: GreaterEqual, origin: ">=", line: 1 }, right: Literal(Number(94.0)) }) diff --git a/crates/parser/tests/snapshots/eval_parser_test__parser_comparison@83 < 99 > 115;.snap b/crates/parser/tests/snapshots/eval_parser_test__parser_comparison@83 < 99 > 115;.snap new file mode 100644 index 0000000..1e8fd11 --- /dev/null +++ b/crates/parser/tests/snapshots/eval_parser_test__parser_comparison@83 < 99 > 115;.snap @@ -0,0 +1,5 @@ +--- +source: crates/parser/tests/eval_parser_test.rs +description: 83 < 99 > 115; +--- +ExpressionStatement(Binary { left: Binary { left: Literal(Number(83.0)), operator: Token { token_type: Less, origin: "<", line: 1 }, right: Literal(Number(99.0)) }, operator: Token { token_type: Greater, origin: ">", line: 1 }, right: Literal(Number(115.0)) }) diff --git "a/crates/parser/tests/snapshots/eval_parser_test__parser_equality@\"baz\" == \"baz\";.snap" "b/crates/parser/tests/snapshots/eval_parser_test__parser_equality@\"baz\" == \"baz\";.snap" new file mode 100644 index 0000000..eba40b5 --- /dev/null +++ "b/crates/parser/tests/snapshots/eval_parser_test__parser_equality@\"baz\" == \"baz\";.snap" @@ -0,0 +1,5 @@ +--- +source: crates/parser/tests/eval_parser_test.rs +description: "\"baz\" == \"baz\";" +--- +ExpressionStatement(Binary { left: Literal(String("baz")), operator: Token { token_type: EqualEqual, origin: "==", line: 1 }, right: Literal(String("baz")) }) diff --git a/crates/parser/tests/snapshots/eval_parser_test__parser_equality@10 != 9;.snap b/crates/parser/tests/snapshots/eval_parser_test__parser_equality@10 != 9;.snap new file mode 100644 index 0000000..b27589c --- /dev/null +++ b/crates/parser/tests/snapshots/eval_parser_test__parser_equality@10 != 9;.snap @@ -0,0 +1,5 @@ +--- +source: crates/parser/tests/eval_parser_test.rs +description: 10 != 9; +--- +ExpressionStatement(Binary { left: Literal(Number(10.0)), operator: Token { token_type: BangEqual, origin: "!=", line: 1 }, right: Literal(Number(9.0)) }) diff --git a/crates/parser/tests/snapshots/eval_parser_test__parser_error@(72 +);.snap b/crates/parser/tests/snapshots/eval_parser_test__parser_error@(72 +);.snap new file mode 100644 index 0000000..0cac8e9 --- /dev/null +++ b/crates/parser/tests/snapshots/eval_parser_test__parser_error@(72 +);.snap @@ -0,0 +1,5 @@ +--- +source: crates/parser/tests/eval_parser_test.rs +description: (72 +); +--- +[line 1] Error at ')': Expect expression. diff --git a/crates/parser/tests/snapshots/eval_parser_test__parser_literals@false;.snap b/crates/parser/tests/snapshots/eval_parser_test__parser_literals@false;.snap new file mode 100644 index 0000000..22a60a0 --- /dev/null +++ b/crates/parser/tests/snapshots/eval_parser_test__parser_literals@false;.snap @@ -0,0 +1,5 @@ +--- +source: crates/parser/tests/eval_parser_test.rs +description: false; +--- +ExpressionStatement(Literal(Bool(false))) diff --git a/crates/parser/tests/snapshots/eval_parser_test__parser_literals@nil;.snap b/crates/parser/tests/snapshots/eval_parser_test__parser_literals@nil;.snap new file mode 100644 index 0000000..0dd2394 --- /dev/null +++ b/crates/parser/tests/snapshots/eval_parser_test__parser_literals@nil;.snap @@ -0,0 +1,5 @@ +--- +source: crates/parser/tests/eval_parser_test.rs +description: nil; +--- +ExpressionStatement(Literal(Nil)) diff --git a/crates/parser/tests/snapshots/eval_parser_test__parser_literals@true;.snap b/crates/parser/tests/snapshots/eval_parser_test__parser_literals@true;.snap new file mode 100644 index 0000000..f9bb6ea --- /dev/null +++ b/crates/parser/tests/snapshots/eval_parser_test__parser_literals@true;.snap @@ -0,0 +1,5 @@ +--- +source: crates/parser/tests/eval_parser_test.rs +description: true; +--- +ExpressionStatement(Literal(Bool(true))) diff --git "a/crates/parser/tests/snapshots/eval_parser_test__parser_parentheses@(\"foo\");.snap" "b/crates/parser/tests/snapshots/eval_parser_test__parser_parentheses@(\"foo\");.snap" new file mode 100644 index 0000000..3fd7d7b --- /dev/null +++ "b/crates/parser/tests/snapshots/eval_parser_test__parser_parentheses@(\"foo\");.snap" @@ -0,0 +1,5 @@ +--- +source: crates/parser/tests/eval_parser_test.rs +description: "(\"foo\");" +--- +ExpressionStatement(Grouping(Literal(String("foo")))) diff --git a/crates/parser/tests/snapshots/eval_parser_test__parser_parentheses@((true));.snap b/crates/parser/tests/snapshots/eval_parser_test__parser_parentheses@((true));.snap new file mode 100644 index 0000000..08f9aca --- /dev/null +++ b/crates/parser/tests/snapshots/eval_parser_test__parser_parentheses@((true));.snap @@ -0,0 +1,5 @@ +--- +source: crates/parser/tests/eval_parser_test.rs +description: ((true)); +--- +ExpressionStatement(Grouping(Grouping(Literal(Bool(true))))) diff --git a/crates/parser/tests/snapshots/eval_parser_test__parser_parentheses@(1);.snap b/crates/parser/tests/snapshots/eval_parser_test__parser_parentheses@(1);.snap new file mode 100644 index 0000000..fdc805f --- /dev/null +++ b/crates/parser/tests/snapshots/eval_parser_test__parser_parentheses@(1);.snap @@ -0,0 +1,5 @@ +--- +source: crates/parser/tests/eval_parser_test.rs +description: (1); +--- +ExpressionStatement(Grouping(Literal(Number(1.0)))) diff --git a/crates/parser/tests/snapshots/eval_parser_test__parser_unary@!false;.snap b/crates/parser/tests/snapshots/eval_parser_test__parser_unary@!false;.snap new file mode 100644 index 0000000..22222bf --- /dev/null +++ b/crates/parser/tests/snapshots/eval_parser_test__parser_unary@!false;.snap @@ -0,0 +1,5 @@ +--- +source: crates/parser/tests/eval_parser_test.rs +description: "!false;" +--- +ExpressionStatement(Unary { operator: Token { token_type: Bang, origin: "!", line: 1 }, right: Literal(Bool(false)) }) diff --git a/crates/parser/tests/snapshots/eval_parser_test__parser_unary@!true;.snap b/crates/parser/tests/snapshots/eval_parser_test__parser_unary@!true;.snap new file mode 100644 index 0000000..6cb7e32 --- /dev/null +++ b/crates/parser/tests/snapshots/eval_parser_test__parser_unary@!true;.snap @@ -0,0 +1,5 @@ +--- +source: crates/parser/tests/eval_parser_test.rs +description: "!true;" +--- +ExpressionStatement(Unary { operator: Token { token_type: Bang, origin: "!", line: 1 }, right: Literal(Bool(true)) }) diff --git a/crates/parser/tests/snapshots/eval_parser_test__parser_unary@-10;.snap b/crates/parser/tests/snapshots/eval_parser_test__parser_unary@-10;.snap new file mode 100644 index 0000000..5c09e1b --- /dev/null +++ b/crates/parser/tests/snapshots/eval_parser_test__parser_unary@-10;.snap @@ -0,0 +1,5 @@ +--- +source: crates/parser/tests/eval_parser_test.rs +description: "-10;" +--- +ExpressionStatement(Unary { operator: Token { token_type: Minus, origin: "-", line: 1 }, right: Literal(Number(10.0)) }) diff --git a/src/eval.rs b/src/eval.rs deleted file mode 100644 index e845da5..0000000 --- a/src/eval.rs +++ /dev/null @@ -1,159 +0,0 @@ -//! Eval module -//! -//! Responsible for evalulating the AST and returning the computed values -//! Only supports simple expressions - -use crate::{ - eval_parser::{Expr, LiteralAtom, Parser}, - lexer::TokenType, - value::EvaluatedValue, -}; - -/// `Eval` -/// an iterator that consumes expressions from the parser and tries to evaluate them. -pub struct Eval<'de> { - parser: Parser<'de>, -} - -impl<'de> Eval<'de> { - /// Create a new `Eval` to process a given input source code - #[must_use] - pub fn new(input: &'de str) -> Self { - Eval { - parser: Parser::new(input), - } - } -} - -impl Iterator for Eval<'_> { - type Item = Result; - - fn next(&mut self) -> Option { - let expr = self.parser.next()?; - expr.map_or_else(|_| todo!(), |e| Some(evaluate_expression(e))) - } -} -fn evaluate_expression(expr: Expr) -> Result { - match expr { - Expr::Binary { - left, - operator, - right, - } => { - let l_expr = evaluate_expression(*left)?; - let r_expr = evaluate_expression(*right)?; - match operator.token_type { - TokenType::Minus - | TokenType::Star - | TokenType::Slash - | TokenType::Greater - | TokenType::GreaterEqual - | TokenType::Less - | TokenType::LessEqual => { - if let (EvaluatedValue::Number(_), EvaluatedValue::Number(_)) = - (&l_expr, &r_expr) - { - } else { - eprintln!("Operand must be a number."); - eprintln!("[line {}]", operator.line); - return Err("Operand must be a number".to_string()); - } - } - TokenType::Plus => match (&l_expr, &r_expr) { - (EvaluatedValue::Number(_), EvaluatedValue::Number(_)) - | (EvaluatedValue::String(_), EvaluatedValue::String(_)) => {} - _ => { - eprintln!("Operand must be a number."); - eprintln!("[line {}]", operator.line); - return Err("Operand must be a number".to_string()); - } - }, - _ => {} - } - - match (l_expr, r_expr, operator) { - (EvaluatedValue::Number(n1), EvaluatedValue::Number(n2), op) => { - match op.token_type { - TokenType::Plus => Ok(EvaluatedValue::Number(n1 + n2)), - TokenType::Minus => Ok(EvaluatedValue::Number(n1 - n2)), - TokenType::Star => Ok(EvaluatedValue::Number(n1 * n2)), - TokenType::Slash => Ok(EvaluatedValue::Number(n1 / n2)), - TokenType::Greater => Ok(EvaluatedValue::Bool(n1 > n2)), - TokenType::GreaterEqual => Ok(EvaluatedValue::Bool(n1 >= n2)), - TokenType::Less => Ok(EvaluatedValue::Bool(n1 < n2)), - TokenType::LessEqual => Ok(EvaluatedValue::Bool(n1 <= n2)), - TokenType::EqualEqual => Ok(EvaluatedValue::Bool(n1 == n2)), - TokenType::BangEqual => Ok(EvaluatedValue::Bool(n1 != n2)), - // TODO: Make unrepresentable by narrowing `operator` to `BinaryOperator:Not|Negate` - _ => panic!("{op} is not a valid token type for Expr::Binary with Numbers"), - } - } - (EvaluatedValue::String(s1), EvaluatedValue::String(s2), operator) => { - match operator.token_type { - TokenType::Plus => Ok(EvaluatedValue::String(s1 + &s2)), - TokenType::EqualEqual => Ok(EvaluatedValue::Bool(s1 == s2)), - TokenType::BangEqual => Ok(EvaluatedValue::Bool(s1 != s2)), - // TODO: Make unrepresentable by narrowing `operator` to `BinaryOperator:Not|Negate` - _ => panic!( - "{operator} is not a valid token type for Expr:Binary with Strings" - ), - } - } - (EvaluatedValue::String(_), EvaluatedValue::Number(_), operator) - | (EvaluatedValue::Number(_), EvaluatedValue::String(_), operator) => { - match operator.token_type { - TokenType::EqualEqual => Ok(EvaluatedValue::Bool(false)), - TokenType::BangEqual => Ok(EvaluatedValue::Bool(true)), - _ => panic!("{operator} is not supported for String<>Number"), - } - } - (l, r, op) => todo!("Add handling for {l} {r} {op}"), - } - } - Expr::Unary { operator, right } => { - let r = evaluate_expression(*right); - if let (TokenType::Minus, Ok(e)) = (operator.token_type, &r) { - if let EvaluatedValue::Number(_) = e { - } else { - eprintln!("Operand must be a number."); - eprintln!("[line {}]", operator.line); - return Err("Operand must be a number".to_string()); - } - } - match operator.token_type { - TokenType::Bang => r.as_ref().map_or_else( - |_| todo!(), - |v| match v { - EvaluatedValue::String(_) | EvaluatedValue::Number(_) => { - Ok(EvaluatedValue::Bool(false)) - } - EvaluatedValue::Nil => Ok(EvaluatedValue::Bool(true)), - EvaluatedValue::Bool(b) => match b { - true => Ok(EvaluatedValue::Bool(false)), - false => Ok(EvaluatedValue::Bool(true)), - }, - _ => todo!(), - }, - ), - TokenType::Minus => r.as_ref().map_or_else( - |_| todo!(), - |v| match v { - EvaluatedValue::Number(n) => Ok(EvaluatedValue::Number(-n)), - _ => todo!(), - }, - ), - // TODO: Make unrepresentable by narrowing `operator` to `UnaryOperator:Not|Negate` - _ => { - panic!("{:?} is not a valid unary token type", operator.token_type) - } - } - } - Expr::Literal(literal_atom) => match literal_atom { - LiteralAtom::String(s) => Ok(EvaluatedValue::String(s.to_string())), - LiteralAtom::Number(num) => Ok(EvaluatedValue::Number(num)), - LiteralAtom::Nil => Ok(EvaluatedValue::Nil), - LiteralAtom::Bool(b) => Ok(EvaluatedValue::Bool(b)), - }, - Expr::Grouping(expr) => evaluate_expression(*expr), - } -} diff --git a/src/eval_parser.rs b/src/eval_parser.rs deleted file mode 100644 index 6c4ef48..0000000 --- a/src/eval_parser.rs +++ /dev/null @@ -1,338 +0,0 @@ -//! Parser -//! -//! Responsible for transforming a given token stream into an AST -//! -//! Uses a recursive desecent parser. To transform the token stream into -//! `Expr` -use std::{fmt::Display, process::ExitCode}; - -use crate::lexer::{Lexer, Token, TokenType}; - -/// `Parser` is responsible for iterating over the token stream from `Lexer` -/// and converting the lexed `Token` into `Expr` which represent an Abstract Syntax Tree (AST) -pub struct Parser<'de> { - tokens: Vec>, - current: usize, - parse_failed: bool, - has_lex_error: bool, -} - -#[derive(Debug, Clone, PartialEq)] -/// `LiteralAtom` represents the types of literals supported by Lox -pub enum LiteralAtom<'de> { - /// `String` literal for example `"foo"` - String(&'de str), - /// Number literal for example `123.1` - Number(f64), - /// Nil literal - Nil, - /// Bool literals `false` or `true` - Bool(bool), -} - -#[derive(Debug)] -/// `Expr` represents a unit of an AST -pub enum Expr<'de> { - /// `Binary` is a binary expression such as `1 * 2` - Binary { - /// The left item `Expr` in an expression - left: Box>, - /// The operator to be applied on the `left` and `right` `Expr` - operator: Token<'de>, - /// The right item `Expr` in an expression. - right: Box>, - }, - /// `Unary` is a unary expression such as `!true` - Unary { - /// The operator to be applied on the `right` `Expr` - operator: Token<'de>, - /// The expression the unary operator will be applied to - right: Box>, - }, - /// `Literal` is a value - Literal(LiteralAtom<'de>), - /// `Grouping` holds other `Expr` such as `(1 * 2)` - Grouping(Box>), -} - -impl Display for Expr<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Expr::Unary { operator, right } => { - write!(f, "({} {})", operator.origin, right) - } - Expr::Binary { - left, - operator, - right, - } => { - write!(f, "({} {} {})", operator.origin, left, right) - } - Expr::Grouping(exp) => { - write!(f, "(group {exp})") - } - Expr::Literal(literal_atom) => match literal_atom { - LiteralAtom::String(cow) => write!(f, "{cow}"), - LiteralAtom::Number(num) => write!(f, "{num:?}"), - LiteralAtom::Nil => write!(f, "nil"), - LiteralAtom::Bool(b) => write!(f, "{b:?}"), - }, - } - } -} - -impl<'de> Iterator for Parser<'de> { - type Item = Result, String>; - - fn next(&mut self) -> Option { - if self.is_at_end() || self.parse_failed { - return None; - } - - let exp = self.expression(); - match exp { - Ok(e) => Some(Ok(e)), - Err(err) => { - eprintln!("{err}"); - self.parse_failed = true; - Some(Err(err)) - } - } - } -} - -impl<'de> Parser<'de> { - /// Create new `Parser` from a lexed token stream - #[must_use] - pub fn new(input: &'de str) -> Self { - let mut tokens = Vec::::new(); - let mut has_lex_error = false; - for token in Lexer::new(input) { - if let Ok(t) = token { - tokens.push(t); - } else { - has_lex_error = true; - } - } - Parser { - tokens, - current: 0, - parse_failed: false, - has_lex_error, - } - } - /// Parse the token stream, returning an `ExitCode` to indicate if the process - /// encountered an error when running - pub fn parse(&mut self) -> ExitCode { - let mut exit_code = if self.has_lex_error { 65 } else { 0 }; - for exp in self { - match exp { - Ok(ex) => { - println!("{ex}"); - } - Err(_) => { - exit_code = 65; - } - } - } - ExitCode::from(exit_code) - } - - fn expression(&mut self) -> Result, String> { - self.equality() - } - - fn equality(&mut self) -> Result, String> { - let mut expr = self.comparison()?; - - while self.match_tokens(&[TokenType::BangEqual, TokenType::EqualEqual]) { - let operator = self.previous().clone(); - let right = self.comparison()?; - expr = Expr::Binary { - left: Box::new(expr), - operator, - right: Box::new(right), - }; - } - - Ok(expr) - } - - fn comparison(&mut self) -> Result, String> { - let mut expr = self.term()?; - - while self.match_tokens(&[ - TokenType::Greater, - TokenType::GreaterEqual, - TokenType::Less, - TokenType::LessEqual, - ]) { - let operator = self.previous().clone(); - let right = self.term()?; - expr = Expr::Binary { - left: Box::new(expr), - operator, - right: Box::new(right), - }; - } - - Ok(expr) - } - - fn term(&mut self) -> Result, String> { - let mut expr = self.factor()?; - - while self.match_tokens(&[TokenType::Minus, TokenType::Plus]) { - let operator = self.previous().clone(); - let right = self.factor()?; - expr = Expr::Binary { - left: Box::new(expr), - operator, - right: Box::new(right), - }; - } - - Ok(expr) - } - - fn factor(&mut self) -> Result, String> { - let mut expr = self.unary()?; - - while self.match_tokens(&[TokenType::Slash, TokenType::Star]) { - let operator = self.previous().clone(); - let right = self.unary()?; - expr = Expr::Binary { - left: Box::new(expr), - operator, - right: Box::new(right), - }; - } - - Ok(expr) - } - - fn unary(&mut self) -> Result, String> { - if self.match_tokens(&[TokenType::Bang, TokenType::Minus]) { - let operator = self.previous().clone(); - let right = self.unary()?; - return Ok(Expr::Unary { - operator, - right: Box::new(right), - }); - } - - self.primary() - } - - fn primary(&mut self) -> Result, String> { - if let Some(token) = self.peek() { - let origin = token.origin; - let line_num = token.line; - match token.token_type { - TokenType::Number(n) => { - self.advance(); - Ok(Expr::Literal(LiteralAtom::Number(n))) - } - TokenType::String => { - self.advance(); - Ok(Expr::Literal(LiteralAtom::String(origin))) - } - TokenType::True => { - self.advance(); - Ok(Expr::Literal(LiteralAtom::Bool(true))) - } - TokenType::False => { - self.advance(); - Ok(Expr::Literal(LiteralAtom::Bool(false))) - } - TokenType::Nil => { - self.advance(); - Ok(Expr::Literal(LiteralAtom::Nil)) - } - TokenType::LeftParen => { - self.advance(); - let expr = self.expression()?; - self.consume( - TokenType::RightParen, - origin, - line_num, - "Expect ')' after expression", - )?; - Ok(Expr::Grouping(Box::new(expr))) - } - _ => { - let err_msg = - Self::error_msg(&token.token_type, origin, line_num, "Expect expression"); - Err(err_msg) - } - } - } else { - Err("error".to_string()) - } - } - - // Helper methods - fn match_tokens(&mut self, types: &[TokenType]) -> bool { - for t in types { - if self.check(t) { - self.advance(); - return true; - } - } - false - } - - fn check(&self, token_type: &TokenType) -> bool { - if self.is_at_end() { - return false; - } - std::mem::discriminant( - &self - .peek() - .expect("We have returned early if we are at end of token stream") - .token_type, - ) == std::mem::discriminant(token_type) - } - - fn advance(&mut self) -> &Token<'de> { - if !self.is_at_end() { - self.current += 1; - } - self.previous() - } - - fn peek(&self) -> Option<&Token<'de>> { - self.tokens.get(self.current) - } - - fn previous(&self) -> &Token<'de> { - self.tokens.get(self.current - 1).unwrap() - } - - fn is_at_end(&self) -> bool { - self.peek() - .is_none_or(|token| matches!(token.token_type, TokenType::Eof)) - } - - fn consume( - &mut self, - token_type: TokenType, - origin: &str, - num: usize, - message: &str, - ) -> Result<&Token<'de>, String> { - if self.check(&token_type) { - Ok(self.advance()) - } else { - Err(Self::error_msg(&token_type, origin, num, message)) - } - } - - fn error_msg(token_type: &TokenType, origin: &str, num: usize, message: &str) -> String { - if *token_type == TokenType::Eof { - format!("[line {num}] Error at end: {message}.") - } else { - format!("[line {num}] Error at '{origin}': {message}.") - } - } -} diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index 03e9637..0000000 --- a/src/main.rs +++ /dev/null @@ -1,72 +0,0 @@ -use clap::Subcommand; -use loxide::eval::Eval; -use loxide::eval_parser::Parser; -use loxide::interpreter::Interpreter; -use loxide::lexer::Lexer; -use miette::{IntoDiagnostic, Result, WrapErr}; -use std::fs; -use std::path::PathBuf; -use std::process::ExitCode; - -use clap::Parser as ClapParser; - -#[derive(ClapParser, Debug)] -#[command(version, about, long_about = None)] -struct Args { - #[command(subcommand)] - commands: Commands, -} -#[derive(Subcommand, Debug)] -enum Commands { - Tokenize { filename: PathBuf }, - Parse { filename: PathBuf }, - Evaluate { filename: PathBuf }, - Run { filename: PathBuf }, -} - -fn main() -> Result { - let args = Args::parse(); - match args.commands { - Commands::Tokenize { filename } => { - let input = fs::read_to_string(filename) - .into_diagnostic() - .wrap_err_with(|| "reading file".to_string())?; - Ok(Lexer::new(&input).tokenize_lex()) - } - Commands::Parse { filename } => { - let input = fs::read_to_string(filename) - .into_diagnostic() - .wrap_err_with(|| "reading file".to_string())?; - Ok(Parser::new(&input).parse()) - } - Commands::Evaluate { filename } => { - let input = fs::read_to_string(filename) - .into_diagnostic() - .wrap_err_with(|| "reading file".to_string())?; - let mut exit_code = 0; - for res in Eval::new(&input) { - match res { - Ok(r) => println!("{r}"), - Err(_) => exit_code = 70, - } - } - Ok(ExitCode::from(exit_code)) - } - Commands::Run { filename } => { - let input = fs::read_to_string(filename) - .into_diagnostic() - .wrap_err_with(|| "reading file".to_string())?; - let mut exit_code = 0; - for res in Interpreter::new(&input) { - match res { - Ok(()) => {} - Err(err_code) => { - exit_code = err_code; - break; - } - } - } - Ok(ExitCode::from(exit_code)) - } - } -} diff --git a/tests/eval_test.rs b/tests/eval_test.rs deleted file mode 100644 index 06eac7c..0000000 --- a/tests/eval_test.rs +++ /dev/null @@ -1,84 +0,0 @@ -use insta::{assert_debug_snapshot, assert_snapshot}; -use loxide::eval::Eval; -use rstest::*; - -macro_rules! set_snapshot_suffix { - ($($expr:expr),*) => { - let mut settings = insta::Settings::clone_current(); - settings.set_snapshot_suffix(format!($($expr,)*)); - settings.set_description(format!($($expr,)*)); - settings.set_omit_expression(true); - let _guard = settings.bind_to_scope(); - } -} - -#[rstest] -#[case("true")] -#[case("false")] -#[case("nil")] -#[case("\"hello world\"")] -#[case("10.4")] -#[case("10")] -#[case("10.0")] -#[case("(\"hello world!\")")] -#[case("(10.5)")] -#[case("((false))")] -#[case("-73")] -#[case("!true")] -#[case("!nil")] -#[case("!10.40")] -#[case("!((false))")] -#[case("42 / 5")] -#[case("18 * 3 / (3 * 6)")] -#[case("(10.40 * 2) / 2")] -#[case("23 + 28 - (-(61 - 99))")] -#[case("\"foo\" + \"bar\"")] -#[case("\"42\" + \"24\"")] -#[case("57 > -65")] -#[case("11 >= 11")] -#[case("(54 - 67) >= -(114 / 57 + 11)")] -#[case("\"hello\" == \"world\"")] -#[case("\"foo\" != \"bar\"")] -#[case("\"foo\" == \"foo\"")] -#[case("61 == \"61\"")] -#[case("61 != \"61\"")] -#[case("\"61\" != 61")] -fn test_eval_literals(#[case] input: &str) { - set_snapshot_suffix!("{}", input); - let exprs: Vec = Eval::new(input) - .take_while(std::result::Result::is_ok) - .map(|e| match e { - Ok(exp) => format!("{exp}"), - Err(_) => String::new(), - }) - .collect(); - assert_snapshot!(exprs.join("\n")); -} - -#[rstest] -#[case("-\"hello world!\"")] -#[case("-true")] -#[case("-(\"world\" + \"foo\")")] -#[case("\"foo\" * 42")] -#[case("true / 2")] -#[case("(\"foo\" * \"bar\")")] -#[case("false / true")] -#[case("\"foo\" + true")] -#[case("42 - true")] -#[case("true + false")] -#[case("\"foo\" - \"bar\"")] -#[case("\"foo\" < false")] -#[case("true < 2")] -#[case("(\"foo\" + \"bar\") < 42")] -#[case("false > true")] -fn test_eval_errors(#[case] input: &str) { - set_snapshot_suffix!("{}", input); - let mut errors = Vec::new(); - for e in Eval::new(input) { - match e { - Ok(_) => {} - Err(e) => errors.push(e), - } - } - assert_debug_snapshot!(errors); -} diff --git a/tests/main_test.rs b/tests/main_test.rs deleted file mode 100644 index 69ade05..0000000 --- a/tests/main_test.rs +++ /dev/null @@ -1,226 +0,0 @@ -use assert_cmd::Command; -use rstest::rstest; - -#[test] -fn test_cli_version() { - Command::cargo_bin("loxide") - .unwrap() - .arg("--version") - .assert() - .success() - .code(0) - .stdout("loxide 0.1.0\n".to_string()) - .stderr(""); - - Command::cargo_bin("loxide") - .unwrap() - .arg("-V") - .assert() - .success() - .code(0) - .stdout("loxide 0.1.0\n".to_string()) - .stderr(""); -} -#[test] -fn test_tokenize_no_file() { - Command::cargo_bin("loxide") - .unwrap() - .arg("tokenize") - .arg("text.lox") - .assert() - .failure() - .code(1); -} - -#[test] -fn test_tokenize_with_file() { - Command::cargo_bin("loxide") - .unwrap() - .arg("tokenize") - .arg("tests/fixtures/lexer.lox") - .assert() - .success() - .code(0) - .stdout( - "STRING \"hello\" hello\nNUMBER 123 123.0\nFALSE false null\nNIL nil null\nEOF null\n", - ); -} - -#[test] -fn test_tokenize_with_file_error() { - Command::cargo_bin("loxide") - .unwrap() - .arg("tokenize") - .arg("tests/fixtures/lexer_error.lox") - .assert() - .failure() - .code(65) - .stderr("[line 1] Error: Unexpected character: #\n[line 1] Error: Unterminated string.\n") - .stdout("EOF null\n"); -} - -#[test] -fn test_parse_no_file() { - Command::cargo_bin("loxide") - .unwrap() - .arg("parse") - .arg("text.lox") - .assert() - .failure() - .code(1); -} - -#[test] -fn test_parse_with_file() { - Command::cargo_bin("loxide") - .unwrap() - .arg("parse") - .arg("tests/fixtures/parser.lox") - .assert() - .success() - .code(0) - .stdout("(- (+ 52.0 80.0) 94.0)\n(> (< 83.0 99.0) 115.0)\n"); -} - -#[test] -fn test_parse_with_file_error() { - Command::cargo_bin("loxide") - .unwrap() - .arg("parse") - .arg("tests/fixtures/parser_error.lox") - .assert() - .failure() - .code(65) - .stderr("[line 1] Error at \')\': Expect expression.\n") - .stdout(""); -} - -#[test] -fn test_evaluate_no_file() { - Command::cargo_bin("loxide") - .unwrap() - .arg("evaluate") - .arg("text.lox") - .assert() - .failure() - .code(1); -} - -#[test] -fn test_evaluate_with_file() { - Command::cargo_bin("loxide") - .unwrap() - .arg("evaluate") - .arg("tests/fixtures/evaluate.lox") - .assert() - .success() - .code(0) - .stdout("false\ntrue\nnil\n"); -} - -#[test] -fn test_evaluate_with_file_error() { - Command::cargo_bin("loxide") - .unwrap() - .arg("evaluate") - .arg("tests/fixtures/evaluate_error.lox") - .assert() - .failure() - .code(70) - .stderr( - "Operand must be a number. -[line 1]\n", - ); -} - -#[test] -fn test_run_no_file() { - Command::cargo_bin("loxide") - .unwrap() - .arg("run") - .arg("text.lox") - .assert() - .failure() - .code(1); -} - -#[rstest] -#[case("run", "true\ntrue\ntrue\nthe expression below is invalid\n3\nsomething\ntrue\ntrue\ntrue\nfalse\nnil\nnil\n98\n98\nbefore\nafter\nafter\nbefore -inner world\nouter baz\nglobal quz\nouter world\nouter baz\nglobal quz\nglobal world\nglobal baz\nglobal quz\n", )] -#[case( - "run_if", - "bar\nblock body\ntrue\nadult\neligible for voting: true\nif\nelse\n" -)] -#[case( - "run_logical", - "baz\nbaz\nworld\nbar\nbar\n41\n41\ntrue\nfalse\nfalse\ntrue\nfalse\ntrue\n" -)] -#[case( - "run_while", - "1\n2\n3\n0\n1\n2\nProduct of numbers 1 to 5: \n120\n0\n1\n1\n2\n3\n5\n8\n13\n21\n34\n" -)] -#[case("run_for", "1\n2\n3\n0\n1\n2\n0\n1\n0\n1\n0\n-1\nafter\n0\n")] -fn test_run_with_file(#[case] file_name: &str, #[case] expected_stdout: &str) { - let path = format!("tests/fixtures/{file_name}.lox"); - Command::cargo_bin("loxide") - .unwrap() - .arg("run") - .arg(path) - .assert() - .success() - .code(0) - .stdout(expected_stdout.to_string()); -} - -#[rstest] -#[case("run_error", "Operand must be a number.\n[line 1]\n", "", 70)] -#[case("run_error_var", "Undefined variable 'x'.\n", "", 70)] -#[case( - "run_error_var_assign", - "[line 1] Error at \';\': Expect expression.\n", - "", - 65 -)] -#[case( - "run_error_undefined_var", - "Undefined variable 'quz'.\n[line 17]\n", - "modified foo\ninner quz\nmodified foo\nouter quz\n", - 70 -)] -#[case( - "run_error_must_be_a_number", - "Operand must be a number.\n[line 1]\n", - "", - 70 -)] -#[case( - "run_error_illegal_call", - "Can only call function and classes.\n", - "", - 70 -)] -#[case( - "run_error_incorrect_arity", - "Expected 0 arguments but got 3.\n", - "", - 70 -)] -fn test_run_with_file_error( - #[case] file_name: &str, - #[case] expected_err: &str, - #[case] expected_stdout: &str, - #[case] expected_code: i32, -) { - let err = expected_err.to_string(); - let out = expected_stdout.to_string(); - let path = format!("tests/fixtures/{file_name}.lox"); - Command::cargo_bin("loxide") - .unwrap() - .arg("run") - .arg(path) - .assert() - .failure() - .code(expected_code) - .stderr(err) - .stdout(out); -} diff --git a/tests/snapshots/eval_parser_test__parser_arimethic@16 * 38 __ 58.snap b/tests/snapshots/eval_parser_test__parser_arimethic@16 * 38 __ 58.snap deleted file mode 100644 index 9388383..0000000 --- a/tests/snapshots/eval_parser_test__parser_arimethic@16 * 38 __ 58.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_parser_test.rs -description: 16 * 38 / 58 ---- -(/ (* 16.0 38.0) 58.0) diff --git a/tests/snapshots/eval_parser_test__parser_arimethic@52 + 80 - 94.snap b/tests/snapshots/eval_parser_test__parser_arimethic@52 + 80 - 94.snap deleted file mode 100644 index 086b8c4..0000000 --- a/tests/snapshots/eval_parser_test__parser_arimethic@52 + 80 - 94.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_parser_test.rs -description: 52 + 80 - 94 ---- -(- (+ 52.0 80.0) 94.0) diff --git a/tests/snapshots/eval_parser_test__parser_comparison@52 <= 80 >= 94.snap b/tests/snapshots/eval_parser_test__parser_comparison@52 <= 80 >= 94.snap deleted file mode 100644 index f3288a6..0000000 --- a/tests/snapshots/eval_parser_test__parser_comparison@52 <= 80 >= 94.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_parser_test.rs -description: 52 <= 80 >= 94 ---- -(>= (<= 52.0 80.0) 94.0) diff --git a/tests/snapshots/eval_parser_test__parser_comparison@83 < 99 > 115.snap b/tests/snapshots/eval_parser_test__parser_comparison@83 < 99 > 115.snap deleted file mode 100644 index fe7b06a..0000000 --- a/tests/snapshots/eval_parser_test__parser_comparison@83 < 99 > 115.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_parser_test.rs -description: 83 < 99 > 115 ---- -(> (< 83.0 99.0) 115.0) diff --git "a/tests/snapshots/eval_parser_test__parser_equality@\"baz\" == \"baz\".snap" "b/tests/snapshots/eval_parser_test__parser_equality@\"baz\" == \"baz\".snap" deleted file mode 100644 index a32ad50..0000000 --- "a/tests/snapshots/eval_parser_test__parser_equality@\"baz\" == \"baz\".snap" +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_parser_test.rs -description: "\"baz\" == \"baz\"" ---- -(== baz baz) diff --git a/tests/snapshots/eval_parser_test__parser_equality@10 != 9.snap b/tests/snapshots/eval_parser_test__parser_equality@10 != 9.snap deleted file mode 100644 index 10f8428..0000000 --- a/tests/snapshots/eval_parser_test__parser_equality@10 != 9.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_parser_test.rs -description: 10 != 9 ---- -(!= 10.0 9.0) diff --git a/tests/snapshots/eval_parser_test__parser_error@(72 +).snap b/tests/snapshots/eval_parser_test__parser_error@(72 +).snap deleted file mode 100644 index 4b28ff2..0000000 --- a/tests/snapshots/eval_parser_test__parser_error@(72 +).snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_parser_test.rs -description: (72 +) ---- -[line 1] Error at ')': Expect expression. diff --git a/tests/snapshots/eval_parser_test__parser_literals@false.snap b/tests/snapshots/eval_parser_test__parser_literals@false.snap deleted file mode 100644 index 060a813..0000000 --- a/tests/snapshots/eval_parser_test__parser_literals@false.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_parser_test.rs -description: "false" ---- -false diff --git a/tests/snapshots/eval_parser_test__parser_literals@nil.snap b/tests/snapshots/eval_parser_test__parser_literals@nil.snap deleted file mode 100644 index 200fed8..0000000 --- a/tests/snapshots/eval_parser_test__parser_literals@nil.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_parser_test.rs -description: nil ---- -nil diff --git a/tests/snapshots/eval_parser_test__parser_literals@true.snap b/tests/snapshots/eval_parser_test__parser_literals@true.snap deleted file mode 100644 index faf0a9f..0000000 --- a/tests/snapshots/eval_parser_test__parser_literals@true.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_parser_test.rs -description: "true" ---- -true diff --git "a/tests/snapshots/eval_parser_test__parser_parentheses@(\"foo\").snap" "b/tests/snapshots/eval_parser_test__parser_parentheses@(\"foo\").snap" deleted file mode 100644 index 77e4e5b..0000000 --- "a/tests/snapshots/eval_parser_test__parser_parentheses@(\"foo\").snap" +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_parser_test.rs -description: "(\"foo\")" ---- -(group foo) diff --git a/tests/snapshots/eval_parser_test__parser_parentheses@((true)).snap b/tests/snapshots/eval_parser_test__parser_parentheses@((true)).snap deleted file mode 100644 index cfad8ba..0000000 --- a/tests/snapshots/eval_parser_test__parser_parentheses@((true)).snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_parser_test.rs -description: ((true)) ---- -(group (group true)) diff --git a/tests/snapshots/eval_parser_test__parser_parentheses@(1).snap b/tests/snapshots/eval_parser_test__parser_parentheses@(1).snap deleted file mode 100644 index e5ab480..0000000 --- a/tests/snapshots/eval_parser_test__parser_parentheses@(1).snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_parser_test.rs -description: (1) ---- -(group 1.0) diff --git a/tests/snapshots/eval_parser_test__parser_unary@!false.snap b/tests/snapshots/eval_parser_test__parser_unary@!false.snap deleted file mode 100644 index f6f2e3f..0000000 --- a/tests/snapshots/eval_parser_test__parser_unary@!false.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_parser_test.rs -description: "!false" ---- -(! false) diff --git a/tests/snapshots/eval_parser_test__parser_unary@!true.snap b/tests/snapshots/eval_parser_test__parser_unary@!true.snap deleted file mode 100644 index a88d574..0000000 --- a/tests/snapshots/eval_parser_test__parser_unary@!true.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_parser_test.rs -description: "!true" ---- -(! true) diff --git a/tests/snapshots/eval_parser_test__parser_unary@-10.snap b/tests/snapshots/eval_parser_test__parser_unary@-10.snap deleted file mode 100644 index 145a4ec..0000000 --- a/tests/snapshots/eval_parser_test__parser_unary@-10.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_parser_test.rs -description: "-10" ---- -(- 10.0) diff --git "a/tests/snapshots/eval_test__eval_errors@\"foo\" * 42.snap" "b/tests/snapshots/eval_test__eval_errors@\"foo\" * 42.snap" deleted file mode 100644 index 9d270a0..0000000 --- "a/tests/snapshots/eval_test__eval_errors@\"foo\" * 42.snap" +++ /dev/null @@ -1,7 +0,0 @@ ---- -source: tests/eval_test.rs -description: "\"foo\" * 42" ---- -[ - "Operand must be a number", -] diff --git "a/tests/snapshots/eval_test__eval_errors@\"foo\" + true.snap" "b/tests/snapshots/eval_test__eval_errors@\"foo\" + true.snap" deleted file mode 100644 index 7f1c16d..0000000 --- "a/tests/snapshots/eval_test__eval_errors@\"foo\" + true.snap" +++ /dev/null @@ -1,7 +0,0 @@ ---- -source: tests/eval_test.rs -description: "\"foo\" + true" ---- -[ - "Operand must be a number", -] diff --git "a/tests/snapshots/eval_test__eval_errors@\"foo\" - \"bar\".snap" "b/tests/snapshots/eval_test__eval_errors@\"foo\" - \"bar\".snap" deleted file mode 100644 index 6c424ce..0000000 --- "a/tests/snapshots/eval_test__eval_errors@\"foo\" - \"bar\".snap" +++ /dev/null @@ -1,7 +0,0 @@ ---- -source: tests/eval_test.rs -description: "\"foo\" - \"bar\"" ---- -[ - "Operand must be a number", -] diff --git "a/tests/snapshots/eval_test__eval_errors@\"foo\" < false.snap" "b/tests/snapshots/eval_test__eval_errors@\"foo\" < false.snap" deleted file mode 100644 index ecc1a82..0000000 --- "a/tests/snapshots/eval_test__eval_errors@\"foo\" < false.snap" +++ /dev/null @@ -1,7 +0,0 @@ ---- -source: tests/eval_test.rs -description: "\"foo\" < false" ---- -[ - "Operand must be a number", -] diff --git "a/tests/snapshots/eval_test__eval_errors@(\"foo\" * \"bar\").snap" "b/tests/snapshots/eval_test__eval_errors@(\"foo\" * \"bar\").snap" deleted file mode 100644 index 028c475..0000000 --- "a/tests/snapshots/eval_test__eval_errors@(\"foo\" * \"bar\").snap" +++ /dev/null @@ -1,7 +0,0 @@ ---- -source: tests/eval_test.rs -description: "(\"foo\" * \"bar\")" ---- -[ - "Operand must be a number", -] diff --git "a/tests/snapshots/eval_test__eval_errors@(\"foo\" + \"bar\") < 42.snap" "b/tests/snapshots/eval_test__eval_errors@(\"foo\" + \"bar\") < 42.snap" deleted file mode 100644 index 4a95de0..0000000 --- "a/tests/snapshots/eval_test__eval_errors@(\"foo\" + \"bar\") < 42.snap" +++ /dev/null @@ -1,7 +0,0 @@ ---- -source: tests/eval_test.rs -description: "(\"foo\" + \"bar\") < 42" ---- -[ - "Operand must be a number", -] diff --git "a/tests/snapshots/eval_test__eval_errors@-\"hello world!\".snap" "b/tests/snapshots/eval_test__eval_errors@-\"hello world!\".snap" deleted file mode 100644 index e565068..0000000 --- "a/tests/snapshots/eval_test__eval_errors@-\"hello world!\".snap" +++ /dev/null @@ -1,7 +0,0 @@ ---- -source: tests/eval_test.rs -description: "-\"hello world!\"" ---- -[ - "Operand must be a number", -] diff --git "a/tests/snapshots/eval_test__eval_errors@-(\"world\" + \"foo\").snap" "b/tests/snapshots/eval_test__eval_errors@-(\"world\" + \"foo\").snap" deleted file mode 100644 index c7023de..0000000 --- "a/tests/snapshots/eval_test__eval_errors@-(\"world\" + \"foo\").snap" +++ /dev/null @@ -1,7 +0,0 @@ ---- -source: tests/eval_test.rs -description: "-(\"world\" + \"foo\")" ---- -[ - "Operand must be a number", -] diff --git a/tests/snapshots/eval_test__eval_errors@-true.snap b/tests/snapshots/eval_test__eval_errors@-true.snap deleted file mode 100644 index 8acf3c0..0000000 --- a/tests/snapshots/eval_test__eval_errors@-true.snap +++ /dev/null @@ -1,7 +0,0 @@ ---- -source: tests/eval_test.rs -description: "-true" ---- -[ - "Operand must be a number", -] diff --git a/tests/snapshots/eval_test__eval_errors@42 - true.snap b/tests/snapshots/eval_test__eval_errors@42 - true.snap deleted file mode 100644 index d4407b4..0000000 --- a/tests/snapshots/eval_test__eval_errors@42 - true.snap +++ /dev/null @@ -1,7 +0,0 @@ ---- -source: tests/eval_test.rs -description: 42 - true ---- -[ - "Operand must be a number", -] diff --git a/tests/snapshots/eval_test__eval_errors@false > true.snap b/tests/snapshots/eval_test__eval_errors@false > true.snap deleted file mode 100644 index 9100314..0000000 --- a/tests/snapshots/eval_test__eval_errors@false > true.snap +++ /dev/null @@ -1,7 +0,0 @@ ---- -source: tests/eval_test.rs -description: false > true ---- -[ - "Operand must be a number", -] diff --git a/tests/snapshots/eval_test__eval_errors@false __ true.snap b/tests/snapshots/eval_test__eval_errors@false __ true.snap deleted file mode 100644 index ff46eb8..0000000 --- a/tests/snapshots/eval_test__eval_errors@false __ true.snap +++ /dev/null @@ -1,7 +0,0 @@ ---- -source: tests/eval_test.rs -description: false / true ---- -[ - "Operand must be a number", -] diff --git a/tests/snapshots/eval_test__eval_errors@true + false.snap b/tests/snapshots/eval_test__eval_errors@true + false.snap deleted file mode 100644 index 1cc6e84..0000000 --- a/tests/snapshots/eval_test__eval_errors@true + false.snap +++ /dev/null @@ -1,7 +0,0 @@ ---- -source: tests/eval_test.rs -description: true + false ---- -[ - "Operand must be a number", -] diff --git a/tests/snapshots/eval_test__eval_errors@true < 2.snap b/tests/snapshots/eval_test__eval_errors@true < 2.snap deleted file mode 100644 index 1285cf3..0000000 --- a/tests/snapshots/eval_test__eval_errors@true < 2.snap +++ /dev/null @@ -1,7 +0,0 @@ ---- -source: tests/eval_test.rs -description: true < 2 ---- -[ - "Operand must be a number", -] diff --git a/tests/snapshots/eval_test__eval_errors@true __ 2.snap b/tests/snapshots/eval_test__eval_errors@true __ 2.snap deleted file mode 100644 index 08afcce..0000000 --- a/tests/snapshots/eval_test__eval_errors@true __ 2.snap +++ /dev/null @@ -1,7 +0,0 @@ ---- -source: tests/eval_test.rs -description: true / 2 ---- -[ - "Operand must be a number", -] diff --git a/tests/snapshots/eval_test__eval_literals@!((false)).snap b/tests/snapshots/eval_test__eval_literals@!((false)).snap deleted file mode 100644 index 72e4b39..0000000 --- a/tests/snapshots/eval_test__eval_literals@!((false)).snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "!((false))" ---- -true diff --git a/tests/snapshots/eval_test__eval_literals@!10.40.snap b/tests/snapshots/eval_test__eval_literals@!10.40.snap deleted file mode 100644 index 642b200..0000000 --- a/tests/snapshots/eval_test__eval_literals@!10.40.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "!10.40" ---- -false diff --git a/tests/snapshots/eval_test__eval_literals@!nil.snap b/tests/snapshots/eval_test__eval_literals@!nil.snap deleted file mode 100644 index 278d69d..0000000 --- a/tests/snapshots/eval_test__eval_literals@!nil.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "!nil" ---- -true diff --git a/tests/snapshots/eval_test__eval_literals@!true.snap b/tests/snapshots/eval_test__eval_literals@!true.snap deleted file mode 100644 index 892e3fb..0000000 --- a/tests/snapshots/eval_test__eval_literals@!true.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "!true" ---- -false diff --git "a/tests/snapshots/eval_test__eval_literals@\"42\" + \"24\".snap" "b/tests/snapshots/eval_test__eval_literals@\"42\" + \"24\".snap" deleted file mode 100644 index 28b7283..0000000 --- "a/tests/snapshots/eval_test__eval_literals@\"42\" + \"24\".snap" +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "\"42\" + \"24\"" ---- -4224 diff --git "a/tests/snapshots/eval_test__eval_literals@\"61\" != 61.snap" "b/tests/snapshots/eval_test__eval_literals@\"61\" != 61.snap" deleted file mode 100644 index 61d20ce..0000000 --- "a/tests/snapshots/eval_test__eval_literals@\"61\" != 61.snap" +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "\"61\" != 61" ---- -true diff --git "a/tests/snapshots/eval_test__eval_literals@\"foo\" != \"bar\".snap" "b/tests/snapshots/eval_test__eval_literals@\"foo\" != \"bar\".snap" deleted file mode 100644 index 4397ba7..0000000 --- "a/tests/snapshots/eval_test__eval_literals@\"foo\" != \"bar\".snap" +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "\"foo\" != \"bar\"" ---- -true diff --git "a/tests/snapshots/eval_test__eval_literals@\"foo\" + \"bar\".snap" "b/tests/snapshots/eval_test__eval_literals@\"foo\" + \"bar\".snap" deleted file mode 100644 index 23b2e75..0000000 --- "a/tests/snapshots/eval_test__eval_literals@\"foo\" + \"bar\".snap" +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "\"foo\" + \"bar\"" ---- -foobar diff --git "a/tests/snapshots/eval_test__eval_literals@\"foo\" == \"foo\".snap" "b/tests/snapshots/eval_test__eval_literals@\"foo\" == \"foo\".snap" deleted file mode 100644 index 6b5953e..0000000 --- "a/tests/snapshots/eval_test__eval_literals@\"foo\" == \"foo\".snap" +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "\"foo\" == \"foo\"" ---- -true diff --git "a/tests/snapshots/eval_test__eval_literals@\"hello world\".snap" "b/tests/snapshots/eval_test__eval_literals@\"hello world\".snap" deleted file mode 100644 index e73481d..0000000 --- "a/tests/snapshots/eval_test__eval_literals@\"hello world\".snap" +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "\"hello world\"" ---- -hello world diff --git "a/tests/snapshots/eval_test__eval_literals@\"hello\" == \"world\".snap" "b/tests/snapshots/eval_test__eval_literals@\"hello\" == \"world\".snap" deleted file mode 100644 index dc13f46..0000000 --- "a/tests/snapshots/eval_test__eval_literals@\"hello\" == \"world\".snap" +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "\"hello\" == \"world\"" ---- -false diff --git "a/tests/snapshots/eval_test__eval_literals@(\"hello world!\").snap" "b/tests/snapshots/eval_test__eval_literals@(\"hello world!\").snap" deleted file mode 100644 index 1ee9cae..0000000 --- "a/tests/snapshots/eval_test__eval_literals@(\"hello world!\").snap" +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "(\"hello world!\")" ---- -hello world! diff --git a/tests/snapshots/eval_test__eval_literals@((false)).snap b/tests/snapshots/eval_test__eval_literals@((false)).snap deleted file mode 100644 index f051a91..0000000 --- a/tests/snapshots/eval_test__eval_literals@((false)).snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: ((false)) ---- -false diff --git a/tests/snapshots/eval_test__eval_literals@(10.40 * 2) __ 2.snap b/tests/snapshots/eval_test__eval_literals@(10.40 * 2) __ 2.snap deleted file mode 100644 index 0ce9aa3..0000000 --- a/tests/snapshots/eval_test__eval_literals@(10.40 * 2) __ 2.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: (10.40 * 2) / 2 ---- -10.4 diff --git a/tests/snapshots/eval_test__eval_literals@(10.5).snap b/tests/snapshots/eval_test__eval_literals@(10.5).snap deleted file mode 100644 index f250944..0000000 --- a/tests/snapshots/eval_test__eval_literals@(10.5).snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: (10.5) ---- -10.5 diff --git a/tests/snapshots/eval_test__eval_literals@(54 - 67) >= -(114 __ 57 + 11).snap b/tests/snapshots/eval_test__eval_literals@(54 - 67) >= -(114 __ 57 + 11).snap deleted file mode 100644 index b8adee7..0000000 --- a/tests/snapshots/eval_test__eval_literals@(54 - 67) >= -(114 __ 57 + 11).snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: (54 - 67) >= -(114 / 57 + 11) ---- -true diff --git a/tests/snapshots/eval_test__eval_literals@-73.snap b/tests/snapshots/eval_test__eval_literals@-73.snap deleted file mode 100644 index be52ef2..0000000 --- a/tests/snapshots/eval_test__eval_literals@-73.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "-73" ---- --73 diff --git a/tests/snapshots/eval_test__eval_literals@10.0.snap b/tests/snapshots/eval_test__eval_literals@10.0.snap deleted file mode 100644 index 502b709..0000000 --- a/tests/snapshots/eval_test__eval_literals@10.0.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "10.0" ---- -10 diff --git a/tests/snapshots/eval_test__eval_literals@10.4.snap b/tests/snapshots/eval_test__eval_literals@10.4.snap deleted file mode 100644 index 1ef39c9..0000000 --- a/tests/snapshots/eval_test__eval_literals@10.4.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "10.4" ---- -10.4 diff --git a/tests/snapshots/eval_test__eval_literals@10.snap b/tests/snapshots/eval_test__eval_literals@10.snap deleted file mode 100644 index 2bca02c..0000000 --- a/tests/snapshots/eval_test__eval_literals@10.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "10" ---- -10 diff --git a/tests/snapshots/eval_test__eval_literals@11 >= 11.snap b/tests/snapshots/eval_test__eval_literals@11 >= 11.snap deleted file mode 100644 index 1eeb259..0000000 --- a/tests/snapshots/eval_test__eval_literals@11 >= 11.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: 11 >= 11 ---- -true diff --git a/tests/snapshots/eval_test__eval_literals@18 * 3 __ (3 * 6).snap b/tests/snapshots/eval_test__eval_literals@18 * 3 __ (3 * 6).snap deleted file mode 100644 index f545cdd..0000000 --- a/tests/snapshots/eval_test__eval_literals@18 * 3 __ (3 * 6).snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: 18 * 3 / (3 * 6) ---- -3 diff --git a/tests/snapshots/eval_test__eval_literals@23 + 28 - (-(61 - 99)).snap b/tests/snapshots/eval_test__eval_literals@23 + 28 - (-(61 - 99)).snap deleted file mode 100644 index acd356a..0000000 --- a/tests/snapshots/eval_test__eval_literals@23 + 28 - (-(61 - 99)).snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: 23 + 28 - (-(61 - 99)) ---- -13 diff --git a/tests/snapshots/eval_test__eval_literals@42 __ 5.snap b/tests/snapshots/eval_test__eval_literals@42 __ 5.snap deleted file mode 100644 index 7467b02..0000000 --- a/tests/snapshots/eval_test__eval_literals@42 __ 5.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: 42 / 5 ---- -8.4 diff --git a/tests/snapshots/eval_test__eval_literals@57 > -65.snap b/tests/snapshots/eval_test__eval_literals@57 > -65.snap deleted file mode 100644 index 38cb82e..0000000 --- a/tests/snapshots/eval_test__eval_literals@57 > -65.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: 57 > -65 ---- -true diff --git "a/tests/snapshots/eval_test__eval_literals@61 != \"61\".snap" "b/tests/snapshots/eval_test__eval_literals@61 != \"61\".snap" deleted file mode 100644 index 2eb37b1..0000000 --- "a/tests/snapshots/eval_test__eval_literals@61 != \"61\".snap" +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "61 != \"61\"" ---- -true diff --git "a/tests/snapshots/eval_test__eval_literals@61 == \"61\".snap" "b/tests/snapshots/eval_test__eval_literals@61 == \"61\".snap" deleted file mode 100644 index b982b7b..0000000 --- "a/tests/snapshots/eval_test__eval_literals@61 == \"61\".snap" +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "61 == \"61\"" ---- -false diff --git a/tests/snapshots/eval_test__eval_literals@false.snap b/tests/snapshots/eval_test__eval_literals@false.snap deleted file mode 100644 index 54651ef..0000000 --- a/tests/snapshots/eval_test__eval_literals@false.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "false" ---- -false diff --git a/tests/snapshots/eval_test__eval_literals@nil.snap b/tests/snapshots/eval_test__eval_literals@nil.snap deleted file mode 100644 index 7d46eaa..0000000 --- a/tests/snapshots/eval_test__eval_literals@nil.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: nil ---- -nil diff --git a/tests/snapshots/eval_test__eval_literals@true.snap b/tests/snapshots/eval_test__eval_literals@true.snap deleted file mode 100644 index b159842..0000000 --- a/tests/snapshots/eval_test__eval_literals@true.snap +++ /dev/null @@ -1,5 +0,0 @@ ---- -source: tests/eval_test.rs -description: "true" ---- -true