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

/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

Large files files are truncated, but you can click here to view the full file

  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-

Large files files are truncated, but you can click here to view the full file