Index: libcfa/src/exception.hfa
===================================================================
--- libcfa/src/exception.hfa	(revision f277633e42d8329774ead0a097af86b585de8910)
+++ libcfa/src/exception.hfa	(revision 21b0a23f5172b5102ba4fe6b283d6d16f97865ba)
@@ -10,6 +10,6 @@
 // Created On       : Thu Apr  7 10:25:00 2020
 // Last Modified By : Andrew Beach
-// Last Modified On : Tue May 19 14:17:00 2020
-// Update Count     : 2
+// Last Modified On : Tue Aug  4 16:22:00 2020
+// Update Count     : 3
 //
 
@@ -18,18 +18,15 @@
 // -----------------------------------------------------------------------------------------------
 
-// All internals helper macros begin with an underscore.
-#define _CLOSE(...) __VA_ARGS__ }
-#define _GLUE2(left, right) left##right
-#define _GLUE3(left, middle, right) left##middle##right
-#define _EXC_DISPATCH(to, ...) to(__VA_ARGS__,__cfaehm_base_exception_t,)
-
-// FWD_TRIVIAL_EXCEPTION(exception_name);
+// TRIVIAL_EXCEPTION_DECLARATION(exception_name);
 // Declare a trivial exception, one that adds no fields or features.
 // This will make the exception visible and may go in a .hfa or .cfa file.
-#define FWD_TRIVIAL_EXCEPTION(...) _EXC_DISPATCH(_FWD_TRIVIAL_EXCEPTION, __VA_ARGS__)
-// INST_TRIVIAL_EXCEPTION(exception_name);
+#define TRIVIAL_EXCEPTION_DECLARATION(...) \
+	_EXC_DISPATCH(_TRIVIAL_EXCEPTION_DECLARATION, __VA_ARGS__)
+
+// TRIVIAL_EXCEPTION_INSTANCE(exception_name);
 // Create the trival exception. This must be used exactly once and should be used in a .cfa file,
 // as it creates the unique instance of the virtual table.
-#define INST_TRIVIAL_EXCEPTION(...) _EXC_DISPATCH(_INST_TRIVIAL_EXCEPTION, __VA_ARGS__)
+#define TRIVIAL_EXCEPTION_INSTANCE(...) _EXC_DISPATCH(_TRIVIAL_EXCEPTION_INSTANCE, __VA_ARGS__)
+
 // TRIVIAL_EXCEPTION(exception_name[, parent_name]);
 // Does both of the above, a short hand if the exception is only used in one .cfa file.
@@ -37,7 +34,104 @@
 // base exception. This feature may be removed or changed.
 #define TRIVIAL_EXCEPTION(...) \
