1 | #include "ReplacePseudoFunc.hpp" |
---|
2 | |
---|
3 | #include <set> |
---|
4 | |
---|
5 | #include "AST/Decl.hpp" |
---|
6 | #include "AST/Inspect.hpp" |
---|
7 | #include "AST/Pass.hpp" |
---|
8 | #include "AST/Print.hpp" |
---|
9 | #include "AST/Stmt.hpp" |
---|
10 | #include "Common/utility.h" |
---|
11 | #include "ResolvExpr/CandidateFinder.hpp" |
---|
12 | #include "ResolvExpr/Resolver.h" |
---|
13 | #include "SymTab/Mangler.h" |
---|
14 | |
---|
15 | namespace Validate { |
---|
16 | |
---|
17 | namespace { |
---|
18 | |
---|
19 | ast::ptr<ast::Expr> reduceCastExpr(ast::ptr<ast::Expr> expr) { |
---|
20 | if (auto castExpr = expr.as<ast::CastExpr>()) { |
---|
21 | return reduceCastExpr(castExpr->arg); |
---|
22 | } |
---|
23 | return expr; |
---|
24 | } |
---|
25 | |
---|
26 | struct ReplaceSuccAndPred final : public ast::WithSymbolTable, |
---|
27 | public ast::WithConstTranslationUnit { |
---|
28 | const ast::Expr* postvisit(const ast::ApplicationExpr* expr) { |
---|
29 | auto fname = ast::getFunctionName(expr); |
---|
30 | if (fname == "succ" || fname == "pred") { |
---|
31 | const CodeLocation& location = expr->location; |
---|
32 | if (expr->args.size() != 1) return expr; |
---|
33 | |
---|
34 | auto param = expr->args.front(); |
---|
35 | if (auto argAsVar = reduceCastExpr(param).as<ast::VariableExpr>()) { |
---|
36 | if (auto argAsDecl = argAsVar->var.as<ast::ObjectDecl>()) { |
---|
37 | if (auto enumInst = |
---|
38 | argAsDecl->type.as<ast::EnumInstType>()) { |
---|
39 | auto castTo = new ast::EnumAttrType( |
---|
40 | enumInst, ast::EnumAttribute::Posn); |
---|
41 | auto castExpr = |
---|
42 | new ast::CastExpr(param->location, param, castTo); |
---|
43 | |
---|
44 | auto untyped = new ast::UntypedExpr( |
---|
45 | expr->location, |
---|
46 | new ast::NameExpr(location, fname == "succ" |
---|
47 | ? "_successor_" |
---|
48 | : "_predessor_"), |
---|
49 | {castExpr}); |
---|
50 | ResolvExpr::ResolveContext context{symtab, |
---|
51 | transUnit().global}; |
---|
52 | auto typedResult = |
---|
53 | ResolvExpr::findVoidExpression(untyped, context); |
---|
54 | ast::ptr<ast::ApplicationExpr> ret = |
---|
55 | typedResult.strict_as<ast::ApplicationExpr>(); |
---|
56 | return ast::deepCopy(ret); |
---|
57 | } else if (argAsDecl->type.as<ast::EnumAttrType>()) { |
---|
58 | std::cerr << "PseudoFunc: succ/pred should not be applied on EnumAttrType directly" << std::endl; |
---|
59 | } |
---|
60 | } |
---|
61 | } |
---|
62 | } |
---|
63 | return expr; |
---|
64 | } |
---|
65 | }; |
---|
66 | |
---|
67 | } // namespace |
---|
68 | |
---|
69 | void replacePseudoFunc(ast::TranslationUnit& translationUnit) { |
---|
70 | ast::Pass<ReplaceSuccAndPred>::run(translationUnit); |
---|
71 | } |
---|
72 | } // namespace Validate |
---|