diff --git a/graph/graph/__DEBUG_graph__.rkt b/graph/graph/__DEBUG_graph__.rkt
index bc275db8..a77cac58 100644
--- a/graph/graph/__DEBUG_graph__.rkt
+++ b/graph/graph/__DEBUG_graph__.rkt
@@ -1,5 +1,19 @@
 #lang debug typed/racket
 
+(require "structure.lp2.rkt")
+(require "../type-expander/type-expander.lp2.rkt")
+(require "../lib/low.rkt")
+
+(define-structure st [a Number] [b String])
+(check-equal:? (st 1 "b") (structure [a 1] [b "b"]))
+(check-equal:? (st 1 "b") (structure [a : Number 1] [b : String "b"]))
+(check-equal:? (st 1 "b") ((structure [a : Number] [b : String]) 1 "b"))
+(check-equal:? (st 1 "b") ((structure [a] [b]) 1 "b"))
+(check-equal:? (st 1 "b") ((structure a b) 1 "b"))
+(check-equal:? (st 1 "b") ((structure [a] b) 1 "b"))
+
+
+#|
 (require (submod "graph3.lp2.rkt" test))
 (require "../lib/low.rkt")
 (require racket/list)
@@ -34,3 +48,5 @@
       x))
 
 (forceall 5 g)
+
+|#
\ No newline at end of file
diff --git a/graph/graph/remember.rkt b/graph/graph/remember.rkt
index 168c8fd8..3807ba91 100644
--- a/graph/graph/remember.rkt
+++ b/graph/graph/remember.rkt
@@ -38,3 +38,5 @@
 (structure faa fab fav)
 (structure fba fbv)
 (structure fav)
