(require 'elsa-types)
(require 'elsa-type-helpers)
(require 'elsa-type-algebra)

;; File: data.c
(put 'eq 'elsa-type (elsa-make-type (function (mixed mixed) bool)))
(put 'null 'elsa-type (elsa-make-type (function (mixed) (is nil))))
(put 'type-of 'elsa-type (elsa-make-type (function (mixed) symbol)))
(put 'consp 'elsa-type (elsa-make-type (function (mixed) (is (cons mixed mixed)))))
(put 'atom 'elsa-type (elsa-make-type (function (mixed) bool)))
(put 'listp 'elsa-type (elsa-make-type (function (mixed) (is (or (list mixed) nil)))))
(put 'nlistp 'elsa-type (elsa-make-type (function (mixed) (is (diff mixed cons)))))
(put 'symbolp 'elsa-type (elsa-make-type (function (mixed) (is symbol))))
(put 'keywordp 'elsa-type (elsa-make-type (function (mixed) (is keyword))))
(put 'vectorp 'elsa-type (elsa-make-type (function (mixed) (is vector))))
(put 'recordp 'elsa-type (elsa-make-type (function (mixed) (is record))))
(put 'stringp 'elsa-type (elsa-make-type (function (mixed) (is string))))
(put 'multibyte-string-p 'elsa-type (elsa-make-type (function (mixed) bool)))
(put 'char-table-p 'elsa-type (elsa-make-type (function (mixed) (is char-table))))
(put 'vector-or-char-table-p 'elsa-type (elsa-make-type (function (mixed) bool)))
(put 'bool-vector-p 'elsa-type (elsa-make-type (function (mixed) (is bool-vector))))
(put 'arrayp 'elsa-type (elsa-make-type (function (mixed) (is (or string vector)))))
(put 'sequencep 'elsa-type (elsa-make-type (function (mixed) (is sequence))))
(put 'bufferp 'elsa-type (elsa-make-type (function (mixed) (is buffer))))
(put 'markerp 'elsa-type (elsa-make-type (function (mixed) (is marker))))
(put 'user-ptrp 'elsa-type (elsa-make-type (function (mixed) bool)))
(put 'subrp 'elsa-type (elsa-make-type (function (mixed) bool)))
(put 'byte-code-function-p 'elsa-type (elsa-make-type (function (mixed) bool)))
(put 'char-or-string-p 'elsa-type (elsa-make-type (function (mixed) bool)))
(put 'integerp 'elsa-type (elsa-make-type (function (mixed) (is int))))
(put 'integer-or-marker-p 'elsa-type (elsa-make-type (function (mixed) (is (or int marker)))))
(put 'natnump 'elsa-type (elsa-make-type (function (mixed) bool)))
(put 'numberp 'elsa-type (elsa-make-type (function (mixed) (is number))))
(put 'number-or-marker-p 'elsa-type (elsa-make-type (function (mixed) (is (or number marker)))))
(put 'floatp 'elsa-type (elsa-make-type (function (mixed) (is float))))
(put 'threadp 'elsa-type (elsa-make-type (function (mixed) (is thread))))
(put 'mutexp 'elsa-type (elsa-make-type (function (mixed) (is mutex))))
(put 'condition-variable-p 'elsa-type (elsa-make-type (function (mixed) (is condition-variable))))
;; TODO: generic
(put 'car 'elsa-type (elsa-make-type (function ((or (cons mixed mixed) nil)) mixed)))
;; TODO: generic
(put 'car-safe 'elsa-type (elsa-make-type (function ((or (cons mixed mixed) nil)) mixed)))
;; TODO: generic
(put 'cdr 'elsa-type (elsa-make-type (function ((or (cons mixed mixed) nil)) mixed)))
;; TODO: generic
(put 'cdr-safe 'elsa-type (elsa-make-type (function ((or (cons mixed mixed) nil)) mixed)))
(put 'setcar 'elsa-type (elsa-make-type (function ((cons mixed mixed) mixed) mixed)))
(put 'setcdr 'elsa-type (elsa-make-type (function ((cons mixed mixed) mixed) mixed)))
(put 'boundp 'elsa-type (elsa-make-type (function (symbol) bool)))
(put 'fboundp 'elsa-type (elsa-make-type (function (symbol) bool)))
(put 'makunbound 'elsa-type (elsa-make-type (function (symbol) symbol)))
(put 'fmakunbound 'elsa-type (elsa-make-type (function (symbol) symbol)))
;; (put 'symbol-function 'elsa-type (elsa-make-type nil))
(put 'symbol-plist 'elsa-type (elsa-make-type (function ((or symbol nil)) (list mixed))))
(put 'symbol-name 'elsa-type (elsa-make-type (function ((or symbol nil)) string)))
;; (put 'fset 'elsa-type (elsa-make-type ))
;; (put 'defalias 'elsa-type (elsa-make-type ))
(put 'setplist 'elsa-type (elsa-make-type (function (symbol (list mixed)) (list mixed))))
(put 'subr-arity 'elsa-type (elsa-make-type (function (mixed) (cons int (or int (const many))))))
;; (put 'subr-name 'elsa-type (elsa-make-type ))
(put 'interactive-form 'elsa-type (elsa-make-type (function (symbol) (or (cons (const interactive) (or string nil)) nil))))
(put 'indirect-variable 'elsa-type (elsa-make-type (function (symbol) symbol)))
(put 'symbol-value 'elsa-type (elsa-make-type (function (symbol) mixed)))
(put 'set 'elsa-type (elsa-make-type (function (symbol mixed) mixed)))
(put 'default-boundp 'elsa-type (elsa-make-type (function (symbol) bool)))
(put 'default-value 'elsa-type (elsa-make-type (function (symbol) mixed)))
(put 'set-default 'elsa-type (elsa-make-type (function (symbol mixed) mixed)))
;; SPECIAL FORM (put 'setq-default 'elsa-type (elsa-make-type ))
(put 'make-variable-buffer-local 'elsa-type (elsa-make-type (function (symbol) symbol)))
(put 'make-local-variable 'elsa-type (elsa-make-type (function (symbol) symbol)))
(put 'kill-local-variable 'elsa-type (elsa-make-type (function (symbol) symbol)))
;; (put 'make-variable-frame-local 'elsa-type (elsa-make-type ))
(put 'local-variable-p 'elsa-type (elsa-make-type (function (symbol (or buffer nil)) bool)))
(put 'local-variable-if-set-p 'elsa-type (elsa-make-type (function (symbol (or buffer nil)) bool)))
(put 'variable-binding-locus 'elsa-type (elsa-make-type (function (symbol) (or buffer frame nil))))
;; (put 'terminal-local-value 'elsa-type (elsa-make-type ))
;; (put 'set-terminal-local-value 'elsa-type (elsa-make-type ))
;; (put 'indirect-function 'elsa-type (elsa-make-type ))
(put 'aref 'elsa-type (elsa-make-type (function ((or string (vector mixed)) int) mixed)))
;; TODO: can have a generic type (elsa-make-type String | Vector -> Int -> a -> a)
;; Also other functions which are of a "set" variety which take
;; something, set a variable to that value and return the same thing
;; back.
(put 'aset 'elsa-type (elsa-make-type (function ((or string (vector mixed)) int mixed) mixed)))
;; TODO: should also accept markers
(put '= 'elsa-type (elsa-make-type (function ((or number marker) &rest (or number marker)) bool)))
(put '< 'elsa-type (elsa-make-type (function ((or number marker) &rest (or number marker)) bool)))
(put '> 'elsa-type (elsa-make-type (function ((or number marker) &rest (or number marker)) bool)))
(put '<= 'elsa-type (elsa-make-type (function ((or number marker) &rest (or number marker)) bool)))
(put '>= 'elsa-type (elsa-make-type (function ((or number marker) &rest (or number marker)) bool)))
(put '/= 'elsa-type (elsa-make-type (function ((or number marker) (or number marker)) bool)))
(put 'number-to-string 'elsa-type (elsa-make-type (function (number) string)))
(put 'string-to-number 'elsa-type (elsa-make-type (function (string (or number nil)) number)))
(put '+ 'elsa-type (elsa-make-type (function (&rest (or number marker)) number)))
(put '- 'elsa-type (elsa-make-type (function (&rest (or number marker)) number)))
(put '* 'elsa-type (elsa-make-type (function (&rest (or number marker)) number)))
(put '/ 'elsa-type (elsa-make-type (function ((or number marker) &rest (or number marker)) number)))
(put '% 'elsa-type (elsa-make-type (function ((or number marker) (or number marker)) number)))
(put 'mod 'elsa-type (elsa-make-type (function ((or number marker) (or number marker)) number)))
(put 'max 'elsa-type (elsa-make-type (function ((or number marker) &rest (or number marker)) number)))
(put 'min 'elsa-type (elsa-make-type (function ((or number marker) &rest (or number marker)) number)))
(put 'logand 'elsa-type (elsa-make-type (function (&rest (or number marker)) int)))
(put 'logior 'elsa-type (elsa-make-type (function (&rest (or number marker)) int)))
(put 'logxor 'elsa-type (elsa-make-type (function (&rest (or number marker)) int)))
(put 'ash 'elsa-type (elsa-make-type (function (int int) int)))
(put 'lsh 'elsa-type (elsa-make-type (function (int int) int)))
(put '1+ 'elsa-type (elsa-make-type (and (function ((or int marker)) int) (function (float) float))))
(put '1- 'elsa-type (elsa-make-type (and (function ((or int marker)) int) (function (float) float))))
(put 'lognot 'elsa-type (elsa-make-type (function (int) int)))
(put 'byteorder 'elsa-type (elsa-make-type int))
;; TODO: Implement bool vectors
;; (put 'bool-vector-exclusive-or 'elsa-type (elsa-make-type ))
;; (put 'bool-vector-union 'elsa-type (elsa-make-type ))
;; (put 'bool-vector-intersection 'elsa-type (elsa-make-type ))
;; (put 'bool-vector-set-difference 'elsa-type (elsa-make-type ))
;; (put 'bool-vector-subsetp 'elsa-type (elsa-make-type ))
;; (put 'bool-vector-not 'elsa-type (elsa-make-type ))
;; (put 'bool-vector-count-population 'elsa-type (elsa-make-type ))
;; (put 'bool-vector-count-consecutive 'elsa-type (elsa-make-type ))

;; File: bytecode.c
(put 'byte-code 'elsa-type (elsa-make-type (function (string (vector mixed) int) mixed)))

;; File: callproc.c
(put 'call-process 'elsa-type
     (elsa-make-type (function (string (or string nil) (or bool (const 0) (cons (const :file) (cons string nil)) (cons (or bool (const 0) (cons (const :file) (cons string nil))) (cons (or bool string) nil))) mixed &rest string) (or nil int string))))
(put 'call-process-region 'elsa-type
     (elsa-make-type (function ((or int marker) (or int marker) string mixed (or bool (const 0) (cons (const :file) (cons string nil)) (cons (or bool (const 0) (cons (const :file) (cons string nil))) (cons (or bool string) nil))) mixed &rest string) (or nil int string))))
(put 'getenv-internal 'elsa-type (elsa-make-type (function (string (list string)) (or string nil))))

;; File: kqueue.c
;; (put 'kqueue-add-watch 'elsa-type (elsa-make-type))
;; (put 'kqueue-rm-watch 'elsa-type (elsa-make-type))
;; (put 'kqueue-valid-p 'elsa-type (elsa-make-type))

;; File: print.c
(put 'write-char 'elsa-type (elsa-make-type (function (int (or t marker buffer (function (mixed) mixed))) int)))
(put 'terpri 'elsa-type (elsa-make-type (function ((or t marker buffer (function (mixed) mixed)) mixed) mixed)))
(put 'prin1 'elsa-type (elsa-make-type (function (mixed (or t marker buffer (function (mixed) mixed) symbol)) mixed)))
(put 'prin1-to-string 'elsa-type (elsa-make-type (function (mixed mixed) string)))
(put 'princ 'elsa-type (elsa-make-type (function (mixed (or t marker buffer (function (mixed) mixed) symbol)) mixed)))
(put 'print 'elsa-type (elsa-make-type (function (mixed (or t marker buffer (function (mixed) mixed) symbol)) mixed)))
(put 'external-debugging-output 'elsa-type (elsa-make-type (function (int) int)))
(put 'redirect-debugging-output 'elsa-type (elsa-make-type (function ((or string nil) mixed) nil)))
(put 'error-message-string 'elsa-type (elsa-make-type (function ((cons symbol mixed)) string)))

;; File: xmenu.c
(put 'x-menu-bar-open-internal 'elsa-type (elsa-make-type (function ((or frame nil)) nil)))
(put 'menu-or-popup-active-p 'elsa-type (elsa-make-type bool))

;; File: inotify.c
;; (put 'inotify-add-watch 'elsa-type (elsa-make-type))
;; (put 'inotify-rm-watch 'elsa-type (elsa-make-type))
;; (put 'inotify-valid-p 'elsa-type (elsa-make-type))

;; File: fns.c
;; (put 'identity 'elsa-type (elsa-make-type ))
(put 'random 'elsa-type (elsa-make-type (function ((or int t string)) int)))
(put 'length 'elsa-type (elsa-make-type (function ((or sequence nil)) int)))
(put 'safe-length 'elsa-type (elsa-make-type (function (mixed) int)))
(put 'string-bytes 'elsa-type (elsa-make-type (function (string) int)))
(put 'string-equal 'elsa-type (elsa-make-type (function ((or string symbol) (or string symbol)) bool)))
(put 'compare-strings 'elsa-type (elsa-make-type (function (string (or int nil) (or int nil) string (or int nil) (or int nil) bool) (or int t))))
(put 'string-lessp 'elsa-type (elsa-make-type (function ((or string symbol) (or string symbol)) bool)))
(put 'string-collate-lessp 'elsa-type (elsa-make-type (function ((or string symbol) (or string symbol) (or string nil) bool) bool)))
(put 'string-collate-equalp 'elsa-type (elsa-make-type (function ((or string symbol) (or string symbol) (or string nil) bool) bool)))
(put 'append 'elsa-type (elsa-make-type (function (&rest sequence) (list mixed))))
(put 'concat 'elsa-type (elsa-make-type (function (&rest (or string (list int) (vector int))) string)))
(put 'vconcat 'elsa-type (elsa-make-type (function (&rest sequence) (vector mixed))))
;; (put 'copy-sequence 'elsa-type (elsa-make-type ))
;; (put 'string-make-multibyte 'elsa-type (elsa-make-type ))
;; (put 'string-make-unibyte 'elsa-type (elsa-make-type ))
;; (put 'string-as-unibyte 'elsa-type (elsa-make-type ))
;; (put 'string-as-multibyte 'elsa-type (elsa-make-type ))
;; (put 'string-to-multibyte 'elsa-type (elsa-make-type ))
;; (put 'string-to-unibyte 'elsa-type (elsa-make-type ))
;; Should be `[Cons a b] -> [Cons a b]'
(put 'copy-alist 'elsa-type (elsa-make-type (function ((list (cons mixed mixed))) (list (cons mixed mixed)))))
(put 'substring 'elsa-type (elsa-make-type (function (string (or int nil) (or int nil)) string)))
(put 'substring-no-properties 'elsa-type (elsa-make-type (function (string (or int nil) (or int nil)) string)))
(put 'nthcdr 'elsa-type (elsa-make-type (function (int (list mixed)) mixed)))
;; TODO: once generics are introduced this can turn into
;; "Int -> List a -> a" and similarly for elt
(put 'nth 'elsa-type (elsa-make-type (function (int (list mixed)) mixed)))
(put 'elt 'elsa-type (elsa-make-type (function (sequence int) mixed)))
;; TODO: Could use generics as well? a -> List a -> List a?
(put 'member 'elsa-type (elsa-make-type (function (mixed (list mixed)) (list mixed))))
(put 'memq 'elsa-type (elsa-make-type (function (mixed (list mixed)) (list mixed))))
(put 'memql 'elsa-type (elsa-make-type (function (mixed (list mixed)) (list mixed))))
;; TODO: this can be a -> [Mixed] -> Cons a Mixed
(put 'assq 'elsa-type (elsa-make-type (function (mixed (list mixed)) (or nil (cons mixed mixed)))))
(put 'assoc 'elsa-type (elsa-make-type (function (mixed (list mixed)) (or nil (cons mixed mixed)))))
;; (put 'rassq 'elsa-type (elsa-make-type ))
;; (put 'rassoc 'elsa-type (elsa-make-type ))
;; (put 'delq 'elsa-type (elsa-make-type ))
;; (put 'delete 'elsa-type (elsa-make-type ))
;; (put 'nreverse 'elsa-type (elsa-make-type ))
;; (put 'reverse 'elsa-type (elsa-make-type ))
;; (put 'sort 'elsa-type (elsa-make-type ))
;; (put 'plist-get 'elsa-type (elsa-make-type ))
;; (put 'get 'elsa-type (elsa-make-type ))
;; (put 'plist-put 'elsa-type (elsa-make-type ))
;; (put 'put 'elsa-type (elsa-make-type ))
;; (put 'lax-plist-get 'elsa-type (elsa-make-type ))
;; (put 'lax-plist-put 'elsa-type (elsa-make-type ))
;; (put 'eql 'elsa-type (elsa-make-type ))
;; (put 'equal 'elsa-type (elsa-make-type ))
;; (put 'equal-including-properties 'elsa-type (elsa-make-type ))
;; (put 'fillarray 'elsa-type (elsa-make-type ))
;; (put 'clear-string 'elsa-type (elsa-make-type ))
;; (put 'nconc 'elsa-type (elsa-make-type ))
;; TODO: generic
(put 'mapconcat 'elsa-type (elsa-make-type (function ((function (mixed) string) (list mixed) string) string)))
;; (put 'mapcar 'elsa-type (elsa-make-type ))
;; (put 'mapc 'elsa-type (elsa-make-type ))
(put 'yes-or-no-p 'elsa-type (elsa-make-type (function (string) bool)))
(put 'load-average 'elsa-type (elsa-make-type (function (bool) (cons number (cons number (cons number nil))))))
(put 'featurep 'elsa-type (elsa-make-type (function (symbol (or symbol nil)) bool)))
(put 'provide 'elsa-type (elsa-make-type (function (symbol (list symbol)) symbol)))
(put 'require 'elsa-type (elsa-make-type (function (symbol (or string nil) bool) symbol)))
(put 'plist-member 'elsa-type (elsa-make-type (function ((list mixed) symbol) (list mixed))))
;; (put 'widget-put 'elsa-type (elsa-make-type ))
;; (put 'widget-get 'elsa-type (elsa-make-type ))
;; (put 'widget-apply 'elsa-type (elsa-make-type ))
;; (put 'locale-info 'elsa-type (elsa-make-type ))
;; (put 'base64-encode-region 'elsa-type (elsa-make-type ))
;; (put 'base64-encode-string 'elsa-type (elsa-make-type ))
;; (put 'base64-decode-region 'elsa-type (elsa-make-type ))
;; (put 'base64-decode-string 'elsa-type (elsa-make-type ))
;; (put 'sxhash 'elsa-type (elsa-make-type ))
;; (put 'make-hash-table 'elsa-type (elsa-make-type ))
(put 'copy-hash-table 'elsa-type (elsa-make-type (function (hash-table) hash-table)))
(put 'hash-table-count 'elsa-type (elsa-make-type (function (hash-table) int)))
(put 'hash-table-rehash-size 'elsa-type (elsa-make-type (function (hash-table) float)))
(put 'hash-table-rehash-threshold 'elsa-type (elsa-make-type (function (hash-table) float)))
(put 'hash-table-size 'elsa-type (elsa-make-type (function (hash-table) int)))
;; (put 'hash-table-test 'elsa-type (elsa-make-type ))
(put 'hash-table-weakness 'elsa-type (elsa-make-type (function (hash-table) (or symbol nil))))
(put 'hash-table-p 'elsa-type (elsa-make-type (function (mixed) (is hash-table))))
(put 'clrhash 'elsa-type (elsa-make-type (function (hash-table) hash-table)))
;; TODO: make generic
(put 'gethash 'elsa-type (elsa-make-type (function (mixed hash-table (or mixed nil)) mixed)))
(put 'puthash 'elsa-type (elsa-make-type (function (mixed mixed hash-table) mixed)))
(put 'remhash 'elsa-type (elsa-make-type (function (mixed hash-table) nil)))
(put 'maphash 'elsa-type (elsa-make-type (function ((function (mixed mixed) mixed) hash-table) nil)))
;; (put 'define-hash-table-test 'elsa-type (elsa-make-type ))
(put 'md5 'elsa-type (elsa-make-type (function ((or buffer string) (or int nil) (or int nil) (or symbol nil) bool) string)))
(put 'secure-hash 'elsa-type (elsa-make-type (function (symbol (or buffer string) (or int nil) (or int nil) bool) string)))

;; File: font.c
(put 'fontp 'elsa-type (elsa-make-type (function (mixed) (is font))))
;; (put 'font-spec 'elsa-type (elsa-make-type ))
;; (put 'font-get 'elsa-type (elsa-make-type ))
;; (put 'font-face-attributes 'elsa-type (elsa-make-type ))
;; (put 'font-put 'elsa-type (elsa-make-type ))
;; (put 'list-fonts 'elsa-type (elsa-make-type ))
;; (put 'font-family-list 'elsa-type (elsa-make-type ))
;; (put 'find-font 'elsa-type (elsa-make-type ))
;; (put 'font-xlfd-name 'elsa-type (elsa-make-type ))
;; (put 'clear-font-cache 'elsa-type (elsa-make-type ))
;; (put 'font-shape-gstring 'elsa-type (elsa-make-type ))
;; (put 'font-variation-glyphs 'elsa-type (elsa-make-type ))
;; (put 'internal-char-font 'elsa-type (elsa-make-type ))
;; (put 'font-drive-otf 'elsa-type (elsa-make-type ))
;; (put 'font-otf-alternates 'elsa-type (elsa-make-type ))
;; (put 'open-font 'elsa-type (elsa-make-type ))
;; (put 'close-font 'elsa-type (elsa-make-type ))
;; (put 'query-font 'elsa-type (elsa-make-type ))
;; (put 'font-get-glyphs 'elsa-type (elsa-make-type ))
;; (put 'font-match-p 'elsa-type (elsa-make-type ))
;; (put 'font-at 'elsa-type (elsa-make-type ))
;; (put 'draw-string 'elsa-type (elsa-make-type ))
;; (put 'frame-font-cache 'elsa-type (elsa-make-type ))
;; (put 'font-info 'elsa-type (elsa-make-type ))

;; File: window.c
(put 'windowp 'elsa-type (elsa-make-type (function (mixed) (is window))))
;; (put 'window-valid-p 'elsa-type (elsa-make-type ))
;; (put 'window-live-p 'elsa-type (elsa-make-type ))
;; (put 'window-frame 'elsa-type (elsa-make-type ))
;; (put 'frame-root-window 'elsa-type (elsa-make-type ))
;; (put 'minibuffer-window 'elsa-type (elsa-make-type ))
;; (put 'window-minibuffer-p 'elsa-type (elsa-make-type ))
;; (put 'frame-first-window 'elsa-type (elsa-make-type ))
;; (put 'frame-selected-window 'elsa-type (elsa-make-type ))
;; (put 'set-frame-selected-window 'elsa-type (elsa-make-type ))
;; (put 'selected-window 'elsa-type (elsa-make-type ))
;; (put 'select-window 'elsa-type (elsa-make-type ))
;; (put 'window-buffer 'elsa-type (elsa-make-type ))
;; (put 'window-parent 'elsa-type (elsa-make-type ))
;; (put 'window-top-child 'elsa-type (elsa-make-type ))
;; (put 'window-left-child 'elsa-type (elsa-make-type ))
;; (put 'window-next-sibling 'elsa-type (elsa-make-type ))
;; (put 'window-prev-sibling 'elsa-type (elsa-make-type ))
;; (put 'window-combination-limit 'elsa-type (elsa-make-type ))
;; (put 'set-window-combination-limit 'elsa-type (elsa-make-type ))
;; (put 'window-use-time 'elsa-type (elsa-make-type ))
;; (put 'window-pixel-width 'elsa-type (elsa-make-type ))
;; (put 'window-pixel-height 'elsa-type (elsa-make-type ))
;; (put 'window-total-height 'elsa-type (elsa-make-type ))
;; (put 'window-total-width 'elsa-type (elsa-make-type ))
;; (put 'window-new-total 'elsa-type (elsa-make-type ))
;; (put 'window-normal-size 'elsa-type (elsa-make-type ))
;; (put 'window-new-normal 'elsa-type (elsa-make-type ))
;; (put 'window-new-pixel 'elsa-type (elsa-make-type ))
;; (put 'window-pixel-left 'elsa-type (elsa-make-type ))
;; (put 'window-pixel-top 'elsa-type (elsa-make-type ))
;; (put 'window-left-column 'elsa-type (elsa-make-type ))
;; (put 'window-top-line 'elsa-type (elsa-make-type ))
;; (put 'window-body-height 'elsa-type (elsa-make-type ))
;; (put 'window-body-width 'elsa-type (elsa-make-type ))
;; (put 'window-mode-line-height 'elsa-type (elsa-make-type ))
;; (put 'window-header-line-height 'elsa-type (elsa-make-type ))
;; (put 'window-right-divider-width 'elsa-type (elsa-make-type ))
;; (put 'window-bottom-divider-width 'elsa-type (elsa-make-type ))
;; (put 'window-scroll-bar-width 'elsa-type (elsa-make-type ))
;; (put 'window-scroll-bar-height 'elsa-type (elsa-make-type ))
;; (put 'window-hscroll 'elsa-type (elsa-make-type ))
;; (put 'set-window-hscroll 'elsa-type (elsa-make-type ))
;; (put 'window-redisplay-end-trigger 'elsa-type (elsa-make-type ))
;; (put 'set-window-redisplay-end-trigger 'elsa-type (elsa-make-type ))
;; (put 'coordinates-in-window-p 'elsa-type (elsa-make-type ))
;; (put 'window-at 'elsa-type (elsa-make-type ))
;; (put 'window-point 'elsa-type (elsa-make-type ))
;; (put 'window-old-point 'elsa-type (elsa-make-type ))
;; (put 'window-start 'elsa-type (elsa-make-type ))
;; (put 'window-end 'elsa-type (elsa-make-type ))
;; (put 'set-window-point 'elsa-type (elsa-make-type ))
;; (put 'set-window-start 'elsa-type (elsa-make-type ))
;; (put 'pos-visible-in-window-p 'elsa-type (elsa-make-type ))
;; (put 'window-line-height 'elsa-type (elsa-make-type ))
;; (put 'window-dedicated-p 'elsa-type (elsa-make-type ))
;; (put 'set-window-dedicated-p 'elsa-type (elsa-make-type ))
;; (put 'window-prev-buffers 'elsa-type (elsa-make-type ))
;; (put 'set-window-prev-buffers 'elsa-type (elsa-make-type ))
;; (put 'window-next-buffers 'elsa-type (elsa-make-type ))
;; (put 'set-window-next-buffers 'elsa-type (elsa-make-type ))
;; (put 'window-parameters 'elsa-type (elsa-make-type ))
;; (put 'window-parameter 'elsa-type (elsa-make-type ))
;; (put 'set-window-parameter 'elsa-type (elsa-make-type ))
;; (put 'window-display-table 'elsa-type (elsa-make-type ))
;; (put 'set-window-display-table 'elsa-type (elsa-make-type ))
;; (put 'next-window 'elsa-type (elsa-make-type ))
;; (put 'previous-window 'elsa-type (elsa-make-type ))
;; (put 'window-list 'elsa-type (elsa-make-type ))
;; (put 'window-list-1 'elsa-type (elsa-make-type ))
;; (put 'get-buffer-window 'elsa-type (elsa-make-type ))
;; (put 'window--sanitize-window-sizes 'elsa-type (elsa-make-type ))
;; (put 'delete-other-windows-internal 'elsa-type (elsa-make-type ))
;; (put 'run-window-configuration-change-hook 'elsa-type (elsa-make-type ))
;; (put 'run-window-scroll-functions 'elsa-type (elsa-make-type ))
;; (put 'set-window-buffer 'elsa-type (elsa-make-type ))
;; (put 'force-window-update 'elsa-type (elsa-make-type ))
;; (put 'set-window-new-pixel 'elsa-type (elsa-make-type ))
;; (put 'set-window-new-total 'elsa-type (elsa-make-type ))
;; (put 'set-window-new-normal 'elsa-type (elsa-make-type ))
;; (put 'window-resize-apply 'elsa-type (elsa-make-type ))
;; (put 'window-resize-apply-total 'elsa-type (elsa-make-type ))
;; (put 'split-window-internal 'elsa-type (elsa-make-type ))
;; (put 'delete-window-internal 'elsa-type (elsa-make-type ))
;; (put 'resize-mini-window-internal 'elsa-type (elsa-make-type ))
;; (put 'scroll-up 'elsa-type (elsa-make-type ))
;; (put 'scroll-down 'elsa-type (elsa-make-type ))
;; (put 'other-window-for-scrolling 'elsa-type (elsa-make-type ))
;; (put 'scroll-other-window 'elsa-type (elsa-make-type ))
;; (put 'scroll-left 'elsa-type (elsa-make-type ))
;; (put 'scroll-right 'elsa-type (elsa-make-type ))
;; (put 'minibuffer-selected-window 'elsa-type (elsa-make-type ))
;; (put 'recenter 'elsa-type (elsa-make-type ))
;; (put 'window-text-width 'elsa-type (elsa-make-type ))
;; (put 'window-text-height 'elsa-type (elsa-make-type ))
;; (put 'move-to-window-line 'elsa-type (elsa-make-type ))
(put 'window-configuration-p 'elsa-type (elsa-make-type (function (mixed) (is window-configuration))))
;; (put 'window-configuration-frame 'elsa-type (elsa-make-type ))
;; (put 'set-window-configuration 'elsa-type (elsa-make-type ))
;; (put 'current-window-configuration 'elsa-type (elsa-make-type ))
;; (put 'set-window-margins 'elsa-type (elsa-make-type ))
;; (put 'window-margins 'elsa-type (elsa-make-type ))
;; (put 'set-window-fringes 'elsa-type (elsa-make-type ))
;; (put 'window-fringes 'elsa-type (elsa-make-type ))
;; (put 'set-window-scroll-bars 'elsa-type (elsa-make-type ))
;; (put 'window-scroll-bars 'elsa-type (elsa-make-type ))
;; (put 'window-vscroll 'elsa-type (elsa-make-type ))
;; (put 'set-window-vscroll 'elsa-type (elsa-make-type ))
;; (put 'compare-window-configurations 'elsa-type (elsa-make-type ))

;; File: dired.c
(put 'directory-files 'elsa-type (elsa-make-type (function (string mixed mixed mixed) (list string))))
(put 'directory-files-and-attributes 'elsa-type (elsa-make-type (function (string mixed mixed mixed mixed) (list (list mixed)))))
(put 'file-name-completion 'elsa-type (elsa-make-type (function (string string (or (function (string) bool) nil)) (or string nil t))))
(put 'file-name-all-completions 'elsa-type (elsa-make-type (function (string string) (list string))))
(put 'file-attributes 'elsa-type (elsa-make-type (function (string) (list mixed))))
(put 'file-attributes-lessp 'elsa-type (elsa-make-type (function ((list mixed) (list mixed)) bool)))
(put 'system-users 'elsa-type (elsa-make-type (list string)))
(put 'system-groups 'elsa-type (elsa-make-type (list string)))


;; File: editfns.c
(put 'char-to-string 'elsa-type (elsa-make-type (function (int) string)))
(put 'byte-to-string 'elsa-type (elsa-make-type (function (int) string)))
(put 'string-to-char 'elsa-type (elsa-make-type (function (string) int)))
(put 'point 'elsa-type (elsa-make-type int))
(put 'point-marker 'elsa-type (elsa-make-type marker))
(put 'goto-char 'elsa-type (elsa-make-type (function ((or int marker)) int)))
(put 'region-beginning 'elsa-type (elsa-make-type int))
(put 'region-end 'elsa-type (elsa-make-type int))
(put 'mark-marker 'elsa-type (elsa-make-type marker))
;; (put 'get-pos-property 'elsa-type (elsa-make-type))
;; (put 'delete-field 'elsa-type (elsa-make-type))
;; (put 'field-string 'elsa-type (elsa-make-type))
;; (put 'field-string-no-properties 'elsa-type (elsa-make-type))
;; (put 'field-beginning 'elsa-type (elsa-make-type))
;; (put 'field-end 'elsa-type (elsa-make-type))
;; (put 'constrain-to-field 'elsa-type (elsa-make-type))
(put 'line-beginning-position 'elsa-type (elsa-make-type int))
(put 'line-end-position 'elsa-type (elsa-make-type int))
;; (put 'save-excursion 'elsa-type (elsa-make-type))
;; (put 'save-current-buffer 'elsa-type (elsa-make-type))
(put 'buffer-size 'elsa-type (elsa-make-type (function ((or buffer nil)) int)))
(put 'point-min 'elsa-type (elsa-make-type int))
(put 'point-min-marker 'elsa-type (elsa-make-type marker))
(put 'point-max 'elsa-type (elsa-make-type int))
(put 'point-max-marker 'elsa-type (elsa-make-type marker))
(put 'gap-position 'elsa-type (elsa-make-type int))
(put 'gap-size 'elsa-type (elsa-make-type int))
;; (put 'position-bytes 'elsa-type (elsa-make-type))
;; (put 'byte-to-position 'elsa-type (elsa-make-type))
(put 'following-char 'elsa-type (elsa-make-type int))
(put 'preceding-char 'elsa-type (elsa-make-type int))
(put 'bobp 'elsa-type (elsa-make-type bool))
(put 'eobp 'elsa-type (elsa-make-type bool))
(put 'bolp 'elsa-type (elsa-make-type bool))
(put 'eolp 'elsa-type (elsa-make-type bool))
(put 'char-after 'elsa-type (elsa-make-type (function ((or int marker nil)) int)))
(put 'char-before 'elsa-type (elsa-make-type (function ((or int marker nil)) int)))
;; TODO: Can only return nil if arg is non-nil; same for user-full-name
(put 'user-login-name 'elsa-type (elsa-make-type (function ((or number nil)) (or string nil))))
(put 'user-real-login-name 'elsa-type (elsa-make-type string))
(put 'user-uid 'elsa-type (elsa-make-type number))
(put 'user-real-uid 'elsa-type (elsa-make-type number))
(put 'group-gid 'elsa-type (elsa-make-type number))
(put 'group-real-gid 'elsa-type (elsa-make-type number))
(put 'user-full-name 'elsa-type (elsa-make-type (function ((or number nil)) (or string nil))))
(put 'system-name 'elsa-type (elsa-make-type string))
(put 'emacs-pid 'elsa-type (elsa-make-type number))
;; (put 'current-time 'elsa-type (elsa-make-type))
;; (put 'time-add 'elsa-type (elsa-make-type))
;; (put 'time-subtract 'elsa-type (elsa-make-type))
;; (put 'time-less-p 'elsa-type (elsa-make-type))
;; (put 'get-internal-run-time 'elsa-type (elsa-make-type))
;; (put 'float-time 'elsa-type (elsa-make-type))
;; (put 'format-time-string 'elsa-type (elsa-make-type))
;; (put 'decode-time 'elsa-type (elsa-make-type))
;; (put 'encode-time 'elsa-type (elsa-make-type))
;; (put 'current-time-string 'elsa-type (elsa-make-type))
;; (put 'current-time-zone 'elsa-type (elsa-make-type))
;; (put 'set-time-zone-rule 'elsa-type (elsa-make-type))
;; TODO: rewrite as (String | Int)... when that syntax is available
(put 'insert 'elsa-type (elsa-make-type (function (&rest (or string int)) nil)))
(put 'insert-and-inherit 'elsa-type (elsa-make-type (function (&rest (or string int)) nil)))
(put 'insert-before-markers 'elsa-type (elsa-make-type (function (&rest (or string int)) nil)))
(put 'insert-before-markers-and-inherit 'elsa-type (elsa-make-type (function (&rest (or string int)) nil)))
(put 'insert-char 'elsa-type (elsa-make-type (function (int (or int nil) bool) nil)))
(put 'insert-byte 'elsa-type (elsa-make-type (function (int (or int nil) bool) nil)))
(put 'buffer-substring 'elsa-type (elsa-make-type (function (int int) string)))
(put 'buffer-substring-no-properties 'elsa-type (elsa-make-type (function (int int) string)))
(put 'buffer-string 'elsa-type (elsa-make-type string))
(put 'insert-buffer-substring 'elsa-type (elsa-make-type (function (buffer (or int nil) (or int nil)) nil)))
(put 'compare-buffer-substrings 'elsa-type (elsa-make-type (function ((or buffer nil) (or int nil) (or int nil) (or buffer nil) (or int nil) (or int nil)) int)))
;; (put 'subst-char-in-region 'elsa-type (elsa-make-type))
;; (put 'translate-region-internal 'elsa-type (elsa-make-type))
;; (put 'delete-region 'elsa-type (elsa-make-type))
;; (put 'delete-and-extract-region 'elsa-type (elsa-make-type))
;; (put 'widen 'elsa-type (elsa-make-type))
;; (put 'narrow-to-region 'elsa-type (elsa-make-type))
;; (put 'save-restriction 'elsa-type (elsa-make-type))
(put 'message 'elsa-type (elsa-make-type (function (string &rest mixed) string)))
(put 'message-box 'elsa-type (elsa-make-type (function (string &rest mixed) string)))
(put 'message-or-box 'elsa-type (elsa-make-type (function (string &rest mixed) string)))
(put 'current-message 'elsa-type (elsa-make-type string))
(put 'propertize 'elsa-type (elsa-make-type (function (string &rest mixed) string)))
(put 'format 'elsa-type (elsa-make-type (function (string &rest mixed) string)))
(put 'format-message 'elsa-type (elsa-make-type (function (string &rest mixed) string)))
(put 'char-equal 'elsa-type (elsa-make-type (function (int int) bool)))
;; (put 'transpose-regions 'elsa-type (elsa-make-type))

;; File: alloc.c
(put 'make-string 'elsa-type (elsa-make-type (function (int int) string)))
(put 'make-bool-vector 'elsa-type (elsa-make-type (function (int bool) bool-vector)))
(put 'bool-vector 'elsa-type (elsa-make-type (function (&rest mixed) bool-vector)))
;; TODO: generic type a -> b -> Cons a b...  This fails deriving the
;; type of something like (cons 1 "foo")... it still thinks the return
;; type is Cons Mixed Mixed
(put 'cons 'elsa-type (elsa-make-type (function (mixed mixed) (cons mixed mixed))))
(put 'list 'elsa-type (elsa-make-type (function (&rest mixed) (list mixed))))
;; TODO: generic type
(put 'make-list 'elsa-type (elsa-make-type (function (int mixed) (list mixed))))
(put 'make-vector 'elsa-type (elsa-make-type (function (int mixed) (vector mixed))))
(put 'vector 'elsa-type (elsa-make-type (function (&rest mixed) (vector mixed))))
;; TODO: how to detect the return type?
(put 'make-byte-code 'elsa-type (elsa-make-type (function ((or (list symbol) int) string (vector mixed) int (or string nil) mixed) mixed)))
(put 'make-symbol 'elsa-type (elsa-make-type (function (string) symbol)))
(put 'make-marker 'elsa-type (elsa-make-type marker))
;; TODO: add Callable
(put 'make-finalizer 'elsa-type (elsa-make-type (function (mixed) mixed)))
;; TODO: generic type
(put 'purecopy 'elsa-type (elsa-make-type (function (mixed) mixed)))
(put 'garbage-collect 'elsa-type (elsa-make-type (list (list mixed))))
;; TODO: make this a constant length list
(put 'memory-info 'elsa-type (elsa-make-type (list int)))
(put 'memory-limit 'elsa-type (elsa-make-type int))
;; TODO: make this a constant length list
(put 'memory-use-counts 'elsa-type (elsa-make-type (list int)))
;; TODO: generic type
(put 'suspicious-object 'elsa-type (elsa-make-type (function (mixed) mixed)))

;; File: cmds.c
(put 'forward-point 'elsa-type (elsa-make-type (function (int) int)))
(put 'forward-char 'elsa-type (elsa-make-type (function ((or int nil)) nil)))
(put 'backward-char 'elsa-type (elsa-make-type (function ((or int nil)) nil)))
(put 'forward-line 'elsa-type (elsa-make-type (function ((or int nil)) int)))
(put 'beginning-of-line 'elsa-type (elsa-make-type (function ((or int nil)) nil)))
(put 'end-of-line 'elsa-type (elsa-make-type (function ((or int nil)) nil)))
(put 'delete-char 'elsa-type (elsa-make-type (function (int mixed) nil)))
(put 'self-insert-command 'elsa-type (elsa-make-type (function (int) nil)))

;; File: fileio.c
(put 'file-name-directory 'elsa-type (elsa-make-type (function (string) (or string nil))))

;; File: frame.c
(put 'framep 'elsa-type (elsa-make-type (function (mixed) (is frame))))
;; (put 'frame-live-p 'elsa-type (elsa-make-type ))
;; (put 'window-system 'elsa-type (elsa-make-type ))
;; (put 'frame-windows-min-size 'elsa-type (elsa-make-type ))
;; (put 'make-terminal-frame 'elsa-type (elsa-make-type ))
;; (put 'select-frame 'elsa-type (elsa-make-type ))
;; (put 'handle-switch-frame 'elsa-type (elsa-make-type ))
;; (put 'selected-frame 'elsa-type (elsa-make-type ))
;; (put 'frame-list 'elsa-type (elsa-make-type ))
;; (put 'next-frame 'elsa-type (elsa-make-type ))
;; (put 'previous-frame 'elsa-type (elsa-make-type ))
;; (put 'last-nonminibuffer-frame 'elsa-type (elsa-make-type ))
;; (put 'delete-frame 'elsa-type (elsa-make-type ))
;; (put 'mouse-position 'elsa-type (elsa-make-type ))
;; (put 'mouse-pixel-position 'elsa-type (elsa-make-type ))
;; (put 'set-mouse-position 'elsa-type (elsa-make-type ))
;; (put 'set-mouse-pixel-position 'elsa-type (elsa-make-type ))
;; (put 'make-frame-visible 'elsa-type (elsa-make-type ))
;; (put 'make-frame-invisible 'elsa-type (elsa-make-type ))
;; (put 'iconify-frame 'elsa-type (elsa-make-type ))
;; (put 'frame-visible-p 'elsa-type (elsa-make-type ))
;; (put 'visible-frame-list 'elsa-type (elsa-make-type ))
;; (put 'raise-frame 'elsa-type (elsa-make-type ))
;; (put 'lower-frame 'elsa-type (elsa-make-type ))
;; (put 'redirect-frame-focus 'elsa-type (elsa-make-type ))
;; (put 'frame-focus 'elsa-type (elsa-make-type ))
;; (put 'x-focus-frame 'elsa-type (elsa-make-type ))
;; (put 'frame-after-make-frame 'elsa-type (elsa-make-type ))
;; (put 'frame-parameters 'elsa-type (elsa-make-type ))
;; (put 'frame-parameter 'elsa-type (elsa-make-type ))
;; (put 'modify-frame-parameters 'elsa-type (elsa-make-type ))
;; (put 'frame-char-height 'elsa-type (elsa-make-type ))
;; (put 'frame-char-width 'elsa-type (elsa-make-type ))
;; (put 'frame-pixel-height 'elsa-type (elsa-make-type ))
;; (put 'frame-pixel-width 'elsa-type (elsa-make-type ))
;; (put 'tool-bar-pixel-width 'elsa-type (elsa-make-type ))
;; (put 'frame-text-cols 'elsa-type (elsa-make-type ))
;; (put 'frame-text-lines 'elsa-type (elsa-make-type ))
;; (put 'frame-total-cols 'elsa-type (elsa-make-type ))
;; (put 'frame-total-lines 'elsa-type (elsa-make-type ))
;; (put 'frame-text-width 'elsa-type (elsa-make-type ))
;; (put 'frame-text-height 'elsa-type (elsa-make-type ))
;; (put 'frame-scroll-bar-width 'elsa-type (elsa-make-type ))
;; (put 'frame-scroll-bar-height 'elsa-type (elsa-make-type ))
;; (put 'frame-fringe-width 'elsa-type (elsa-make-type ))
;; (put 'frame-border-width 'elsa-type (elsa-make-type ))
;; (put 'frame-right-divider-width 'elsa-type (elsa-make-type ))
;; (put 'frame-bottom-divider-width 'elsa-type (elsa-make-type ))
;; (put 'set-frame-height 'elsa-type (elsa-make-type ))
;; (put 'set-frame-width 'elsa-type (elsa-make-type ))
;; (put 'set-frame-size 'elsa-type (elsa-make-type ))
;; (put 'frame-position 'elsa-type (elsa-make-type ))
;; (put 'set-frame-position 'elsa-type (elsa-make-type ))
;; (put 'x-get-resource 'elsa-type (elsa-make-type ))
;; (put 'x-parse-geometry 'elsa-type (elsa-make-type ))
;; (put 'frame-pointer-visible-p 'elsa-type (elsa-make-type ))

;; File: process.c
(put 'processp 'elsa-type (elsa-make-type (function (mixed) bool)))
(put 'get-process 'elsa-type (elsa-make-type (function (string) (or process nil))))
(put 'delete-process 'elsa-type (elsa-make-type (function ((or process buffer string nil)) mixed)))
(put 'process-status 'elsa-type (elsa-make-type (function ((or process buffer string nil)) (or symbol nil))))
(put 'process-exit-status 'elsa-type (elsa-make-type (function (process) int)))
(put 'process-id 'elsa-type (elsa-make-type (function (process) (or number nil))))
(put 'process-name 'elsa-type (elsa-make-type (function (process) string)))
(put 'process-command 'elsa-type (elsa-make-type (function (process) (or (list string) bool))))
(put 'process-tty-name 'elsa-type (elsa-make-type (function (process) (or string nil))))
(put 'set-process-buffer 'elsa-type (elsa-make-type (function (nil) buffer)))
(put 'process-buffer 'elsa-type (elsa-make-type (function (process) buffer)))
(put 'process-mark 'elsa-type (elsa-make-type (function (process) marker)))
(put 'set-process-filter 'elsa-type (elsa-make-type (function (process (function (process string) nil)) mixed)))
(put 'process-filter 'elsa-type (elsa-make-type (function (process) (function (process string) nil))))
(put 'set-process-sentinel 'elsa-type (elsa-make-type (function (process (function (process string) nil)) mixed)))
(put 'process-sentinel 'elsa-type (elsa-make-type (function (process) (function (process string) nil))))
(put 'set-process-window-size 'elsa-type (elsa-make-type (function (process int int) bool)))
(put 'set-process-inherit-coding-system-flag 'elsa-type (elsa-make-type (function (process bool) bool)))
(put 'set-process-query-on-exit-flag 'elsa-type (elsa-make-type (function (process bool) bool)))
(put 'process-query-on-exit-flag 'elsa-type (elsa-make-type (function (process) bool)))
;; TODO process-contact has an &optional parameter:
(put 'process-contact 'elsa-type (elsa-make-type (function (process (or symbol nil)) mixed)))
(put 'process-plist 'elsa-type (elsa-make-type (function (process) (list mixed))))
(put 'set-process-plist 'elsa-type (elsa-make-type (function (process (list mixed)) (list mixed))))
;; (put 'process-connection 'elsa-type (elsa-make-type nil))
(put 'process-type 'elsa-type (elsa-make-type (function ((or process buffer string nil)) symbol)))
;; TODO format-network-address has an &optional parameter:
(put 'format-network-address 'elsa-type (elsa-make-type (function ((or (vector int) string (cons mixed mixed)) bool) (or string nil))))
(put 'process-list 'elsa-type (elsa-make-type (function (nil) (list process))))
(put 'make-process 'elsa-type (elsa-make-type (function ((list mixed)) process)))
(put 'make-pipe-process 'elsa-type (elsa-make-type (function ((list mixed)) process)))
(put 'process-datagram-address 'elsa-type (elsa-make-type (function (process) mixed)))
(put 'set-process-datagram-address 'elsa-type (elsa-make-type (function (process mixed) mixed)))
;; TODO set-network-process-option has an &optional parameter:
(put 'set-network-process-option 'elsa-type (elsa-make-type (function (process symbol mixed bool) bool)))
(put 'serial-process-configure 'elsa-type (elsa-make-type (function ((list mixed)) mixed)))
(put 'make-serial-process 'elsa-type (elsa-make-type (function ((list mixed)) process)))
(put 'make-network-process 'elsa-type (elsa-make-type (function ((list mixed)) process)))
(put 'network-interface-list 'elsa-type (elsa-make-type (function (nil) (list (cons string mixed)))))
(put 'network-interface-info 'elsa-type (elsa-make-type (function (string) (list mixed))))
;; TODO accept-process-output has an &optional parameter:
(put 'accept-process-output 'elsa-type (elsa-make-type (function ((or process nil) number nil (or bool int)) bool)))
(put 'internal-default-process-filter 'elsa-type (elsa-make-type (function (process string) mixed)))
(put 'process-send-region 'elsa-type (elsa-make-type (function (process int int) mixed)))
(put 'process-send-string 'elsa-type (elsa-make-type (function (process string) mixed)))
;; TODO process-running-child-p has an &optional parameter:
(put 'process-running-child-p 'elsa-type (elsa-make-type (function (process) (or int bool))))
;; TODO interrupt-process has an &optional parameter:
(put 'interrupt-process 'elsa-type (elsa-make-type (function ((or process buffer string nil) (or symbol nil)) mixed)))
;; TODO kill-process has an &optional parameter:
(put 'kill-process 'elsa-type (elsa-make-type (function ((or process string nil) (or symbol nil)) mixed)))
;; TODO quit-process has an &optional parameter:
(put 'quit-process 'elsa-type (elsa-make-type (function ((or process string nil) (or symbol nil)) mixed)))
;; TODO stop-process has an &optional parameter:
(put 'stop-process 'elsa-type (elsa-make-type (function ((or process string nil) (or symbol nil)) mixed)))
;; TODO continue-process has an &optional parameter:
(put 'continue-process 'elsa-type (elsa-make-type (function ((or process string nil) (or symbol nil)) mixed)))
(put 'signal-process 'elsa-type (elsa-make-type (function ((or process int) (or symbol int)) mixed)))
;; TODO process-send-eof has an &optional parameter:
(put 'process-send-eof 'elsa-type (elsa-make-type (function ((or process buffer string nil)) mixed)))
(put 'internal-default-process-sentinel 'elsa-type (elsa-make-type (function (process string) mixed)))
(put 'set-process-coding-system 'elsa-type (elsa-make-type (function (process symbol symbol) mixed)))
(put 'process-coding-system 'elsa-type (elsa-make-type (function (process) (cons symbol symbol))))
(put 'set-process-filter-multibyte 'elsa-type (elsa-make-type (function (process bool) mixed)))
(put 'process-filter-multibyte-p 'elsa-type (elsa-make-type (function (process) bool)))
(put 'get-buffer-process 'elsa-type (elsa-make-type (function ((or buffer string)) (or process nil))))
(put 'process-inherit-coding-system-flag 'elsa-type (elsa-make-type (function (process) bool)))
(put 'waiting-for-user-input-p 'elsa-type (elsa-make-type (function (nil) bool)))
(put 'list-system-processes 'elsa-type (elsa-make-type (function (nil) (list int))))
(put 'process-attributes 'elsa-type (elsa-make-type (function (int) (list (cons symbol mixed)))))

;; File: syntax.c
;; (put 'syntax-table-p 'elsa-type (elsa-make-type))
;; (put 'syntax-table 'elsa-type (elsa-make-type))
;; (put 'standard-syntax-table 'elsa-type (elsa-make-type))
;; (put 'copy-syntax-table 'elsa-type (elsa-make-type))
;; (put 'set-syntax-table 'elsa-type (elsa-make-type))
(put 'char-syntax 'elsa-type (elsa-make-type (function (int) int)))
(put 'matching-paren 'elsa-type (elsa-make-type (function (int) (or int nil))))
;; (put 'string-to-syntax 'elsa-type (elsa-make-type))
;; (put 'modify-syntax-entry 'elsa-type (elsa-make-type))
;; (put 'internal-describe-syntax-value 'elsa-type (elsa-make-type))
(put 'forward-word 'elsa-type (elsa-make-type (function ((or int nil)) bool)))
(put 'skip-chars-forward 'elsa-type (elsa-make-type (function (string (or int nil)) int)))
(put 'skip-chars-backward 'elsa-type (elsa-make-type (function (string (or int nil)) int)))
;; (put 'skip-syntax-forward 'elsa-type (elsa-make-type))
;; (put 'skip-syntax-backward 'elsa-type (elsa-make-type))
(put 'forward-comment 'elsa-type (elsa-make-type (function (int) bool)))
(put 'scan-lists 'elsa-type (elsa-make-type (function (int int int) (or int nil))))
(put 'scan-sexps 'elsa-type (elsa-make-type (function (int int) (or int nil))))
(put 'backward-prefix-chars 'elsa-type (elsa-make-type nil))
;; (put 'parse-partial-sexp 'elsa-type (elsa-make-type))

;; File: keymap.c
;; (put 'make-keymap 'elsa-type (elsa-make-type ))
;; (put 'make-sparse-keymap 'elsa-type (elsa-make-type ))
(put 'keymapp 'elsa-type (elsa-make-type (function (mixed) (is keymap))))
;; (put 'keymap-prompt 'elsa-type (elsa-make-type ))
;; (put 'keymap-parent 'elsa-type (elsa-make-type ))
;; (put 'set-keymap-parent 'elsa-type (elsa-make-type ))
;; (put 'map-keymap-internal 'elsa-type (elsa-make-type ))
;; (put 'map-keymap 'elsa-type (elsa-make-type ))
;; (put 'copy-keymap 'elsa-type (elsa-make-type ))
;; (put 'define-key 'elsa-type (elsa-make-type ))
;; (put 'command-remapping 'elsa-type (elsa-make-type ))
;; (put 'lookup-key 'elsa-type (elsa-make-type ))
;; (put 'current-active-maps 'elsa-type (elsa-make-type ))
;; (put 'key-binding 'elsa-type (elsa-make-type ))
;; (put 'local-key-binding 'elsa-type (elsa-make-type ))
;; (put 'global-key-binding 'elsa-type (elsa-make-type ))
;; (put 'minor-mode-key-binding 'elsa-type (elsa-make-type ))
;; (put 'define-prefix-command 'elsa-type (elsa-make-type ))
;; (put 'use-global-map 'elsa-type (elsa-make-type ))
;; (put 'use-local-map 'elsa-type (elsa-make-type ))
;; (put 'current-local-map 'elsa-type (elsa-make-type ))
;; (put 'current-global-map 'elsa-type (elsa-make-type ))
;; (put 'current-minor-mode-maps 'elsa-type (elsa-make-type ))
;; (put 'accessible-keymaps 'elsa-type (elsa-make-type ))
;; (put 'key-description 'elsa-type (elsa-make-type ))
(put 'single-key-description 'elsa-type (elsa-make-type (function (int mixed) string)))
;; (put 'text-char-description 'elsa-type (elsa-make-type ))
;; (put 'where-is-internal 'elsa-type (elsa-make-type ))
;; (put 'describe-buffer-bindings 'elsa-type (elsa-make-type ))
;; (put 'describe-vector 'elsa-type (elsa-make-type ))
;; (put 'apropos-internal 'elsa-type (elsa-make-type ))

;; File: search.c
(put 'looking-at 'elsa-type (elsa-make-type (function (string) bool)))
(put 'posix-looking-at 'elsa-type (elsa-make-type (function (string) bool)))
;; TODO: string-match has an &optional arg
(put 'string-match 'elsa-type (elsa-make-type (function (string string (or int nil)) (or int nil))))
(put 'posix-string-match 'elsa-type (elsa-make-type (function (string string int) (or int nil))))
(put 'search-backward 'elsa-type (elsa-make-type (function (string (or int nil) mixed (or int nil)) (or int nil))))
(put 'search-forward 'elsa-type (elsa-make-type (function (string (or int nil) mixed (or int nil)) (or int nil))))
(put 're-search-backward 'elsa-type (elsa-make-type (function (string (or int nil) mixed (or int nil)) (or int nil))))
(put 're-search-forward 'elsa-type (elsa-make-type (function (string (or int nil) mixed (or int nil)) (or int nil))))
(put 'posix-search-backward 'elsa-type (elsa-make-type (function (string (or int nil) mixed) (or int nil))))
(put 'posix-search-forward 'elsa-type (elsa-make-type (function (string (or int nil) mixed) (or int nil))))
(put 'replace-match 'elsa-type (elsa-make-type (function (string bool bool (or string nil) int) nil)))
(put 'match-beginning 'elsa-type (elsa-make-type (function (int) (or nil int))))
(put 'match-end 'elsa-type (elsa-make-type (function (int) (or nil int))))
;; TODO: Return type depends on first arg. Also see docstring for note
;; on return value.
(put 'match-data 'elsa-type (elsa-make-type (function (bool (list mixed) bool) (list (or marker int nil)))))
(put 'set-match-data 'elsa-type (elsa-make-type (function ((list (or marker int nil)) bool) nil)))
(put 'regexp-quote 'elsa-type (elsa-make-type (function (string) string)))
;; (put 'newline-cache-check 'elsa-type (elsa-make-type ))

;; File: buffer.c
(put 'buffer-live-p 'elsa-type (elsa-make-type (function (mixed) bool)))
(put 'buffer-list 'elsa-type (elsa-make-type (function ((or frame nil)) (list buffer))))
;; TODO: Theoretically should only return nil for a string arg
(put 'get-buffer 'elsa-type (elsa-make-type (function ((or buffer string)) (or buffer nil))))
(put 'get-file-buffer 'elsa-type (elsa-make-type (function (string) (or buffer nil))))
(put 'get-buffer-create 'elsa-type (elsa-make-type (function ((or buffer string)) buffer)))
(put 'make-indirect-buffer 'elsa-type (elsa-make-type (function (buffer string bool) buffer)))
(put 'generate-new-buffer-name 'elsa-type (elsa-make-type (function (string (or string nil)) string)))
;; TODO: Theoretically can only return nil if BUFFER is non-nil
(put 'buffer-name 'elsa-type (elsa-make-type (function ((or buffer nil)) (or string nil))))
(put 'buffer-file-name 'elsa-type (elsa-make-type (function ((or buffer nil)) (or string nil))))
(put 'buffer-base-buffer 'elsa-type (elsa-make-type (function ((or buffer nil)) (or buffer nil))))
(put 'buffer-local-value 'elsa-type (elsa-make-type (function (symbol buffer) mixed)))
(put 'buffer-local-variables 'elsa-type (elsa-make-type (function ((or buffer nil)) (list (or symbol (cons symbol mixed))))))
(put 'buffer-modified-p 'elsa-type (elsa-make-type (function ((or buffer nil)) bool)))
(put 'force-mode-line-update 'elsa-type (elsa-make-type (function (bool) bool)))
(put 'set-buffer-modified-p 'elsa-type (elsa-make-type (function (bool) bool)))
(put 'restore-buffer-modified-p 'elsa-type (elsa-make-type (function (bool) bool)))
(put 'buffer-modified-tick 'elsa-type (elsa-make-type (function ((or buffer nil)) int)))
(put 'buffer-chars-modified-tick 'elsa-type (elsa-make-type (function ((or buffer nil)) int)))
(put 'rename-buffer 'elsa-type (elsa-make-type (function (string bool) string)))
(put 'other-buffer 'elsa-type (elsa-make-type (function ((or buffer nil) bool (or frame nil)) buffer)))
(put 'buffer-enable-undo 'elsa-type (elsa-make-type (function ((or buffer nil)) nil)))
(put 'kill-buffer 'elsa-type (elsa-make-type (function ((or buffer string nil)) bool)))
(put 'bury-buffer-internal 'elsa-type (elsa-make-type (function (buffer) nil)))
(put 'set-buffer-major-mode 'elsa-type (elsa-make-type (function (buffer) nil)))
(put 'current-buffer 'elsa-type (elsa-make-type buffer))
(put 'set-buffer 'elsa-type (elsa-make-type (function ((or buffer string)) buffer)))
(put 'barf-if-buffer-read-only 'elsa-type (elsa-make-type (function ((or int nil)) nil)))
(put 'erase-buffer 'elsa-type (elsa-make-type nil))
(put 'buffer-swap-text 'elsa-type (elsa-make-type (function (buffer) nil)))
(put 'set-buffer-multibyte 'elsa-type (elsa-make-type (function ((or bool (const to))) (or bool (const to)))))
(put 'kill-all-local-variables 'elsa-type (elsa-make-type nil))
(put 'overlayp 'elsa-type (elsa-make-type (function (mixed) (is overlay))))
;; (put 'make-overlay 'elsa-type (elsa-make-type ))
;; (put 'move-overlay 'elsa-type (elsa-make-type ))
;; (put 'delete-overlay 'elsa-type (elsa-make-type ))
;; (put 'delete-all-overlays 'elsa-type (elsa-make-type ))
;; TODO: overlay type
(put 'overlay-start 'elsa-type (elsa-make-type (function (mixed) int)))
;; TODO: overlay type
(put 'overlay-end 'elsa-type (elsa-make-type (function (mixed) int)))
;; (put 'overlay-buffer 'elsa-type (elsa-make-type ))
;; (put 'overlay-properties 'elsa-type (elsa-make-type ))
;; (put 'overlays-at 'elsa-type (elsa-make-type ))
;; (put 'overlays-in 'elsa-type (elsa-make-type ))
;; (put 'next-overlay-change 'elsa-type (elsa-make-type ))
;; (put 'previous-overlay-change 'elsa-type (elsa-make-type ))
;; (put 'overlay-lists 'elsa-type (elsa-make-type ))
;; (put 'overlay-recenter 'elsa-type (elsa-make-type ))
;; (put 'overlay-get 'elsa-type (elsa-make-type ))
;; (put 'overlay-put 'elsa-type (elsa-make-type ))

;; File: casefiddle.c
(put 'upcase 'elsa-type (elsa-make-type (and (function (string) string) (function (int) int))))
(put 'downcase 'elsa-type (elsa-make-type (and (function (string) string) (function (int) int))))

;; boolean functions
(put 'not 'elsa-type (elsa-make-type (function (mixed) (is nil))))

;; string functions
(put 'split-string 'elsa-type (elsa-make-type (function (string string) (list string))))
(put 'concat 'elsa-type (elsa-make-type (function (&rest string) string)))

;; sequence functions

;; built-in variables
(put 'command-line-args-left 'elsa-type-var (elsa-make-type (list string)))
(put 'major-mode 'elsa-type-var (elsa-make-type symbol))
(put 'last-command-event 'elsa-type-var (elsa-make-type int))
(put 'load-file-name 'elsa-type-var (elsa-make-type (or string nil)))
(put 'buffer-file-name 'elsa-type-var (elsa-make-type (or string nil)))

;; File: emacs.c
(put 'command-line-args 'elsa-tye-var (elsa-make-type (list string)))
(put 'system-type 'elsa-tye-var (elsa-make-type symbol))
(put 'system-configuration 'elsa-tye-var (elsa-make-type string))
(put 'system-configuration-options 'elsa-tye-var (elsa-make-type string))
(put 'system-configuration-features 'elsa-tye-var (elsa-make-type string))
(put 'noninteractive 'elsa-tye-var (elsa-make-type mixed))
(put 'kill-emacs-hook 'elsa-tye-var (elsa-make-type (list symbol)))
;; (put 'path-separator 'elsa-tye-var (elsa-make-type nil))
;; (put 'invocation-name 'elsa-tye-var (elsa-make-type nil))
;; (put 'invocation-directory 'elsa-tye-var (elsa-make-type nil))
;; (put 'installation-directory 'elsa-tye-var (elsa-make-type nil))
;; (put 'system-messages-locale 'elsa-tye-var (elsa-make-type nil))
;; (put 'previous-system-messages-locale 'elsa-tye-var (elsa-make-type nil))
;; (put 'system-time-locale 'elsa-tye-var (elsa-make-type nil))
;; (put 'previous-system-time-locale 'elsa-tye-var (elsa-make-type nil))
;; (put 'before-init-time 'elsa-tye-var (elsa-make-type nil))
;; (put 'after-init-time 'elsa-tye-var (elsa-make-type nil))
;; (put 'inhibit-x-resources 'elsa-tye-var (elsa-make-type nil))
;; (put 'emacs-copyright 'elsa-tye-var (elsa-make-type nil))
;; (put 'emacs-version 'elsa-tye-var (elsa-make-type nil))
;; (put 'report-emacs-bug-address 'elsa-tye-var (elsa-make-type nil))
;; (put 'dynamic-library-alist 'elsa-tye-var (elsa-make-type nil))
;; these two seem only to be defined in Emacs 26.3, not 28.1
;; previous-system-messages-locale
;; previous-system-time-locale

;; File: callproc.c
(put 'shell-file-name 'elsa-type-var (elsa-make-type string))
(put 'exec-path 'elsa-type-var (elsa-make-type (list string)))
(put 'exec-suffixes 'elsa-type-var (elsa-make-type (list string)))
(put 'exec-directory 'elsa-type-var (elsa-make-type string))
(put 'data-directory 'elsa-type-var (elsa-make-type string))
(put 'doc-directory 'elsa-type-var (elsa-make-type string))
(put 'configure-info-directory 'elsa-type-var (elsa-make-type string))
(put 'shared-game-score-directory 'elsa-type-var (elsa-make-type (or string nil)))
(put 'initial-environment 'elsa-type-var (elsa-make-type (list string)))
(put 'process-environment 'elsa-type-var (elsa-make-type (list string)))

;; help.el
(put 'help-function-arglist 'elsa-type (elsa-make-type (function (symbol) (list symbol))))

(provide 'elsa-typed-builtin)
