Index: src/AST/Fwd.hpp
===================================================================
--- src/AST/Fwd.hpp	(revision c17dc80e8b27ae7339c64fb486e005e85e49377f)
+++ src/AST/Fwd.hpp	(revision 0522ebe7b3ae7204a1d2c50a1bc7273bfa36762a)
@@ -133,4 +133,5 @@
 class OneType;
 class GlobalScopeType;
+class EnumPosType;
 
 class Designation;
Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision c17dc80e8b27ae7339c64fb486e005e85e49377f)
+++ src/AST/Pass.hpp	(revision 0522ebe7b3ae7204a1d2c50a1bc7273bfa36762a)
@@ -222,4 +222,5 @@
 	const ast::Type *             visit( const ast::UnionInstType        * ) override final;
 	const ast::Type *             visit( const ast::EnumInstType         * ) override final;
+	const ast::Type *             visit( const ast::EnumPosType          * ) override final;
 	const ast::Type *             visit( const ast::TraitInstType        * ) override final;
 	const ast::Type *             visit( const ast::TypeInstType         * ) override final;
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision c17dc80e8b27ae7339c64fb486e005e85e49377f)
+++ src/AST/Pass.impl.hpp	(revision 0522ebe7b3ae7204a1d2c50a1bc7273bfa36762a)
@@ -1986,4 +1986,13 @@
 
 //--------------------------------------------------------------------------
+// EnumPosType
+template< typename core_t >
+const ast::Type * ast::Pass< core_t >::visit( const ast::EnumPosType * node ) {
+	VISIT_START( node );
+
+	VISIT_END( Type, node );
+}
+
+//--------------------------------------------------------------------------
 // TraitInstType
 template< typename core_t >
Index: src/AST/Print.cpp
===================================================================
--- src/AST/Print.cpp	(revision c17dc80e8b27ae7339c64fb486e005e85e49377f)
+++ src/AST/Print.cpp	(revision 0522ebe7b3ae7204a1d2c50a1bc7273bfa36762a)
@@ -1576,4 +1576,11 @@
 	}
 
