Index: doc/proposals/enum.tex
===================================================================
--- doc/proposals/enum.tex	(revision 71b5aad58696e7080180f82a1dd2c772721ae91d)
+++ doc/proposals/enum.tex	(revision 61e362feab9ac30e7e3748f946b2cf384102b37b)
@@ -245,5 +245,21 @@
 
 
-\
+\subsection{Aggressive Inline}
+To avoid allocating memory for enumeration data structures, \CFA inline the result of enumeration attribute pseudo-function whenever it is possible. 
+\begin{lstlisting}[label=lst:enumeration_inline]
+enum(int) OddNumber { A=1, B=3 };
+sout | "A: " | OddNumber.A | "B: " | OddNumber.B | "A+B: " | OddNumber.A + OddNumber.B
+\end{lstlisting}
+Instead of calling pseudo-function @value@ on expression $OddNumber.A$ and $OddNumber.B$, because the result is known statistically, \CFA will inline the constant expression 1 and 3, respectively. Because no runtime lookup for enumeration value is necessary, \CFA will not generate data structure for enumeration OddNumber.
+
+\subsection{Weak Reference}
+\begin{lstlisting}[label=lst:week_ref]
+enum(int) OddNumber { A=1, B=3 };
+enum OddNumber i = ...;
+...
+sout | OddNumber;
+\end{lstlisting}
+In this example, \CFA cannot determine the static value of the enum variable i, and Runtime lookup is necessary. The OddNumber can be referenced in multiple compilations, and allocating the arrays in all compilation units is not desirable. \CFA addresses this by declaring the value array as a weak reference. All compilation units reference OddNumber have weak references to the same enumeration data structure. No extra memory is allocated if more compilation units reference OddNumber, and the OddNumber is initialized once.
+
 \section{Unification}
 
@@ -622,48 +638,5 @@
 \section{Implementation}
 
-\subsection{Static Attribute Expression}
-\begin{lstlisting}[label=lst:static_attr]
-enum( char * ) Colour {
-    Red = "red", Blue = "blue", Green = "green"  
-};
-\end{lstlisting}
-An enumerator expression returns its enumerator value as a constant expression with no runtime cost. For example, @Colour.Red@ is equivalent to the constant expression "red", and \CFA finishes the expression evaluation before generating the corresponding C code. Applying a pseudo-function to a constant enumerator expression results in a constant expression as well. @value( Colour.Red )@, @position( Colour. Red )@, and @label( Colour.Red )@ are equivalent to constant expression with char * value "red", int value 0, and char * value "Red", respectively. 
-
-\subsection{Runtime Attribute Expression and Weak Referenced Data}
-\begin{lstlisting}[label=lst:dynamic_attr]
-Colour c;
-...
-value( c ); // or c
-\end{lstlisting}
-An enumeration variable c is equivalent to an integer variable with the value of @position( c )@ In Example~\ref{lst:dynamic_attr}, the value of enumeration variable c is unknown at compile time. In this case, the pseudo-function calls are reduced to expression that returns the enumerator values at runtime.
-
-\CFA stores the variables and labels in const arrays to provide runtime lookup for enumeration information. 
-
-\begin{lstlisting}[label=lst:attr_array]
-const char * Colour_labels [3] = { "Red", "Blue", "Green" };
-const char * Colour_values [3] = { "red", "blue", "green" };
-\end{lstlisting}
-The \CFA compiles transforms the attribute expressions into array access.
-\begin{lstlisting}[label=lst:attr_array_access]
-position( c ) // c; an integer
-value( c ); // Colour_values[c]
-label( c ); // Colour_labels[c]
-\end{lstlisting}
-
-To avoid unnecessary memory usage, the labels and values array are only generated as needed, and only generate once across all compilation units. By default, \CFA defers the declaration of the label and value arrays until an call to attribute function with a dynamic value. If an attribute function is never called on a dynamic value of an enumerator, the array will never be allocated. Once the arrays are created, all compilation units share a weak reference to the allocation array. 
-
-\subsection{Enum Prelude}
-
-\begin{lstlisting}[label=lst:enum_func_dec]
-forall( T ) {
-    unsigned position( unsigned );
-    T value( unsigned );
-    char * label( unsigned );
-}
-\end{lstlisting}
-\CFA loads the declaration of enumeration function from the enum.hfa.
-
-\subsection{Internal Representation}
-
+\subsection{Compiler Representation (Reworking)}
 The definition of an enumeration is represented by an internal type called @EnumDecl@. At the minimum, it stores all the information needed to construct the companion object. Therefore, an @EnumDecl@ can be represented as the following:
 \begin{lstlisting}[label=lst:EnumDecl]
