From 4ae6c9790430287cdb28b9ce6448a718d08fb562 Mon Sep 17 00:00:00 2001 From: bronku Date: Mon, 1 Dec 2025 11:39:43 +0100 Subject: [PATCH] basic tests --- makefile | 10 ++-- src/codegen.hpp | 125 +++++++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 5 ++ test/ruby/01.out | 2 +- test/ruby/02.out | 2 +- test/ruby/03.out | 2 +- test/ruby/04.out | 2 +- test/ruby/05.out | 2 +- test/ruby/06.out | 2 +- test/ruby/07.out | 2 +- test/ruby/08.out | 2 +- test/ruby/09.out | 2 +- test/ruby/10.out | 2 +- test/ruby/11.out | 2 +- test/ruby/12.out | 2 +- test/ruby/13.out | 2 +- test/ruby/14.out | 2 +- test/ruby/15.out | 2 +- test/ruby/16.out | 1 + test/ruby/17.out | 2 +- test/ruby/18.out | 2 +- test/ruby/19.out | 2 +- test/ruby/20.out | 2 +- test/ruby/21.out | 2 +- test/ruby/22.out | 2 +- 25 files changed, 158 insertions(+), 25 deletions(-) create mode 100644 src/codegen.hpp diff --git a/makefile b/makefile index 6ed9765..aeb4ac4 100644 --- a/makefile +++ b/makefile @@ -5,7 +5,7 @@ FLEX = flex TARGET = build/py2rb -$(TARGET): build/parser.o build/lexer.o build/main.o +$(TARGET): build/parser.o build/lexer.o build/main.o $(CXX) $^ -o $@ build/parser.cpp build/parser.hpp: src/parser.y | build @@ -17,11 +17,13 @@ build/lexer.cpp build/lexer.hpp: src/lexer.l build/parser.hpp src/scanner.hpp sr build/%.o: build/%.cpp $(CXX) -c $(ARGS) $< -o $@ -build/%.o: src/%.cpp | build - $(CXX) -c $(ARGS) $< -o $@ +build/main.o: src/main.cpp build src/codegen.hpp + $(CXX) -c $(ARGS) src/main.cpp -o build/main.o src/ast.hpp: src/ast/base.hpp src/ast/expressions.hpp src/ast/literals.hpp src/ast/operators.hpp src/ast/statements.hpp src/ast/string_utils.hpp +src/codegen.hpp : src/ast.hpp + build: mkdir -p build @@ -34,4 +36,4 @@ run: $(TARGET) test: $(TARGET) test/tester.sh -.PHONY: clean run test +.PHONY: clean run test diff --git a/src/codegen.hpp b/src/codegen.hpp new file mode 100644 index 0000000..8ca1dce --- /dev/null +++ b/src/codegen.hpp @@ -0,0 +1,125 @@ +#pragma once +#include "ast.hpp" +#include + +class RubyGenerator +{ + std::ostringstream output; + int indent_level = 0; + + void write_indent() + { + for (int i = 0; i < indent_level; i++) + { + output << " "; + } + } + + void write(const std::string &s) + { + output << s; + } + +public: + std::string generate(const Module &module) + { + output.str(""); + indent_level = 0; + + for (const auto &stmt : module.body) + { + generate_stmt(*stmt); + } + + return output.str(); + } + +private: + void generate_stmt(const Stmt &stmt) + { + if (auto *expr_stmt = dynamic_cast(&stmt)) + { + write_indent(); + generate_expr(*expr_stmt->expr); + write("\n"); + } + else if (auto *assign = dynamic_cast(&stmt)) + { + write_indent(); + generate_expr(*assign->target); + write(" = "); + generate_expr(*assign->value); + write("\n"); + } + else if (auto *if_stmt = dynamic_cast(&stmt)) + { + write_indent(); + write("if "); + generate_expr(*if_stmt->condition); + write("\n"); + + indent_level++; + for (const auto &s : if_stmt->then_body) + { + generate_stmt(*s); + } + indent_level--; + + if (!if_stmt->else_body.empty()) + { + write("else\n"); + indent_level++; + for (const auto &s : if_stmt->else_body) + { + generate_stmt(*s); + } + indent_level--; + } + + write("end\n"); + } + else if (auto *ret = dynamic_cast(&stmt)) + { + write_indent(); + write("return "); + if (ret->value) + { + generate_expr(*ret->value); + } + write("\n"); + } + } + void generate_expr(const Expr &expr) + { + if (auto *num = dynamic_cast(&expr)) + { + write(num->value); + } + else if (auto *id = dynamic_cast(&expr)) + { + write(id->name); + } + else if (auto *str = dynamic_cast(&expr)) + { + write("\"" + str->value + "\""); + } + else if (auto *binop = dynamic_cast(&expr)) + { + generate_expr(*binop->left); + write(" " + binop->op.symbol() + " "); + generate_expr(*binop->right); + } + else if (auto *call = dynamic_cast(&expr)) + { + generate_expr(*call->func); + write("("); + for (size_t i = 0; i < call->args.size(); i++) + { + if (i > 0) + write(", "); + generate_expr(*call->args[i]); + } + write(")"); + } + } +}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 1b47df6..0b18ad5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ #include "parser.hpp" #include "scanner.hpp" #include "ast.hpp" +#include "codegen.hpp" #include #include @@ -71,5 +72,9 @@ int main(int argc, char *argv[]) if (ast_dump) { std::cout << ast_root->dump(); + return 0; } + + RubyGenerator generator; + std::cout << generator.generate(*ast_root); } \ No newline at end of file diff --git a/test/ruby/01.out b/test/ruby/01.out index f70d7bb..d81cc07 100644 --- a/test/ruby/01.out +++ b/test/ruby/01.out @@ -1 +1 @@ -42 \ No newline at end of file +42 diff --git a/test/ruby/02.out b/test/ruby/02.out index c1b0730..587be6b 100644 --- a/test/ruby/02.out +++ b/test/ruby/02.out @@ -1 +1 @@ -x \ No newline at end of file +x diff --git a/test/ruby/03.out b/test/ruby/03.out index f428463..fed79d0 100644 --- a/test/ruby/03.out +++ b/test/ruby/03.out @@ -1 +1 @@ -x = 5 \ No newline at end of file +x = 5 diff --git a/test/ruby/04.out b/test/ruby/04.out index ab64bde..5b5a327 100644 --- a/test/ruby/04.out +++ b/test/ruby/04.out @@ -1 +1 @@ -2 + 3 \ No newline at end of file +2 + 3 diff --git a/test/ruby/05.out b/test/ruby/05.out index 5b3f477..34c0f94 100644 --- a/test/ruby/05.out +++ b/test/ruby/05.out @@ -1 +1 @@ -x = 2 + 3 \ No newline at end of file +x = 2 + 3 diff --git a/test/ruby/06.out b/test/ruby/06.out index 3a2decf..c3c70f9 100644 --- a/test/ruby/06.out +++ b/test/ruby/06.out @@ -1,2 +1,2 @@ x = 5 -y = 10 \ No newline at end of file +y = 10 diff --git a/test/ruby/07.out b/test/ruby/07.out index a57d168..eb28ef4 100644 --- a/test/ruby/07.out +++ b/test/ruby/07.out @@ -1 +1 @@ -foo() \ No newline at end of file +foo() diff --git a/test/ruby/08.out b/test/ruby/08.out index e1dca18..99ceb54 100644 --- a/test/ruby/08.out +++ b/test/ruby/08.out @@ -1 +1 @@ -print(x, y) \ No newline at end of file +print(x, y) diff --git a/test/ruby/09.out b/test/ruby/09.out index 79029c2..de090e3 100644 --- a/test/ruby/09.out +++ b/test/ruby/09.out @@ -1,3 +1,3 @@ if x y = 5 -end \ No newline at end of file +end diff --git a/test/ruby/10.out b/test/ruby/10.out index a0bd09b..0884948 100644 --- a/test/ruby/10.out +++ b/test/ruby/10.out @@ -2,4 +2,4 @@ if x y = 5 else y = 10 -end \ No newline at end of file +end diff --git a/test/ruby/11.out b/test/ruby/11.out index 7c036de..616a975 100644 --- a/test/ruby/11.out +++ b/test/ruby/11.out @@ -1,3 +1,3 @@ for i in items print(i) -end \ No newline at end of file +end diff --git a/test/ruby/12.out b/test/ruby/12.out index 51cac14..8ac3f12 100644 --- a/test/ruby/12.out +++ b/test/ruby/12.out @@ -1,3 +1,3 @@ while x x = x - 1 -end \ No newline at end of file +end diff --git a/test/ruby/13.out b/test/ruby/13.out index 07e600c..8222475 100644 --- a/test/ruby/13.out +++ b/test/ruby/13.out @@ -1,3 +1,3 @@ def add(a, b) return a + b -end \ No newline at end of file +end diff --git a/test/ruby/14.out b/test/ruby/14.out index a592792..4f71a8d 100644 --- a/test/ruby/14.out +++ b/test/ruby/14.out @@ -2,4 +2,4 @@ if x if y z = 1 end -end \ No newline at end of file +end diff --git a/test/ruby/15.out b/test/ruby/15.out index 6001c44..b5d8bb5 100644 --- a/test/ruby/15.out +++ b/test/ruby/15.out @@ -1 +1 @@ -[1, 2, 3] \ No newline at end of file +[1, 2, 3] diff --git a/test/ruby/16.out b/test/ruby/16.out index e69de29..3196588 100644 --- a/test/ruby/16.out +++ b/test/ruby/16.out @@ -0,0 +1 @@ +obj.method() diff --git a/test/ruby/17.out b/test/ruby/17.out index 101aa8f..291da53 100644 --- a/test/ruby/17.out +++ b/test/ruby/17.out @@ -1 +1 @@ -lst[0] \ No newline at end of file +lst[0] diff --git a/test/ruby/18.out b/test/ruby/18.out index 84ed78b..3580093 100644 --- a/test/ruby/18.out +++ b/test/ruby/18.out @@ -1 +1 @@ -"hello" \ No newline at end of file +"hello" diff --git a/test/ruby/19.out b/test/ruby/19.out index 52f1476..4311933 100644 --- a/test/ruby/19.out +++ b/test/ruby/19.out @@ -1 +1 @@ -x and y \ No newline at end of file +x and y diff --git a/test/ruby/20.out b/test/ruby/20.out index 87a70fe..d51bd22 100644 --- a/test/ruby/20.out +++ b/test/ruby/20.out @@ -1 +1 @@ -not x \ No newline at end of file +not x diff --git a/test/ruby/21.out b/test/ruby/21.out index 8e1abc0..461badd 100644 --- a/test/ruby/21.out +++ b/test/ruby/21.out @@ -3,4 +3,4 @@ class Point @x = x @y = y end -end \ No newline at end of file +end diff --git a/test/ruby/22.out b/test/ruby/22.out index 84e5a2e..3bee33a 100644 --- a/test/ruby/22.out +++ b/test/ruby/22.out @@ -2,4 +2,4 @@ class Counter def increment @count = @count + 1 end -end \ No newline at end of file +end