Index: src/AST/Expr.cpp
===================================================================
--- src/AST/Expr.cpp	(revision 490fb92ee824a236b6dd44604bfed5090c7acc95)
+++ src/AST/Expr.cpp	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -102,4 +102,29 @@
 	}
 	return ret;
+}
+
+// --- VariableExpr
+
+VariableExpr::VariableExpr( const CodeLocation & loc )
+: Expr( loc ), var( nullptr ) {}
+
+VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v )
+: Expr( loc ), var( v ) {
+	assert( var );
+	assert( var->get_type() );
+	result = shallowCopy( var->get_type() );
+}
+
+bool VariableExpr::get_lvalue() const {
+	// It isn't always an lvalue, but it is never an rvalue.
+	return true;
+}
+
+VariableExpr * VariableExpr::functionPointer(
+		const CodeLocation & loc, const FunctionDecl * decl ) {
+	// wrap usually-determined result type in a pointer
+	VariableExpr * funcExpr = new VariableExpr{ loc, decl };
+	funcExpr->result = new PointerType{ funcExpr->result };
+	return funcExpr;
 }
 
@@ -238,29 +263,4 @@
 }
 
-// --- VariableExpr
-
-VariableExpr::VariableExpr( const CodeLocation & loc )
-: Expr( loc ), var( nullptr ) {}
-
-VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v )
-: Expr( loc ), var( v ) {
-	assert( var );
-	assert( var->get_type() );
-	result = shallowCopy( var->get_type() );
-}
-
-bool VariableExpr::get_lvalue() const {
-	// It isn't always an lvalue, but it is never an rvalue.
-	return true;
-}
-
-VariableExpr * VariableExpr::functionPointer(
-		const CodeLocation & loc, const FunctionDecl * decl ) {
-	// wrap usually-determined result type in a pointer
-	VariableExpr * funcExpr = new VariableExpr{ loc, decl };
-	funcExpr->result = new PointerType{ funcExpr->result };
-	return funcExpr;
-}
-
 // --- ConstantExpr
 
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision 490fb92ee824a236b6dd44604bfed5090c7acc95)
+++ src/AST/Expr.hpp	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -250,4 +250,23 @@
 };
 
+/// A reference to a named variable.
+class VariableExpr final : public Expr {
+public:
+	readonly<DeclWithType> var;
+
+	VariableExpr( const CodeLocation & loc );
+	VariableExpr( const CodeLocation & loc, const DeclWithType * v );
+
+	bool get_lvalue() const final;
+
+	/// generates a function pointer for a given function
+	static VariableExpr * functionPointer( const CodeLocation & loc, const FunctionDecl * decl );
+
+	const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	VariableExpr * clone() const override { return new VariableExpr{ *this }; }
+	MUTATE_FRIEND
+};
+
 /// Address-of expression `&e`
 class AddressExpr final : public Expr {
@@ -390,23 +409,4 @@
 	friend class ::ConverterOldToNew;
 	friend class ::ConverterNewToOld;
-};
-
-/// A reference to a named variable.
-class VariableExpr final : public Expr {
-public:
-	readonly<DeclWithType> var;
-
-	VariableExpr( const CodeLocation & loc );
-	VariableExpr( const CodeLocation & loc, const DeclWithType * v );
-
-	bool get_lvalue() const final;
-
-	/// generates a function pointer for a given function
-	static VariableExpr * functionPointer( const CodeLocation & loc, const FunctionDecl * decl );
-
-	const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
-	VariableExpr * clone() const override { return new VariableExpr{ *this }; }
-	MUTATE_FRIEND
 };
 
Index: src/AST/Type.cpp
===================================================================
--- src/AST/Type.cpp	(revision 490fb92ee824a236b6dd44604bfed5090c7acc95)
+++ src/AST/Type.cpp	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -157,4 +157,10 @@
 
 template<typename decl_t>
+SueInstType<decl_t>::SueInstType(
+	const base_type * b, std::vector<ptr<Expr>> && params,
+	CV::Qualifiers q, std::vector<ptr<Attribute>> && as )
+: BaseInstType( b->name, std::move(params), q, std::move(as) ), base( b ) {}
+
+template<typename decl_t>
 bool SueInstType<decl_t>::isComplete() const {
 	return base ? base->body : false;
Index: src/AST/Type.hpp
===================================================================
--- src/AST/Type.hpp	(revision 490fb92ee824a236b6dd44604bfed5090c7acc95)
+++ src/AST/Type.hpp	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -302,7 +302,4 @@
 class FunctionType final : public ParameterizedType {
 public:
-//	std::vector<ptr<DeclWithType>> returns;
-//	std::vector<ptr<DeclWithType>> params;
-
 	std::vector<ptr<Type>> returns;
 	std::vector<ptr<Type>> params;
@@ -345,4 +342,9 @@
 	: ParameterizedType(q, std::move(as)), params(), name(n) {}
 
+	BaseInstType(
+		const std::string& n, std::vector<ptr<Expr>> && params,
+		CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
+	: ParameterizedType(q, std::move(as)), params(std::move(params)), name(n) {}
+
 	BaseInstType( const BaseInstType & o );
 
@@ -369,5 +371,9 @@
 
 	SueInstType(
-		const decl_t * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
+		const base_type * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
+
+	SueInstType(
+		const base_type * b, std::vector<ptr<Expr>> && params,
+		CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
 
 	bool isComplete() const override;
Index: src/AST/porting.md
===================================================================
--- src/AST/porting.md	(revision 490fb92ee824a236b6dd44604bfed5090c7acc95)
+++ src/AST/porting.md	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -30,4 +30,8 @@
   * Base nodes now override `const Node * accept( Visitor & v ) const = 0` with, e.g. `const Stmt * accept( Visitor & v ) const override = 0`
 * `PassVisitor` is replaced with `ast::Pass`
+  * Most one shot uses can use `ast::Pass::run` and `ast::Pass::read`.
+
+`WithConstTypeSubstitution`
+* `env` => `typeSubs`
 
 ## Structural Changes ##
@@ -146,4 +150,9 @@
   * allows `newObject` as just default settings
 
+`FunctionDecl`
+* `params` and `returns` added.
+  * Contain the declarations of the parameters and return variables.
+  * Types should match (even be shared with) the fields of `type`.
+
 `NamedTypeDecl`
 * `parameters` => `params`
@@ -154,4 +163,7 @@
 `AggregateDecl`
 * `parameters` => `params`
+
+`StructDecl`
+* `makeInst` replaced by better constructor on `StructInstType`.
 
 `Expr`
@@ -245,5 +257,5 @@
 * **TODO** move `kind`, `typeNames` into code generator
 
-`ReferenceToType`
+`ReferenceToType` => `BaseInstType`
 * deleted `get_baseParameters()` from children
   * replace with `aggr() ? aggr()->params : nullptr`
@@ -261,5 +273,10 @@
 * `returnVals` => `returns`
 * `parameters` => `params`
+  * Both now just point at types.
 * `bool isVarArgs;` => `enum ArgumentFlag { FixedArgs, VariableArgs }; ArgumentFlag isVarArgs;`
+
+`SueInstType`
+* Template class, with specializations and using to implement some other types:
+  * `StructInstType`, `UnionInstType` & `EnumInstType`
 
 `TypeInstType`
