diff --git a/Cargo.lock b/Cargo.lock index f5aa90d..f034f27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,9 +25,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "bumpalo" @@ -55,9 +55,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "clap" -version = "4.5.23" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" +checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" dependencies = [ "clap_builder", "clap_derive", @@ -65,9 +65,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.23" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" +checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" dependencies = [ "anstyle", "clap_lex", @@ -75,9 +75,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" dependencies = [ "heck", "proc-macro2", @@ -173,9 +173,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", @@ -195,15 +195,15 @@ checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "log" -version = "0.4.22" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "memchr" @@ -323,9 +323,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] @@ -410,9 +410,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rustix" -version = "0.38.42" +version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ "bitflags", "errno", @@ -421,6 +421,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + [[package]] name = "rustyline" version = "15.0.0" @@ -451,9 +457,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "syn" -version = "2.0.95" +version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", @@ -543,20 +549,21 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", @@ -568,9 +575,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -578,9 +585,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -591,9 +598,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "windows-sys" diff --git a/Cargo.toml b/Cargo.toml index 60d5ad0..1dde686 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,6 @@ members = ["talc-lang", "talc-bin", "talc-std", "talc-macros", "talc-web"] resolver = "2" - [workspace.lints.clippy] semicolon_if_nothing_returned = "warn" allow_attributes = "warn" @@ -18,6 +17,8 @@ manual_assert = "warn" needless_pass_by_value = "warn" unnested_or_patterns = "warn" redundant_else = "warn" +cast_possible_wrap = "warn" +cast_possible_truncation = "warn" [profile.release-opt] diff --git a/talc-bin/Cargo.toml b/talc-bin/Cargo.toml index 5b9ada1..d488f24 100644 --- a/talc-bin/Cargo.toml +++ b/talc-bin/Cargo.toml @@ -14,7 +14,7 @@ path = "src/main.rs" [dependencies] talc-lang = { path = "../talc-lang" } talc-std = { path = "../talc-std" } -rustyline = "15.0" -clap = { version = "4.5", features = ["std", "help", "usage", "derive", "error-context"], default-features = false } -ctrlc = "3.4" -lazy_static = "1.5" +rustyline = "15" +clap = { version = "4", features = ["std", "help", "usage", "derive", "error-context"], default-features = false } +ctrlc = "3" +lazy_static = "1" diff --git a/talc-bin/src/helper.rs b/talc-bin/src/helper.rs index d01517a..3c2d66d 100644 --- a/talc-bin/src/helper.rs +++ b/talc-bin/src/helper.rs @@ -53,7 +53,7 @@ impl Completer for TalcHelper { .map(LStr::to_string) .collect::>(); keys.sort(); - Ok((pos - res.as_bytes().len(), keys)) + Ok((pos - res.len(), keys)) } } diff --git a/talc-bin/src/main.rs b/talc-bin/src/main.rs index c93a152..c2dd10b 100644 --- a/talc-bin/src/main.rs +++ b/talc-bin/src/main.rs @@ -6,7 +6,6 @@ use talc_lang::{ optimize::optimize, parser, prelude::*, - serial, symbol::Symbol, value::{function::disasm_recursive, Value}, vm::Vm, @@ -30,10 +29,6 @@ struct Args { #[arg(short = 'a', long)] show_ast: bool, - /// Compile to a bytecode file - #[arg(short, long)] - compile: Option, - /// Don't apply optimizations #[arg(long)] no_opt: bool, @@ -86,26 +81,6 @@ fn exec(name: Symbol, src: &str, args: &Args) -> ExitCode { } } - if let Some(path) = &args.compile { - let f = std::fs::File::options() - .write(true) - .truncate(true) - .create(true) - .open(path); - let mut w = match f { - Ok(f) => f, - Err(e) => { - eprintln!("Error opening output file: {e}"); - return ExitCode::FAILURE - } - }; - if let Err(e) = serial::write_program(&mut w, &func) { - eprintln!("Error writing bytecode: {e}"); - return ExitCode::FAILURE - } - return ExitCode::SUCCESS - } - let res = vm.run_function(func.clone(), vec![func.into()]); match res { @@ -114,7 +89,7 @@ fn exec(name: Symbol, src: &str, args: &Args) -> ExitCode { ExitCode::FAILURE } Ok(Value::Bool(false)) => ExitCode::FAILURE, - Ok(Value::Int(n)) => ExitCode::from(n.to_u64().unwrap_or(1) as u8), + Ok(Value::Int(n)) => ExitCode::from(n.to_u64().unwrap_or(1).to_le_bytes()[0]), _ => ExitCode::SUCCESS, } } @@ -123,10 +98,6 @@ fn main() -> ExitCode { let args = Args::parse(); if args.repl || args.args.is_empty() { - if args.compile.is_some() { - eprintln!("Error: cannot compile in REPL mode"); - return ExitCode::FAILURE - } return repl::repl(&args) } diff --git a/talc-lang/Cargo.toml b/talc-lang/Cargo.toml index 5130336..5ca1dc0 100644 --- a/talc-lang/Cargo.toml +++ b/talc-lang/Cargo.toml @@ -9,5 +9,5 @@ workspace = true [dependencies] num = "0.4" -lazy_static = "1.5" -unicode-ident = "1.0" +lazy_static = "1" +unicode-ident = "1" diff --git a/talc-lang/src/chunk.rs b/talc-lang/src/chunk.rs index e75131b..9e24a0a 100644 --- a/talc-lang/src/chunk.rs +++ b/talc-lang/src/chunk.rs @@ -71,6 +71,7 @@ impl From for usize { impl From for i32 { #[inline] + #[expect(clippy::cast_possible_wrap)] fn from(v: Arg24) -> Self { let mut n = u32::from(v); // sign-extend @@ -252,7 +253,7 @@ impl Chunk { } pub fn set_line(&mut self, line: u32) { - let instr = self.instrs.len() as u32; + let instr = u32::try_from(self.instrs.len()).expect("chunk too big"); if let Some((i, l)) = self.lines.last_mut() { if *i == instr { *l = line; diff --git a/talc-lang/src/compiler.rs b/talc-lang/src/compiler.rs index 6c35553..cc24dd9 100644 --- a/talc-lang/src/compiler.rs +++ b/talc-lang/src/compiler.rs @@ -483,20 +483,29 @@ impl<'a> Compiler<'a> { self.emit(I::Index); } ExprKind::FnCall(f, args) => { + let Ok(argc) = u8::try_from(args.len()) else { + throw!(span.start, "too many arguments to function (max 255)") + }; self.expr(f)?; for a in args { self.expr(a)?; } - self.emit(I::Call(args.len() as u8)); + self.emit(I::Call(argc)); } ExprKind::TailCall(f, args) => { + let Ok(argc) = u8::try_from(args.len()) else { + throw!(span.start, "too many arguments to function (max 255)") + }; self.expr(f)?; for a in args { self.expr(a)?; } - self.emit(I::Tail(args.len() as u8)); + self.emit(I::Tail(argc)); } ExprKind::AssocFnCall(o, f, args) => { + let Ok(argc) = u8::try_from(args.len() + 1) else { + throw!(span.start, "too many arguments to function (max 254)") + }; self.expr(o)?; self.emit(I::Dup); self.emit(I::Symbol(Arg24::from_symbol(*f))); @@ -505,9 +514,12 @@ impl<'a> Compiler<'a> { for a in args { self.expr(a)?; } - self.emit(I::Call((args.len() + 1) as u8)); + self.emit(I::Call(argc)); } ExprKind::AssocTailCall(o, f, args) => { + let Ok(argc) = u8::try_from(args.len() + 1) else { + throw!(span.start, "too many arguments to function (max 254)") + }; self.expr(o)?; self.emit(I::Dup); self.emit(I::Symbol(Arg24::from_symbol(*f))); @@ -516,7 +528,7 @@ impl<'a> Compiler<'a> { for a in args { self.expr(a)?; } - self.emit(I::Tail((args.len() + 1) as u8)); + self.emit(I::Tail(argc)); } ExprKind::Return(e) => { if let Some(e) = e { @@ -587,15 +599,15 @@ impl<'a> Compiler<'a> { self.emit(I::NewList(0)); return Ok(()) } - fn finish_chunk(c: &mut Compiler, len: &mut usize, first: &mut bool) { + fn finish_chunk(c: &mut Compiler, len: &mut u8, first: &mut bool) { if *first { - c.emit(I::NewList(*len as u8)); + c.emit(I::NewList(*len)); *first = false; } else { if *len == 0 { return } - c.emit(I::GrowList(*len as u8)); + c.emit(I::GrowList(*len)); } *len = 0; } @@ -625,15 +637,15 @@ impl<'a> Compiler<'a> { self.emit(I::NewTable(0)); return Ok(()) } - fn finish_chunk(c: &mut Compiler, len: &mut usize, first: &mut bool) { + fn finish_chunk(c: &mut Compiler, len: &mut u8, first: &mut bool) { if *first { - c.emit(I::NewTable(*len as u8)); + c.emit(I::NewTable(*len)); *first = false; } else { if *len == 0 { return } - c.emit(I::GrowTable(*len as u8)); + c.emit(I::GrowTable(*len)); } *len = 0; } diff --git a/talc-lang/src/lib.rs b/talc-lang/src/lib.rs index 1d4e3a8..0eef978 100644 --- a/talc-lang/src/lib.rs +++ b/talc-lang/src/lib.rs @@ -6,7 +6,6 @@ pub mod number; pub mod ops; pub mod optimize; pub mod parser; -pub mod serial; pub mod symbol; pub mod value; pub mod vm; diff --git a/talc-lang/src/parser/pos.rs b/talc-lang/src/parser/pos.rs index 512f781..59309b9 100644 --- a/talc-lang/src/parser/pos.rs +++ b/talc-lang/src/parser/pos.rs @@ -32,7 +32,7 @@ impl Pos { pub fn advance(self, c: char) -> Pos { let idx = self .idx - .checked_add(c.len_utf8() as u32) + .checked_add(u32::try_from(c.len_utf8()).expect("character too long??")) .expect("source file contains more than u32::MAX chars"); if c == '\n' { Pos { diff --git a/talc-lang/src/parser/util.rs b/talc-lang/src/parser/util.rs index e3ff1ea..7fcac86 100644 --- a/talc-lang/src/parser/util.rs +++ b/talc-lang/src/parser/util.rs @@ -101,7 +101,7 @@ pub fn parse_str_escapes(src: &str) -> Result { let n1 = c.to_digit(16).ok_or(StrEscapeError::InvalidHex(c))?; let c = chars.next().ok_or(StrEscapeError::HexEof)?; let n2 = c.to_digit(16).ok_or(StrEscapeError::InvalidHex(c))?; - s.push_byte((n1 * 16 + n2) as u8); + s.push_byte(u8::try_from(n1 * 16 + n2).expect("hex too large?")); } 'u' => { let Some('{') = chars.next() else { diff --git a/talc-lang/src/serial/mod.rs b/talc-lang/src/serial/mod.rs deleted file mode 100644 index f420675..0000000 --- a/talc-lang/src/serial/mod.rs +++ /dev/null @@ -1,251 +0,0 @@ -use std::fmt; -use std::io::{self, Write}; - -use num::{bigint::Sign, BigInt}; - -use crate::{ - chunk::{Chunk, Instruction, TryTable}, - lstring::LStr, - number::Int, - prelude::*, - symbol::Symbol, - value::{function::Function, Value}, -}; - -const MAGIC: [u8; 8] = *b"\x7fTALC\0\0\0"; -const VERSION: u32 = 1; - -#[derive(Debug)] -pub enum SerialError { - Io(io::Error), - Serial(String), -} - -impl std::error::Error for SerialError {} - -impl fmt::Display for SerialError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - SerialError::Io(e) => e.fmt(f), - SerialError::Serial(e) => e.fmt(f), - } - } -} - -type Result = std::result::Result; - -impl From for SerialError { - fn from(value: io::Error) -> Self { - Self::Io(value) - } -} - -impl From for SerialError { - fn from(value: String) -> Self { - Self::Serial(value) - } -} - -impl From<&str> for SerialError { - fn from(value: &str) -> Self { - Self::Serial(value.to_owned()) - } -} - -pub fn write_program(w: &mut impl Write, prog: &Function) -> Result<()> { - ProgramWriter::new(w).write_program(prog) -} - -struct ProgramWriter<'w, W: Write> { - w: &'w mut W, -} - -impl<'w, W: Write> ProgramWriter<'w, W> { - fn new(w: &'w mut W) -> Self { - Self { w } - } - - fn write_program(&mut self, prog: &Function) -> Result<()> { - self.w.write_all(&MAGIC)?; - self.w.write_all(&VERSION.to_le_bytes())?; - self.write_function(prog)?; - Ok(()) - } - - fn write_function(&mut self, func: &Function) -> Result<()> { - self.write_bool(func.attrs.name.is_some())?; - if let Some(name) = func.attrs.name { - self.write_sym(name)?; - } - self.write_u32(func.attrs.arity as u32)?; - self.write_u32(func.state.len() as u32)?; - self.write_chunk(&func.chunk)?; - Ok(()) - } - - fn write_chunk(&mut self, chunk: &Chunk) -> Result<()> { - self.write_u32(chunk.consts.len() as u32)?; - self.write_u32(chunk.instrs.len() as u32)?; - self.write_u32(chunk.try_tables.len() as u32)?; - - for c in &chunk.consts { - self.write_value(c)?; - } - for i in &chunk.instrs { - self.write_instr(*i)?; - } - for t in &chunk.try_tables { - self.write_try_table(t)?; - } - Ok(()) - } - - fn write_value(&mut self, val: &Value) -> Result<()> { - match val { - Value::Nil => self.write_u8(0), - Value::Bool(b) => { - self.write_u8(1)?; - self.write_bool(*b) - } - Value::Symbol(sym) => { - self.write_u8(2)?; - self.write_sym(*sym) - } - Value::Int(n) => { - self.write_u8(3)?; - self.write_int(n.clone()) - } - Value::Ratio(r) => { - self.write_u8(4)?; - self.write_int(Int::from(r.numer().clone()))?; - self.write_int(Int::from(r.denom().clone())) - } - Value::Float(f) => { - self.write_u8(5)?; - self.write_f64(*f) - } - Value::Complex(z) => { - self.write_u8(6)?; - self.write_f64(z.re)?; - self.write_f64(z.im) - } - Value::Range(r) => { - self.write_u8(7)?; - if let Some(s) = &r.start { - self.write_u8(1)?; - self.write_int(s.into())?; - } else { - self.write_u8(0)?; - } - if let Some(e) = &r.end { - self.write_u8(1)?; - self.write_int(e.into())?; - } else { - self.write_u8(0)?; - } - self.write_bool(r.inclusive) - } - Value::String(s) => { - self.write_u8(8)?; - self.write_str(s) - } - Value::Function(func) => { - self.write_u8(9)?; - self.write_function(func) - } - Value::Cell(_) - | Value::List(_) - | Value::Table(_) - | Value::NativeFunc(_) - | Value::Native(_) => Err(format!( - "cannot serialize value of type {}", - val.get_type().name() - ) - .into()), - } - } - - fn write_instr(&mut self, i: Instruction) -> Result<()> { - let n: u32 = unsafe { std::mem::transmute(i) }; - self.write_u32(n) - } - - fn write_try_table(&mut self, t: &TryTable) -> Result<()> { - self.write_u32(t.local_count as u32)?; - self.write_u32(t.catches.len() as u32)?; - for catch in &t.catches { - self.write_u32(catch.addr as u32)?; - self.write_bool(catch.types.is_some())?; - if let Some(tys) = &catch.types { - self.write_u32(tys.len() as u32)?; - for ty in tys { - self.write_sym(*ty)?; - } - } - } - Ok(()) - } - - fn write_sym(&mut self, sym: Symbol) -> Result<()> { - self.write_str(sym.name()) - } - - fn write_str(&mut self, s: &LStr) -> Result<()> { - let Ok(n) = s.len().try_into() else { - return Err("string to long to serialize".into()) - }; - self.write_u32(n)?; - self.w.write_all(s.as_bytes())?; - Ok(()) - } - - fn write_f64(&mut self, x: f64) -> Result<()> { - self.w.write_all(&x.to_le_bytes())?; - Ok(()) - } - - fn write_int(&mut self, n: Int) -> Result<()> { - if let Some(i) = n.to_i64() { - self.write_u8(0x80)?; - self.write_i64(i) - } else { - let big = BigInt::from(n); - let (sign, digits) = big.to_u64_digits(); - match sign { - Sign::Minus => self.write_u8(0xff)?, - Sign::NoSign => self.write_u8(0x00)?, - Sign::Plus => self.write_u8(0x01)?, - } - self.write_u32(digits.len() as u32)?; - for digit in digits { - self.write_u64(digit)?; - } - Ok(()) - } - } - - fn write_i64(&mut self, n: i64) -> Result<()> { - self.w.write_all(&n.to_le_bytes())?; - Ok(()) - } - - fn write_u64(&mut self, n: u64) -> Result<()> { - self.w.write_all(&n.to_le_bytes())?; - Ok(()) - } - - fn write_u32(&mut self, n: u32) -> Result<()> { - self.w.write_all(&n.to_le_bytes())?; - Ok(()) - } - - fn write_u8(&mut self, n: u8) -> Result<()> { - self.w.write_all(&[n])?; - Ok(()) - } - - fn write_bool(&mut self, n: bool) -> Result<()> { - self.w.write_all(&[n as u8])?; - Ok(()) - } -} diff --git a/talc-lang/src/symbol.rs b/talc-lang/src/symbol.rs index bbffc87..5ac60e2 100644 --- a/talc-lang/src/symbol.rs +++ b/talc-lang/src/symbol.rs @@ -76,7 +76,7 @@ impl Symbol { let symno = table.names.len(); assert!(symno <= MAX_SYMBOL, "too many symbols"); - let sym = Symbol(symno as u32); + let sym = Symbol(u32::try_from(symno).expect("too many symbols")); let name = LString::leak(name.to_owned()); table.names.push(name); diff --git a/talc-lang/src/value/index.rs b/talc-lang/src/value/index.rs index 233d36c..cf90103 100644 --- a/talc-lang/src/value/index.rs +++ b/talc-lang/src/value/index.rs @@ -25,11 +25,12 @@ impl Value { ) }; let mut j = i; + let len = isize::try_from(l.len()).expect("list too big"); if j < 0 { - j += l.len() as isize; + j += len; } - if (0..l.len() as isize).contains(&j) { - Ok(l[j as usize].clone()) + if (0..len).contains(&j) { + Ok(l[usize::try_from(j).expect("checked not negative")].clone()) } else { throw!( *SYM_INDEX_ERROR, @@ -96,11 +97,12 @@ impl Value { ) }; let mut j = i; + let len = isize::try_from(l.len()).expect("list too big"); if j < 0 { - j += l.len() as isize; + j += len; } - if (0..l.len() as isize).contains(&j) { - l[j as usize] = val; + if (0..len).contains(&j) { + l[usize::try_from(j).expect("checked not negative")] = val; Ok(()) } else { throw!( diff --git a/talc-lang/src/vm.rs b/talc-lang/src/vm.rs index 3580aed..b26dbc2 100644 --- a/talc-lang/src/vm.rs +++ b/talc-lang/src/vm.rs @@ -218,6 +218,7 @@ impl Vm { mut exc: Exception, ) -> Result<()> { loop { + #[expect(clippy::cast_possible_truncation)] let line = frame.func.chunk.get_line(frame.ip as u32); exc.add_trace(line, frame.func.attrs.name); while let Some(try_frame) = frame.try_frames.pop() { diff --git a/talc-macros/Cargo.toml b/talc-macros/Cargo.toml index b325c2e..cf048fb 100644 --- a/talc-macros/Cargo.toml +++ b/talc-macros/Cargo.toml @@ -11,5 +11,5 @@ workspace = true proc-macro = true [dependencies] -syn = { version = "2.0", features = ["full"] } -quote = "1.0" +syn = { version = "2", features = ["full"] } +quote = "1" diff --git a/talc-std/Cargo.toml b/talc-std/Cargo.toml index b9377bd..21ba721 100644 --- a/talc-std/Cargo.toml +++ b/talc-std/Cargo.toml @@ -10,9 +10,9 @@ workspace = true [dependencies] talc-lang = { path = "../talc-lang" } talc-macros = { path = "../talc-macros" } -lazy_static = "1.5" +lazy_static = "1" num-bigint = { version = "0.4", features = ["rand"], optional = true } -regex = { version = "1.11", optional = true } +regex = { version = "1", optional = true } rand = { version = "0.8", optional = true } [features] diff --git a/talc-std/src/ints.rs b/talc-std/src/ints.rs index cc716d5..ca95073 100644 --- a/talc-std/src/ints.rs +++ b/talc-std/src/ints.rs @@ -502,10 +502,10 @@ pub fn popcnt(_: &mut Vm, args: Vec) -> Result { if n.is_negative() { // count_zeros always succeeds on negative numbers let z = n.count_zeros().unwrap(); - Ok(Value::from(-(z as i64))) + Ok(Value::from(-Int::from(z))) } else { // count_ones always succeeds on nonnegative numbers let z = n.count_ones().unwrap(); - Ok(Value::from(z as i64)) + Ok(Value::from(z)) } } diff --git a/talc-std/src/io.rs b/talc-std/src/io.rs index d3893e0..34994cb 100644 --- a/talc-std/src/io.rs +++ b/talc-std/src/io.rs @@ -95,11 +95,7 @@ pub fn time_ns(_: &mut Vm, _: Vec) -> Result { let time = SystemTime::now() .duration_since(UNIX_EPOCH) .expect("time went backwards"); - Ok(vec![ - (time.as_secs() as i64).into(), - (time.subsec_nanos() as i64).into(), - ] - .into()) + Ok(vec![time.as_secs().into(), time.subsec_nanos().into()].into()) } #[native_func(1)] @@ -210,7 +206,7 @@ pub fn arg(vm: &mut Vm, args: Vec) -> Result { #[native_func(0)] pub fn argc(vm: &mut Vm, args: Vec) -> Result { let [_] = unpack_args!(args); - Ok(Value::from(vm.args().len() as i64)) + Ok(Value::from(vm.args().len())) } #[native_func(0)] diff --git a/talc-std/src/iter.rs b/talc-std/src/iter.rs index 2dda07b..36faeed 100644 --- a/talc-std/src/iter.rs +++ b/talc-std/src/iter.rs @@ -647,9 +647,9 @@ pub fn table(vm: &mut Vm, args: Vec) -> Result { pub fn len(vm: &mut Vm, args: Vec) -> Result { let [_, value] = unpack_args!(args); match value { - Value::String(s) => return Ok((s.chars().count() as i64).into()), - Value::List(l) => return Ok((l.borrow().len() as i64).into()), - Value::Table(t) => return Ok((t.borrow().len() as i64).into()), + Value::String(s) => return Ok((s.chars().count()).into()), + Value::List(l) => return Ok((l.borrow().len()).into()), + Value::Table(t) => return Ok((t.borrow().len()).into()), Value::Range(ref r) => { if let Some(len) = r.len() { return Ok(len.into()) diff --git a/talc-std/src/regex.rs b/talc-std/src/regex.rs index 5df9428..4a285da 100644 --- a/talc-std/src/regex.rs +++ b/talc-std/src/regex.rs @@ -76,8 +76,8 @@ pub fn load(vm: &mut Vm) { fn match_to_value(m: Match) -> Value { Value::new_table(|t| { - t.insert((*SYM_START).into(), (m.start() as i64).into()); - t.insert((*SYM_END).into(), (m.end() as i64).into()); + t.insert((*SYM_START).into(), m.start().into()); + t.insert((*SYM_END).into(), m.end().into()); t.insert( (*SYM_STR).into(), LString::from(m.as_str().to_string()).into(), diff --git a/talc-std/src/string.rs b/talc-std/src/string.rs index 1cada6b..1110272 100644 --- a/talc-std/src/string.rs +++ b/talc-std/src/string.rs @@ -41,7 +41,7 @@ pub fn ord(_: &mut Vm, args: Vec) -> Result { if chars.next().is_some() { throw!(*SYM_VALUE_ERROR, "argument to ord must have length 1") }; - Ok(Value::from(c as u32 as i64)) + Ok(Value::from(c as u32)) } #[native_func(1)] @@ -68,7 +68,7 @@ pub fn len_bytes(_: &mut Vm, args: Vec) -> Result { "len_bytes expected string argument, got {s:#}" ) }; - Ok(Value::from(s.len() as i64)) + Ok(Value::from(s.len())) } #[native_func(1)] diff --git a/talc-std/src/value.rs b/talc-std/src/value.rs index b2154cc..922118d 100644 --- a/talc-std/src/value.rs +++ b/talc-std/src/value.rs @@ -275,7 +275,7 @@ pub fn func_arity(_: &mut Vm, args: Vec) -> Result { let Some(attrs) = func.func_attrs() else { throw!(*SYM_TYPE_ERROR, "closure_state: {func:#} is not a function") }; - Ok((attrs.arity as i64).into()) + Ok(attrs.arity.into()) } #[native_func(1)] diff --git a/talc-web/Cargo.toml b/talc-web/Cargo.toml index 32f0e98..8f52a5c 100644 --- a/talc-web/Cargo.toml +++ b/talc-web/Cargo.toml @@ -2,6 +2,7 @@ name = "talc-web" version = "0.1.0" edition = "2021" +rust-version = "1.81.0" [lib] crate-type = ["cdylib", "rlib"] diff --git a/talc-web/main.js b/talc-web/main.js index a592973..38105e8 100644 --- a/talc-web/main.js +++ b/talc-web/main.js @@ -119,15 +119,15 @@ function handleCtrlKey(event) { } function keyPressed(event) { - if (event.key === "Enter" && !event.shiftKey) { + if (event.key === "Enter" && !event.shiftKey && !event.altKey) { event.preventDefault(); execLine() - } else if (event.ctrlKey) { + } else if (event.ctrlKey && !event.altKey) { handleCtrlKey(event); - } else if (event.key === "ArrowUp") { + } else if (event.key === "ArrowUp" && !event.altKey) { event.preventDefault(); prevHistory(); - } else if (event.key === "ArrowDown") { + } else if (event.key === "ArrowDown" && !event.altKey) { event.preventDefault(); nextHistory(); }