Index: src/Validate/Autogen.cpp
===================================================================
--- src/Validate/Autogen.cpp	(revision 76fe046c5d7501192d849b5595c9079478c38b0b)
+++ src/Validate/Autogen.cpp	(revision af746ccdf606483f8f89907b52e8b9471c72df7c)
@@ -196,22 +196,8 @@
 
 	bool shouldAutogen() const final { return true; }
-	void genAttrFuncForward();
-	void genPosFunctions();
 private:
 	void genFuncBody( ast::FunctionDecl * decl ) final;
 	void genFieldCtors() final;
 	const ast::Decl * getDecl() const final { return decl; }
-
-	ast::FunctionDecl * genPosProto() const;
-	ast::FunctionDecl * genLabelProto() const;
-	ast::FunctionDecl * genValueProto() const;
-	ast::FunctionDecl * genSuccProto() const;
-	ast::FunctionDecl * genPredProto() const;
-
-	ast::FunctionDecl * genSuccPosProto() const;
-	ast::FunctionDecl * genPredPosProto() const;
-
-	ast::FunctionDecl * genSuccPredFunc( bool succ );
-	// ast::FunctionDecl * genPredFunc();
 };
 
@@ -256,8 +242,4 @@
 	enumInst.base = enumDecl;
 	EnumFuncGenerator gen( enumDecl, &enumInst, functionNesting );
-	if ( enumDecl->base ) {
-		gen.genAttrFuncForward();
-		gen.genPosFunctions();
-	}
 	gen.generateAndAppendFunctions( declsToAddAfter );
 }
@@ -418,5 +400,5 @@
 }
 
-/// Use the current type T to create `void ?{}(T & _dst)`.
+/// Use the current type T to create `void ^?{}(T & _dst)`.
 ast::FunctionDecl * FuncGenerator::genDtorProto() const {
 	// The destructor must be mutex on a concurrent type.
@@ -777,131 +759,4 @@
 }
 
