Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision 933f32f2ae9703d54327e4727aceb5746433092d)
+++ src/InitTweak/InitTweak.cc	(revision 1259c35c5f47adf8a1a7b994be8123b2fdf43aa5)
@@ -346,4 +346,5 @@
 	namespace {
 		DeclarationWithType * getCalledFunction( Expression * expr );
+		const ast::DeclWithType * getCalledFunction( const ast::Expr * expr );
 
 		template<typename CallExpr>
@@ -355,4 +356,14 @@
 			return getCalledFunction( expr->get_args().front() );
 		}
+
+		template<typename CallExpr>
+		const ast::DeclWithType * handleDerefCalledFunction( const CallExpr * expr ) {
+			// (*f)(x) => should get "f"
+			std::string name = getFunctionName( expr );
+			assertf( name == "*?", "Unexpected untyped expression: %s", name.c_str() );
+			assertf( ! expr->args.empty(), "Cannot get called function from dereference with no arguments" );
+			return getCalledFunction( expr->args.front() );
+		}
+
 
 		DeclarationWithType * getCalledFunction( Expression * expr ) {
@@ -375,4 +386,24 @@
 			return nullptr;
 		}
+
+		const ast::DeclWithType * getCalledFunction( const ast::Expr * expr ) {
+			assert( expr );
+			if ( const ast::VariableExpr * varExpr = dynamic_cast< const ast::VariableExpr * >( expr ) ) {
+				return varExpr->var;
+			} else if ( const ast::MemberExpr * memberExpr = dynamic_cast< const ast::MemberExpr * >( expr ) ) {
+				return memberExpr->member;
+			} else if ( const ast::CastExpr * castExpr = dynamic_cast< const ast::CastExpr * >( expr ) ) {
+				return getCalledFunction( castExpr->arg );
+			} else if ( const ast::UntypedExpr * untypedExpr = dynamic_cast< const ast::UntypedExpr * >( expr ) ) {
+				return handleDerefCalledFunction( untypedExpr );
+			} else if ( const ast::ApplicationExpr * appExpr = dynamic_cast< const ast::ApplicationExpr * > ( expr ) ) {
+				return handleDerefCalledFunction( appExpr );
+			} else if ( const ast::AddressExpr * addrExpr = dynamic_cast< const ast::AddressExpr * >( expr ) ) {
+				return getCalledFunction( addrExpr->arg );
+			} else if ( const ast::CommaExpr * commaExpr = dynamic_cast< const ast::CommaExpr * >( expr ) ) {
+				return getCalledFunction( commaExpr->arg2 );
+			}
+			return nullptr;
+		}
 	}
 
@@ -382,4 +413,13 @@
 		} else if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * > ( expr ) ) {
 			return getCalledFunction( untyped->get_function() );
+		}
+		assertf( false, "getFunction received unknown expression: %s", toString( expr ).c_str() );
+	}
+
+	const ast::DeclWithType * getFunction( const ast::Expr * expr ) {
+		if ( const ast::ApplicationExpr * appExpr = dynamic_cast< const ast::ApplicationExpr * >( expr ) ) {
+			return getCalledFunction( appExpr->func );
+		} else if ( const ast::UntypedExpr * untyped = dynamic_cast< const ast::UntypedExpr * > ( expr ) ) {
+			return getCalledFunction( untyped->func );
 		}
 		assertf( false, "getFunction received unknown expression: %s", toString( expr ).c_str() );
@@ -434,16 +474,16 @@
 		}
 
-		// template<typename CallExpr>
-		// const ast::Expr * callArg( const CallExpr * call, unsigned int pos ) {
-		// 	if( pos >= call->args.size() ) {
-		// 		assertf( false, "getCallArg for argument that doesn't exist: (%u); %s.",
-		// 			pos, toString( call ).c_str() );
-		// 	}
-		// 	for ( const ast::Expr * arg : call->args ) {
-		// 		if ( pos == 0 ) return arg;
-		// 		--pos;
-		// 	}
-		// 	assert( false );
-		// }
+		template<typename CallExpr>
+		const ast::Expr * callArg( const CallExpr * call, unsigned int pos ) {
+			if( pos >= call->args.size() ) {
+				assertf( false, "getCallArg for argument that doesn't exist: (%u); %s.",
+					pos, toString( call ).c_str() );
+			}
+			for ( const ast::Expr * arg : call->args ) {
+				if ( pos == 0 ) return arg;
+				--pos;
+			}
+			assert( false );
+		}
 	}
 
