anchor.diff:        type MalTypeType-methods dup @ 1+ dup rot ! ( new-count )
         1- dup type MalTypeType-method-keys @ idx pxt array-insert ( old-count new-array )
           type MalTypeType-method-keys ! ( old-count )
  -      \ cr ." before: " ObjList MalTypeType-method-vals @ @ . cr
  +      \ cr ." before: " MalList MalTypeType-method-vals @ @ . cr
         type MalTypeType-method-vals @ idx ixt array-insert ( new-array )
           type MalTypeType-method-vals !
  -      \ cr ." after: " ObjList MalTypeType-method-vals @ @ . cr
  +      \ cr ." after: " MalList MalTypeType-method-vals @ @ . cr
       endif
     endif
     type
     ;
   
  -\ Examples of making new protocol methods (without a protocol to group them yet!)
  -: pr-str [ latestxt ] literal execute-method ;
  -: conj   [ latestxt ] literal execute-method ;
  -
  -\ Examples of extending existing protocol methods to existing type
  -MalDefault ' pr-str :noname s" #<MalObject>" ; extend-method*
  -ObjList ' pr-str :noname drop s" #<ObjList>" ; extend-method*
  -ObjList ' conj :noname ." not yet done" ; extend-method*
  -
  -\ Run some protocol methods!
  -ObjList new pr-str type
  -ObjList new conj
  +
  +\ def-protocol-method pr-str   ...can be written:
  +\ : pr-str ( obj -- str ) [ latestxt ] literal execute-method ;
  +: def-protocol-method ( "name" -- )
  +    create latestxt ,
  +  does> ( ??? obj xt-ref -- ??? )
  +    @ execute-method ;
  +
  +: extend ( type -- type pxt <noname...>)
  +    parse-name find-name name>int ( type pxt )
  +    :noname
  +    ;
  +
  +: ;; ( type pxt <noname...> -- type )
  +    [compile] ; ( type pxt ixt )
  +    extend-method*
  +    ; immediate
   
   (
  -  method-count 1+ to method-count
  -
  +\ These whole-protocol names are only needed for 'satisfies?':
   protocol IPrintable
  -  method% pr-str
  +  def-protocol-method pr-str
   end-protocol
  -)
  -
  -(
  -ObjList IPrintable extend
  -
  +
  +MalList IPrintable extend
     ' pr-str :noname drop s" <unprintable>" ; extend-method*
   
     extend-method pr-str
  -    drop s" <unprintable>" ;
  +    drop s" <unprintable>" ;;
   end-extend
   )
   
  -\ new-obj
  -
  -\ new-instance
  -
  -
  -\ maybe useful for debugging?
  -: p dup . ;
  -: @p dup @ dup . ;
  -
  -(
  -
  -create buff 128 allot
  -
  -." user> "
  -
  -buff 128 stdin read-line throw
  -
  -buff c@ .
  -buff 5 + c@ .
  -
  -S" Hello" dup . type
  -
  -
  -)
  -
  -
  -cr
  +\ Examples of making new protocol methods (without a protocol to group them yet!)
  +def-protocol-method pr-buf ( str-addr str-len this -- str-addr str-len )
  +def-protocol-method conj ( obj this -- this )
  +
  +: pr-str { obj }
  +    new-str obj pr-buf ;
  +
  +\ Examples of extending existing protocol methods to existing type
  +MalDefault
  +  extend pr-buf
  +    { this }
  +    s" #<MalObject" str-append a-space
  +    this int>str str-append
  +    s" >" str-append ;;
  +  extend conj   ( obj this -- this )
  +    swap drop ;;
  +drop
  +
  +MalNil
  +  extend pr-buf
  +    drop s" nil" str-append ;;
  +  ' conj ' MalList/conj extend-method*
  +drop
  +
  +MalList
  +  extend pr-buf
  +    -rot s" (" str-append ( list str-addr str-len )
  +    rot dup MalList/cdr @ swap MalList/car @ 2swap rot pr-buf
  +    begin ( list str-addr str-len )
  +      2 pick mal-nil <>
  +    while
  +      a-space
  +      rot dup MalList/cdr @ swap MalList/car @ 2swap rot pr-buf
  +    repeat
  +    s" )" str-append rot drop ;;
  +  ' conj ' MalList/conj extend-method*
  +drop
  +
  +
  +MalType%
  +  cell% field MalInt/int
  +deftype* constant MalInt
  +
  +MalInt
  +  extend pr-buf
  +    MalInt/int @ int>str str-append ;;
  +drop
  +
  +: MalInt. { int -- mal-int }
  +    MalInt new dup MalInt/int int swap ! ;
  +
  +
  +\ Run some protocol methods!
  +
  +mal-nil
  +42 MalInt. mal-nil conj
  +10 MalInt. mal-nil conj conj
  +20 MalInt. swap conj
  +23 MalInt. mal-nil conj conj conj
  +
  +pr-str safe-type cr
  +
   bye
  -." Done loading" cr
  
positive.code:     swap cr ." | got " . cr ." | expected " . cr
    endif ;
  
  \ === classic lisp list === /
  : cons { addr val -- new-list-address }
    2 cells allocate throw
    dup addr val rot 2! ;
  
  : cdr ( addr -- next-addr )
    cell+ @ ;
  
  : int-pr ( num -- )
    s>d <# #s #> type ;
  
  : prn ( list-address -- )
    ." (" 2@ int-pr
    begin
      space 2@ int-pr
      dup 0=
    until
    .\" )\n" ;
  
  0 1 cons 2 cons 3 cons 4 cons
  prn
  
  
  \ === mutable vector === /
  \ Singly-linked list, with an "object" pair that points to both ends.
  \ This allows fast append and fast iteration from beginning to end,
  \ like a vector.  ...but buys simplicity with mutability
  : new-mutvec ( -- mutvec-addr )
    2 cells allocate throw
    dup 0 0 rot 2! ;
  
  : mutvec-append { mutvec-addr value -- }
    2 cells allocate throw    \ new pair
    dup nil value rot 2!      \ put value in new pair
    dup mutvec-addr @
      ?dup 0= if mutvec-addr endif
      cell+ !                 \ update old tail
    mutvec-addr !             \ update object
    ;
  
  new-mutvec
  dup 5 mutvec-append
  dup 4 mutvec-append
  dup 3 mutvec-append
  dup 2 mutvec-append
  cdr prn
  
  
  \ === mutable string buffer === /
  
negative.code:   str-addr buf-addr buf-str-len + str-len cmove
    buf-addr new-len ;
  
  \ define a function to append a space
  bl c,
  here constant space-str
  : a-space space-str 1 str-append ;
  
  : int>str ( num -- str-addr str-len )
    s>d <# #s #> ;
  
  
  \ === deftype* -- protocol-enabled structs === /
  \ Each type has MalTypeType% struct allocated on the stack, with
  