#include "StaticPass.hpp" namespace jk { /*explicit*/ StaticPass::StaticPass(std::shared_ptr sym, Logger& logger) : m_sym { sym } , m_logger { logger } { } /*virtual*/ StaticPass::~StaticPass() { } void StaticPass::pass(std::shared_ptr node) { switch (node->type()) { case NODE_PROG: case NODE_BODY: { for (size_t i=0; isize(); i++) { pass(node->child(i).lock()); pop(); } } break; case NODE_LAMBDA: { auto params = node->child(0).lock(); auto body = node->child(1).lock(); for (size_t i=0; isize(); i++) { auto param = params->child(i).lock(); std::string ident = params->child(i).lock()->repr(); m_sym->declare(ident, std::make_shared(TYPE_NIL), param->loc()); } pass(body); push(std::make_shared(TYPE_FUNCTION)); } break; case NODE_INT: { push(std::make_shared(TYPE_INT)); } break; case NODE_BOOL: { push(std::make_shared(TYPE_BOOL)); } break; case NODE_IDENT: { std::string ident = node->repr(); auto entry = m_sym->find(ident); if (!entry && std::find(std::begin(m_statics), std::end(m_statics), ident) == std::end(m_statics)) { m_logger.log(LOG_ERROR, node->loc(), std::string() + "'" + ident + "' is undefined"); } if (entry) { push(entry->type); } } break; case NODE_VARDECL: { std::string ident = node->child(0).lock()->repr(); pass(node->child(1).lock()); auto type = pop(); m_sym->declare(ident, type, node->loc()); push(type); } break; case NODE_FUNCALL: { auto is_static = std::find(std::begin(m_statics), std::end(m_statics), node->child(0).lock()->repr()) != std::end(m_statics); if (!is_static) { for (size_t i=0; isize(); i++) { pass(node->child(i).lock()); pop(); } } push(std::make_shared(TYPE_NIL)); } break; default: std::cerr << "cannot static_pass unknown node '" << NodeTypeStr[node->type()] << "'" << std::endl; abort(); } } void StaticPass::add_static(std::string const& name) { m_statics.push_back(name); } void StaticPass::push(std::shared_ptr type) { m_types.push_back(type); } std::shared_ptr StaticPass::pop() { auto type = m_types.back(); m_types.pop_back(); return type; } }