-ast::FunctionDecl * EnumFuncGenerator::genPosProto() const {
-	return genProto( "posE", 
-		{ new ast::ObjectDecl( getLocation(), "_i", 
-		new ast::EnumInstType( decl ) )}, 
-		{ new ast::ObjectDecl( getLocation(), "_ret", 
-		new ast::BasicType{ ast::BasicType::UnsignedInt } )} );
-}
-
-ast::FunctionDecl * EnumFuncGenerator::genLabelProto() const {
-	return genProto( "labelE",
-		{ new ast::ObjectDecl( getLocation(), "_i", 
-		new ast::EnumInstType( decl ) ) },
-		{ new ast::ObjectDecl( getLocation(), "_ret", 
-		new ast::PointerType( new ast::BasicType{ ast::BasicType::Char } ) ) } );
-}
-
-ast::FunctionDecl * EnumFuncGenerator::genValueProto() const {
-	return genProto( "valueE", 
-		{ new ast::ObjectDecl( getLocation(), "_i", new ast::EnumInstType( decl ) )},
-		{ new ast::ObjectDecl( getLocation(), "_ret", ast::deepCopy( decl->base ) ) } );
-}
-
-ast::FunctionDecl * EnumFuncGenerator::genSuccProto() const {
-	return genProto( "succ",
-		{ new ast::ObjectDecl( getLocation(), "_i", new ast::EnumInstType( decl ) )},
-		{ new ast::ObjectDecl( getLocation(), "_ret", new ast::EnumInstType( decl ))} ); 
-}
-
-ast::FunctionDecl * EnumFuncGenerator::genPredProto() const {
-	return genProto( "pred",
-		{ new ast::ObjectDecl( getLocation(), "_i", new ast::EnumInstType( decl ))},
-		{ new ast::ObjectDecl( getLocation(), "_ret", new ast::EnumInstType( decl ))} );
-}
-
-ast::FunctionDecl * EnumFuncGenerator::genSuccPosProto() const {
-	return genProto( "_successor_",
-		{ new ast::ObjectDecl( getLocation(), "_i", 
-			new ast::EnumPosType( new ast::EnumInstType( decl ) ) )},
-		{ 
-			new ast::ObjectDecl( getLocation(), "_ret", 
-			new ast::EnumPosType( new ast::EnumInstType( decl ) ) )
-		} ); 
-}
-
-ast::FunctionDecl * EnumFuncGenerator::genPredPosProto() const {
-	return genProto( "_predessor_",
-		{ new ast::ObjectDecl( getLocation(), "_i", 
-			new ast::EnumPosType( new ast::EnumInstType( decl ) ) )},
-		{ 
-			new ast::ObjectDecl( getLocation(), "_ret", 
-			new ast::EnumPosType( new ast::EnumInstType( decl ) ) )
-		} ); 
-}
-
-ast::FunctionDecl * EnumFuncGenerator::genSuccPredFunc( bool succ ) {
-	ast::FunctionDecl * decl = succ? genSuccPosProto(): genPredPosProto();
-	produceForwardDecl( decl );
-
-	const CodeLocation& location = getLocation();
-
-	auto & params = decl->params;
-	assert( params.size() == 1 );
-	auto param = params.front().strict_as<ast::ObjectDecl>();
-
-	auto newReturn = new ast::ObjectDecl( location, "_returns",
-		new ast::BasicType{ ast::BasicType::SignedInt} );
-	
-
-	ast::UntypedExpr * addOneExpr = new ast::UntypedExpr( location,
-		new ast::NameExpr( location, succ? "?+?": "?-?" )
-	);
-	addOneExpr->args.push_back( 
-		new ast::CastExpr( location, 
-			new ast::VariableExpr( location, param ),
-			new ast::BasicType{ ast::BasicType::SignedInt }
-		)
-	);
-	addOneExpr->args.push_back( 
-		ast::ConstantExpr::from_int( location, 1 )
-	);
-
-	ast::UntypedExpr * assignExpr = new ast::UntypedExpr( location,
-		new ast::NameExpr( location, "?=?" )
-	);
-	assignExpr->args.push_back(	
-		new ast::VariableExpr( location, newReturn )
-	);
-	assignExpr->args.push_back(
-		addOneExpr
-	);
-
-	decl->stmts = new ast::CompoundStmt( location, 
-		{
-			new ast::DeclStmt( location, newReturn ),
-			new ast::ExprStmt( location, assignExpr ),
-			new ast::ReturnStmt( location, 
-				new ast::VariableExpr( location, newReturn )) 
-		} );
-	
-	return decl;
-}
-
-void EnumFuncGenerator::genAttrFuncForward() {	
-	if ( decl->base ) {
-		ast::FunctionDecl *(EnumFuncGenerator::*attrProtos[5])() const = {
-			&EnumFuncGenerator::genPosProto, &EnumFuncGenerator::genLabelProto, 
-			&EnumFuncGenerator::genValueProto, &EnumFuncGenerator::genSuccProto,
-			&EnumFuncGenerator::genPredProto
-			// ,&EnumFuncGenerator::genSuccPosProto,
-			// &EnumFuncGenerator::genPredPosProto
-		};
-		for ( auto & generator : attrProtos ) {
-			produceForwardDecl( (this->*generator)() );
-		}
-	}
-}
-
-void EnumFuncGenerator::genPosFunctions() {
-	if ( decl->base ) {
-		ast::FunctionDecl * succ = genSuccPredFunc( true );
-		ast::FunctionDecl * pred = genSuccPredFunc( false );
-		produceDecl( succ );
-		produceDecl( pred );
-	}
-
-}
-
 void TypeFuncGenerator::genFieldCtors() {
 	// Opaque types do not have field constructors.
Index: src/Validate/ImplementEnumFunc.cpp
===================================================================
--- src/Validate/ImplementEnumFunc.cpp	(revision af746ccdf606483f8f89907b52e8b9471c72df7c)
+++ src/Validate/ImplementEnumFunc.cpp	(revision af746ccdf606483f8f89907b52e8b9471c72df7c)
@@ -0,0 +1,537 @@
+#include "AST/Create.hpp"
+#include "AST/Pass.hpp"
+#include "AST/TranslationUnit.hpp"
+#include "CodeGen/OperatorTable.h"  // for isCtorDtor, isCtorDtorAssign
+#include "InitTweak/InitTweak.h"    // for isAssignment, isCopyConstructor
+namespace Validate {
+
+namespace {
+class EnumAttrFuncGenerator {
+    const ast::EnumDecl* decl;
+    const ast::EnumInstType* instType;
+    // const ast::EnumAttrType* attrType;
+    unsigned int functionNesting;
+    ast::Linkage::Spec proto_linkage;
+
+   public:
+    std::list<ast::ptr<ast::Decl>> forwards;
+    std::list<ast::ptr<ast::Decl>> definitions;
+
+    void generateAndAppendFunctions(std::list<ast::ptr<ast::Decl>>&);
+
+    EnumAttrFuncGenerator(const ast::EnumDecl* decl,
+                          const ast::EnumInstType* instType,
+                          // const ast::EnumAttrType* enumAttrType,
+                          unsigned int functionNesting)
+        : decl(decl),
+          instType{instType},
+          // attrType{enumAttrType},
+          functionNesting{functionNesting},
+          proto_linkage{ast::Linkage::Cforall} {}
+
+    void genAttrFunctions();
+    void genSuccPredPosn();
+    void genSuccPredDecl();
+
+    void appendReturnThis(ast::FunctionDecl* decl) {
+        assert(1 <= decl->params.size());
+        assert(1 == decl->returns.size());
+        assert(decl->stmts);
+
+        const CodeLocation& location = (decl->stmts->kids.empty())
+                                           ? decl->stmts->location
+                                           : decl->stmts->kids.back()->location;
+        const ast::DeclWithType* thisParam = decl->params.front();
+        decl->stmts.get_and_mutate()->push_back(new ast::ReturnStmt(
+            location, new ast::VariableExpr(location, thisParam)));
+    }
+    void genAttrStandardFuncs() {
+        ast::FunctionDecl* (EnumAttrFuncGenerator::*standardProtos[4])()
+            const = {&EnumAttrFuncGenerator::genCtorProto,
+                     &EnumAttrFuncGenerator::genCopyProto,
+                     &EnumAttrFuncGenerator::genDtorProto,
+                     &EnumAttrFuncGenerator::genAssignProto};
+        for (auto& generator : standardProtos) {
+            ast::FunctionDecl* decl = (this->*generator)();
+            produceForwardDecl(decl);
+            genFuncBody(decl);
+            if (CodeGen::isAssignment(decl->name)) {
+                appendReturnThis(decl);
+            }
+            produceDecl(decl);
+        }
+    }
+
+   private:
+    const CodeLocation& getLocation() const { return decl->location; }
+
+    ast::FunctionDecl* genProto(
+        std::string&& name, std::vector<ast::ptr<ast::DeclWithType>>&& params,
+        std::vector<ast::ptr<ast::DeclWithType>>&& returns) const;
+
+    void produceDecl(const ast::FunctionDecl* decl);
+    void produceForwardDecl(const ast::FunctionDecl* decl);
+
+    const ast::Decl* getDecl() const { return decl; }
+
+    ast::FunctionDecl* genPosnProto() const;
+    ast::FunctionDecl* genLabelProto() const;
+    ast::FunctionDecl* genValueProto() const;
+    ast::FunctionDecl* genSuccProto() const;
+    ast::FunctionDecl* genPredProto() const;
+
+    ast::FunctionDecl* genSuccPosProto() const;
+    ast::FunctionDecl* genPredPosProto() const;
+
+    // ---------------------------------------------------
+    // ast::FunctionDecl* genAttrCtorProto() const;
+    /// Changes the node inside a pointer so that it has the unused attribute.
+    void addUnusedAttribute(ast::ptr<ast::DeclWithType>& declPtr) {
+        ast::DeclWithType* decl = declPtr.get_and_mutate();
+        decl->attributes.push_back(new ast::Attribute("unused"));
+    }
+
+    ast::ObjectDecl* dstParam() const {
+        return new ast::ObjectDecl(getLocation(), "_dst",
+                                   new ast::ReferenceType(new ast::EnumAttrType(
+                                       ast::deepCopy(instType))));
+    }
+
+    ast::ObjectDecl* srcParam() const {
+        return new ast::ObjectDecl(
+            getLocation(), "_src",
+            new ast::EnumAttrType(ast::deepCopy(instType)));
+    }
+
+    /// E = EnumAttrType<T>`
+    /// `void ?{}(E & _dst)`.
+    ast::FunctionDecl* genCtorProto() const {
+        return genProto("?{}", {dstParam()}, {});
+    }
+
+    /// void ?{}(E & _dst, E _src)`.
+    ast::FunctionDecl* genCopyProto() const {
+        return genProto("?{}", {dstParam(), srcParam()}, {});
+    }
+
+    ///`void ^?{}(E & _dst)`.
+    ast::FunctionDecl* genDtorProto() const {
+        // The destructor must be mutex on a concurrent type.
+        return genProto("^?{}", {dstParam()}, {});
+    }
+
+    /// `E ?{}(E & _dst, E _src)`.
+    ast::FunctionDecl* genAssignProto() const {
+        // Only the name is different, so just reuse the generation function.
+        auto retval = srcParam();
+        retval->name = "_ret";
+        return genProto("?=?", {dstParam(), srcParam()}, {retval});
+    }
+
+    void genFuncBody(ast::FunctionDecl* func) {
+        const CodeLocation& location = func->location;
+        auto& params = func->params;
+        if (InitTweak::isCopyConstructor(func) ||
+            InitTweak::isAssignment(func)) {
+            assert(2 == params.size());
+            auto dstParam = params.front().strict_as<ast::ObjectDecl>();
+            auto srcParam = params.back().strict_as<ast::ObjectDecl>();
+            func->stmts = genCopyBody(location, dstParam, srcParam);
+        } else {
+            assert(1 == params.size());
+            // Default constructor and destructor is empty.
+            func->stmts = new ast::CompoundStmt(location);
+            // Add unused attribute to parameter to silence warnings.
+            addUnusedAttribute(params.front());
+
+            // Just an extra step to make the forward and declaration match.
+            if (forwards.empty()) return;
+            ast::FunctionDecl* fwd = strict_dynamic_cast<ast::FunctionDecl*>(
+                forwards.back().get_and_mutate());
+            addUnusedAttribute(fwd->params.front());
+        }
+    }
+
+    const ast::CompoundStmt* genCopyBody(const CodeLocation& location,
+                                         const ast::ObjectDecl* dstParam,
+                                         const ast::ObjectDecl* srcParam) {
+        // const CodeLocation& location = func->location;
+        // auto& params = func->params;
+        // assert(2 == params.size());
+        // auto dstParam = params.front().strict_as<ast::ObjectDecl>();
+        // auto srcParam = params.back().strict_as<ast::ObjectDecl>();
+        return new ast::CompoundStmt(
+            location,
+            {new ast::ExprStmt(
+                location,
+                new ast::UntypedExpr(
+                    location, new ast::NameExpr(location, "__builtin_memcpy"),
+                    {
+                        new ast::AddressExpr(location, new ast::VariableExpr(
+                                                           location, dstParam)),
+                        new ast::AddressExpr(location, new ast::VariableExpr(
+                                                           location, srcParam)),
+                        new ast::SizeofExpr(location, srcParam->type),
+                    }))});
+    }
+
+    void genDtorBody(ast::FunctionDecl* func) {
+        const CodeLocation& location = func->location;
+        auto& params = func->params;
+        assert(1 == params.size());
+        func->stmts = new ast::CompoundStmt(location);
+        addUnusedAttribute(params.front());
+
+        // Just an extra step to make the forward and declaration match.
+        if (forwards.empty()) return;
+        ast::FunctionDecl* fwd = strict_dynamic_cast<ast::FunctionDecl*>(
+            forwards.back().get_and_mutate());
+        addUnusedAttribute(fwd->params.front());
+    }
+
+    // ast::FunctionDecl*
+    // ----------------------------------------------------
+
+    ast::FunctionDecl* genSuccPredFunc(bool succ);
+
+    const ast::Init* getAutoInit(const ast::Init* prev) const;
+
+    std::vector<ast::ptr<ast::Init>> genLabelInit() const;
+
+    std::vector<ast::ptr<ast::Init>> genValueInit() const;
+    ast::ObjectDecl* genAttrArrayProto(
+        const ast::EnumAttribute attr, const CodeLocation& location,
+        std::vector<ast::ptr<ast::Init>>& inits) const;
+    void genValueOrLabelBody(ast::FunctionDecl* func,
+                             ast::ObjectDecl* arrDecl) const;
+    void genPosnBody(ast::FunctionDecl* func) const;
+    void genAttributesDecls(const ast::EnumAttribute attr);
+};
+
+std::vector<ast::ptr<ast::Init>> EnumAttrFuncGenerator::genLabelInit() const {
+    std::vector<ast::ptr<ast::Init>> inits;
+    for (size_t i = 0; i < decl->members.size(); i++) {
+        ast::ptr<ast::Decl> mem = decl->members.at(i);
+        auto memAsObjectDecl = mem.as<ast::ObjectDecl>();
+        assert(memAsObjectDecl);
+        inits.emplace_back(new ast::SingleInit(
+            mem->location,
+            ast::ConstantExpr::from_string(mem->location, mem->name)));
+    }
+    return inits;
+}
+
+std::vector<ast::ptr<ast::Init>> EnumAttrFuncGenerator::genValueInit() const {
+    std::vector<ast::ptr<ast::Init>> inits;
+    for (size_t i = 0; i < decl->members.size(); i++) {
+        ast::ptr<ast::Decl> mem = decl->members.at(i);
+        auto memAsObjectDecl = mem.as<ast::ObjectDecl>();
+        assert(memAsObjectDecl);
+        if (memAsObjectDecl->init) {
+            inits.emplace_back(memAsObjectDecl->init);
+        } else {
+            const CodeLocation& location = mem->location;
+            if (i == 0) {
+                inits.emplace_back(new ast::SingleInit(
+                    location, ast::ConstantExpr::from_int(mem->location, 0)));
+            } else {
+                inits.emplace_back(getAutoInit(inits.at(i - 1)));
+            }
+        }
+    }
+    return inits;
+}
+const ast::Init* EnumAttrFuncGenerator::getAutoInit(
+    const ast::Init* prev) const {
+    if (prev == nullptr) {
+        return new ast::SingleInit(
+            getLocation(), ast::ConstantExpr::from_int(getLocation(), 0));
+    }
+    auto prevInit = dynamic_cast<const ast::SingleInit*>(prev);
+    assert(prevInit);
+    auto prevInitExpr = prevInit->value;
+    if (auto constInit = prevInitExpr.as<ast::ConstantExpr>()) {
+        // Assume no string literal for now
+        return new ast::SingleInit(
+            getLocation(), ast::ConstantExpr::from_int(
+                               getLocation(), constInit->intValue() + 1));
+    } else {
+        auto untypedThisInit = new ast::UntypedExpr(
+            getLocation(), new ast::NameExpr(getLocation(), "?++"),
+            {prevInitExpr});
+        return new ast::SingleInit(getLocation(), untypedThisInit);
+    }
+}
+
+ast::FunctionDecl* EnumAttrFuncGenerator::genProto(
+    std::string&& name, std::vector<ast::ptr<ast::DeclWithType>>&& params,
+    std::vector<ast::ptr<ast::DeclWithType>>&& returns) const {
+    ast::FunctionDecl* decl = new ast::FunctionDecl(
+        // Auto-generated routines use the type declaration's location.
+        getLocation(), std::move(name), {}, {}, std::move(params),
+        std::move(returns),
+        // Only a prototype, no body.
+        nullptr,
+        // Use static storage if we are at the top level.
+        (0 < functionNesting) ? ast::Storage::Classes() : ast::Storage::Static,
+        proto_linkage, std::vector<ast::ptr<ast::Attribute>>(),
+        // Auto-generated routines are inline to avoid conflicts.
+        ast::Function::Specs(ast::Function::Inline));
+    decl->fixUniqueId();
+    return decl;
+}
+
+void EnumAttrFuncGenerator::produceDecl(const ast::FunctionDecl* decl) {
+    assert(nullptr != decl->stmts);
+
+    definitions.push_back(decl);
+}
+
+void EnumAttrFuncGenerator::produceForwardDecl(const ast::FunctionDecl* decl) {
+    if (0 != functionNesting) return;
+    ast::FunctionDecl* fwd =
+        (decl->stmts) ? ast::asForward(decl) : ast::deepCopy(decl);
+    fwd->fixUniqueId();
+    forwards.push_back(fwd);
+}
+
+ast::FunctionDecl* EnumAttrFuncGenerator::genPosnProto() const {
+    return genProto(
+        "posE",
+        {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
+        {new ast::ObjectDecl(getLocation(), "_ret",
+                             new ast::EnumAttrType(new ast::EnumInstType(decl),
+                                                   ast::EnumAttribute::Posn))});
+}
+
+ast::FunctionDecl* EnumAttrFuncGenerator::genLabelProto() const {
+    return genProto(
+        "labelE",
+        {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
+        {new ast::ObjectDecl(
+            getLocation(), "_ret",
+            new ast::PointerType(new ast::BasicType{ast::BasicType::Char}))});
+}
+
+ast::FunctionDecl* EnumAttrFuncGenerator::genValueProto() const {
+    return genProto(
+        "valueE",
+        {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
+        {new ast::ObjectDecl(getLocation(), "_ret",
+                             ast::deepCopy(decl->base))});
+}
+
+ast::FunctionDecl* EnumAttrFuncGenerator::genSuccProto() const {
+    return genProto(
+        "succ",
+        {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
+        {new ast::ObjectDecl(getLocation(), "_ret",
+                             new ast::EnumInstType(decl))});
+}
+
+ast::FunctionDecl* EnumAttrFuncGenerator::genPredProto() const {
+    return genProto(
+        "pred",
+        {new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
+        {new ast::ObjectDecl(getLocation(), "_ret",
+                             new ast::EnumInstType(decl))});
+}
+
+inline ast::EnumAttrType * getPosnType( const ast::EnumDecl * decl ) {
+    return new ast::EnumAttrType(new ast::EnumInstType(decl), ast::EnumAttribute::Posn);
+}
+
+ast::FunctionDecl* EnumAttrFuncGenerator::genSuccPosProto() const {
+    return genProto(
+        "_successor_",
+        {new ast::ObjectDecl(getLocation(), "_i", getPosnType(decl))},
+        {new ast::ObjectDecl(getLocation(), "_ret", getPosnType(decl))}
+    );
+}
+
+ast::FunctionDecl* EnumAttrFuncGenerator::genPredPosProto() const {
+    return genProto(
+        "_predessor_",
+        {new ast::ObjectDecl(getLocation(), "_i", getPosnType(decl))},
+        {new ast::ObjectDecl(getLocation(), "_ret", getPosnType(decl))}
+    );
+}
+
+ast::ObjectDecl* EnumAttrFuncGenerator::genAttrArrayProto(
+    const ast::EnumAttribute attr, const CodeLocation& location,
+    std::vector<ast::ptr<ast::Init>>& inits) const {
+    ast::ArrayType* arrT = new ast::ArrayType(
+        attr == ast::EnumAttribute::Value
+            ? decl->base
+            : new ast::PointerType(new ast::BasicType{ast::BasicType::Char}),
+        ast::ConstantExpr::from_int(decl->location, decl->members.size()),
+        ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim);
+
+    ast::ObjectDecl* objDecl =
+        new ast::ObjectDecl(decl->location, decl->getUnmangeldArrayName(attr),
+                            arrT, new ast::ListInit(location, std::move(inits)),
+                            ast::Storage::Static, ast::Linkage::AutoGen);
+
+    return objDecl;
+}
+
+void EnumAttrFuncGenerator::genValueOrLabelBody(
+    ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const {
+    ast::UntypedExpr* untyped = ast::UntypedExpr::createCall(
+        func->location, "?[?]",
+        {new ast::NameExpr(func->location, arrDecl->name),
+         new ast::CastExpr(
+             func->location,
+             new ast::VariableExpr(func->location, func->params.front()),
+             new ast::EnumAttrType(new ast::EnumInstType(decl),
+                                   ast::EnumAttribute::Posn))});
+    func->stmts = new ast::CompoundStmt(
+        func->location, {new ast::ReturnStmt(func->location, untyped)});
+}
+
+void EnumAttrFuncGenerator::genPosnBody(ast::FunctionDecl* func) const {
+    auto castExpr = new ast::CastExpr(
+        func->location,
+        new ast::VariableExpr(func->location, func->params.front()),
+        new ast::EnumAttrType(new ast::EnumInstType(decl),
+                              ast::EnumAttribute::Posn));
+    func->stmts = new ast::CompoundStmt(
+        func->location, {new ast::ReturnStmt(func->location, castExpr)});
+}
+
+void EnumAttrFuncGenerator::genAttributesDecls(const ast::EnumAttribute attr) {
+    if (attr == ast::EnumAttribute::Value ||
+        attr == ast::EnumAttribute::Label) {
+        std::vector<ast::ptr<ast::Init>> inits =
+            attr == ast::EnumAttribute::Value ? genValueInit() : genLabelInit();
+        ast::ObjectDecl* arrayProto =
+            genAttrArrayProto(attr, getLocation(), inits);
+        forwards.push_back(arrayProto);
+
+        ast::FunctionDecl* funcProto = attr == ast::EnumAttribute::Value
+                                           ? genValueProto()
+                                           : genLabelProto();
+        produceForwardDecl(funcProto);
+        genValueOrLabelBody(funcProto, arrayProto);
+        produceDecl(funcProto);
+    } else {
+        ast::FunctionDecl* funcProto = genPosnProto();
+        produceForwardDecl(funcProto);
+        genPosnBody(funcProto);
+        produceDecl(funcProto);
+    }
+}
+
+ast::FunctionDecl* EnumAttrFuncGenerator::genSuccPredFunc(bool succ) {
+    ast::FunctionDecl* funcDecl = succ ? genSuccPosProto() : genPredPosProto();
+    produceForwardDecl(funcDecl);
+
+    const CodeLocation& location = getLocation();
+
+    auto& params = funcDecl->params;
+    assert(params.size() == 1);
+    auto param = params.front().strict_as<ast::ObjectDecl>();
+
+
+    auto rets = funcDecl->returns;
+    assert(params.size() == 1);
+    auto ret = rets.front().strict_as<ast::ObjectDecl>();
+    auto retType = ret->type.strict_as<ast::EnumAttrType>();
+
+    auto addOneExpr = ast::UntypedExpr::createCall( location,
+        "?+?",
+        {new ast::VariableExpr(location, param),
+        ast::ConstantExpr::from_int(location, 1)}
+    );
+
+    funcDecl->stmts = new ast::CompoundStmt(
+        location, {
+            new ast::ReturnStmt(
+                location, 
+                new ast::CastExpr(location, addOneExpr, retType) 
+            )
+        }
+    );
+
+    return funcDecl;
+}
+
+void EnumAttrFuncGenerator::genAttrFunctions() {
+    if (decl->base) {
+        genAttributesDecls(ast::EnumAttribute::Value);
+        genAttributesDecls(ast::EnumAttribute::Label);
+        genAttributesDecls(ast::EnumAttribute::Posn);
+    }
+}
+
+void EnumAttrFuncGenerator::genSuccPredDecl() {
+    if (decl->base) {
+        auto succProto = genSuccProto();
+        auto predProto = genPredProto();
+
+        produceForwardDecl(succProto);
+        produceForwardDecl(predProto);
+    }
+}
+
+void EnumAttrFuncGenerator::genSuccPredPosn() {
+    if (decl->base) {
+        ast::FunctionDecl* succ = genSuccPredFunc(true);
+        ast::FunctionDecl* pred = genSuccPredFunc(false);
+
+        produceDecl(succ);
+        produceDecl(pred);
+    }
+}
+
+void EnumAttrFuncGenerator::generateAndAppendFunctions(
+    std::list<ast::ptr<ast::Decl>>& decls) {
+    // Generate the functions (they go into forwards and definitions).
+    genAttrStandardFuncs();
+    genAttrFunctions();
+    genSuccPredDecl();
+    genSuccPredPosn(); // Posn
+    // Now export the lists contents.
+    decls.splice(decls.end(), forwards);
+    decls.splice(decls.end(), definitions);
+}
+
+// ---------------------------------------------------------
+
+struct ImplementEnumFunc final : public ast::WithDeclsToAdd<>,
+                                 public ast::WithShortCircuiting {
+    void previsit(const ast::EnumDecl* enumDecl);
+    void previsit(const ast::FunctionDecl* functionDecl);
+    void postvisit(const ast::FunctionDecl* functionDecl);
+
+   private:
+    // Current level of nested functions.
+    unsigned int functionNesting = 0;
+};
+
+void ImplementEnumFunc::previsit(const ast::EnumDecl* enumDecl) {
+    if (!enumDecl->body) return;
+    if (!enumDecl->base) return;
+
+    ast::EnumInstType enumInst(enumDecl->name);
+    enumInst.base = enumDecl;
+    // ast::EnumAttrType attr = ast::EnumAttrType(&enumInst);
+    // EnumAttrFuncGenerator gen(enumDecl, &enumInst functionNesting);
+    EnumAttrFuncGenerator gen(enumDecl, &enumInst, functionNesting);
+    gen.generateAndAppendFunctions(declsToAddAfter);
+}
+
+void ImplementEnumFunc::previsit(const ast::FunctionDecl*) {
+    functionNesting += 1;
+}
+
+void ImplementEnumFunc::postvisit(const ast::FunctionDecl*) {
+    functionNesting -= 1;
+}
+
+}  // namespace
+
+void implementEnumFunc(ast::TranslationUnit& translationUnit) {
+    ast::Pass<ImplementEnumFunc>::run(translationUnit);
+}
+}  // namespace Validate
Index: src/Validate/ImplementEnumFunc.hpp
===================================================================
--- src/Validate/ImplementEnumFunc.hpp	(revision af746ccdf606483f8f89907b52e8b9471c72df7c)
+++ src/Validate/ImplementEnumFunc.hpp	(revision af746ccdf606483f8f89907b52e8b9471c72df7c)
@@ -0,0 +1,9 @@
+#pragma once
+
+namespace ast {
+    class TranslationUnit;
+}
+
+namespace Validate {
+    void implementEnumFunc( ast::TranslationUnit & translationUnit );
+}
Index: src/Validate/ReplacePseudoFunc.cpp
===================================================================
--- src/Validate/ReplacePseudoFunc.cpp	(revision 76fe046c5d7501192d849b5595c9079478c38b0b)
+++ src/Validate/ReplacePseudoFunc.cpp	(revision af746ccdf606483f8f89907b52e8b9471c72df7c)
@@ -16,324 +16,4 @@
 
 namespace {
-
-std::set<std::string> queryLabels;
-std::set<std::string> queryValues;
-
-struct ReplaceEnumInstWithPos final : public ast::WithShortCircuiting {
-    const ast::ObjectDecl* postvisit(const ast::ObjectDecl* decl) {
-        auto enumInst = decl->type.strict_as<ast::EnumInstType>();
-        auto enumPos = new ast::EnumPosType(enumInst);
-        auto ret = ast::mutate_field(decl, &ast::ObjectDecl::type, enumPos);
-        ret = ast::mutate_field(ret, &ast::ObjectDecl::mangleName,
-                                Mangle::mangle(ret));
-        return ret;
-    }
-};
-
-const inline std::string getValueArrayName(std::string enumName) {
-    return "values_" + enumName;
-}
-
-// struct AutoInit {
-//     ast::EnumDecl const* postvisit( const ast::EnumDecl* expr );
-// };
-
-struct WrapEnumValueExpr final : public ast::WithShortCircuiting,
-                                 public ast::WithSymbolTable,
-                                 public ast::WithConstTranslationUnit {
-    void previsit(const ast::DeclStmt* expr);
-    void previsit(const ast::ApplicationExpr* expr);
-    void previsit(const ast::CastExpr* expr);
-    void previsit(const ast::VariableExpr*) { visit_children = false; }
-
-    ast::Expr const* postvisit(const ast::VariableExpr* expr);
-};
-
-struct FindGenEnumArray final : public ast::WithShortCircuiting {
-    void previsit(const ast::ApplicationExpr* enumDecl);
-};
-
-struct PseudoFuncGenerateRoutine final : public ast::WithDeclsToAdd<>,
-                                         public ast::WithSymbolTable,
-                                         public ast::WithShortCircuiting,
-                                         public ast::WithConstTranslationUnit {
-    void previsit(const ast::EnumDecl* enumDecl);
-};
-
-struct ReplacePseudoFuncCore : public ast::WithShortCircuiting,
-                               public ast::WithSymbolTable,
-                               public ast::WithConstTranslationUnit {
-    ast::Expr const* postvisit(ast::ApplicationExpr const* decl);
-};
-
-// ast::EnumDecl const * AutoInit::postvisit( const ast::EnumDecl * expr ) {
-//     for ( size_t i = 0; i < expr->members.size(); i++ ) {
-//         auto mem = expr->members[i].as<ast::ObjectDecl>();
-//         assert( mem );
-//         if ( mem->init )
-//     }
-//     return expr;
-// }
-
-void WrapEnumValueExpr::previsit(const ast::ApplicationExpr* expr) {
-    auto varExpr = expr->func.as<ast::VariableExpr>();
-    auto fname = ast::getFunctionName(expr);
-    if (!varExpr || varExpr->var->linkage == ast::Linkage::Intrinsic) {
-        if (fname == "?{}" || fname == "?=?") visit_children = false;
-    }
-
-    if (fname == "labelE" || fname == "valueE" || fname == "posE" ||
-        fname == "pred" || fname == "succ") {
-        visit_children = false;
-    }
-}
-
-void WrapEnumValueExpr::previsit(const ast::DeclStmt*) {
-    visit_children = false;
-}
-
-void WrapEnumValueExpr::previsit(const ast::CastExpr* expr) {
-    if (expr->result && expr->result.as<ast::ReferenceType>()) {
-        visit_children = false;
-    }
-}
-
-ast::Expr const* WrapEnumValueExpr::postvisit(const ast::VariableExpr* expr) {
-    if (!expr->result) {
-        return expr;
-    }
-    if (auto enumInst = expr->result.as<ast::EnumInstType>()) {
-        if (enumInst->base && enumInst->base->base) {
-            auto untyped = new ast::UntypedExpr(
-                expr->location, new ast::NameExpr(expr->location, "valueE"),
-                {std::move(expr)});
-            ResolvExpr::ResolveContext context{symtab, transUnit().global};
-            auto result = ResolvExpr::findVoidExpression(untyped, context);
-            ast::ptr<ast::ApplicationExpr> ret =
-                result.strict_as<ast::ApplicationExpr>();
-            return ast::deepCopy(ret);
-        }
-    }
-    return expr;
-}
-
-void FindGenEnumArray::previsit(const ast::ApplicationExpr* expr) {
-    auto fname = ast::getFunctionName(expr);
-    if (fname == "labelE" || fname == "valueE") {
-        if (expr->args.size() != 1) {
-            SemanticError(expr, "Position Expression only take one parameter");
-        }
-        const ast::VariableExpr* arg =
-            expr->args.front().as<const ast::VariableExpr>();
-        if (!arg) {
-            SemanticError(expr, "Unimplement Pseudo Function Cases");
-        }
-        const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>();
-        const std::string referredName = argAsVar->name;
-        const ast::EnumInstType* argType =
-            argAsVar->type.as<const ast::EnumInstType>();
-        if (!argType) {
-            SemanticError(
-                argAsVar,
-                "Position can only be used on an enumeration instance");
-        }
-        ast::ptr<ast::EnumDecl> base = argType->base;
-        assert(base);
-        if (fname == "labelE") queryLabels.insert(base->name);
-        if (fname == "valueE") queryValues.insert(base->name);
-    }
-}
-
-const ast::Init* getAutoInit(const CodeLocation& location,
-                             const ast::Type* type,
-                             ResolvExpr::ResolveContext context,
-                             const ast::Init* prev) {
-    if (auto prevInit = dynamic_cast<const ast::SingleInit*>(prev)) {
-        auto prevInitExpr = prevInit->value;
-        if (auto constInit = prevInitExpr.as<ast::ConstantExpr>()) {
-            // Assume no string literal for now
-            return new ast::SingleInit(
-                location, ast::ConstantExpr::from_int(
-                              location, constInit->intValue() + 1));
-        } else {
-            auto untypedThisInit = new ast::UntypedExpr(
-                location, new ast::NameExpr(location, "?++"), {prevInitExpr});
-            auto typedInit = ResolvExpr::findSingleExpression(untypedThisInit,
-                                                              type, context);
-            return new ast::SingleInit(location, typedInit);
-        }
-    }
-    SemanticError(prev, "Auto Init a List is not implemented");
-    return prev;
-}
-
-void PseudoFuncGenerateRoutine::previsit(const ast::EnumDecl* enumDecl) {
-    visit_children = false;
-    const CodeLocation& location = enumDecl->location;
-    if (enumDecl->members.size() == 0 || !enumDecl->base) return;
-
-    std::vector<ast::ptr<ast::Init>> inits;
-    std::vector<ast::ptr<ast::Init>> labels;
-    auto type = enumDecl->base;
-
-    for (size_t i = 0; i < enumDecl->members.size(); i++) {
-        ast::ptr<ast::Decl> mem = enumDecl->members.at(i);
-        auto memAsObjectDecl = mem.as<ast::ObjectDecl>();
-        assert(memAsObjectDecl);
-        if (memAsObjectDecl->init) {
-            inits.emplace_back(memAsObjectDecl->init);
-        } else {
-            const CodeLocation& location = mem->location;
-            if (i == 0) {
-                inits.emplace_back(new ast::SingleInit(
-                    location, ast::ConstantExpr::from_int(mem->location, 0)));
-            } else {
-                inits.emplace_back(getAutoInit(
-                    location, enumDecl->base,
-                    ResolvExpr::ResolveContext{symtab, transUnit().global},
-                    inits.at(i - 1).as<ast::SingleInit>()));
-            }
-        }
-        labels.emplace_back(new ast::SingleInit(
-            location, ast::ConstantExpr::from_string(location, mem->name)));
-    }
-    if (queryValues.count(enumDecl->name)) {
-        auto init = new ast::ListInit(location, std::move(inits));
-        const ast::ArrayType* arrT = new ast::ArrayType(
-            enumDecl->base,
-            ast::ConstantExpr::from_int(location, enumDecl->members.size()),
-            ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim);
-        ast::ObjectDecl* values = new ast::ObjectDecl(
-            location, "values_" + enumDecl->name, arrT, init,
-            ast::Storage::Static, ast::Linkage::AutoGen);
-        symtab.addId(values);
-        values->mangleName = Mangle::mangle(values);
-        declsToAddAfter.push_back(values);
-    }
-    if (queryLabels.count(enumDecl->name)) {
-        auto label_strings = new ast::ListInit(location, std::move(labels));
-        auto labels = new ast::ObjectDecl(
-            location, "labels_" + enumDecl->name,
-            new ast::ArrayType(
-                new ast::PointerType(new ast::BasicType{ast::BasicType::Char}),
-                ast::ConstantExpr::from_int(location, enumDecl->members.size()),
-                ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim),
-            label_strings, ast::Storage::Static, ast::Linkage::AutoGen);
-        symtab.addId(labels);
-        labels->mangleName = Mangle::mangle(labels);
-        declsToAddAfter.push_back(labels);
-    }
-}
-
-ast::ApplicationExpr const* resolveAttributeFunctions(
-    const CodeLocation location, ResolvExpr::ResolveContext context,
-    const ast::VariableExpr* arg, const ast::EnumDecl* base,
-    const std::string& name) {
-    ast::Expr* toResolve = new ast::NameExpr(location, name + base->name);
-    // Find the request arrary
-    auto arr = ResolvExpr::findVoidExpression(toResolve, context);
-    assert(arr.get());
-    auto arrAsVar = arr.strict_as<ast::VariableExpr>();
-    // change EnumInstType to EnumPosType to avoid recursive resolution
-    auto argAsDecl = arg->var.as<ast::ObjectDecl>();
-    if (argAsDecl->type.as<ast::EnumInstType>()) {
-        ast::Pass<ReplaceEnumInstWithPos> replacer;
-        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, "?[?]"),
-                                 {std::move(arrAsVar), mutatedArg});
-        auto typedResult = ResolvExpr::findVoidExpression(untyped, context);
-        ast::ptr<ast::ApplicationExpr> ret =
-            typedResult.strict_as<ast::ApplicationExpr>();
-        return ast::deepCopy(ret);
-    } else {
-        auto untyped =
-            new ast::UntypedExpr(location, new ast::NameExpr(location, "?[?]"),
-                                 {std::move(arrAsVar), arg});
-        auto typedResult = ResolvExpr::findVoidExpression(untyped, context);
-
-        ast::ptr<ast::ApplicationExpr> ret =
-            typedResult.strict_as<ast::ApplicationExpr>();
-        return ast::deepCopy(ret);
-    }
-}
-
-ast::Expr const* ReplacePseudoFuncCore::postvisit(
-    ast::ApplicationExpr const* expr) {
-    auto fname = ast::getFunctionName(expr);
-    auto location = expr->location;
-    if (fname == "posE" || fname == "valueE" || fname == "labelE") {
-        if (expr->args.size() != 1) {
-            SemanticError(expr,
-                          "Pseudo Enum Expression only take one parameter");
-        }
-        ast::ptr<ast::VariableExpr> arg =
-            expr->args.front().as<const ast::VariableExpr>();
-        if (!arg) {
-            SemanticError(expr, "Unimplement Pseudo Function Cases");
-        }
-        const ast::ObjectDecl* argAsVar = arg->var.as<const ast::ObjectDecl>();
-        const std::string referredName = argAsVar->name;
-
-        if (const ast::EnumInstType* argTypeAsEnumInst =
-                argAsVar->type.as<const ast::EnumInstType>()) {
-            const ast::EnumDecl* base = argTypeAsEnumInst->base;
-            ResolvExpr::ResolveContext context{symtab, transUnit().global};
-            // If resolvable as constant
-            for (size_t i = 0; i < base->members.size(); i++) {
-                if (base->members[i]->name == referredName) {
-                    if (fname == "posE")
-                        return ast::ConstantExpr::from_int(expr->location, i);
-                    else if (fname == "labelE")
-                        return ast::ConstantExpr::from_string(expr->location,
-                                                              referredName);
-                    else {
-                        return resolveAttributeFunctions(
-                            location, context, arg.get(), base, "values_");
-                    }
-                }
-            }
-
-            if (fname == "labelE") {
-                if (auto labelExpr = resolveAttributeFunctions(
-                        location, context, arg.get(), base, "labels_")) {
-                    return labelExpr;
-                }
-            } else if (fname == "valueE") {
-                if (auto valueExpr = resolveAttributeFunctions(
-                        location, context, arg.get(), base, "values_")) {
-                    return valueExpr;
-                }
-            } else {  // it is position; replace itself
-                return std::move(arg.get());
-            }
-        } else if (const ast::EnumPosType* argTypeAsPos =
-                       argAsVar->type.as<const ast::EnumPosType>()) {
-            const ast::EnumDecl* base = argTypeAsPos->instance->base;
-            ResolvExpr::ResolveContext context{symtab, transUnit().global};
-            if (fname == "labelE") {
-                if (auto labelExpr = resolveAttributeFunctions(
-                        location, context, arg.get(), base, "labels_")) {
-                    return labelExpr;
-                }
-            } else if (fname == "valueE") {
-                if (auto valueExpr = resolveAttributeFunctions(
-                        location, context, arg.get(), base, "values_")) {
-                    return valueExpr;
-                }
-            } else {  // it is position; replace itself
-                return std::move(arg.get());
-            }
-        } else {
-            SemanticError(argAsVar,
-                          "Pseudo Enum Expression can only be used on an "
-                          "enumeration instance");
-        }
-    }
-    return expr;
-}
 
 ast::ptr<ast::Expr> reduceCastExpr(ast::ptr<ast::Expr> expr) {
@@ -357,5 +37,6 @@
                     if (auto enumInst =
                             argAsDecl->type.as<ast::EnumInstType>()) {
-                        auto castTo = new ast::EnumPosType(enumInst);
+                        auto castTo = new ast::EnumAttrType(
+                            enumInst, ast::EnumAttribute::Posn);
                         auto castExpr =
                             new ast::CastExpr(param->location, param, castTo);
@@ -375,42 +56,6 @@
                         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);
+                                   argAsDecl->type.as<ast::EnumAttrType>()) {
+                        std::cerr << "PseudoFunc: succ/pred should not be applied on EnumAttrType directly" << std::endl;
                     }
                 }
@@ -424,10 +69,4 @@
 
 void replacePseudoFunc(ast::TranslationUnit& translationUnit) {
-    ast::Pass<WrapEnumValueExpr>::run(translationUnit);
-    ast::Pass<FindGenEnumArray>::run(translationUnit);
-
-    ast::Pass<PseudoFuncGenerateRoutine>::run(translationUnit);
-    ast::Pass<ReplacePseudoFuncCore>::run(translationUnit);
-
     ast::Pass<ReplaceSuccAndPred>::run(translationUnit);
 }
Index: src/Validate/module.mk
===================================================================
--- src/Validate/module.mk	(revision 76fe046c5d7501192d849b5595c9079478c38b0b)
+++ src/Validate/module.mk	(revision af746ccdf606483f8f89907b52e8b9471c72df7c)
@@ -54,5 +54,7 @@
 	Validate/VerifyCtorDtorAssign.hpp \
 	Validate/ReplacePseudoFunc.cpp \
-	Validate/ReplacePseudoFunc.hpp
+	Validate/ReplacePseudoFunc.hpp \
+	Validate/ImplementEnumFunc.cpp \
+	Validate/ImplementEnumFunc.hpp
 
 SRCDEMANGLE += $(SRC_VALIDATE)