@@ -466,30 +506,28 @@
 		}
 	}
+
 	const ast::Expr * getCallArg( const ast::Expr * call, unsigned pos ) {
-		(void)call;
-		(void)pos;
-		#warning unimplemented; needs to build AST/Expr.cpp
-		assertf(false, "unimplemented; needs to build AST/Expr.cpp");
-		// if ( auto app = dynamic_cast< const ast::ApplicationExpr * >( call ) ) {
-		// 	return callArg( app, pos );
-		// } else if ( auto untyped = dynamic_cast< const ast::UntypedExpr * >( call ) ) {
-		// 	return callArg( untyped, pos );
-		// } else if ( auto tupleAssn = dynamic_cast< const ast::TupleAssignExpr * >( call ) ) {
-		// 	const std::list<ast::ptr<ast::Stmt>>& stmts = tupleAssn->stmtExpr->stmts->kids;
-		// 	assertf( ! stmts.empty(), "TupleAssignExpr missing statements." );
-		// 	const ExprStmt * stmt = strict_dynamic_cast< const ast::ExprStmt * >( stmts.back() );
-		// 	const TupleExpr * tuple = strict_dynamic_cast< const ast::TupleExpr * >( stmt->expr );
-		// 	assertf( ! tuple->exprs.empty(), "TupleAssignExpr has empty tuple expr.");
-		// 	return getCallArg( tuple->exprs.front(), pos );
-		// } else if ( auto ctor = dynamic_cast< const ast::ImplicitCopyCtorExpr * >( call ) ) {
-		// 	return getCallArg( ctor->callExpr, pos );
-		// } else {
-		// 	assertf( false, "Unexpected expression type passed to getCallArg: %s",
-		// 		toString( call ).c_str() );
-		// }
+		if ( auto app = dynamic_cast< const ast::ApplicationExpr * >( call ) ) {
+			return callArg( app, pos );
+		} else if ( auto untyped = dynamic_cast< const ast::UntypedExpr * >( call ) ) {
+			return callArg( untyped, pos );
+		} else if ( auto tupleAssn = dynamic_cast< const ast::TupleAssignExpr * >( call ) ) {
+			const std::list<ast::ptr<ast::Stmt>>& stmts = tupleAssn->stmtExpr->stmts->kids;
+			assertf( ! stmts.empty(), "TupleAssignExpr missing statements." );
+			auto stmt  = strict_dynamic_cast< const ast::ExprStmt * >( stmts.back().get() );
+			auto tuple = strict_dynamic_cast< const ast::TupleExpr * >( stmt->expr.get() );
+			assertf( ! tuple->exprs.empty(), "TupleAssignExpr has empty tuple expr.");
+			return getCallArg( tuple->exprs.front(), pos );
+		} else if ( auto ctor = dynamic_cast< const ast::ImplicitCopyCtorExpr * >( call ) ) {
+			return getCallArg( ctor->callExpr, pos );
+		} else {
+			assertf( false, "Unexpected expression type passed to getCallArg: %s",
+				toString( call ).c_str() );
+		}
 	}
 
 	namespace {
 		std::string funcName( Expression * func );
+		std::string funcName( const ast::Expr * func );
 
 		template<typename CallExpr>
@@ -500,4 +538,13 @@
 			assertf( ! expr->get_args().empty(), "Cannot get function name from dereference with no arguments" );
 			return funcName( expr->get_args().front() );
+		}
+
+		template<typename CallExpr>
+		std::string handleDerefName( const CallExpr * expr ) {
+			// (*f)(x) => should get name "f"
+			std::string name = getFunctionName( expr );
+			assertf( name == "*?", "Unexpected untyped expression: %s", name.c_str() );
+			assertf( ! expr->args.empty(), "Cannot get function name from dereference with no arguments" );
+			return funcName( expr->args.front() );
 		}
 
@@ -523,4 +570,26 @@
 			}
 		}
