#include "ReplacePseudoFunc.hpp" #include #include "AST/Decl.hpp" #include "AST/Inspect.hpp" #include "AST/Pass.hpp" #include "AST/Print.hpp" #include "AST/Stmt.hpp" #include "Common/utility.h" #include "ResolvExpr/CandidateFinder.hpp" #include "ResolvExpr/Resolver.h" #include "SymTab/Mangler.h" namespace Validate { namespace { ast::ptr reduceCastExpr(ast::ptr expr) { if (auto castExpr = expr.as()) { return reduceCastExpr(castExpr->arg); } return expr; } struct ReplaceSuccAndPred final : public ast::WithSymbolTable, public ast::WithConstTranslationUnit { const ast::Expr* postvisit(const ast::ApplicationExpr* expr) { auto fname = ast::getFunctionName(expr); if (fname == "succ" || fname == "pred") { const CodeLocation& location = expr->location; if (expr->args.size() != 1) return expr; auto param = expr->args.front(); if (auto argAsVar = reduceCastExpr(param).as()) { if (auto argAsDecl = argAsVar->var.as()) { if (auto enumInst = argAsDecl->type.as()) { auto castTo = new ast::EnumAttrType( enumInst, ast::EnumAttribute::Posn); auto castExpr = new ast::CastExpr(param->location, param, castTo); auto untyped = new ast::UntypedExpr( expr->location, new ast::NameExpr(location, fname == "succ" ? "_successor_" : "_predessor_"), {castExpr}); ResolvExpr::ResolveContext context{symtab, transUnit().global}; auto typedResult = ResolvExpr::findVoidExpression(untyped, context); ast::ptr ret = typedResult.strict_as(); return ast::deepCopy(ret); } else if (auto posType = argAsDecl->type.as()) { std::cerr << "PseudoFunc: succ/pred should not be applied on EnumAttrType directly" << std::endl; } } } } return expr; } }; } // namespace void replacePseudoFunc(ast::TranslationUnit& translationUnit) { ast::Pass::run(translationUnit); } } // namespace Validate