Index: src/Common/Eval.cc
===================================================================
--- src/Common/Eval.cc	(revision e5ea867f74eefbaecafb0b5081b7a0a3ed60d64f)
+++ src/Common/Eval.cc	(revision e5ea867f74eefbaecafb0b5081b7a0a3ed60d64f)
@@ -0,0 +1,96 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// utility.h --
+//
+// Author           : Richard C. Bilson
+// Created On       : Mon May 18 07:44:20 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sun May  6 22:24:16 2018
+// Update Count     : 40
+//
+
+#include <utility> // for pair
+
+#include "Common/PassVisitor.h"
+#include "InitTweak/InitTweak.h"
+#include "SynTree/Expression.h"
+
+struct Eval : public WithShortCircuiting {
+	long long int value = 0;
+	bool valid = true;
+
+	void previsit( BaseSyntaxNode * ) { visit_children = false; }
+	void postvisit( BaseSyntaxNode * ) { valid = false; }
+
+	void postvisit( ConstantExpr * expr ) {
+		value = expr->intValue();
+	}
+
+	void postvisit( CastExpr * expr ) {
+		auto arg = eval(expr->arg);
+		valid = arg.second;
+		value = arg.first;
+		// TODO: perform type conversion on value if valid
+	}
+
+	void postvisit( VariableExpr * expr ) {
+		if ( EnumInstType * inst = dynamic_cast<EnumInstType *>(expr->result) ) {
+			if ( EnumDecl * decl = inst->baseEnum ) {
+				if ( decl->valueOf( expr->var, value ) ) { // value filled by valueOf
+					return;
+				}
+			}
+		}
+		valid = false;
+	}
+
+	void postvisit( ApplicationExpr * expr ) {
+		DeclarationWithType * function = InitTweak::getFunction(expr);
+		if ( ! function || function->linkage != LinkageSpec::Intrinsic ) { valid = false; return; }
+		const std::string & fname = function->name;
+		assertf( expr->args.size() == 1 || expr->args.size() == 2, "Intrinsic function with %zd arguments: %s", expr->args.size(), fname.c_str() );
+		std::pair<long long int, bool> arg1, arg2;
+		arg1 = eval(expr->args.front());
+		valid = valid && arg1.second;
+		if ( ! valid ) return;
+		if ( expr->args.size() == 2 ) {
+			arg2 = eval(expr->args.back());
+			valid = valid && arg2.second;
+			if ( ! valid ) return;
+		}
+		if (fname == "?+?") {
+			value = arg1.first + arg2.first;
+		} else if (fname == "?-?") {
+			value = arg1.first - arg2.first;
+		} else if (fname == "?*?") {
+			value = arg1.first * arg2.first;
+		} else if (fname == "?/?") {
+			value = arg1.first / arg2.first;
+		} else if (fname == "?%?") {
+			value = arg1.first % arg2.first;
+		} else {
+			valid = false;
+		}
+		// TODO: implement other intrinsic functions
+	}
+};
+
+std::pair<long long int, bool> eval(Expression * expr) {
+	PassVisitor<Eval> ev;
+	if (expr) {
+		expr->accept(ev);
+		return std::make_pair(ev.pass.value, ev.pass.valid);
+	} else {
+		return std::make_pair(0, false);
+	}
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Common/module.mk
===================================================================
--- src/Common/module.mk	(revision fd2debf6bc04a25e7312e0b1f5ff93f7d5aff352)
+++ src/Common/module.mk	(revision e5ea867f74eefbaecafb0b5081b7a0a3ed60d64f)
@@ -19,3 +19,4 @@
        Common/DebugMalloc.cc \
        Common/Assert.cc \
-       Common/Heap.cc
+       Common/Heap.cc \
+       Common/Eval.cc
Index: src/Common/utility.h
===================================================================
--- src/Common/utility.h	(revision fd2debf6bc04a25e7312e0b1f5ff93f7d5aff352)
+++ src/Common/utility.h	(revision e5ea867f74eefbaecafb0b5081b7a0a3ed60d64f)
@@ -31,4 +31,6 @@
 #include "Common/Indenter.h"
 
+class Expression;
+
 template< typename T >
 static inline T * maybeClone( const T *orig ) {
@@ -456,4 +458,7 @@
 } // ilog2
 
+// -----------------------------------------------------------------------------
+/// evaluates expr as a long long int. If second is false, expr could not be evaluated
+std::pair<long long int, bool> eval(Expression * expr);
 
 // Local Variables: //
