Index: src/Validate/Autogen.cpp
===================================================================
--- src/Validate/Autogen.cpp	(revision 00eaeb8994cf3f494e7144b8b16c571570217395)
+++ src/Validate/Autogen.cpp	(revision bbf2cb164e26be1589f185df9bf81b21c503c1d2)
@@ -212,5 +212,6 @@
 	ast::FunctionDecl * genPredPosProto() const;
 
-	void genSuccFunc(ast::FunctionDecl *);
+	ast::FunctionDecl * genSuccPredFunc( bool succ );
+	// ast::FunctionDecl * genPredFunc();
 };
 
@@ -811,5 +812,5 @@
 
 ast::FunctionDecl * EnumFuncGenerator::genSuccPosProto() const {
-	return genProto( "succ",
+	return genProto( "_successor_",
 		{ new ast::ObjectDecl( getLocation(), "_i", 
 			new ast::EnumPosType( new ast::EnumInstType( decl ) ) )},
@@ -821,5 +822,5 @@
 
 ast::FunctionDecl * EnumFuncGenerator::genPredPosProto() const {
-	return genProto( "pred",
+	return genProto( "_predessor_",
 		{ new ast::ObjectDecl( getLocation(), "_i", 
 			new ast::EnumPosType( new ast::EnumInstType( decl ) ) )},
@@ -830,17 +831,13 @@
 }
 
-void EnumFuncGenerator::genSuccFunc(ast::FunctionDecl * succDecl) {
+ast::FunctionDecl * EnumFuncGenerator::genSuccPredFunc( bool succ ) {
+	ast::FunctionDecl * decl = succ? genSuccPosProto(): genPredPosProto();
+	produceForwardDecl( decl );
+
 	const CodeLocation& location = getLocation();
 
-	auto & params = succDecl->params;
+	auto & params = decl->params;
 	assert( params.size() == 1 );
 	auto param = params.front().strict_as<ast::ObjectDecl>();
-
-	// auto & returns = succDecl->returns;
-	// assert( returns.size() == 1 );
-	// auto oldRet = returns.front().strict_as<ast::ObjectDecl>();
-
-	// auto param = new ast::ObjectDecl( getLocation(), "_i", 
-	// 		new ast::EnumPosType( new ast::EnumInstType( decl ) ) );
 
 	auto newReturn = new ast::ObjectDecl( location, "_returns",
@@ -849,5 +846,5 @@
 
 	ast::UntypedExpr * addOneExpr = new ast::UntypedExpr( location,
-		new ast::NameExpr( location, "?+?" )
+		new ast::NameExpr( location, succ? "?+?": "?-?" )
 	);
 	addOneExpr->args.push_back( 
@@ -871,5 +868,5 @@
 	);
 
-	succDecl->stmts = new ast::CompoundStmt( location, 
+	decl->stmts = new ast::CompoundStmt( location, 
 		{
 			new ast::DeclStmt( location, newReturn ),
@@ -878,4 +875,6 @@
 				new ast::VariableExpr( location, newReturn )) 
 		} );
+	
+	return decl;
 }
 
@@ -886,4 +885,6 @@
 			&EnumFuncGenerator::genValueProto, &EnumFuncGenerator::genSuccProto,
 			&EnumFuncGenerator::genPredProto
+			// ,&EnumFuncGenerator::genSuccPosProto,
+			// &EnumFuncGenerator::genPredPosProto
 		};
 		for ( auto & generator : attrProtos ) {
@@ -895,8 +896,8 @@
 void EnumFuncGenerator::genPosFunctions() {
 	if ( decl->base ) {
-		ast::FunctionDecl * decl = genSuccPosProto();
-		produceForwardDecl( decl );
-		genSuccFunc (decl );
-		produceDecl( decl );
+		ast::FunctionDecl * succ = genSuccPredFunc( true );
+		ast::FunctionDecl * pred = genSuccPredFunc( false );
+		produceDecl( succ );
+		produceDecl( pred );
 	}
 
Index: src/Validate/ReplacePseudoFunc.cpp
===================================================================
--- src/Validate/ReplacePseudoFunc.cpp	(revision 00eaeb8994cf3f494e7144b8b16c571570217395)
+++ src/Validate/ReplacePseudoFunc.cpp	(revision bbf2cb164e26be1589f185df9bf81b21c503c1d2)
@@ -21,5 +21,4 @@
 
 struct ReplaceEnumInstWithPos final : public ast::WithShortCircuiting {
-    void previsit(const ast::ObjectDecl*) { visit_children = false; }
     const ast::ObjectDecl* postvisit(const ast::ObjectDecl* decl) {
         auto enumInst = decl->type.strict_as<ast::EnumInstType>();
@@ -84,5 +83,6 @@
     }
 
-    if (fname == "labelE" || fname == "valueE" || fname == "posE") {
+    if (fname == "labelE" || fname == "valueE" || fname == "posE" ||
+        fname == "pred" || fname == "succ") {
         visit_children = false;
     }
@@ -226,5 +226,5 @@
 }
 
-ast::ApplicationExpr const* getPseudoFuncApplication(
+ast::ApplicationExpr const* resolveAttributeFunctions(
     const CodeLocation location, ResolvExpr::ResolveContext context,
     const ast::VariableExpr* arg, const ast::EnumDecl* base,
@@ -241,4 +241,6 @@
         auto rep = argAsDecl->accept(replacer);
         auto mutatedArg = ast::mutate_field(arg, &ast::VariableExpr::var, rep);
+        mutatedArg = ast::mutate_field(mutatedArg, &ast::VariableExpr::result,
+                                       mutatedArg->var->get_type());
         auto untyped =
             new ast::UntypedExpr(location, new ast::NameExpr(location, "?[?]"),
@@ -290,5 +292,5 @@
                                                               referredName);
                     else {
-                        return getPseudoFuncApplication(
+                        return resolveAttributeFunctions(
                             location, context, arg.get(), base, "values_");
                     }
@@ -297,10 +299,10 @@
 
             if (fname == "labelE") {
-                if (auto labelExpr = getPseudoFuncApplication(
+                if (auto labelExpr = resolveAttributeFunctions(
                         location, context, arg.get(), base, "labels_")) {
                     return labelExpr;
                 }
             } else if (fname == "valueE") {
-                if (auto valueExpr = getPseudoFuncApplication(
+                if (auto valueExpr = resolveAttributeFunctions(
                         location, context, arg.get(), base, "values_")) {
                     return valueExpr;
@@ -314,10 +316,10 @@
             ResolvExpr::ResolveContext context{symtab, transUnit().global};
             if (fname == "labelE") {
-                if (auto labelExpr = getPseudoFuncApplication(
+                if (auto labelExpr = resolveAttributeFunctions(
                         location, context, arg.get(), base, "labels_")) {
                     return labelExpr;
                 }
             } else if (fname == "valueE") {
-                if (auto valueExpr = getPseudoFuncApplication(
+                if (auto valueExpr = resolveAttributeFunctions(
                         location, context, arg.get(), base, "values_")) {
                     return valueExpr;
@@ -345,36 +347,171 @@
     const ast::Expr* postvisit(const ast::ApplicationExpr* expr) {
         auto fname = ast::getFunctionName(expr);
-        if (fname != "?[?]") return expr;
-        if (expr->args.size() != 2) return expr;
-
-        auto arg1AsVar =
-            reduceCastExpr(expr->args.front()).as<ast::VariableExpr>();
-        auto arg2AsVar =
-            reduceCastExpr(expr->args.back()).as<ast::VariableExpr>();
-
-        if (!arg1AsVar || !arg2AsVar) return expr;
-
-        auto arg1Asecl = arg1AsVar->var.as<ast::ObjectDecl>();
-        auto arg2Asecl = arg2AsVar->var.as<ast::ObjectDecl>();
-
-        if (!arg1Asecl || !arg2Asecl) return expr;
-        auto arrInst = arg1Asecl->type.as<ast::ArrayType>();
-        auto pointerInst = arg1Asecl->type.as<ast::PointerType>();
-        if (!arrInst && !pointerInst) {
-            return expr;
-        }
-        auto enumInst = arg2Asecl->type.as<ast::EnumInstType>();
-        if (!enumInst) return expr;
-
-        const std::string arrName = arg1Asecl->name;
-        if (arrName != getValueArrayName(enumInst->base->name)) return expr;
-        ast::Pass<ReplaceEnumInstWithPos> replacer;
-        auto rep = arg2Asecl->accept(replacer);
-        if (!rep) return expr;
-        auto mutObj =
-            ast::mutate_field(arg2AsVar, &ast::VariableExpr::var, rep);
-        auto mut = ast::mutate_field_index(expr, &ast::ApplicationExpr::args, 1,
-                                           mutObj);
-        return mut;
+        if (fname == "?[?]") {
+            if (expr->args.size() != 2) return expr;
+
+            auto arg1AsVar =
+                reduceCastExpr(expr->args.front()).as<ast::VariableExpr>();
+            auto arg2AsVar =
+                reduceCastExpr(expr->args.back()).as<ast::VariableExpr>();
+
+            if (!arg1AsVar || !arg2AsVar) return expr;
+
+            auto arg1AsDecl = arg1AsVar->var.as<ast::ObjectDecl>();
+            auto arg2AsDecl = arg2AsVar->var.as<ast::ObjectDecl>();
+
+            if (!arg1AsDecl || !arg2AsDecl) return expr;
+            auto arrInst = arg1AsDecl->type.as<ast::ArrayType>();
+            auto pointerInst = arg1AsDecl->type.as<ast::PointerType>();
+            if (!arrInst && !pointerInst) {
+                return expr;
+            }
+            auto enumInst = arg2AsDecl->type.as<ast::EnumInstType>();
+            if (!enumInst) return expr;
+
+            const std::string arrName = arg1AsDecl->name;
+            if (arrName != getValueArrayName(enumInst->base->name)) return expr;
+            ast::Pass<ReplaceEnumInstWithPos> replacer;
+            auto rep = arg2AsDecl->accept(replacer);
+            if (!rep) return expr;
+            auto mutObj =
+                ast::mutate_field(arg2AsVar, &ast::VariableExpr::var, rep);
+            mutObj = ast::mutate_field(mutObj, &ast::VariableExpr::result,
+                                       mutObj->var->get_type());
+            auto mut = ast::mutate_field_index(
+                expr, &ast::ApplicationExpr::args, 1, mutObj);
+            return mut;
+        }
+        // else if (fname == "succ" || fname == "pred") {
+        //     if (expr->args.size() != 1) return expr;
+        //     auto argExpr = expr->args.front();
+        //     auto argAsVar = reduceCastExpr(argExpr).as<ast::VariableExpr>();
+
+        //     if (auto argAsDecl = argAsVar->var.as<ast::ObjectDecl>()) {
+        //         if (auto enumInst = argAsDecl->type.as<ast::EnumInstType>())
+        //         {
+        //             auto enumPos = new ast::EnumPosType(enumInst);
+        //             auto castExpr =
+        //                 new ast::CastExpr(argExpr->location, argExpr,
+        //                 enumPos);
+        //             auto mut = ast::mutate_field_index(
+        //                 expr, &ast::ApplicationExpr::args, 0, castExpr);
+        //             return mut;
+        //         } else if (auto enumPos =
+        //                        argAsDecl->type.as<ast::EnumPosType>()) {
+        //             //     std::cout << "pos" << std::endl;
+        //             return expr;
+        //         }
+        //     }
+        // }
+        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;
+
+            // if (auto argAsVar = reduceCastExpr(expr->args.front())
+            //                         .as<ast::VariableExpr>()) {
+            //     if (auto argAsDecl = argAsVar->var.as<ast::ObjectDecl>()) {
+            //         auto enumPos = argAsDecl->type.as<ast::EnumPosType>();
+            //         if (!enumPos) return expr;
+            //         // ast::Pass<ReplaceEnumInstWithPos> replacer;
+            //         // auto posObj = argAsDecl->accept(replacer);
+            //         // if (!posObj) return expr;
+
+            //         // auto newParam = new ast::VariableExpr( location,
+            //         posObj
+            //         // );
+
+            //         auto untyped = new ast::UntypedExpr(
+            //             location,
+            //             new ast::NameExpr(location, fname == "succ"
+            //                                             ? "_successor_"
+            //                                             : "_predessor_"),
+            //             {argAsVar});
+
+            //         ResolvExpr::ResolveContext context{symtab,
+            //                                            transUnit().global};
+
+            //         auto typedResult =
+            //             ResolvExpr::findVoidExpression(untyped, context);
+
+            //         ast::ptr<ast::ApplicationExpr> ret =
+            //             typedResult.strict_as<ast::ApplicationExpr>();
+
+            //         return ast::deepCopy(ret);
+            //     }
+            // }
+            auto param = expr->args.front();
+            if (auto argAsVar = reduceCastExpr(param).as<ast::VariableExpr>()) {
+                if (auto argAsDecl = argAsVar->var.as<ast::ObjectDecl>()) {
+                    if (auto enumInst =
+                            argAsDecl->type.as<ast::EnumInstType>()) {
+                        auto castTo = new ast::EnumPosType(enumInst);
+                        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<ast::ApplicationExpr> ret =
+                            typedResult.strict_as<ast::ApplicationExpr>();
+                        return ast::deepCopy(ret);
+                    } else if (auto posType =
+                                   argAsDecl->type.as<ast::EnumPosType>()) {
+                        // Very nasty fix. Must be revisit
+                        if (auto paramAsVar = param.as<ast::VariableExpr>()) {
+                            if (paramAsVar->result.as<ast::EnumInstType>()) {
+                                auto paramToUse = ast::mutate_field(
+                                    paramAsVar, &ast::VariableExpr::result,
+                                    posType);
+                                auto untyped = new ast::UntypedExpr(
+                                    expr->location,
+                                    new ast::NameExpr(location,
+                                                      fname == "succ"
+                                                          ? "_successor_"
+                                                          : "_predessor_"),
+                                    {paramToUse});
+                                ResolvExpr::ResolveContext context{
+                                    symtab, transUnit().global};
+                                auto typedResult =
+                                    ResolvExpr::findVoidExpression(untyped,
+                                                                   context);
+                                ast::ptr<ast::ApplicationExpr> ret =
+                                    typedResult
+                                        .strict_as<ast::ApplicationExpr>();
+                                return ast::deepCopy(ret);
+                            }
+                        }
+                        auto untyped = new ast::UntypedExpr(
+                            expr->location,
+                            new ast::NameExpr(location, fname == "succ"
+                                                            ? "_successor_"
+                                                            : "_predessor_"),
+                            {param});
+                        ResolvExpr::ResolveContext context{symtab,
+                                                           transUnit().global};
+                        auto typedResult =
+                            ResolvExpr::findVoidExpression(untyped, context);
+                        ast::ptr<ast::ApplicationExpr> ret =
+                            typedResult.strict_as<ast::ApplicationExpr>();
+                        return ast::deepCopy(ret);
+                    }
+                }
+            }
+        }
+        return expr;
     }
 };
@@ -385,7 +522,10 @@
     ast::Pass<WrapEnumValueExpr>::run(translationUnit);
     ast::Pass<FindGenEnumArray>::run(translationUnit);
+
     ast::Pass<PseudoFuncGenerateRoutine>::run(translationUnit);
     ast::Pass<ReplacePseudoFuncCore>::run(translationUnit);
     ast::Pass<ReplaceEnumInst>::run(translationUnit);
+
+    ast::Pass<ReplaceSuccAndPred>::run(translationUnit);
 }
 }  // namespace Validate
