From 28483812eac6bf2097a34e8daa7bd8a6f133feaf Mon Sep 17 00:00:00 2001 From: Sofia Date: Mon, 13 Apr 2026 21:45:58 +0300 Subject: [PATCH] Allow implicit cast from char to int --- src/casting.cpp | 13 ++++++++++--- src/typechecker.cpp | 6 +++++- src/types.cpp | 21 +++++++++++++++++++++ src/types.h | 4 ++++ test.c | 2 +- 5 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/casting.cpp b/src/casting.cpp index dc27e14..09596d1 100644 --- a/src/casting.cpp +++ b/src/casting.cpp @@ -1,5 +1,6 @@ #include "casting.h" +#include namespace types { std::vector create_casts() { @@ -21,15 +22,21 @@ namespace types { [](codegen::Builder&, std::shared_ptr, llvm::Value* value) { return value; } }); + continue; } - else if (target_ty->is_signed()) { - casts.push_back(CastDefinition{ source_ty, target_ty, false, + + bool allow_implicit = false; + if (target_ty->size() >= source_ty->size()) + allow_implicit = true; + + if (target_ty->is_signed()) { + casts.push_back(CastDefinition{ source_ty, target_ty, allow_implicit, [](codegen::Builder& builder, std::shared_ptr target, llvm::Value* value) { return builder.builder->CreateSExtOrTrunc(value, target->codegen(builder), "cast"); } }); } else { - casts.push_back(CastDefinition{ source_ty, target_ty, false, + casts.push_back(CastDefinition{ source_ty, target_ty, allow_implicit, [](codegen::Builder& builder, std::shared_ptr target, llvm::Value* value) { return builder.builder->CreateZExtOrTrunc(value, target->codegen(builder), "cast"); } }); diff --git a/src/typechecker.cpp b/src/typechecker.cpp index 90849d0..48163c9 100644 --- a/src/typechecker.cpp +++ b/src/typechecker.cpp @@ -15,9 +15,13 @@ namespace { std::shared_ptr result; }; - Result check_type(typecheck::State& state, std::shared_ptr checked, std::shared_ptr target) { + Result check_type( + typecheck::State& state, + std::shared_ptr checked, + std::shared_ptr target) { auto potential_cast = types::find_cast(state.casts, checked, target); + if (types::types_equal(checked, target)) { return TypecheckRes{ TypecheckResKind::Ok, target }; } diff --git a/src/types.cpp b/src/types.cpp index dde30a8..adc95dd 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -140,6 +140,19 @@ namespace types { } } + uint32_t FundamentalType::size() { + switch (this->m_ty) { + case FundamentalTypeKind::Int: + return 32; + case FundamentalTypeKind::Bool: + return 1; + case FundamentalTypeKind::Char: + return 8; + default: + throw std::runtime_error("Invalid type"); + } + } + std::string FunctionType::formatted() { std::stringstream out{ "" }; out << "("; @@ -170,6 +183,10 @@ namespace types { return std::pair(ptr, self); } + uint32_t FunctionType::size() { + return 64; + } + std::string PointerType::formatted() { std::stringstream out{ "" }; out << this->m_inner->formatted() << "*"; @@ -183,6 +200,10 @@ namespace types { ); } + uint32_t PointerType::size() { + return 64; + } + bool types_equal(std::shared_ptr type1, std::shared_ptr type2) { if (type1->m_kind != type2->m_kind) return false; diff --git a/src/types.h b/src/types.h index 0b5bd72..9d012ef 100644 --- a/src/types.h +++ b/src/types.h @@ -34,6 +34,7 @@ namespace types { virtual llvm::Value* lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs); virtual llvm::Value* gt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs); virtual bool is_signed(); + virtual uint32_t size() = 0; }; class FundamentalType : public Type { @@ -49,6 +50,7 @@ namespace types { virtual llvm::Value* lt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override; virtual llvm::Value* gt(codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) override; virtual bool is_signed() override; + virtual uint32_t size() override; }; @@ -68,6 +70,7 @@ namespace types { virtual llvm::Type* codegen(codegen::Builder& builder) override; virtual std::pair> load(codegen::Builder& builder, llvm::Value* ptr) override; virtual std::optional> return_type() override; + virtual uint32_t size() override; }; @@ -82,6 +85,7 @@ namespace types { virtual std::string formatted() override; virtual llvm::Type* codegen(codegen::Builder& builder) override; virtual std::pair> load(codegen::Builder& builder, llvm::Value* ptr) override; + virtual uint32_t size() override; }; bool types_equal(std::shared_ptr type1, std::shared_ptr type2); diff --git a/test.c b/test.c index c0ea202..42e26d0 100644 --- a/test.c +++ b/test.c @@ -10,5 +10,5 @@ int main() { printf("10th fibonacci number is %d!", fibonacci(10)); char res = 0; res = 15; - return (int)res; + return res; } \ No newline at end of file