use crate::ast::TypeExpr;
use super::{all_signatures, BuiltinMetadata, BuiltinSignature, Ty};
pub fn lookup(name: &str) -> Option<&'static BuiltinSignature> {
let signatures = all_signatures();
signatures
.binary_search_by_key(&name, |sig| sig.name)
.ok()
.map(|idx| &signatures[idx])
}
pub fn is_builtin(name: &str) -> bool {
lookup(name).is_some()
}
pub fn iter_builtin_names() -> impl Iterator<Item = &'static str> {
all_signatures().iter().map(|sig| sig.name)
}
pub fn iter_builtin_metadata() -> impl Iterator<Item = BuiltinMetadata> {
all_signatures().iter().map(|sig| BuiltinMetadata {
name: sig.name,
return_types: builtin_return_type_names(sig),
})
}
pub fn builtin_return_type(name: &str) -> Option<TypeExpr> {
let sig = lookup(name)?;
if sig.returns.is_any() {
return None;
}
Some(sig.returns.to_type_expr())
}
pub fn is_untyped_boundary_source(name: &str) -> bool {
matches!(
name,
"json_parse"
| "json_extract"
| "yaml_parse"
| "toml_parse"
| "llm_call"
| "llm_call_safe"
| "llm_completion"
| "http_get"
| "http_post"
| "http_put"
| "http_patch"
| "http_delete"
| "http_download"
| "http_request"
| "http_session_request"
| "http_stream_info"
| "sse_receive"
| "sse_server_mock_receive"
| "sse_server_response"
| "sse_server_status"
| "websocket_accept"
| "websocket_receive"
| "host_call"
| "connector_call"
| "host_tool_call"
| "mcp_call"
)
}
fn builtin_return_type_names(sig: &BuiltinSignature) -> &'static [&'static str] {
match &sig.returns {
Ty::Named(name) => match *name {
"bool" => &["bool"],
"bytes" => &["bytes"],
"dict" => &["dict"],
"float" => &["float"],
"int" => &["int"],
"list" => &["list"],
"nil" => &["nil"],
"string" => &["string"],
_ => &[],
},
Ty::Union(members) => match *members {
[Ty::Named("string"), Ty::Named("nil")] => &["string", "nil"],
[Ty::Named("nil"), Ty::Named("string")] => &["string", "nil"],
[Ty::Named("int"), Ty::Named("nil")] => &["int", "nil"],
[Ty::Named("nil"), Ty::Named("int")] => &["int", "nil"],
[Ty::Named("dict"), Ty::Named("nil")] => &["dict", "nil"],
[Ty::Named("nil"), Ty::Named("dict")] => &["dict", "nil"],
[Ty::Named("bytes"), Ty::Named("nil")] => &["bytes", "nil"],
[Ty::Named("nil"), Ty::Named("bytes")] => &["bytes", "nil"],
_ => &[],
},
Ty::Never => &["never"],
_ => &[],
}
}