-	_EXC_DISPATCH(_FWD_TRIVIAL_EXCEPTION, __VA_ARGS__); \
-	_EXC_DISPATCH(_INST_TRIVIAL_EXCEPTION, __VA_ARGS__)
-#define _FWD_TRIVIAL_EXCEPTION(exception_name, parent_name, ...) \
+	_EXC_DISPATCH(_TRIVIAL_EXCEPTION_DECLARATION, __VA_ARGS__); \
+	_EXC_DISPATCH(_TRIVIAL_EXCEPTION_INSTANCE, __VA_ARGS__)
+
+// FORALL_TRIVIAL_EXCEPTION(exception_name, (assertions...), (parameters...));
+// Forward declare a polymorphic but otherwise trivial exception type. You must provide the entire
+// assertion list (exactly what would go in the forall clause) and parameters list (only the
+// parameter names from the assertion list, same order and comma seperated). This should be
+// visible where ever use the exception. This just generates the polymorphic framework, see
+// POLY_VTABLE_DECLARATION to allow instantiations.
+#define FORALL_TRIVIAL_EXCEPTION(exception_name, assertions, parameters) \
+	_FORALL_TRIVIAL_EXCEPTION(exception_name, __cfaehm_base_exception_t, assertions, parameters, )
+
+// FORALL_TRIVIAL_INSTANCE(exception_name, (assertions...), (parameters...))
+// Create the forall trivial exception. The assertion list and parameters must match.
+// There must be exactly one use of this in a program for each exception type. This just
+// generates the polymorphic framework, see POLY_VTABLE_INSTANCE to allow instantiations.
+#define FORALL_TRIVIAL_INSTANCE(exception_name, assertions, parameters) \
+	_FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters)
+
+// DATA_EXCEPTION(exception_name)(fields...);
+// Forward declare an exception that adds fields but no features. The added fields go in the
+// second argument list. The virtual table instance must be provided later (see VTABLE_INSTANCE).
+#define DATA_EXCEPTION(...) _EXC_DISPATCH(_DATA_EXCEPTION, __VA_ARGS__)
+
+// FORALL_DATA_EXCEPTION(exception_name, (assertions...), (parameters...))(fields...);
+// Define a polymorphic exception that adds fields but no additional features. The assertion list
+// and matching parameters must match. Then you can give the list of fields. This should be
+// visible where ever you use the exception. This just generates the polymorphic framework, see
+// POLY_VTABLE_DECLARATION to allow instantiations.
+#define FORALL_DATA_EXCEPTION(exception_name, assertions, parameters) \
+	_FORALL_DATA_EXCEPTION(exception_name, __cfaehm_base_exception_t, assertions, parameters, )
+
+// FORALL_DATA_INSTANCE(exception_name, (assertions...), (parameters...))
+// Create a polymorphic data exception. The assertion list and parameters must match. This should
+// appear once in each program. This just generates the polymorphic framework, see
+// POLY_VTABLE_INSTANCE to allow instantiations.
+#define FORALL_DATA_INSTANCE(exception_name, assertions, parameters) \
+	_FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters)
+
+// VTABLE_DECLARATION(exception_name)([new_features...]);
+// Declare a virtual table type for an exception with exception_name. You may also add features
+// (fields on the virtual table) by including them in the second list.
+#define VTABLE_DECLARATION(...) _EXC_DISPATCH(_VTABLE_DECLARATION, __VA_ARGS__)
+
+// VTABLE_INSTANCE(exception_name)(msg [, others...]);
+// Create the instance of the virtual table. There must be exactly one instance of a virtual table
+// for each exception type. This fills in most of the fields of the virtual table (uses ?=? and
+// ^?{}) but you must provide the message function and any other fields added in the declaration.
+#define VTABLE_INSTANCE(...) _EXC_DISPATCH(_VTABLE_INSTANCE, __VA_ARGS__)
+
+// FORALL_VTABLE_DECLARATION(exception_name, (assertions...), (parameters...))([new_features...]);
+// Declare a polymorphic virtual table type for an exception with exception_name, the given
+// assertions and parameters. You may also add features (fields on the virtual table). This just
+// generates the polymorphic framework, see POLY_VTABLE_DECLARATION to allow instantiations.
+#define FORALL_VTABLE_DECLARATION(exception_name, assertions, parameters) \
+	_FORALL_VTABLE_DECLARATION(exception_name, __cfaehm_base_exception_t, assertions, parameters, )
+
+// POLY_VTABLE_DECLARATION(exception_name, types...);
+// Declares that an instantiation for this exception exists for the given types. This should be
+// visible anywhere you use the instantiation of the exception is used.
+#define POLY_VTABLE_DECLARATION(exception_name, ...) \
+	void mark_exception(exception_name(__VA_ARGS__) *); \
+	extern VTABLE_TYPE(exception_name)(__VA_ARGS__) VTABLE_NAME(exception_name)
+
+// POLY_VTABLE_INSTANCE(exception_name, types...)(msg [, others...]);
+// Creates an instantiation for the given exception for the given types. This should occur only
+// once in the entire program. You must fill in all features, message and any others given in the
+// initial declaration.
+#define POLY_VTABLE_INSTANCE(exception_name, ...) \
+	_POLY_VTABLE_INSTANCE(exception_name, __cfaehm_base_exception_t, __VA_ARGS__)
+
+// VTABLE_TYPE(exception_name) | VTABLE_NAME(exception_name)
+// Get the name of the vtable type or the name of the vtable instance for an exception type.
+#define VTABLE_TYPE(exception_name) struct _GLUE2(exception_name,_vtable)
+#define VTABLE_NAME(exception_name) _GLUE3(_,exception_name,_vtable_instance)
+
+// VTABLE_FIELD(exception_name);
+// FORALL_VTABLE_FIELD(exception_name, (parameters-or-types));
+// The declaration of the virtual table field. Should be the first declaration in a virtual type.
+#define VTABLE_FIELD(exception_name) VTABLE_TYPE(exception_name) const * virtual_table
+#define FORALL_VTABLE_FIELD(exception_name, parameters) \
+	VTABLE_TYPE(exception_name) parameters const * virtual_table
+
+// VTABLE_INIT(object_reference, exception_name);
+// Sets a virtual table field on an object to the virtual table instance for the type.
+#define VTABLE_INIT(this, exception_name) (this).virtual_table = &VTABLE_NAME(exception_name)
+
+// VTABLE_ASSERTION(exception_name, (parameters...))
+// The assertion that there is an instantiation of the vtable for the exception and types.
+#define VTABLE_ASSERTION(exception_name, parameters) \
+	{ VTABLE_TYPE(exception_name) parameters VTABLE_NAME(exception_name); }
+
+// All internal helper macros begin with an underscore.
+#define _CLOSE(...) __VA_ARGS__ }
+#define _GLUE2(left, right) left##right
+#define _GLUE3(left, middle, right) left##middle##right
+#define _EXC_DISPATCH(to, ...) to(__VA_ARGS__,__cfaehm_base_exception_t,)
+#define _UNPACK(...) __VA_ARGS__
+
+#define _TRIVIAL_EXCEPTION_DECLARATION(exception_name, parent_name, ...) \
 	_VTABLE_DECLARATION(exception_name, parent_name)(); \
 	struct exception_name { \
@@ -46,5 +140,6 @@
 	void ?{}(exception_name & this); \
 	const char * _GLUE2(exception_name,_msg)(exception_name * this)
-#define _INST_TRIVIAL_EXCEPTION(exception_name, parent_name, ...) \
+
+#define _TRIVIAL_EXCEPTION_INSTANCE(exception_name, parent_name, ...) \
 	void ?{}(exception_name & this) { \
 		VTABLE_INIT(this, exception_name); \
@@ -55,16 +150,38 @@
 	_VTABLE_INSTANCE(exception_name, parent_name,)(_GLUE2(exception_name,_msg))
 
-// DATA_EXCEPTION(exception_name)(fields...);
-// Forward declare an exception that adds fields but no features. The added fields go in the
-// second argument list. The virtual table instance must be provided later (see VTABLE_INSTANCE).
-#define DATA_EXCEPTION(...) _EXC_DISPATCH(_DATA_EXCEPTION, __VA_ARGS__)
+#define _FORALL_TRIVIAL_EXCEPTION(exception_name, parent_name, assertions, \
+		parameters, parent_parameters) \
+	_FORALL_VTABLE_DECLARATION(exception_name, parent_name, assertions, \
+		parameters, parent_parameters)(); \
+	forall assertions struct exception_name { \
+		FORALL_VTABLE_FIELD(exception_name, parameters); \
+	}; \
+	_FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters)
+
+#define _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) \
+	forall(_UNPACK assertions | VTABLE_ASSERTION(exception_name, assertions, parameters) ) \
+		/*| { VTABLE_TYPE(exception_name) parameters VTABLE_NAME(exception_name); } ) */ \
+	void ?{}(exception_name parameters & this)
+
+#define _FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters) \
+	_FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) { \
+		VTABLE_INIT(this, exception_name); \
+	}
+
 #define _DATA_EXCEPTION(exception_name, parent_name, ...) \
 	_VTABLE_DECLARATION(exception_name, parent_name)(); \
