Login
7 branches 0 tags
Ben (X220/Parabola) WIP 9ee567a 3 years ago 673 Commits
nujel / stdlib / compiler / core.nuj
[defn load/forms [source environment]
      "Load multiple forms, evaluating the results in environment, so we can make use of macros we just defined"
      [for-in [form source]
              [-> [macroexpand form environment]
                  bytecompile
                  assemble*
                  [bytecode-eval environment]]]]

[defn macroexpand/forms [source-raw environment]
      "Expand multiple forms, evaluating the source in a temporary environment, so we can make use of macros we just defined."
      [when-not environment [set! environment [ω]]]
      [load/forms source-raw environment]
      [macroexpand source-raw environment]]

[defn compile/debug [expr]
      [-> [macroexpand expr]
          bytecompile
          assemble*
          disassemble]]

[defn compile* [source environment]
      "Compile SOURCE so it can be evaluated/applied"
      [-> [macroexpand source environment]
          bytecompile
          assemble*]]

[defn compile/do* [source environment]
      [compile* [cons do source] environment]]

[defmacro compile [source]
          "Compile SOURCE so it can be evaluated/applied"
          `[compile* ~source [current-closure]]]

[defmacro compile/do [source]
          "Compile SOURCE so it can be evaluated/applied"
          `[compile* [cons do ~source] [current-closure]]]

[defn meta/parse/body [type args body]
      [def meta @[]]
      [for-in [v body]
              [case [type-of v]
                    [:pair [return meta]]
                    [:string [tree/set! meta :documentation [trim [cat [string [tree/ref meta :documentation]]
                                                                       "\n"
                                                                       v]]]]
                    [:keyword [tree/set! meta v #t]]]]
      [return meta]]

[defmacro defmacro [name args . body]
          "Define a new macro"
          `[def ~name [macro* '~name
                               '~args
                               ~[tree/set! [meta/parse/body :macro args body] :source body]
                               '~[compile/do* body [current-closure]]]]]

[defmacro fn [args . body]
          "Define an anonymous function"
          `[fn* 'anonymous
                 '~args
                 ~[tree/set! [meta/parse/body :lambda args body] :source body]
                 '~[compile/do* body [current-closure]]]]

[defmacro defn [name args . body]
          "Define a new function"
          `[def ~name [fn* '~name
                            '~args
                            ~[tree/set! [meta/parse/body :lambda args body] :source body]
                            '~[compile/do* body [current-closure]]]]]

[defmacro ω body
          "Defines and returns new object after evaluating body within"
          [macroexpand [cons 'ω* body]]]
[def defobj ω]

[defn eval-in [closure expr]
      "Compile and the immediatly evaluate the result"
      ""
      "Mostly used by lRun()"
      [try display/error [-> [compile* expr closure]
                             [bytecode-eval closure]]]]

[defn eval-in/trace [closure expr]
      "Compile and the immediatly evaluate the result"
      ""
      "mostly used by lRun()"
      [try display/error
           [def bc [compile* expr closure]]
           [println [str/write bc]]
           [bytecode-eval bc closure]]]

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

[defmacro typecheck/only [v t]
          `[when-not [== [type-of ~v] ~t] [throw [list :type-error ~[fmt "Expected a value of type {t}"] ~v [current-lambda]]]]]