1use std::borrow::Cow;
2
3use harn_builtin_meta::{BuiltinContract, BuiltinExposure};
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq)]
7pub enum VmBuiltinKind {
8 Sync,
9 Async,
10}
11
12#[derive(Clone, Copy, Debug, PartialEq, Eq)]
17pub enum VmBuiltinArity {
18 Exact(usize),
19 Min(usize),
20 Range { min: usize, max: usize },
21 Variadic,
22}
23
24#[derive(Clone, Debug, PartialEq, Eq)]
26pub struct VmBuiltinMetadata {
27 name: Cow<'static, str>,
28 kind: VmBuiltinKind,
29 signature: Option<Cow<'static, str>>,
30 arity: Option<VmBuiltinArity>,
31 category: Option<Cow<'static, str>>,
32 doc: Option<Cow<'static, str>>,
33 contract: BuiltinContract,
34}
35
36impl VmBuiltinMetadata {
37 pub fn sync(name: impl Into<Cow<'static, str>>) -> Self {
38 Self::new(name, VmBuiltinKind::Sync)
39 }
40
41 pub fn async_builtin(name: impl Into<Cow<'static, str>>) -> Self {
42 Self::new(name, VmBuiltinKind::Async)
43 }
44
45 pub const fn sync_static(name: &'static str) -> Self {
46 Self::new_static(name, VmBuiltinKind::Sync)
47 }
48
49 pub const fn async_static(name: &'static str) -> Self {
50 Self::new_static(name, VmBuiltinKind::Async)
51 }
52
53 fn new(name: impl Into<Cow<'static, str>>, kind: VmBuiltinKind) -> Self {
54 Self {
55 name: name.into(),
56 kind,
57 signature: None,
58 arity: None,
59 category: None,
60 doc: None,
61 contract: BuiltinContract::RUNTIME_INTERNAL,
62 }
63 }
64
65 const fn new_static(name: &'static str, kind: VmBuiltinKind) -> Self {
66 Self {
67 name: Cow::Borrowed(name),
68 kind,
69 signature: None,
70 arity: None,
71 category: None,
72 doc: None,
73 contract: BuiltinContract::RUNTIME_INTERNAL,
74 }
75 }
76
77 pub(crate) fn with_kind(mut self, kind: VmBuiltinKind) -> Self {
78 self.kind = kind;
79 self
80 }
81
82 pub fn signature_static(mut self, signature: &'static str) -> Self {
83 self.signature = Some(Cow::Borrowed(signature));
84 self
85 }
86
87 pub fn signature_owned(mut self, signature: impl Into<Cow<'static, str>>) -> Self {
88 self.signature = Some(signature.into());
89 self
90 }
91
92 pub fn arity(mut self, arity: VmBuiltinArity) -> Self {
93 self.arity = Some(arity);
94 self
95 }
96
97 pub fn category_static(mut self, category: &'static str) -> Self {
98 self.category = Some(Cow::Borrowed(category));
99 self
100 }
101
102 pub fn category_owned(mut self, category: impl Into<Cow<'static, str>>) -> Self {
103 self.category = Some(category.into());
104 self
105 }
106
107 pub fn doc_static(mut self, doc: &'static str) -> Self {
108 self.doc = Some(Cow::Borrowed(doc));
109 self
110 }
111
112 pub fn doc_owned(mut self, doc: impl Into<Cow<'static, str>>) -> Self {
113 self.doc = Some(doc.into());
114 self
115 }
116
117 pub fn with_contract(mut self, contract: BuiltinContract) -> Self {
118 assert!(
119 contract.is_declared(),
120 "dynamic builtin `{}` must supply a declared contract",
121 self.name
122 );
123 self.contract = contract;
124 self
125 }
126
127 pub fn name(&self) -> &str {
128 self.name.as_ref()
129 }
130
131 pub fn kind(&self) -> VmBuiltinKind {
132 self.kind
133 }
134
135 pub fn signature(&self) -> Option<&str> {
136 self.signature.as_deref()
137 }
138
139 pub fn arity_metadata(&self) -> Option<VmBuiltinArity> {
140 self.arity
141 }
142
143 pub fn category(&self) -> Option<&str> {
144 self.category.as_deref()
145 }
146
147 pub fn doc(&self) -> Option<&str> {
148 self.doc.as_deref()
149 }
150
151 pub const fn contract(&self) -> BuiltinContract {
152 self.contract
153 }
154
155 pub const fn is_source_visible(&self) -> bool {
156 !matches!(
157 self.contract.exposure,
158 BuiltinExposure::RuntimeInternal | BuiltinExposure::Undeclared
159 )
160 }
161}