#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 root) { TypeResolver resolver {m_log}; switch (root->type()) { case NODE_ASSERT_STATIC_FAIL: 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(TY_BOOL)); check_types(root, lhs, rhs); } break; case NODE_ASSERT: case NODE_NOT: { check_children(root); auto lhs = resolver.find(root->child(0)); check_types(root, lhs, std::make_shared(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(TY_INT)); check_types(root, lhs, rhs); } break; case NODE_UADD: case NODE_USUB: { check_children(root); auto lhs = resolver.find(root->child(0)); check_types(root, lhs, std::make_shared(TY_INT)); } 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 root) { for (size_t i=0; isize(); i++) { check(root->child(i)); } } void StaticPass::check_types(std::shared_ptr root, std::shared_ptr lhs, std::shared_ptr 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 root, std::shared_ptr lhs, std::vector> 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()); } }