mrubyedge_cli/rbs_parser/
mod.rs1extern crate nom;
2
3#[derive(Debug)]
4pub struct FuncDef {
5 pub name: String,
6 pub argstype: Vec<String>,
7 pub rettype: String,
8}
9
10impl FuncDef {
11 pub fn args_decl(&self) -> &str {
12 if self.argstype.len() == 0 {
13 return "";
14 }
15
16 let converted: Vec<String> = self
17 .argstype
18 .iter()
19 .enumerate()
20 .map(|(idx, arg)| match arg.as_str() {
21 "Integer" => format!("a{}: i32", idx),
22 "Float" => format!("a{}: f32", idx),
23 "bool" => format!("a{}: bool", idx),
24 "String" => format!("p{0}: *const u8, l{0}: usize", idx),
25 _ => {
26 unimplemented!("unsupported arg type")
27 }
28 })
29 .collect();
30 converted.join(", ").leak()
31 }
32
33 pub fn args_let_vec(&self) -> &str {
34 if self.argstype.len() == 0 {
35 return "vec![]";
36 }
37
38 let converted: Vec<String> = self
39 .argstype
40 .iter()
41 .enumerate()
42 .map(|(idx, arg)| match arg.as_str() {
43 "Integer" => format!("std::rc::Rc::new(RObject::integer(a{} as i64))", idx),
44 "Float" => format!("std::rc::Rc::new(RObject::float(a{} as f64))", idx),
45 "bool" => format!("std::rc::Rc::new(RObject::boolean(a{}))", idx),
46 "String" => format!("std::rc::Rc::new(RObject::string(a{}.to_string()))", idx),
47 _ => {
48 unimplemented!("unsupported arg type")
49 }
50 })
51 .collect();
52 format!("vec![{}]", converted.join(", ")).leak()
53 }
54
55 pub fn str_args_converter(&self) -> &str {
56 if self.argstype.len() == 0 {
57 return "";
58 }
59 let mut buf = String::new();
60
61 for (idx, arg) in self.argstype.iter().enumerate() {
62 match arg.as_str() {
63 "String" => {
64 buf.push_str(&format!(
65 "
66let a{0} = unsafe {{
67 let s = std::slice::from_raw_parts(p{0}, l{0} as usize);
68 std::str::from_utf8(s).expect(\"invalid utf8\")
69}};
70",
71 idx
72 ));
73 }
74 _ => {
75 }
77 }
78 }
79
80 buf.leak()
81 }
82
83 pub fn rettype_decl(&self) -> &str {
84 match self.rettype.as_str() {
85 "void" => "-> ()",
86 "Integer" => "-> i32",
87 "Float" => "-> f32",
88 "bool" => "-> bool",
89 "String" => "-> *const u8",
90 "SharedMemory" => "-> *mut u8",
91 _ => {
92 unimplemented!("unsupported arg type")
93 }
94 }
95 }
96
97 pub fn handle_retval(&self) -> &str {
98 match self.rettype.as_str() {
99 "String" => {
100 let mut buf = String::new();
101 buf.push_str("let mut retval: String = retval.as_ref().try_into().unwrap();\n");
102 buf.push_str("retval.push('\0');\n");
103 buf.push_str(&format!(
104 "unsafe {{ {} = retval.len() - 1; }}\n",
105 self.size_helper_var_name()
106 ));
107 buf.push_str("retval.as_str().as_ptr()\n");
108 buf.leak()
109 }
110 _ => "retval.as_ref().try_into().unwrap()",
111 }
112 }
113
114 fn size_helper_var_name(&self) -> String {
115 format!("__{}_size", self.name)
116 }
117
118 pub fn exported_helper_var(&self) -> &str {
119 match self.rettype.as_str() {
120 "String" => format!(
121 "
122#[allow(non_upper_case_globals)]
123pub static mut {0}: usize = 0;
124#[no_mangle]
125pub unsafe fn __get{0}() -> u32 {{
126 return {0} as u32;
127}}
128",
129 &self.size_helper_var_name()
130 )
131 .leak(),
132 _ => "",
133 }
134 }
135
136 pub fn import_helper_var(&self) -> &str {
137 match self.rettype.as_str() {
138 "String" => format!(
139 "
140#[allow(non_upper_case_globals)]
141pub static mut {0}: usize = 0;
142#[no_mangle]
143pub unsafe fn __set{0}(s: u32) {{
144 {0} = s as usize;
145}}
146",
147 &self.size_helper_var_name()
148 )
149 .leak(),
150 _ => "",
151 }
152 }
153
154 pub fn imported_body(&self) -> &str {
156 let mut buf = String::new();
157 for (i, typ) in self.argstype.iter().enumerate() {
158 let tmp = match typ.as_str() {
159 "String" => {
160 let mut buf = String::new();
161 buf.push_str(&format!(
162 "let a{0}: String = args[{0}].clone().as_ref().try_into().unwrap();\n",
163 i
164 ));
165 buf.push_str(&format!("let p{0} = a{0}.as_str().as_ptr();\n", i));
166 buf.push_str(&format!("let l{0} = a{0}.as_str().len();\n", i));
167 buf
168 }
169 _ => format!(
170 "let a{0} = args[{0}].clone().as_ref().try_into().unwrap();\n",
171 i,
172 ),
173 };
174 buf.push_str(&tmp);
175 }
176 let call_arg = self
177 .argstype
178 .iter()
179 .enumerate()
180 .map(|(i, typ)| match typ.as_str() {
181 "String" => format!("p{0}, l{0}", i),
182 _ => format!("a{}", i),
183 })
184 .collect::<Vec<String>>()
185 .join(",");
186 buf.push_str(&format!(
187 "let r0 = unsafe {{ {}({}) }};\n",
188 &self.name, call_arg
189 ));
190
191 if self.rettype.as_str() == "String" {
192 buf.push_str(&format!(
193 "
194let s0: String;
195unsafe {{
196 if {0} == 0 {{
197 let mut buf = Vec::<u8>::new();
198 let mut off: usize = 0;
199 loop {{
200 let b = *(r0.add(off));
201 if b == 0 {{
202 break;
203 }} else {{
204 buf.push(b);
205 }}
206 if off >= 65536 {{
207 panic!(\"unterminated string detected\");
208 }}
209 off += 1;
210 }}
211 s0 = String::from_utf8_unchecked(buf);
212 }} else {{
213 let off = {0};
214 let s = std::slice::from_raw_parts(r0, off);
215 s0 = String::from_utf8_unchecked(s.to_vec());
216 }}
217}}
218",
219 self.size_helper_var_name()
220 ));
221 }
222
223 let ret_mruby_type = match self.rettype.as_str() {
224 "Integer" => "RObject::integer(r0 as i64)",
225 "Float" => "RObject::float(r0 as f64)",
226 "bool" => "RObject::boolean(r0)",
227 "String" => "RObject::string(s0)",
228 "void" => "RObject::nil()",
229 _ => unimplemented!("unsupported arg type"),
230 };
231 buf.push_str(&format!("Ok(Rc::new({}))\n", ret_mruby_type));
232 buf.leak()
233 }
234}
235
236use nom::branch::alt;
237use nom::branch::permutation;
238use nom::bytes::complete::tag;
239use nom::character::complete::*;
240use nom::IResult;
242use nom::error::VerboseError;
243use nom::error::context;
244use nom::multi::*;
245use nom::sequence::tuple;
246
247type Res<T, U> = IResult<T, U, VerboseError<T>>;
248
249fn def(input: &str) -> Res<&str, ()> {
250 context("def", tag("def"))(input).map(|(s, _)| (s, ()))
251}
252
253fn alpha_just_1(input: &str) -> Res<&str, char> {
254 satisfy(|c| c == '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))(input)
255}
256
257fn alphanumeric_just_1(input: &str) -> Res<&str, char> {
258 satisfy(|c| {
259 c == '_' || ('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
260 })(input)
261}
262
263fn symbol(input: &str) -> Res<&str, String> {
264 tuple((alpha_just_1, many0(alphanumeric_just_1)))(input).map(|(s, (head, tail))| {
265 let mut name: String = head.to_string();
266 for c in tail.iter() {
267 name += &c.to_string()
268 }
269 (s, name)
270 })
271}
272
273fn method(input: &str) -> Res<&str, String> {
274 tuple((symbol, char(':'), space0))(input).map(|(s, (sym, _, _))| (s, sym))
275}
276
277fn emptyarg(input: &str) -> Res<&str, Vec<String>> {
278 tuple((char('('), space0, char(')')))(input).map(|(s, _)| (s, vec![]))
279}
280
281fn contentarg(input: &str) -> Res<&str, Vec<String>> {
282 tuple((
283 char('('),
284 space0,
285 symbol,
286 space0,
287 many0(tuple((char(','), space0, symbol, space0))),
288 char(')'),
289 ))(input)
290 .map(|(s, (_, _, head, _, rest, _))| {
291 let mut syms: Vec<String> = rest.into_iter().map(|(_, _, val, _)| val).collect();
292 syms.insert(0, head);
293 (s, syms)
294 })
295}
296
297fn arg(input: &str) -> Res<&str, Vec<String>> {
298 alt((emptyarg, contentarg))(input)
299}
300
301fn ret(input: &str) -> Res<&str, String> {
302 tuple((tag("->"), space0, symbol))(input).map(|(s, (_, _, sym))| (s, sym))
303}
304
305fn fntype(input: &str) -> Res<&str, (Vec<String>, String)> {
306 tuple((arg, space0, ret))(input).map(|(s, (arg, _, ret))| (s, (arg, ret)))
307}
308
309pub fn fn_def(input: &str) -> Res<&str, FuncDef> {
310 tuple((def, space1, method, fntype))(input).map(|(s, (_, _, name, (argstype, rettype)))| {
311 (
312 s,
313 FuncDef {
314 name,
315 argstype,
316 rettype,
317 },
318 )
319 })
320}
321
322pub fn parse(input: &str) -> Res<&str, Vec<FuncDef>> {
323 tuple((
324 multispace0,
325 separated_list0(permutation((space0, many1(char('\n')), space0)), fn_def),
326 ))(input)
327 .map(|(s, (_, list))| (s, list))
328}