Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
compiler_parser_test.cc
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
31
37# include <gtest/gtest.h>
38
39# include <Compiler_Parser.H>
40
41using namespace Aleph;
42
43
45{
47 const auto id = sm.add_virtual_file(
48 "main.aw",
49 "fn add(x, y) {\n"
50 " let z = add(x, y);\n"
51 " return z + 1;\n"
52 "}\n");
53
55 Compiler_Ast_Context ctx(1 << 16);
56 Compiler_Parser parser(ctx, sm, id, &dx);
57
58 auto * module = parser.parse_module();
59
60 ASSERT_NE(module, nullptr);
61 ASSERT_EQ(module->functions.size(), 1u);
62 EXPECT_EQ(module->statements.size(), 0u);
64
65 const auto * fn = module->functions.access(0);
66 ASSERT_NE(fn, nullptr);
67 EXPECT_EQ(fn->name, "add");
68 ASSERT_EQ(fn->parameters.size(), 2u);
69 EXPECT_EQ(fn->parameters.access(0).name, "x");
70 EXPECT_EQ(fn->parameters.access(1).name, "y");
71
72 ASSERT_NE(fn->body, nullptr);
73 ASSERT_EQ(fn->body->statements.size(), 2u);
74
75 ASSERT_EQ(fn->body->statements.access(0)->kind, Compiler_Stmt_Kind::Let);
76 const auto * let_stmt =
77 static_cast<const Compiler_Let_Stmt *>(fn->body->statements.access(0));
78 EXPECT_EQ(let_stmt->name, "z");
79 ASSERT_NE(let_stmt->initializer, nullptr);
80 ASSERT_EQ(let_stmt->initializer->kind, Compiler_Expr_Kind::Call);
81 const auto * call_expr =
82 static_cast<const Compiler_Call_Expr *>(let_stmt->initializer);
83 ASSERT_EQ(call_expr->arguments.size(), 2u);
84
85 ASSERT_EQ(fn->body->statements.access(1)->kind, Compiler_Stmt_Kind::Return);
86 const auto * ret_stmt =
87 static_cast<const Compiler_Return_Stmt *>(fn->body->statements.access(1));
88 ASSERT_NE(ret_stmt->value, nullptr);
89 ASSERT_EQ(ret_stmt->value->kind, Compiler_Expr_Kind::Binary);
90 const auto * ret_expr =
91 static_cast<const Compiler_Binary_Expr *>(ret_stmt->value);
92 EXPECT_EQ(ret_expr->op, Compiler_Token_Kind::Plus);
93
94 const auto dump = compiler_dump_module(module);
95 EXPECT_NE(dump.find("Function(add)"), std::string::npos);
96 EXPECT_NE(dump.find("Call"), std::string::npos);
97 EXPECT_NE(dump.find("Binary(Plus)"), std::string::npos);
98}
99
100
102{
104 const auto id = sm.add_virtual_file(
105 "main.aw",
106 "let x = 3;\n"
107 "while x {\n"
108 " x = x - 1;\n"
109 "}\n");
110
112 Compiler_Ast_Context ctx(1 << 16);
113 Compiler_Parser parser(ctx, sm, id, &dx);
114
115 auto * module = parser.parse_module();
116
117 ASSERT_NE(module, nullptr);
118 ASSERT_EQ(module->functions.size(), 0u);
119 ASSERT_EQ(module->statements.size(), 2u);
121
122 ASSERT_EQ(module->statements.access(0)->kind, Compiler_Stmt_Kind::Let);
123 const auto * let_stmt =
124 static_cast<const Compiler_Let_Stmt *>(module->statements.access(0));
125 EXPECT_EQ(let_stmt->name, "x");
126
127 ASSERT_EQ(module->statements.access(1)->kind, Compiler_Stmt_Kind::While);
128 const auto * while_stmt =
129 static_cast<const Compiler_While_Stmt *>(module->statements.access(1));
130 ASSERT_NE(while_stmt->condition, nullptr);
131 EXPECT_EQ(while_stmt->condition->kind, Compiler_Expr_Kind::Identifier);
132 ASSERT_NE(while_stmt->body, nullptr);
133 ASSERT_EQ(while_stmt->body->kind, Compiler_Stmt_Kind::Block);
134}
135
136
138{
140 const auto id = sm.add_virtual_file(
141 "main.aw",
142 "fn id(x: T) -> T {\n"
143 " let alias: fn(T) -> T = id;\n"
144 " return alias(x);\n"
145 "}\n");
146
148 Compiler_Ast_Context ctx(1 << 15);
149 Compiler_Parser parser(ctx, sm, id, &dx);
150
151 auto * module = parser.parse_module();
152
153 ASSERT_NE(module, nullptr);
154 ASSERT_EQ(module->functions.size(), 1u);
156
157 const auto * fn = module->functions.access(0);
158 ASSERT_EQ(fn->parameters.size(), 1u);
159 ASSERT_NE(fn->parameters.access(0).annotation, nullptr);
160 EXPECT_EQ(fn->parameters.access(0).annotation->kind, Compiler_Type_Expr_Kind::Named);
161 ASSERT_NE(fn->return_annotation, nullptr);
162 EXPECT_EQ(fn->return_annotation->kind, Compiler_Type_Expr_Kind::Named);
163
164 ASSERT_NE(fn->body, nullptr);
165 ASSERT_EQ(fn->body->statements.size(), 2u);
166 const auto * let_stmt = static_cast<const Compiler_Let_Stmt *>(fn->body->statements.access(0));
167 ASSERT_NE(let_stmt->annotation, nullptr);
168 ASSERT_EQ(let_stmt->annotation->kind, Compiler_Type_Expr_Kind::Function);
169
170 const auto * fn_type = static_cast<const Compiler_Function_Type_Expr *>(let_stmt->annotation);
171 ASSERT_EQ(fn_type->parameters.size(), 1u);
172 ASSERT_NE(fn_type->result, nullptr);
173 EXPECT_EQ(fn_type->parameters.access(0)->kind, Compiler_Type_Expr_Kind::Named);
174 EXPECT_EQ(fn_type->result->kind, Compiler_Type_Expr_Kind::Named);
175
176 const auto dump = compiler_dump_function(fn);
177 EXPECT_NE(dump.find("Params: x: T"), std::string::npos);
178 EXPECT_NE(dump.find("Return: T"), std::string::npos);
179 EXPECT_NE(dump.find("Let(alias): fn(T) -> T"), std::string::npos);
180}
181
182
184{
186 const auto id = sm.add_virtual_file(
187 "types.aw",
188 "struct Point {\n"
189 " x: Int;\n"
190 " y: Int;\n"
191 "}\n"
192 "enum Color { Red, Green, Blue, }\n"
193 "type UserId = Int;\n");
194
196 Compiler_Ast_Context ctx(1 << 15);
197 Compiler_Parser parser(ctx, sm, id, &dx);
198
199 auto * module = parser.parse_module();
200
201 ASSERT_NE(module, nullptr);
202 ASSERT_EQ(module->type_declarations.size(), 3u);
204
205 const auto * point = static_cast<const Compiler_Struct_Decl *>(module->type_declarations.access(0));
206 ASSERT_EQ(point->kind, Compiler_Type_Decl_Kind::Struct);
207 ASSERT_EQ(point->fields.size(), 2u);
208 EXPECT_EQ(point->fields.access(0).name, "x");
209 EXPECT_EQ(point->fields.access(1).name, "y");
210
211 const auto * color = static_cast<const Compiler_Enum_Decl *>(module->type_declarations.access(1));
212 ASSERT_EQ(color->kind, Compiler_Type_Decl_Kind::Enum);
213 ASSERT_EQ(color->variants.size(), 3u);
214 EXPECT_EQ(color->variants.access(0).name, "Red");
215 EXPECT_EQ(color->variants.access(2).name, "Blue");
216
217 const auto * user_id
218 = static_cast<const Compiler_Type_Alias_Decl *>(module->type_declarations.access(2));
219 ASSERT_EQ(user_id->kind, Compiler_Type_Decl_Kind::Alias);
220 ASSERT_NE(user_id->aliased_type, nullptr);
221 EXPECT_EQ(user_id->aliased_type->kind, Compiler_Type_Expr_Kind::Named);
222
223 const auto dump = compiler_dump_module(module);
224 EXPECT_NE(dump.find("Struct(Point)"), std::string::npos);
225 EXPECT_NE(dump.find("Enum(Color)"), std::string::npos);
226 EXPECT_NE(dump.find("TypeAlias(UserId) = Int"), std::string::npos);
227}
228
229
231{
233 const auto id = sm.add_virtual_file(
234 "main.aw",
235 "import \"math.aw\";\n"
236 "import \"types.aw\";\n"
237 "fn use() { return value; }\n");
238
240 Compiler_Ast_Context ctx(1 << 15);
241 Compiler_Parser parser(ctx, sm, id, &dx);
242
243 auto * module = parser.parse_module();
244
245 ASSERT_NE(module, nullptr);
247 ASSERT_EQ(module->imports.size(), 2u);
248 EXPECT_EQ(module->source_name, "main.aw");
249 EXPECT_EQ(module->imports.access(0)->module_name, "math.aw");
250 EXPECT_EQ(module->imports.access(1)->module_name, "types.aw");
251
252 const auto dump = compiler_dump_module(module);
253 EXPECT_NE(dump.find("Import(\"math.aw\")"), std::string::npos);
254 EXPECT_NE(dump.find("Import(\"types.aw\")"), std::string::npos);
255 EXPECT_NE(dump.find("Function(use)"), std::string::npos);
256}
257
258
260{
262 const auto id = sm.add_virtual_file("main.aw", "let x = 1;\n");
263
265 Compiler_Ast_Context ctx(1 << 15);
268 Compiler_Parser parser(ctx, sm, id, &dx, opts);
269
270 auto * module = parser.parse_module();
271
272 ASSERT_NE(module, nullptr);
273 ASSERT_EQ(module->statements.size(), 1u);
275 ASSERT_GE(dx.size(), 1u);
276 EXPECT_EQ(dx.get(0).code, "PAR004");
277}
278
279
281{
283 const auto id = sm.add_virtual_file("main.aw", "let x = ;\n");
284
286 Compiler_Ast_Context ctx(1 << 15);
287 Compiler_Parser parser(ctx, sm, id, &dx);
288
289 auto * module = parser.parse_module();
290
291 ASSERT_NE(module, nullptr);
292 ASSERT_EQ(module->statements.size(), 1u);
294 ASSERT_GE(dx.size(), 1u);
295
296 ASSERT_EQ(module->statements.access(0)->kind, Compiler_Stmt_Kind::Let);
297 const auto * let_stmt =
298 static_cast<const Compiler_Let_Stmt *>(module->statements.access(0));
299 ASSERT_NE(let_stmt->initializer, nullptr);
300 EXPECT_EQ(let_stmt->initializer->kind, Compiler_Expr_Kind::Invalid);
301}
302
303
305{
307 const auto id = sm.add_virtual_file("empty.aw", "");
308
310 Compiler_Ast_Context ctx(1 << 15);
311 Compiler_Parser parser(ctx, sm, id, &dx);
312
313 auto * module = parser.parse_module();
314
315 ASSERT_NE(module, nullptr);
316 EXPECT_EQ(module->functions.size(), 0u);
317 EXPECT_EQ(module->statements.size(), 0u);
319}
Recursive-descent parser for the compiler-support MVP grammar.
Arena-backed ownership context for AST nodes.
Recursive-descent parser that produces an AST in Compiler_Ast_Context.
Diagnostic accumulator and renderer.
bool has_errors() const noexcept
Returns whether any error or fatal diagnostic was emitted.
const Diagnostic & get(const size_t i) const
Returns diagnostic i.
size_t size() const noexcept
Returns the number of stored diagnostics.
Stores source files and resolves offsets into human-readable data.
Definition ah-source.H:184
Source_File_Id add_virtual_file(const std::string &name, const std::string &text)
Registers an in-memory source file.
Definition ah-source.H:258
#define TEST(name)
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
std::string compiler_dump_module(const Compiler_Module *module)
Dumps a parsed module in a deterministic text format.
std::string compiler_dump_function(const Compiler_Function_Decl *fn)
Dumps a function declaration in a deterministic text format.
static long & color(typename GT::Node *p)
Node representing an infix binary operation.
Node representing a function or method call.
Nominal top-level enum declaration with unit variants.
Function type syntax such as fn(Int, T) -> Bool.
Node representing a local variable binding.
Parser configuration knobs for the MVP grammar.
bool allow_top_level_statements
If false, only top-level declarations are accepted.
Node representing a return from the current function.
Nominal top-level struct declaration.
Transparent top-level type alias declaration.
Node representing a while-loop.
std::string code
Optional stable code such as E001.