pub(crate) fn rt_builtin_symbol(name: &str) -> Option<&'static str> {
if let Some(sym) = typelisp_front::c_struct::rt_symbol(name) {
return Some(sym);
}
Some(match name {
typelisp_front::ffi_callback::ADDRESS_BUILTIN => "rt_ffi_callback_address",
"sexpr-car" => "rt_car",
"sexpr-cdr" => "rt_cdr",
"sexpr-cons" => "rt_cons",
"sexpr-consp" => "rt_consp",
"sexpr-null" => "rt_null",
"sexpr-atom" => "rt_atom",
"sexpr-symp" => "rt_symp",
"sexpr-int" => "rt_sexpr_int",
"sexpr-i32" => "rt_sexpr_i32",
"sexpr-bool" => "rt_sexpr_bool",
"sexpr-char" => "rt_sexpr_char",
"sexpr-f64" => "rt_f64_value",
"sexpr-f32" => "rt_f32_value",
"sexpr-i8" => "rt_sexpr_i8",
"sexpr-i16" => "rt_sexpr_i16",
"sexpr-u8" => "rt_sexpr_u8",
"sexpr-u16" => "rt_sexpr_u16",
"sexpr-u32" => "rt_sexpr_u32",
"sexpr-str" => "rt_sexpr_str",
"sexpr-sym-name" => "rt_sym_name",
"symbol->string" => "rt_sym_name",
"string->symbol" => "rt_intern_symbol",
"equal" => "rt_sexpr_equal",
"equalp" => "rt_sexpr_equalp",
"parse-float" => "rt_parse_float",
"get-universal-time" => "rt_get_universal_time",
"get-internal-real-time" => "rt_get_internal_real_time",
"command-line-args" => "rt_command_line_args",
"getenv" => "rt_getenv",
"home-directory" => "rt_home_directory",
"lisp-implementation-version" => "rt_lisp_implementation_version",
"machine-type" => "rt_machine_type",
"software-type" => "rt_software_type",
"get-internal-run-time" => "rt_get_internal_run_time",
"machine-instance" => "rt_machine_instance",
"machine-version" => "rt_machine_version",
"software-version" => "rt_software_version",
"timezone-offset-seconds" => "rt_timezone_offset_seconds",
"timezone-daylight-p" => "rt_timezone_daylight_p",
"exit" => "rt_exit",
"read" => "rt_read",
"read-datum-at" => "rt_read_datum_at",
"eval" => "rt_eval",
"macroexpand-1" => "rt_macroexpand_1",
"macroexpand" => "rt_macroexpand",
"format-rt" => "rt_format",
"print-rt" => "rt_print",
"println-rt" => "rt_println",
"pprint-rt" => "rt_pprint",
"pprint-block-start-rt" => "rt_pprint_block_start",
"pprint-block-end-rt" => "rt_pprint_block_end",
"pprint-newline" => "rt_pprint_newline",
"pprint-indent" => "rt_pprint_indent",
"pprint-tab" => "rt_pprint_tab",
"pprint-pop" => "rt_pprint_pop",
"pprint-list-exhausted" => "rt_pprint_list_exhausted",
"random-state-next" => "rt_random_state_next",
"random-state-copy" => "rt_random_state_copy",
"make-random-state-fresh" => "rt_make_random_state_fresh",
"seed-random-state" => "rt_seed_random_state",
"stream-stdin" => "rt_stream_stdin",
"stream-stdout" => "rt_stream_stdout",
"stream-stderr" => "rt_stream_stderr",
"stream-string-input" => "rt_stream_string_input",
"stream-string-output" => "rt_stream_string_output",
"stream-open-file" => "rt_stream_open_file",
"stream-close" => "rt_stream_close",
"stream-open-p" => "rt_stream_open_p",
"stream-describe" => "rt_stream_describe",
"stream-input-p" => "rt_stream_input_p",
"stream-output-p" => "rt_stream_output_p",
"stream-read-char" => "rt_stream_read_char",
"stream-read-byte" => "rt_stream_read_byte",
"stream-write-byte" => "rt_stream_write_byte",
"stream-unread-char" => "rt_stream_unread_char",
"set-macro-character" => "rt_set_macro_character",
"get-macro-character" => "rt_get_macro_character",
"set-dispatch-macro-character" => "rt_set_dispatch_macro_character",
"get-dispatch-macro-character" => "rt_get_dispatch_macro_character",
"sleep" => "rt_suspend_sleep",
"yield" => "rt_suspend_yield",
"net-wait" => "rt_suspend_io",
"net-wait-for" => "rt_suspend_io_for",
"heap-info" => "rt_heap_info",
"dribble-start" => "rt_dribble_start",
"dribble-stop" => "rt_dribble_stop",
"ed-open" => "rt_ed_open",
"stream-listen" => "rt_stream_listen",
"stream-position" => "rt_stream_position",
"stream-write-string" => "rt_stream_write_string",
"stream-at-line-start" => "rt_stream_at_line_start",
"stream-finish-output" => "rt_stream_finish_output",
"stream-take-output-string" => "rt_stream_take_output_string",
"file-exists-p" => "rt_file_exists_p",
"file-delete" => "rt_file_delete",
"file-truename" => "rt_file_truename",
"file-modified-date" => "rt_file_modified_date",
"file-owner-name" => "rt_file_owner_name",
"file-directory-p" => "rt_file_directory_p",
"file-list-directory" => "rt_file_list_directory",
"file-create-directories" => "rt_file_create_directories",
"file-rename" => "rt_file_rename",
"net-resolve-begin" => "rt_net_resolve_begin",
"net-resolve-finish" => "rt_net_resolve_finish",
"net-tls-start" => "rt_net_tls_start",
"net-tls-listen" => "rt_net_tls_listen",
"net-socket-error" => "rt_net_socket_error",
"net-peer-subject" => "rt_net_peer_subject",
"net-server-name" => "rt_net_server_name",
"net-set-nodelay" => "rt_net_set_nodelay",
"net-set-keepalive" => "rt_net_set_keepalive",
"net-set-keepalive-period" => "rt_net_set_keepalive_period",
"net-tls-add-certificate" => "rt_net_tls_add_certificate",
"net-tls-handshake" => "rt_net_tls_handshake",
"net-udp-bind" => "rt_net_udp_bind",
"net-udp-send-to" => "rt_net_udp_send_to",
"net-udp-recv" => "rt_net_udp_recv",
"net-udp-last-sender" => "rt_net_udp_last_sender",
"net-connect-begin" => "rt_net_connect_begin",
"net-connect-finish" => "rt_net_connect_finish",
"net-listen" => "rt_net_listen",
"net-unix-connect" => "rt_net_unix_connect",
"net-unix-listen" => "rt_net_unix_listen",
"net-accept" => "rt_net_accept",
"net-fill" => "rt_net_fill",
"net-pop-byte" => "rt_net_pop_byte",
"net-pop-char" => "rt_net_pop_char",
"net-buffered-p" => "rt_net_buffered_p",
"net-push-string" => "rt_net_push_string",
"net-push-byte" => "rt_net_push_byte",
"net-flush" => "rt_net_flush",
"net-shutdown-write" => "rt_net_shutdown_write",
"net-local-address" => "rt_net_local_address",
"net-peer-address" => "rt_net_peer_address",
_ => return None,
})
}
pub(crate) fn rt_suspend_method_symbol(type_local: &str, method: &str) -> Option<&'static str> {
match (type_local, method) {
("task", "wait") => Some("rt_suspend_wait"),
("thread", "join") => Some("rt_suspend_wait"),
("chan", "new") => Some("rt_suspend_chan_new"),
("chan", "len") => Some("rt_suspend_chan_len"),
("chan", "cap") => Some("rt_suspend_chan_cap"),
("chan", "close") => Some("rt_suspend_chan_close"),
("chan", "send") => Some("rt_suspend_chan_send"),
("chan", "recv") => Some("rt_suspend_chan_recv"),
_ => None,
}
}
pub(crate) fn rt_static_method_symbol(type_local: &str, method: &str) -> Option<&'static str> {
match (type_local, method) {
("thread", "current-id") => Some("rt_thread_current_id"),
("thread", "available-parallelism") => Some("rt_thread_available_parallelism"),
_ => None,
}
}
pub(crate) fn needs_interpreter(name: &str) -> bool {
matches!(
name,
"rt_eval" | "rt_macroexpand" | "rt_macroexpand_1" | "rt_read" | "rt_read_datum_at" | "rt_ffi_callback_address"
)
}
pub(crate) const RT_SUSPEND_MAIN: &str = "rt_suspend_main";
pub(crate) const RT_SUSPEND_PREFIX: &str = "rt_suspend_";
pub(crate) const RT_SUSPEND_BOOL_ANSWER: &str = "rt_suspend_io_for";
pub(crate) fn builtin_shim(path: &crate::Path) -> Option<&'static str> {
let name = path.last_segment();
let shim = rt_builtin_symbol(name)?;
let at_home = if internal_builtins().contains(name) {
path.parent() == [typelisp_front::INTERNAL_MODULE]
} else {
path.is_simple()
};
at_home.then_some(shim)
}
pub(crate) fn is_rt_builtin(path: &crate::Path) -> bool {
builtin_shim(path).is_some()
}
fn internal_builtins() -> &'static std::collections::HashSet<String> {
static NAMES: std::sync::OnceLock<std::collections::HashSet<String>> = std::sync::OnceLock::new();
NAMES.get_or_init(|| {
let reg = typelisp_front::check::Registry::with_builtins();
let ns = reg
.root
.module(&[typelisp_front::INTERNAL_MODULE.to_string()])
.expect("the registry keeps its internal builtins in their own module");
ns.fns.iter().filter(|(_, sig)| sig.builtin).map(|(name, _)| name.clone()).collect()
})
}
pub(crate) fn is_native_lowered_primitive_method(type_local: &str, method: &str) -> bool {
native_lowered_primitive_methods(type_local).contains(&method)
}
pub(crate) fn native_lowered_primitive_methods(type_local: &str) -> &'static [&'static str] {
match type_local {
"i32" | "i8" | "i16" | "u8" | "u16" | "u32" | "c-long" | "c-ulong" => &[
"+", "-", "*", "/", "mod", "<", "<=", ">", ">=", "=", "eq", "eql", "equal", "equalp", "/=",
"int->int", "int->ratio", "int->float", "int->char",
"int->i8", "int->i16", "int->i32", "int->u8", "int->u16", "int->u32",
"int->c-long", "int->c-ulong",
"try-int->char",
"try-int->i8", "try-int->i16", "try-int->i32", "try-int->u8", "try-int->u16", "try-int->u32",
"try-int->c-long", "try-int->c-ulong",
"max", "min", "logand", "logior", "logxor", "logtest", "lognot", "logcount", "integer-length",
"ash", "logbitp",
],
"string" => &[
"length", "ref", "eq", "eql", "equal", "equalp", "lt", "<", "<=", ">", ">=", "append", "substring",
"upcase", "downcase",
],
"char" => &[
"eq", "eql", "equal", "equalp", "lt", "<", "<=", ">", ">=", "char->int", "char->string",
"upcase", "downcase", "alphap", "digitp",
],
"f64" | "f32" => &[
"+", "-", "*", "/", "expt", "sqrt", "floor", "ceiling", "round", "truncate",
"float->int", "float->ratio", "float->f32", "float->f64",
"try-float->f32", "try-float->f64",
"<", "<=", ">", ">=", "=", "/=", "eq", "eql", "equal", "equalp",
"max", "min", "sin", "cos", "tan", "asin", "acos", "atan", "sinh", "cosh", "tanh",
"asinh", "acosh", "atanh", "exp", "log",
],
"int" => &[
"+", "-", "*", "/", "mod", "<", "<=", ">", ">=", "=", "/=", "eq", "eql", "equal", "equalp",
"max", "min", "logand", "logior", "logxor", "logtest", "lognot", "logcount", "integer-length",
"ash", "logbitp",
"int->float", "int->ratio", "int->int", "int->char", "try-int->char",
"int->i8", "int->i16", "int->i32", "int->u8", "int->u16", "int->u32",
"int->c-long", "int->c-ulong",
"try-int->i8", "try-int->i16", "try-int->i32", "try-int->u8", "try-int->u16", "try-int->u32",
"try-int->c-long", "try-int->c-ulong",
],
"ratio" => &[
"+", "-", "*", "/", "<", "<=", ">", ">=", "=", "/=", "eq", "eql", "equal", "equalp",
"ratio->int", "ratio->float", "numerator", "denominator", "max", "min",
],
"sexpr" => &["eq", "eql"],
"bool" => &["eq", "eql", "equal", "equalp"],
"symbol" => &["eq", "eql"],
_ => &[],
}
}
pub(crate) fn rt_extern_functions() -> [(&'static str, usize); 321] {
use typelisp_rt::c_mem::{
rt_c_alloc, rt_c_arena_close, rt_c_arena_open, rt_c_index, rt_c_load, rt_c_offset, rt_c_ptr_check, rt_c_store,
};
use typelisp_rt::equality::{rt_sexpr_eql, rt_sexpr_equal, rt_sexpr_equalp};
use typelisp_rt::ffi_callback::{
rt_ffi_callback_address, rt_ffi_callback_enter, rt_ffi_callback_invoke, rt_ffi_callback_leave,
rt_ffi_callback_register,
};
use typelisp_print::shim::{
rt_format, rt_pprint, rt_pprint_block_end, rt_pprint_block_start, rt_pprint_indent,
rt_pprint_list_exhausted, rt_pprint_newline, rt_pprint_pop, rt_pprint_tab, rt_print, rt_println,
};
use typelisp_print::aot::{
rt_format_call_method, rt_print_enum_variant, rt_print_field_name, rt_print_field_template, rt_print_global,
rt_print_object_method,
};
use typelisp_front::shim::{rt_eval, rt_eval_init, rt_eval_state, rt_macroexpand, rt_macroexpand_1};
use typelisp_read::shim::{rt_read, rt_read_datum_at};
use typelisp_rt::coroutine::{
rt_loop_safepoint, rt_suspend_chan_cap, rt_suspend_chan_close, rt_suspend_chan_len,
rt_suspend_chan_new, rt_suspend_chan_recv, rt_suspend_chan_select, rt_suspend_chan_send,
rt_suspend_task, rt_suspend_io, rt_suspend_io_for, rt_suspend_main, rt_suspend_sleep, rt_suspend_thread,
rt_suspend_wait, rt_suspend_yield,
};
use typelisp_rt::sys_builtin::{
rt_command_line_args, rt_dribble_start, rt_dribble_stop, rt_ed_open, rt_exit,
rt_get_internal_real_time, rt_get_internal_run_time,
rt_get_universal_time, rt_getenv, rt_heap_info, rt_home_directory, rt_lisp_implementation_version,
rt_machine_instance, rt_machine_type, rt_machine_version, rt_parse_float,
rt_software_type, rt_software_version, rt_thread_available_parallelism, rt_thread_current_id,
rt_timezone_daylight_p, rt_timezone_offset_seconds,
};
use typelisp_rt::integer::{
rt_integer_add, rt_integer_ash, rt_integer_cmp, rt_integer_div, rt_integer_fits, rt_integer_fits_char,
rt_integer_from_word, rt_integer_integer_length, rt_integer_logand, rt_integer_logbitp, rt_integer_logcount,
rt_integer_logior, rt_integer_lognot, rt_integer_logtest, rt_integer_logxor, rt_integer_mod, rt_integer_mul,
rt_integer_narrow, rt_integer_sub, rt_integer_to_char, rt_integer_to_float,
rt_integer_to_ratio, rt_int_not_fixnum,
};
use typelisp_rt::{
rt_atom, rt_bignum_new,
rt_make_random_state_fresh, rt_random_state_copy, rt_random_state_next, rt_seed_random_state,
rt_file_create_directories, rt_file_delete, rt_file_directory_p, rt_file_exists_p,
rt_file_list_directory, rt_file_modified_date, rt_file_owner_name, rt_file_rename,
rt_file_truename,
rt_net_accept, rt_net_buffered_p, rt_net_connect_begin, rt_net_connect_finish, rt_net_fill, rt_net_flush,
rt_net_listen, rt_net_local_address, rt_net_peer_address, rt_net_pop_byte, rt_net_pop_char,
rt_net_push_byte, rt_net_push_string, rt_net_shutdown_write,
rt_net_resolve_begin, rt_net_resolve_finish, rt_net_tls_handshake, rt_net_tls_start,
rt_net_tls_listen, rt_net_socket_error, rt_net_peer_subject, rt_net_server_name, rt_net_set_nodelay,
rt_net_set_keepalive, rt_net_set_keepalive_period, rt_net_tls_add_certificate,
rt_net_udp_bind, rt_net_udp_last_sender, rt_net_udp_recv, rt_net_udp_send_to,
rt_net_unix_connect, rt_net_unix_listen,
rt_stream_at_line_start, rt_stream_close,
rt_stream_finish_output, rt_stream_input_p, rt_stream_listen, rt_stream_open_file, rt_stream_open_p, rt_stream_describe,
rt_stream_output_p, rt_stream_position, rt_stream_read_byte, rt_stream_read_char, rt_stream_stderr, rt_stream_stdin, rt_stream_stdout,
rt_set_macro_character, rt_get_macro_character, rt_set_dispatch_macro_character, rt_get_dispatch_macro_character,
rt_stream_string_input, rt_stream_string_output, rt_stream_take_output_string, rt_stream_unread_char,
rt_stream_write_byte, rt_stream_write_string,
rt_box_kind, rt_car, rt_cdr,
rt_cell_get, rt_cell_new, rt_cell_set, rt_char_alphap, rt_char_digitp, rt_char_downcase,
rt_char_equalp, rt_char_upcase, rt_int_to_char, rt_closure_env_get, rt_closure_env_len,
rt_closure_fnptr, rt_closure_new, rt_coroutine_closure_new, rt_cons, rt_consp, rt_data_field, rt_data_new, rt_data_variant, rt_f64_new, rt_f32_new, rt_narrow_new, rt_narrow_value, rt_float_to_int,
rt_float_to_ratio, rt_f64_value, rt_f32_value, rt_global_get, rt_global_new, rt_global_set, rt_int_div, rt_int_mod,
rt_int_ash, rt_int_logbitp, rt_int_logcount, rt_int_integer_length,
rt_f64_tan, rt_f64_asin, rt_f64_acos, rt_f64_atan, rt_f64_sinh, rt_f64_cosh, rt_f64_tanh, rt_f64_asinh, rt_f64_acosh,
rt_f64_atanh,
rt_hashtable_bucket_count, rt_hashtable_bucket_delete, rt_hashtable_bucket_key, rt_hashtable_bucket_put,
rt_hashtable_bucket_value,
rt_hashtable_clear, rt_hashtable_count, rt_hashtable_entries, rt_hashtable_keys,
rt_hashtable_new, rt_hashtable_values, rt_int_to_ratio,
rt_intern_path, rt_intern_symbol, rt_wk_symbol, rt_list_to_path, rt_match_fail, rt_null, rt_panic, rt_path_to_list, rt_pop_sexpr_root, rt_push_permanent_sexpr_root,
rt_push_sexpr_root, rt_ratio_add, rt_ratio_cmp, rt_ratio_denominator, rt_ratio_div, rt_ratio_from_bignums, rt_ratio_mul,
rt_ratio_numerator, rt_ratio_sub, rt_ratio_to_int, rt_ratio_to_float, rt_root_count, rt_set_car, rt_set_cdr,
rt_set_sexpr_root, rt_sexpr_bool, rt_sexpr_char, rt_sexpr_instance_test, rt_sexpr_int, rt_sexpr_i32, rt_sexpr_i8, rt_sexpr_i16, rt_sexpr_u8, rt_sexpr_u16, rt_sexpr_u32, rt_sexpr_str, rt_str_append, rt_str_eq, rt_str_equalp,
rt_ffi_cstring_new, rt_ffi_cstring_free, rt_ffi_string_from_cstr, rt_ffi_enter_native, rt_ffi_leave_native,
rt_str_length, rt_str_lt, rt_str_new, rt_str_ref, rt_str_substring, rt_str_upcase, rt_str_downcase, rt_int_fits, rt_int_fits_char, rt_f64_fits_f32, rt_struct_field_count, rt_struct_field_get, rt_struct_field_set,
rt_struct_new, rt_struct_pop_field, rt_struct_push_field, rt_sym_name, rt_symp, rt_truncate_sexpr_roots,
rt_dyn_new, rt_dyn_upcast, rt_dyn_value, rt_dyn_vtable, rt_upcast_set, rt_vtable_set,
rt_throw, rt_throw_matches, rt_throw_take_value,
rt_frame_new, rt_frame_data, rt_frame_mask_bit, rt_frame_pc, rt_frame_set_pc,
rt_frame_entered, rt_frame_call, rt_frame_call_env, rt_frame_apply, rt_frame_dyn_call, rt_pending_arg, rt_pending_argc,
rt_pending_env, rt_pending_envc,
};
[
("rt_llvm_call", crate::compile::llvm_builtins::rt_llvm_call as *const () as usize),
("rt_dyn_new", rt_dyn_new as *const () as usize),
("rt_dyn_vtable", rt_dyn_vtable as *const () as usize),
("rt_dyn_value", rt_dyn_value as *const () as usize),
("rt_dyn_upcast", rt_dyn_upcast as *const () as usize),
("rt_vtable_set", rt_vtable_set as *const () as usize),
("rt_upcast_set", rt_upcast_set as *const () as usize),
("rt_sexpr_eql", rt_sexpr_eql as *const () as usize),
("rt_sexpr_equal", rt_sexpr_equal as *const () as usize),
("rt_sexpr_equalp", rt_sexpr_equalp as *const () as usize),
("rt_parse_float", rt_parse_float as *const () as usize),
("rt_get_universal_time", rt_get_universal_time as *const () as usize),
("rt_get_internal_real_time", rt_get_internal_real_time as *const () as usize),
("rt_exit", rt_exit as *const () as usize),
("rt_read", rt_read as *const () as usize),
("rt_read_datum_at", rt_read_datum_at as *const () as usize),
("rt_eval", rt_eval as *const () as usize),
("rt_macroexpand_1", rt_macroexpand_1 as *const () as usize),
("rt_macroexpand", rt_macroexpand as *const () as usize),
("rt_eval_state", rt_eval_state as *const () as usize),
("rt_eval_init", rt_eval_init as *const () as usize),
("rt_format", rt_format as *const () as usize),
("rt_print", rt_print as *const () as usize),
("rt_println", rt_println as *const () as usize),
("rt_pprint", rt_pprint as *const () as usize),
("rt_pprint_block_start", rt_pprint_block_start as *const () as usize),
("rt_pprint_block_end", rt_pprint_block_end as *const () as usize),
("rt_pprint_newline", rt_pprint_newline as *const () as usize),
("rt_pprint_indent", rt_pprint_indent as *const () as usize),
("rt_pprint_tab", rt_pprint_tab as *const () as usize),
("rt_pprint_pop", rt_pprint_pop as *const () as usize),
("rt_pprint_list_exhausted", rt_pprint_list_exhausted as *const () as usize),
("rt_print_enum_variant", rt_print_enum_variant as *const () as usize),
("rt_print_field_template", rt_print_field_template as *const () as usize),
("rt_print_field_name", rt_print_field_name as *const () as usize),
("rt_print_object_method", rt_print_object_method as *const () as usize),
("rt_format_call_method", rt_format_call_method as *const () as usize),
("rt_print_global", rt_print_global as *const () as usize),
("rt_car", rt_car as *const () as usize),
("rt_cdr", rt_cdr as *const () as usize),
("rt_cons", rt_cons as *const () as usize),
("rt_consp", rt_consp as *const () as usize),
("rt_null", rt_null as *const () as usize),
("rt_atom", rt_atom as *const () as usize),
("rt_symp", rt_symp as *const () as usize),
("rt_sexpr_int", rt_sexpr_int as *const () as usize),
("rt_sexpr_i32", rt_sexpr_i32 as *const () as usize),
("rt_sexpr_i8", rt_sexpr_i8 as *const () as usize),
("rt_sexpr_i16", rt_sexpr_i16 as *const () as usize),
("rt_sexpr_u8", rt_sexpr_u8 as *const () as usize),
("rt_sexpr_u16", rt_sexpr_u16 as *const () as usize),
("rt_sexpr_u32", rt_sexpr_u32 as *const () as usize),
("rt_sexpr_bool", rt_sexpr_bool as *const () as usize),
("rt_sexpr_char", rt_sexpr_char as *const () as usize),
("rt_sexpr_str", rt_sexpr_str as *const () as usize),
("rt_sym_name", rt_sym_name as *const () as usize),
("rt_set_car", rt_set_car as *const () as usize),
("rt_set_cdr", rt_set_cdr as *const () as usize),
("rt_match_fail", rt_match_fail as *const () as usize),
("rt_panic", rt_panic as *const () as usize),
("rt_frame_new", rt_frame_new as *const () as usize),
("rt_frame_data", rt_frame_data as *const () as usize),
("rt_frame_mask_bit", rt_frame_mask_bit as *const () as usize),
("rt_frame_pc", rt_frame_pc as *const () as usize),
("rt_frame_set_pc", rt_frame_set_pc as *const () as usize),
("rt_frame_entered", rt_frame_entered as *const () as usize),
("rt_frame_call", rt_frame_call as *const () as usize),
("rt_frame_apply", rt_frame_apply as *const () as usize),
("rt_frame_dyn_call", rt_frame_dyn_call as *const () as usize),
("rt_frame_call_env", rt_frame_call_env as *const () as usize),
("rt_pending_arg", rt_pending_arg as *const () as usize),
("rt_pending_argc", rt_pending_argc as *const () as usize),
("rt_pending_env", rt_pending_env as *const () as usize),
("rt_pending_envc", rt_pending_envc as *const () as usize),
("rt_throw", rt_throw as *const () as usize),
("rt_throw_matches", rt_throw_matches as *const () as usize),
("rt_throw_take_value", rt_throw_take_value as *const () as usize),
("rt_push_sexpr_root", rt_push_sexpr_root as *const () as usize),
("rt_pop_sexpr_root", rt_pop_sexpr_root as *const () as usize),
("rt_push_permanent_sexpr_root", rt_push_permanent_sexpr_root as *const () as usize),
("rt_root_count", rt_root_count as *const () as usize),
("rt_set_sexpr_root", rt_set_sexpr_root as *const () as usize),
("rt_truncate_sexpr_roots", rt_truncate_sexpr_roots as *const () as usize),
("rt_ffi_cstring_new", rt_ffi_cstring_new as *const () as usize),
("rt_ffi_cstring_free", rt_ffi_cstring_free as *const () as usize),
("rt_ffi_string_from_cstr", rt_ffi_string_from_cstr as *const () as usize),
("rt_ffi_enter_native", rt_ffi_enter_native as *const () as usize),
("rt_ffi_leave_native", rt_ffi_leave_native as *const () as usize),
("rt_ffi_callback_address", rt_ffi_callback_address as *const () as usize),
("rt_ffi_callback_register", rt_ffi_callback_register as *const () as usize),
("rt_ffi_callback_enter", rt_ffi_callback_enter as *const () as usize),
("rt_ffi_callback_invoke", rt_ffi_callback_invoke as *const () as usize),
("rt_ffi_callback_leave", rt_ffi_callback_leave as *const () as usize),
("rt_c_arena_open", rt_c_arena_open as *const () as usize),
("rt_c_arena_close", rt_c_arena_close as *const () as usize),
("rt_c_alloc", rt_c_alloc as *const () as usize),
("rt_c_ptr_check", rt_c_ptr_check as *const () as usize),
("rt_c_index", rt_c_index as *const () as usize),
("rt_c_offset", rt_c_offset as *const () as usize),
("rt_c_load", rt_c_load as *const () as usize),
("rt_c_store", rt_c_store as *const () as usize),
("rt_str_new", rt_str_new as *const () as usize),
("rt_str_length", rt_str_length as *const () as usize),
("rt_str_ref", rt_str_ref as *const () as usize),
("rt_str_eq", rt_str_eq as *const () as usize),
("rt_str_equalp", rt_str_equalp as *const () as usize),
("rt_char_equalp", rt_char_equalp as *const () as usize),
("rt_char_upcase", rt_char_upcase as *const () as usize),
("rt_char_downcase", rt_char_downcase as *const () as usize),
("rt_char_alphap", rt_char_alphap as *const () as usize),
("rt_char_digitp", rt_char_digitp as *const () as usize),
("rt_int_to_char", rt_int_to_char as *const () as usize),
("rt_str_lt", rt_str_lt as *const () as usize),
("rt_str_append", rt_str_append as *const () as usize),
("rt_str_substring", rt_str_substring as *const () as usize),
("rt_str_upcase", rt_str_upcase as *const () as usize),
("rt_int_fits", rt_int_fits as *const () as usize),
("rt_int_fits_char", rt_int_fits_char as *const () as usize),
("rt_f64_fits_f32", rt_f64_fits_f32 as *const () as usize),
("rt_str_downcase", rt_str_downcase as *const () as usize),
("rt_f64_new", rt_f64_new as *const () as usize),
("rt_f64_value", rt_f64_value as *const () as usize),
("rt_f32_new", rt_f32_new as *const () as usize),
("rt_f32_value", rt_f32_value as *const () as usize),
("rt_narrow_new", rt_narrow_new as *const () as usize),
("rt_narrow_value", rt_narrow_value as *const () as usize),
("rt_box_kind", rt_box_kind as *const () as usize),
("rt_struct_new", rt_struct_new as *const () as usize),
("rt_struct_field_get", rt_struct_field_get as *const () as usize),
("rt_struct_field_set", rt_struct_field_set as *const () as usize),
("rt_struct_field_count", rt_struct_field_count as *const () as usize),
("rt_struct_push_field", rt_struct_push_field as *const () as usize),
("rt_struct_pop_field", rt_struct_pop_field as *const () as usize),
("rt_closure_new", rt_closure_new as *const () as usize),
("rt_coroutine_closure_new", rt_coroutine_closure_new as *const () as usize),
("rt_closure_fnptr", rt_closure_fnptr as *const () as usize),
("rt_closure_env_len", rt_closure_env_len as *const () as usize),
("rt_closure_env_get", rt_closure_env_get as *const () as usize),
("rt_cell_new", rt_cell_new as *const () as usize),
("rt_cell_get", rt_cell_get as *const () as usize),
("rt_cell_set", rt_cell_set as *const () as usize),
("rt_data_new", rt_data_new as *const () as usize),
("rt_data_variant", rt_data_variant as *const () as usize),
("rt_data_field", rt_data_field as *const () as usize),
("rt_sexpr_instance_test", rt_sexpr_instance_test as *const () as usize),
("rt_hashtable_new", rt_hashtable_new as *const () as usize),
("rt_hashtable_count", rt_hashtable_count as *const () as usize),
("rt_hashtable_clear", rt_hashtable_clear as *const () as usize),
("rt_hashtable_keys", rt_hashtable_keys as *const () as usize),
("rt_hashtable_values", rt_hashtable_values as *const () as usize),
("rt_hashtable_entries", rt_hashtable_entries as *const () as usize),
("rt_hashtable_bucket_count", rt_hashtable_bucket_count as *const () as usize),
("rt_hashtable_bucket_key", rt_hashtable_bucket_key as *const () as usize),
("rt_hashtable_bucket_value", rt_hashtable_bucket_value as *const () as usize),
("rt_hashtable_bucket_put", rt_hashtable_bucket_put as *const () as usize),
("rt_hashtable_bucket_delete", rt_hashtable_bucket_delete as *const () as usize),
("rt_global_new", rt_global_new as *const () as usize),
("rt_global_get", rt_global_get as *const () as usize),
("rt_global_set", rt_global_set as *const () as usize),
("rt_bignum_new", rt_bignum_new as *const () as usize),
("rt_ratio_from_bignums", rt_ratio_from_bignums as *const () as usize),
("rt_integer_add", rt_integer_add as *const () as usize),
("rt_integer_sub", rt_integer_sub as *const () as usize),
("rt_integer_mul", rt_integer_mul as *const () as usize),
("rt_integer_div", rt_integer_div as *const () as usize),
("rt_integer_mod", rt_integer_mod as *const () as usize),
("rt_integer_cmp", rt_integer_cmp as *const () as usize),
("rt_integer_logand", rt_integer_logand as *const () as usize),
("rt_integer_logior", rt_integer_logior as *const () as usize),
("rt_integer_logxor", rt_integer_logxor as *const () as usize),
("rt_integer_logtest", rt_integer_logtest as *const () as usize),
("rt_integer_ash", rt_integer_ash as *const () as usize),
("rt_integer_logbitp", rt_integer_logbitp as *const () as usize),
("rt_integer_lognot", rt_integer_lognot as *const () as usize),
("rt_integer_logcount", rt_integer_logcount as *const () as usize),
("rt_integer_integer_length", rt_integer_integer_length as *const () as usize),
("rt_integer_to_float", rt_integer_to_float as *const () as usize),
("rt_integer_to_ratio", rt_integer_to_ratio as *const () as usize),
("rt_integer_to_char", rt_integer_to_char as *const () as usize),
("rt_integer_fits_char", rt_integer_fits_char as *const () as usize),
("rt_integer_narrow", rt_integer_narrow as *const () as usize),
("rt_integer_fits", rt_integer_fits as *const () as usize),
("rt_integer_from_word", rt_integer_from_word as *const () as usize),
("rt_int_not_fixnum", rt_int_not_fixnum as *const () as usize),
("rt_random_state_next", rt_random_state_next as *const () as usize),
("rt_random_state_copy", rt_random_state_copy as *const () as usize),
("rt_make_random_state_fresh", rt_make_random_state_fresh as *const () as usize),
("rt_seed_random_state", rt_seed_random_state as *const () as usize),
("rt_stream_stdin", rt_stream_stdin as *const () as usize),
("rt_stream_stdout", rt_stream_stdout as *const () as usize),
("rt_stream_stderr", rt_stream_stderr as *const () as usize),
("rt_stream_string_input", rt_stream_string_input as *const () as usize),
("rt_stream_string_output", rt_stream_string_output as *const () as usize),
("rt_stream_open_file", rt_stream_open_file as *const () as usize),
("rt_stream_close", rt_stream_close as *const () as usize),
("rt_stream_open_p", rt_stream_open_p as *const () as usize),
("rt_stream_describe", rt_stream_describe as *const () as usize),
("rt_stream_input_p", rt_stream_input_p as *const () as usize),
("rt_stream_output_p", rt_stream_output_p as *const () as usize),
("rt_stream_read_char", rt_stream_read_char as *const () as usize),
("rt_stream_read_byte", rt_stream_read_byte as *const () as usize),
("rt_stream_write_byte", rt_stream_write_byte as *const () as usize),
("rt_stream_unread_char", rt_stream_unread_char as *const () as usize),
("rt_suspend_sleep", rt_suspend_sleep as *const () as usize),
("rt_suspend_io", rt_suspend_io as *const () as usize),
("rt_suspend_io_for", rt_suspend_io_for as *const () as usize),
("rt_net_resolve_begin", rt_net_resolve_begin as *const () as usize),
("rt_net_resolve_finish", rt_net_resolve_finish as *const () as usize),
("rt_net_tls_start", rt_net_tls_start as *const () as usize),
("rt_net_tls_listen", rt_net_tls_listen as *const () as usize),
("rt_net_socket_error", rt_net_socket_error as *const () as usize),
("rt_net_peer_subject", rt_net_peer_subject as *const () as usize),
("rt_net_server_name", rt_net_server_name as *const () as usize),
("rt_net_set_nodelay", rt_net_set_nodelay as *const () as usize),
("rt_net_set_keepalive", rt_net_set_keepalive as *const () as usize),
("rt_net_set_keepalive_period", rt_net_set_keepalive_period as *const () as usize),
("rt_net_tls_add_certificate", rt_net_tls_add_certificate as *const () as usize),
("rt_net_tls_handshake", rt_net_tls_handshake as *const () as usize),
("rt_net_udp_bind", rt_net_udp_bind as *const () as usize),
("rt_net_udp_send_to", rt_net_udp_send_to as *const () as usize),
("rt_net_udp_recv", rt_net_udp_recv as *const () as usize),
("rt_net_udp_last_sender", rt_net_udp_last_sender as *const () as usize),
("rt_net_connect_begin", rt_net_connect_begin as *const () as usize),
("rt_net_connect_finish", rt_net_connect_finish as *const () as usize),
("rt_net_listen", rt_net_listen as *const () as usize),
("rt_net_unix_connect", rt_net_unix_connect as *const () as usize),
("rt_net_unix_listen", rt_net_unix_listen as *const () as usize),
("rt_net_accept", rt_net_accept as *const () as usize),
("rt_net_fill", rt_net_fill as *const () as usize),
("rt_net_pop_byte", rt_net_pop_byte as *const () as usize),
("rt_net_pop_char", rt_net_pop_char as *const () as usize),
("rt_net_buffered_p", rt_net_buffered_p as *const () as usize),
("rt_net_push_string", rt_net_push_string as *const () as usize),
("rt_net_push_byte", rt_net_push_byte as *const () as usize),
("rt_net_flush", rt_net_flush as *const () as usize),
("rt_net_shutdown_write", rt_net_shutdown_write as *const () as usize),
("rt_net_local_address", rt_net_local_address as *const () as usize),
("rt_net_peer_address", rt_net_peer_address as *const () as usize),
("rt_suspend_wait", rt_suspend_wait as *const () as usize),
("rt_suspend_yield", rt_suspend_yield as *const () as usize),
("rt_suspend_task", rt_suspend_task as *const () as usize),
("rt_suspend_thread", rt_suspend_thread as *const () as usize),
("rt_suspend_main", rt_suspend_main as *const () as usize),
("rt_thread_current_id", rt_thread_current_id as *const () as usize),
("rt_thread_available_parallelism", rt_thread_available_parallelism as *const () as usize),
("rt_suspend_chan_new", rt_suspend_chan_new as *const () as usize),
("rt_suspend_chan_len", rt_suspend_chan_len as *const () as usize),
("rt_suspend_chan_cap", rt_suspend_chan_cap as *const () as usize),
("rt_suspend_chan_close", rt_suspend_chan_close as *const () as usize),
("rt_suspend_chan_send", rt_suspend_chan_send as *const () as usize),
("rt_suspend_chan_recv", rt_suspend_chan_recv as *const () as usize),
("rt_suspend_chan_select", rt_suspend_chan_select as *const () as usize),
("rt_loop_safepoint", rt_loop_safepoint as *const () as usize),
("rt_stream_listen", rt_stream_listen as *const () as usize),
("rt_stream_position", rt_stream_position as *const () as usize),
("rt_set_macro_character", rt_set_macro_character as *const () as usize),
("rt_get_macro_character", rt_get_macro_character as *const () as usize),
("rt_set_dispatch_macro_character", rt_set_dispatch_macro_character as *const () as usize),
("rt_get_dispatch_macro_character", rt_get_dispatch_macro_character as *const () as usize),
("rt_stream_write_string", rt_stream_write_string as *const () as usize),
("rt_stream_at_line_start", rt_stream_at_line_start as *const () as usize),
("rt_stream_finish_output", rt_stream_finish_output as *const () as usize),
("rt_stream_take_output_string", rt_stream_take_output_string as *const () as usize),
("rt_file_exists_p", rt_file_exists_p as *const () as usize),
("rt_file_delete", rt_file_delete as *const () as usize),
("rt_file_rename", rt_file_rename as *const () as usize),
("rt_file_truename", rt_file_truename as *const () as usize),
("rt_file_modified_date", rt_file_modified_date as *const () as usize),
("rt_file_owner_name", rt_file_owner_name as *const () as usize),
("rt_file_directory_p", rt_file_directory_p as *const () as usize),
("rt_file_list_directory", rt_file_list_directory as *const () as usize),
("rt_file_create_directories", rt_file_create_directories as *const () as usize),
("rt_command_line_args", rt_command_line_args as *const () as usize),
("rt_getenv", rt_getenv as *const () as usize),
("rt_home_directory", rt_home_directory as *const () as usize),
("rt_lisp_implementation_version", rt_lisp_implementation_version as *const () as usize),
("rt_machine_type", rt_machine_type as *const () as usize),
("rt_get_internal_run_time", rt_get_internal_run_time as *const () as usize),
("rt_machine_instance", rt_machine_instance as *const () as usize),
("rt_machine_version", rt_machine_version as *const () as usize),
("rt_software_version", rt_software_version as *const () as usize),
("rt_timezone_offset_seconds", rt_timezone_offset_seconds as *const () as usize),
("rt_timezone_daylight_p", rt_timezone_daylight_p as *const () as usize),
("rt_software_type", rt_software_type as *const () as usize),
("rt_heap_info", rt_heap_info as *const () as usize),
("rt_dribble_start", rt_dribble_start as *const () as usize),
("rt_dribble_stop", rt_dribble_stop as *const () as usize),
("rt_ed_open", rt_ed_open as *const () as usize),
("rt_int_to_ratio", rt_int_to_ratio as *const () as usize),
("rt_float_to_int", rt_float_to_int as *const () as usize),
("rt_float_to_ratio", rt_float_to_ratio as *const () as usize),
("rt_ratio_add", rt_ratio_add as *const () as usize),
("rt_ratio_sub", rt_ratio_sub as *const () as usize),
("rt_ratio_mul", rt_ratio_mul as *const () as usize),
("rt_ratio_div", rt_ratio_div as *const () as usize),
("rt_ratio_cmp", rt_ratio_cmp as *const () as usize),
("rt_ratio_to_int", rt_ratio_to_int as *const () as usize),
("rt_ratio_to_float", rt_ratio_to_float as *const () as usize),
("rt_ratio_numerator", rt_ratio_numerator as *const () as usize),
("rt_ratio_denominator", rt_ratio_denominator as *const () as usize),
("rt_intern_symbol", rt_intern_symbol as *const () as usize),
("rt_wk_symbol", rt_wk_symbol as *const () as usize),
("rt_intern_path", rt_intern_path as *const () as usize),
("rt_path_to_list", rt_path_to_list as *const () as usize),
("rt_list_to_path", rt_list_to_path as *const () as usize),
("rt_int_div", rt_int_div as *const () as usize),
("rt_int_mod", rt_int_mod as *const () as usize),
("rt_int_ash", rt_int_ash as *const () as usize),
("rt_int_logbitp", rt_int_logbitp as *const () as usize),
("rt_int_logcount", rt_int_logcount as *const () as usize),
("rt_int_integer_length", rt_int_integer_length as *const () as usize),
("rt_f64_tan", rt_f64_tan as *const () as usize),
("rt_f64_asin", rt_f64_asin as *const () as usize),
("rt_f64_acos", rt_f64_acos as *const () as usize),
("rt_f64_atan", rt_f64_atan as *const () as usize),
("rt_f64_sinh", rt_f64_sinh as *const () as usize),
("rt_f64_cosh", rt_f64_cosh as *const () as usize),
("rt_f64_tanh", rt_f64_tanh as *const () as usize),
("rt_f64_asinh", rt_f64_asinh as *const () as usize),
("rt_f64_acosh", rt_f64_acosh as *const () as usize),
("rt_f64_atanh", rt_f64_atanh as *const () as usize),
]
}
#[cfg(test)]
mod scc_tests {
use std::cell::RefCell;
use std::rc::Rc;
use typelisp_mem::{Heap, Value};
use crate::check::core;
use crate::check::repr::Repr;
use crate::eval::interp::{FnDef, Interp};
use crate::types::Path;
#[test]
fn compile_function_compiles_a_genuine_two_node_cycle_bypassing_the_checker() {
let mut heap = Heap::with_capacity(1 << 16);
let mut checker = crate::Checker::new();
let mut interp = Interp::new();
crate::load_compiler(&mut heap, &mut checker, &mut interp);
for (name, callee) in [("a", "b"), ("b", "a")] {
let path = heap.intern_symbol(callee);
heap.push_root(path);
let call = core::tagged(&mut heap, "call", &[Value::Empty, Value::Empty, path, Value::Empty])
.expect("building a 4-field node cannot exhaust a 1<<16 heap");
heap.push_permanent_root(call);
heap.pop_root();
interp.root.borrow_mut().define_fn(
name.to_string(),
Rc::new(FnDef { ffi: false,
name: name.to_string(),
params: vec![],
body: vec![call],
rest: false,
lambda: None,
sig: Some((vec![], Repr::Narrow)),
public: true,
compiled: RefCell::new(None),
}),
);
}
crate::compile::driver::compile_function(&interp, &mut heap, &crate::CompileTarget::Fn(crate::check::resolved::Ref::synthetic(Path::root("a"))))
.expect("mutual recursion across separate top-level functions should now compile");
assert!(interp.root.borrow().fn_compiled(&Path::root("a")), "\"a\" should have ended up compiled");
assert!(interp.root.borrow().fn_compiled(&Path::root("b")), "\"b\", pulled in transitively as part of the same SCC, should have ended up compiled too");
}
}
#[cfg(test)]
mod native_method_list_tests {
use super::native_lowered_primitive_methods;
const PRIMITIVES: &[(&str, &[&str])] = &[
("int", &["i32", "i8", "i16", "u8", "u16", "u32", "c-long", "c-ulong"]),
("integer", &["int"]),
("string", &["string"]),
("char", &["char"]),
("float", &["f64", "f32"]),
("ratio", &["ratio"]),
("bool", &["bool"]),
("symbol", &["symbol"]),
("sexpr", &["sexpr"]),
];
fn island_methods(name: &str) -> Vec<String> {
let src = crate::compiler::SOURCE;
let head = format!("(defun {}-native-method? ", name);
let start = src.find(&head).unwrap_or_else(|| panic!("`{}` not found in the island SOURCE", head));
let rest = &src[start + head.len()..];
let body = match rest.find("\n(defun ") {
Some(end) => &rest[..end],
None => rest,
};
let mut out = Vec::new();
let mut chars = body.char_indices();
while let Some((i, c)) = chars.next() {
match c {
';' => {
for (_, c) in chars.by_ref() {
if c == '\n' {
break;
}
}
}
'"' => {
let from = i + 1;
let mut end = None;
for (j, c) in chars.by_ref() {
if c == '"' {
end = Some(j);
break;
}
}
let to = end.expect("unterminated method-name string in the island SOURCE");
out.push(body[from..to].to_string());
}
_ => {}
}
}
out.sort();
out
}
#[test]
fn the_rust_and_island_native_method_lists_agree() {
for (island_name, type_locals) in PRIMITIVES {
let island = island_methods(island_name);
assert!(!island.is_empty(), "`{}-native-method?` parsed as empty — the scan is broken", island_name);
for type_local in *type_locals {
let mut rust: Vec<String> =
native_lowered_primitive_methods(type_local).iter().map(|m| m.to_string()).collect();
rust.sort();
let island_only: Vec<&String> = island.iter().filter(|m| !rust.contains(m)).collect();
let rust_only: Vec<&String> = rust.iter().filter(|m| !island.contains(m)).collect();
assert!(
island_only.is_empty() && rust_only.is_empty(),
"`{}` disagrees between the two native-method lists:\n island-only (a missed \
optimization): {:?}\n Rust-only (a call to one aborts the process at compile \
time): {:?}",
type_local,
island_only,
rust_only
);
}
}
}
#[test]
fn every_registered_builtin_method_on_a_native_receiver_lowers() {
let registry = typelisp_front::check::registry::Registry::with_builtins();
let mut gaps: Vec<String> = Vec::new();
for (_, type_locals) in PRIMITIVES {
for type_local in *type_locals {
let def = registry
.root
.types
.get(*type_local)
.unwrap_or_else(|| panic!("`{}` is not a built-in type in the registry", type_local));
for (method, f) in &def.assoc {
if !f.builtin {
continue;
}
if !native_lowered_primitive_methods(type_local).contains(&method.as_str()) {
gaps.push(format!("{}::{}", type_local, method));
}
}
}
}
assert!(
gaps.is_empty(),
"these builtin methods are registered but have no compiled lowering, so a `defun` \
calling one cannot be compiled: {:?}\n Add each to `native_lowered_primitive_methods` \
*and* the island's matching `*-native-method?`, or — if it is unreachable as a method \
call the way `print` is — say so in `CHECKER_SPECIAL_FORMS`.",
gaps
);
}
}