+	virtual const ast::Type * visit( const ast::EnumPosType * node ) override final {
+		preprint( node );
+		os << "enum pos with ";
+		(*(node->instance)).accept( *this );
+		return node;
+	}
+
 	virtual const ast::Type * visit( const ast::TraitInstType * node ) override final {
 		preprint( node );
Index: src/AST/Type.hpp
===================================================================
--- src/AST/Type.hpp	(revision c17dc80e8b27ae7339c64fb486e005e85e49377f)
+++ src/AST/Type.hpp	(revision 0522ebe7b3ae7204a1d2c50a1bc7273bfa36762a)
@@ -362,4 +362,15 @@
 using EnumInstType = SueInstType<EnumDecl>;
 
+class EnumPosType final : public Type {
+public:
+	readonly<EnumInstType> instance;
+	const Type * accept( Visitor & v ) const override { return v.visit( this ); }
+	EnumPosType( const EnumInstType * instance ): instance(instance) {}
+	
+private:
+	EnumPosType * clone() const override { return new EnumPosType{ *this }; }
+	MUTATE_FRIEND
+};
+
 /// An instance of a trait type.
 class TraitInstType final : public BaseInstType {
Index: src/AST/Visitor.hpp
===================================================================
--- src/AST/Visitor.hpp	(revision c17dc80e8b27ae7339c64fb486e005e85e49377f)
+++ src/AST/Visitor.hpp	(revision 0522ebe7b3ae7204a1d2c50a1bc7273bfa36762a)
@@ -119,4 +119,5 @@
     virtual const ast::Type *             visit( const ast::OneType              * ) = 0;
     virtual const ast::Type *             visit( const ast::GlobalScopeType      * ) = 0;
+    virtual const ast::Type *             visit( const ast::EnumPosType          * ) = 0;
     virtual const ast::Designation *      visit( const ast::Designation          * ) = 0;
     virtual const ast::Init *             visit( const ast::SingleInit           * ) = 0;
Index: src/CodeGen/GenType.cc
===================================================================
--- src/CodeGen/GenType.cc	(revision c17dc80e8b27ae7339c64fb486e005e85e49377f)
+++ src/CodeGen/GenType.cc	(revision 0522ebe7b3ae7204a1d2c50a1bc7273bfa36762a)
@@ -46,4 +46,5 @@
 	void postvisit( ast::UnionInstType const * type );
 	void postvisit( ast::EnumInstType const * type );
+	void postvisit( ast::EnumPosType const * type );
 	void postvisit( ast::TypeInstType const * type );
 	void postvisit( ast::TupleType const * type );
@@ -239,4 +240,8 @@
 }
 
+void GenType::postvisit( ast::EnumPosType const * type ) {
+	postvisit( type->instance );
+}
+
 void GenType::postvisit( ast::TypeInstType const * type ) {
 	assertf( !options.genC, "TypeInstType should not reach code generation." );
Index: src/Common/CodeLocationTools.cpp
===================================================================
--- src/Common/CodeLocationTools.cpp	(revision c17dc80e8b27ae7339c64fb486e005e85e49377f)
+++ src/Common/CodeLocationTools.cpp	(revision 0522ebe7b3ae7204a1d2c50a1bc7273bfa36762a)
@@ -188,4 +188,5 @@
     macro(UnionInstType, Type) \
     macro(EnumInstType, Type) \
+    macro(EnumPosType, Type) \
     macro(TraitInstType, Type) \
     macro(TypeInstType, Type) \
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision c17dc80e8b27ae7339c64fb486e005e85e49377f)
+++ src/Parser/parser.yy	(revision 0522ebe7b3ae7204a1d2c50a1bc7273bfa36762a)
@@ -3006,4 +3006,10 @@
 	| assertion_list
 		{ $$ = DeclarationNode::newTypeParam( ast::TypeDecl::Dtype, new string( DeclarationNode::anonymous.newName() ) )->addAssertions( $1 ); }
+	| ENUM '(' identifier_or_type_name ')' identifier_or_type_name new_type_class type_initializer_opt assertion_list_opt
+		{	
+			typedefTable.addToScope( *$3, TYPEDIMname, "type_parameter 4" );
+			typedefTable.addToScope( *$5, TYPEDIMname, "type_parameter 5" );
+			$$ = DeclarationNode::newTypeParam( $6, $5 )->addTypeInitializer( $7 )->addAssertions( $8 );
+		}
 	;
 
Index: src/ResolvExpr/CandidateFinder.cpp
===================================================================
--- src/ResolvExpr/CandidateFinder.cpp	(revision c17dc80e8b27ae7339c64fb486e005e85e49377f)
+++ src/ResolvExpr/CandidateFinder.cpp	(revision 0522ebe7b3ae7204a1d2c50a1bc7273bfa36762a)
@@ -893,17 +893,60 @@
 		} 
 		else if ( auto enumInst = aggrExpr->result.as< ast::EnumInstType >() ) {
-			// The Attribute Arrays are not yet generated, need to proxy them
-			// as attribute function call
-			const CodeLocation & location = cand->expr->location;
-			if ( enumInst->base && enumInst->base->base ) {
-				auto valueName = new ast::NameExpr(location, "valueE");
-				auto untypedValueCall = new ast::UntypedExpr( 
-					location, valueName, { aggrExpr } );
-				auto result = ResolvExpr::findVoidExpression( untypedValueCall, context );
-				assert( result.get() );
-				CandidateRef newCand = std::make_shared<Candidate>(
-					*cand, result, Cost::safe );
-				candidates.emplace_back( std::move( newCand ) );
-			}
+			if (enumInst->base && enumInst->base->base) {
+            const CodeLocation &location = cand->expr->location;
+
+            CandidateFinder funcFinder(context, tenv);
+            auto nameExpr = new ast::NameExpr(location, "valueE");
+            ResolveMode mode = {true, false, selfFinder.candidates.empty()};
+            funcFinder.find( nameExpr, mode );
+
+            // make variableExpr itself the candidate for the value Call
+            ExplodedArgs argExpansions;
+            argExpansions.emplace_back();
+            auto &argE = argExpansions.back();
+
+            argE.emplace_back(*cand, symtab); // Use the typed name expr as param for value
+
+            CandidateList found;
+            SemanticErrorException errors;
+
+            for (CandidateRef &func : funcFinder) {
+                try {
+                    const ast::Type *funcResult =
+                        func->expr->result->stripReferences();
+                    if (auto pointer = dynamic_cast<const ast::PointerType *>(
+                            funcResult)) {
+                        if (auto function =
+                                pointer->base.as<ast::FunctionType>()) {
+                            CandidateRef newFunc{new Candidate{*func}};
+                            newFunc->expr = referenceToRvalueConversion(
+                                newFunc->expr, newFunc->cost);
+                            makeFunctionCandidates( location,
+                                                   newFunc, function,
+                                                   argExpansions, found );
+                        }
+                    }
+                } catch (SemanticErrorException &e) {
+                    std::cerr
+                        << "Resolving value function should cause an error"
+                        << std::endl;
+                    errors.append(e);
+                }
+            }
+
+            if (found.empty()) {
+                std::cerr << "Resolve value function should always success"
+                          << std::endl;
+            }
+
+            for (CandidateRef &withFunc : found) {
+                withFunc->cost.incSafe();
+                Cost cvtCost =
+                    computeApplicationConversionCost(withFunc, symtab);
+                assert(cvtCost != Cost::infinity);
+
+                candidates.emplace_back(std::move(withFunc));
+            }
+        }
 		}
 	}
