Skip to content

Commit b9fcb13

Browse files
committed
Code refactoring #5: operator overloading support
Refactor code to support operator overloading and integrate internal data types with user code - Implement support for operator overloading, allowing greater flexibility in handling custom objects and types. - Integrate interpreter's internal data types with user-defined code, ensuring better interoperability and consistency. - Improve code structure to facilitate future expansions and maintenance.
1 parent b2cf27e commit b9fcb13

38 files changed

+2263
-1011
lines changed

.gitignore

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Prerequisites
2+
*.d
3+
4+
# Compiled Object files
5+
*.slo
6+
*.lo
7+
*.o
8+
*.obj
9+
10+
# Precompiled Headers
11+
*.gch
12+
*.pch
13+
14+
# Compiled Dynamic libraries
15+
*.so
16+
*.dylib
17+
*.dll
18+
19+
# Fortran module files
20+
*.mod
21+
*.smod
22+
23+
# Compiled Static libraries
24+
*.lai
25+
*.la
26+
*.a
27+
*.lib
28+
29+
# Executables
30+
*.exe
31+
*.out
32+
*.app
33+
34+
t2.py

.vscode/settings.json

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{
2+
"files.associations": {
3+
"array": "cpp",
4+
"atomic": "cpp",
5+
"bit": "cpp",
6+
"*.tcc": "cpp",
7+
"cctype": "cpp",
8+
"clocale": "cpp",
9+
"cmath": "cpp",
10+
"compare": "cpp",
11+
"concepts": "cpp",
12+
"cstddef": "cpp",
13+
"cstdint": "cpp",
14+
"cstdio": "cpp",
15+
"cstdlib": "cpp",
16+
"cwchar": "cpp",
17+
"cwctype": "cpp",
18+
"deque": "cpp",
19+
"string": "cpp",
20+
"unordered_map": "cpp",
21+
"vector": "cpp",
22+
"exception": "cpp",
23+
"algorithm": "cpp",
24+
"functional": "cpp",
25+
"iterator": "cpp",
26+
"memory": "cpp",
27+
"memory_resource": "cpp",
28+
"numeric": "cpp",
29+
"optional": "cpp",
30+
"random": "cpp",
31+
"string_view": "cpp",
32+
"system_error": "cpp",
33+
"tuple": "cpp",
34+
"type_traits": "cpp",
35+
"utility": "cpp",
36+
"fstream": "cpp",
37+
"initializer_list": "cpp",
38+
"iosfwd": "cpp",
39+
"iostream": "cpp",
40+
"istream": "cpp",
41+
"limits": "cpp",
42+
"new": "cpp",
43+
"numbers": "cpp",
44+
"ostream": "cpp",
45+
"stdexcept": "cpp",
46+
"streambuf": "cpp",
47+
"typeinfo": "cpp",
48+
"sstream": "cpp"
49+
},
50+
"C_Cpp.errorSquiggles": "disabled"
51+
}

Makefile

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
# Get a list of all .cpp files in the root directory and its subdirectories
2-
SRCS := $(shell find . -name "*.cpp")
3-
4-
# Set the output file name
5-
OUTPUT := main
1+
# Detect OS
2+
ifeq ($(OS),Windows_NT)
3+
# Windows settings
4+
SRCS := $(shell powershell -Command "Get-ChildItem -Recurse -Filter *.cpp | Select-Object -ExpandProperty FullName" | tr '\r\n' ' ')
5+
OUTPUT := main.exe
6+
else
7+
# Unix-like settings (Linux, macOS, etc.)
8+
SRCS := $(shell find . -name "*.cpp")
9+
OUTPUT := main
10+
endif
611

712
# Set the compiler and compiler flags
813
CC := g++
9-
CFLAGS := -std=c++17
14+
CFLAGS := -std=c++20
1015

1116
# Add DEBUG macro to CFLAGS
1217
ifdef DEBUG
@@ -18,14 +23,21 @@ endif
1823
build: $(OUTPUT)
1924

2025
# Linking rule
21-
$(OUTPUT): $(SRCS)
26+
$(OUTPUT):
2227
$(CC) $(CFLAGS) $(SRCS) -o $(OUTPUT)
2328

29+
# Test rule with optional TEST variable
30+
# Usage: make test TEST=<test_name>
2431
test:
2532
chmod +x test.sh
26-
./test.sh
33+
./test.sh $(TEST)
2734

2835
# Clean rule
2936
clean:
37+
ifeq ($(OS),Windows_NT)
38+
@powershell -Command "Remove-Item -Force -ErrorAction SilentlyContinue $(OUTPUT)"
39+
else
3040
@rm -f $(OUTPUT)
41+
endif
42+
3143

