smelt_stdlib/classes.rs
1//! Synthetic standard-library class recognition shared by frontends and codegen.
2
3/// Standard-library class modeled with dedicated runtime support instead of
4/// user-defined struct emission.
5#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
6#[non_exhaustive]
7pub enum StdlibClass {
8 /// JavaScript `Date`, represented by timestamp and date helper operations.
9 Date,
10 /// JavaScript `Map`, represented by dictionary HIR values.
11 Map,
12 /// Synthetic `RegExp` match result (`RegExp.exec` / `String.matchAll`),
13 /// backed by the generated concrete `SmeltMatch` runtime type. Consumer
14 /// reads (`m[0]`, `m.index`, `m.input`, `m.groups.name`) resolve to typed
15 /// accessors on `SmeltMatch` instead of the erased `SmeltUnknown` path.
16 Match,
17 /// Synthetic named-capture-group accessor for `matchResult.groups`. It is
18 /// the same underlying `SmeltMatch` value; a `.name` read on it resolves to
19 /// the typed named-group accessor.
20 MatchGroups,
21 /// Remeda parser helper result class synthesized during TypeScript lowering.
22 MatchFnResult,
23 /// JavaScript `RegExp`, backed by the generated regex runtime shim.
24 RegExp,
25 /// JavaScript `Set`, represented by set HIR values.
26 Set,
27}
28
29/// Reserved synthetic class name for a `RegExp` match result value.
30///
31/// The name is not writable in user TypeScript (double-underscore prefix), so
32/// it never collides with a source class; it exists only to carry the concrete
33/// match shape through the internal type system.
34pub const MATCH_CLASS_NAME: &str = "__SmeltMatch";
35
36/// Reserved synthetic class name for `matchResult.groups` named-group access.
37pub const MATCH_GROUPS_CLASS_NAME: &str = "__SmeltMatchGroups";
38
39/// Return the stdlib class modeled by a TypeScript class type name.
40///
41/// Codegen consults this instead of comparing class symbol names inline so
42/// stdlib class identities stay in one registry.
43#[must_use]
44pub fn typescript_stdlib_class(name: &str) -> Option<StdlibClass> {
45 match name {
46 "Date" => Some(StdlibClass::Date),
47 "Map" => Some(StdlibClass::Map),
48 MATCH_CLASS_NAME => Some(StdlibClass::Match),
49 MATCH_GROUPS_CLASS_NAME => Some(StdlibClass::MatchGroups),
50 "MatchFnResult" => Some(StdlibClass::MatchFnResult),
51 "RegExp" => Some(StdlibClass::RegExp),
52 "Set" => Some(StdlibClass::Set),
53 _ => None,
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 /// Exact stdlib class names resolve to their registry identity.
62 #[test]
63 fn recognizes_stdlib_class_names() {
64 assert_eq!(typescript_stdlib_class("Date"), Some(StdlibClass::Date));
65 assert_eq!(typescript_stdlib_class("Map"), Some(StdlibClass::Map));
66 assert_eq!(
67 typescript_stdlib_class(MATCH_CLASS_NAME),
68 Some(StdlibClass::Match)
69 );
70 assert_eq!(
71 typescript_stdlib_class(MATCH_GROUPS_CLASS_NAME),
72 Some(StdlibClass::MatchGroups)
73 );
74 assert_eq!(
75 typescript_stdlib_class("MatchFnResult"),
76 Some(StdlibClass::MatchFnResult)
77 );
78 assert_eq!(typescript_stdlib_class("RegExp"), Some(StdlibClass::RegExp));
79 assert_eq!(typescript_stdlib_class("Set"), Some(StdlibClass::Set));
80 }
81
82 /// User class names never resolve to a stdlib identity.
83 #[test]
84 fn rejects_user_class_names() {
85 for name in ["Regexp", "RegExpLike", "Dates", "HashMap", "MyClass"] {
86 assert_eq!(typescript_stdlib_class(name), None);
87 }
88 }
89}