@@ -1401,8 +1444,70 @@
 	}
 
-	void Finder::postvisit( const ast::VariableExpr * variableExpr ) {
-		// not sufficient to just pass `variableExpr` here, type might have changed since
-		addCandidate( variableExpr, tenv );		
-	}
+    void Finder::postvisit(const ast::VariableExpr *variableExpr) {
+        // not sufficient to just pass `variableExpr` here, type might have changed
+
+        auto cand = new Candidate(variableExpr, tenv);
+        candidates.emplace_back(cand);
+
+        if (auto enumInst = dynamic_cast<const ast::EnumInstType *>(
+                variableExpr->var->get_type())) {
+            if (enumInst->base && enumInst->base->base) {
+                const CodeLocation &location = cand->expr->location;
+
+                CandidateFinder funcFinder(context, tenv);
+                auto nameExpr = new ast::NameExpr(location, "valueE");
+                ResolveMode mode = {true, false, selfFinder.candidates.empty()};
+                funcFinder.find( nameExpr, mode );
+
+                // make variableExpr itself the candidate for the value Call
+                ExplodedArgs argExpansions;
+                argExpansions.emplace_back();
+                auto &argE = argExpansions.back();
+
+                argE.emplace_back(*cand, symtab);
+
+                CandidateList found;
+                SemanticErrorException errors;
+
+                for (CandidateRef &func : funcFinder) {
+                    try {
+                    const ast::Type *funcResult =
+                        func->expr->result->stripReferences();
+                    if (auto pointer = dynamic_cast<const ast::PointerType *>(
+                            funcResult)) {
+                        if (auto function =
+                                pointer->base.as<ast::FunctionType>()) {
+                            CandidateRef newFunc{new Candidate{*func}};
+                            newFunc->expr = referenceToRvalueConversion(
+                                newFunc->expr, newFunc->cost);
+                            makeFunctionCandidates(variableExpr->location,
+                                                   newFunc, function,
+                                                   argExpansions, found);
+                        }
+                    }
+                    } catch (SemanticErrorException &e) {
+                        std::cerr
+                            << "Resolving value function should cause an error"
+                            << std::endl;
+                        errors.append(e);
+                    }
+                }
+
+                if (found.empty()) {
+                    std::cerr << "Resolve value function should always success"
+                            << std::endl;
+                }
+
+                for (CandidateRef &withFunc : found) {
+                    withFunc->cost.incSafe();
+                    Cost cvtCost =
+                        computeApplicationConversionCost(withFunc, symtab);
+                    assert(cvtCost != Cost::infinity);
+
+                    candidates.emplace_back(std::move(withFunc));
+                }
+            }
+        }
+    }
 
 	void Finder::postvisit( const ast::ConstantExpr * constantExpr ) {
Index: src/ResolvExpr/CommonType.cc
===================================================================
--- src/ResolvExpr/CommonType.cc	(revision c17dc80e8b27ae7339c64fb486e005e85e49377f)
+++ src/ResolvExpr/CommonType.cc	(revision 0522ebe7b3ae7204a1d2c50a1bc7273bfa36762a)
@@ -397,4 +397,14 @@
 					result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers };
 				}
