(.module: [lux #* [control [monad (#+ Monad do)] ["ex" exception (#+ exception:)]] [data ["." error (#+ Error)] ["." text ("#;." equivalence) format]] [type (#+ :share) ["." check]] [compiler ["." phase ["." analysis ["." module] ["." type]] ["." generation] ["." statement (#+ State+ Operation) ["." total]] ["." extension]] ["." default ["." syntax] ["." platform (#+ Platform)] ["." init]] ["." cli (#+ Configuration)]] [world ["." file (#+ File)] ["." console (#+ Console)]]] ["." /type]) (exception: #export (error {message Text}) message) (def: #export module "") (def: fresh-source Source [[..module 1 0] 0 ""]) (def: (add-line line [where offset input]) (-> Text Source Source) [where offset (format input text.new-line line)]) (def: exit-command Text "exit") (def: welcome-message Text (format text.new-line "Welcome to the interpreter!" text.new-line "Type '" ..exit-command "' to leave." text.new-line text.new-line)) (def: farewell-message Text "Till next time...") (def: enter-module (All [anchor expression statement] (Operation anchor expression statement Any)) (statement.lift-analysis (do phase.monad [_ (module.create 0 ..module)] (analysis.set-current-module ..module)))) (def: (initialize Monad Console platform configuration generation-bundle) (All [! anchor expression statement] (-> (Monad !) (Console !) (Platform ! anchor expression statement) Configuration (generation.Bundle anchor expression statement) (! (State+ anchor expression statement)))) (do Monad [state (platform.initialize platform generation-bundle) state (platform.compile platform (set@ #cli.module syntax.prelude configuration) (set@ [#extension.state #statement.analysis #statement.state #extension.state #.info #.mode] #.Interpreter state)) [state _] (:: (get@ #platform.file-system platform) lift (phase.run' state enter-module)) _ (:: Console write ..welcome-message)] (wrap state))) (with-expansions [ (as-is (Operation anchor expression statement [Type Any]))] (def: (interpret-statement code) (All [anchor expression statement] (-> Code )) (do phase.monad [_ (total.phase code) _ init.refresh] (wrap [Any []]))) (def: (interpret-expression code) (All [anchor expression statement] (-> Code )) (do phase.monad [state (extension.lift phase.get-state) #let [analyse (get@ [#statement.analysis #statement.phase] state) synthesize (get@ [#statement.synthesis #statement.phase] state) generate (get@ [#statement.generation #statement.phase] state)] [_ codeT codeA] (statement.lift-analysis (analysis.with-scope (type.with-fresh-env (do @ [[codeT codeA] (type.with-inference (analyse code)) codeT (type.with-env (check.clean codeT))] (wrap [codeT codeA]))))) codeS (statement.lift-synthesis (synthesize codeA))] (statement.lift-generation (generation.with-buffer (do @ [codeH (generate codeS) count generation.next codeV (generation.evaluate! (format "interpretation_" (%n count)) codeH)] (wrap [codeT codeV])))))) (def: (interpret configuration code) (All [anchor expression statement] (-> Configuration Code )) (function (_ state) (case (<| (phase.run' state) (:share [anchor expression statement] {(State+ anchor expression statement) state} { (interpret-statement code)})) (#error.Success [state' output]) (#error.Success [state' output]) (#error.Failure error) (if (ex.match? total.not-a-statement error) (<| (phase.run' state) (:share [anchor expression statement] {(State+ anchor expression statement) state} { (interpret-expression code)})) (#error.Failure error))))) ) (def: (execute configuration code) (All [anchor expression statement] (-> Configuration Code (Operation anchor expression statement Text))) (do phase.monad [[codeT codeV] (interpret configuration code) state phase.get-state] (wrap (/type.represent (get@ [#extension.state #statement.analysis #statement.state #extension.state] state) codeT codeV)))) (type: (Context anchor expression statement) {#configuration Configuration #state (State+ anchor expression statement) #source Source}) (with-expansions [ (as-is (Context anchor expression statement))] (def: (read-eval-print context) (All [anchor expression statement] (-> (Error [ Text]))) (do error.monad [#let [[_where _offset _code] (get@ #source context)] [source' input] (syntax.parse ..module syntax.no-aliases (text.size _code) (get@ #source context)) [state' representation] (let [## TODO: Simplify ASAP state (:share [anchor expression statement] { context} {(State+ anchor expression statement) (get@ #state context)})] (<| (phase.run' state) ## TODO: Simplify ASAP (:share [anchor expression statement] { context} {(Operation anchor expression statement Text) (execute (get@ #configuration context) input)})))] (wrap [(|> context (set@ #state state') (set@ #source source')) representation])))) (def: #export (run Monad Console platform configuration generation-bundle) (All [! anchor expression statement] (-> (Monad !) (Console !) (Platform ! anchor expression statement) Configuration (generation.Bundle anchor expression statement) (! Any))) (do Monad [state (initialize Monad Console platform configuration)] (loop [context {#configuration configuration #state state #source ..fresh-source} multi-line? #0] (do @ [_ (if multi-line? (:: Console write " ") (:: Console write "> ")) line (:: Console read-line)] (if (and (not multi-line?) (text;= ..exit-command line)) (:: Console write ..farewell-message) (case (read-eval-print (update@ #source (add-line line) context)) (#error.Success [context' representation]) (do @ [_ (:: Console write representation)] (recur context' #0)) (#error.Failure error) (if (ex.match? syntax.end-of-file error) (recur context #1) (exec (log! (ex.construct ..error error)) (recur (set@ #source ..fresh-source context) #0)))))) )))