1#![allow(unreachable_patterns)]
9
10use pest::Parser;
11use pest_derive::Parser;
12use std::path::Path;
13
14pub mod annotations;
15
16#[derive(Parser)]
17#[grammar = "grammar.pest"]
18pub struct ThalirParser;
19
20pub type ParseResult<T> = Result<T, Box<pest::error::Error<Rule>>>;
21
22pub fn parse(input: &str) -> ParseResult<pest::iterators::Pairs<'_, Rule>> {
23 ThalirParser::parse(Rule::module, input).map_err(|e| Box::new(e))
24}
25
26pub fn parse_file<P: AsRef<Path>>(path: P) -> ParseResult<String> {
27 std::fs::read_to_string(path).map_err(|e| {
28 Box::new(pest::error::Error::new_from_pos(
29 pest::error::ErrorVariant::CustomError {
30 message: format!("Failed to read file: {}", e),
31 },
32 pest::Position::from_start(""),
33 ))
34 })
35}
36
37pub fn check(input: &str) -> bool {
38 parse(input).is_ok()
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 #[test]
46 fn test_empty_module() {
47 let input = "";
48 assert!(check(input));
49 }
50
51 #[test]
52 fn test_simple_function() {
53 let input = r"
54function %test(i32, i32) -> i32 {
55block0(v0: i32, v1: i32):
56 v2 = iadd v0, v1
57 return v2
58}
59";
60 assert!(check(input));
61 }
62
63 #[test]
64 fn test_function_with_entities() {
65 let input = r"
66function %f(i64, i32) -> i32 {
67 gv0 = vmctx
68 gv1 = load.i64 notrap readonly aligned gv0+8
69 fn0 = %g(i64)
70
71block0(v0: i64, v1: i32):
72 v2 = global_value.i64 gv1
73 v3 = load.i32 v2+8
74 return v3
75}
76";
77 match parse(input) {
78 Ok(_) => {}
79 Err(e) => panic!("Parse error: {}", e),
80 }
81 }
82
83 #[test]
84 #[ignore]
85 fn test_branch_with_block_args() {
86 let input = r"
87function %f(i32, i32) -> i32 {
88block0(v0: i32, v1: i32):
89 v2 = iadd v0, v1
90 brif v2, block1(v0), block2(v1)
91
92block1(v3: i32):
93 return v3
94
95block2(v4: i32):
96 return v4
97}
98";
99 match parse(input) {
100 Ok(_) => {}
101 Err(e) => panic!("Parse error: {}", e),
102 }
103 }
104
105 #[test]
106 fn test_test_directives() {
107 let input = r"
108test optimize
109set opt_level=speed
110target x86_64
111
112function %f(i32) -> i32 {
113block0(v0: i32):
114 return v0
115}
116";
117 assert!(check(input));
118 }
119
120 #[test]
121 #[ignore]
122 fn test_floats_and_vectors() {
123 let input = r"
124function %f(f32x4, f64) -> f32x4 {
125block0(v0: f32x4, v1: f64):
126 v2 = fconst.f32 0x1.5p-3
127 v3 = fconst.f64 3.14159
128 v4 = fconst.f64 NaN
129 v5 = fconst.f64 Inf
130 return v0
131}
132";
133 assert!(check(input));
134 }
135}