diff --git a/src/binops.cpp b/src/binops.cpp index e83109d..7a2e747 100644 --- a/src/binops.cpp +++ b/src/binops.cpp @@ -7,13 +7,33 @@ namespace types { auto int_ty = std::shared_ptr{ new types::FundamentalType{ false, types::FundamentalTypeKind::Int } }; + auto uint_ty = std::shared_ptr{ + new types::FundamentalType{ false, types::FundamentalTypeKind::UInt } }; auto char_ty = std::shared_ptr{ new types::FundamentalType{ false, types::FundamentalTypeKind::Char } }; + auto uchar_ty = std::shared_ptr{ + new types::FundamentalType{ false, types::FundamentalTypeKind::UChar } }; + auto short_int_ty = std::shared_ptr{ + new types::FundamentalType{ false, types::FundamentalTypeKind::ShortInt } }; + auto ushort_int_ty = std::shared_ptr{ + new types::FundamentalType{ false, types::FundamentalTypeKind::UShortInt } }; + auto long_int_ty = std::shared_ptr{ + new types::FundamentalType{ false, types::FundamentalTypeKind::LongInt } }; + auto ulong_int_ty = std::shared_ptr{ + new types::FundamentalType{ false, types::FundamentalTypeKind::ULongInt } }; + auto long_long_int_ty = std::shared_ptr{ + new types::FundamentalType{ false, types::FundamentalTypeKind::LongLongInt } }; + auto ulong_long_int_ty = std::shared_ptr{ + new types::FundamentalType{ false, types::FundamentalTypeKind::ULongLongInt } }; auto bool_ty = std::shared_ptr{ new types::FundamentalType{ false, types::FundamentalTypeKind::Bool } }; // Integer arithmetic binops - for (auto& ty : { int_ty, char_ty, bool_ty }) { + for (auto& ty : { + short_int_ty, int_ty, long_int_ty, long_long_int_ty, char_ty, + ushort_int_ty, uint_ty, ulong_int_ty, ulong_long_int_ty, uchar_ty, + bool_ty + }) { definitions.push_back(BinopDefinition{ ty, types::BinOp::Add, ty, [](codegen::Builder& builder, llvm::Value* lhs, llvm::Value* rhs) { diff --git a/src/typechecker.cpp b/src/typechecker.cpp index 236e620..784babd 100644 --- a/src/typechecker.cpp +++ b/src/typechecker.cpp @@ -244,6 +244,31 @@ namespace AST { } } + // if that fails, accept binops that match the result type perfectly and + // is able to cast both types successfully + for (auto& binop : state.binops) { + if (expected_ty) { + // Skip any binops that would not be immediately assignable to + // the expected type + if (!types::types_equal(binop.result(binop, lhs_ty, rhs_ty), *expected_ty)) { + continue; + } + } + + auto rhs_res = check_type(state, rhs_ty, binop.rhs); + auto lhs_res = check_type(state, lhs_ty, binop.lhs); + if (!rhs_res.ok() || !lhs_res.ok()) + continue; + + lhs_ty = this->m_lhs->typecheck(state, scope, binop.lhs).type; + rhs_ty = this->m_rhs->typecheck(state, scope, binop.rhs).type; + lhs_res = check_type(state, lhs_ty, binop.lhs); + rhs_res = check_type(state, rhs_ty, binop.rhs); + this->m_lhs = handle_res(std::move(this->m_lhs), lhs_res, state); + this->m_rhs = handle_res(std::move(this->m_rhs), rhs_res, state); + return { binop.result(binop, lhs_ty, rhs_ty), false, false }; + } + // Finally check for any binop that allows the result to be implicitly // casted to the result for (auto& binop : state.binops) {