+			}
+		} else if ( const ast::EnumPosType * pos = dynamic_cast< const ast::EnumPosType * >( type2 ) ) {
+			ast::BasicType::Kind kind = commonTypes[ basic->kind ][ ast::BasicType::SignedInt ];
+			if (
+				( ( kind == basic->kind && basic->qualifiers >= type2->qualifiers )
+					|| widen.first )
+				&& ( ( kind != basic->kind && basic->qualifiers <= type2->qualifiers )
+					|| widen.second )
+			) {
+				result = new ast::BasicType{ kind, basic->qualifiers | type2->qualifiers };
 			}
 		}
Index: src/ResolvExpr/ConversionCost.cc
===================================================================
--- src/ResolvExpr/ConversionCost.cc	(revision c17dc80e8b27ae7339c64fb486e005e85e49377f)
+++ src/ResolvExpr/ConversionCost.cc	(revision 0522ebe7b3ae7204a1d2c50a1bc7273bfa36762a)
@@ -278,9 +278,11 @@
 	if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) {
 		conversionCostFromBasicToBasic( basicType, dstAsBasic );
-	} else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
+	} 
+	else if ( const ast::EnumInstType * enumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
 		auto enumDecl = enumInst->base;
-		if ( auto baseType = enumDecl->base.get() ) {
-			cost = costCalc( basicType, baseType, srcIsLvalue, symtab, env );
-			cost.incUnsafe();
+		if ( enumDecl->base.get() ) {
+			// cost = costCalc( basicType, baseType, srcIsLvalue, symtab, env );
+			// cost.incUnsafe();
+			cost = Cost::infinity;
 		} else {
             cost = Cost::unsafe;
@@ -365,4 +367,12 @@
 	cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
 	// }
+	if ( cost < Cost::unsafe ) {
+		cost.incSafe();
+	}
+}
+
+void ConversionCost::postvisit( const ast::EnumPosType * ) {
+	static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
+	cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
 	if ( cost < Cost::unsafe ) {
 		cost.incSafe();
Index: src/ResolvExpr/ConversionCost.h
===================================================================
--- src/ResolvExpr/ConversionCost.h	(revision c17dc80e8b27ae7339c64fb486e005e85e49377f)
+++ src/ResolvExpr/ConversionCost.h	(revision 0522ebe7b3ae7204a1d2c50a1bc7273bfa36762a)
@@ -72,4 +72,5 @@
 	void postvisit( const ast::ZeroType * zeroType );
 	void postvisit( const ast::OneType * oneType );
+	void postvisit( const ast::EnumPosType * posType );
 private:
 	// refactor for code resue
Index: src/ResolvExpr/Unify.cc
===================================================================
--- src/ResolvExpr/Unify.cc	(revision c17dc80e8b27ae7339c64fb486e005e85e49377f)
+++ src/ResolvExpr/Unify.cc	(revision 0522ebe7b3ae7204a1d2c50a1bc7273bfa36762a)
@@ -517,4 +517,9 @@
 		}
 
+		void postvisit( const ast::EnumPosType * posType ) {
+			// Does nothing for now. Handled in ReplacePseudoFunc
+			// Might move here in the future
+		}
+
 		void postvisit( const ast::TraitInstType * aggrType ) {
 			handleRefType( aggrType, type2 );
Index: src/SymTab/Mangler.cc
===================================================================
--- src/SymTab/Mangler.cc	(revision c17dc80e8b27ae7339c64fb486e005e85e49377f)
+++ src/SymTab/Mangler.cc	(revision 0522ebe7b3ae7204a1d2c50a1bc7273bfa36762a)
@@ -59,4 +59,6 @@
 	void postvisit( const ast::QualifiedType * qualType );
 
+	void postvisit( const ast::EnumPosType * posType );
+
 	/// The result is the current constructed mangled name.
 	std::string result() const { return mangleName; }
@@ -277,4 +279,9 @@
 	assertf( decl->kind < ast::TypeDecl::Kind::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
 	mangleName += Encoding::typeVariables[ decl->kind ] + std::to_string( decl->name.length() ) + decl->name;
+}
+
+void Mangler::postvisit( const ast::EnumPosType * pos ) {
+	postvisit( pos->instance );
+	mangleName += "_pos";
 }
 
Index: src/Validate/Autogen.cpp
===================================================================
--- src/Validate/Autogen.cpp	(revision c17dc80e8b27ae7339c64fb486e005e85e49377f)
+++ src/Validate/Autogen.cpp	(revision 0522ebe7b3ae7204a1d2c50a1bc7273bfa36762a)
@@ -206,4 +206,5 @@
 	ast::FunctionDecl * genLabelProto() const;
 	ast::FunctionDecl * genValueProto() const;
+	// ast::FunctionDecl * genValueProto2() const;
 };
 
@@ -790,9 +791,17 @@
 }
 
+// ast::FunctionDecl * EnumFuncGenerator::genValueProto2() const {
+// 	return genProto( "valueE", 
+// 		{ new ast::ObjectDecl( getLocation(), "_i", new ast::EnumPosType( new ast::EnumInstType( decl ) ) )},
+// 		{ new ast::ObjectDecl( getLocation(), "_ret", ast::deepCopy( decl->base ) ) } );
+// }
+
 void EnumFuncGenerator::genAttrFuncForward() {	
 	if ( decl->base ) {
 		ast::FunctionDecl *(EnumFuncGenerator::*attrProtos[3])() const = {
 			&EnumFuncGenerator::genPosProto, &EnumFuncGenerator::genLabelProto, 
-			&EnumFuncGenerator::genValueProto };
+			&EnumFuncGenerator::genValueProto
+			// , &EnumFuncGenerator::genValueProto2 
+			};
 		for ( auto & generator : attrProtos ) {
 			produceForwardDecl( (this->*generator)() );
Index: src/Validate/ReplacePseudoFunc.cpp
===================================================================
--- src/Validate/ReplacePseudoFunc.cpp	(revision c17dc80e8b27ae7339c64fb486e005e85e49377f)
+++ src/Validate/ReplacePseudoFunc.cpp	(revision 0522ebe7b3ae7204a1d2c50a1bc7273bfa36762a)
@@ -6,13 +6,11 @@
 #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"
 
-#include "AST/Print.hpp"
-
-#include "ResolvExpr/CandidateFinder.hpp"
-
 namespace Validate {
 
@@ -21,4 +19,20 @@
 std::set<std::string> queryLabels;
 std::set<std::string> queryValues;
+
+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>();
+        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 {
@@ -32,5 +46,5 @@
     void previsit(const ast::ApplicationExpr* expr);
     void previsit(const ast::CastExpr* expr);
-    void previsit(const ast::VariableExpr* ) { visit_children = false; }
+    void previsit(const ast::VariableExpr*) { visit_children = false; }
 
     ast::Expr const* postvisit(const ast::VariableExpr* expr);
@@ -66,8 +80,7 @@
     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 (!varExpr || varExpr->var->linkage == ast::Linkage::Intrinsic) {
+        if (fname == "?{}" || fname == "?=?") visit_children = false;
+    }
 
     if (fname == "labelE" || fname == "valueE" || fname == "posE") {
@@ -94,10 +107,10 @@
             auto untyped = new ast::UntypedExpr(
                 expr->location, new ast::NameExpr(expr->location, "valueE"),
-                { std::move( expr ) });
+                {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 );
+                result.strict_as<ast::ApplicationExpr>();
+            return ast::deepCopy(ret);
         }
     }
@@ -132,27 +145,24 @@
 }
 
-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 ) ) {
+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 >() ) {
+        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 )
-            );
+                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" );
+                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;
 }
