py_ast/parse/
types.rs

1use std::ops::Deref;
2
3use py_lex::types::BasicExtenWord;
4
5use super::*;
6use crate::complex_pu;
7
8/// Decorators
9#[derive(Debug, Clone, Copy)]
10pub struct TypeConstExtend;
11
12impl ParseUnit<Token> for TypeConstExtend {
13    type Target = TypeConstExtend;
14
15    fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
16        p.r#match(BasicExtenWord::Const)?;
17
18        Ok(TypeConstExtend)
19    }
20}
21
22#[derive(Debug,Clone, Copy)]
23pub struct Size{
24    size: PU<usize>
25}
26
27impl Deref for Size{
28    type Target = usize;
29
30    fn deref(&self) -> &Self::Target {
31        &self.size
32    }
33}
34
35impl WithSpan for Size{
36    fn get_span(&self) -> Span {
37        self.size.get_span()
38    }
39}
40
41
42impl ParseUnit<Token> for Size{
43    type Target = Size;
44
45    fn parse(p: &mut Parser<Token>) -> terl::Result<Self::Target, ParseError> {
46        let token =p.parse::<Token>()?;
47        let size = match token.parse::<usize>(){
48                Ok(num) => PU::new(token.get_span(),num),
49                Err(pe) => return token.unmatch(format!("expect a number, but got `{}` while parsing",pe)),
50            };
51        Ok(Self { size })
52    }
53}
54/// Decorators
55#[derive(Debug, Clone, Copy)]
56pub struct TypeArrayExtend {
57    pub keyword: PU<BasicExtenWord>,
58    pub size: Option<Size>,
59}
60
61impl ParseUnit<Token> for TypeArrayExtend {
62    type Target = TypeArrayExtend;
63
64    fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
65        let keyword = p.r#match(RPU(BasicExtenWord::Array))?;
66        let size = p.parse::<Size>().apply(mapper::Try)?;
67        Ok(TypeArrayExtend { keyword, size })
68    }
69}
70
71/// Decorators
72#[derive(Debug, Clone, Copy)]
73pub struct TypeReferenceExtend;
74
75impl ParseUnit<Token> for TypeReferenceExtend {
76    type Target = TypeReferenceExtend;
77
78    fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
79        p.r#match(BasicExtenWord::Reference)?;
80        Ok(TypeReferenceExtend)
81    }
82}
83
84/// Decorators
85#[derive(Debug, Clone, Copy)]
86pub struct TypePointerExtend;
87
88impl ParseUnit<Token> for TypePointerExtend {
89    type Target = TypePointerExtend;
90
91    fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
92        p.r#match(BasicExtenWord::Pointer)?;
93        Ok(TypePointerExtend)
94    }
95}
96
97complex_pu! {
98    cpu TypeDecorators {
99        TypeArrayExtend,
100        TypeReferenceExtend,
101        TypePointerExtend
102    }
103}
104
105/// Decorators for primitive types
106
107#[derive(Debug, Clone, Copy)]
108pub struct TypeWidthExtend {
109    
110    pub width: Size,
111}
112
113impl ParseUnit<Token> for TypeWidthExtend {
114    type Target = TypeWidthExtend;
115
116    fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
117        p.r#match(BasicExtenWord::Width)?;
118        let width = p.parse::<Size>().apply(mapper::MustMatch)?;
119
120        Ok(TypeWidthExtend {  width })
121    }
122}
123
124/// Decorators for `zheng3`
125
126#[derive(Debug, Clone, Copy)]
127pub struct TypeSignExtend {
128    pub sign: bool,
129}
130
131impl ParseUnit<Token> for TypeSignExtend {
132    type Target = TypeSignExtend;
133
134    fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
135        let keyword = p.parse::<PU<BasicExtenWord>>()?;
136        let sign = match *keyword {
137            BasicExtenWord::Signed => true,
138            BasicExtenWord::Unsigned => false,
139            _ => {
140                return keyword.throw("should be `you3fu2` or `wu2fu2`");
141            }
142        };
143
144        Ok(TypeSignExtend { sign })
145    }
146}
147
148#[derive(Debug, Clone)]
149pub struct TypeDefine {
150    pub const_: Option<PU<TypeConstExtend>>,
151    pub decorators: Vec<PU<TypeDecorators>>,
152    pub width: Option<PU<TypeWidthExtend>>,
153    pub sign: Option<PU<TypeSignExtend>>,
154    pub ty: Ident,
155}
156
157impl TypeDefine {
158    pub(crate) fn to_mir_ty(&self) -> terl::Result<crate::ir::types::TypeDefine> {
159        self.try_into()
160    }
161}
162
163impl TryFrom<&TypeDefine> for crate::ir::types::TypeDefine {
164    type Error = terl::Error;
165
166    fn try_from(def: &crate::parse::TypeDefine) -> std::result::Result<Self, Self::Error> {
167        use crate::ir::types::{ComplexType, PrimitiveType};
168        /*
169           int: sign, width
170           float: width
171        */
172
173        if &*def.ty == "zheng3" {
174            // default to be i64
175            let sign = def.sign.map(|pu| pu.sign).unwrap_or(true);
176
177            let width = if let Some(width_extend) = def.width {
178                if !width_extend.width.is_power_of_two()
179                    || *width_extend.width > 128
180                    || *width_extend.width < 64
181                {
182                    return Err(width_extend.make_error(format!(
183                        "`zheng3` with width {} is not suppert now",
184                        *width_extend.width
185                    )));
186                }
187                *width_extend.width
188            } else {
189                64
190            };
191
192            use PrimitiveType::*;
193            #[rustfmt::skip]
194            let ty = match width {
195                8   => if sign { I8   } else { U8   },                
196                16  => if sign { I16  } else { U16  },                
197                32  => if sign { I32  } else { U32  },                
198                64  => if sign { I64  } else { U64  },            
199                128 => if sign { I128 } else { U128 },
200                _ => unreachable!(),
201            };
202            return Ok(ty.into());
203        } else if &*def.ty == "fu2" {
204            // default to be f32
205            if let Some(sign) = def.sign {
206                return Err(
207                    sign.make_error("`fu2` type cant be decorated with `you3fu2` or `wu2fu2`")
208                );
209            }
210            let width = if let Some(width) = def.width {
211                if *width.width == 32 || *width.width == 64 {
212                    *width.width
213                } else {
214                    return Err(width.make_error(format!(
215                        "`fu2` with width {} is not supperted now",
216                        *width.width
217                    )));
218                }
219            } else {
220                32
221            };
222
223            let ty = match width {
224                32 => PrimitiveType::F32,
225                64 => PrimitiveType::F64,
226                _ => unreachable!(),
227            };
228            return Ok(ty.into());
229        }
230
231        if let Some(sign) = def.sign {
232            return Err(sign.make_error(format!(
233                "type `{}` with `you3fu2` or `wu2fu2` is not supperted now",
234                def.ty
235            )));
236        }
237        if let Some(width) = def.width {
238            return Err(width.make_error(format!(
239                "type `{}` with `you3fu2` or `wu2fu2` is not supperted now",
240                def.ty
241            )));
242        }
243        let ty = def.ty.to_string();
244
245        if def.const_.is_none() && def.decorators.is_empty() {
246            return Ok(ComplexType::no_decorators(ty).into());
247        }
248
249        use crate::ir::types::TypeDecorators::*;
250
251        let mut decorators = vec![];
252        if def.const_.is_some() {
253            decorators.push(Const);
254        }
255
256        for decorator in &def.decorators {
257            let decorator = match &**decorator{
258                crate::parse::TypeDecorators::TypeArrayExtend(array) => match array.size {
259                    Some(size) => SizedArray(*size),
260                    None => Array,
261                },
262                crate::parse::TypeDecorators::TypeReferenceExtend(_) => {
263                    Reference
264                }
265                crate::parse::TypeDecorators::TypePointerExtend(_) => {
266                    Pointer
267                }
268            };
269            decorators.push(decorator);
270        }
271
272        Ok(ComplexType { decorators, ty }.into())
273    }
274}
275
276impl ParseUnit<Token> for TypeDefine {
277    type Target = TypeDefine;
278
279    fn parse(p: &mut Parser<Token>) -> ParseResult<Self, Token> {
280        let const_ = p.parse::<PU<TypeConstExtend>>().apply(mapper::Try)?;
281        let mut decorators = vec![];
282        while let Some(decorator) = p.parse::<PU<TypeDecorators>>().apply(mapper::Try)? {
283            decorators.push(decorator);
284        }
285        let width = p.parse::<PU<TypeWidthExtend>>().apply(mapper::Try)?;
286        let sign = p.parse::<PU<TypeSignExtend>>().apply(mapper::Try)?;
287        let ty = p.parse::<Ident>()?;
288        Ok(TypeDefine {
289            const_,
290            decorators,
291            width,
292            sign,
293            ty,
294        })
295    }
296}
297
298#[cfg(test)]
299mod tests {
300    use crate::parse_test;
301
302    use super::*;
303
304    #[test]
305    fn fucking_type() {
306        parse_test("yin3 zu3 114514 kuan1 32 wu2fu2 zheng3", |p| {
307            p.parse::<TypeDefine>()?;
308            Ok(())
309        })
310    }
311}