Skip to main content

perl_builtins_phf/
lib.rs

1//! Consolidated built-in function signatures for Perl using perfect hash
2//!
3//! This module provides a single source of truth for all Perl built-in function signatures
4//! Used by both InlayHints and SignatureHelp providers
5
6use phf::phf_map;
7
8/// Built-in function signatures as a perfect hash map
9/// Each entry maps function name to parameter names
10pub static BUILTIN_SIGS: phf::Map<&'static str, &'static [&'static str]> = phf_map! {
11    // ===== I/O Functions =====
12    "print" => &["FILEHANDLE", "LIST"],
13    "printf" => &["FILEHANDLE", "FORMAT", "LIST"],
14    "say" => &["FILEHANDLE", "LIST"],
15    "open" => &["FILEHANDLE", "MODE", "FILENAME"],
16    "sysopen" => &["FILEHANDLE", "FILENAME", "MODE", "PERMS"],
17    "close" => &["FILEHANDLE"],
18    "read" => &["FILEHANDLE", "SCALAR", "LENGTH", "OFFSET"],
19    "readpipe" => &["EXPR"],
20    "sysread" => &["FILEHANDLE", "SCALAR", "LENGTH", "OFFSET"],
21    "write" => &["FILEHANDLE"],
22    "syswrite" => &["FILEHANDLE", "SCALAR", "LENGTH", "OFFSET"],
23    "binmode" => &["FILEHANDLE", "LAYER"],
24    "seek" => &["FILEHANDLE", "POSITION", "WHENCE"],
25    "tell" => &["FILEHANDLE"],
26    "truncate" => &["FILEHANDLE", "LENGTH"],
27    "eof" => &["FILEHANDLE"],
28    "fileno" => &["FILEHANDLE"],
29    "flock" => &["FILEHANDLE", "OPERATION"],
30    "fcntl" => &["FILEHANDLE", "FUNCTION", "SCALAR"],
31    "ioctl" => &["FILEHANDLE", "FUNCTION", "SCALAR"],
32    "getc" => &["FILEHANDLE"],
33    "readline" => &["FILEHANDLE"],
34    "select" => &["FILEHANDLE"],
35    "sysseek" => &["FILEHANDLE", "POSITION", "WHENCE"],
36
37    // ===== String Functions =====
38    "chomp" => &["VARIABLE"],
39    "chop" => &["VARIABLE"],
40    "chr" => &["NUMBER"],
41    "crypt" => &["PLAINTEXT", "SALT"],
42    "fc" => &["EXPR"],
43    "index" => &["STR", "SUBSTR", "POSITION"],
44    "lc" => &["EXPR"],
45    "lcfirst" => &["EXPR"],
46    "length" => &["EXPR"],
47    "ord" => &["EXPR"],
48    "pack" => &["TEMPLATE", "LIST"],
49    "reverse" => &["LIST"],
50    "rindex" => &["STR", "SUBSTR", "POSITION"],
51    "sprintf" => &["FORMAT", "LIST"],
52    "substr" => &["EXPR", "OFFSET", "LENGTH", "REPLACEMENT"],
53    "uc" => &["EXPR"],
54    "ucfirst" => &["EXPR"],
55    "unpack" => &["TEMPLATE", "EXPR"],
56    "quotemeta" => &["EXPR"],
57
58    // ===== Array Functions =====
59    "push" => &["ARRAY", "LIST"],
60    "pop" => &["ARRAY"],
61    "shift" => &["ARRAY"],
62    "unshift" => &["ARRAY", "LIST"],
63    "splice" => &["ARRAY", "OFFSET", "LENGTH", "LIST"],
64    "grep" => &["BLOCK", "LIST"],
65    "map" => &["BLOCK", "LIST"],
66    "sort" => &["BLOCK", "LIST"],
67    "join" => &["EXPR", "LIST"],
68    "split" => &["PATTERN", "EXPR", "LIMIT"],
69
70    // ===== Hash Functions =====
71    "each" => &["HASH"],
72    "keys" => &["HASH"],
73    "values" => &["HASH"],
74    "delete" => &["EXPR"],
75    "exists" => &["EXPR"],
76
77    // ===== Math Functions =====
78    "abs" => &["VALUE"],
79    "atan2" => &["Y", "X"],
80    "cos" => &["EXPR"],
81    "exp" => &["EXPR"],
82    "hex" => &["EXPR"],
83    "int" => &["EXPR"],
84    "log" => &["EXPR"],
85    "oct" => &["EXPR"],
86    "rand" => &["EXPR"],
87    "sin" => &["EXPR"],
88    "sqrt" => &["EXPR"],
89    "srand" => &["EXPR"],
90
91    // ===== File/Directory Functions =====
92    "chdir" => &["EXPR"],
93    "chroot" => &["FILENAME"],
94    "chmod" => &["MODE", "LIST"],
95    "chown" => &["UID", "GID", "LIST"],
96    "link" => &["OLDFILE", "NEWFILE"],
97    "lstat" => &["FILEHANDLE"],
98    "mkdir" => &["FILENAME", "MODE"],
99    "opendir" => &["DIRHANDLE", "EXPR"],
100    "readdir" => &["DIRHANDLE"],
101    "readlink" => &["EXPR"],
102    "glob" => &["EXPR"],
103    "rename" => &["OLDNAME", "NEWNAME"],
104    "rmdir" => &["FILENAME"],
105    "stat" => &["FILEHANDLE"],
106    "symlink" => &["OLDFILE", "NEWFILE"],
107    "umask" => &["EXPR"],
108    "unlink" => &["LIST"],
109    "utime" => &["ATIME", "MTIME", "LIST"],
110    "closedir" => &["DIRHANDLE"],
111    "rewinddir" => &["DIRHANDLE"],
112    "seekdir" => &["DIRHANDLE", "POS"],
113    "telldir" => &["DIRHANDLE"],
114
115    // ===== File Test Operators =====
116    "-e" => &["FILE"],
117    "-f" => &["FILE"],
118    "-d" => &["FILE"],
119    "-r" => &["FILE"],
120    "-w" => &["FILE"],
121    "-x" => &["FILE"],
122    "-o" => &["FILE"],
123    "-R" => &["FILE"],
124    "-W" => &["FILE"],
125    "-X" => &["FILE"],
126    "-O" => &["FILE"],
127    "-z" => &["FILE"],
128    "-s" => &["FILE"],
129    "-l" => &["FILE"],
130    "-p" => &["FILE"],
131    "-S" => &["FILE"],
132    "-b" => &["FILE"],
133    "-c" => &["FILE"],
134    "-t" => &["FILE"],
135    "-u" => &["FILE"],
136    "-g" => &["FILE"],
137    "-k" => &["FILE"],
138    "-T" => &["FILE"],
139    "-B" => &["FILE"],
140    "-M" => &["FILE"],
141    "-A" => &["FILE"],
142    "-C" => &["FILE"],
143
144    // ===== Process Functions =====
145    "alarm" => &["SECONDS"],
146    "exec" => &["PROGRAM", "LIST"],
147    "fork" => &[],
148    "getpgrp" => &["PID"],
149    "getppid" => &[],
150    "getpriority" => &["WHICH", "WHO"],
151    "kill" => &["SIGNAL", "LIST"],
152    "pipe" => &["READHANDLE", "WRITEHANDLE"],
153    "setpgrp" => &["PID", "PGRP"],
154    "setpriority" => &["WHICH", "WHO", "PRIORITY"],
155    "syscall" => &["NUMBER", "LIST"],
156    "sleep" => &["EXPR"],
157    "system" => &["PROGRAM", "LIST"],
158    "times" => &[],
159    "wait" => &[],
160    "waitpid" => &["PID", "FLAGS"],
161
162    // ===== Time Functions =====
163    "gmtime" => &["EXPR"],
164    "localtime" => &["EXPR"],
165    "time" => &[],
166
167    // ===== Network Functions =====
168    "accept" => &["NEWSOCKET", "GENERICSOCKET"],
169    "bind" => &["SOCKET", "NAME"],
170    "connect" => &["SOCKET", "NAME"],
171    "getpeername" => &["SOCKET"],
172    "getsockname" => &["SOCKET"],
173    "getsockopt" => &["SOCKET", "LEVEL", "OPTNAME"],
174    "listen" => &["SOCKET", "QUEUESIZE"],
175    "recv" => &["SOCKET", "SCALAR", "LENGTH", "FLAGS"],
176    "send" => &["SOCKET", "MSG", "FLAGS", "TO"],
177    "setsockopt" => &["SOCKET", "LEVEL", "OPTNAME", "OPTVAL"],
178    "shutdown" => &["SOCKET", "HOW"],
179    "socket" => &["SOCKET", "DOMAIN", "TYPE", "PROTOCOL"],
180    "socketpair" => &["SOCKET1", "SOCKET2", "DOMAIN", "TYPE", "PROTOCOL"],
181    "sockatmark" => &["SOCKET"],
182
183    // ===== System Info Functions =====
184    "gethostbyaddr" => &["ADDR", "ADDRTYPE"],
185    "gethostbyname" => &["NAME"],
186    "gethostent" => &[],
187    "getnetbyaddr" => &["ADDR", "ADDRTYPE"],
188    "getnetbyname" => &["NAME"],
189    "getnetent" => &[],
190    "getprotobyname" => &["NAME"],
191    "getprotobynumber" => &["NUMBER"],
192    "getprotoent" => &[],
193    "getservbyname" => &["NAME", "PROTO"],
194    "getservbyport" => &["PORT", "PROTO"],
195    "getservent" => &[],
196    "sethostent" => &["STAYOPEN"],
197    "setnetent" => &["STAYOPEN"],
198    "setprotoent" => &["STAYOPEN"],
199    "setservent" => &["STAYOPEN"],
200    "endhostent" => &[],
201    "endnetent" => &[],
202    "endprotoent" => &[],
203    "endservent" => &[],
204
205    // ===== User/Group Functions =====
206    "getgrent" => &[],
207    "getgrgid" => &["GID"],
208    "getgrnam" => &["NAME"],
209    "getlogin" => &[],
210    "getuid" => &[],
211    "geteuid" => &[],
212    "getgid" => &[],
213    "getegid" => &[],
214    "getgroups" => &[],
215    "setuid" => &["UID"],
216    "seteuid" => &["UID"],
217    "setgid" => &["GID"],
218    "setegid" => &["GID"],
219    "setgroups" => &["LIST"],
220    "getpwent" => &[],
221    "getpwnam" => &["NAME"],
222    "getpwuid" => &["UID"],
223    "setgrent" => &[],
224    "setpwent" => &[],
225    "endgrent" => &[],
226    "endpwent" => &[],
227
228    // ===== IPC Functions =====
229    "msgctl" => &["ID", "CMD", "ARG"],
230    "msgget" => &["KEY", "FLAGS"],
231    "msgrcv" => &["ID", "VAR", "SIZE", "TYPE", "FLAGS"],
232    "msgsnd" => &["ID", "MSG", "FLAGS"],
233    "semctl" => &["ID", "SEMNUM", "CMD", "ARG"],
234    "semget" => &["KEY", "NSEMS", "FLAGS"],
235    "semop" => &["ID", "OPSTRING"],
236    "shmctl" => &["ID", "CMD", "ARG"],
237    "shmget" => &["KEY", "SIZE", "FLAGS"],
238    "shmread" => &["ID", "VAR", "POS", "SIZE"],
239    "shmwrite" => &["ID", "STRING", "POS", "SIZE"],
240
241    // ===== Database Functions =====
242    "dbmclose" => &["HASH"],
243    "dbmopen" => &["HASH", "DBNAME", "MODE"],
244    "tie" => &["VARIABLE", "CLASSNAME", "LIST"],
245    "tied" => &["VARIABLE"],
246    "untie" => &["VARIABLE"],
247
248    // ===== Miscellaneous Functions =====
249    "bless" => &["REF", "CLASSNAME"],
250    "caller" => &["EXPR"],
251    "die" => &["LIST"],
252    "do" => &["BLOCK"],
253    "eval" => &["EXPR"],
254    "exit" => &["EXPR"],
255    "goto" => &["LABEL"],
256    "last" => &["LABEL"],
257    "next" => &["LABEL"],
258    "redo" => &["LABEL"],
259    "ref" => &["EXPR"],
260    "require" => &["VERSION"],
261    "return" => &["LIST"],
262    "scalar" => &["EXPR"],
263    "undef" => &["EXPR"],
264    "wantarray" => &[],
265    "warn" => &["LIST"],
266    "defined" => &["EXPR"],
267    "dump" => &["LABEL"],
268    "formline" => &["PICTURE", "LIST"],
269    "local" => &["EXPR"],
270    "my" => &["VARLIST"],
271    "our" => &["VARLIST"],
272    "state" => &["VARLIST"],
273    "reset" => &["EXPR"],
274    "study" => &["SCALAR"],
275    "pos" => &["SCALAR"],
276    "use" => &["MODULE", "VERSION", "LIST"],
277    "vec" => &["EXPR", "OFFSET", "BITS"],
278    "lock" => &["THING"],
279    "prototype" => &["FUNCTION"],
280};
281
282/// Full signatures for documentation (used by signature help)
283pub static BUILTIN_FULL_SIGS: phf::Map<&'static str, &'static [&'static str]> = phf_map! {
284    "print" => &["print FILEHANDLE LIST", "print FILEHANDLE", "print LIST", "print"],
285    "printf" => &["printf FILEHANDLE FORMAT, LIST", "printf FORMAT, LIST"],
286    "say" => &["say FILEHANDLE LIST", "say FILEHANDLE", "say LIST", "say"],
287    "open" => &["open FILEHANDLE, MODE, FILENAME", "open FILEHANDLE, EXPR", "open FILEHANDLE"],
288    "close" => &["close FILEHANDLE", "close"],
289    "substr" => &["substr EXPR, OFFSET, LENGTH, REPLACEMENT", "substr EXPR, OFFSET, LENGTH", "substr EXPR, OFFSET"],
290    "splice" => &["splice ARRAY, OFFSET, LENGTH, LIST", "splice ARRAY, OFFSET, LENGTH", "splice ARRAY, OFFSET", "splice ARRAY"],
291    "split" => &["split PATTERN, EXPR, LIMIT", "split PATTERN, EXPR", "split PATTERN", "split"],
292    // Add more as needed for detailed signatures
293};
294
295/// Get parameter names for a builtin function
296pub fn get_param_names(function_name: &str) -> &'static [&'static str] {
297    BUILTIN_SIGS.get(function_name).copied().unwrap_or(&[])
298}
299
300/// Check if a function is a builtin
301pub fn is_builtin(function_name: &str) -> bool {
302    BUILTIN_SIGS.contains_key(function_name)
303}
304
305/// Get the number of builtins
306pub fn builtin_count() -> usize {
307    BUILTIN_SIGS.len()
308}
309
310#[cfg(test)]
311mod tests {
312    use super::{builtin_count, get_param_names, is_builtin};
313
314    #[test]
315    fn exposes_common_builtins() {
316        assert!(is_builtin("print"));
317        assert!(!is_builtin("not_a_builtin"));
318    }
319
320    #[test]
321    fn returns_open_param_names() {
322        assert_eq!(get_param_names("open"), ["FILEHANDLE", "MODE", "FILENAME"]);
323        assert!(builtin_count() > 150);
324    }
325}