Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
compiler_sema_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# include <Compiler_Sema.H>
41
42# include <string>
43# include <vector>
44
45using namespace Aleph;
46
47
48namespace
49{
50 std::vector<std::string>
52 {
53 std::vector<std::string> codes;
54 for (size_t i = 0; i < dx.size(); ++i)
55 codes.push_back(dx.get(i).code);
56 return codes;
57 }
58
59 bool
60 contains_code(const std::vector<std::string> & codes,
61 const std::string & code)
62 {
63 for (const auto & item : codes)
64 if (item == code)
66 return false;
67 }
68}
69
70
72{
74 const auto id = sm.add_virtual_file(
75 "main.aw",
76 "fn add(x, y) {\n"
77 " let z = x + y;\n"
78 " return z;\n"
79 "}\n"
80 "let value = add(1, 2);\n");
81
83 Compiler_Ast_Context ctx(1 << 16);
84 Compiler_Parser parser(ctx, sm, id, &dx);
85 const auto * module = parser.parse_module();
87
89 sema.analyze_module(module);
90
92 EXPECT_EQ(sema.symbol_count(), 5u);
93 EXPECT_EQ(sema.resolution_count(), 4u);
94
95 const auto * fn = module->functions.access(0);
96 const auto * let_stmt =
97 static_cast<const Compiler_Let_Stmt *>(fn->body->statements.access(0));
98 const auto * sum =
99 static_cast<const Compiler_Binary_Expr *>(let_stmt->initializer);
100 const auto * x_ref =
101 static_cast<const Compiler_Identifier_Expr *>(sum->left);
102 const auto * y_ref =
103 static_cast<const Compiler_Identifier_Expr *>(sum->right);
104 const auto * ret_stmt =
105 static_cast<const Compiler_Return_Stmt *>(fn->body->statements.access(1));
106 const auto * z_ref =
107 static_cast<const Compiler_Identifier_Expr *>(ret_stmt->value);
108 const auto * top_let =
109 static_cast<const Compiler_Let_Stmt *>(module->statements.access(0));
110 const auto * call =
111 static_cast<const Compiler_Call_Expr *>(top_let->initializer);
112 const auto * add_ref =
113 static_cast<const Compiler_Identifier_Expr *>(call->callee);
114
115 ASSERT_NE(sema.resolved_symbol(x_ref), nullptr);
116 EXPECT_EQ(sema.resolved_symbol(x_ref)->kind, Compiler_Symbol_Kind::Parameter);
117 EXPECT_EQ(sema.resolved_symbol(x_ref)->name, "x");
118
119 ASSERT_NE(sema.resolved_symbol(y_ref), nullptr);
120 EXPECT_EQ(sema.resolved_symbol(y_ref)->kind, Compiler_Symbol_Kind::Parameter);
121 EXPECT_EQ(sema.resolved_symbol(y_ref)->name, "y");
122
123 ASSERT_NE(sema.resolved_symbol(z_ref), nullptr);
124 EXPECT_EQ(sema.resolved_symbol(z_ref)->kind, Compiler_Symbol_Kind::Local);
125 EXPECT_EQ(sema.resolved_symbol(z_ref)->name, "z");
126
127 ASSERT_NE(sema.resolved_symbol(add_ref), nullptr);
128 EXPECT_EQ(sema.resolved_symbol(add_ref)->kind, Compiler_Symbol_Kind::Function);
129 EXPECT_EQ(sema.resolved_symbol(add_ref)->name, "add");
130}
131
132
134{
136 const auto id = sm.add_virtual_file(
137 "main.aw",
138 "fn dup(x, x) { let y = 1; let y = 2; }\n"
139 "fn dup() {}\n"
140 "fn shadow(a) { { let a = 1; } }\n");
141
143 Compiler_Ast_Context ctx(1 << 16);
144 Compiler_Parser parser(ctx, sm, id, &dx);
145 const auto * module = parser.parse_module();
147
149 opts.allow_shadowing = false;
151 sema.analyze_module(module);
152
154 const auto codes = collect_codes(dx);
155 EXPECT_TRUE(contains_code(codes, "SEM001"));
156 EXPECT_TRUE(contains_code(codes, "SEM007"));
157}
158
159
161{
163 const auto id = sm.add_virtual_file(
164 "main.aw",
165 "struct Point { x: Int; }\n"
166 "enum Point { Origin }\n");
167
169 Compiler_Ast_Context ctx(1 << 16);
170 Compiler_Parser parser(ctx, sm, id, &dx);
171 const auto * module = parser.parse_module();
173
175 sema.analyze_module(module);
176
178 const auto codes = collect_codes(dx);
179 EXPECT_TRUE(contains_code(codes, "SEM008"));
180}
181
182
184{
186 const auto id = sm.add_virtual_file(
187 "main.aw",
188 "import \"dep.aw\";\n"
189 "import \"dep.aw\";\n"
190 "import \"main.aw\";\n");
191
193 Compiler_Ast_Context ctx(1 << 16);
194 Compiler_Parser parser(ctx, sm, id, &dx);
195 const auto * module = parser.parse_module();
197
199 sema.analyze_module(module);
200
202 const auto codes = collect_codes(dx);
203 EXPECT_TRUE(contains_code(codes, "SEM009"));
204 EXPECT_TRUE(contains_code(codes, "SEM010"));
205}
206
207
209{
211 const auto id = sm.add_virtual_file(
212 "main.aw",
213 "return missing;\n"
214 "break;\n"
215 "continue;\n"
216 "let x = 1;\n"
217 "x();\n");
218
220 Compiler_Ast_Context ctx(1 << 16);
221 Compiler_Parser parser(ctx, sm, id, &dx);
222 const auto * module = parser.parse_module();
224
226 sema.analyze_module(module);
227
229 const auto codes = collect_codes(dx);
230 EXPECT_TRUE(contains_code(codes, "SEM002"));
231 EXPECT_TRUE(contains_code(codes, "SEM003"));
232 EXPECT_TRUE(contains_code(codes, "SEM004"));
233 EXPECT_TRUE(contains_code(codes, "SEM006"));
234}
Recursive-descent parser for the compiler-support MVP grammar.
Name-resolution and basic semantic checks for the compiler-support MVP.
Arena-backed ownership context for AST nodes.
Recursive-descent parser that produces an AST in Compiler_Ast_Context.
Name-resolution and basic semantic checker for the MVP AST.
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 code(Node *root)
Compute a string with the Lukasiewicz`s word of a tree.
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
Node representing an infix binary operation.
Node representing a function or method call.
Node representing a named identifier reference.
Node representing a local variable binding.
Node representing a return from the current function.
Options controlling semantic analyzer behavior.
bool allow_shadowing
If false, nested redefinitions report SEM007.
std::string code
Optional stable code such as E001.