#include "TypeResolver.hpp" #include "FunTy.hpp" namespace roza { /*explicit*/ TypeResolver::TypeResolver(StatusLog& log) : m_log { log } { } /*virtual*/ TypeResolver::~TypeResolver() { } std::shared_ptr TypeResolver::find(std::shared_ptr root, SymTable const& sym) { switch (root->type()) { case NODE_PROG: { return find(root->child(root->size() - 1), sym); } break; case NODE_CALL: { auto fun = sym.find(root->child(0)->repr()).node; return find(fun->child(1), sym); } break; case NODE_RET: { return find(root->child(0), sym); } break; case NODE_FUN: { auto params = root->child(0); auto ret = root->child(1); auto ty = std::make_shared(); for (size_t i=0; isize(); i++) { ty->add_input(find(params->child(i)->child(1), sym)); } if (ret->size() > 0) { ty->set_output(find(ret->child(0), sym)); } return ty; } break; case NODE_TYPE: { if (root->repr() == "nil") { return std::make_shared(TY_NIL); } if (root->repr() == "int") { return std::make_shared(TY_INT); } if (root->repr() == "bool") { return std::make_shared(TY_BOOL); } if (root->repr() == "fun") { auto ty = std::make_shared(); if (root->size() > 0) { for (size_t i=0; isize() - 1; i++) { ty->add_input(find(root->child(i), sym)); } } if (root->size() > 0) { ty->set_output(find(root->child(root->size()-1), sym)); } return ty; } m_log.fatal(root->loc(), "cannot find type of '" + root->repr() + "'"); } break; case NODE_IDENT: { std::string name = root->repr(); SymEntry const& entry = sym.find(name); return find(entry.node, sym); } break; case NODE_CONSTDECL: case NODE_VARDECL: { auto ty = find(root->child(1), sym); } break; case NODE_INT: { return std::make_shared(BaseType::TY_INT); } break; case NODE_EQ: case NODE_NE: case NODE_LT: case NODE_LE: case NODE_GT: case NODE_GE: case NODE_IMP: case NODE_AND: case NODE_OR: case NODE_NOT: case NODE_BOOL: { return std::make_shared(BaseType::TY_BOOL); } break; case NODE_ADD: case NODE_SUB: case NODE_MUL: case NODE_DIV: case NODE_MOD: case NODE_POW: case NODE_UADD: case NODE_USUB:{ return find(root->child(0), sym); } break; default: m_log.fatal(root->loc(), "cannot find type of node '" + root->string() + "'"); } return nullptr; } }