src/bin/main.cpp

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,38 +9,37 @@
99
#pragma GCC optimize("Ofast")
1010
#pragma GCC target("avx,avx2,fma")
1111

12-
using namespace std;
13-
14-
inline void show_tokens(const vector<Token>& tokens) {
12+
#ifdef DEBUG
13+
inline void show_tokens(const std::vector<Token>& tokens) {
1514
for (const auto& token : tokens) {
16-
cout << token << '\n';
15+
std::cout << token << '\n';
1716
}
18-
cout << flush;
17+
std::cout << std::flush;
1918
}
19+
#endif
2020

2121
int main(int argc, char* argv[]) {
22-
ios_base::sync_with_stdio(false);
23-
cin.tie(nullptr);
24-
cout.tie(nullptr);
22+
std::ios_base::sync_with_stdio(false);
23+
std::cin.tie(nullptr); std::cout.tie(nullptr);
2524

2625
if (argc != 2) {
27-
cerr << "Usage: " << argv[0] << " [filename].py\n";
26+
std::cerr << "Usage: " << argv[0] << " [filename].py\n";
2827
return 1;
2928
}
3029

3130
const char* const filename = argv[1];
32-
ifstream inputFile(filename);
31+
std::ifstream inputFile(filename);
3332

3433
if (!inputFile) {
35-
cerr << "Error: could not open file '" << filename << "'\n";
34+
std::cerr << "Error: could not open file '" << filename << "'\n";
3635
return 1;
3736
}
3837

39-
string source((istreambuf_iterator<char>(inputFile)), {});
38+
std::string source((std::istreambuf_iterator<char>(inputFile)), {});
4039

4140
try {
4241
Lexer lexer(source);
43-
vector<Token> tokens = lexer.scanTokens();
42+
std::vector<Token> tokens = lexer.scanTokens();
4443

4544
#ifdef DEBUG
4645
/* To define DEBUG, use `make DEBUG=1` when compiling */
@@ -53,8 +52,8 @@ int main(int argc, char* argv[]) {
5352
Interpreter interpreter;
5453
interpreter.interpret(root);
5554

56-
} catch (const runtime_error& err) {
57-
cerr << err.what() << '\n';
55+
} catch (const std::runtime_error& err) {
56+
std::cerr << err.what() << '\n';
5857
return EXIT_FAILURE;
5958
}
6059

src/libs/ast/ast.cpp

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,190 @@
1+
#include <iostream>
12
#include "ast.hpp"
23

4+
ProgramNode* AstNode::unwrap_program_node() {
5+
if (type == AstNodeType::Program) {
6+
return dynamic_cast<ProgramNode*>(this);
7+
} else {
8+
throw std::runtime_error("Failed to unwrap AstNode.");
9+
}
10+
}
11+
12+
BlockNode* AstNode::unwrap_block_node() {
13+
if (type == AstNodeType::Block) {
14+
return dynamic_cast<BlockNode*>(this);
15+
} else {
16+
throw std::runtime_error("Failed to unwrap AstNode.");
17+
}
18+
}
19+
20+
TernaryOpNode* AstNode::unwrap_ternary_op_node() {
21+
if (type == AstNodeType::TernaryOp) {
22+
return dynamic_cast<TernaryOpNode*>(this);
23+
} else {
24+
throw std::runtime_error("Failed to unwrap AstNode.");
25+
}
26+
}
27+
28+
BinaryOpNode* AstNode::unwrap_binary_op_node() {
29+
if (type == AstNodeType::BinaryOp) {
30+
return dynamic_cast<BinaryOpNode*>(this);
31+
} else {
32+
throw std::runtime_error("Failed to unwrap AstNode.");
33+
}
34+
}
35+
36+
UnaryOpNode* AstNode::unwrap_unary_op_node() {
37+
if (type == AstNodeType::UnaryOp) {
38+
return dynamic_cast<UnaryOpNode*>(this);
39+
} else {
40+
throw std::runtime_error("Failed to unwrap AstNode.");
41+
}
42+
}
43+
44+
AssignNode* AstNode::unwrap_assign_node() {
45+
if (type == AstNodeType::Assign) {
46+
return dynamic_cast<AssignNode*>(this);
47+
} else {
48+
throw std::runtime_error("Failed to unwrap AstNode.");
49+
}
50+
}
51+
52+
IntNode* AstNode::unwrap_int_node() {
53+
if (type == AstNodeType::Int) {
54+
return dynamic_cast<IntNode*>(this);
55+
} else {
56+
throw std::runtime_error("Failed to unwrap AstNode.");
57+
}
58+
}
59+
60+
BooleanNode* AstNode::unwrap_bool_node() {
61+
if (type == AstNodeType::Boolean) {
62+
return dynamic_cast<BooleanNode*>(this);
63+
} else {
64+
throw std::runtime_error("Failed to unwrap AstNode.");
65+
}
66+
}
67+
68+
FloatNode* AstNode::unwrap_float_node() {
69+
if (type == AstNodeType::Float) {
70+
return dynamic_cast<FloatNode*>(this);
71+
} else {
72+
throw std::runtime_error("Failed to unwrap AstNode.");
73+
}
74+
}
75+
76+
StringNode* AstNode::unwrap_string_node() {
77+
if (type == AstNodeType::String) {
78+
return dynamic_cast<StringNode*>(this);
79+
} else {
80+
throw std::runtime_error("Failed to unwrap AstNode.");
81+
}
82+
}
83+
84+
NullNode* AstNode::unwrap_null_node() {
85+
if (type == AstNodeType::Null) {
86+
return dynamic_cast<NullNode*>(this);
87+
} else {
88+
throw std::runtime_error("Failed to unwrap AstNode.");
89+
}
90+
}
91+
92+
NameNode* AstNode::unwrap_name_node() {
93+
if (type == AstNodeType::Name) {
94+
return dynamic_cast<NameNode*>(this);
95+
} else {
96+
throw std::runtime_error("Failed to unwrap AstNode.");
97+
}
98+
}
99+
100+
IfNode* AstNode::unwrap_cond_node() {
101+
if (type == AstNodeType::If) {
102+
return dynamic_cast<IfNode*>(this);
103+
} else {
104+
throw std::runtime_error("Failed to unwrap AstNode.");
105+
}
106+
}
107+
108+
WhileNode* AstNode::unwrap_rep_node() {
109+
if (type == AstNodeType::While) {
110+
return dynamic_cast<WhileNode*>(this);
111+
} else {
112+
throw std::runtime_error("Failed to unwrap AstNode.");
113+
}
114+
}
115+
116+
BreakNode* AstNode::unwrap_break_node() {
117+
if (type == AstNodeType::Break) {
118+
return dynamic_cast<BreakNode*>(this);
119+
} else {
120+
throw std::runtime_error("Failed to unwrap AstNode.");
121+
}
122+
}
123+
124+
ContinueNode* AstNode::unwrap_continue_node() {
125+
if (type == AstNodeType::Continue) {
126+
return dynamic_cast<ContinueNode*>(this);
127+
} else {
128+
throw std::runtime_error("Failed to unwrap AstNode.");
129+
}
130+
}
131+
132+
PassNode* AstNode::unwrap_pass_node() {
133+
if (type == AstNodeType::Pass) {
134+
return dynamic_cast<PassNode*>(this);
135+
} else {
136+
throw std::runtime_error("Failed to unwrap AstNode.");
137+
}
138+
}
139+
140+
CallNode* AstNode::unwrap_call_node() {
141+
if (type == AstNodeType::Call) {
142+
return dynamic_cast<CallNode*>(this);
143+
} else {
144+
throw std::runtime_error("Failed to unwrap AstNode.");
145+
}
146+
}
147+
148+
FunctionNode* AstNode::unwrap_function_node() {
149+
if (type == AstNodeType::Function) {
150+
return dynamic_cast<FunctionNode*>(this);
151+
} else {
152+
throw std::runtime_error("Failed to unwrap AstNode.");
153+
}
154+
}
155+
156+
ReturnNode* AstNode::unwrap_ret_node() {
157+
if (type == AstNodeType::Return) {
158+
return dynamic_cast<ReturnNode*>(this);
159+
} else {
160+
throw std::runtime_error("Failed to unwrap AstNode.");
161+
}
162+
}
163+
164+
ClassNode* AstNode::unwrap_class_node() {
165+
if (type == AstNodeType::Class) {
166+
return dynamic_cast<ClassNode*>(this);
167+
} else {
168+
throw std::runtime_error("Failed to unwrap AstNode.");
169+
}
170+
}
171+
172+
PropertyNode* AstNode::unwrap_property_node() {
173+
if (type == AstNodeType::AttrRef) {
174+
return dynamic_cast<PropertyNode*>(this);
175+
} else {
176+
throw std::runtime_error("Failed to unwrap AstNode.");
177+
}
178+
}
179+
180+
PrintNode* AstNode::unwrap_print_node() {
181+
if (type == AstNodeType::Print) {
182+
return dynamic_cast<PrintNode*>(this);
183+
} else {
184+
throw std::runtime_error("Failed to unwrap AstNode.");
185+
}
186+
}
187+
3188
PyObject* AssignNode::accept(NodeVisitor* visitor) {
4189
#ifdef DEBUG
5190
std::cout << "visiting " << "AssignNode" << "\n";

0 commit comments

Comments
 (0)