131 lines
3.0 KiB
C++
131 lines
3.0 KiB
C++
#include "StaticPass.hpp"
|
|
#include "lib/Node.hpp"
|
|
#include "TypeResolver.hpp"
|
|
|
|
namespace roza
|
|
{
|
|
/*explicit*/ StaticPass::StaticPass(StatusLog& log)
|
|
: m_log { log }
|
|
{
|
|
}
|
|
|
|
/*virtual*/ StaticPass::~StaticPass()
|
|
{
|
|
}
|
|
|
|
void StaticPass::check(std::shared_ptr<Node> root)
|
|
{
|
|
TypeResolver resolver {m_log};
|
|
|
|
switch (root->type())
|
|
{
|
|
case NODE_INT:
|
|
case NODE_BOOL:
|
|
break;
|
|
|
|
case NODE_EQ:
|
|
case NODE_NE: {
|
|
check_children(root);
|
|
auto lhs = resolver.find(root->child(0));
|
|
auto rhs = resolver.find(root->child(1));
|
|
check_types(root, lhs, rhs);
|
|
} break;
|
|
|
|
case NODE_IMP:
|
|
case NODE_OR:
|
|
case NODE_AND: {
|
|
check_children(root);
|
|
auto lhs = resolver.find(root->child(0));
|
|
auto rhs = resolver.find(root->child(1));
|
|
check_types(root, lhs, std::make_shared<Type>(TY_BOOL));
|
|
check_types(root, lhs, rhs);
|
|
} break;
|
|
|
|
case NODE_NOT: {
|
|
check_children(root);
|
|
auto lhs = resolver.find(root->child(0));
|
|
check_types(root, lhs, std::make_shared<Type>(TY_BOOL));
|
|
} break;
|
|
|
|
case NODE_LT:
|
|
case NODE_LE:
|
|
case NODE_GT:
|
|
case NODE_GE:
|
|
case NODE_ADD:
|
|
case NODE_SUB:
|
|
case NODE_MUL:
|
|
case NODE_DIV:
|
|
case NODE_MOD:
|
|
case NODE_POW: {
|
|
check_children(root);
|
|
auto lhs = resolver.find(root->child(0));
|
|
auto rhs = resolver.find(root->child(1));
|
|
check_types(root, lhs, std::make_shared<Type>(TY_INT));
|
|
check_types(root, lhs, rhs);
|
|
} break;
|
|
|
|
case NODE_UADD:
|
|
case NODE_USUB: {
|
|
check_children(root);
|
|
} break;
|
|
|
|
case NODE_PROG: {
|
|
check_children(root);
|
|
} break;
|
|
|
|
default:
|
|
m_log.fatal(root->loc(), "cannot check node '" + root->string() + "'");
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
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());
|
|
}
|
|
|
|
}
|