PageRenderTime 262ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/lisp/compile.l

https://github.com/snmsts/xyzzy
LEX | 2042 lines | 1864 code | 178 blank | 0 comment | 0 complexity | 927cb394aad6ac99151f2efc1bf3b58e MD5 | raw file
Possible License(s): BSD-3-Clause
  1. ;;; -*- Mode: Lisp; Package: COMPILER -*-
  2. ;;;
  3. ;;; This file is part of xyzzy.
  4. ;;;
  5. (provide "compile")
  6. ;;; OPE-CODES
  7. ;;; LEXICAL-REF: レキシカル変数の参照 (LEXICAL-REF (<SYMBOL> <SPECIAL-P> <REF-CLOSURE-P>))
  8. ;;; GLOBAL-REF: グローバル変数の参照 (GLOBAL-REF <SYMBOL>)
  9. ;;; LEXICAL-SET: レキシカル変数の設定 (LEXICAL-SET (<SYMBOL> <SPECIAL-P> <REF-CLOSURE-P>))
  10. ;;; GLOBAL-SET: グローバル変数の設定 (GLOBAL-SET <SYMBOL>)
  11. ;;; CONSTANT: 自己参照型 (CONSTANT <OBJECT>)
  12. ;;; CALL: 関数コール (CALL <FUNCTION> <NARGS>)
  13. ;;; DISCARD: スタックポインタを1- (DISCARD)
  14. ;;; GOTO: (GOTO <TAG>)
  15. ;;; IF-NIL-GOTO: stack[0]がnilならばgoto (IF-NIL-GOTO <TAG>)
  16. ;;; IF-NIL-GOTO-AND-POP: stack[0]がnilならばgoto (IF-NIL-GOTO-AND-POP <TAG>)
  17. ;;; IF-NON-NIL-GOTO: stack[0]がnon-nilならばgoto (IF-NON-NIL-GOTO <TAG>)
  18. ;;; IF-NON-NIL-GOTO-AND-POP: stack[0]がnon-nilならばgoto (IF-NON-NIL-GOTO-AND-POP <TAG>)
  19. ;;; LABEL: (LABEL <TAG>)
  20. ;;; RETURN: (RETURN <TAG>)
  21. ;;; GO: (GO <TAG>)
  22. ;;; ADJUST-STACK (ADJUST-STACK <STACK-DEPTH> <TAG>)
  23. ;;; BLOCK (BLOCK <TAG>)
  24. ;;; SPECIAL (SPECIAL <TAG> {<VAR>}*)
  25. ;;; SPECIAL-END
  26. ;;; MULTIPLE-VALUE-SET (MULTIPLE-VALUE-SET <COUNT>)
  27. ;;; MULTIPLE-VALUE-SET-END (MULTIPLE-VALUE-SET-END)
  28. ;;; LIST-MULTIPLE-VALUE
  29. ;;; CALL-MULTIPLE-VALUE
  30. ;;; SAVE-MULTIPLE-VALUE
  31. ;;; TAGBODY
  32. ;;; UNWIND-PROTECT
  33. ;;; CATCH
  34. ;;; THROW
  35. ;;; MAKE-CLOSURE
  36. ;;; SAVE-EXCURSION
  37. ;;; SAVE-RESTRICTION
  38. ;;; SAVE-WINDOW-EXCURSION
  39. ;;; OPTIMIZER
  40. ;;; SET - DISCARD - REF ---> SET
  41. ;;; SET - DISCARD ---> SET-DISCARD
  42. ;;; REF - DISCARD ---> none
  43. ;;; CONSTANT - DISCARD ---> none
  44. ;;; NULL/NOT NULL/NOT ---> none(無条件にやるのはまずい? まだやってないけど)
  45. ;;; NULL/NOT - IF-NIL-GOTO ---> IF-NON-NIL-GOTO (予定)
  46. ;;; NULL/NOT - IF-NON-NIL-GOTO ---> IF-NIL-GOTO (予定)
  47. ;;; jump optimize
  48. ;;; omit unreached code
  49. ;;; local return/go ---> GOTO
  50. ;;; constant folding
  51. (lisp:in-package "lisp")
  52. (eval-when (:compile-toplevel :load-toplevel :execute)
  53. (export '(compile-file byte-compile-file
  54. byte-recompile-directory compile
  55. mc-compile-file mc-byte-compile-file
  56. mc-byte-recompile-directory)))
  57. (eval-when (:compile-toplevel :load-toplevel :execute)
  58. (unless (find-package "compiler")
  59. (defpackage "compiler"
  60. (:use "lisp" "editor")
  61. (:internal-size 200)
  62. (:external-size 10))))
  63. (in-package "compiler")
  64. (let ()
  65. ;; *MACRO-ENVIRONMENT*: defmacro(コンパイル単位)
  66. ;; ローカルな関数マクロのリスト
  67. (defvar *macro-environment* nil)
  68. ;; *SPECIAL-VARIABLES*: スペシャル変数のリスト(コンパイル単位)
  69. (defvar *special-variables* nil)
  70. ;; *CONSTANT-VARIABLES*: 定数変数のリスト(コンパイル単位)
  71. ;; (SYMBOL . VALUE)
  72. (defvar *constant-variables* nil)
  73. ;; *STACK-DEPTH*: 現在のスタックの深さ
  74. (defvar *stack-depth* 0)
  75. ;; *STACK-DEPTH-MAX*: 最大のスタックの深さ
  76. (defvar *stack-depth-max* 0)
  77. ;; *VARIABLE-LIST*: 束縛変数のリスト
  78. (defvar *variable-list* nil)
  79. ;; *BOUND-VARS*: 束縛変数のリスト
  80. (defvar *bound-vars* nil)
  81. ;; *STACK-FRAME-INDEX*:
  82. (defvar *stack-frame-index* 0)
  83. ;; *STACK-FRAME-MAX*: 同時に有効になる束縛変数の個数の最大値
  84. (defvar *stack-frame-max* 0)
  85. ;; *BLOCK-ENVIRONMENT*: block環境のリスト
  86. (defvar *block-environment* nil)
  87. ;; *TAGBODY-ENVIRONMENT*: tagbody環境のリスト
  88. (defvar *tagbody-environment* nil)
  89. ;; *INSN-LIST*: 中間コードのリスト
  90. (defvar *insn-list* nil)
  91. (defvar *compile-time-too* nil))
  92. (let ()
  93. (setf (get 'defun 'toplevel-macro) 'print-defun)
  94. (setf (get 'defmacro 'toplevel-macro) 'print-form)
  95. (setf (get 'defconstant 'toplevel-macro) 'print-form)
  96. (setf (get 'defvar 'toplevel-macro) 'print-form)
  97. (setf (get 'defparameter 'toplevel-macro) 'print-form)
  98. (setf (get 'defmacro 'compiler-effect) 'record-defmacro)
  99. (setf (get 'defconstant 'compiler-effect) 'record-defconstant)
  100. (setf (get 'defvar 'compiler-effect) 'record-defvar)
  101. (setf (get 'defparameter 'compiler-effect) 'record-defvar)
  102. (setf (get 'quote 'special-form) 'compile-quote)
  103. (setf (get 'function 'special-form) 'compile-function)
  104. (setf (get 'progn 'special-form) 'compile-progn)
  105. (setf (get 'let 'special-form) 'compile-let)
  106. (setf (get 'let* 'special-form) 'compile-let*)
  107. (setf (get 'if 'special-form) 'compile-if)
  108. (setf (get 'setq 'special-form) 'compile-setq)
  109. (setf (get 'block 'special-form) 'compile-block)
  110. (setf (get 'return-from 'special-form) 'compile-return-from)
  111. (setf (get 'tagbody 'special-form) 'compile-tagbody)
  112. (setf (get 'go 'special-form) 'compile-go)
  113. (setf (get 'unwind-protect 'special-form) 'compile-unwind-protect)
  114. (setf (get 'catch 'special-form) 'compile-catch)
  115. (setf (get 'throw 'special-form) 'compile-throw)
  116. (setf (get 'eval-when 'special-form) 'compile-eval-when)
  117. (setf (get 'multiple-value-call 'special-form) 'compile-multiple-value-call)
  118. (setf (get 'multiple-value-prog1 'special-form) 'compile-multiple-value-prog1)
  119. (setf (get 'multiple-value-bind 'special-form) 'compile-multiple-value-bind)
  120. (setf (get 'multiple-value-setq 'special-form) 'compile-multiple-value-setq)
  121. (setf (get 'save-excursion 'special-form) 'compile-save-excursion)
  122. (setf (get 'save-restriction 'special-form) 'compile-save-restriction)
  123. (setf (get 'save-window-excursion 'special-form) 'compile-save-window-excursion)
  124. (setf (get 'flet 'special-form) 'compile-flet)
  125. (setf (get 'labels 'special-form) 'compile-labels)
  126. (setf (get 'macrolet 'special-form) 'compile-macrolet)
  127. (setf (get '*compile-flet-bind 'special-form) '*compile-flet-bind))
  128. (defun byte-compile-file (filename)
  129. (interactive "fByte compile file: " :title0 "Byte compile file")
  130. (long-operation
  131. (compile-file filename)))
  132. (defun mc-byte-compile-file (filename &optional encoding)
  133. (interactive "fByte compile file: \n0zEncoding: " :title0 "Byte compile file")
  134. (long-operation
  135. (mc-compile-file filename encoding)))
  136. (defun byte-recompile-directory (dirname &optional arg)
  137. (interactive "DByte compile directory: \np")
  138. (byte-recompile-directory-1 dirname arg #'compile-file))
  139. (defun mc-byte-recompile-directory (dirname &optional arg)
  140. (interactive "DByte compile directory: \np")
  141. (byte-recompile-directory-1 dirname arg #'mc-compile-file))
  142. (defun byte-recompile-directory-1 (dirname arg compile-fn)
  143. (long-operation
  144. (let ((count 0))
  145. (dolist (src (mapcan #'(lambda (ext)
  146. (directory (merge-pathnames ext dirname) :absolute t))
  147. '("*.l" "*.lisp")))
  148. (let ((dst (compile-file-pathname src)))
  149. (when (if (file-exist-p dst)
  150. (file-newer-than-file-p src dst)
  151. (and arg (yes-no-or-cancel-p "~Aをコンパイルしますか?" src)))
  152. (funcall compile-fn src)
  153. (setq count (1+ count)))))
  154. (format t "Total ~[No~:;~:*~d~] file~:*~p compiled~%" count)
  155. count)))
  156. (defun compile-file (filename)
  157. (with-open-file (is filename :direction :input :if-does-not-exist :error)
  158. (compile-file-1 filename is)))
  159. (defun mc-compile-file (filename &optional encoding)
  160. (unless (file-exist-p filename)
  161. (error 'file-not-found
  162. :datum "ファイルが見つかりません"
  163. :pathname filename))
  164. (let (buffer)
  165. (unwind-protect
  166. (ed:save-excursion
  167. (setq buffer (ed:create-new-buffer " *compile file*"))
  168. (ed:set-buffer buffer)
  169. (let ((ed:*expected-fileio-encoding*
  170. (or encoding
  171. (ed::find-file-auto-encoding filename)
  172. ed:*expected-fileio-encoding*)))
  173. (declare (special ed:*expected-fileio-encoding*))
  174. (ed:insert-file-contents filename t)
  175. (compile-file-1 filename (ed:make-buffer-stream buffer)
  176. (cadr (assoc (ed:buffer-fileio-encoding) ed:*character-set-alist*
  177. :key #'symbol-value)))))
  178. (when buffer
  179. (ed:delete-buffer buffer)))))
  180. (defun compile-file-1 (filename is &optional encoding)
  181. (setq filename (namestring filename))
  182. (with-open-file (os (compile-file-pathname filename)
  183. :direction :output
  184. :if-exists :supersede
  185. :if-does-not-exist :create)
  186. (when encoding
  187. (format os ";;; -*- Mode: Lisp; Encoding: ~A; -*-~%" encoding))
  188. (let ((*macro-environment* nil)
  189. (*special-variables* nil)
  190. (*constant-variables* nil)
  191. (*compile-time-too* nil)
  192. (*package* *package*))
  193. (let ((eof (make-symbol "eof"))
  194. form)
  195. (while (setq form (read is nil eof))
  196. (if (eq form eof)
  197. (return))
  198. (let ((opackage *package*))
  199. (setq form (process-toplevel form))
  200. (let ((*package* opackage))
  201. (if (and (consp form)
  202. (eq (car form) 'progn))
  203. (dolist (f (cdr form))
  204. (unless (constant-variable-p f)
  205. (write f :stream os :escape t :circle t)
  206. (terpri os)))
  207. (unless (constant-variable-p form)
  208. (write form :stream os :escape t :circle t)
  209. (terpri os)))))))))
  210. (princ "done.\n")
  211. t)
  212. (defun compile (name &optional definition)
  213. (setq definition
  214. (coerce (or definition
  215. (setq definition (symbol-function name)))
  216. 'function))
  217. (cond ((compiled-function-p definition))
  218. ((and (listp definition)
  219. (eq (car definition) 'macro)))
  220. ((si:*closurep definition)
  221. (when (or (si:closure-variable definition)
  222. (si:closure-function definition)
  223. (si:closure-frame definition))
  224. (error "空でない環境で定義された関数はコンパイルできません"))
  225. (let ((*macro-environment* nil)
  226. (*special-variables* nil)
  227. (*constant-variables* nil)
  228. (*stack-depth* 0)
  229. (*stack-depth-max* 0)
  230. (*variable-list* nil)
  231. (*bound-vars* nil)
  232. (*stack-frame-index* 0)
  233. (*stack-frame-max* 0)
  234. (*block-environment* nil)
  235. (*tagbody-environment* nil)
  236. (*insn-list* nil)
  237. (form (si:closure-body definition)))
  238. (multiple-value-bind (decl intr nargs)
  239. (compile-lambda form)
  240. (setq definition
  241. (coerce `(lambda ,(cadr form) ,@decl ,@intr
  242. ,(output-bytecode
  243. (optimize-insn (nreverse *insn-list*))
  244. nargs))
  245. 'function)))))
  246. (t
  247. (error "~Sはコンパイルできません" definition)))
  248. (if (null name)
  249. definition
  250. (progn
  251. (setf (symbol-function name) definition)
  252. name)))
  253. (defun print-defun (f)
  254. (format t "Compiling ~S...~%" (cadr f)))
  255. (defun print-form (f)
  256. (format t "~S...~%" f))
  257. (defun record-defmacro (form)
  258. (when (special-form-p (cadr form))
  259. (error 'invalid-function :datum (cadr form)))
  260. (push (cons (cadr form)
  261. (cons 'macro (cddr form)))
  262. *macro-environment*)
  263. form)
  264. (defun record-defconstant (form)
  265. (let ((symbol (cadr form))
  266. (value (eval (caddr form))))
  267. (check-type symbol symbol)
  268. (unless (constantp symbol)
  269. (set symbol value))
  270. (push (cons symbol value) *constant-variables*)
  271. (push symbol *special-variables*)
  272. form))
  273. (defun record-defvar (form)
  274. (let ((symbol (cadr form)))
  275. (check-type symbol symbol)
  276. (push symbol *special-variables*)
  277. form))
  278. (defun output-insn (ope &rest args)
  279. (push (cons ope args) *insn-list*))
  280. (defun output-label (tag)
  281. (push (list 'insn-label tag) *insn-list*))
  282. (defun update-stack (l)
  283. (incf *stack-depth* l)
  284. (setq *stack-depth-max* (max *stack-depth* *stack-depth-max*)))
  285. ;;; VARが定数変数?
  286. (defun constant-variable-p (var)
  287. (or (constantp var)
  288. (assoc var *constant-variables* :test #'eq)))
  289. (defmacro bound-var-symbol (x) `(car ,x))
  290. (defmacro bound-var-special-p (x) `(cadr ,x))
  291. (defmacro bound-var-refered-from-closure-p (x) `(caddr ,x))
  292. (defmacro bound-var-stack-frame-index (x) `(cadddr ,x))
  293. ;;; VARがグローバルなスペシャル変数?
  294. (defun global-special-p (var)
  295. (or (si:*specialp var)
  296. (member var *special-variables* :test #'eq)))
  297. ;;; 変数を作る: (SYMBOL SPECIALP <closureから参照された?> <stack frameのインデックス>)
  298. (defun make-variable (var)
  299. (unless (symbolp var)
  300. (compile-error "Wrong type argument: ~S" var))
  301. (when (constant-variable-p var)
  302. (compile-error "Attempt to modify constant: ~S" var))
  303. (let ((x (list var nil nil nil)))
  304. (push x *variable-list*)
  305. x))
  306. ;;; 変数にスタックフレームのインデックスをセットする
  307. (defun make-stack-frame (vars)
  308. (dolist (var vars)
  309. (setf (bound-var-stack-frame-index var) *stack-frame-index*)
  310. (incf *stack-frame-index*))
  311. (setq *stack-frame-max* (max *stack-frame-max* *stack-frame-index*)))
  312. ;;; シンボルVARの値を得る。
  313. (defun compile-varref (var)
  314. (let ((closurep nil))
  315. (dolist (l *bound-vars* 'nil)
  316. (if (eq l 'closure)
  317. (setq closurep t)
  318. (let ((v (assoc var l :test #'eq)))
  319. (when v
  320. (if (bound-var-special-p v)
  321. (return))
  322. (output-insn 'insn-lexical-ref v)
  323. (if closurep
  324. (setf (bound-var-refered-from-closure-p v) 't))
  325. (return-from compile-varref)))))
  326. (if (constant-variable-p var)
  327. (let ((value (assoc var *constant-variables* :test #'eq)))
  328. (setq value (if value (cdr value) (symbol-value var)))
  329. (if (or (integerp value)
  330. (floatp value)
  331. (characterp value)
  332. (and (symbolp value)
  333. (symbol-package value)))
  334. (compile-constant value)
  335. (output-insn 'insn-global-ref var)))
  336. (output-insn 'insn-global-ref var))))
  337. ;;; シンボルVARに値をセットする
  338. (defun compile-varset (var)
  339. (check-type var symbol)
  340. (cond ((constant-variable-p var)
  341. (compile-error 'modify-constant :name var))
  342. ((let ((closurep nil))
  343. (dolist (l *bound-vars* 'nil)
  344. (if (eq l 'closure)
  345. (setq closurep t)
  346. (let ((v (assoc var l :test #'eq)))
  347. (when v
  348. (if (bound-var-special-p v)
  349. (return 'nil))
  350. (output-insn 'insn-lexical-set v)
  351. (if closurep
  352. (setf (bound-var-refered-from-closure-p v) 't))
  353. (return 't)))))))
  354. (t
  355. (output-insn 'insn-global-set var))))
  356. ;;; 自己評価フォームを出力
  357. (defun compile-constant (object)
  358. (output-insn 'insn-constant object))
  359. ;;; スペシャル宣言された束縛変数を集める。
  360. (defun process-declare (decl)
  361. (let ((decls '())
  362. (specials '()))
  363. (dolist (d decl)
  364. (dolist (l (cdr d))
  365. (if (eq (car l) 'special)
  366. (dolist (x (cdr l))
  367. (if (symbolp x)
  368. (push x decls))))))
  369. (dolist (v (car *bound-vars*))
  370. (when (global-special-p (car v))
  371. (push v specials)))
  372. (dolist (d decls)
  373. (unless (or (global-special-p d)
  374. (assoc d specials :test #'eq))
  375. (dolist (l *bound-vars*)
  376. (let ((v (assoc d l :test #'eq)))
  377. (when v
  378. (push v specials)
  379. (return))))))
  380. specials))
  381. ;;; スペシャル宣言された束縛変数にマークをつける。
  382. (defun mark-special-vars (specials)
  383. (dolist (v specials)
  384. (setf (bound-var-special-p v) 't)))
  385. ;;; ブロックを確立する: (<識別子> <TAG> <closureから参照された?>)
  386. (defun estab-block (name)
  387. (let ((x (list name (make-tag (gensym "BLOCK")) 'nil)))
  388. (output-insn 'insn-block x)
  389. (push x *block-environment*)))
  390. ;;; ブロックを解除する。
  391. (defun unestab-block ()
  392. (let ((x (pop *block-environment*)))
  393. (output-label (cadr x))))
  394. ;;; NAMEにマッチするブロックのTAGを返す。
  395. (defun find-block (name)
  396. (let ((closurep nil))
  397. (dolist (x *block-environment*)
  398. (cond ((eq x 'closure)
  399. (setq closurep t))
  400. ((eq (car x) name)
  401. (if closurep
  402. (setf (caddr x) t))
  403. (return-from find-block (values x closurep))))))
  404. (compile-error 'no-target :operation 'return-from :target name))
  405. ;;; タグを作る (<識別子> <stack-depth> <closureから参照された?>)
  406. (defun make-tag (&optional (name (gensym "TAG")))
  407. (list name *stack-depth* 'nil))
  408. ;;; NAMEにマッチするtabgodyのTAGを返す。
  409. (defun find-tagbody (name)
  410. (let ((closurep nil))
  411. (dolist (l *tagbody-environment*)
  412. (if (eq l 'closure)
  413. (setq closurep t)
  414. (let ((x (assoc name l :test #'eq)))
  415. (when x
  416. (if closurep
  417. (setf (caddr x) t))
  418. (return-from find-tagbody (values x closurep)))))))
  419. (compile-error 'no-target :operation 'go :target name))
  420. (defun parse-lambda-list (arglist)
  421. (let ((lambda-keys '(&optional &rest &key &aux))
  422. (vars '())
  423. arg)
  424. (while (setq arg (pop arglist))
  425. (if (member arg lambda-keys :test #'eq)
  426. (return))
  427. (push (make-variable arg) vars))
  428. (pop lambda-keys)
  429. (when (eq arg '&optional)
  430. (while (setq arg (pop arglist))
  431. (cond ((member arg lambda-keys :test #'eq)
  432. (return))
  433. ((symbolp arg)
  434. (push (make-variable arg) vars))
  435. ((consp arg)
  436. (push (make-variable (car arg)) vars)
  437. (when (caddr arg)
  438. (push (make-variable (caddr arg)) vars)))
  439. (t
  440. (compile-error 'type-error
  441. :datum arg
  442. :expected-type '(or symbol cons))))))
  443. (pop lambda-keys)
  444. (when (eq arg '&rest)
  445. (setq arg (pop arglist))
  446. (push (make-variable arg) vars)
  447. (setq arg (pop arglist)))
  448. (pop lambda-keys)
  449. (when (eq arg '&key)
  450. (while (setq arg (pop arglist))
  451. (cond ((member arg lambda-keys :test #'eq)
  452. (return))
  453. ((symbolp arg)
  454. (push (make-variable arg) vars))
  455. ((consp arg)
  456. (cond ((symbolp (car arg))
  457. (push (make-variable (car arg)) vars))
  458. ((consp (car arg))
  459. (push (make-variable (cadar arg)) vars))
  460. (t
  461. (compile-error 'type-error
  462. :expected-type '(or symbol cons)
  463. :datum (car arg))))
  464. (when (caddr arg)
  465. (push (make-variable (caddr arg)) vars)))
  466. (t
  467. (compile-error 'type-error
  468. :expected-type '(or symbol cons)
  469. :datum arg)))))
  470. (when (eq arg '&aux)
  471. (while (setq arg (pop arglist))
  472. (cond ((symbolp arg)
  473. (push (make-variable arg) vars))
  474. ((consp arg)
  475. (push (make-variable (car arg)) vars))
  476. (t
  477. (compile-error 'type-error
  478. :expected-type '(or symbol cons)
  479. :datum arg)))))
  480. vars))
  481. (defun compile-lambda (form)
  482. (multiple-value-bind (decl body)
  483. (lisp::find-declaration (cddr form))
  484. (multiple-value-bind (intr body)
  485. (lisp::find-interactive body)
  486. (let* ((*stack-frame-index* *stack-frame-index*)
  487. (args (parse-lambda-list (cadr form)))
  488. (nargs (length args)))
  489. (push args *bound-vars*)
  490. (make-stack-frame args)
  491. (mark-special-vars (process-declare decl))
  492. (compile-progn body)
  493. (pop *bound-vars*)
  494. (values decl intr nargs)))))
  495. (defun compile-closure (form)
  496. (let ((*stack-depth* 0)
  497. (*stack-depth-max* 0)
  498. (*stack-frame-index* 0)
  499. (*stack-frame-max* 0)
  500. (*insn-list* nil)
  501. decl
  502. intr
  503. nargs
  504. insn)
  505. (push 'closure *tagbody-environment*)
  506. (push 'closure *block-environment*)
  507. (push 'closure *bound-vars*)
  508. (multiple-value-setq (decl intr nargs) (compile-lambda form))
  509. (pop *bound-vars*)
  510. (pop *block-environment*)
  511. (pop *tagbody-environment*)
  512. (setq insn (optimize-insn (nreverse *insn-list*)))
  513. `(lambda ,(cadr form) ,@decl ,@intr ,(output-bytecode insn nargs))))
  514. (defun compile-toplevel (fn form)
  515. (cond ((eq (car form) 'quote)
  516. form)
  517. ((and (eq (car form) 'function)
  518. (symbolp (cadr form)))
  519. form)
  520. (t
  521. (let ((*stack-depth* 0)
  522. (*stack-depth-max* 0)
  523. (*variable-list* nil)
  524. (*bound-vars* nil)
  525. (*stack-frame-index* 0)
  526. (*stack-frame-max* 0)
  527. (*block-environment* nil)
  528. (*tagbody-environment* nil)
  529. (*insn-list* nil))
  530. (compile-form form)
  531. (output-bytecode (optimize-insn (nreverse *insn-list*)) 0)))))
  532. (defun process-toplevel (f)
  533. (cond ((or (atom f)
  534. (not (symbolp (car f))))
  535. f)
  536. ((eq (car f) 'progn)
  537. (setq f (mapcan #'(lambda (x)
  538. (setq x (process-toplevel x))
  539. (if x (list x)))
  540. (cdr f)))
  541. (if (endp (cdr f))
  542. (car f)
  543. (cons 'progn f)))
  544. ((eq (car f) 'eval-when)
  545. (cond ((endp (cdr f))
  546. (compile-error "EVAL-WHENフォームの形式が不正です: ~S" f))
  547. ((or (member :load-toplevel (cadr f) :test #'eq)
  548. (member 'load (cadr f) :test #'eq))
  549. (let ((*compile-time-too*
  550. (or (member :compile-toplevel (cadr f) :test #'eq)
  551. (member 'compile (cadr f) :test #'eq)
  552. (and (or (member :execute (cadr f) :test #'eq)
  553. (member 'eval (cadr f) :test #'eq))
  554. *compile-time-too*))))
  555. (process-toplevel (cons 'progn (cddr f)))))
  556. ((or (member :compile-toplevel (cadr f) :test #'eq)
  557. (member 'compile (cadr f) :test #'eq)
  558. (and (or (member :execute (cadr f) :test #'eq)
  559. (member 'eval (cadr f) :test #'eq))
  560. *compile-time-too*))
  561. (mapc #'eval (cddr f))
  562. nil)
  563. (t nil)))
  564. ((eq (car f) 'quote)
  565. f)
  566. (t
  567. (let (tem)
  568. (and (setq tem (get (car f) 'toplevel-macro))
  569. (funcall tem f))
  570. (and (setq tem (get (car f) 'compiler-effect))
  571. (funcall tem f))
  572. (setq tem (macroexpand-1 f *macro-environment*))
  573. (unless (eq tem f)
  574. (return-from process-toplevel (process-toplevel tem)))
  575. (if *compile-time-too*
  576. (eval f))
  577. (setq tem (get (car f) 'special-form))
  578. (if tem
  579. (compile-toplevel tem f)
  580. (cons (car f)
  581. (mapcar #'(lambda (x)
  582. (if (and (consp x)
  583. (symbolp (car x))
  584. (get (car x) 'special-form))
  585. (compile-toplevel (get (car x) 'special-form) x)
  586. x))
  587. (cdr f))))))))
  588. (defun compile-call (form)
  589. (let ((f (assoc (car form) *macro-environment* :test #'eq)))
  590. (cond ((null f)
  591. (when (and (consp (car form))
  592. (eq (caar form) 'lambda))
  593. (push 'funcall form))
  594. (dolist (f (cdr form))
  595. (compile-form f))
  596. (output-insn 'insn-call (car form) (- (length form) 1)))
  597. ((symbolp (cdr f))
  598. (compile-form (cdr f))
  599. (dolist (f (cdr form))
  600. (compile-form f))
  601. (output-insn 'insn-call 'funcall (length form)))
  602. (t
  603. (compile-error "不正な関数コールです: ~S" form)))))
  604. (defun compile-form (form)
  605. (let ((ostack *stack-depth*))
  606. (cond ((symbolp form)
  607. (compile-varref form))
  608. ((consp form)
  609. (if (symbolp (car form))
  610. (let ((tem (get (car form) 'special-form)))
  611. (cond (tem
  612. (funcall tem (cdr form)))
  613. (t
  614. (and (setq tem (get (car form) 'compiler-effect))
  615. (funcall tem form))
  616. (multiple-value-setq (form tem)
  617. (macroexpand-1 form *macro-environment*))
  618. (if tem
  619. (compile-form form)
  620. (progn
  621. (and (null (assoc (car form) *macro-environment*
  622. :test #'eq))
  623. (setq tem (get (car form) 'optimize-form))
  624. (setq form (funcall tem form)))
  625. (compile-call form))))))
  626. (compile-call form)))
  627. (t
  628. (compile-constant form)))
  629. (setq *stack-depth* ostack)
  630. (update-stack 1)))
  631. (defun compile-setq (form)
  632. (if (null form)
  633. (compile-form nil)
  634. (do ((f form (cddr f)))
  635. ((endp f))
  636. (cond ((endp (cdr f))
  637. (compile-error 'too-few-arguments))
  638. (t
  639. (compile-form (cadr f))
  640. (compile-varset (car f))
  641. (unless (endp (cddr f))
  642. (decf *stack-depth*)
  643. (output-insn 'insn-discard)))))))
  644. (defun compile-progn (form)
  645. (compile-form (car form))
  646. (dolist (x (cdr form))
  647. (decf *stack-depth*)
  648. (output-insn 'insn-discard)
  649. (compile-form x)))
  650. (defun compile-let (form)
  651. (if (endp form)
  652. (compile-error "LETフォームの形式が不正です: ~S" form))
  653. (multiple-value-bind (decl body)
  654. (lisp::find-declaration (cdr form))
  655. (let ((*stack-frame-index* *stack-frame-index*)
  656. (varlist (car form))
  657. (vars '())
  658. (tag (make-tag (gensym "LET"))))
  659. (dolist (var varlist)
  660. (compile-form (if (consp var) (cadr var) 'nil)))
  661. (dolist (var varlist)
  662. (push (make-variable (if (consp var) (car var) var)) vars))
  663. (output-insn 'insn-lexical-bind (cons tag vars))
  664. (push vars *bound-vars*)
  665. (make-stack-frame vars)
  666. (dolist (var (reverse varlist))
  667. (compile-varset (if (consp var) (car var) var))
  668. (output-insn 'insn-discard))
  669. (decf *stack-depth* (length varlist))
  670. (let ((specials (process-declare decl)))
  671. (if specials
  672. (progn
  673. (output-insn 'insn-special (list* tag specials))
  674. (dolist (v specials)
  675. (compile-varref (bound-var-symbol v)))
  676. (output-insn 'insn-special-end)
  677. (mark-special-vars specials)
  678. (compile-progn body))
  679. (compile-progn body)))
  680. (output-label tag)
  681. (pop *bound-vars*))))
  682. ;;;(defun compile-let* (form)
  683. ;;; (if (endp form)
  684. ;;; (compile-error "LET*フォームの形式が不正です: ~S" form))
  685. ;;; (multiple-value-bind (decl body)
  686. ;;; (lisp::find-declaration (cdr form))
  687. ;;; (let ((*stack-frame-index* *stack-frame-index*)
  688. ;;; (varlist (car form))
  689. ;;; (vars '())
  690. ;;; (tag (make-tag (gensym "LET"))))
  691. ;;; (push 'nil *bound-vars*)
  692. ;;; (dolist (var varlist)
  693. ;;; (push (make-variable (if (consp var) (car var) var)) vars))
  694. ;;; (setq vars (nreverse vars))
  695. ;;; (output-insn 'insn-lexical-bind (cons tag vars))
  696. ;;; (dolist (var varlist)
  697. ;;; (compile-form (if (consp var) (cadr var) 'nil))
  698. ;;; (push (pop vars) (car *bound-vars*))
  699. ;;; (decf *stack-depth*)
  700. ;;; (compile-varset (if (consp var) (car var) var))
  701. ;;; (output-insn 'insn-discard))
  702. ;;; (make-stack-frame (car *bound-vars*))
  703. ;;; (let ((specials (process-declare decl)))
  704. ;;; (if specials
  705. ;;; (progn
  706. ;;; (output-insn 'insn-special (list* tag specials))
  707. ;;; (dolist (v specials)
  708. ;;; (compile-varref (bound-var-symbol v)))
  709. ;;; (output-insn 'insn-special-end)
  710. ;;; (mark-special-vars specials)
  711. ;;; (compile-progn body))
  712. ;;; (compile-progn body)))
  713. ;;; (output-label tag)
  714. ;;; (pop *bound-vars*))))
  715. (defun compile-let* (form)
  716. (if (endp form)
  717. (compile-error "LET*フォームの形式が不正です: ~S" form))
  718. (multiple-value-bind (decl body)
  719. (lisp::find-declaration (cdr form))
  720. (let ((*stack-frame-index* *stack-frame-index*)
  721. (varlist (car form))
  722. (vars '())
  723. (tag (make-tag (gensym "LET"))))
  724. (push 'nil *bound-vars*)
  725. (dolist (var varlist)
  726. (push (make-variable (if (consp var) (car var) var)) vars))
  727. (setq vars (nreverse vars))
  728. (output-insn 'insn-lexical-bind (cons tag vars))
  729. (dolist (var varlist)
  730. (compile-form (if (consp var) (cadr var) 'nil))
  731. (let ((v (pop vars)))
  732. (push v (car *bound-vars*))
  733. (decf *stack-depth*)
  734. (compile-varset (if (consp var) (car var) var))
  735. (output-insn 'insn-discard)
  736. (make-stack-frame (list v))))
  737. (let ((specials (process-declare decl)))
  738. (if specials
  739. (progn
  740. (output-insn 'insn-special (list* tag specials))
  741. (dolist (v specials)
  742. (compile-varref (bound-var-symbol v)))
  743. (output-insn 'insn-special-end)
  744. (mark-special-vars specials)
  745. (compile-progn body))
  746. (compile-progn body)))
  747. (output-label tag)
  748. (pop *bound-vars*))))
  749. (defun compile-multiple-value-bind (form)
  750. (if (or (endp form)
  751. (endp (cdr form)))
  752. (compile-error "MULTIPLE-VALUE-BINDフォームの形式が不正です: ~S" form))
  753. (multiple-value-bind (decl body)
  754. (lisp::find-declaration (cddr form))
  755. (let ((*stack-frame-index* *stack-frame-index*)
  756. (varlist (car form))
  757. (vars '())
  758. (tag (make-tag (gensym "MULTIPLE-VALUE-BIND"))))
  759. (compile-form (cadr form)) ; compile values-form
  760. (dolist (var varlist)
  761. (push (make-variable var) vars))
  762. (output-insn 'insn-lexical-bind (cons tag vars))
  763. (push vars *bound-vars*)
  764. (make-stack-frame vars)
  765. (output-insn 'insn-multiple-value-set (length vars))
  766. (dolist (var varlist)
  767. (compile-varset (if (consp var) (car var) var)))
  768. (output-insn 'insn-multiple-value-set-end)
  769. (output-insn 'insn-discard)
  770. (decf *stack-depth*)
  771. (let ((specials (process-declare decl)))
  772. (if specials
  773. (progn
  774. (output-insn 'insn-special (list* tag specials))
  775. (dolist (v specials)
  776. (compile-varref (bound-var-symbol v)))
  777. (output-insn 'insn-special-end)
  778. (mark-special-vars specials)
  779. (compile-progn body))
  780. (compile-progn body)))
  781. (output-label tag)
  782. (pop *bound-vars*))))
  783. (defun compile-multiple-value-setq (form)
  784. (if (or (endp form)
  785. (not (listp form))
  786. (endp (cdr form)))
  787. (compile-error "MULTIPLE-VALUE-SETQフォームの形式が不正です: ~S" form))
  788. (compile-form (cadr form)) ; compile values-form
  789. (output-insn 'insn-multiple-value-set (length (car form)))
  790. (dolist (var (car form))
  791. (compile-varset var))
  792. (output-insn 'insn-multiple-value-set-end))
  793. (defun compile-multiple-value-call (form)
  794. (if (endp form)
  795. (compile-error "MULTIPLE-VALUE-CALLフォームの形式が不正です: ~S" form))
  796. (compile-form (car form))
  797. (compile-form 'nil)
  798. (dolist (f (cdr form))
  799. (compile-form f)
  800. (decf *stack-depth*)
  801. (output-insn 'insn-list-multiple-value))
  802. ;(decf *stack-depth*)
  803. (output-insn 'insn-call-multiple-value))
  804. (defun compile-multiple-value-prog1 (form)
  805. (if (endp form)
  806. (compile-error "MULTIPLE-VALUE-PROG1フォームの形式が不正です: ~S" form))
  807. (let ((end-tag (make-tag (gensym "MV-PROG1"))))
  808. (compile-form (car form))
  809. (output-insn 'insn-save-multiple-value end-tag)
  810. (compile-progn (cdr form))
  811. ;(decf *stack-depth*)
  812. (output-insn 'insn-discard)
  813. (output-label end-tag)))
  814. (defun compile-tagbody (form)
  815. (let ((end-tag (make-tag (gensym "TAGBODY")))
  816. tags)
  817. (dolist (f form)
  818. (if (or (integerp f) (symbolp f))
  819. (push (make-tag f) tags)))
  820. (push tags *tagbody-environment*)
  821. (output-insn 'insn-tagbody end-tag tags)
  822. (dolist (f form)
  823. (if (or (integerp f) (symbolp f))
  824. (output-label (assoc f tags :test #'eq))
  825. (progn
  826. (compile-form f)
  827. (decf *stack-depth*)
  828. (output-insn 'insn-discard))))
  829. (pop *tagbody-environment*)
  830. (compile-form 'nil)
  831. (output-label end-tag)))
  832. (defun compile-go (form)
  833. (if (or (endp form)
  834. (not (endp (cdr form))))
  835. (compile-error "TAGBODYフォームの形式が不正です: ~S" form))
  836. (multiple-value-bind (goal closurep)
  837. (find-tagbody (car form))
  838. (if closurep
  839. (output-insn 'insn-go goal)
  840. (progn
  841. (unless (= (cadr goal) *stack-depth*)
  842. (output-insn 'insn-adjust-stack (cadr goal)))
  843. (output-insn 'insn-goto goal)))))
  844. (defun compile-block (form)
  845. (if (endp form)
  846. (compile-error "BLOCKフォームの形式が不正です: ~S" form))
  847. (check-type (car form) symbol)
  848. (estab-block (car form))
  849. (compile-progn (cdr form))
  850. (unestab-block))
  851. (defun compile-return-from (form)
  852. (if (endp form)
  853. (compile-error "RETURN-FROMフォームの形式が不正です: ~S" form))
  854. (check-type (car form) symbol)
  855. (multiple-value-bind (goal closurep)
  856. (find-block (car form))
  857. (when (and (not closurep)
  858. (/= (cadadr goal) *stack-depth*))
  859. (setq *stack-depth* (cadadr goal))
  860. (output-insn 'insn-adjust-stack *stack-depth*))
  861. (cond ((endp (cdr form))
  862. (compile-form 'nil))
  863. ((endp (cddr form))
  864. (compile-form (cadr form)))
  865. (t
  866. (compile-error "RETURN-FROMフォームの形式が不正です: ~S" form)))
  867. (if closurep
  868. (output-insn 'insn-return goal)
  869. (output-insn 'insn-goto (cadr goal)))))
  870. (defun compile-if (form)
  871. (let ((l (length form)))
  872. (cond ((= l 2)
  873. (let ((donetag (make-tag)))
  874. (compile-form (car form))
  875. (output-insn 'insn-if-nil-goto donetag)
  876. (decf *stack-depth*)
  877. (compile-form (cadr form))
  878. (output-label donetag)))
  879. ((= l 3)
  880. (let ((elsetag (make-tag))
  881. (donetag (make-tag)))
  882. (compile-form (car form))
  883. (output-insn 'insn-if-nil-goto-and-pop elsetag)
  884. (decf *stack-depth*)
  885. (compile-form (cadr form))
  886. (output-insn 'insn-goto donetag)
  887. (decf *stack-depth*)
  888. (output-label elsetag)
  889. (compile-form (caddr form))
  890. (output-label donetag)))
  891. (t
  892. (compile-error "IFフォームの形式が不正です: ~S" form)))))
  893. (defun compile-quote (form)
  894. (unless (= (length form) 1)
  895. (compile-error "QUOTEフォームの形式が不正です: ~S" form))
  896. (compile-constant (car form)))
  897. (defun compile-unwind-protect (form)
  898. (if (endp form)
  899. (compile-error "UNWIND-PROTECTフォームの形式が不正です: ~S" form))
  900. (let ((ctag (make-tag (gensym "CLEANUP")))
  901. (ptag (make-tag (gensym "PROTECT"))))
  902. (output-insn 'insn-unwind-protect ctag ptag)
  903. (compile-form (car form))
  904. (output-label ctag)
  905. (compile-progn (cdr form))
  906. ;(decf *stack-depth*)
  907. (output-insn 'insn-discard) ; ???
  908. (output-label ptag)))
  909. (defun compile-catch (form)
  910. (if (endp form)
  911. (compile-error "CATCHフォームの形式が不正です: ~S" form))
  912. (compile-form (car form))
  913. (decf *stack-depth*)
  914. (let ((tag (make-tag (gensym "CATCH"))))
  915. (output-insn 'insn-catch tag)
  916. (compile-progn (cdr form))
  917. (output-label tag)))
  918. (defun compile-throw (form)
  919. (if (/= (length form) 2)
  920. (compile-error "THROWフォームの形式が不正です: ~S" form))
  921. (compile-form (cadr form))
  922. (compile-form (car form))
  923. ;;(decf *stack-depth*)
  924. (output-insn 'insn-throw))
  925. (defun compile-eval-when (form)
  926. (if (endp form)
  927. (compile-error "EVAL-WHENフォームの形式が不正です: ~S" form))
  928. ;;(incf *stack-depth*)
  929. (if (or (member ':execute (car form) :test #'eq)
  930. (member 'eval (car form) :test #'eq))
  931. (compile-progn (cdr form))
  932. (compile-form 'nil)))
  933. (defun compile-function (form)
  934. (unless (= (length form) 1)
  935. (compile-error "FUNCTIONフォームの形式が不正です: ~S" form))
  936. ;;(incf *stack-depth*)
  937. (cond ((symbolp (car form))
  938. (let ((f (assoc (car form) *macro-environment* :test #'eq)))
  939. (cond ((null f)
  940. (output-insn 'insn-function-symbol (car form)))
  941. ((symbolp (cdr f))
  942. (compile-form (cdr f)))
  943. (t
  944. (compile-error 'invalid-function
  945. :datum (car form))))))
  946. ((and (consp (car form))
  947. (eq (caar form) 'lambda))
  948. (output-insn 'insn-make-closure
  949. (compile-closure (car form))))
  950. (t
  951. (compile-error 'invalid-function :datum (car form)))))
  952. (defun flet-temp-vars (fnam form)
  953. (when (or (endp form)
  954. (endp (cdr form)))
  955. (compile-error "~Aフォームの形式が不正です: ~S" fnam form))
  956. (let ((env-vars '())
  957. (bind-forms '()))
  958. (dolist (def (car form))
  959. (when (or (endp def)
  960. (endp (cdr def)))
  961. (compile-error "~Aフォームの形式が不正です: ~S" fnam def))
  962. (let ((name (car def))
  963. (body (cdr def)))
  964. (unless (symbolp name)
  965. (compile-error "関数名が不正です: ~S" name))
  966. (when (or (endp body)
  967. (not (listp (car body))))
  968. (compile-error "不正な関数です: ~S" body))
  969. (let ((lambda-list (car body)))
  970. (multiple-value-bind (decl body)
  971. (lisp::find-declaration (cdr body))
  972. (if (eq fnam 'macrolet)
  973. (push (cons name `(macro ,lambda-list ,@decl (block ,name ,@body)))
  974. env-vars)
  975. (let ((temp (gensym)))
  976. (push (cons name temp) env-vars)
  977. (multiple-value-bind (intr body)
  978. (lisp::find-interactive body)
  979. (push `(,temp #'(lambda ,lambda-list ,@decl ,@intr (block ,name ,@body)))
  980. bind-forms))))))))
  981. (values env-vars bind-forms)))
  982. ;;; DO NOT CALL THIS FUNCTION.
  983. (defun *compile-flet-bind (vars)
  984. (setq *macro-environment* (append (car vars) *macro-environment*))
  985. (compile-form 'nil))
  986. (defun compile-flet-unbind (vars)
  987. (dolist (x vars)
  988. (setq *macro-environment* (delete x *macro-environment* :test #'eq))))
  989. (defun compile-flet (form)
  990. (multiple-value-bind (env-vars bind-forms)
  991. (flet-temp-vars 'flet form)
  992. (multiple-value-bind (decl body)
  993. (lisp::find-declaration (cdr form))
  994. (compile-form `(let ,bind-forms
  995. (*compile-flet-bind ,env-vars)
  996. ,@body)))
  997. (compile-flet-unbind env-vars)))
  998. (defun compile-labels (form)
  999. (multiple-value-bind (env-vars bind-forms)
  1000. (flet-temp-vars 'labels form)
  1001. (multiple-value-bind (decl body)
  1002. (lisp::find-declaration (cdr form))
  1003. (compile-form `(let ,(mapcar #'car bind-forms)
  1004. (*compile-flet-bind ,env-vars)
  1005. ,@(mapcar #'(lambda (x) (cons 'setq x)) bind-forms)
  1006. ,@body)))
  1007. (compile-flet-unbind env-vars)))
  1008. (defun compile-macrolet (form)
  1009. (let ((vars (flet-temp-vars 'macrolet form)))
  1010. (setq *macro-environment* (append vars *macro-environment*))
  1011. (multiple-value-bind (decl body)
  1012. (lisp::find-declaration (cdr form))
  1013. (compile-progn body))
  1014. (compile-flet-unbind vars)))
  1015. (defun compile-save-excursion (form)
  1016. (let ((end-tag (make-tag (gensym "SAVE-EXCURSION"))))
  1017. (output-insn 'insn-save-excursion end-tag)
  1018. (compile-progn form)
  1019. (output-label end-tag)))
  1020. (defun compile-save-restriction (form)
  1021. (let ((end-tag (make-tag (gensym "SAVE-RESTRICTION"))))
  1022. (output-insn 'insn-save-restriction end-tag)
  1023. (compile-progn form)
  1024. (output-label end-tag)))
  1025. (defun compile-save-window-excursion (form)
  1026. (let ((end-tag (make-tag (gensym "SAVE-WINDOW-EXCURSION"))))
  1027. (output-insn 'insn-save-window-excursion end-tag)
  1028. (compile-progn form)
  1029. (output-label end-tag)))
  1030. (defun compile-error (&rest r)
  1031. (apply #'error r))
  1032. ;;; optimize
  1033. (defun remove-nil-insns (insn)
  1034. (mapcan #'(lambda (x) (if x (list x))) insn))
  1035. ;;; closureから参照されないlet/block/tagbodyを削除する
  1036. (defun remove-local-lexicals (insn)
  1037. (let ((mod nil))
  1038. (do ((i insn (cdr i)))
  1039. ((endp i))
  1040. (when (or (and (eq (caar i) 'insn-block)
  1041. (not (caddr (cadar i))))
  1042. (and (eq (caar i) 'insn-tagbody)
  1043. (not (setf (caddar i)
  1044. (let ((tags '()))
  1045. (dolist (x (caddar i) tags)
  1046. (when (caddr x)
  1047. (push x tags)))))))
  1048. (and (eq (caar i) 'insn-lexical-bind)
  1049. (not (setf (cdadar i)
  1050. (let ((vars '()))
  1051. (dolist (x (cdadar i) vars)
  1052. (when (bound-var-refered-from-closure-p x)
  1053. (push x vars))))))))
  1054. (setf (car i) 'nil)
  1055. (setq mod t)))
  1056. (if mod
  1057. (remove-nil-insns insn)
  1058. insn)))
  1059. (defun remove-duplicate-labels (insn)
  1060. (do ((i insn (cdr i)))
  1061. ((endp i))
  1062. (when (eq (caar i) 'insn-label)
  1063. (setf (cdr i)
  1064. (do* ((j (cdr i) (cdr j))
  1065. (op (car j) (car j)))
  1066. ((or (endp j)
  1067. (not (eq (car op) 'insn-label)))
  1068. j)
  1069. (nsubst (cadar i) (cadr op) insn :test #'eq)))))
  1070. insn)
  1071. (let ()
  1072. (setf (get 'insn-goto 'jump) 't)
  1073. (setf (get 'insn-if-nil-goto 'jump) 't)
  1074. (setf (get 'insn-if-nil-goto 'if-nil-goto) 't)
  1075. (setf (get 'insn-if-non-nil-goto 'jump) 't)
  1076. (setf (get 'insn-if-nil-goto-and-pop 'jump) 't)
  1077. (setf (get 'insn-if-nil-goto-and-pop 'if-nil-goto) 't)
  1078. (setf (get 'insn-if-nil-goto-and-pop 'goto-and-pop) 't)
  1079. (setf (get 'insn-if-non-nil-goto-and-pop 'jump) 't)
  1080. (setf (get 'insn-if-non-nil-goto-and-pop 'goto-and-pop) 't))
  1081. ;;; ジャンプを最適化
  1082. (defun optimize-jump (insn)
  1083. (let ((continue 't))
  1084. (while continue
  1085. (setq continue 'nil)
  1086. (do ((i insn (cdr i)))
  1087. ((endp i))
  1088. (when (eq (caar i) 'insn-label)
  1089. (cond ((eq (caadr i) 'insn-goto)
  1090. ;; ラベルの直後が無条件ジャンプ(A)のときそのラベルを参照している
  1091. ;; ジャンプ(B)を無条件ジャンプ(A)の飛び先に変更する
  1092. (let ((label (cadadr i)))
  1093. (dolist (j insn)
  1094. (when (and (get (car j) 'jump)
  1095. (eq (cadr j) (cadar i))
  1096. (not (eq j (cadr i))))
  1097. (setf (cadr j) label)
  1098. (setq continue 't)))))
  1099. ((get (caadr i) 'jump)
  1100. ;; ラベルの直後が条件ジャンプ(A)のときそのラベルを参照している同一の
  1101. ;; 条件ジャンプ(B)を条件ジャンプ(A)の飛び先に変更する
  1102. ;; 条件ジャンプ(A)がgoto-and-popならば条件ジャンプ(B)のオペコードも
  1103. ;; 条件ジャンプ(A)と同じものに変更する
  1104. ;; 条件ジャンプ(A)がgoto-and-popでないならば条件ジャンプ(B)がgoto-and-pop
  1105. ;; でない場合のみ
  1106. (let* ((ope (caadr i))
  1107. (label (cadadr i))
  1108. (ope-if-nil-goto (get ope 'if-nil-goto))
  1109. (ope-goto-and-pop (get ope 'goto-and-pop)))
  1110. (dolist (j insn)
  1111. (when (and (get (car j) 'jump)
  1112. (eq (cadr j) (cadar i))
  1113. (not (eq j (cadr i)))
  1114. (eq (get (car j) 'if-nil-goto) ope-if-nil-goto))
  1115. (cond (ope-goto-and-pop
  1116. (setf (car j) ope)
  1117. (setf (cadr j) label)
  1118. (setq continue 't))
  1119. ((not (get (car j) 'goto-and-pop))
  1120. (setf (cadr j) label)
  1121. (setq continue 't))))))))))))
  1122. ;; 次の行へのジャンプを削除する
  1123. ;; ただし条件ジャンプの場合
  1124. ;; goto-and-popの場合はdiscardへ変更する
  1125. ;; goto-and-popでない場合はなにもしない
  1126. (let ((mod nil))
  1127. (do ((i insn (cdr i)))
  1128. ((endp i))
  1129. (when (and (get (caar i) 'jump)
  1130. (eq (caadr i) 'insn-label)
  1131. (eq (cadar i) (cadadr i)))
  1132. (cond ((eq (caar i) 'insn-goto)
  1133. (setf (car i) 'nil)
  1134. (setq mod t))
  1135. ((get (caar i) 'goto-and-pop)
  1136. (setf (car i) '(insn-discard))))))
  1137. (if mod
  1138. (remove-nil-insns insn)
  1139. insn)))
  1140. ;;; 未参照ラベルを削除
  1141. (defun remove-unreferenced-label (insn)
  1142. (let ((mod nil))
  1143. (do ((i insn (cdr i)))
  1144. ((endp i))
  1145. (when (eq (caar i) 'insn-label)
  1146. (let ((save (car i)))
  1147. (setf (car i) nil)
  1148. (if (si:*tree-find (cadr save) insn :test #'eq)
  1149. (setf (car i) save)
  1150. (setq mod t)))))
  1151. (if mod
  1152. (remove-nil-insns insn)
  1153. insn)))
  1154. (let ()
  1155. (setf (get 'insn-goto 'no-cond-jump) 't)
  1156. (setf (get 'insn-go 'no-cond-jump) 't)
  1157. (setf (get 'insn-return 'no-cond-jump) 't))
  1158. ;;; 未参照コードを削除
  1159. (defun remove-unreferenced-code (insn)
  1160. (do ((i insn (cdr i)))
  1161. ((endp i) insn)
  1162. (when (get (caar i) 'no-cond-jump)
  1163. (setf (cdr i) (member 'insn-label (cdr i) :test #'eq :key #'car)))))
  1164. (defun optimize-set-discard-ref (insn)
  1165. (let ((mod nil))
  1166. (do ((i insn (cdr i)))
  1167. ((endp i))
  1168. (when (and (eq (caadr i) 'insn-discard)
  1169. (or (and (eq (caar i) 'insn-lexical-set)
  1170. (eq (caaddr i) 'insn-lexical-ref))
  1171. (and (eq (caar i) 'insn-global-ref)
  1172. (eq (caaddr i) 'insn-global-ref)))
  1173. (eq (cadar i) (car (cdaddr i))))
  1174. (setf (cadr i) 'nil)
  1175. (setf (caddr i) 'nil)
  1176. (setq mod t)))
  1177. (if mod
  1178. (remove-nil-insns insn)
  1179. insn)))
  1180. (defun optimize-set-discard (insn)
  1181. (let ((mod nil))
  1182. (do ((i insn (cdr i)))
  1183. ((endp i))
  1184. (when (eq (caadr i) 'insn-discard)
  1185. (cond ((eq (caar i) 'insn-lexical-set)
  1186. (setf (caar i) 'insn-lexical-set-discard)
  1187. (setf (cadr i) 'nil)
  1188. (setq mod t))
  1189. ((eq (caar i) 'insn-global-set)
  1190. (setf (caar i) 'insn-global-set-discard)
  1191. (setf (cadr i) 'nil)
  1192. (setq mod t)))))
  1193. (if mod
  1194. (remove-nil-insns insn)
  1195. insn)))
  1196. (defun remove-ref-discard (insn)
  1197. (let ((mod nil))
  1198. (do ((i insn (cdr i)))
  1199. ((endp i))
  1200. (when (and (or (eq (caar i) 'insn-lexical-ref)
  1201. (eq (caar i) 'insn-global-ref)
  1202. (eq (caar i) 'insn-constant))
  1203. (eq (caadr i) 'insn-discard))
  1204. (setf (car i) 'nil)
  1205. (setf (cadr i) 'nil)
  1206. (setq mod t)))
  1207. (if mod
  1208. (remove-nil-insns insn)
  1209. insn)))
  1210. ;; 定数の畳み込み
  1211. ;; 副作用がなく1引数または2引数で多値を返さない数値演算関数のみ
  1212. (dolist (x '(zerop plusp minusp oddp evenp
  1213. = /= < > <= >= + - * /
  1214. max min conjugate
  1215. gcd lcm isqrt
  1216. exp log sqrt abs
  1217. sin cos tan asin acos atan
  1218. signum float rational complex realpart imagpart
  1219. rationalize numerator denominator
  1220. float-radix float-sign float-digits float-precision
  1221. lognot logcount logand logior logxor logeqv
  1222. cis phase sinh cosh tanh asinh acosh atanh))
  1223. (setf (get x 'fold-const-1) 't))
  1224. (dolist (x '(= /= < > <= >= + - * /
  1225. max min gcd lcm expt complex rem mod ash
  1226. logtest logbitp logand logior logxor logeqv
  1227. lognand lognor logandc1 logandc2 logorc1 logorc2
  1228. log float float-sign))
  1229. (setf (get x 'fold-const-2) 't))
  1230. (defun constant-folding (insn)
  1231. (loop
  1232. (let ((mod nil))
  1233. (do ((i insn (cdr i)))
  1234. ((endp i))
  1235. (let ((op1 (car i))
  1236. (op2 (cadr i))
  1237. (op3 (caddr i)))
  1238. (cond ((and (eq (car op1) 'insn-constant)
  1239. (numberp (cadr op1))
  1240. (eq (car op2) 'insn-call)
  1241. (symbolp (cadr op2))
  1242. (get (cadr op2) 'fold-const-1)
  1243. (= (caddr op2) 1))
  1244. (let ((val (ignore-errors
  1245. (multiple-value-list
  1246. (funcall (cadr op2) (cadr op1))))))
  1247. (when (= (length val) 1)
  1248. (setf (cadr op1) (car val))
  1249. (setf (cadr i) 'nil)
  1250. (setq mod t))))
  1251. ((and (eq (car op1) 'insn-constant)
  1252. (numberp (cadr op1))
  1253. (eq (car op2) 'insn-constant)
  1254. (numberp (cadr op2))
  1255. (eq (car op3) 'insn-call)
  1256. (symbolp (cadr op3))
  1257. (get (cadr op3) 'fold-const-2)
  1258. (= (caddr op3) 2))
  1259. (let ((val (ignore-errors
  1260. (multiple-value-list
  1261. (funcall (cadr op3) (cadr op1) (cadr op2))))))
  1262. (when (= (length val) 1)
  1263. (setf (cadr op1) (car val))
  1264. (setf (cadr i) 'nil)
  1265. (setf (caddr i) 'nil)
  1266. (setq mod t)))))))
  1267. (unless mod
  1268. (return insn)))
  1269. (setq insn (remove-nil-insns insn))))
  1270. (defun optimize-insn (insn)
  1271. (when t
  1272. (setq insn (remove-local-lexicals insn))
  1273. (setq insn (remove-duplicate-labels insn))
  1274. (setq insn (optimize-jump insn))
  1275. (setq insn (remove-unreferenced-label insn))
  1276. (setq insn (remove-unreferenced-code insn))
  1277. (setq insn (remove-unreferenced-label insn))
  1278. (setq insn (optimize-set-discard-ref insn))
  1279. (setq insn (optimize-set-discard insn))
  1280. (setq insn (remove-ref-discard insn))
  1281. (setq insn (constant-folding insn))
  1282. (setq insn (remove-ref-discard insn))
  1283. )
  1284. insn)
  1285. (setf (get 'cons 'optimize-form)
  1286. #'(lambda (form)
  1287. (if (and (= (length form) 3)
  1288. (null (caddr form)))
  1289. (list 'list (cadr form))
  1290. form)))
  1291. (setf (get 'not 'optimize-form) #'(lambda (x) `(null ,(cadr x))))
  1292. (let ((fn #'(lambda (form)
  1293. (if (<= (length form) 3)
  1294. form
  1295. (let ((ope (car form))
  1296. (c (cadr form)))
  1297. (dolist (x (cddr form) c)
  1298. (setq c (list ope c x))))))))
  1299. (dolist (x '(+ - * min max))
  1300. (setf (get x 'optimize-form) fn)))
  1301. (setf (get '/ 'optimize-form)
  1302. #'(lambda (form)
  1303. (let ((l (length form)))
  1304. (cond ((= l 2)
  1305. (list '/ 1 (cadr form)))
  1306. ((<= (length form) 3)
  1307. form)
  1308. (t
  1309. (let ((ope (car form))
  1310. (c (cadr form)))
  1311. (dolist (x (cddr form) c)
  1312. (setq c (list ope c x)))))))))
  1313. (let ()
  1314. (setf (get '1+ 'optimize-form) #'(lambda (x) `(+ ,(cadr x) 1)))
  1315. (setf (get '1- 'optimize-form) #'(lambda (x) `(- ,(cadr x) 1)))
  1316. (setf (get 'caar 'optimize-form) #'(lambda (x) `(car (car ,(cadr x)))))
  1317. (setf (get 'cadr 'optimize-form) #'(lambda (x) `(car (cdr ,(cadr x)))))
  1318. (setf (get 'cdar 'optimize-form) #'(lambda (x) `(cdr (car ,(cadr x)))))
  1319. (setf (get 'cddr 'optimize-form) #'(lambda (x) `(cdr (cdr ,(cadr x)))))
  1320. (setf (get 'caaar 'optimize-form) #'(lambda (x) `(car (car (car ,(cadr x))))))
  1321. (setf (get 'caadr 'optimize-form) #'(lambda (x) `(car (car (cdr ,(cadr x))))))
  1322. (setf (get 'cadar 'optimize-form) #'(lambda (x) `(car (cdr (car ,(cadr x))))))
  1323. (setf (get 'caddr 'optimize-form) #'(lambda (x) `(car (cdr (cdr ,(cadr x))))))
  1324. (setf (get 'cdaar 'optimize-form) #'(lambda (x) `(cdr (car (car ,(cadr x))))))
  1325. (setf (get 'cdadr 'optimize-form) #'(lambda (x) `(cdr (car (cdr ,(cadr x))))))
  1326. (setf (get 'cddar 'optimize-form) #'(lambda (x) `(cdr (cdr (car ,(cadr x))))))
  1327. (setf (get 'cdddr 'optimize-form) #'(lambda (x) `(cdr (cdr (cdr ,(cadr x))))))
  1328. (setf (get 'caaaar 'optimize-form) #'(lambda (x) `(car (car (car (car ,(cadr x)))))))
  1329. (setf (get 'caaadr 'optimize-form) #'(lambda (x) `(car (car (car (cdr ,(cadr x)))))))
  1330. (setf (get 'caadar 'optimize-form) #'(lambda (x) `(car (car (cdr (car ,(cadr x)))))))
  1331. (setf (get 'caaddr 'optimize-form) #'(lambda (x) `(car (car (cdr (cdr ,(cadr x)))))))
  1332. (setf (get 'cadaar 'optimize-form) #'(lambda (x) `(car (cdr (car (car ,(cadr x)))))))
  1333. (setf (get 'cadadr 'optimize-form) #'(lambda (x) `(car (cdr (car (cdr ,(cadr x)))))))
  1334. (setf (get 'caddar 'optimize-form) #'(lambda (x) `(car (cdr (cdr (car ,(cadr x)))))))
  1335. (setf (get 'cadddr 'optimize-form) #'(lambda (x) `(car (cdr (cdr (cdr ,(cadr x)))))))
  1336. (setf (get 'cdaaar 'optimize-form) #'(lambda (x) `(cdr (car (car (car ,(cadr x)))))))
  1337. (setf (get 'cdaadr 'optimize-form) #'(lambda (x) `(cdr (car (car (cdr ,(cadr x)))))))
  1338. (setf (get 'cdadar 'optimize-form) #'(lambda (x) `(cdr (car (cdr (car ,(cadr x)))))))
  1339. (setf (get 'cdaddr 'optimize-form) #'(lambda (x) `(cdr (car (cdr (cdr ,(cadr x)))))))
  1340. (setf (get 'cddaar 'optimize-form) #'(lambda (x) `(cdr (cdr (car (car ,(cadr x)))))))
  1341. (setf (get 'cddadr 'optimize-form) #'(lambda (x) `(cdr (cdr (car (cdr ,(cadr x)))))))
  1342. (setf (get 'cdddar 'optimize-form) #'(lambda (x) `(cdr (cdr (cdr (car ,(cadr x)))))))
  1343. (setf (get 'cddddr 'optimize-form) #'(lambda (x) `(cdr (cdr (cdr (cdr ,(cadr x)))))))
  1344. (setf (get 'rest 'optimize-form) #'(lambda (x) `(cdr ,(cadr x))))
  1345. (setf (get 'first 'optimize-form) #'(lambda (x) `(car ,(cadr x))))
  1346. (setf (get 'second 'optimize-form) #'(lambda (x) `(car (cdr ,(cadr x)))))
  1347. (setf (get 'third 'optimize-form) #'(lambda (x) `(car (cdr (cdr ,(cadr x))))))
  1348. (setf (get 'fourth 'optimize-form) #'(lambda (x) `(car (cdr (cdr (cdr ,(cadr x)))))))
  1349. (setf (get 'fifth 'optimize-form) #'(lambda (x) `(nth 4 ,(cadr x))))
  1350. (setf (get 'sixth 'optimize-form) #'(lambda (x) `(nth 5 ,(cadr x))))
  1351. (setf (get 'seventh 'optimize-form) #'(lambda (x) `(nth 6 ,(cadr x))))
  1352. (setf (get 'eighth 'optimize-form) #'(lambda (x) `(nth 7 ,(cadr x))))
  1353. (setf (get 'ninth 'optimize-form) #'(lambda (x) `(nth 8 ,(cadr x))))
  1354. (setf (get 'tenth 'optimize-form) #'(lambda (x) `(nth 9 ,(cadr x)))))
  1355. (let ((fn #'(lambda (x)
  1356. (if (endp (cdr x))
  1357. (list (car x) 1)
  1358. x))))
  1359. (dolist (x '(forward-char forward-line forward-virtual-line))
  1360. (setf (get x 'optimize-form) fn)))
  1361. (let ()
  1362. (defconstant byte-code-constant 1)
  1363. (defconstant byte-code-global-set 2)
  1364. (defconstant byte-code-global-ref 3)
  1365. (defconstant byte-code-lexical-set 4)
  1366. (defconstant byte-code-lexical-ref 5)
  1367. (defconstant byte-code-local-set 8)
  1368. (defconstant byte-code-local-ref 9)
  1369. (defconstant byte-code-make-closure 10)
  1370. (defconstant byte-code-discard 11)
  1371. (defconstant byte-code-goto 12)
  1372. (defconstant byte-code-if-nil-goto 13)
  1373. (defconstant byte-code-if-non-nil-goto 14)
  1374. (defconstant byte-code-if-nil-goto-and-pop 15)
  1375. (defconstant byte-code-if-non-nil-goto-and-pop 16)
  1376. (defconstant byte-code-go 17)
  1377. (defconstant byte-code-return 18)
  1378. (defconstant byte-code-adjust-stack 19)
  1379. (defconstant byte-code-call-0 20)
  1380. (defconstant byte-code-call-1 21)
  1381. (defconstant byte-code-call-2 22)
  1382. (defconstant byte-code-call-3 23)
  1383. (defconstant byte-code-call-4 24)
  1384. (defconstant byte-code-call-n 25)
  1385. (defconstant byte-code-global-set-discard 26)
  1386. (defconstant byte-code-lexical-set-discard 27)
  1387. (defconstant byte-code-local-set-discard 28)
  1388. (defconstant byte-code-lexical-bind 29)
  1389. (defconstant byte-code-block 30)
  1390. (defconstant byte-code-special 31)
  1391. (defconstant byte-code-tagbody 32)
  1392. (defconstant byte-code-unwind-protect 33)
  1393. (defconstant byte-code-catch 34)
  1394. (defconstant byte-code-throw 35)
  1395. (defconstant byte-code-save-excursion 36)
  1396. (defconstant byte-code-save-restriction 37)
  1397. (defconstant byte-code-save-window-excursion 38)
  1398. (defconstant byte-code-function-symbol 39)
  1399. (defconstant byte-code-multiple-value-set 42)
  1400. (defconstant byte-code-list-multiple-value 43)
  1401. (defconstant byte-code-call-multiple-value 44)
  1402. (defconstant byte-code-save-multiple-value 45)
  1403. (defconstant byte-code-const-t 80)
  1404. (defconstant byte-code-const-nil 81)
  1405. (defconstant byte-code-const-zero 40000)
  1406. (defconstant byte-code-funcall 33255)
  1407. (defconstant byte-code-set 33256)
  1408. (defconstant byte-code-symbol-value 33257)
  1409. (defconstant byte-code-boundp 33258)
  1410. (defconstant byte-code-constantp 33259)
  1411. (defconstant byte-code-specialp 33260)
  1412. (defconstant byte-code-make-constant 33261)
  1413. (defconstant byte-code-make-special 33262)
  1414. (defconstant byte-code-fset 33263)
  1415. (defconstant byte-code-values-list 33264)
  1416. (defconstant byte-code-values 33265)
  1417. (defconstant byte-code-null 33266)
  1418. (defconstant byte-code-symbolp 33267)
  1419. (defconstant byte-code-atom 33268)
  1420. (defconstant byte-code-consp 33269)
  1421. (defconstant byte-code-eq 33270)
  1422. (defconstant byte-code-eql 33271)
  1423. (defconstant byte-code-equal 33272)
  1424. (defconstant byte-code-equalp 33273)
  1425. (defconstant byte-code-car 33274)
  1426. (defconstant byte-code-cdr 33275)
  1427. (defconstant byte-code-cons 33276)
  1428. (defconstant byte-code-endp 33277)
  1429. (defconstant byte-code-nth 33278)
  1430. (defconstant byte-code-nthcdr 33279)
  1431. (defconstant byte-code-list-1 33280)
  1432. (defconstant byte-code-list-2 33281)
  1433. (defconstant byte-code-list-n 33282)
  1434. (defconstant byte-code-rplaca 33283)
  1435. (defconstant byte-code-rplacd 33284)
  1436. (defconstant byte-code-elt 33285)
  1437. (defconstant byte-code-set-elt 33286)
  1438. (defconstant byte-code-length 33287)
  1439. (defconstant byte-code-reverse 33288)
  1440. (defconstant byte-code-nreverse 33289)
  1441. (defconstant byte-code-svref 33290)
  1442. (defconstant byte-code-svset 33291)
  1443. (defconstant byte-code-char 33294)
  1444. (defconstant byte-code-set-char 33295)
  1445. (defconstant byte-code-schar 33296)
  1446. (defconstant byte-code-set-schar 33297)
  1447. (defconstant byte-code-string= 33298)
  1448. (defconstant byte-code-string-equal 33299)
  1449. (defconstant byte-code-zerop 33300)
  1450. (defconstant byte-code-plusp 33301)
  1451. (defconstant byte-code-minusp 33302)
  1452. (defconstant byte-code-oddp 33303)
  1453. (defconstant byte-code-evenp 33304)
  1454. (defconstant byte-code-= 33305)
  1455. (defconstant byte-code-/= 33306)
  1456. (defconstant byte-code-< 33307)
  1457. (defconstant byte-code-> 33308)
  1458. (defconstant byte-code-<= 33309)
  1459. (defconstant byte-code->= 33310)
  1460. (defconstant byte-code-max 33311)
  1461. (defconstant byte-code-min 33312)
  1462. (defconstant byte-code-+ 33313)
  1463. (defconstant byte-code-- 33314)
  1464. (defconstant byte-code-nagate 33315)
  1465. (defconstant byte-code-* 33316)
  1466. (defconstant byte-code-/ 33317)
  1467. (defconstant byte-code-abs 33318)
  1468. (defconstant byte-code-char= 33319)
  1469. (defconstant byte-code-char/= 33320)
  1470. (defconstant byte-code-char< 33321)
  1471. (defconstant byte-code-char> 33322)
  1472. (defconstant byte-code-char<= 33323)
  1473. (defconstant byte-code-char>= 33324)
  1474. (defconstant byte-code-char-equal 33325)
  1475. (defconstant byte-code-char-not-equal 33326)
  1476. (defconstant byte-code-char-lessp 33327)
  1477. (defconstant byte-code-char-greaterp 33328)
  1478. (defconstant byte-code-char-not-greaterp 33329)
  1479. (defconstant byte-code-char-not-lessp 33330)
  1480. (defconstant byte-code-char-code 33331)
  1481. (defconstant byte-code-code-char 33332)
  1482. (defconstant byte-code-bobp 33536)
  1483. (defconstant byte-code-eobp 33537)
  1484. (defconstant byte-code-bolp 33538)
  1485. (defconstant byte-code-eolp 33539)
  1486. (defconstant byte-code-goto-bol 33540)
  1487. (defconstant byte-code-goto-eol 33541)
  1488. (defconstant byte-code-forward-char 33542)
  1489. (defconstant byte-code-forward-line 33543)
  1490. (defconstant byte-code-goto-line 33544)
  1491. (defconstant byte-code-goto-column 33545)
  1492. (defconstant byte-code-current-column 33546)
  1493. (defconstant byte-code-following-char 33547)
  1494. (defconstant byte-code-preceding-char 33548)
  1495. (defconstant byte-code-point 33549)
  1496. (defconstant byte-code-goto-char 33550)
  1497. (defconstant byte-code-looking-for 33551)
  1498. (defconstant byte-code-looking-at 33552)
  1499. (defconstant byte-code-skip-chars-forward 33553)
  1500. (defconstant byte-code-skip-chars-backward 33554)
  1501. (defconstant byte-code-point-min 33555)
  1502. (defconstant byte-code-point-max 33556)
  1503. (defconstant byte-code-skip-syntax-spec-forward 33557)
  1504. (defconstant byte-code-skip-syntax-spec-backward 33558)
  1505. (defconstant byte-code-interactive-p 33559)
  1506. (defconstant byte-code-get-selection-type 33560)
  1507. (defconstant byte-code-selection-mark 33561)
  1508. (defconstant byte-code-stop-selection 33562)
  1509. (defconstant byte-code-pre-selection-p 33563)
  1510. (defconstant byte-code-continue-pre-selection 33564)
  1511. (defconstant byte-code-delete-region 33565)
  1512. (defconstant byte-code-buffer-substring 33566)
  1513. (defconstant byte-code-selection-point 33567)
  1514. (defconstant byte-code-virtual-bolp 33568)
  1515. (defconstant byte-code-virtual-eolp 33569)
  1516. (defconstant byte-code-goto-virtual-bol 33570)
  1517. (defconstant byte-code-goto-virtual-eol 33571)
  1518. (defconstant byte-code-forward-virtual-line 33572)
  1519. (defconstant byte-code-goto-virtual-line 33573)
  1520. (defconstant byte-code-goto-virtual-column 33574)
  1521. (defconstant byte-code-current-virtual-column 33575))
  1522. (let ()
  1523. (setf (get 'funcall 'inline) '(byte-code-funcall . *))
  1524. (setf (get 'set 'inline) '(byte-code-set . 2))
  1525. (setf (get 'symbol-value 'inline) '(byte-code-symbol-value . 1))
  1526. (setf (get 'boundp 'inline) '(byte-code-boundp . 1))
  1527. (setf (get 'constantp 'inline) '(byte-code-constantp . 1))
  1528. (setf (get 'si:*specialp 'inline) '(byte-code-specialp . 1))
  1529. (setf (get 'si:*make-constant 'inline) '(byte-code-make-constant . 1))
  1530. (setf (get 'si:*make-special 'inline) '(byte-code-make-special . 1))
  1531. (setf (get 'si:*fset 'inline) '(byte-code-fset . 2))
  1532. (setf (get 'values-list 'inline) '(byte-code-values-list . 1))
  1533. (setf (get 'values 'inline) '(byte-code-values . *))
  1534. (setf (get 'null 'inline) '(byte-code-null . 1))
  1535. (setf (get 'symbolp 'inline) '(byte-code-symbolp . 1))
  1536. (setf (get 'atom 'inline) '(byte-code-atom . 1))
  1537. (setf (get 'consp 'inline) '(byte-code-consp . 1))
  1538. (setf (get 'eq 'inline) '(byte-code-eq . 2))
  1539. (setf (get 'eql 'inline) '(byte-code-eql . 2))
  1540. (setf (get 'equal 'inline) '(byte-code-equal . 2))
  1541. (setf (get 'equalp 'inline) '(byte-code-equalp . 2))
  1542. (setf (get 'car 'inline) '(byte-code-car . 1))
  1543. (setf (get 'cdr 'inline) '(byte-code-cdr . 1))
  1544. (setf (get 'cons 'inline) '(byte-code-cons . 2))
  1545. (setf (get 'endp 'inline) '(byte-code-endp . 1))
  1546. (setf (get 'nth 'inline) '(byte-code-nth . 2))
  1547. (setf (get 'nthcdr 'inline) '(byte-code-nthcdr . 2))
  1548. (setf (get 'list 'inline) '((byte-code-list-1 . 1)
  1549. (byte-code-list-2 . 2)
  1550. (byte-code-list-n . *)))
  1551. (setf (get 'rplaca 'inline) '(byte-code-rplaca . 2))
  1552. (setf (get 'rplacd 'inline) '(byte-code-rplacd . 2))
  1553. (setf (get 'elt 'inline) '(byte-code-elt . 2))
  1554. (setf (get 'si:*set-elt 'inline) '(byte-code-set-elt . 3))
  1555. (setf (get 'length 'inline) '(byte-code-length . 1))
  1556. (setf (get 'reverse 'inline) '(byte-code-reverse . 1))
  1557. (setf (get 'nreverse 'inline) '(byte-code-nreverse . 1))
  1558. (setf (get 'svref 'inline) '(byte-code-svref . 2))
  1559. (setf (get 'si:*svset 'inline) '(byte-code-svset . 3))
  1560. (setf (get 'char 'inline) '(byte-code-char . 2))
  1561. (setf (get 'si:*set-char 'inline) '(byte-code-set-char . 3))
  1562. (setf (get 'schar 'inline) '(byte-code-schar . 2))
  1563. (setf (get 'si:*set-schar 'inline) '(byte-code-set-schar . 3))
  1564. (setf (get 'string= 'inline) '(byte-code-string= . 2))
  1565. (setf (get 'string-equal 'inline) '(byte-code-string-equal . 2))
  1566. (setf (get 'zerop 'inline) '(byte-code-zerop . 1))
  1567. (setf (get 'plusp 'inline) '(byte-code-plusp . 1))
  1568. (setf (get 'minusp 'inline) '(byte-code-minusp . 1))
  1569. (setf (get 'oddp 'inline) '(byte-code-oddp . 1))
  1570. (setf (get 'evenp 'inline) '(byte-code-evenp . 1))
  1571. (setf (get '= 'inline) '(byte-code-= . 2))
  1572. (setf (get '/= 'inline) '(byte-code-/= . 2))
  1573. (setf (get '< 'inline) '(byte-code-< . 2))
  1574. (setf (get '> 'inline) '(byte-code-> . 2))
  1575. (setf (get '<= 'inline) '(byte-code-<= . 2))
  1576. (setf (get '>= 'inline) '(byte-code->= . 2))
  1577. (setf (get 'max 'inline) '(byte-code-max . 2))
  1578. (setf (get 'min 'inline) '(byte-code-min . 2))
  1579. (setf (get '+ 'inline) '(byte-code-+ . 2))
  1580. (setf (get '- 'inline) '((byte-code-- . 2) (byte-code-nagate . 1)))
  1581. (setf (get '* 'inline) '(byte-code-* . 2))
  1582. (setf (get '/ 'inline) '(byte-code-/ . 2))
  1583. (setf (get 'abs 'inline) '(byte-code-abs . 1))
  1584. (setf (get 'char= 'inline) '(byte-code-char= . 2))
  1585. (setf (get 'char/= 'inline) '(byte-code-char/= . 2))
  1586. (setf (get 'char< 'inline) '(byte-code-char< . 2))
  1587. (setf (get 'char> 'inline) '(byte-code-char> . 2))
  1588. (setf (get 'char<= 'inline) '(byte-code-char<= . 2))
  1589. (setf (get 'char>= 'inline) '(byte-code-char>= . 2))
  1590. (setf (get 'char-equal 'inline) '(byte-code-char-equal . 2))
  1591. (setf (get 'char-not-equal 'inline) '(byte-code-char-not-equal . 2))
  1592. (setf (get 'char-lessp 'inline) '(byte-code-char-lessp . 2))
  1593. (setf (get 'char-greaterp 'inline) '(byte-code-char-greaterp . 2))
  1594. (setf (get 'char-not-greaterp 'inline) '(byte-code-char-not-greaterp . 2))
  1595. (setf (get 'char-not-lessp 'inline) '(byte-code-char-not-lessp . 2))
  1596. (setf (get 'char-code 'inline) '(byte-code-char-code . 1))
  1597. (setf (get 'code-char 'inline) '(byte-code-code-char . 1))
  1598. (setf (get 'bobp 'inline) '(byte-code-bobp . 0))
  1599. (setf (get 'eobp 'inline) '(byte-code-eobp . 0))
  1600. (setf (get 'bolp 'inline) '(byte-code-bolp . 0))
  1601. (setf (get 'eolp 'inline) '(byte-code-eolp . 0))
  1602. (setf (get 'goto-bol 'inline) '(byte-code-goto-bol . 0))
  1603. (setf (get 'goto-eol 'inline) '(byte-code-goto-eol . 0))
  1604. (setf (get 'forward-char 'inline) '(byte-code-forward-char . 1))
  1605. (setf (get 'forward-line 'inline) '(byte-code-forward-line . 1))
  1606. (setf (get 'goto-line 'inline) '(byte-code-goto-line . 1))
  1607. (setf (get 'goto-column 'inline) '(byte-code-goto-column . 2))
  1608. (setf (get 'current-column 'inline) '(byte-code-current-column . 0))
  1609. (setf (get 'virtual-bolp 'inline) '(byte-code-virtual-bolp . 0))
  1610. (setf (get 'virtual-eolp 'inline) '(byte-code-virtual-eolp . 0))
  1611. (setf (get 'goto-virtual-bol 'inline) '(byte-code-goto-virtual-bol . 0))
  1612. (setf (get 'goto-virtual-eol 'inline) '(byte-code-goto-virtual-eol . 0))
  1613. (setf (get 'forward-virtual-line 'inline) '(byte-code-forward-virtual-line . 1))
  1614. (setf (get 'goto-virtual-line 'inline) '(byte-code-goto-virtual-line . 1))
  1615. (setf (get 'goto-virtual-column 'inline) '(byte-code-goto-virtual-column . 2))
  1616. (setf (get 'current-virtual-column 'inline) '(byte-code-current-virtual-column . 0))
  1617. (setf (get 'following-char 'inline) '(byte-code-following-char . 0))
  1618. (setf (get 'preceding-char 'inline) '(byte-code-preceding-char . 0))
  1619. (setf (get 'point 'inline) '(byte-code-point . 0))
  1620. (setf (get 'goto-char 'inline) '(byte-code-goto-char . 1))
  1621. (setf (get 'looking-for 'inline) '(byte-code-looking-for . 2))
  1622. (setf (get 'looking-at 'inline) '(byte-code-looking-at . 2))
  1623. (setf (get 'skip-chars-forward 'inline) '(byte-code-skip-chars-forward . 1))
  1624. (setf (get 'skip-chars-backward 'inline) '(byte-code-skip-chars-backward . 1))
  1625. (setf (get 'point-min 'inline) '(byte-code-point-min . 0))
  1626. (setf (get 'point-max 'inline) '(byte-code-point-max . 0))
  1627. (setf (get 'skip-syntax-spec-forward 'inline) '(byte-code-skip-syntax-spec-forward . 1))
  1628. (setf (get 'skip-syntax-spec-backward 'inline) '(byte-code-skip-syntax-spec-backward . 1))
  1629. (setf (get 'interactive-p 'inline) '(byte-code-interactive-p . 0))
  1630. (setf (get 'get-selection-type 'inline) '(byte-code-get-selection-type . 0))
  1631. (setf (get 'selection-mark 'inline) '(byte-code-selection-mark . 0))
  1632. (setf (get 'stop-selection 'inline) '(byte-code-stop-selection . 0))
  1633. (setf (get 'pre-selection-p 'inline) '(byte-code-pre-selection-p . 0))
  1634. (setf (get 'continue-pre-selection 'inline) '(byte-code-continue-pre-selection . 0))
  1635. (setf (get 'delete-region 'inline) '(byte-code-delete-region . 2))
  1636. (setf (get 'buffer-substring 'inline) '(byte-code-buffer-substring . 2))
  1637. (setf (get 'selection-point 'inline) '(byte-code-selection-point . 0)))
  1638. (let ()
  1639. (setf (get 'insn-lexical-ref 'one-insn)
  1640. #'(lambda (insn)
  1641. (bound-var-symbol (cadr insn))))
  1642. (setf (get 'insn-global-ref 'one-insn)
  1643. #'(lambda (insn) (cadr insn)))
  1644. (setf (get 'insn-constant 'one-insn)
  1645. #'(lambda (insn) (list 'quote (cadr insn))))
  1646. (setf (get 'insn-function-symbol 'one-insn)
  1647. #'(lambda (insn) (list 'function (cadr insn))))
  1648. (setf (get 'insn-make-closure 'one-insn)
  1649. #'(lambda (insn) (list 'function (cadr insn)))))
  1650. (defvar *constant-list* nil)
  1651. (defvar *bytecode-stream* nil)
  1652. (defvar *bytecode-tags* nil)
  1653. (defun output-bytecode (insn nargs)
  1654. (cond ((endp insn)
  1655. (return-from output-bytecode 'nil))
  1656. ((endp (cdr insn))
  1657. (let ((f (get (caar insn) 'one-insn)))
  1658. (when f
  1659. (return-from output-bytecode (funcall f (car insn)))))))
  1660. (let ((*constant-list* '())
  1661. (*bytecode-tags* '())
  1662. (*bytecode-stream* (make-vector 128 :element-type 'character
  1663. :fill-pointer 0 :adjustable t)))
  1664. (vector-push-extend (code-char *stack-frame-max*) *bytecode-stream*)
  1665. (vector-push-extend (code-char *stack-depth-max*) *bytecode-stream*)
  1666. (vector-push-extend (code-char nargs) *bytecode-stream*)
  1667. (dolist (i insn)
  1668. (funcall (car i) i))
  1669. (if *constant-list*
  1670. (list 'si:*byte-code *bytecode-stream*
  1671. (apply 'vector (nreverse *constant-list*)))
  1672. (list 'si:*byte-code *bytecode-stream*))))
  1673. (defun output-code (n)
  1674. (vector-push-extend (code-char n) *bytecode-stream*))
  1675. (defun find-constant (object)
  1676. (let ((i (position object *constant-list* :test #'equal)))
  1677. (if i
  1678. (- (length *constant-list*) i 1)
  1679. (prog1
  1680. (length *constant-list*)
  1681. (push object *constant-list*)))))
  1682. (defun push-tag (tag)
  1683. (let ((tem (assoc tag *bytecode-tags* :test #'eq))
  1684. (pc (fill-pointer *bytecode-stream*)))
  1685. (cond (tem
  1686. (setf (cadr tem) pc)
  1687. (dolist (i (cddr tem))
  1688. (setf (char *bytecode-stream* i) (code-char pc)))
  1689. (setf (cddr tem) 'nil))
  1690. (t
  1691. (push (list tag pc) *bytecode-tags*)))))
  1692. (defun output-tag (tag)
  1693. (let ((tem (assoc tag *bytecode-tags* :test #'eq)))
  1694. (cond ((cadr tem)
  1695. (output-code (cadr tem)))
  1696. (tem
  1697. (push (fill-pointer *bytecode-stream*) (cddr tem))
  1698. (output-code 0))
  1699. (t
  1700. (push (list tag 'nil (fill-pointer *bytecode-stream*))
  1701. *bytecode-tags*)
  1702. (output-code 0)))))
  1703. (defun insn-lexical-ref (insn)
  1704. (cond ((bound-var-refered-from-closure-p (cadr insn))
  1705. (output-code byte-code-lexical-ref)
  1706. (output-code (find-constant (bound-var-symbol (cadr insn)))))
  1707. (t
  1708. (output-code byte-code-local-ref)
  1709. (output-code (bound-var-stack-frame-index (cadr insn))))))
  1710. (defun insn-global-ref (insn)
  1711. (output-code byte-code-global-ref)
  1712. (output-code (find-constant (cadr insn))))
  1713. (defun insn-lexical-set (insn)
  1714. (cond ((bound-var-refered-from-closure-p (cadr insn))
  1715. (output-code byte-code-lexical-set)
  1716. (output-code (find-constant (bound-var-symbol (cadr insn)))))
  1717. (t
  1718. (output-code byte-code-local-set)
  1719. (output-code (bound-var-stack-frame-index (cadr insn))))))
  1720. (defun insn-lexical-set-discard (insn)
  1721. (cond ((bound-var-refered-from-closure-p (cadr insn))
  1722. (output-code byte-code-lexical-set-discard)
  1723. (output-code (find-constant (bound-var-symbol (cadr insn)))))
  1724. (t
  1725. (output-code byte-code-local-set-discard)
  1726. (output-code (bound-var-stack-frame-index (cadr insn))))))
  1727. (defun insn-global-set (insn)
  1728. (output-code byte-code-global-set)
  1729. (output-code (find-constant (cadr insn))))
  1730. (defun insn-global-set-discard (insn)
  1731. (output-code byte-code-global-set-discard)
  1732. (output-code (find-constant (cadr insn))))
  1733. (defun insn-constant (insn)
  1734. (let ((object (cadr insn)))
  1735. (cond ((eq object 't)
  1736. (output-code byte-code-const-t))
  1737. ((eq object 'nil)
  1738. (output-code byte-code-const-nil))
  1739. ((and (integerp object)
  1740. (<= -1024 object 1024))
  1741. (output-code (+ byte-code-const-zero object)))
  1742. (t
  1743. (output-code byte-code-constant)
  1744. (output-code (find-constant object))))))
  1745. (defun insn-call (insn)
  1746. (when (symbolp (cadr insn))
  1747. (let ((opt (get (cadr insn) 'inline)))
  1748. (when opt
  1749. (if (symbolp (car opt))
  1750. (cond ((eq (cdr opt) '*)
  1751. (output-code (symbol-value (car opt)))
  1752. (output-code (caddr insn))
  1753. (return-from insn-call))
  1754. ((= (caddr insn) (cdr opt))
  1755. (output-code (symbol-value (car opt)))
  1756. (return-from insn-call)))
  1757. (dolist (x opt)
  1758. (cond ((eq (cdr x) '*)
  1759. (output-code (symbol-value (car x)))
  1760. (output-code (caddr insn))
  1761. (return-from insn-call))
  1762. ((= (caddr insn) (cdr x))
  1763. (output-code (symbol-value (car x)))
  1764. (return-from insn-call))))))))
  1765. (case (caddr insn)
  1766. (0 (output-code byte-code-call-0))
  1767. (1 (output-code byte-code-call-1))
  1768. (2 (output-code byte-code-call-2))
  1769. (3 (output-code byte-code-call-3))
  1770. (4 (output-code byte-code-call-4))
  1771. (t (output-code byte-code-call-n)
  1772. (output-code (caddr insn))))
  1773. (output-code (find-constant (cadr insn))))
  1774. (defun insn-discard (insn)
  1775. (output-code byte-code-discard))
  1776. (defun insn-goto (insn)
  1777. (output-code byte-code-goto)
  1778. (output-tag (cadr insn)))
  1779. (defun insn-if-nil-goto (insn)
  1780. (output-code byte-code-if-nil-goto)
  1781. (output-tag (cadr insn)))
  1782. (defun insn-if-nil-goto-and-pop (insn)
  1783. (output-code byte-code-if-nil-goto-and-pop)
  1784. (output-tag (cadr insn)))
  1785. (defun insn-if-non-nil-goto (insn)
  1786. (output-code byte-code-if-non-nil-goto)
  1787. (output-tag (cadr insn)))
  1788. (defun insn-if-non-nil-goto-and-pop (insn)
  1789. (output-code byte-code-if-non-nil-goto-and-pop)
  1790. (output-tag (cadr insn)))
  1791. (defun insn-label (insn)
  1792. (push-tag (cadr insn)))
  1793. (defun insn-return (insn)
  1794. (output-code byte-code-return)
  1795. (output-code (find-constant (caadr insn))))
  1796. (defun insn-go (insn)
  1797. (output-code byte-code-go)
  1798. (output-code (find-constant (caadr insn))))
  1799. (defun insn-adjust-stack (insn)
  1800. (output-code byte-code-adjust-stack)
  1801. (output-code (cadr insn)))
  1802. (defun insn-block (insn)
  1803. (output-code byte-code-block)
  1804. (output-tag (cadadr insn))
  1805. (output-code (find-constant (caadr insn))))
  1806. (defun insn-tagbody (insn)
  1807. (output-code byte-code-tagbody)
  1808. (output-tag (cadr insn))
  1809. (output-code (length (caddr insn)))
  1810. (dolist (i (caddr insn))
  1811. (output-tag i)
  1812. (output-code (find-constant (car i)))))
  1813. (defun insn-unwind-protect (insn)
  1814. (output-code byte-code-unwind-protect)
  1815. (output-tag (cadr insn))
  1816. (output-tag (caddr insn)))
  1817. (defun insn-catch (insn)
  1818. (output-code byte-code-catch)
  1819. (output-tag (cadr insn)))
  1820. (defun insn-throw (insn)
  1821. (output-code byte-code-throw))
  1822. (defun insn-special (insn)
  1823. (output-code byte-code-special)
  1824. (output-tag (caadr insn))
  1825. (output-code (length (cdadr insn)))
  1826. (dolist (i (cdadr insn))
  1827. (output-code (find-constant (bound-var-symbol i)))))
  1828. (defun insn-special-end (insn)
  1829. ;; no opecode
  1830. )
  1831. (defun insn-multiple-value-set (insn)
  1832. (output-code byte-code-multiple-value-set)
  1833. (output-code (cadr insn)))
  1834. (defun insn-multiple-value-set-end (insn)
  1835. ;; no opecode
  1836. )
  1837. (defun insn-list-multiple-value (insn)
  1838. (output-code byte-code-list-multiple-value))
  1839. (defun insn-call-multiple-value (insn)
  1840. (output-code byte-code-call-multiple-value))
  1841. (defun insn-save-multiple-value (insn)
  1842. (output-code byte-code-save-multiple-value)
  1843. (output-tag (cadr insn)))
  1844. (defun insn-make-closure (insn)
  1845. (output-code byte-code-make-closure)
  1846. (output-code (find-constant (cadr insn))))
  1847. (defun insn-lexical-bind (insn)
  1848. (output-code byte-code-lexical-bind)
  1849. (output-tag (caadr insn))
  1850. (output-code (length (cdadr insn)))
  1851. (dolist (i (cdadr insn))
  1852. (output-code (find-constant (bound-var-symbol i)))))
  1853. (defun insn-save-excursion (insn)
  1854. (output-code byte-code-save-excursion)
  1855. (output-tag (cadr insn)))
  1856. (defun insn-save-restriction (insn)
  1857. (output-code byte-code-save-restriction)
  1858. (output-tag (cadr insn)))
  1859. (defun insn-save-window-excursion (insn)
  1860. (output-code byte-code-save-window-excursion)
  1861. (output-tag (cadr insn)))
  1862. (defun insn-function-symbol (insn)
  1863. (output-code byte-code-function-symbol)
  1864. (output-code (find-constant (cadr insn))))