From 285de1ae1925c2b030bd96032498ccbaa6fc90c9 Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Mon, 18 Mar 2019 18:36:18 -0400 Subject: Cobbled together a simple packager. --- lux-js/source/program.lux | 7 +- stdlib/source/lux/host/js.lux | 63 +++++++++----- stdlib/source/lux/tool/compiler/default/init.lux | 95 +++++++++++++++------- .../lux/tool/compiler/meta/packager/script.lux | 38 +++++++++ .../tool/compiler/phase/extension/statement.lux | 28 +++---- .../source/lux/tool/compiler/phase/generation.lux | 49 +++++------ .../lux/tool/compiler/phase/generation/js/loop.lux | 4 +- .../tool/compiler/phase/generation/js/runtime.lux | 2 +- stdlib/source/program/compositor.lux | 62 ++++++++++++-- 9 files changed, 247 insertions(+), 101 deletions(-) create mode 100644 stdlib/source/lux/tool/compiler/meta/packager/script.lux diff --git a/lux-js/source/program.lux b/lux-js/source/program.lux index 9cd93a9eb..0a723ec30 100644 --- a/lux-js/source/program.lux +++ b/lux-js/source/program.lux @@ -449,15 +449,16 @@ (wrap []))) (def: (define! interpreter [module name] input) - (-> javax/script/ScriptEngine Name _.Expression (Error [Text Any])) + (-> javax/script/ScriptEngine Name _.Expression (Error [Text Any _.Statement])) (let [global (format (text.replace-all .module-separator ..separator module) ..separator (name.normalize name) "___" (%n (text/hash name))) @global (_.var global)] (do error.monad - [_ (execute! interpreter global (_.define @global input)) + [#let [definition (_.define @global input)] + _ (execute! interpreter global definition) value (evaluate! interpreter global @global)] - (wrap [global value])))) + (wrap [global value definition])))) (type: Host (generation.Host _.Expression _.Statement)) diff --git a/stdlib/source/lux/host/js.lux b/stdlib/source/lux/host/js.lux index 7fa3b7123..647e21957 100644 --- a/stdlib/source/lux/host/js.lux +++ b/stdlib/source/lux/host/js.lux @@ -1,12 +1,12 @@ (.module: - [lux (#- Code or and function if cond undefined for false true not) + [lux (#- Code or and function if cond undefined for comment false true not) [control [pipe (#+ case>)]] [data ["." text format] [collection - ["." list ("#;." functor fold)]]] + ["." list ("#@." functor fold)]]] [macro ["." template]] [type @@ -31,6 +31,7 @@ [Expression Expression' [Code]] [Computation Computation' [Expression' Code]] [Location Location' [Computation' Expression' Code]] + [Statement Statement' [Code]] ) (do-template [ +] @@ -39,7 +40,8 @@ [Var Var' [Location' Computation' Expression' Code]] [Access Access' [Location' Computation' Expression' Code]] - [Statement Statement' [Code]] + [Loop Loop' [Statement' Code]] + [Label Label' [Code]] ) (do-template [ ] @@ -93,7 +95,7 @@ (def: #export array (-> (List Expression) Computation) - (|>> (list;map ..code) + (|>> (list@map ..code) (text.join-with ..argument-separator) ..element :abstraction)) @@ -115,7 +117,7 @@ (def: #export (apply/* function inputs) (-> Expression (List Expression) Computation) (|> inputs - (list;map ..code) + (list@map ..code) (text.join-with ..argument-separator) ..argument (format (:representation function)) @@ -148,7 +150,7 @@ (def: #export object (-> (List [Text Expression]) Computation) - (|>> (list;map (.function (_ [key val]) + (|>> (list@map (.function (_ [key val]) (format (:representation (..string key)) ..field-separator (:representation val)))) (text.join-with ..argument-separator) (text.enclose ["{" "}"]) @@ -167,16 +169,16 @@ text.new-line (:representation post)))) - ## (def: indent - ## (-> Text Text) - ## (text.replace-all text.new-line (format text.new-line text.tab))) + (def: indent + (-> Text Text) + (text.replace-all text.new-line (format text.new-line text.tab))) (def: block (-> Statement Text) (let [close (format text.new-line "}")] (|>> :representation (format text.new-line) - ## ..indent + ..indent (text.enclose ["{" close])))) @@ -186,7 +188,7 @@ ..block (format "function " (:representation name) (|> inputs - (list;map ..code) + (list@map ..code) (text.join-with ..argument-separator) ..argument) " ") @@ -199,7 +201,7 @@ ..block (format "function" (|> inputs - (list;map ..code) + (list@map ..code) (text.join-with ..argument-separator) ..argument) " ") @@ -275,7 +277,7 @@ (-> Expression (List Expression) Computation) (|> (format "new " (:representation constructor) (|> inputs - (list;map ..code) + (list@map ..code) (text.join-with ..argument-separator) ..argument)) ..argument @@ -326,12 +328,12 @@ (..block then!)))) (def: #export (while test body) - (-> Expression Statement Statement) + (-> Expression Statement Loop) (:abstraction (format "while(" (:representation test) ") " (..block body)))) (def: #export (do-while test body) - (-> Expression Statement Statement) + (-> Expression Statement Loop) (:abstraction (format "do " (..block body) " while(" (:representation test) ")" ..statement-suffix))) @@ -343,16 +345,33 @@ (..block catch)))) (def: #export (for var init condition update iteration) - (-> Var Expression Expression Expression Statement Statement) + (-> Var Expression Expression Expression Statement Loop) (:abstraction (format "for(" (:representation (..define var init)) " " (:representation condition) ..statement-suffix " " (:representation update) ")" (..block iteration)))) - (def: #export break - Statement - (:abstraction (format "break" ..statement-suffix))) + (def: #export label + (-> Text Label) + (|>> :abstraction)) + + (def: #export (with-label label loop) + (-> Label Loop Statement) + (:abstraction (format (:representation label) ": " (:representation loop)))) + + (do-template [ <0> <1>] + [(def: #export <0> + Statement + (:abstraction (format ..statement-suffix))) + + (def: #export (<1> label) + (-> Label Statement) + (:abstraction (format " " (:representation label) ..statement-suffix)))] + + ["break" break break-at] + ["continue" continue continue-at] + ) (do-template [ ] [(def: #export @@ -364,11 +383,15 @@ [++ "++"] [-- "--"] ) + + (def: #export (comment commentary on) + (All [kind] (-> Text (Code kind) (Code kind))) + (:abstraction (format "/* " commentary " */" " " (:representation on)))) ) (def: #export (cond clauses else!) (-> (List [Expression Statement]) Statement Statement) - (list;fold (.function (_ [test then!] next!) + (list@fold (.function (_ [test then!] next!) (..if test then! next!)) else! (list.reverse clauses))) diff --git a/stdlib/source/lux/tool/compiler/default/init.lux b/stdlib/source/lux/tool/compiler/default/init.lux index 4686441f1..10476cfc5 100644 --- a/stdlib/source/lux/tool/compiler/default/init.lux +++ b/stdlib/source/lux/tool/compiler/default/init.lux @@ -1,5 +1,6 @@ (.module: [lux (#- Module) + [type (#+ :share)] [control ["." monad (#+ do)] ["ex" exception (#+ exception:)]] @@ -119,7 +120,10 @@ (///statement.Operation anchor expression statement a))) (def: (begin dependencies hash input) - (-> (List Module) Nat ///.Input (Operation Source)) + (-> (List Module) Nat ///.Input + (All [anchor expression statement] + (///statement.Operation anchor expression statement + [Source (generation.Buffer statement)]))) (///statement.lift-analysis (do ///phase.monad [#let [module (get@ #///.module input)] @@ -128,32 +132,67 @@ _ (monad.map @ module.import dependencies) #let [source (///analysis.source (get@ #///.module input) (get@ #///.code input))] _ (///analysis.set-source-code source)] - (wrap source)))) + (wrap [source generation.empty-buffer])))) -(def: end +(def: (end module) (-> Module (Operation Any)) - (|>> module.set-compiled - ///statement.lift-analysis)) + (do ///phase.monad + [_ (///statement.lift-analysis + (module.set-compiled module))] + (///statement.lift-generation + (generation.save-buffer! module)))) -(def: (iteration expander reader source) - (-> Expander Reader Source (Operation [Source Requirements])) - (let [execute! (statementP.phase expander)] - (do ///phase.monad - [[source code] (///statement.lift-analysis - (..read source reader)) - requirements (execute! code) - _ (..refresh expander)] - (wrap [source requirements])))) - -(def: (iterate expander module source) - (-> Expander Module Source (Operation (Maybe [Source Requirements]))) +## TODO: Inline ASAP +(def: (get-current-buffer old-buffer) + (All [statement] + (-> (generation.Buffer statement) + (All [anchor expression] + (///statement.Operation anchor expression statement + (generation.Buffer statement))))) + (///statement.lift-generation + generation.buffer)) + +## TODO: Inline ASAP +(def: (process-statement expander pre-buffer code) + (All [statement] + (-> Expander (generation.Buffer statement) Code + (All [anchor expression] + (///statement.Operation anchor expression statement + [Requirements (generation.Buffer statement)])))) + (do ///phase.monad + [_ (///statement.lift-generation + (generation.set-buffer pre-buffer)) + requirements (let [execute! (statementP.phase expander)] + (execute! code)) + post-buffer (..get-current-buffer pre-buffer)] + (wrap [requirements post-buffer]))) + +(def: (iteration expander reader source pre-buffer) + (All [statement] + (-> Expander Reader Source (generation.Buffer statement) + (All [anchor expression] + (///statement.Operation anchor expression statement + [Source Requirements (generation.Buffer statement)])))) + (do ///phase.monad + [[source code] (///statement.lift-analysis + (..read source reader)) + [requirements post-buffer] (process-statement expander pre-buffer code) + _ (..refresh expander)] + (wrap [source requirements post-buffer]))) + +(def: (iterate expander module source pre-buffer) + (All [statement] + (-> Expander Module Source (generation.Buffer statement) + (All [anchor expression] + (///statement.Operation anchor expression statement + (Maybe [Source Requirements (generation.Buffer statement)]))))) (do ///phase.monad [reader (///statement.lift-analysis (..reader module //syntax.no-aliases source))] (function (_ state) - (case (///phase.run' state (..iteration expander reader source)) - (#error.Success [state source&requirements]) - (#error.Success [state (#.Some source&requirements)]) + (case (///phase.run' state (..iteration expander reader source pre-buffer)) + (#error.Success [state source&requirements&buffer]) + (#error.Success [state (#.Some source&requirements&buffer)]) (#error.Failure error) (if (ex.match? //syntax.end-of-file error) @@ -177,14 +216,14 @@ #///.process (function (_ state archive) (do error.monad [#let [hash (text;hash (get@ #///.code input))] - [state source] (<| (///phase.run' state) - (..begin dependencies hash input)) + [state [source buffer]] (<| (///phase.run' state) + (..begin dependencies hash input)) #let [module (get@ #///.module input)]] (loop [iteration (<| (///phase.run' state) - (..iterate expander module source))] + (..iterate expander module source buffer))] (do @ - [[state ?source&requirements] iteration] - (case ?source&requirements + [[state ?source&requirements&buffer] iteration] + (case ?source&requirements&buffer #.None (do @ [[state analysis-module] (<| (///phase.run' state) @@ -202,8 +241,8 @@ (wrap [state (#.Right [[descriptor (document.write key analysis-module)] (dictionary.new text.hash)])])) - - (#.Some [source requirements]) + + (#.Some [source requirements buffer]) (wrap [state (#.Left {#///.dependencies (|> requirements (get@ #///statement.imports) @@ -213,7 +252,7 @@ (do ///phase.monad [_ (monad.map @ execute! (get@ #///statement.referrals requirements)) _ (..refresh expander)] - (..iterate expander module source)))))})]) + (..iterate expander module source buffer)))))})]) )))))})))) (def: #export key diff --git a/stdlib/source/lux/tool/compiler/meta/packager/script.lux b/stdlib/source/lux/tool/compiler/meta/packager/script.lux new file mode 100644 index 000000000..e51afe7a2 --- /dev/null +++ b/stdlib/source/lux/tool/compiler/meta/packager/script.lux @@ -0,0 +1,38 @@ +(.module: + [lux #* + [data + ["." text + format + ["." encoding]] + [collection + ["." dictionary] + ["." row] + ["." list ("#@." functor fold)]]] + [host + ["_" js]] + [tool + [compiler + [phase + [generation (#+ Output)]]]] + [world + [binary (#+ Binary)]]]) + +(def: #export (package outputs) + (All [statements] + (-> (Output statements) Binary)) + (|> outputs + dictionary.entries + (list@map (function (_ [module buffer]) + (|> buffer + row.to-list + (:coerce (List [Name _.Statement])) + (list@fold (function (_ [artifact content] pre!) + (|> content + (_.comment (%name artifact)) + (_.then pre!))) + (_.comment module + _.use-strict)) + (: _.Statement) + _.code))) + (text.join-with text.new-line) + encoding.to-utf8)) diff --git a/stdlib/source/lux/tool/compiler/phase/extension/statement.lux b/stdlib/source/lux/tool/compiler/phase/extension/statement.lux index 18bb58fbd..4f36ef89f 100644 --- a/stdlib/source/lux/tool/compiler/phase/extension/statement.lux +++ b/stdlib/source/lux/tool/compiler/phase/extension/statement.lux @@ -36,12 +36,11 @@ Synthesis (Operation anchor expression statement [Type expression Any]))) (////statement.lift-generation - (///generation.with-buffer - (do ///.monad - [codeT (generate codeS) - count ///generation.next - codeV (///generation.evaluate! (format "evaluate" (%n count)) codeT)] - (wrap [code//type codeT codeV]))))) + (do ///.monad + [codeT (generate codeS) + count ///generation.next + codeV (///generation.evaluate! (format "evaluate" (%n count)) codeT)] + (wrap [code//type codeT codeV])))) (def: (evaluate! type codeC) (All [anchor expression statement] @@ -71,11 +70,11 @@ Synthesis (Operation anchor expression statement [Type expression Text Any]))) (////statement.lift-generation - (///generation.with-buffer - (do ///.monad - [codeT (generate codeS) - codeN+V (///generation.define! name codeT)] - (wrap [code//type codeT codeN+V]))))) + (do ///.monad + [codeT (generate codeS) + [target-name value statement] (///generation.define! name codeT) + _ (///generation.save! name statement)] + (wrap [code//type codeT target-name value])))) (def: (definition name ?type codeC) (All [anchor expression statement] @@ -270,10 +269,9 @@ (-> expression statement) Synthesis (///generation.Operation anchor expression statement Any))) - (///generation.with-buffer - (do ///.monad - [programG (generate programS)] - (///generation.save! ["" ""] (program programG))))) + (do ///.monad + [programG (generate programS)] + (///generation.save! ["" ""] (program programG)))) (def: (def::program program) (All [anchor expression statement] diff --git a/stdlib/source/lux/tool/compiler/phase/generation.lux b/stdlib/source/lux/tool/compiler/phase/generation.lux index 3fe3f867b..203c5d4ab 100644 --- a/stdlib/source/lux/tool/compiler/phase/generation.lux +++ b/stdlib/source/lux/tool/compiler/phase/generation.lux @@ -19,14 +19,6 @@ [// [synthesis (#+ Synthesis)]]]) -(do-template [] - [(exception: #export () - "")] - - [no-active-buffer] - [no-anchor] - ) - (exception: #export (cannot-interpret {error Text}) (exception.report ["Error" error])) @@ -61,19 +53,19 @@ evaluate!) (: (-> Text statement (Error Any)) execute!) - (: (-> Name expression (Error [Text Any])) + (: (-> Name expression (Error [Text Any statement])) define!)) (type: #export (Buffer statement) (Row [Name statement])) -(type: #export (Outputs statement) (Dictionary Path (Buffer statement))) +(type: #export (Output statement) (Dictionary Path (Buffer statement))) (type: #export (State anchor expression statement) {#context Context #anchor (Maybe anchor) #host (Host expression statement) #buffer (Maybe (Buffer statement)) - #outputs (Outputs statement) + #output (Output statement) #counter Nat #name-cache (Dictionary Name Text)}) @@ -97,7 +89,7 @@ #anchor #.None #host host #buffer #.None - #outputs (dictionary.new text.hash) + #output (dictionary.new text.hash) #counter 0 #name-cache (dictionary.new name.hash)}) @@ -122,10 +114,14 @@ (extension.read (|>> (get@ #context) (get@ #scope-name)))) +(def: #export empty-buffer Buffer row.empty) + (do-template [ - ] - [(def: #export + ] + [(exception: #export ) + + (def: #export (All [anchor expression statement output] ) (function (_ body) (function (_ [bundle state]) @@ -146,27 +142,34 @@ (#error.Success [stateE output]) #.None - (exception.throw []))))] + (exception.throw [])))) + + (def: #export ( value) + (All [anchor expression statement] + (-> (Operation anchor expression statement Any))) + (function (_ [bundle state]) + (#error.Success [[bundle (set@ (#.Some value) state)] + []])))] [#anchor (with-anchor anchor) (-> anchor (Operation anchor expression statement output) (Operation anchor expression statement output)) anchor - anchor anchor no-anchor] + set-anchor anchor anchor no-anchor] [#buffer with-buffer (-> (Operation anchor expression statement output) (Operation anchor expression statement output)) - row.empty - buffer (Buffer statement) no-active-buffer] + ..empty-buffer + set-buffer buffer (Buffer statement) no-active-buffer] ) -(def: #export outputs +(def: #export output (All [anchor expression statement] - (Operation anchor expression statement (Outputs statement))) - (extension.read (get@ #outputs))) + (Operation anchor expression statement (Output statement))) + (extension.read (get@ #output))) (def: #export next (All [anchor expression statement] @@ -194,7 +197,7 @@ (def: #export (define! name code) (All [anchor expression statement] - (-> Name expression (Operation anchor expression statement [Text Any]))) + (-> Name expression (Operation anchor expression statement [Text Any statement]))) (function (_ (^@ stateE [bundle state])) (case (:: (get@ #host state) define! name code) (#error.Success output) @@ -224,7 +227,7 @@ (-> Path (Operation anchor expression statement Any))) (do //.monad [buffer ..buffer] - (extension.update (update@ #outputs (dictionary.put target buffer))))) + (extension.update (update@ #output (dictionary.put target buffer))))) (def: #export (remember lux-name) (All [anchor expression statement] diff --git a/stdlib/source/lux/tool/compiler/phase/generation/js/loop.lux b/stdlib/source/lux/tool/compiler/phase/generation/js/loop.lux index e0ec074d3..d905db9a2 100644 --- a/stdlib/source/lux/tool/compiler/phase/generation/js/loop.lux +++ b/stdlib/source/lux/tool/compiler/phase/generation/js/loop.lux @@ -7,7 +7,7 @@ ["." text format] [collection - ["." list ("#;." functor)]]] + ["." list ("#@." functor)]]] [host ["_" js (#+ Computation Var)]]] ["." // #_ @@ -29,7 +29,7 @@ #let [closure (_.function @scope (|> initsS+ list.enumerate - (list;map (|>> product.left (n/+ start) //case.register))) + (list@map (|>> product.left (n/+ start) //case.register))) (_.return bodyO))]] (wrap (_.apply/* closure initsO+)))) diff --git a/stdlib/source/lux/tool/compiler/phase/generation/js/runtime.lux b/stdlib/source/lux/tool/compiler/phase/generation/js/runtime.lux index 5e2da39de..cb65b8b85 100644 --- a/stdlib/source/lux/tool/compiler/phase/generation/js/runtime.lux +++ b/stdlib/source/lux/tool/compiler/phase/generation/js/runtime.lux @@ -743,7 +743,7 @@ runtime//array )) -(def: #export artifact Text (format prefix ".js")) +(def: #export artifact Text prefix) (def: #export generate (Operation Any) diff --git a/stdlib/source/program/compositor.lux b/stdlib/source/program/compositor.lux index b2ab8208e..8262fe841 100644 --- a/stdlib/source/program/compositor.lux +++ b/stdlib/source/program/compositor.lux @@ -4,26 +4,38 @@ [cli (#+ program:)] ["." io (#+ IO io)] [control - [monad (#+ do)]] + [monad (#+ do)] + [security + ["!" capability]]] [data + ["." product] ["." error (#+ Error)] ["." text - format]] + format] + [collection + ["." dictionary] + ["." row] + ["." list ("#@." functor fold)]]] [time ["." instant (#+ Instant)]] + [host + ["_" js]] [world + ["." file] ["." console]] [tool [compiler ["." statement] - [phase + ["." phase [macro (#+ Expander)] ["." generation]] [default ["." platform (#+ Platform)] ["." syntax]] [meta - ["." archive (#+ Archive)]]] + ["." archive (#+ Archive)] + [packager + ["." script]]]] ## ["." interpreter] ]] [/ @@ -44,6 +56,37 @@ (#error.Success output) (wrap output)))) +(def: (save-artifacts! system state) + (All [anchor expression statement] + (-> (file.System IO) + (statement.State+ anchor expression statement) + (IO (Error Any)))) + (let [?outcome (phase.run' state + (:share [anchor expression statement] + {(statement.State+ anchor expression statement) + state} + {(statement.Operation anchor expression statement + (generation.Output statement)) + (statement.lift-generation generation.output)}))] + (case ?outcome + (#error.Success [state output]) + (exec (log! "all buffers | output:") + (log! (|> output + dictionary.entries + (list@map (function (_ [module buffer]) + (|> buffer + row.to-list + (list@map (|>> product.left %name (format text.new-line text.tab))) + (text.join-with "") + (format module)))) + (text.join-with text.new-line))) + (do (error.with io.monad) + [file (!.use (:: system create-file) "program.js")] + (!.use (:: file over-write) (script.package output)))) + + (#error.Failure error) + (:: io.monad wrap (#error.Failure error))))) + (def: #export (compiler expander platform bundle program service) (All [anchor expression statement] (-> Expander @@ -64,11 +107,12 @@ platform} {(IO (Error (statement.State+ anchor expression statement))) (platform.initialize expander platform bundle program)}) - _ (:share [anchor expression statement] - {(Platform IO anchor expression statement) - platform} - {(IO (Error [Archive (statement.State+ anchor expression statement)])) - (platform.compile expander platform configuration archive.empty state)}) + [archive state] (:share [anchor expression statement] + {(Platform IO anchor expression statement) + platform} + {(IO (Error [Archive (statement.State+ anchor expression statement)])) + (platform.compile expander platform configuration archive.empty state)}) + _ (save-artifacts! (get@ #platform.&file-system platform) state) ## _ (cache/io.clean target ...) ] (wrap (log! "Compilation complete!")))) -- cgit v1.2.3