harn_parser/builtin_signatures/
lookup.rs1use crate::ast::TypeExpr;
10use harn_builtin_meta::{BuiltinExposure, CapabilityId};
11
12use super::signatures;
13use super::{BuiltinMetadata, BuiltinSignature, Ty, TyExt};
14
15pub fn lookup(name: &str) -> Option<&'static BuiltinSignature> {
22 for entry in harn_builtin_registry::installed_manifest() {
23 if entry.name == name {
24 return matches!(
25 entry.contract.exposure,
26 BuiltinExposure::PureGlobal | BuiltinExposure::CapabilityFunction { .. }
27 )
28 .then_some(entry.signature);
29 }
30 }
31 for group in signatures::groups() {
32 for sig in group {
33 if sig.name == name {
34 return Some(sig);
35 }
36 }
37 }
38 None
39}
40
41pub fn lookup_capability_method(
43 capability: CapabilityId,
44 method: &str,
45) -> Option<&'static BuiltinSignature> {
46 capability_method_entry(capability.field_name(), method).map(|entry| entry.signature)
47}
48
49pub fn capability_method_entry(
53 field: &str,
54 method: &str,
55) -> Option<&'static harn_builtin_registry::BuiltinManifestEntry> {
56 let capability = CapabilityId::from_field_name(field)?;
57 harn_builtin_registry::installed_manifest()
58 .iter()
59 .copied()
60 .find(|entry| {
61 matches!(
62 entry.contract.exposure,
63 BuiltinExposure::HarnessMethod {
64 capability: candidate,
65 method: candidate_method,
66 } if candidate == capability && candidate_method == method
67 )
68 })
69 .or_else(|| harn_capability_contracts::capability_method_entry(field, method))
70}
71
72pub fn is_builtin(name: &str) -> bool {
74 lookup(name).is_some()
75}
76
77pub fn iter_builtin_names() -> impl Iterator<Item = &'static str> {
81 let installed: Vec<_> = harn_builtin_registry::installed_manifest()
82 .into_iter()
83 .filter(|entry| {
84 matches!(
85 entry.contract.exposure,
86 BuiltinExposure::PureGlobal | BuiltinExposure::CapabilityFunction { .. }
87 )
88 })
89 .collect();
90 let installed_names: std::collections::HashSet<&'static str> =
91 harn_builtin_registry::installed_manifest()
92 .into_iter()
93 .map(|entry| entry.name)
94 .collect();
95 installed.into_iter().map(|entry| entry.name).chain(
96 signatures::groups()
97 .into_iter()
98 .flat_map(|g| g.iter())
99 .filter(move |s| !installed_names.contains(s.name))
100 .map(|s| s.name),
101 )
102}
103
104pub fn static_signature_names() -> impl Iterator<Item = &'static str> {
113 signatures::groups()
114 .into_iter()
115 .flat_map(|g| g.iter())
116 .map(|s| s.name)
117}
118
119pub fn iter_builtin_metadata() -> impl Iterator<Item = BuiltinMetadata> {
124 let installed: Vec<_> = harn_builtin_registry::installed_manifest()
125 .into_iter()
126 .filter(|entry| {
127 matches!(
128 entry.contract.exposure,
129 BuiltinExposure::PureGlobal | BuiltinExposure::CapabilityFunction { .. }
130 )
131 })
132 .collect();
133 let installed_names: std::collections::HashSet<&'static str> =
134 harn_builtin_registry::installed_manifest()
135 .into_iter()
136 .map(|entry| entry.name)
137 .collect();
138 installed
139 .into_iter()
140 .map(|entry| BuiltinMetadata {
141 name: entry.name,
142 return_types: builtin_return_type_names(entry.signature),
143 })
144 .chain(
145 signatures::groups()
146 .into_iter()
147 .flat_map(|g| g.iter())
148 .filter(move |s| !installed_names.contains(s.name))
149 .map(|sig| BuiltinMetadata {
150 name: sig.name,
151 return_types: builtin_return_type_names(sig),
152 }),
153 )
154}
155
156pub fn builtin_return_type(name: &str) -> Option<TypeExpr> {
160 let sig = lookup(name)?;
161 if sig.returns.is_any() {
162 return None;
163 }
164 Some(sig.returns.to_type_expr())
165}
166
167pub fn is_untyped_boundary_source(name: &str) -> bool {
174 matches!(
175 name,
176 "json_parse"
177 | "json_extract"
178 | "yaml_parse"
179 | "toml_parse"
180 | "llm_call"
181 | "llm_call_safe"
182 | "llm_completion"
183 | "http_get"
184 | "http_post"
185 | "http_put"
186 | "http_patch"
187 | "http_delete"
188 | "http_download"
189 | "http_request"
190 | "http_session_request"
191 | "http_stream_info"
192 | "sse_receive"
193 | "sse_server_mock_receive"
194 | "sse_server_response"
195 | "sse_server_status"
196 | "websocket_accept"
197 | "websocket_receive"
198 | "host_call"
199 | "connector_call"
200 | "host_tool_call"
201 )
202}
203
204fn builtin_return_type_names(sig: &BuiltinSignature) -> &'static [&'static str] {
210 match &sig.returns {
211 Ty::Named(name) => match *name {
212 "bool" => &["bool"],
213 "bytes" => &["bytes"],
214 "dict" => &["dict"],
215 "float" => &["float"],
216 "int" => &["int"],
217 "list" => &["list"],
218 "nil" => &["nil"],
219 "string" => &["string"],
220 _ => &[],
221 },
222 Ty::Union(members) => match *members {
223 [Ty::Named("string"), Ty::Named("nil")] => &["string", "nil"],
224 [Ty::Named("nil"), Ty::Named("string")] => &["string", "nil"],
225 [Ty::Named("int"), Ty::Named("nil")] => &["int", "nil"],
226 [Ty::Named("nil"), Ty::Named("int")] => &["int", "nil"],
227 [Ty::Named("dict"), Ty::Named("nil")] => &["dict", "nil"],
228 [Ty::Named("nil"), Ty::Named("dict")] => &["dict", "nil"],
229 [Ty::Named("bytes"), Ty::Named("nil")] => &["bytes", "nil"],
230 [Ty::Named("nil"), Ty::Named("bytes")] => &["bytes", "nil"],
231 _ => &[],
232 },
233 Ty::Never => &["never"],
234 _ => &[],
235 }
236}