-	struct exception_name { VTABLE_FIELD(exception_name); _CLOSE
-
-// VTABLE_DECLARATION(exception_name)([new_features...]);
-// Declare a virtual table type for an exception with exception_name. You may also add features
-// (fields on the virtual table) by including them in the second list.
-#define VTABLE_DECLARATION(...) _EXC_DISPATCH(_VTABLE_DECLARATION, __VA_ARGS__)
+	struct exception_name { \
+		VTABLE_FIELD(exception_name); \
+		_CLOSE
+
+#define _FORALL_DATA_EXCEPTION(exception_name, parent_name, \
+		assertions, parameters, parent_parameters) \
+	_FORALL_VTABLE_DECLARATION(exception_name, parent_name, \
+		assertions, parameters, parent_parameters)(); \
+	_FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters); \
+	forall assertions struct exception_name { \
+		FORALL_VTABLE_FIELD(exception_name, parameters); \
+		_CLOSE
+
 #define _VTABLE_DECLARATION(exception_name, parent_name, ...) \
 	struct exception_name; \
@@ -80,9 +197,4 @@
 		_CLOSE
 
-// VTABLE_INSTANCE(exception_name)(msg [, others...]);
-// Create the instance of the virtual table. There must be exactly one instance of a virtual table
-// for each exception type. This fills in most of the fields of the virtual table (uses ?=? and
-// ^?{}) but you must provide the message function and any other fields added in the declaration.
-#define VTABLE_INSTANCE(...) _EXC_DISPATCH(_VTABLE_INSTANCE, __VA_ARGS__)
 #define _VTABLE_INSTANCE(exception_name, parent_name, ...) \
 	void mark_exception(exception_name *) {} \
@@ -95,14 +207,23 @@
 		_CLOSE
 
-// VTABLE_TYPE(exception_name) | VTABLE_NAME(exception_name)
-// Get the name of the vtable type or the name of the vtable instance for an exception type.
-#define VTABLE_TYPE(exception_name) struct _GLUE2(exception_name,_vtable)
-#define VTABLE_NAME(exception_name) _GLUE3(_,exception_name,_vtable_instance)
-
-// VTABLE_FIELD(exception_name);
-// The declaration of the virtual table field. Should be the first declaration in a virtual type.
-#define VTABLE_FIELD(exception_name) VTABLE_TYPE(exception_name) const * virtual_table
-
-// VTABLE_INIT(object_reference, exception_name);
-// Sets a virtual table field on an object to the virtual table instance for the type.
-#define VTABLE_INIT(this, exception_name) (this).virtual_table = &VTABLE_NAME(exception_name)
+#define _FORALL_VTABLE_DECLARATION(exception_name, parent_name, assertions, \
+		parameters, parent_parameters) \
+	forall assertions struct exception_name; \
+	forall assertions VTABLE_TYPE(exception_name) { \
+		VTABLE_TYPE(parent_name) parent_parameters const * parent; \
+		size_t size; \
+		void (*copy)(exception_name parameters * this, exception_name parameters * other); \
+		void (*free)(exception_name parameters & this); \
+		const char * (*msg)(exception_name parameters * this); \
+		_CLOSE
+
+#define _POLY_VTABLE_INSTANCE(exception_name, parent_name, ...) \
+	void mark_exception(exception_name(__VA_ARGS__) *) {} \
+	void _GLUE2(exception_name,_copy)( \
+			exception_name(__VA_ARGS__) * this, exception_name(__VA_ARGS__) * other) { \
+		*this = *other; \
+	} \
+	VTABLE_TYPE(exception_name)(__VA_ARGS__) VTABLE_NAME(exception_name) @= { \
+		&VTABLE_NAME(parent_name), sizeof(exception_name(__VA_ARGS__)), \
+		_GLUE2(exception_name,_copy), ^?{}, \
+		_CLOSE
Index: tests/exceptions/.expect/polymophic.txt
===================================================================
--- tests/exceptions/.expect/polymophic.txt	(revision 21b0a23f5172b5102ba4fe6b283d6d16f97865ba)
+++ tests/exceptions/.expect/polymophic.txt	(revision 21b0a23f5172b5102ba4fe6b283d6d16f97865ba)
@@ -0,0 +1,7 @@
+terminate catch
+resume catch
+caught proxy(char)
+
+-7
+0
+1
Index: tests/exceptions/polymophic.cfa
===================================================================
--- tests/exceptions/polymophic.cfa	(revision 21b0a23f5172b5102ba4fe6b283d6d16f97865ba)
+++ tests/exceptions/polymophic.cfa	(revision 21b0a23f5172b5102ba4fe6b283d6d16f97865ba)
@@ -0,0 +1,72 @@
+// Testing polymophic exception types.
+
+#include <exception.hfa>
+
+FORALL_TRIVIAL_EXCEPTION_(proxy, (otype U3), (U3));
+FORALL_TRIVIAL_INSTANCE_(proxy, (otype U4), (U4))
+
+const char * msg(proxy(int) * this) { return "proxy(int)"; }
+const char * msg(proxy(char) * this) { return "proxy(char)"; }
+POLY_VTABLE_INSTANCE(proxy, int)(msg);
+POLY_VTABLE_INSTANCE(proxy, char)(msg);
+
+void proxy_test () {
+    try {
+		throw (proxy(int)){};
+	} catch (proxy(int) *) {
+		printf("terminate catch\n");
+	}
+
+	try {
+		throwResume (proxy(char)){};
+	} catchResume (proxy(char) *) {
+		printf("resume catch\n");
+	}
+
+	try {
+		throw (proxy(char)){};
+	} catch (proxy(int) *) {
+		printf("caught proxy(int)\n");
+	} catch (proxy(char) *) {
+		printf("caught proxy(char)\n");
+	}
+}
+
+FORALL_DATA_EXCEPTION(cell, (otype T), (T))(
+	T data;
+);
+
+FORALL_DATA_INSTANCE(cell, (otype T), (T))
+
+const char * msg(cell(int) * this) { return "cell(int)"; }
+const char * msg(cell(char) * this) { return "cell(char)"; }
+const char * msg(cell(bool) * this) { return "cell(bool)"; }
+POLY_VTABLE_INSTANCE(cell, int)(msg);
+POLY_VTABLE_INSTANCE(cell, char)(msg);
+POLY_VTABLE_INSTANCE(cell, bool)(msg);
+
+void cell_test(void) {
+	try {
+		cell(int) except;
+		except.data = -7;
+		throw except;
+	} catch (cell(int) * error) {
+		printf("%d\n", error->data);
+	}
+
+	try {
+		cell(bool) ball;
+		ball.data = false;
+		throwResume ball;
+		printf("%i\n", ball.data);
+	} catchResume (cell(bool) * error) {
+		printf("%i\n", error->data);
+		error->data = true;
+	}
+}
+
+int main(int argc, char * argv[]) {
+	proxy_test();
+	printf("\n");
+	cell_test();
+}