+
+		std::string funcName( const ast::Expr * func ) {
+			if ( const ast::NameExpr * nameExpr = dynamic_cast< const ast::NameExpr * >( func ) ) {
+				return nameExpr->name;
+			} else if ( const ast::VariableExpr * varExpr = dynamic_cast< const ast::VariableExpr * >( func ) ) {
+				return varExpr->var->name;
+			}	else if ( const ast::CastExpr * castExpr = dynamic_cast< const ast::CastExpr * >( func ) ) {
+				return funcName( castExpr->arg );
+			} else if ( const ast::MemberExpr * memberExpr = dynamic_cast< const ast::MemberExpr * >( func ) ) {
+				return memberExpr->member->name;
+			} else if ( const ast::UntypedMemberExpr * memberExpr = dynamic_cast< const ast::UntypedMemberExpr * > ( func ) ) {
+				return funcName( memberExpr->member );
+			} else if ( const ast::UntypedExpr * untypedExpr = dynamic_cast< const ast::UntypedExpr * >( func ) ) {
+				return handleDerefName( untypedExpr );
+			} else if ( const ast::ApplicationExpr * appExpr = dynamic_cast< const ast::ApplicationExpr * >( func ) ) {
+				return handleDerefName( appExpr );
+			} else if ( const ast::ConstructorExpr * ctorExpr = dynamic_cast< const ast::ConstructorExpr * >( func ) ) {
+				return funcName( getCallArg( ctorExpr->callExpr, 0 ) );
+			} else {
+				assertf( false, "Unexpected expression type being called as a function in call expression: %s", toString( func ).c_str() );
+			}
+		}
 	}
 
@@ -539,4 +608,18 @@
 	}
 
+	std::string getFunctionName( const ast::Expr * expr ) {
+		// there's some unforunate overlap here with getCalledFunction. Ideally this would be able to use getCalledFunction and
+		// return the name of the DeclarationWithType, but this needs to work for NameExpr and UntypedMemberExpr, where getCalledFunction
+		// can't possibly do anything reasonable.
+		if ( const ast::ApplicationExpr * appExpr = dynamic_cast< const ast::ApplicationExpr * >( expr ) ) {
+			return funcName( appExpr->func );
+		} else if ( const ast::UntypedExpr * untypedExpr = dynamic_cast< const ast::UntypedExpr * > ( expr ) ) {
+			return funcName( untypedExpr->func );
+		} else {
+			std::cerr << expr << std::endl;
+			assertf( false, "Unexpected expression type passed to getFunctionName" );
+		}
+	}
+
 	Type * getPointerBase( Type * type ) {
 		if ( PointerType * ptrType = dynamic_cast< PointerType * >( type ) ) {
@@ -551,14 +634,11 @@
 	}
 	const ast::Type* getPointerBase( const ast::Type* t ) {
-		(void)t;
-		#warning needs to build Type.cpp before inclusion
-		assertf(false, "needs to build Type.cpp before inclusion");
-		// if ( const auto * p = dynamic_cast< const ast::PointerType * >( t ) ) {
-		// 	return p->base;
-		// } else if ( const auto * a = dynamic_cast< const ast::ArrayType * >( t ) ) {
-		// 	return a->base;
-		// } else if ( const auto * r = dynamic_cast< const ast::ReferenceType * >( t ) ) {
-		// 	return r->base;
-		// } else return nullptr;
+		if ( const auto * p = dynamic_cast< const ast::PointerType * >( t ) ) {
+			return p->base;
+		} else if ( const auto * a = dynamic_cast< const ast::ArrayType * >( t ) ) {
+			return a->base;
+		} else if ( const auto * r = dynamic_cast< const ast::ReferenceType * >( t ) ) {
+			return r->base;
+		} else return nullptr;
 	}
 
Index: src/InitTweak/InitTweak.h
===================================================================
--- src/InitTweak/InitTweak.h	(revision 933f32f2ae9703d54327e4727aceb5746433092d)
+++ src/InitTweak/InitTweak.h	(revision 1259c35c5f47adf8a1a7b994be8123b2fdf43aa5)
@@ -58,4 +58,5 @@
 	/// returns the declaration of the function called by the expr (must be ApplicationExpr or UntypedExpr)
 	DeclarationWithType * getFunction( Expression * expr );
+	const ast::DeclWithType * getFunction( const ast::Expr * expr );
 
 	/// Non-Null if expr is a call expression whose target function is intrinsic
@@ -78,4 +79,5 @@
 	/// returns the name of the function being called
 	std::string getFunctionName( Expression * expr );
+	std::string getFunctionName( const ast::Expr * expr );
 
 	/// returns the argument to a call expression in position N indexed from 0