@@ -167,26 +177,25 @@
     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 );
+    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 )
-                ) );
+            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>()) );
+                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)));
-    } 
+            location, ast::ConstantExpr::from_string(location, mem->name)));
+    }
     if (queryValues.count(enumDecl->name)) {
         auto init = new ast::ListInit(location, std::move(inits));
@@ -219,17 +228,34 @@
 ast::ApplicationExpr const* getPseudoFuncApplication(
     const CodeLocation location, ResolvExpr::ResolveContext context,
-    const ast::VariableExpr* arg, const ast::EnumDecl* base, const std::string & name) {
+    const ast::VariableExpr* arg, const ast::EnumDecl* base,
+    const std::string& name) {
     ast::Expr* toResolve = new ast::NameExpr(location, name + base->name);
-    auto result = ResolvExpr::findVoidExpression(toResolve, context);
-    assert(result.get());
-    auto arrAsVar = result.strict_as<ast::VariableExpr>();
-    auto untyped = new ast::UntypedExpr(
-        location, new ast::NameExpr(location, "?[?]"),
-        { std::move(arrAsVar), std::move(arg) });
-    auto typedResult = ResolvExpr::findVoidExpression(untyped, context);
-
-    ast::ptr<ast::ApplicationExpr> ret =
-        typedResult.strict_as<ast::ApplicationExpr>();
-    return ast::deepCopy(ret);
+    // 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);
+        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);
+    }
 }
 