+(structure a)
+(structure a)
diff --git a/graph/graph/structure.lp2.rkt b/graph/graph/structure.lp2.rkt
index 9ac54a3c..3ff518ea 100644
--- a/graph/graph/structure.lp2.rkt
+++ b/graph/graph/structure.lp2.rkt
@@ -12,12 +12,116 @@ Structures are represented using regular racket @tc[struct]s, see
 @seclink["type-system|structures"]{the overview document}.
 @;secref["structures" #:doc "type-system.scrbl"].
 
+When called, @tc[structure] accepts several syntaxes:
+@tc[(structure [field] …)], which returns a constructor with @tc[∀] types for,
+@tc[(structure [field value] …)], which returns an instance, inferring the type
+of the fields, @tc[(structure [field : type] …)], which returns a constructor
+with the given types, or @tc[(structure [field : type value] …)], which returns
+an instance using the given types. the types have to be all provided, or not
+given at all, but a mix of typed and @tc[∀] is not allowed for now (rationale:
+since typed/racket currently doesn't support named instantiation of polymorphic
+types, it wouldn't be clear what fields the remaining type parameters affect).
+
+@;{(begin-for-syntax
+ (define-syntax-class field-descriptor
+ (pattern
+ (~or field:id
+ [field:id (~maybe (~lit :) type:expr) (~maybe value:expr)]))))}
+
 @chunk[<structure>
        (define-multi-id structure
          #:type-expander structure-type-expander
          #:match-expander structure-match-expander
-         #:call (λ/syntax-parse (_ [field value] ...)
-                  #'((make-structure-constructor field ...) value ...)))]
+         #:call (λ (stx)
+                  (syntax-parse stx
+                    [(_) <hybrid-empty>]
+                    [(_ (~or (~seq (~or-bug [field:id] field:id) …)
+                             (~seq [field:id (~lit :) type:expr] …)
+                             (~seq [field:id value:expr] …)
+                             (~seq [field:id (~lit :) type:expr value:expr] …)))
+                     (define/with-syntax c
+                       #'(make-structure-constructor field …))
+                     (define/with-syntax ct
+                       (if (and (attribute type) (not (stx-null? #'(type …))))
+                           #'(inst c type …)
+                           #'c))
+                     (template (?? (ct value …) ct))])))]
+
+@subsection[#:tag "structure|hybrid-empty"]{Hybrid constructor / instance for
+ the empty structure}
+
+A call to @tc[(structure)] with no field, is ambiguous: it could return a
+constructor function, or an instance. We use @tc[define-struct/exec] to make it
+behave like both.
+
+@CHUNK[<declare-hybrid-empty>
+       (struct empty/noexec-type ())
+       
+       (define-struct/exec (empty/exec-type empty)
+         ()
+         [(λ _ empty-instance) : (→ Any empty)])
+       
+       (define empty-instance (empty/exec-type))]
+
+@CHUNK[<test-hybrid-empty>
+       (check-equal:? empty-instance : empty empty-instance)
+       (check-equal:? empty-instance : empty (empty-instance))
+       (check-equal:? (empty-instance) : empty empty-instance)
+       (check-equal:? (empty-instance) : empty (empty-instance))]
+
+@CHUNK[<test-hybrid-empty-2>
+       (check-equal:? (structure) (structure))
+       (check-equal:? (structure) ((structure)))
+       (check-equal:? ((structure)) (structure))
+       (check-equal:? ((structure)) ((structure)))]
+
+@chunk[<test-structure>
+       (let ()
+         (define-structure empty-st)
+         (define-structure stA [a Number])
+         (check-equal:? (empty-st) ((structure)))
+         (check-not-equal:? (empty-st) (structure [a 1]))
+         (check-not-equal:? (structure) (structure [a 1]))
+         (check-not-equal:? (empty-st) (stA 1))
+         (check-not-equal:? (structure) (stA 1)))
+       #;(let ()
+           (define-structure st [a Number] [b String])
+           (define-structure stA [a Number])
+           (define-structure stABC [a Number] [b String] [c Number])
+           (define st1 (st 1 "b"))
+           (check-equal:? st1 (structure [a 1] [b "b"]))
+           (check-equal:? st1 (structure [a : Number 1] [b : String "b"]))
+           (check-equal:? st1 ((structure [a : Number] [b : String]) 1 "b"))
+           (check-equal:? st1 ((structure [a] [b]) 1 "b"))
+           (check-equal:? st1 ((structure a b) 1 "b"))
+           (check-equal:? st1 ((structure [a] b) 1 "b"))
+           
+           (define st2 (st 2 "b"))
+           (check-not-equal:? st2 st1)
+           (check-not-equal:? st2 (structure [a 1] [b "b"]))
+           (check-not-equal:? st2 (structure [a : Number 1] [b : String "b"]))
+           (check-not-equal:? st2 ((structure [a : Number] [b : String]) 1 "b"))
+           (check-not-equal:? st2 ((structure [a] [b]) 1 "b"))
+           (check-not-equal:? st2 ((structure a b) 1 "b"))
+           (check-not-equal:? st2 ((structure [a] b) 1 "b"))
+           
+           (define sta (stA 1))
+           (check-not-equal:? sta st1)
+           (check-not-equal:? sta (structure [a 1] [b "b"]))
+           (check-not-equal:? sta (structure [a : Number 1] [b : String "b"]))
+           (check-not-equal:? sta ((structure [a : Number] [b : String]) 1 "b"))
+           (check-not-equal:? sta ((structure [a] [b]) 1 "b"))
+           (check-not-equal:? sta ((structure a b) 1 "b"))
+           (check-not-equal:? sta ((structure [a] b) 1 "b"))
+           
+           (define st3 (stABC 1 "b" 3))
+           (check-not-equal:? st3 st1)
+           (check-not-equal:? st3 (structure [a 1] [b "b"]))
+           (check-not-equal:? st3 (structure [a : Number 1] [b : String "b"]))
+           (check-not-equal:? st3 ((structure [a : Number] [b : String]) 1 "b"))
+           (check-not-equal:? st3 ((structure [a] [b]) 1 "b"))
+           (check-not-equal:? st3 ((structure a b) 1 "b"))
+           (check-not-equal:? st3 ((structure [a] b) 1 "b")))]
 
 @chunk[<define-structure>
        (define-syntax (define-structure stx)
@@ -34,16 +138,20 @@ Structures are represented using regular racket @tc[struct]s, see
                   (syntax-case stx2 ()
                     [(_ pat ...) #'(structure [field pat] ...)]))
                 #:else
-                (inst (make-structure-constructor field ...) type ...))]))]
+                (if (not (stx-null? #'(type …)))
+                    #'(inst (make-structure-constructor field ...) type ...)
+                    #'(make-structure-constructor field ...)))]))]
 
 
 @chunk[<test-define-structure>
+       (define-structure empty-st)
        (define-structure st [a Number] [b String])
        (define-structure st2 [b String] [a Number])]
 
 Test constructor:
 
 @chunk[<test-define-structure>
+       (check-equal:? (empty-st) : empty-st (empty-st))
        (check-equal:? (get (st 1 "b") b) : String "b")
        (check-equal:? (get (st2 "a" 2) b) : String "a")]
 
@@ -139,10 +247,18 @@ one low-level @tc[struct] is generated for them.
 @CHUNK[<named-sorted-structures>
        (define-for-syntax named-sorted-structures
          (for/list ([s (remove-duplicates (map (λ (s) (sort s symbol<?))
-                                               (get-remembered 'structure)))]
+                                               <all-remembered-structs+empty>))]
                     [i (in-naturals)])
            `(,(string->symbol (format "struct-~a" i)) . ,s)))]
 
+We add the empty struct (with no fields) to the list of remembered structs as a
+special case, because we need it to define the hybrid instance/constructor in
+section @secref{structure|hybrid-empty}.
+
+@chunk[<all-remembered-structs+empty>
+       (cons '()
+             (get-remembered 'structure))]
+
 We will also need utility functions to sort the fields when querying this
 associative list.
 
@@ -175,8 +291,8 @@ be used to make @tc[structure] instances like this:
 
 @chunk[<test-make-structure-constructor>
        (check-equal? (begin ((make-structure-constructor a b c) 1 "b" #t)
-                            #t)
-                     #t)]
+                            'it-works)
+                     'it-works)]
 
 To create such an instance, we use the underlying @tc[struct]'s constructor.
 First, we need to check if the list of fields was already remembered, in which
@@ -332,8 +448,8 @@ instead of needing an extra recompilation.
                 (let ()
                   (define/with-syntax ([sorted-field sorted-type] ...)
                     (sort-car-fields #'((field type) ...)))
-                  (if (null? (syntax->list #'(sorted-type ...)))
-                      (fields→stx-name #'(field ...))
+                  (if (stx-null? #'(sorted-type ...))
+                      (fields→stx-name #'(field …)) ; #'(field …) is empty here.
                       #`(#,(fields→stx-name #'(field ...)) sorted-type ...)))
                 (remember-all-errors #'U stx #'(field ...)))]))]
 
@@ -417,6 +533,7 @@ chances that we could write a definition for that identifier.
            (require (for-syntax racket
                                 racket/syntax
                                 syntax/parse
+                                syntax/parse/experimental/template
                                 mzlib/etc
                                 racket/struct-info
                                 syntax/stx
@@ -441,6 +558,9 @@ chances that we could write a definition for that identifier.
            <sort-fields>
            <declare-all-structs>
            <fields→stx-name>
+           <declare-hybrid-empty>
+           (require typed/rackunit)
+           <test-hybrid-empty>
            <make-structure-constructor>
            <delayed-error-please-recompile>
            
@@ -468,7 +588,9 @@ chances that we could write a definition for that identifier.
            <test-get-field>
            <test-match-expander>
            <test-type-expander>
+           <test-structure>
            <test-define-structure>
+           <test-hybrid-empty-2>
            
            (require (submod ".." doc))))]
 
diff --git a/graph/lib/low.rkt b/graph/lib/low.rkt
index ee39d822..64fb6d9d 100644
--- a/graph/lib/low.rkt
+++ b/graph/lib/low.rkt
@@ -91,12 +91,51 @@
   (require 'mb)
   (check-equal? require-provide-foo 7))
 
-;; ==== low/define-syntax-parse.rkt ====
+;; ==== low/syntax-parse.rkt ====
 (require syntax/parse
-         syntax/parse/define)
+         syntax/parse/define
+         (for-syntax racket/syntax))
 
 (provide define-syntax/parse
-         λ/syntax-parse)
+         λ/syntax-parse
+         ~maybe
+         ~lit
+         ~or-bug)
+
+(define-syntax ~maybe
+  (pattern-expander
+   (λ (stx)
+     (syntax-case stx ()
+       [(~maybe pat ...)
+        (datum->syntax #'~maybe
+                       #'(~optional (~seq pat ...)))]))))
+
+;; Circumvent the bug that causes "syntax-parse: duplicate attribute in: a" in:
+;; (syntax-parse #'(x y z) [((~or a (a b c)) ...) #'(a ...)])
+(define-syntax ~or-bug
+  (pattern-expander
+   (λ (stx)
+     (syntax-case stx ()
+       [(~or-bug pat ...)
+        (let ()
+          (define (s stx) (datum->syntax #'~or-bug stx))
+          ;(define/with-syntax ~~and (datum->syntax #'~or-bug #'~and))
+          ;(define/with-syntax ~~parse (datum->syntax #'~or-bug #'~parse))
+          ;(define/with-syntax ~~or (datum->syntax #'~or-bug #'~parse))
+          #;#'(~~and x (~~parse (~~or pat ...) #'x))
+          #`(#,(s #'~and) x (#,(s #'~parse) #,(s #'(~or pat ...)) #'x))
+          )]))))
+
+(define-syntax ~lit
+  (pattern-expander
+   (λ (stx)
+     (syntax-case stx ()
+       [(~lit lit)
+        (datum->syntax #'~lit
+                       #'(~literal lit))]
+       [(~lit lit …)
+        (datum->syntax #'lit
+                       #'(~seq (~literal lit)))]))))
 
 (begin-for-syntax
   (require (for-syntax racket/base
@@ -132,7 +171,8 @@
               syntax/parse/experimental/template)
   typed/rackunit)
 
-(provide check-equal:?)
+(provide check-equal:?
+         check-not-equal:?)
 
 ;; TODO: this won't expand types in the ann.
 
@@ -140,7 +180,15 @@
   (check-equal:? actual
                  (~optional (~seq (~datum :) type))
                  expected)
-  (template (check-equal? (?? (ann actual type) actual) expected)))
+  (template (check-equal? (?? (ann actual type) actual)
+                          (?? (ann expected type) expected))))
+
+(define-syntax/parse
+  (check-not-equal:? actual
+                     (~optional (~seq (~datum :) type))
+                     expected)
+  (template (check-not-equal? (?? (ann actual type) actual)
+                              (?? (ann expected type) expected))))
 
 ;; ==== low/typed-fixnum.rkt ===
 
@@ -637,14 +685,14 @@
          (define/with-syntax pat
            (format-id #'base.id (syntax-e #'format) #'base.id))
          (define/with-syntax pat-dotted ((attribute base.make-dotted) #'pat))
-
+         
          (define/with-syntax format-temp-ids*
            ((attribute base.wrap) #'(compose car (curry format-temp-ids format))
                                   (λ (x deepest?)
                                     (if deepest?
                                         x
                                         #`(curry stx-map #,x)))))
-
+         
          (syntax-cons-property
           (template (begin (define/with-syntax pat-dotted
                              (format-temp-ids* #'base))
diff --git a/graph/type-expander/multi-id.lp2.rkt b/graph/type-expander/multi-id.lp2.rkt
index 1a6c866e..8c1f8643 100644
--- a/graph/type-expander/multi-id.lp2.rkt
+++ b/graph/type-expander/multi-id.lp2.rkt
@@ -14,16 +14,21 @@ TODO: maybe we should cache @tc[p-else] and @tc[p-get].
           'self
           (format "can't set ~a" (syntax->datum #'self)))]
 
-@chunk[<stx-class-kw-else>
+@CHUNK[<stx-class-kw-else>
        (define-splicing-syntax-class kw-else
+         #:attributes (p-just-set! p-just-call p-just-id)
          (pattern (~seq #:mutable-else p-else)
                   #:with p-just-set! #'#'(set! p-else . rest)
                   #:with p-just-call #'#'(p-else . rest)
                   #:with p-just-id #'#'p-else)
          (pattern (~seq #:else p-else)
                   #:with p-just-set! <fail-set!>
-                  #:with p-just-call #'#'(p-else . rest)
-                  #:with p-just-id #'#'p-else))]
+                  #:with p-just-call #'#`(#,p-else . rest)
+                  #:with p-just-id #'p-else)
+         (pattern (~seq #:mutable-else-id p-else-id)
+                  #:with (:kw-else) #'(#:mutable-else #'p-else-id))
+         (pattern (~seq #:else-id p-else-id)
+                  #:with (:kw-else) #'(#:else #'p-else-id)))]
 
 @chunk[<stx-class-kw-set!+call+id>
        (define-splicing-syntax-class kw-set!+call+id
@@ -31,6 +36,10 @@ TODO: maybe we should cache @tc[p-else] and @tc[p-get].
                         (~optional (~or (~seq #:call p-user-call:expr)
                                         (~seq #:call-id p-user-call-id:id)))
                         (~optional (~seq #:id p-user-id:expr)))
+                  ; TODO: add #:macro with prop:procedure, see
+                  ; file:///usr/local/racket-6.3.0.4/doc/syntax/stxparse-patter
+                  ; ns.html?q=~optional#%28def._%28%28lib._syntax%2Fparse..rkt%
+                  ; 29._prop~3apattern-expander%29%29
                   #:attr p-just-set!
                   (and (attribute p-user-set!) #'(p-user-set! stx))
                   #:attr p-just-call
@@ -129,6 +138,31 @@ to configure).
 
 Test with @tc[#:else]:
 
+@chunk[<test-multi-id>
+       (define-multi-id bar-id
+         #:type-expander
+         (λ (stx) #'(List `,(Repeat 'x 2) Number))
+         #:match-expander
+         (λ (stx) #'(cons _ _))
+         #:custom-write
+         (λ (self port mode) (display "custom-write for foo" port))
+         #:else-id p1)
+       
+       (check-equal? (ann (ann '((x x) 79) bar)
+                          (List (List 'x 'x) Number))
+                     '((x x) 79))
+       
+       ;(set! bar 'bad)
+       
+       (let ([test-match (λ (val) (match val [(bar-id) #t] [_ #f]))])
+         (check-equal? (test-match '(a . b)) #t)
+         (check-equal? (test-match #(1 2 3)) #f))
+
+       (let ([f-bar-id bar-id])
+         (check-equal? (f-bar-id 6) 7))
+       (check-equal? (bar-id 6) 7)
+       (check-equal? (map bar-id '(1 5 3 4 2)) '(2 6 4 5 3))]
+
 @chunk[<test-multi-id>
        (define-multi-id bar
          #:type-expander
@@ -137,7 +171,7 @@ Test with @tc[#:else]:
          (λ (stx) #'(cons _ _))
          #:custom-write
          (λ (self port mode) (display "custom-write for foo" port))
-         #:else p1)
+         #:else #'p1)
        
        (check-equal? (ann (ann '((x x) 79) bar)
                           (List (List 'x 'x) Number))
diff --git a/graph/type-expander/type-expander.lp2.rkt b/graph/type-expander/type-expander.lp2.rkt
index c7efc146..709ba9fa 100644
--- a/graph/type-expander/type-expander.lp2.rkt
+++ b/graph/type-expander/type-expander.lp2.rkt
@@ -40,9 +40,9 @@ contain the expander procedure, or directly an expander procedure.
                [else
                 (raise-argument-error
                  'prop:type-expander-guard
-                 (~a "an exact non-negative integer designating a field index "
-                     "within the structure that should contain a procedure of "
-                     "arity 1, or a procedure of arity 1.")
+                 (~a "a procedure of arity 1, or an exact non-negative integer "
+                     "designating a field index within the structure that "
+                     "should contain a procedure of arity 1.")
                  val)]))]
 
 If the value is a field index, it should be within bounds. The
@@ -269,7 +269,7 @@ ususal @code{#'()} and @code{#`()}. In order to expand types and bind type
 variables in the result, we define two template metafunctions:
 
 @chunk[<template-metafunctions>
-       (define-template-metafunction (template-expand-type stx)
+       (define-template-metafunction (tmpl-expand-type stx)
          (syntax-parse stx
            [(_ () t) (expand-type #'t)]
            [(_ tvars t) (expand-type (bind-type-vars #'tvars #'t))]))]
@@ -329,7 +329,7 @@ them.
                                     (~optional default:expr)])
                   #:with tvars tvars
                   #:with (expanded ...)
-                  (template (kw [id (?@ : (template-expand-type tvars type))
+                  (template (kw [id (?@ : (tmpl-expand-type tvars type))
                                  (?? default)]))))
        
        (define-splicing-syntax-class (new-mand-formal tvars)
@@ -339,7 +339,7 @@ them.
          (pattern [id:id :colon type:expr]
                   #:with tvars tvars
                   #:with (expanded ...)
-                  (template ([id : (template-expand-type tvars type)])))
+                  (template ([id : (tmpl-expand-type tvars type)])))
          (pattern (~var kw (new-kw-formal tvars))
                   #:with (expanded ...) #'(kw.expanded ...)))
        
@@ -348,7 +348,7 @@ them.
          (pattern [id:id (~optional (~seq :colon type:expr)) default:expr]
                   #:with tvars tvars
                   #:with (expanded ...)
-                  (template ([id (?@ : (template-expand-type tvars type))
+                  (template ([id (?@ : (tmpl-expand-type tvars type))
                               default])))
          (pattern (~var kw (new-kw-formal tvars))
                   #:with (expanded ...) #'(kw.expanded ...)))
@@ -363,8 +363,8 @@ them.
                         (~seq (~datum ...) bound:expr)))
                   #:with tvars tvars
                   #:with expanded
-                  (template (rest : (template-expand-type tvars type)
-                                  (?? x* (?@ (... ...) (template-expand-type
+                  (template (rest : (tmpl-expand-type tvars type)
+                                  (?? x* (?@ (... ...) (tmpl-expand-type
                                                         tvars bound)))))))
        
        (define-syntax-class (new-lambda-formals tvars)
@@ -394,7 +394,7 @@ them.
                   #:with tvars tvars
                   #:with expanded
                   (template (name
-                             (?? (?@ : (template-expand-type tvars type)))))))
+                             (?? (?@ : (tmpl-expand-type tvars type)))))))
        
        (define-syntax-class (new-name-or-parenthesised-annotated-name tvars)
          (pattern name:id
@@ -402,7 +402,7 @@ them.
          (pattern [id:id :colon type:expr]
                   #:with tvars tvars
                   #:with expanded
-                  (template [id : (template-expand-type tvars type)])))]
+                  (template [id : (tmpl-expand-type tvars type)])))]
 
 @subsection{@racket[define-type]}
 
@@ -412,7 +412,7 @@ them.
            [(_ (~or name:id (name:id TVar ...)) type . rest)
             (template
              (define-type (?? (name TVar ...) name)
-               (template-expand-type (?? (TVar ...) ()) type)
+               (tmpl-expand-type (?? (TVar ...) ()) type)
                . rest))]))]
 
 @chunk[<test-define-type>
@@ -437,7 +437,7 @@ them.
                e ...)
             (template
              (define (?@ . tvars) (?? v formals.expanded)
-               (?? (?@ : (template-expand-type tvars.vars type)))
+               (?? (?@ : (tmpl-expand-type tvars.vars type)))
                e ...))]))]
 
 @CHUNK[<test-define>
@@ -471,7 +471,7 @@ them.
                (~optional (~seq :colon ret-type))
                e ...)
             (template (lambda (?@ . tvars) args.expanded
-                        (?? (?@ : (template-expand-type tvars.vars ret-type)))
+                        (?? (?@ : (tmpl-expand-type tvars.vars ret-type)))
                         e ...))]))]
 
 @CHUNK[<test-lambda>
@@ -495,8 +495,12 @@ them.
                (~and name+parent (~or name:id [name:id parent:id]))
                ([field:id :colon type:expr] ...)
                . rest)
-            (template (struct (?? tvars.maybe) name+parent
-                        ([field : (template-expand-type tvars.vars type)] ...)
+            (displayln #'(tvars= tvars
+                                 name+parent= name+parent
+                                 field...= field ...
+                                 rest= rest))
+            (template (struct (?? tvars.maybe) name (?? parent)
+                        ([field : (tmpl-expand-type tvars.vars type)] ...)
                         . rest))]))]
 
 @chunk[<test-struct>
@@ -507,6 +511,11 @@ them.
        (struct s4 () #:transparent)
        (struct (A B) s5 ([x : A] [y : B]) #:transparent)
        (struct (A B) s6 () #:transparent)
+       (struct (s7 s2) ([z : String]) #:transparent)
+       (struct (A) (s8 s3) ([z : A]) #:transparent)
+       (struct (A B C) (s9 s5) ([z : C]) #:transparent)
+       (struct (A B C) (s10 s2) ([z : C]) #:transparent)
+       (struct (A B C) (s11 s5) ([z : C]))
        
        (check (λ (a b) (not (equal? a b))) (s0) (s0))
        (check-equal? (s1-x (s1 123)) 123)
@@ -518,13 +527,119 @@ them.
        (check-equal? (s5-x (s5 6 7)) 6)
        (check-equal? (s5-y (s5 6 7)) 7)
        (check-equal? (s5 6 7) (s5 6 7))
-       (check-equal? (s6) (s6))]
+       (check-equal? ((inst s5 Number String) 6 "g") (s5 6 "g"))
+       (check-equal? (s6) (s6))
+       (check-equal? ((inst s6 Number String)) (s6))
+       
+       ;(check-equal? (s7-x (s7 -1 -2 "c") -1))
+       ;(check-equal? (s7-y (s7 -1 -2 "c") -2))
+       (check-equal? (s7-z (s7 -1 -2 "c")) "c")
+       (check-equal? (s2-x (s7 -1 -2 "c")) -1)
+       (check-equal? (s2-y (s7 -1 -2 "c")) -2)
+       (check-not-equal? (s7 -1 -2 "c") (s7 -1 -2 "c"))
+       (check-not-exn (λ () (ann (s7 -1 -2 "c") s2)))
+       (check-true (s2? (s7 -1 -2 "c")))
+       
+       ;(check-equal? (s8-x (s8 -1 -2 "c") -1))
+       ;(check-equal? (s8-y (s8 -1 -2 "c") -2))
+       (check-equal? (s8-z (s8 -1 -2 "c")) "c")
+       (check-equal? (s3-x (s8 -1 -2 "c")) -1)
+       (check-equal? (s3-y (s8 -1 -2 "c")) -2)
+       (check-equal? (s8 -1 -2 "c") (s8 -1 -2 "c"))
+       (check-equal? ((inst s8 String) -1 -2 "c") (s8 -1 -2 "c"))
+       (check-not-exn (λ () (ann ((inst s8 String) -1 -2 "c") s3)))
+       (check-true (s3? ((inst s8 String) -1 -2 "c")))
+       
+       ;(check-equal? (s9-x (s9 8 9 10)) 8)
+       ;(check-equal? (s9-y (s9 8 9 10)) 9)
+       (check-equal? (s9-z (s9 8 9 10)) 10)
+       (check-equal? (s5-x (s9 8 9 10)) 8)
+       (check-equal? (s5-y (s9 8 9 10)) 9)
+       (check-equal? (s9 8 9 10) (s9 8 9 10))
+       ;(check-not-exn (λ () (ann ((inst s9 Number Symbol String) 8 'i "j");;;;;;;;;;;;;;
+       ;                          (Struct s5))));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+       (check-not-exn (λ () (ann ((inst s9 Number Symbol String) 8 'i "j")
+                                 (s5 Number Symbol))))
+       (check-true (s5? ((inst s9 Number Symbol String) -1 'i "j")))
+       (check-not-equal? (s10 11 12 13) (s10 11 12 13))
+       (check-not-equal? (s11 14 15 16) (s11 14 15 16))]
+
+@subsection{@racket[define-struct/exec]}
+
+@chunk[<define-struct/exec>
+       (define-syntax (new-define-struct/exec stx)
+         (syntax-parse stx
+           [(_ (~and name+parent (~or name:id [name:id parent:id]))
+               ([field:id (~maybe :colon type:expr)] ...)
+               [proc :colon proc-type])
+            (template (define-struct/exec name+parent
+                        ([field (?? (?@ : (tmpl-expand-type () type)))] ...)
+                        [proc : (tmpl-expand-type () proc-type)]))]))]
+
+@chunk[<test-define-struct/exec>
+       (define-struct/exec se0 ()
+         ;[(λ (self v) (cons self v)) : (∀ (A) (→ se0 A (Pairof se0 A)))])
+         [(λ (self v) (cons self v)) : (→ se0 Any (Pairof se0 Any))])
+       (define-struct/exec se1 ([x : Number])
+         ;[(λ (self v) (cons self v)) : (∀ (A) (→ se0 A (Pairof se0 A)))])
+         [(λ (self v) (cons self v)) : (→ se1 Any (Pairof se1 Any))])
+       (define-struct/exec se2 ([x : Number] [y : Number])
+         [(λ (self v) (cons self v)) : (→ se2 Any (Pairof se2 Any))])
+       (define-struct/exec (se3 se2) ([z : String])
+         [(λ (self v w) (list self v w))
+          ;: (∀ (A B) (→ se3 A B (List se2 A B)))])
+          : (→ se3 Any Any (List se2 Any Any))])
+       (define-struct/exec (se4 se2) ([z : String])
+         [(λ (self v w) (list self v w))
+          ;: (∀ (A B) (→ se4 A B (List se2 A B)))])
+          : (→ se4 Any (→ Number Number) (List se2 Any (→ Number Number)))])
+       
+       (check (λ (a b) (not (equal? a b))) (se0) (se0))
+       (check-equal? (cdr ((se0) 'a)) 'a)
+       (check-not-exn (λ () (ann (car ((se0) 'a)) se0)))
+       (check-true (se0? (car ((se0) 'a))))
+       
+       (check (λ (a b) (not (equal? a b))) (se1 123) (se1 123))
+       (check-equal? (se1-x (se1 123)) 123)
+       (check-equal? (se1-x (car ((se1 123) 'b))) 123)
+       (check-equal? (cdr ((se1 123) 'b)) 'b)
+       (check-not-exn (λ () (ann (car ((se1 123) 'b)) se1)))
+       (check-true (se1? (car ((se1 123) 'b))))
+       
+       (check (λ (a b) (not (equal? a b))) (se2 2 3) (se2 2 3))
+       (check-equal? (se2-x (se2 2 3)) 2)
+       (check-equal? (se2-y (se2 2 3)) 3)
+       (check-equal? (se2-x (car ((se2 2 3) 'c))) 2)
+       (check-equal? (se2-y (car ((se2 2 3) 'c))) 3)
+       (check-equal? (cdr ((se2 2 3) 'c)) 'c)
+       (check-not-exn (λ () (ann (car ((se2 2 3) 'c)) se2)))
+       (check-true (se2? (car ((se2 2 3) 'c))))
+
+       (check (λ (a b) (not (equal? a b))) (se3 4 5 "f") (se3 4 5 "f"))
+       (check-equal? (se2-x (se3 4 5 "f")) 4)
+       (check-equal? (se2-y (se3 4 5 "f")) 5)
+       (check-equal? (se3-z (se3 4 5 "f")) "f")
+       (check-equal? (se2-x (car ((se3 4 5 "f") 'd 'e))) 2)
+       (check-equal? (se2-y (car ((se3 4 5 "f") 'd 'e))) 3)
+       (check-equal? (let ([ret : Any (car ((se3 4 5 "f") 'd 'e))])
+                       (if (se3? ret)
+                           (se3-z ret)
+                           "wrong type!"))
+                     "f")
+       (check-equal? (cadr ((se3 4 5 "f") 'd 'e)) 'd)
+       (check-equal? (caddr ((se3 4 5 "f") 'd 'e)) 'e)
+       (check-equal? ((caddr ((se4 4 5 "f") 'd (λ ([x : Number]) (* x 2)))) 123)
+                     246)
+       (check-not-exn (λ () (ann (car ((se3 4 5 "f") 'd 'e)) se2)))
+       (check-not-exn (λ () (ann (car ((se3 4 5 "f") 'd 'e)) se3)))
+       (check-true (se2? (car ((se2 2 3) 'd))))
+       (check-true (se3? (car ((se2 2 3) 'e))))]
 
 @subsection{@racket[ann]}
 
 @chunk[<ann>
        (define-syntax/parse (new-ann value:expr (~optional :colon) type:expr)
-         (template (ann value (template-expand-type () type))))]
+         (template (ann value (tmpl-expand-type () type))))]
 
 @chunk[<test-ann>
        (let ()
@@ -543,8 +658,8 @@ them.
        (define-syntax/parse (new-inst v
                                       (~optional :colon) t ...
                                       (~optional (~seq last (~datum ...) b:id)))
-         (template (inst v (template-expand-type () t) ...
-                         (?? (?@ (template-expand-type () last)
+         (template (inst v (tmpl-expand-type () t) ...
+                         (?? (?@ (tmpl-expand-type () last)
                                  (... ...) b)))))]
 
 @chunk[<test-inst>
@@ -577,8 +692,8 @@ them.
             e:expr] ...)
           . rest)
          (template
-          (let (?? (?@ loop (?? (?@ : (template-expand-type tvars.vars
-                                                            return-type)))))
+          (let (?? (?@ loop (?? (?@ : (tmpl-expand-type tvars.vars
+                                                        return-type)))))
             (?@ . tvars)
             ([(?@ . name.expanded) e] ...)
             . rest)))]
@@ -664,7 +779,7 @@ them.
 
 @chunk[<make-predicate>
        (define-syntax/parse (new-make-predicate type:expr)
-         (template (make-predicate (template-expand-type () type))))]
+         (template (make-predicate (tmpl-expand-type () type))))]
 
 @chunk[<test-make-predicate>
        (let ()
@@ -781,7 +896,7 @@ yet.
         do:
         with-handlers
         define-struct/exec:
-        define-struct/exec)]
+        #|define-struct/exec|#)]
 
 @section{Future work}
 
@@ -863,7 +978,8 @@ We can finally define the overloaded forms, as well as the extra
          (require (for-syntax racket
                               racket/syntax
                               syntax/parse
-                              syntax/parse/experimental/template)
+                              syntax/parse/experimental/template
+                              "../lib/low-untyped.rkt")
                   "../lib/low.rkt")
          
          (require (submod ".." expander))
@@ -880,6 +996,7 @@ We can finally define the overloaded forms, as well as the extra
                               [new-lambda lambda]
                               [new-lambda λ]
                               [new-struct struct]
+                              [new-define-struct/exec define-struct/exec]
                               [new-ann ann]
                               [new-inst inst]
                               [new-let let]
@@ -897,6 +1014,7 @@ We can finally define the overloaded forms, as well as the extra
          <define>
          <lambda>
          <struct>
+         <define-struct/exec>
          <ann>
          <inst>
          <let>
@@ -921,6 +1039,7 @@ And, last but not least, we will add a @tc[test] module.
          <test-define>
          <test-lambda>
          <test-struct>
+         <test-define-struct/exec>
          <test-ann>
          <test-inst>
          <test-let>