@@ -694,32 +667,32 @@
 
 
-% \subsection{(Rework) Companion Object and Companion Function}
-
-% \begin{lstlisting}[caption={Enum Type Functions}, label=lst:cforall_enum_functions]
-% forall( T )
-% struct Companion {
-% 	const T * const values;
-%         const char * label;
-% 	int length;
-% };
-% \end{lstlisting}
-% \CFA generates companion objects, an instance of structure that encloses @necessary@ data to represent an enumeration. The size of the companion is unknown at the compilation time, and it "grows" in size to compensate for the @usage@.
-
-% The companion object is singleton across the compilation (investigation).  
-
-% \CFA generates the definition of companion functions.
-% Because \CFA implicitly stores an enumeration instance as its position, the companion function @position@ does nothing but return the position it is passed.
-% Companions function @value@ and @label@ return the array item at the given position of @values@ and @labels@, respectively.
-% \begin{lstlisting}[label=lst:companion_definition]
-% int position( Companion o, int pos ) { return pos; }
-% T value( Companion o, int pos ) { return o.values[ pos ]; }
-% char * label( Companion o, int pos ) { return o.labels[ pos ]; }
-% \end{lstlisting}
-% Notably, the @Companion@ structure definition, and all companion objects, are visible to users.
-% A user can retrieve values and labels defined in an enumeration by accessing the values and labels directly, or indirectly by calling @Companion@ functions @values@ and @labels@
-% \begin{lstlisting}[label=lst:companion_definition_values_labels]
-% Colour.values; // read the Companion's values
-% values( Colour ); // same as Colour.values
-% \end{lstlisting}
+\subsection{(Rework) Companion Object and Companion Function}
+
+\begin{lstlisting}[caption={Enum Type Functions}, label=lst:cforall_enum_functions]
+forall( T )
+struct Companion {
+	const T * const values;
+        const char * label;
+	int length;
+};
+\end{lstlisting}
+\CFA generates companion objects, an instance of structure that encloses @necessary@ data to represent an enumeration. The size of the companion is unknown at the compilation time, and it "grows" in size to compensate for the @usage@.
+
+The companion object is singleton across the compilation (investigation).  
+
+\CFA generates the definition of companion functions.
+Because \CFA implicitly stores an enumeration instance as its position, the companion function @position@ does nothing but return the position it is passed.
+Companions function @value@ and @label@ return the array item at the given position of @values@ and @labels@, respectively.
+\begin{lstlisting}[label=lst:companion_definition]
+int position( Companion o, int pos ) { return pos; }
+T value( Companion o, int pos ) { return o.values[ pos ]; }
+char * label( Companion o, int pos ) { return o.labels[ pos ]; }
+\end{lstlisting}
+Notably, the @Companion@ structure definition, and all companion objects, are visible to users.
+A user can retrieve values and labels defined in an enumeration by accessing the values and labels directly, or indirectly by calling @Companion@ functions @values@ and @labels@
+\begin{lstlisting}[label=lst:companion_definition_values_labels]
+Colour.values; // read the Companion's values
+values( Colour ); // same as Colour.values
+\end{lstlisting}
 
 \subsection{Companion Traits (experimental)}
Index: src/AST/Decl.hpp
===================================================================
--- src/AST/Decl.hpp	(revision 71b5aad58696e7080180f82a1dd2c772721ae91d)
+++ src/AST/Decl.hpp	(revision 61e362feab9ac30e7e3748f946b2cf384102b37b)
@@ -312,4 +312,5 @@
 	ptr<Type> base;
 	enum class EnumHiding { Visible, Hide } hide;
+
 	EnumDecl( const CodeLocation& loc, const std::string& name, bool isTyped = false,
 		std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall,
Index: src/Validate/Autogen.cpp
===================================================================
--- src/Validate/Autogen.cpp	(revision 71b5aad58696e7080180f82a1dd2c772721ae91d)
+++ src/Validate/Autogen.cpp	(revision 61e362feab9ac30e7e3748f946b2cf384102b37b)
@@ -803,8 +803,60 @@
 }
 