@@ -250,45 +276,107 @@
         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) {
+
+        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 getPseudoFuncApplication(
+                            location, context, arg.get(), base, "values_");
+                    }
+                }
+            }
+
+            if (fname == "labelE") {
+                if (auto labelExpr = getPseudoFuncApplication(
+                        location, context, arg.get(), base, "labels_")) {
+                    return labelExpr;
+                }
+            } else if (fname == "valueE") {
+                if (auto valueExpr = getPseudoFuncApplication(
+                        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 = getPseudoFuncApplication(
+                        location, context, arg.get(), base, "labels_")) {
+                    return labelExpr;
+                }
+            } else if (fname == "valueE") {
+                if (auto valueExpr = getPseudoFuncApplication(
+                        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");
         }
-        const ast::EnumDecl* base = argType->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 getPseudoFuncApplication(location, context, arg.get(),
-                                               base, "values_");                    
-                }
-
-            }
-        }
-
-        if (fname == "labelE") {
-            if (auto labelExpr =
-                    getPseudoFuncApplication(location, context, arg.get(), base, "labels_")) {
-                return labelExpr;
-            }
-        } else if (fname == "valueE") {
-            if (auto valueExpr =
-                    getPseudoFuncApplication(location, context, arg.get(), base, "values_")) {
-                return valueExpr;
-            }
-        } else { // it is position; replace itself
-            return std::move( arg.get() );
-        }
     }
     return expr;
 }
+
+ast::ptr<ast::Expr> reduceCastExpr(ast::ptr<ast::Expr> expr) {
+    if (auto castExpr = expr.as<ast::CastExpr>()) {
+        return reduceCastExpr(castExpr->arg);
+    }
+    return expr;
+}
+
+struct ReplaceEnumInst final {
+    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;
+    }
+};
 
 }  // namespace
@@ -299,4 +387,5 @@
     ast::Pass<PseudoFuncGenerateRoutine>::run(translationUnit);
     ast::Pass<ReplacePseudoFuncCore>::run(translationUnit);
+    ast::Pass<ReplaceEnumInst>::run(translationUnit);
 }
 }  // namespace Validate
