1use derive_more::Display;
2use nom::{
3 bytes::complete::{is_not, tag, take, take_while_m_n},
4 character::complete::{alpha1, alphanumeric1, char, multispace0},
5 combinator::opt,
6 error::Error,
7 multi::{many0, separated_list0},
8 sequence::{delimited, tuple},
9 IResult,
10};
11use sha3::{Digest, Sha3_256};
12use std::{collections::BTreeMap, fmt::Display};
13#[derive(Clone, Eq, PartialEq, PartialOrd, Ord)]
14pub struct Attr {
15 pub name: String,
16 pub value: String,
17}
18
19pub fn merge(a: Vec<Attr>, b: Vec<Attr>) -> Vec<Attr> {
20 let mut m = BTreeMap::new();
21 for x in a.into_iter().chain(b) {
22 m.insert(x.name, x.value);
23 }
24 return m
25 .into_iter()
26 .map(|(a, b)| Attr { name: a, value: b })
27 .collect();
28}
29
30pub fn parse_balanced(mut a: &str) -> IResult<&str, String> {
31 let mut v = vec![];
32 let mut i = 0;
33 loop {
34 let (b, x) = nom::character::complete::anychar(a)?;
35 match x {
36 '[' => i += 1,
37 ']' => {
38 if i == 0 {
39 return Ok((a, v.into_iter().collect()));
40 }
41 i -= 1;
42 }
43 _ => {}
44 }
45 a = b;
46 v.push(x)
47 }
48}
49
50pub fn parse_attr(a: &str) -> IResult<&str, Attr> {
51 let (a, _) = multispace0(a)?;
52 let (a, _) = char('[')(a)?;
53 let (a, _) = multispace0(a)?;
54 let (a, name) = alphanumeric1(a)?;
55 let (a, _) = multispace0(a)?;
56 let (a, _) = char('=')(a)?;
57 let (a, _) = multispace0(a)?;
58 let (a, value) = parse_balanced(a)?;
59 let (a, _) = char(']')(a)?;
60 let (a, _) = multispace0(a)?;
61 return Ok((
62 a,
63 Attr {
64 name: name.to_owned(),
65 value,
66 },
67 ));
68}
69
70pub fn parse_attrs(a: &str) -> IResult<&str, Vec<Attr>> {
71 let (a, mut b) = many0(parse_attr)(a)?;
72 b.sort_by_key(|a| a.name.clone());
73 Ok((a, b))
74}
75
76impl Display for Attr {
77 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
78 write!(f, "[{}={}]", self.name, self.value)
79 }
80}
81
82#[derive(Display, Clone, Eq, PartialEq, PartialOrd, Ord)]
83pub enum ResTy {
84 #[display(fmt = "{}", "hex::encode(_0)")]
85 Of([u8; 32]),
86 #[display(fmt = "this")]
87 This,
88}
89pub fn parse_resty(a: &str) -> IResult<&str, ResTy> {
90 if let Some(a) = a.strip_prefix("this") {
91 return Ok((a, ResTy::This));
93 }
94 let (a, d) = take_while_m_n(64, 64, |a: char| a.is_digit(16))(a)?;
95 return Ok((
96 a,{
97
98 let mut b = [0u8; 32];
99 hex::decode_to_slice(d, &mut b).unwrap();
100 ResTy::Of(b)
101 }
102
103 ));
104}
105#[derive(Display, Clone, Eq, PartialEq, PartialOrd, Ord)]
106pub enum Arg {
107 #[display(fmt="{}@{}{}","ann.iter().map(|a|a.to_string()).collect::<Vec<_>>().join(\"\")","name","params.iter().map(|a|a.to_string()).map(|b|format!(\"({b})\")).collect::<Vec<_>>().join(\"\")")]
108 Prim{
109 name: String,
110 ann: Vec<Attr>,
111 params: Vec<Arg>,
112 },
113 #[display(
114 fmt = "{}R{}",
115 "ann.iter().map(|a|a.to_string()).collect::<Vec<_>>().join(\"\")",
116 "ty",
117 )]
118 Resource {
119 ty: ResTy,
120 ann: Vec<Attr>,
121 },
122 }
125pub fn parse_arg(a: &str) -> IResult<&str, Arg> {
126 let (a, ann) = parse_attrs(a)?;
127 let (a, _) = multispace0(a)?;
128 match a.strip_prefix("R") {
130 Some(b) => {
131 let (a, d) = parse_resty(b)?;
142 return Ok((
143 a,
144 Arg::Resource {
145 ty: d,
146 ann,
147 },
148 ));
149 }
150 None => match a.strip_prefix("@"){
155 None => todo!(),
156 Some(a) => {
157 let (a,k) = alphanumeric1(a)?;
158 let (a,l) = many0(delimited(tag("("), parse_arg, tag(")")))(a)?;
159 return Ok((a,Arg::Prim { name: k.to_owned(), ann: ann, params: l }));
160 }
161 }
162 }
163 todo!()
164}
165#[derive(Display, Clone, Eq, PartialEq, PartialOrd, Ord)]
166#[display(
167 fmt = "{}({}) -> ({})",
168 "ann.iter().map(|a|a.to_string()).collect::<Vec<_>>().join(\"\")",
169 "params.iter().map(|a|a.to_string()).collect::<Vec<_>>().join(\",\")",
170 "rets.iter().map(|a|a.to_string()).collect::<Vec<_>>().join(\",\")"
171)]
172pub struct Sig {
173 pub ann: Vec<Attr>,
174 pub params: Vec<Arg>,
175 pub rets: Vec<Arg>,
176}
177pub fn parse_sig(a: &str) -> IResult<&str, Sig> {
178 let (a, b) = parse_attrs(a)?;
179 let (a, _) = multispace0(a)?;
180 let mut d = delimited(char('('), separated_list0(char(','), parse_arg), char(')'));
181 let (a, params) = d(a)?;
182 let (a, _) = multispace0(a)?;
183 let (a, _) = tag("->")(a)?;
184 let (a, _) = multispace0(a)?;
185 let (a, rets) = d(a)?;
186 return Ok((
187 a,
188 Sig {
189 params,
190 rets,
191 ann: b,
192 },
193 ));
194}
195#[derive(Clone, Eq, PartialEq, PartialOrd, Ord)]
196pub struct Interface {
197 pub methods: BTreeMap<String, Sig>,
198 pub ann: Vec<Attr>,
199}
200impl Display for Interface {
201 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
202 for a in self.ann.iter() {
203 write!(f, "{a}")?;
204 }
205 write!(f, "{}", "{")?;
206 let mut x = self.methods.iter().collect::<Vec<_>>();
207 x.sort_by_key(|a| a.0);
208 for (i, (a, b)) in x.into_iter().enumerate() {
209 if i != 0 {
210 write!(f, ";")?;
211 }
212 write!(f, "{}{}", a, b)?;
213 }
214 return write!(f, "{}", "}");
215 }
216}
217pub fn parse_interface(a: &str) -> IResult<&str, Interface> {
218 pub fn go(a: &str) -> IResult<&str, Interface> {
219 let (a, s) = separated_list0(char(';'), tuple((multispace0, alphanumeric1, parse_sig)))(a)?;
220 let (a, _) = multispace0(a)?;
221 return Ok((
222 a,
223 Interface {
224 methods: s.into_iter().map(|(_, a, b)| (a.to_owned(), b)).collect(),
225 ann: vec![],
226 },
227 ));
228 }
229 let (a, _) = multispace0(a)?;
230 let (a, b) = parse_attrs(a)?;
231 let (a, mut c) = delimited(char('{'), go, char('}'))(a)?;
232 c.ann = b;
233 return Ok((a, c));
234}
235impl Interface {
236 pub fn rid(&self) -> [u8; 32] {
237 use std::io::Write;
238 let mut s = Sha3_256::default();
239 write!(s, "{}", self);
240 return s.finalize().try_into().unwrap();
241 }
242 pub fn rid_str(&self) -> String {
243 return hex::encode(self.rid());
244 }
245}
246pub mod info;
247pub fn retuple(a: Vec<Arg>) -> Interface {
248 Interface {
249 methods: a.into_iter().enumerate().map(|(a, b)| {
250 (
251 format!("v{a}"),
252 Sig {
253 ann: vec![],
254 params: vec![],
255 rets: vec![b],
256 },
257 )
258 }).collect(),
259 ann: vec![],
260 }
261}