git.fiddlerwoaroof.com
Raw Blame History
;;; This is the top-level phase structure of the compiler.

;;; Compilation phase support

(define *phase* '#f)
(define *abort-phase* '#f)         ; abort when this phase completes
(define *abort-compilation*
  (lambda ()
    (error "No error continuation defined here!")))

(define *module-asts* '())   ; a global only for debugging purposes

;;; Later add the printing and timing stuff here

(define-local-syntax (phase-body phase-name body printer)
  `(dynamic-let ((*phase*       ',phase-name))
     (when (memq ',phase-name (dynamic *printers*))
       (format '#t "~%Phase ~a:~%" ',phase-name)
       (force-output))
     (let* ((phase-start-time (get-run-time))
	    (result ,body)
	    (current-time  (get-run-time)))
       (when (eq? (dynamic *abort-phase*) ',phase-name)
	 (abort-compilation))
       ,@(if (eq? printer '#f)
	     '()
	     `((when (memq ',phase-name (dynamic *printers*))
		 (funcall ,printer result)
		 (force-output))))
       (when (memq 'phase-time *printers*)
	 (let ((elapsed-time (- current-time phase-start-time)))
	   (format '#t "~&~A complete: ~A seconds~%"
		   ',phase-name elapsed-time)
	   (force-output)))
       result)))



;;; Returns 2 values: module ast's and lisp code.

(define (compile-haskell-files files)
  (dynamic-let ((*abort-phase*                '#f))
     (let ((all-mods       (haskell-parse-files files))
	   (interface-mods '())
	   (regular-mods   '()))
       (dolist (m all-mods)
	 (if (eq? (module-type m) 'interface)
	     (push m interface-mods)
	     (push m regular-mods)))
       (dynamic-let ((*unit*  (module-name (car all-mods))))
	 (values
	   all-mods
	   `(begin
	      ,(if interface-mods
		   (compile-interface-modules (nreverse interface-mods))
		   '#f)
	      ,(if regular-mods
		   (compile-modules (nreverse regular-mods))
		   '#f))
	   )))))



(define (compile-modules mods)
  (dynamic-let ((*context*                    '#f)
		(*recoverable-error-handler*  '#f)
		(*abort-phase*                '#f)
		(*unique-name-counter*        1)
		(*suffix-table*               (make-table)))
  	  (haskell-import-export mods '#f)
	  (haskell-process-type-declarations mods)
	  (haskell-scope mods)
	  (let ((big-let (haskell-dependency-analysis mods)))
	    (cond ((not (void? big-let))
		   (haskell-type-check big-let mods)
		   (setf big-let (haskell-cfn big-let))
		   (setf big-let (haskell-dependency-reanalysis big-let))
		   (setf big-let (haskell-ast-to-flic big-let))
		   (setf big-let (haskell-optimize big-let))
		   (setf big-let (haskell-strictness big-let))
		   (haskell-codegen big-let mods))
		  (else
		   ''#f)
		  ))))


(define (modules->lisp-code modules)
  (dynamic-let ((*unit* (module-name (car modules))))
    (compile-modules modules)))


(predefine (notify-error))  ; in command-interface/command-utils.scm

(define (abort-compilation)
  (notify-error)
  (funcall (dynamic *abort-compilation*)))

(define (halt-compilation)
  (setf (dynamic *abort-phase*) (dynamic *phase*)))


;;; Here are the actual phase bodies

(predefine (parse-files files))

(define (haskell-parse-files filenames)
  (phase-body parse
    (let ((mods (parse-files filenames)))
      mods)
    #f))

(predefine (import-export modules))  ; in import-export/import-export.scm
(predefine (import-export/interface modules))

(define (haskell-import-export modules interface?)
  (phase-body import
    (if interface?
	(import-export/interface modules)
	(import-export modules))
    #f))


(predefine (process-type-declarations modules)) 
    ; in tdecl/type-declaration-analysis.scm

(define (haskell-process-type-declarations modules)
  (phase-body type-decl
    (begin
      (process-type-declarations modules))
    #f))


(predefine (scope-modules x))  ; in prec/scope.scm
(predefine (print-full-module x . maybe-stream)) ; in the printers

(define (haskell-scope modules)
  (phase-body scope
    (scope-modules modules)
    (lambda (result)
      (declare (ignore result))
      (dolist (m modules) (print-full-module m)))
    ))


(predefine (do-dependency-analysis x))  ; in depend/dependency-analysis.scm

(define (haskell-dependency-analysis modules)
  (phase-body depend
    (do-dependency-analysis modules)
    (function pprint*)))


(predefine (do-haskell-type-check big-let mods))

(define (haskell-type-check big-let modules)
  (phase-body type
    (do-haskell-type-check big-let modules)
    #f))

(predefine (cfn-ast x))  ; in cfn/main.scm

(define (haskell-cfn big-let)
  (phase-body cfn
    (cfn-ast big-let)
    (function pprint*)))


(predefine (analyze-dependency-top x))  ; in depend/dependency-analysis.scm

(define (haskell-dependency-reanalysis big-let)
  (phase-body depend2
    (begin
      (analyze-dependency-top big-let)
      big-let)
    (function pprint*)))


(predefine (ast-to-flic x))		; in flic/ast-to-flic.scm

(define (haskell-ast-to-flic big-let)
  (phase-body flic
    (ast-to-flic big-let)
    (function pprint*)))


(predefine (optimize-top x))  ; in backend/optimize.scm

(define (haskell-optimize big-let)
  (phase-body optimize
    (optimize-top big-let)
    (function pprint*)))

(predefine (strictness-analysis-top x)) ; in backend/strictness.scm
(predefine (strictness-analysis-printer x))

(define (haskell-strictness big-let)
  (phase-body strictness
    (strictness-analysis-top big-let)
    (function strictness-analysis-printer)))


(predefine (codegen-top x))  ; in backend/codegen.scm
(predefine (codegen-exported-types x)) ; "
(predefine (codegen-prim-entries x))  ; ditto

(define (haskell-codegen big-let mods)
  (phase-body codegen
    `(begin
       ,(codegen-exported-types mods)
       ,(codegen-top big-let))
    #f))

	       
;;; This is for interface modules.

(predefine (haskell-codegen/interface mods))

(define (compile-interface-modules mods)
 (dynamic-let ((*context*                    '#f)
	       (*recoverable-error-handler*  '#f)
	       (*abort-phase*                '#f))
     (haskell-import-export mods '#t)
     (haskell-process-type-declarations mods)
     (haskell-scope mods)
     (haskell-codegen/interface mods)))