Improve binop typechecking
This commit is contained in:
parent
51c54e375a
commit
57dc022241
@ -117,6 +117,8 @@ std::optional<CompileOutput> compile(std::string_view in_filename) {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compile parsed output
|
||||||
|
|
||||||
codegen::Scope cg_scope{
|
codegen::Scope cg_scope{
|
||||||
.binops = typecheck_state.binops,
|
.binops = typecheck_state.binops,
|
||||||
.casts = typecheck_state.casts,
|
.casts = typecheck_state.casts,
|
||||||
@ -124,7 +126,6 @@ std::optional<CompileOutput> compile(std::string_view in_filename) {
|
|||||||
.is_lvalue = false,
|
.is_lvalue = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Compile parsed output
|
|
||||||
try {
|
try {
|
||||||
for (auto& tls : statements) {
|
for (auto& tls : statements) {
|
||||||
std::cout << tls->formatted() << std::endl;
|
std::cout << tls->formatted() << std::endl;
|
||||||
|
|||||||
@ -111,7 +111,7 @@ namespace AST {
|
|||||||
std::shared_ptr<types::Type> BinaryOperationExpression::typecheck(
|
std::shared_ptr<types::Type> BinaryOperationExpression::typecheck(
|
||||||
typecheck::State& state,
|
typecheck::State& state,
|
||||||
typecheck::Scope& scope,
|
typecheck::Scope& scope,
|
||||||
std::optional<std::shared_ptr<types::Type>>
|
std::optional<std::shared_ptr<types::Type>> expected_ty
|
||||||
) {
|
) {
|
||||||
auto lhs_ty = this->m_lhs->typecheck(state, scope, {});
|
auto lhs_ty = this->m_lhs->typecheck(state, scope, {});
|
||||||
auto rhs_ty = this->m_rhs->typecheck(state, scope, {});
|
auto rhs_ty = this->m_rhs->typecheck(state, scope, {});
|
||||||
@ -119,9 +119,12 @@ namespace AST {
|
|||||||
if (this->m_binop == types::BinOp::Assignment) {
|
if (this->m_binop == types::BinOp::Assignment) {
|
||||||
// Re-typecheck rhs to actually match lhs
|
// Re-typecheck rhs to actually match lhs
|
||||||
auto rhs_ty = this->m_rhs->typecheck(state, scope, lhs_ty);
|
auto rhs_ty = this->m_rhs->typecheck(state, scope, lhs_ty);
|
||||||
|
auto rhs_ty_res = check_type(state, rhs_ty, lhs_ty);
|
||||||
|
this->m_rhs = handle_res(std::move(this->m_rhs), rhs_ty_res, state);
|
||||||
return lhs_ty;
|
return lhs_ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to find a binop that matches exactly
|
||||||
auto binop = types::find_binop(
|
auto binop = types::find_binop(
|
||||||
state.binops,
|
state.binops,
|
||||||
lhs_ty,
|
lhs_ty,
|
||||||
@ -133,8 +136,53 @@ namespace AST {
|
|||||||
return binop->result;
|
return binop->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO check for binops that may be implicitly castable
|
// If that fails, try to find binop that matches on one side perfectly
|
||||||
|
// and is castable on the other side, and would also be perfectly
|
||||||
|
// assignable to the expected value.
|
||||||
|
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, *expected_ty)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (types::types_equal(binop.lhs, lhs_ty)) {
|
||||||
|
auto rhs_res = check_type(state, rhs_ty, binop.rhs);
|
||||||
|
if (!rhs_res.ok())
|
||||||
|
// Skip if not implicitly castable to lhs
|
||||||
|
continue;
|
||||||
|
this->m_rhs = handle_res(std::move(this->m_rhs), rhs_res, state);
|
||||||
|
return binop.result;
|
||||||
|
}
|
||||||
|
else if (types::types_equal(binop.rhs, rhs_ty)) {
|
||||||
|
auto lhs_res = check_type(state, lhs_ty, binop.lhs);
|
||||||
|
if (!lhs_res.ok())
|
||||||
|
// Skip if not implicitly castable to rhs
|
||||||
|
continue;
|
||||||
|
this->m_lhs = handle_res(std::move(this->m_lhs), lhs_res, state);
|
||||||
|
return binop.result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally check for any binop that allows the result to be implicitly
|
||||||
|
// casted to the result
|
||||||
|
for (auto& binop : state.binops) {
|
||||||
|
if (expected_ty) {
|
||||||
|
// Skip any binops that would not even be implicitly castable to
|
||||||
|
// the expected result
|
||||||
|
auto result_res = check_type(state, binop.result, *expected_ty);
|
||||||
|
if (!result_res.ok())
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto lhs_result = check_type(state, lhs_ty, binop.lhs);
|
||||||
|
auto rhs_result = check_type(state, rhs_ty, binop.rhs);
|
||||||
|
this->m_lhs = handle_res(std::move(this->m_lhs), lhs_result, state);
|
||||||
|
this->m_rhs = handle_res(std::move(this->m_rhs), lhs_result, state);
|
||||||
|
return binop.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No suitable binops found :(
|
||||||
state.errors.push_back(CompileError(
|
state.errors.push_back(CompileError(
|
||||||
"No suitable binop between "
|
"No suitable binop between "
|
||||||
+ lhs_ty->formatted() + " "
|
+ lhs_ty->formatted() + " "
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user