Allow implicit cast from char to int

This commit is contained in:
Sofia 2026-04-13 21:45:58 +03:00
parent e0f2a1620e
commit 28483812ea
5 changed files with 41 additions and 5 deletions

View File

@ -1,5 +1,6 @@
#include "casting.h"
#include <iostream>
namespace types {
std::vector<CastDefinition> create_casts() {
@ -21,15 +22,21 @@ namespace types {
[](codegen::Builder&, std::shared_ptr<Type>, 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<Type> 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<Type> target, llvm::Value* value) {
return builder.builder->CreateZExtOrTrunc(value, target->codegen(builder), "cast");
} });

View File

@ -15,9 +15,13 @@ namespace {
std::shared_ptr<types::Type> result;
};
Result<TypecheckRes, std::string> check_type(typecheck::State& state, std::shared_ptr<types::Type> checked, std::shared_ptr<types::Type> target) {
Result<TypecheckRes, std::string> check_type(
typecheck::State& state,
std::shared_ptr<types::Type> checked,
std::shared_ptr<types::Type> target) {
auto potential_cast = types::find_cast(state.casts, checked, target);
if (types::types_equal(checked, target)) {
return TypecheckRes{ TypecheckResKind::Ok, target };
}

View File

@ -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<types::Type> type1, std::shared_ptr<types::Type> type2) {
if (type1->m_kind != type2->m_kind)
return false;

View File

@ -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<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr) override;
virtual std::optional<std::shared_ptr<Type>> 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<llvm::Value*, std::shared_ptr<Type>> load(codegen::Builder& builder, llvm::Value* ptr) override;
virtual uint32_t size() override;
};
bool types_equal(std::shared_ptr<types::Type> type1, std::shared_ptr<types::Type> type2);

2
test.c
View File

@ -10,5 +10,5 @@ int main() {
printf("10th fibonacci number is %d!", fibonacci(10));
char res = 0;
res = 15;
return (int)res;
return res;
}