pit_core/
lib.rs

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#[non_exhaustive]
82#[derive(Display, Clone, Eq, PartialEq, PartialOrd, Ord)]
83pub enum ResTy {
84    #[display(fmt = "")]
85    None,
86    #[display(fmt = "{}", "hex::encode(_0)")]
87    Of([u8; 32]),
88    #[display(fmt = "this")]
89    This,
90}
91pub fn parse_resty(a: &str) -> IResult<&str, ResTy> {
92    if let Some(a) = a.strip_prefix("this") {
93        // let (a, k) = opt(tag("n"))(a)?;
94        return Ok((a, ResTy::This));
95    }
96    let (a, d) = opt(take_while_m_n(64, 64, |a: char| a.is_digit(16)))(a)?;
97    return Ok((
98        a,
99        match d {
100            Some(d) => {
101                let mut b = [0u8; 32];
102                hex::decode_to_slice(d, &mut b).unwrap();
103                ResTy::Of(b)
104            }
105            None => ResTy::None,
106        },
107    ));
108}
109#[non_exhaustive]
110#[derive(Display, Clone, Eq, PartialEq, PartialOrd, Ord)]
111pub enum Arg {
112    I32,
113    I64,
114    F32,
115    F64,
116    #[display(
117        fmt = "{}R{}{}{}",
118        "ann.iter().map(|a|a.to_string()).collect::<Vec<_>>().join(\"\")",
119        "ty",
120        "if *nullable{\"n\"}else{\"\"}",
121        "if *take{\"\"}else{\"&\"}"
122    )]
123    Resource {
124        ty: ResTy,
125        nullable: bool,
126        take: bool,
127        ann: Vec<Attr>,
128    },
129    // #[display(fmt = "{}", _0)]
130    // Func(Sig),
131}
132pub fn parse_arg(a: &str) -> IResult<&str, Arg> {
133    let (a, ann) = parse_attrs(a)?;
134    let (a, _) = multispace0(a)?;
135    // let (c,b) = take(1usize)(a)?;
136    match a.strip_prefix("R") {
137        Some(b) => {
138            // if let Some(a) = b.strip_prefix("this"){
139            //     let (a, k) = opt(tag("n"))(a)?;
140            //     return Ok((
141            //         a,
142            //         Arg::Resource {
143            //             ty: ResTy::This,
144            //             nullable: k.is_some(),
145            //         },
146            //     ));
147            // }
148            let (a, d) = parse_resty(b)?;
149            let (a, k) = opt(tag("n"))(a)?;
150            let (a, take) = opt(tag("&"))(a)?;
151            return Ok((
152                a,
153                Arg::Resource {
154                    ty: d,
155                    nullable: k.is_some(),
156                    take: take.is_none(),
157                    ann,
158                },
159            ));
160        }
161        // "(" => {
162        //     let (a, x) = parse_sig(a)?;
163        //     return Ok((a, Arg::Func(x)));
164        // }
165        None => {
166            let (a, c) = take(3usize)(a)?;
167            match c {
168                "I32" => return Ok((a, Arg::I32)),
169                "I64" => return Ok((a, Arg::I64)),
170                "F32" => return Ok((a, Arg::F32)),
171                "F64" => return Ok((a, Arg::F64)),
172                _ => return Err(nom::Err::Error(Error::new(a, nom::error::ErrorKind::Tag))),
173            }
174        }
175    }
176    todo!()
177}
178#[derive(Display, Clone, Eq, PartialEq, PartialOrd, Ord)]
179#[display(
180    fmt = "{}({}) -> ({})",
181    "ann.iter().map(|a|a.to_string()).collect::<Vec<_>>().join(\"\")",
182    "params.iter().map(|a|a.to_string()).collect::<Vec<_>>().join(\",\")",
183    "rets.iter().map(|a|a.to_string()).collect::<Vec<_>>().join(\",\")"
184)]
185pub struct Sig {
186    pub ann: Vec<Attr>,
187    pub params: Vec<Arg>,
188    pub rets: Vec<Arg>,
189}
190pub fn parse_sig(a: &str) -> IResult<&str, Sig> {
191    let (a, b) = parse_attrs(a)?;
192    let (a, _) = multispace0(a)?;
193    let mut d = delimited(char('('), separated_list0(char(','), parse_arg), char(')'));
194    let (a, params) = d(a)?;
195    let (a, _) = multispace0(a)?;
196    let (a, _) = tag("->")(a)?;
197    let (a, _) = multispace0(a)?;
198    let (a, rets) = d(a)?;
199    return Ok((
200        a,
201        Sig {
202            params,
203            rets,
204            ann: b,
205        },
206    ));
207}
208#[derive(Clone, Eq, PartialEq, PartialOrd, Ord)]
209pub struct Interface {
210    pub methods: BTreeMap<String, Sig>,
211    pub ann: Vec<Attr>,
212}
213impl Display for Interface {
214    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
215        for a in self.ann.iter() {
216            write!(f, "{a}")?;
217        }
218        write!(f, "{}", "{")?;
219        let mut x = self.methods.iter().collect::<Vec<_>>();
220        x.sort_by_key(|a| a.0);
221        for (i, (a, b)) in x.into_iter().enumerate() {
222            if i != 0 {
223                write!(f, ";")?;
224            }
225            write!(f, "{}{}", a, b)?;
226        }
227        return write!(f, "{}", "}");
228    }
229}
230pub fn parse_interface(a: &str) -> IResult<&str, Interface> {
231    pub fn go(a: &str) -> IResult<&str, Interface> {
232        let (a, s) = separated_list0(char(';'), tuple((multispace0, alphanumeric1, parse_sig)))(a)?;
233        let (a, _) = multispace0(a)?;
234        return Ok((
235            a,
236            Interface {
237                methods: s.into_iter().map(|(_, a, b)| (a.to_owned(), b)).collect(),
238                ann: vec![],
239            },
240        ));
241    }
242    let (a, _) = multispace0(a)?;
243    let (a, b) = parse_attrs(a)?;
244    let (a, mut c) = delimited(char('{'), go, char('}'))(a)?;
245    c.ann = b;
246    return Ok((a, c));
247}
248impl Interface {
249    pub fn rid(&self) -> [u8; 32] {
250        use std::io::Write;
251        let mut s = Sha3_256::default();
252        write!(s, "{}", self);
253        return s.finalize().try_into().unwrap();
254    }
255    pub fn rid_str(&self) -> String {
256        return hex::encode(self.rid());
257    }
258}
259pub mod info;
260pub fn retuple(a: Vec<Arg>) -> Interface {
261    Interface {
262        methods: a.into_iter().enumerate().map(|(a, b)| {
263            (
264                format!("v{a}"),
265                Sig {
266                    ann: vec![],
267                    params: vec![],
268                    rets: vec![b],
269                },
270            )
271        }).collect(),
272        ann: vec![],
273    }
274}