Login
7 branches 0 tags
Ben (X13/Arch) Fixed popen on GNU/Linux 4aa45bb 4 years ago 200 Commits
nujel / stdlib / z_compiler.nuj
;; Contains the self-hosting Nujel compiler

[def compile]
[let* [def environment [current-closure]]
      [def verbose #f]

      [defun compile/do/args [args]
             [if [last? args]
                 [cons [compile* [car args]] #nil]
                 [if [pair? [car args]]
                     [let* [def ocar [compile* [car args]]]
                           [if [pair? ocar]
                               [cons ocar [compile/do/args [cdr args]]]
                               [compile/do/args [cdr args]]]
                     ]
                     [compile/do/args [cdr args]]]]
      ]

      [defun compile/do [source]
             [let* [def args [compile/do/args source]]
                   [if [last? args]
                       [car args]
                       [cons 'do args]]
             ]
      ]

      [defun compile/def [source]
             [list 'def [cadr source] [compile* [caddr source]]]
      ]

      [defun compile/set! [source]
             [list 'set! [cadr source] [compile* [caddr source]]]
      ]

      [defun compile/λ [source]
             [if [string?  [caddr source]]
                 [list 'λ* [cadr source] [caddr source] [compile/do [cddr source]]]
                 [list 'λ* [cadr source]             "" [compile/do [cddr source]]]]
      ]

      [defun compile/λ* [source]
             source
      ]

      [defun compile/μ [source]
             [if [string?  [caddr source]]
                 [list 'μ* [cadr source] [caddr source] [compile/do [cddr source]]]
                 [list 'μ* [cadr source]             "" [compile/do [cddr source]]]]
      ]

      [defun compile/μ* [source]
             source
      ]

      [defun compile/ω [source]
             [list 'ω [compile/do [cdr source]]]
      ]

      [defun compile/try [source]
             [list 'try [compile* [cadr source]] [compile/do [cddr source]]]
      ]

      [defun compile/if [source]
             [list 'if [compile* [cadr source]] [compile* [caddr source]] [compile* [cadddr source]]]
      ]

      [defun compile/let* [source]
             [list 'let* [compile/do [cdr source]]]
      ]

      [defun compile/cond/clause [source]
             [cons [compile* [car source]]
                   [cons [compile/do [cdr source]]]]
      ]

      [defun compile/cond/clauses [source]
             [when source
                   [cons [compile/cond/clause [car source]]
                         [compile/cond/clauses [cdr source]]]
             ]
      ]

      [defun compile/cond [source]
             [cons 'cond [compile/cond/clauses [cdr source]]]
      ]

      [defun compile/and [source]
             [compile/procedure/arg source]
      ]

      [defun compile/or [source]
             [compile/procedure/arg source]
      ]

      [defun compile/while [source]
             [list 'while [compile* [cadr source]] [compile/do [cddr source]]]
      ]

      [defun compile/macro [macro source]
             [compile* [macro-apply macro [cdr source]]]
      ]

      [defun compile/procedure/arg [source]
             [when [pair? source]
                   [cons [compile* [car source]]
                         [compile/procedure/arg [cdr source]]]
             ]
      ]

      [defun compile/procedure [proc source]
             [compile/procedure/arg source]
      ]

      [defun compile* [source]
             "Compile the forms in source"
             [let* [def op [if [apply environment `[[resolves? ~[list 'quote [car source]]]]]
                               [apply environment `[[resolve ~[list 'quote [car source]]]]]
                               [car source]]]

                   [cond [[special-form? op]
                          [cond [[eq? op do]     [compile/do     source]]
                                [[eq? op def]    [compile/def    source]]
                                [[eq? op set!]   [compile/set!   source]]
                                [[eq? op let]    [compile/let    source]]
                                [[eq? op let*]   [compile/let*   source]]
                                [[eq? op λ]      [compile/λ      source]]
                                [[eq? op λ*]     [compile/λ*     source]]
                                [[eq? op μ]      [compile/μ      source]]
                                [[eq? op μ*]     [compile/μ*     source]]
                                [[eq? op ω]      [compile/ω      source]]
                                [[eq? op if]     [compile/if     source]]
                                [[eq? op try]    [compile/try    source]]
                                [[eq? op cond]   [compile/cond   source]]
                                [[eq? op and]    [compile/and    source]]
                                [[eq? op or]     [compile/or     source]]
                                [[eq? op while]  [compile/while  source]]
                                [[eq? op quote]                  source ]
                                [#t [throw [list :unknown-special-form "The compiler does not know the current special form, please fix the compiler!" [car source]]]]
                          ]]
                         [[macro? op]     [compile/macro      op source]]
                         [[procedure? op] [compile/procedure  op source]]
                         [[pair? op]      [compile/procedure/arg source]]
                         [[numeric? op]   [compile/procedure/arg source]]
                         [[arr? op]       [compile/procedure/arg source]]
                         [[string? op]    [compile/procedure/arg source]]
                         [[tree? op]      [compile/procedure/arg source]]
                         [#t              source]]
             ]
      ]

      [set! compile [lambda [source new-environment new-verbose]
            [when-not new-environment [set! new-environment [current-closure]]]
            [when-not new-verbose [set! new-verbose #f]]
            [set! environment new-environment]
            [set! verbose new-verbose]
            [compile* source]
      ]]
]

[defun compile/forms [source-raw]
        "Compile multiple forms, evaluation the results in a temporary environment, so we can make use of macros we just defined"
        [def source #nil]
        [def source-next source-raw]
        [def environment [object]]
        [def passes 0]
        [def max-passes 100]
        [defun try-again [source]
               [set! source-next [cons source source-next]]
        ]
        [while source-next
               [set! source source-next]
               [set! source-next #nil]
               [while source
                      [try [lambda [err] [cond [[eq? [car err] :unresolved-procedure] [try-again [car source]]]
                                               [[eq? [car err] :runtime-macro] [try-again [car source]]]
                                               [#t [throw err]]]]
                           [def compiled-form [compile [car source] environment #t]]
                           [apply environment `[[eval* ~compiled-form]]]
                      ]
                      [set! source [cdr source]]
               ]
               [set! source-next [reverse source-next]]
               [if [> [set! passes [+ 1 passes]] max-passes] [throw [list :too-many-passes "The compiler couldn't produce a valid result in a 100 passes, probably something wrong with the code."]]]
        ]
        [compile source-raw environment]
]

[def defmacro [μ [name args ...body]
              [list 'def name [compile [cons 'μ [cons args ...body]] [current-closure]]]
]]

[defmacro defun [name args ...body]
	      [list 'def name [compile [cons 'λ [cons args ...body]] [current-closure]]]
]

[defmacro \ [...body]
        "Define a λ with the self-hosting Nujel compiler"
        [compile [cons 'λ ...body] [current-closure]]
]

[defmacro eval [expr]
          "Compile, Evaluate and then return the result of EXPR"
          `[eval* [compile ~expr [current-closure]]]
]

[defmacro +1 [v]
           `[+ 1 ~v]
]

[defun optimize/code/rest [code]
       [if [pair? code]
           [cons [optimize/code      [car code]]
                 [optimize/code/rest [cdr code]]]
           code]
]
[defun optimize/code [code]
       [if [pair? code]
           [if [and [symbol? [car code]] [resolves? [car code]]]
               [cons [resolve [car code]]
                     [optimize/code/rest [cdr code]]]
               [cons [optimize/code [car code]]
                     [optimize/code/rest [cdr code]]]]
           code]
]
[defun optimize! [fun]
       "Optimize FUN via mutation"
       [if [lambda? fun]
           [closure! fun @[:code [optimize/code [[closure fun] :code]]]]
           #f]
]

[defun optimize-all! []
       "Return a list of all lambdas in CTX"
       [for-each optimize! [filter lambda? [map resolve [symbol-table]]]]
]

[defun bench-while []
       [def i 0]
       [while [< i 10,000,000]
              [set! i [+ 1 i]]
       ]
       [println i]
       i
]
[optimize-all!]