+struct PseudoFuncGenerateRoutine final :
+		public ast::WithDeclsToAdd<>,
+		public ast::WithShortCircuiting {
+	void previsit( const ast::EnumDecl * enumDecl );
+};
+
+void PseudoFuncGenerateRoutine::previsit( const ast::EnumDecl * enumDecl ) {
+	const CodeLocation& location = enumDecl->location;
+	if ( enumDecl->members.size() == 0 || !enumDecl->base || enumDecl->name == "" ) return;
+
+	std::vector<ast::ptr<ast::Init>> inits;
+	std::vector<ast::ptr<ast::Init>> labels;
+	for ( const ast::Decl * mem: enumDecl->members ) {
+		auto memAsObjectDecl = dynamic_cast< const ast::ObjectDecl * >( mem );
+		inits.emplace_back( memAsObjectDecl->init );
+		labels.emplace_back( new ast::SingleInit( 
+			location, ast::ConstantExpr::from_string(location, mem->name) ) );
+	}
+	auto init = new ast::ListInit( location, std::move( inits ) );
+	auto label_strings = new ast::ListInit( location, std::move(labels) );
+	auto values = new ast::ObjectDecl( 
+		location,
+		"__enum_values_"+enumDecl->name,
+		new ast::ArrayType(
+			// new ast::PointerType( new ast::BasicType{ ast::BasicType::Char} ),
+			enumDecl->base,
+			ast::ConstantExpr::from_int( location, enumDecl->members.size() ), 
+			ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim
+		)
+		,init
+		,
+		ast::Storage::Static,
+		ast::Linkage::AutoGen
+	);
+	auto label_arr = new ast::ObjectDecl(
+		location,
+		"__enum_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
+	);
+
+	declsToAddAfter.push_back( values );
+	declsToAddAfter.push_back( label_arr );
+}
+
 } // namespace
 
 void autogenerateRoutines( ast::TranslationUnit & translationUnit ) {
 	ast::Pass<AutogenerateRoutines>::run( translationUnit );
+	// ast::Pass<PseudoFuncGenerateRoutine>::run( translationUnit );
 }
 
Index: src/Validate/ReplacePseudoFunc.cpp
===================================================================
--- src/Validate/ReplacePseudoFunc.cpp	(revision 71b5aad58696e7080180f82a1dd2c772721ae91d)
+++ src/Validate/ReplacePseudoFunc.cpp	(revision 61e362feab9ac30e7e3748f946b2cf384102b37b)
@@ -1,187 +1,39 @@
+#include "AST/Decl.hpp"
+#include "AST/Pass.hpp"
+#include "AST/Stmt.hpp"
+#include "AST/Inspect.hpp"
+#include "Common/utility.h"
 #include "ReplacePseudoFunc.hpp"
 
-#include <set>
-
-#include "AST/Decl.hpp"
-#include "AST/Inspect.hpp"
-#include "AST/Pass.hpp"
-#include "AST/Stmt.hpp"
-#include "Common/utility.h"
-#include "ResolvExpr/Resolver.h"
-#include "SymTab/Mangler.h"  // for Mangler
 namespace Validate {
 
 namespace {
 
-std::set<std::string> queryLabels;
-std::set<std::string> queryValues;
-
-struct FindGenEnumArray final : public ast::WithShortCircuiting {
-    void previsit(const ast::ApplicationExpr* enumDecl);
+struct ReplacePseudoFuncCore {
+    ast::Expr const * postvisit( ast::ApplicationExpr const * decl );
 };
-
-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);
-    }
 }
 
