roza/lib/StaticPass.cpp

185 lines
4.5 KiB
C++
Raw Normal View History

2023-08-30 18:06:26 +00:00
#include "StaticPass.hpp"
#include "lib/Node.hpp"
2023-08-30 22:31:19 +00:00
#include "TypeResolver.hpp"
2023-08-30 18:06:26 +00:00
namespace roza
{
/*explicit*/ StaticPass::StaticPass(StatusLog& log)
: StaticPass (log, SymTable {})
{
}
/*explicit*/ StaticPass::StaticPass(StatusLog& log, SymTable const& sym_table)
2023-08-30 18:06:26 +00:00
: m_log { log }
, m_sym { SymTable(sym_table) }
2023-08-30 18:06:26 +00:00
{
}
/*virtual*/ StaticPass::~StaticPass()
{
}
void StaticPass::check(std::shared_ptr<Node> root)
{
2023-08-30 22:31:19 +00:00
TypeResolver resolver {m_log};
assert(root);
2023-08-30 22:31:19 +00:00
2023-08-30 18:06:26 +00:00
switch (root->type())
{
2023-08-31 23:22:51 +00:00
case NODE_IF: {
m_sym.enter_scope();
auto cond_type = resolver.find(root->child(0), m_sym);
check_types(root, std::make_shared<Type>(TY_BOOL), cond_type);
check_children(root);
m_sym.leave_scope();
} break;
case NODE_THEN:
case NODE_ELSE: {
check_children(root);
} break;
case NODE_CONSTDECL: {
check(root->child(1));
m_sym.declare(root->child(0)->repr(), root->child(1));
} break;
case NODE_VARDECL: {
check(root->child(1));
m_sym.declare_mut(root->child(0)->repr(), root->child(1));
} break;
case NODE_ASSIGN: {
auto const& entry = m_sym.find(root->child(0)->repr());
if (!entry.is_mut)
{
m_log.fatal(root->child(0)->loc(),
root->child(0)->repr() + " is not mutable");
}
auto lhs = resolver.find(entry.node, m_sym);
auto rhs = resolver.find(root->child(1), m_sym);
check_types(root, lhs, rhs);
} break;
case NODE_IDENT:
case NODE_ASSERT_STATIC_FAIL:
2023-08-31 09:07:03 +00:00
case NODE_INT:
case NODE_BOOL:
break;
2023-08-31 09:37:13 +00:00
case NODE_EQ:
case NODE_NE: {
check_children(root);
auto lhs = resolver.find(root->child(0), m_sym);
auto rhs = resolver.find(root->child(1), m_sym);
2023-08-31 09:37:13 +00:00
check_types(root, lhs, rhs);
} break;
2023-08-31 09:07:03 +00:00
case NODE_IMP:
case NODE_OR:
case NODE_AND: {
check_children(root);
auto lhs = resolver.find(root->child(0), m_sym);
auto rhs = resolver.find(root->child(1), m_sym);
2023-08-31 09:07:03 +00:00
check_types(root, lhs, std::make_shared<Type>(TY_BOOL));
check_types(root, lhs, rhs);
} break;
case NODE_ASSERT:
2023-08-31 09:07:03 +00:00
case NODE_NOT: {
check_children(root);
auto lhs = resolver.find(root->child(0), m_sym);
2023-08-31 09:07:03 +00:00
check_types(root, lhs, std::make_shared<Type>(TY_BOOL));
} break;
2023-08-30 18:06:26 +00:00
2023-08-31 09:37:13 +00:00
case NODE_LT:
case NODE_LE:
case NODE_GT:
case NODE_GE:
2023-08-30 22:31:19 +00:00
case NODE_ADD:
case NODE_SUB:
case NODE_MUL:
case NODE_DIV:
case NODE_MOD:
case NODE_POW: {
2023-08-31 09:07:03 +00:00
check_children(root);
auto lhs = resolver.find(root->child(0), m_sym);
auto rhs = resolver.find(root->child(1), m_sym);
2023-08-31 09:07:03 +00:00
check_types(root, lhs, std::make_shared<Type>(TY_INT));
check_types(root, lhs, rhs);
2023-08-30 22:31:19 +00:00
} break;
case NODE_UADD:
case NODE_USUB: {
2023-08-31 09:07:03 +00:00
check_children(root);
auto lhs = resolver.find(root->child(0), m_sym);
check_types(root, lhs, std::make_shared<Type>(TY_INT));
2023-08-30 22:31:19 +00:00
} break;
case NODE_PROG: {
2023-08-31 09:07:03 +00:00
check_children(root);
2023-08-30 18:06:26 +00:00
} break;
default:
m_log.fatal(root->loc(), "cannot check node '" + root->string() + "'");
}
}
2023-08-31 09:07:03 +00:00
void StaticPass::check_children(std::shared_ptr<Node> root)
{
for (size_t i=0; i<root->size(); i++)
{
check(root->child(i));
}
}
void StaticPass::check_types(std::shared_ptr<Node> root,
std::shared_ptr<Type> lhs,
std::shared_ptr<Type> rhs)
{
assert(lhs);
assert(rhs);
2023-08-31 09:07:03 +00:00
if (!lhs->equals(*rhs))
{
m_log.fatal(root->loc(),
std::string()
+ "type mismatch, expected '"
+ lhs->string()
+ "', got '"
+ rhs->string()
+ "'");
}
}
void StaticPass::check_types(std::shared_ptr<Node> root,
std::shared_ptr<Type> lhs,
std::vector<std::shared_ptr<Type>> const& rhs)
{
for (auto const& ty: rhs)
{
if (lhs->equals(*ty))
{
return;
}
}
std::stringstream ss;
ss << "type mismatch, got '" << lhs->string() << "'";
ss << "candidates are:" << std::endl;
for (auto ty: rhs)
{
ss << "\t-> " << ty->string() << std::endl;
}
m_log.fatal(root->loc(), ss.str());
}
2023-08-30 18:06:26 +00:00
}