diff --git a/Cargo.lock b/Cargo.lock index bf08894..33f018a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -367,9 +367,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rustix" -version = "0.38.38" +version = "0.38.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" +checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" dependencies = [ "bitflags", "errno", @@ -436,7 +436,6 @@ dependencies = [ "num-complex", "num-rational", "num-traits", - "thiserror", "unicode-ident", ] @@ -459,26 +458,6 @@ dependencies = [ "talc-macros", ] -[[package]] -name = "thiserror" -version = "1.0.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3c6efbfc763e64eb85c11c25320f0737cb7364c4b6336db90aa9ebe27a0bbd" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b607164372e89797d78b8e23a6d67d5d1038c1c65efd52e1389ef8b77caba2a6" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "unicode-ident" version = "1.0.13" diff --git a/Cargo.toml b/Cargo.toml index 9144afb..dbc4fa2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,11 @@ members = ["talc-lang", "talc-bin", "talc-std", "talc-macros"] resolver = "2" -[profile.release-lto] +[profile.release-opt] inherits = "release" lto = "fat" +strip = true +codegen-units = 1 +panic = "abort" + + diff --git a/talc-lang/Cargo.toml b/talc-lang/Cargo.toml index 78ebd80..b6938ca 100644 --- a/talc-lang/Cargo.toml +++ b/talc-lang/Cargo.toml @@ -7,7 +7,6 @@ edition = "2021" num-complex = "0.4" num-rational = { version = "0.4", default-features = false, features = [] } num-traits = "0.2" -thiserror = "1.0" lazy_static = "1.5" unicode-ident = "1.0" diff --git a/talc-lang/src/chunk.rs b/talc-lang/src/chunk.rs index 73920b2..24b55ae 100644 --- a/talc-lang/src/chunk.rs +++ b/talc-lang/src/chunk.rs @@ -158,10 +158,10 @@ impl std::fmt::Display for Instruction { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match *self { Self::Nop => write!(f, "nop"), - Self::LoadLocal(a) => write!(f, "load {}", usize::from(a)), - Self::StoreLocal(a) => write!(f, "store {}", usize::from(a)), + Self::LoadLocal(a) => write!(f, "load ${}", usize::from(a)), + Self::StoreLocal(a) => write!(f, "store ${}", usize::from(a)), Self::NewLocal => write!(f, "newlocal"), - Self::DropLocal(n) => write!(f, "discardlocal {}", usize::from(n)), + Self::DropLocal(n) => write!(f, "discardlocal ${}", usize::from(n)), Self::LoadGlobal(s) => write!( f, "loadglobal {}", @@ -172,14 +172,14 @@ impl std::fmt::Display for Instruction { "storeglobal {}", Symbol::try_from(s).expect("symbol does not exist").name() ), - Self::CloseOver(n) => write!(f, "closeover {}", usize::from(n)), - Self::Closure(c) => write!(f, "closure {}", usize::from(c)), - Self::LoadUpvalue(n) => write!(f, "load_upval {}", usize::from(n)), - Self::StoreUpvalue(n) => write!(f, "store_upval {}", usize::from(n)), - Self::ContinueUpvalue(n) => write!(f, "cont_upval {}", usize::from(n)), - Self::LoadClosedLocal(n) => write!(f, "load_closed {}", usize::from(n)), - Self::StoreClosedLocal(n) => write!(f, "store_closed {}", usize::from(n)), - Self::Const(c) => write!(f, "const {}", usize::from(c)), + Self::CloseOver(n) => write!(f, "closeover ${}", usize::from(n)), + Self::Closure(c) => write!(f, "closure %{}", usize::from(c)), + Self::LoadUpvalue(n) => write!(f, "load_upval ^{}", usize::from(n)), + Self::StoreUpvalue(n) => write!(f, "store_upval ^{}", usize::from(n)), + Self::ContinueUpvalue(n) => write!(f, "cont_upval ^{}", usize::from(n)), + Self::LoadClosedLocal(n) => write!(f, "load_closed ${}", usize::from(n)), + Self::StoreClosedLocal(n) => write!(f, "store_closed ${}", usize::from(n)), + Self::Const(c) => write!(f, "const %{}", usize::from(c)), Self::Int(i) => write!(f, "int {}", i64::from(i)), Self::Symbol(s) => write!( f, @@ -190,24 +190,24 @@ impl std::fmt::Display for Instruction { Self::Nil => write!(f, "nil"), Self::Dup => write!(f, "dup"), Self::DupTwo => write!(f, "duptwo"), - Self::Drop(n) => write!(f, "discard {}", usize::from(n)), + Self::Drop(n) => write!(f, "discard #{}", usize::from(n)), Self::Swap => write!(f, "swap"), Self::UnaryOp(o) => write!(f, "unary {o:?}"), Self::BinaryOp(o) => write!(f, "binary {o:?}"), - Self::NewList(n) => write!(f, "newlist {n}"), - Self::GrowList(n) => write!(f, "growlist {n}"), - Self::NewTable(n) => write!(f, "newtable {n}"), - Self::GrowTable(n) => write!(f, "growtable {n}"), + Self::NewList(n) => write!(f, "newlist #{n}"), + Self::GrowList(n) => write!(f, "growlist #{n}"), + Self::NewTable(n) => write!(f, "newtable #{n}"), + Self::GrowTable(n) => write!(f, "growtable #{n}"), Self::Index => write!(f, "index"), Self::StoreIndex => write!(f, "storeindex"), - Self::Jump(a) => write!(f, "jump {}", usize::from(a)), - Self::JumpTrue(a) => write!(f, "jumptrue {}", usize::from(a)), - Self::JumpFalse(a) => write!(f, "jumpfalse {}", usize::from(a)), + Self::Jump(a) => write!(f, "jump @{}", usize::from(a)), + Self::JumpTrue(a) => write!(f, "jumptrue @{}", usize::from(a)), + Self::JumpFalse(a) => write!(f, "jumpfalse @{}", usize::from(a)), Self::IterBegin => write!(f, "iterbegin"), - Self::IterTest(a) => write!(f, "itertest {}", usize::from(a)), - Self::BeginTry(t) => write!(f, "begintry {}", usize::from(t)), + Self::IterTest(a) => write!(f, "itertest @{}", usize::from(a)), + Self::BeginTry(t) => write!(f, "begintry #{}", usize::from(t)), Self::EndTry => write!(f, "endtry"), - Self::Call(n) => write!(f, "call {n}"), + Self::Call(n) => write!(f, "call #{n}"), Self::Return => write!(f, "return"), } } diff --git a/talc-lang/src/lstring.rs b/talc-lang/src/lstring.rs index 80325a0..9de9765 100644 --- a/talc-lang/src/lstring.rs +++ b/talc-lang/src/lstring.rs @@ -855,6 +855,11 @@ impl LStr { self.to_str().is_ok() } + #[inline] + pub const fn is_ascii(&self) -> bool { + self.as_bytes().is_ascii() + } + #[inline] pub fn to_utf8_lossy(&self) -> Cow<'_, LStr> { match String::from_utf8_lossy(self.as_bytes()) { diff --git a/talc-lang/src/parser/lexer.rs b/talc-lang/src/parser/lexer.rs index e1b0158..05b45d9 100644 --- a/talc-lang/src/parser/lexer.rs +++ b/talc-lang/src/parser/lexer.rs @@ -402,7 +402,6 @@ impl<'s> Lexer<'s> { self.next()?; } match self.peek()? { - 'r' => todo!("arbitrary radix integer literals"), 'e' => { self.next()?; self.next_float(true) diff --git a/talc-lang/src/parser/util.rs b/talc-lang/src/parser/util.rs index 1f8cb31..08cfb83 100644 --- a/talc-lang/src/parser/util.rs +++ b/talc-lang/src/parser/util.rs @@ -1,18 +1,18 @@ use core::fmt; use std::num::{ParseFloatError, ParseIntError}; -use thiserror::Error; - use crate::lstring::{LStr, LString}; use super::Span; -#[derive(Clone, Debug, Error)] +#[derive(Clone, Debug)] pub struct ParserError { pub span: Span, pub msg: String, } +impl std::error::Error for ParserError {} + impl fmt::Display for ParserError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{} | {}", self.span, self.msg) @@ -34,26 +34,43 @@ impl SpanParserError for Result { } } -#[derive(Clone, Copy, Debug, Error)] +#[derive(Clone, Copy, Debug)] pub enum StrEscapeError { - #[error("EOF in string escape")] Eof, - #[error("EOF in string escape \\x")] HexEof, - #[error("EOF in string escape \\u")] UnicodeEof, - #[error("invalid string escape \\{0}")] Invalid(char), - #[error("invalid hex digit '{0}' in string escape")] InvalidHex(char), - #[error("missing brace after string escape \\u")] MissingBrace, - #[error("invalid codepoint in string escape: {0:x}")] InvalidCodepoint(u32), - #[error("codepoint in string escape too large")] CodepointTooLarge, } +impl std::error::Error for StrEscapeError {} + +impl fmt::Display for StrEscapeError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + StrEscapeError::Eof => write!(f, "EOF in string escape"), + StrEscapeError::HexEof => write!(f, "EOF in string escape \\x"), + StrEscapeError::UnicodeEof => write!(f, "EOF in string escape \\u"), + StrEscapeError::Invalid(c) => write!(f, "invalid string escape \\{c}"), + StrEscapeError::InvalidHex(x) => { + write!(f, "invalid hex digit '{x}' in string escape") + } + StrEscapeError::MissingBrace => { + write!(f, "missing brace after string escape \\u") + } + StrEscapeError::InvalidCodepoint(n) => { + write!(f, "invalid codepoint in string escape: U+{n:0>4x})") + } + StrEscapeError::CodepointTooLarge => { + write!(f, "codepoint in string escape too large") + } + } + } +} + pub fn parse_str_escapes(src: &str) -> Result { let mut s = LString::with_capacity(src.len()); let mut chars = src.chars(); diff --git a/talc-std/src/string.rs b/talc-std/src/string.rs index 2ee25b8..4304d11 100644 --- a/talc-std/src/string.rs +++ b/talc-std/src/string.rs @@ -19,6 +19,7 @@ pub fn load(vm: &mut Vm) { vm.set_global_name("lower", lower().into()); vm.set_global_name("starts_with", starts_with().into()); vm.set_global_name("ends_with", ends_with().into()); + vm.set_global_name("is_ascii", is_ascii().into()); vm.set_global_name("is_utf8", is_utf8().into()); vm.set_global_name("to_utf8", to_utf8().into()); vm.set_global_name("to_utf8_lossy", to_utf8_lossy().into()); @@ -124,6 +125,18 @@ pub fn ends_with(_: &mut Vm, args: Vec) -> Result { Ok(res.into()) } +#[native_func(1)] +pub fn is_ascii(_: &mut Vm, args: Vec) -> Result { + let [_, s] = unpack_args!(args); + let Value::String(s) = s else { + throw!( + *SYM_TYPE_ERROR, + "is_ascii expected string argument, got {s:#}" + ) + }; + Ok(s.is_ascii().into()) +} + #[native_func(1)] pub fn is_utf8(_: &mut Vm, args: Vec) -> Result { let [_, s] = unpack_args!(args);