-struct PseudoFuncGenerateRoutine final : public ast::WithDeclsToAdd<>,
-                                         public ast::WithSymbolTable,
-                                         public ast::WithShortCircuiting {
-    void previsit(const ast::EnumDecl* enumDecl);
-};
-
-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;
-    for (const ast::Decl* mem : enumDecl->members) {
-        auto memAsObjectDecl = dynamic_cast<const ast::ObjectDecl*>(mem);
-        inits.emplace_back(memAsObjectDecl->init);
-        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));
-        auto values = new ast::ObjectDecl(
-            location, "values_" + enumDecl->name,
-            new ast::ArrayType(
-                enumDecl->base,
-                ast::ConstantExpr::from_int(location, enumDecl->members.size()),
-                ast::LengthFlag::FixedLen, ast::DimensionFlag::DynamicDim),
-            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 label_arr = 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(label_arr);
-        label_arr->mangleName = Mangle::mangle(label_arr);
-        declsToAddAfter.push_back(label_arr);
-    }
-}
-
-struct ReplacePseudoFuncCore : public ast::WithShortCircuiting,
-                               public ast::WithSymbolTable,
-                               public ast::WithConstTranslationUnit {
-    ast::Expr const* postvisit(ast::ApplicationExpr const* decl);
-};
-
-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::Expr const * ReplacePseudoFuncCore::postvisit( ast::ApplicationExpr const * expr) {
+    auto fname = ast::getFunctionName( expr );
+    if ( fname == "posE" ) {
+        // std::cerr << "Found App in ReplacePseudoFunc" << std::endl;
+        if ( expr->args.size() != 1 ) {
+            SemanticError( expr, "Position 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::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 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,
-                          "Pseudo Enum Expression can only be used on an "
-                          "enumeration instance");
+        const ast::EnumInstType * argType = argAsVar->type.as<const ast::EnumInstType>();
+        if ( !argType ) {
+            SemanticError( argAsVar, "Position can only be used on an enumeration instance" );
         }
-        const ast::EnumDecl* base = argType->base;
-        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 new ast::TypeExpr(expr->location, argType);
-            }
-        }
-
-        ResolvExpr::ResolveContext context{symtab, transUnit().global};
-
-        if (fname == "labelE") {
-            ast::Expr* toResolve =
-                new ast::NameExpr(expr->location, "labels_" + base->name);
-            auto result = ResolvExpr::findVoidExpression(toResolve, context);
-            if (result.get()) {
-                auto arrAsVar = result.strict_as<ast::VariableExpr>();
-                auto untyped = new ast::UntypedExpr(
-                    location, new ast::NameExpr(location, "?[?]"),
-                    {new ast::VariableExpr(*arrAsVar),
-                     ast::ConstantExpr::from_int(
-                         location,
-                         0)});  /// TODO: dummy value.
-                                /// To make it works need to change the unifier
-
-                auto typedResult =
-                    ResolvExpr::findVoidExpression(untyped, context);
-                if (result.get()) {
-                    ast::ptr<ast::ApplicationExpr> ret =
-                        typedResult.strict_as<ast::ApplicationExpr>();
-                    return new ast::ApplicationExpr(*ret);
-                }
-            }
-        }
-        
-        if (fname == "valueE") {
-            ast::Expr* toResolve =
-                new ast::NameExpr(expr->location, "values_" + base->name);
-            auto result = ResolvExpr::findVoidExpression(toResolve, context);
-            if (result.get()) {
-                auto arrAsVar = result.strict_as<ast::VariableExpr>();
-                auto untyped = new ast::UntypedExpr(
-                    location, new ast::NameExpr(location, "?[?]"),
-                    {new ast::VariableExpr(*arrAsVar),
-                     ast::ConstantExpr::from_int(
-                         location,
-                         0)});  /// TODO: dummy value.
-                                /// To make it works need to change the unifier
-
-                auto typedResult =
-                    ResolvExpr::findVoidExpression(untyped, context);
-                if (result.get()) {
-                    ast::ptr<ast::ApplicationExpr> ret =
-                        typedResult.strict_as<ast::ApplicationExpr>();
-                    return new ast::ApplicationExpr(*ret);
-                }
+        const ast::EnumDecl * base = argType->base;
+        for ( size_t i = 0; i < base->members.size(); i++ ) {
+            if ( base->members[i]->name == referredName ) {
+                return ast::ConstantExpr::from_int( expr->location, i );
             }
         }
@@ -190,10 +42,9 @@
 }
 
-}  // namespace
 
-void replacePseudoFunc(ast::TranslationUnit& translationUnit) {
-    ast::Pass<FindGenEnumArray>::run(translationUnit);
-    ast::Pass<PseudoFuncGenerateRoutine>::run(translationUnit);
-    ast::Pass<ReplacePseudoFuncCore>::run(translationUnit);
+
+void replacePseudoFunc( ast::TranslationUnit & translationUnit ) {
+    ast::Pass<ReplacePseudoFuncCore>::run( translationUnit );
 }
-}  // namespace Validate
+
+}
