From 664e02d1b5e5aa479869c4e17ec4128f5cfd04e2 Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Wed, 29 Jun 2022 03:15:23 -0400 Subject: New "parser" hierarchy. [Part 6] --- .../library/lux/control/parser/environment.lux | 44 --- stdlib/source/library/lux/test.lux | 4 +- stdlib/source/library/lux/world/environment.lux | 439 ++++++++++++++++++++ stdlib/source/library/lux/world/net/http.lux | 9 +- stdlib/source/library/lux/world/program.lux | 440 --------------------- stdlib/source/library/lux/world/shell.lux | 8 +- 6 files changed, 450 insertions(+), 494 deletions(-) delete mode 100644 stdlib/source/library/lux/control/parser/environment.lux create mode 100644 stdlib/source/library/lux/world/environment.lux delete mode 100644 stdlib/source/library/lux/world/program.lux (limited to 'stdlib/source/library') diff --git a/stdlib/source/library/lux/control/parser/environment.lux b/stdlib/source/library/lux/control/parser/environment.lux deleted file mode 100644 index df9bf0fbc..000000000 --- a/stdlib/source/library/lux/control/parser/environment.lux +++ /dev/null @@ -1,44 +0,0 @@ -(.require - [library - [lux (.except) - [control - ["[0]" try (.only Try)] - ["[0]" exception (.only exception)]] - [data - ["[0]" product] - ["[0]" text (.only) - ["%" \\format (.only format)]] - [collection - ["[0]" dictionary (.only Dictionary)]]]]] - ["[0]" //]) - -(type .public Property - Text) - -(type .public Environment - (Dictionary Property Text)) - -(exception .public (unknown_property [property Property]) - (exception.report - "Property" (%.text property))) - -(type .public (Parser a) - (//.Parser Environment a)) - -(def .public empty - Environment - (dictionary.empty text.hash)) - -(def .public (property name) - (-> Property (Parser Text)) - (function (_ environment) - (case (dictionary.value name environment) - {.#Some value} - {try.#Success [environment value]} - - {.#None} - (exception.except ..unknown_property [name])))) - -(def .public (result parser environment) - (All (_ a) (-> (Parser a) Environment (Try a))) - (at try.monad each product.right (parser environment))) diff --git a/stdlib/source/library/lux/test.lux b/stdlib/source/library/lux/test.lux index 110675c5d..5f086c633 100644 --- a/stdlib/source/library/lux/test.lux +++ b/stdlib/source/library/lux/test.lux @@ -39,7 +39,7 @@ ["[0]" meta (.only) ["[0]" symbol]] [world - ["[0]" program] + ["[0]" environment] ["[0]" console]]]]) (type .public Tally @@ -259,7 +259,7 @@ {.#Some console} (console.write_line report console)) ))] - (async.future (at program.default exit + (async.future (at environment.default exit (case (the #failures tally) 0 ..success_exit_code _ ..failure_exit_code))))) diff --git a/stdlib/source/library/lux/world/environment.lux b/stdlib/source/library/lux/world/environment.lux new file mode 100644 index 000000000..2955c5343 --- /dev/null +++ b/stdlib/source/library/lux/world/environment.lux @@ -0,0 +1,439 @@ +(.`` (.`` (.require + [library + [lux (.except) + ["@" target] + [abstract + ["[0]" monad (.only Monad do)]] + [control + ["[0]" function] + ["[0]" io (.only IO)] + ["[0]" maybe (.use "[1]#[0]" functor)] + ["[0]" try (.only Try)] + ["[0]" exception (.only exception)] + [concurrency + ["[0]" atom] + ["[0]" async (.only Async)]]] + [data + ["[0]" bit (.use "[1]#[0]" equivalence)] + ["[0]" text (.only) + ["%" \\format (.only format)]] + [collection + ["[0]" array (.only Array)] + ["[0]" dictionary (.only Dictionary)] + ["[0]" list (.use "[1]#[0]" functor)]]] + ["[0]" ffi (.only import) + (.~~ (.for "JavaScript" (.~~ (.these ["[0]" node_js])) + "{old}" (.~~ (.these ["node_js" //math])) + (.~~ (.these))))] + ["[0]" macro (.only) + ["[0]" template]] + [math + [number + ["i" int]]]]] + ["[0]" \\parser] + [// + [file (.only Path)] + [shell (.only Exit)]]))) + +(exception .public (unknown_environment_variable [name Text]) + (exception.report + "Name" (%.text name))) + +(type .public (Environment !) + (Interface + (is (-> Any (! (List Text))) + available_variables) + (is (-> Text (! (Try Text))) + variable) + (is Path + home) + (is Path + directory) + (is (-> Exit (! Nothing)) + exit))) + +(def .public (environment monad environment) + (All (_ !) (-> (Monad !) (Environment !) (! \\parser.Environment))) + (do [! monad] + [variables (at environment available_variables []) + entries (monad.each ! (function (_ name) + (at ! each (|>> [name]) (at environment variable name))) + variables)] + (in (|> entries + (list.all (function (_ [name value]) + (case value + {try.#Success value} + {.#Some [name value]} + + {try.#Failure _} + {.#None}))) + (dictionary.of_list text.hash))))) + +(`` (def .public (async environment) + (-> (Environment IO) (Environment Async)) + (implementation + (~~ (with_template [] + [(def + (at environment ))] + + [home] + [directory] + )) + + (~~ (with_template [] + [(def + (|>> (at environment ) async.future))] + + [available_variables] + [variable] + [exit] + ))))) + +(def .public (mock environment home directory) + (-> \\parser.Environment Path Path (Environment IO)) + (let [@dead? (atom.atom false)] + (implementation + (def available_variables + (function.constant (io.io (dictionary.keys environment)))) + (def (variable name) + (io.io (case (dictionary.value name environment) + {.#Some value} + {try.#Success value} + + {.#None} + (exception.except ..unknown_environment_variable [name])))) + (def home + home) + (def directory + directory) + (def exit + (|>> %.int panic! io.io))))) + +... Do not trust the values of environment variables +... https://wiki.sei.cmu.edu/confluence/display/java/ENV02-J.+Do+not+trust+the+values+of+environment+variables + +(with_expansions [ (these (import java/lang/String + "[1]::[0]") + + (import (java/util/Iterator a) + "[1]::[0]" + (hasNext [] boolean) + (next [] a)) + + (import (java/util/Set a) + "[1]::[0]" + (iterator [] (java/util/Iterator a))) + + (import (java/util/Map k v) + "[1]::[0]" + (keySet [] (java/util/Set k))) + + (import java/lang/System + "[1]::[0]" + ("static" getenv [] (java/util/Map java/lang/String java/lang/String)) + ("static" getenv "as" resolveEnv [java/lang/String] "io" "?" java/lang/String) + ("static" getProperty [java/lang/String] "?" java/lang/String) + ("static" exit [int] "io" void)) + + (def (jvm::consume iterator) + (All (_ a) (-> (java/util/Iterator a) (List a))) + (if (ffi.of_boolean (java/util/Iterator::hasNext iterator)) + {.#Item (java/util/Iterator::next iterator) + (jvm::consume iterator)} + {.#End})) + )] + (for @.old (these ) + @.jvm (these ) + @.js (these (def default_exit! + (-> Exit (IO Nothing)) + (|>> %.int panic! io.io)) + + (import NodeJs_Process + "[1]::[0]" + (exit [ffi.Number] "io" Nothing) + (cwd [] "io" Path)) + + (def (exit_node_js! code) + (-> Exit (IO Nothing)) + (case (ffi.global ..NodeJs_Process [process]) + {.#Some process} + (NodeJs_Process::exit (i.frac code) process) + + {.#None} + (..default_exit! code))) + + (import Browser_Window + "[1]::[0]" + (close [] Nothing)) + + (import Browser_Location + "[1]::[0]" + (reload [] Nothing)) + + (def (exit_browser! code) + (-> Exit (IO Nothing)) + (case [(ffi.global ..Browser_Window [window]) + (ffi.global ..Browser_Location [location])] + [{.#Some window} {.#Some location}] + (exec + (Browser_Window::close window) + (Browser_Location::reload location) + (..default_exit! code)) + + [{.#Some window} {.#None}] + (exec + (Browser_Window::close window) + (..default_exit! code)) + + [{.#None} {.#Some location}] + (exec + (Browser_Location::reload location) + (..default_exit! code)) + + [{.#None} {.#None}] + (..default_exit! code))) + + (import Object + "[1]::[0]" + ("static" entries [Object] (Array (Array ffi.String)))) + + (import NodeJs_OS + "[1]::[0]" + (homedir [] "io" Path))) + @.python (these (import os + "[1]::[0]" + ("static" getcwd [] "io" ffi.String) + ("static" _exit [ffi.Integer] "io" Nothing)) + + (import os/path + "[1]::[0]" + ("static" expanduser [ffi.String] "io" ffi.String)) + + (import os/environ + "[1]::[0]" + ("static" keys [] "io" (Array ffi.String)) + ("static" get [ffi.String] "io" "?" ffi.String))) + @.lua (these (ffi.import LuaFile + "[1]::[0]" + (read [ffi.String] "io" "?" ffi.String) + (close [] "io" ffi.Boolean)) + + (ffi.import (io/popen [ffi.String] "io" "try" "?" LuaFile)) + (ffi.import (os/getenv [ffi.String] "io" "?" ffi.String)) + (ffi.import (os/exit [ffi.Integer] "io" Nothing)) + + (def (run_command default command) + (-> Text Text (IO Text)) + (do [! io.monad] + [outcome (io/popen [command])] + (case outcome + {try.#Success outcome} + (case outcome + {.#Some file} + (do ! + [?output (LuaFile::read "*l" file) + _ (LuaFile::close file)] + (in (maybe.else default ?output))) + + {.#None} + (in default)) + + {try.#Failure _} + (in default))))) + @.ruby (these (ffi.import Env + "[1]::[0]" + ("static" keys [] (Array Text)) + ("static" fetch [Text] "io" "?" Text)) + + (ffi.import "fileutils" FileUtils + "[1]::[0]" + ("static" pwd Path)) + + (ffi.import Dir + "[1]::[0]" + ("static" home Path)) + + (ffi.import Kernel + "[1]::[0]" + ("static" exit [Int] "io" Nothing))) + + ... @.php + ... (these (ffi.import (exit [Int] "io" Nothing)) + ... ... https://www.php.net/manual/en/function.exit.php + ... (ffi.import (getcwd [] "io" ffi.String)) + ... ... https://www.php.net/manual/en/function.getcwd.php + ... (ffi.import (getenv "as" getenv/1 [ffi.String] "io" ffi.String)) + ... (ffi.import (getenv "as" getenv/0 [] "io" (Array ffi.String))) + ... ... https://www.php.net/manual/en/function.getenv.php + ... ... https://www.php.net/manual/en/function.array-keys.php + ... (ffi.import (array_keys [(Array ffi.String)] (Array ffi.String))) + ... ) + + ... @.scheme + ... (these (ffi.import (exit [Int] "io" Nothing)) + ... ... https://srfi.schemers.org/srfi-98/srfi-98.html + ... (primitive Pair Any) + ... (primitive PList Any) + ... (ffi.import (get-environment-variables [] "io" PList)) + ... (ffi.import (car [Pair] Text)) + ... (ffi.import (cdr [Pair] Text)) + ... (ffi.import (car "as" head [PList] Pair)) + ... (ffi.import (cdr "as" tail [PList] PList))) + + (these))) + +(def .public default + (Environment IO) + (implementation + (def (available_variables _) + (with_expansions [ (|> (java/lang/System::getenv) + java/util/Map::keySet + java/util/Set::iterator + ..jvm::consume + (list#each (|>> ffi.of_string)) + io.io)] + (for @.old + @.jvm + @.js (io.io (if ffi.on_node_js? + (case (ffi.global Object [process env]) + {.#Some process/env} + (|> (Object::entries [process/env]) + (array.list {.#None}) + (list#each (|>> (array.item 0) maybe.trusted))) + + {.#None} + (list)) + (list))) + @.python (at io.monad each (array.list {.#None}) (os/environ::keys [])) + ... Lua offers no way to get all the environment variables available. + @.lua (io.io (list)) + @.ruby (io.io (array.list {.#None} (Env::keys []))) + ... @.php (do io.monad + ... [environment (..getenv/0 [])] + ... (in (|> environment + ... ..array_keys + ... (array.list {.#None}) + ... (list#each (function (_ variable) + ... [variable ("php array read" (as Nat variable) environment)])) + ... (dictionary.of_list text.hash)))) + ... @.scheme (do io.monad + ... [input (..get-environment-variables [])] + ... (loop (again [input input + ... output \\parser.empty]) + ... (if ("scheme object nil?" input) + ... (in output) + ... (let [entry (..head input)] + ... (again (..tail input) + ... (dictionary.has (..car entry) (..cdr entry) output)))))) + ))) + + (def (variable name) + (template.let [(!fetch ) + [(do io.monad + [value (|> name )] + (in (case value + {.#Some value} + {try.#Success ( value)} + + {.#None} + (exception.except ..unknown_environment_variable [name]))))]] + (with_expansions [ (!fetch (<| java/lang/System::resolveEnv ffi.as_string) ffi.of_string)] + (for @.old + @.jvm + @.js (io.io (if ffi.on_node_js? + (case (do maybe.monad + [process/env (ffi.global Object [process env])] + (array.item (as Nat name) + (as (Array Text) process/env))) + {.#Some value} + {try.#Success value} + + {.#None} + (exception.except ..unknown_environment_variable [name])) + (exception.except ..unknown_environment_variable [name]))) + @.python (!fetch os/environ::get |>) + @.lua (!fetch os/getenv |>) + @.ruby (!fetch Env::fetch |>) + )))) + + (def home + (io.run! + (with_expansions [ (io.io "~") + (|> (java/lang/System::getProperty (ffi.as_string "user.home")) + (maybe#each (|>> ffi.of_string)) + (maybe.else "") + io.io)] + (for @.old + @.jvm + @.js (if ffi.on_node_js? + (|> (node_js.require "os") + maybe.trusted + (as NodeJs_OS) + NodeJs_OS::homedir) + ) + @.python (os/path::expanduser "~") + @.lua (..run_command "~" "echo ~") + @.ruby (io.io (Dir::home)) + ... @.php (do io.monad + ... [output (..getenv/1 ["HOME"])] + ... (in (if (bit#= false (as Bit output)) + ... "~" + ... output))) + + ... TODO: Replace dummy implementation. + )))) + + (def directory + (io.run! + (with_expansions [ "." + (|> (java/lang/System::getProperty (ffi.as_string "user.dir")) + (maybe#each (|>> ffi.of_string)) + (maybe.else "") + io.io)] + (for @.old + @.jvm + @.js (if ffi.on_node_js? + (case (ffi.global ..NodeJs_Process [process]) + {.#Some process} + (NodeJs_Process::cwd process) + + {.#None} + (io.io )) + (io.io )) + @.python (os::getcwd []) + @.lua (do io.monad + [.let [default ] + on_windows (..run_command default "cd")] + (if (same? default on_windows) + (..run_command default "pwd") + (in on_windows))) + @.ruby (io.io (FileUtils::pwd)) + ... @.php (do io.monad + ... [output (..getcwd [])] + ... (in (if (bit#= false (as Bit output)) + ... "." + ... output))) + + ... TODO: Replace dummy implementation. + (io.io ))))) + + (def (exit code) + (with_expansions [ (do io.monad + [_ (java/lang/System::exit (ffi.as_int code))] + (in (undefined)))] + (for @.old + @.jvm + @.js (cond ffi.on_node_js? + (..exit_node_js! code) + + ffi.on_browser? + (..exit_browser! code) + + ... else + (..default_exit! code)) + @.python (os::_exit code) + @.lua (os/exit code) + @.ruby (Kernel::exit code) + ... @.php (..exit [code]) + ... @.scheme (..exit [code]) + ))))) diff --git a/stdlib/source/library/lux/world/net/http.lux b/stdlib/source/library/lux/world/net/http.lux index d98151768..0582c9192 100644 --- a/stdlib/source/library/lux/world/net/http.lux +++ b/stdlib/source/library/lux/world/net/http.lux @@ -4,13 +4,14 @@ [control [try (.only Try)] [concurrency - [frp (.only Channel)]] - [parser - ["[0]" environment (.only Environment)]]] + [frp (.only Channel)]]] [data [binary (.only Binary)]]]] [// (.only URL) - [uri (.only URI)]]) + [uri (.only URI)] + [// + ["[0]" environment + ["[1]" \\parser (.only Environment)]]]]) (type .public Version Text) diff --git a/stdlib/source/library/lux/world/program.lux b/stdlib/source/library/lux/world/program.lux deleted file mode 100644 index 9923535c9..000000000 --- a/stdlib/source/library/lux/world/program.lux +++ /dev/null @@ -1,440 +0,0 @@ -(.`` (.`` (.require - [library - [lux (.except) - ["@" target] - [abstract - ["[0]" monad (.only Monad do)]] - [control - ["[0]" function] - ["[0]" io (.only IO)] - ["[0]" maybe (.use "[1]#[0]" functor)] - ["[0]" try (.only Try)] - ["[0]" exception (.only exception)] - [concurrency - ["[0]" atom] - ["[0]" async (.only Async)]] - [parser - ["[0]" environment (.only Environment)]]] - [data - ["[0]" bit (.use "[1]#[0]" equivalence)] - ["[0]" text (.only) - ["%" \\format (.only format)]] - [collection - ["[0]" array (.only Array)] - ["[0]" dictionary (.only Dictionary)] - ["[0]" list (.use "[1]#[0]" functor)]]] - ["[0]" ffi (.only import) - (.~~ (.for "JavaScript" (.~~ (.these ["[0]" node_js])) - "{old}" (.~~ (.these ["node_js" //math])) - (.~~ (.these))))] - ["[0]" macro (.only) - ["[0]" template]] - [math - [number - ["i" int]]]]] - [// - [file (.only Path)] - [shell (.only Exit)]]))) - -(exception .public (unknown_environment_variable [name Text]) - (exception.report - "Name" (%.text name))) - -(type .public (Program !) - (Interface - (is (-> Any (! (List Text))) - available_variables) - (is (-> Text (! (Try Text))) - variable) - (is Path - home) - (is Path - directory) - (is (-> Exit (! Nothing)) - exit))) - -(def .public (environment monad program) - (All (_ !) (-> (Monad !) (Program !) (! Environment))) - (do [! monad] - [variables (at program available_variables []) - entries (monad.each ! (function (_ name) - (at ! each (|>> [name]) (at program variable name))) - variables)] - (in (|> entries - (list.all (function (_ [name value]) - (case value - {try.#Success value} - {.#Some [name value]} - - {try.#Failure _} - {.#None}))) - (dictionary.of_list text.hash))))) - -(`` (def .public (async program) - (-> (Program IO) (Program Async)) - (implementation - (~~ (with_template [] - [(def - (at program ))] - - [home] - [directory] - )) - - (~~ (with_template [] - [(def - (|>> (at program ) async.future))] - - [available_variables] - [variable] - [exit] - ))))) - -(def .public (mock environment home directory) - (-> Environment Path Path (Program IO)) - (let [@dead? (atom.atom false)] - (implementation - (def available_variables - (function.constant (io.io (dictionary.keys environment)))) - (def (variable name) - (io.io (case (dictionary.value name environment) - {.#Some value} - {try.#Success value} - - {.#None} - (exception.except ..unknown_environment_variable [name])))) - (def home - home) - (def directory - directory) - (def exit - (|>> %.int panic! io.io))))) - -... Do not trust the values of environment variables -... https://wiki.sei.cmu.edu/confluence/display/java/ENV02-J.+Do+not+trust+the+values+of+environment+variables - -(with_expansions [ (these (import java/lang/String - "[1]::[0]") - - (import (java/util/Iterator a) - "[1]::[0]" - (hasNext [] boolean) - (next [] a)) - - (import (java/util/Set a) - "[1]::[0]" - (iterator [] (java/util/Iterator a))) - - (import (java/util/Map k v) - "[1]::[0]" - (keySet [] (java/util/Set k))) - - (import java/lang/System - "[1]::[0]" - ("static" getenv [] (java/util/Map java/lang/String java/lang/String)) - ("static" getenv "as" resolveEnv [java/lang/String] "io" "?" java/lang/String) - ("static" getProperty [java/lang/String] "?" java/lang/String) - ("static" exit [int] "io" void)) - - (def (jvm::consume iterator) - (All (_ a) (-> (java/util/Iterator a) (List a))) - (if (ffi.of_boolean (java/util/Iterator::hasNext iterator)) - {.#Item (java/util/Iterator::next iterator) - (jvm::consume iterator)} - {.#End})) - )] - (for @.old (these ) - @.jvm (these ) - @.js (these (def default_exit! - (-> Exit (IO Nothing)) - (|>> %.int panic! io.io)) - - (import NodeJs_Process - "[1]::[0]" - (exit [ffi.Number] "io" Nothing) - (cwd [] "io" Path)) - - (def (exit_node_js! code) - (-> Exit (IO Nothing)) - (case (ffi.global ..NodeJs_Process [process]) - {.#Some process} - (NodeJs_Process::exit (i.frac code) process) - - {.#None} - (..default_exit! code))) - - (import Browser_Window - "[1]::[0]" - (close [] Nothing)) - - (import Browser_Location - "[1]::[0]" - (reload [] Nothing)) - - (def (exit_browser! code) - (-> Exit (IO Nothing)) - (case [(ffi.global ..Browser_Window [window]) - (ffi.global ..Browser_Location [location])] - [{.#Some window} {.#Some location}] - (exec - (Browser_Window::close window) - (Browser_Location::reload location) - (..default_exit! code)) - - [{.#Some window} {.#None}] - (exec - (Browser_Window::close window) - (..default_exit! code)) - - [{.#None} {.#Some location}] - (exec - (Browser_Location::reload location) - (..default_exit! code)) - - [{.#None} {.#None}] - (..default_exit! code))) - - (import Object - "[1]::[0]" - ("static" entries [Object] (Array (Array ffi.String)))) - - (import NodeJs_OS - "[1]::[0]" - (homedir [] "io" Path))) - @.python (these (import os - "[1]::[0]" - ("static" getcwd [] "io" ffi.String) - ("static" _exit [ffi.Integer] "io" Nothing)) - - (import os/path - "[1]::[0]" - ("static" expanduser [ffi.String] "io" ffi.String)) - - (import os/environ - "[1]::[0]" - ("static" keys [] "io" (Array ffi.String)) - ("static" get [ffi.String] "io" "?" ffi.String))) - @.lua (these (ffi.import LuaFile - "[1]::[0]" - (read [ffi.String] "io" "?" ffi.String) - (close [] "io" ffi.Boolean)) - - (ffi.import (io/popen [ffi.String] "io" "try" "?" LuaFile)) - (ffi.import (os/getenv [ffi.String] "io" "?" ffi.String)) - (ffi.import (os/exit [ffi.Integer] "io" Nothing)) - - (def (run_command default command) - (-> Text Text (IO Text)) - (do [! io.monad] - [outcome (io/popen [command])] - (case outcome - {try.#Success outcome} - (case outcome - {.#Some file} - (do ! - [?output (LuaFile::read "*l" file) - _ (LuaFile::close file)] - (in (maybe.else default ?output))) - - {.#None} - (in default)) - - {try.#Failure _} - (in default))))) - @.ruby (these (ffi.import Env - "[1]::[0]" - ("static" keys [] (Array Text)) - ("static" fetch [Text] "io" "?" Text)) - - (ffi.import "fileutils" FileUtils - "[1]::[0]" - ("static" pwd Path)) - - (ffi.import Dir - "[1]::[0]" - ("static" home Path)) - - (ffi.import Kernel - "[1]::[0]" - ("static" exit [Int] "io" Nothing))) - - ... @.php - ... (these (ffi.import (exit [Int] "io" Nothing)) - ... ... https://www.php.net/manual/en/function.exit.php - ... (ffi.import (getcwd [] "io" ffi.String)) - ... ... https://www.php.net/manual/en/function.getcwd.php - ... (ffi.import (getenv "as" getenv/1 [ffi.String] "io" ffi.String)) - ... (ffi.import (getenv "as" getenv/0 [] "io" (Array ffi.String))) - ... ... https://www.php.net/manual/en/function.getenv.php - ... ... https://www.php.net/manual/en/function.array-keys.php - ... (ffi.import (array_keys [(Array ffi.String)] (Array ffi.String))) - ... ) - - ... @.scheme - ... (these (ffi.import (exit [Int] "io" Nothing)) - ... ... https://srfi.schemers.org/srfi-98/srfi-98.html - ... (primitive Pair Any) - ... (primitive PList Any) - ... (ffi.import (get-environment-variables [] "io" PList)) - ... (ffi.import (car [Pair] Text)) - ... (ffi.import (cdr [Pair] Text)) - ... (ffi.import (car "as" head [PList] Pair)) - ... (ffi.import (cdr "as" tail [PList] PList))) - - (these))) - -(def .public default - (Program IO) - (implementation - (def (available_variables _) - (with_expansions [ (|> (java/lang/System::getenv) - java/util/Map::keySet - java/util/Set::iterator - ..jvm::consume - (list#each (|>> ffi.of_string)) - io.io)] - (for @.old - @.jvm - @.js (io.io (if ffi.on_node_js? - (case (ffi.global Object [process env]) - {.#Some process/env} - (|> (Object::entries [process/env]) - (array.list {.#None}) - (list#each (|>> (array.item 0) maybe.trusted))) - - {.#None} - (list)) - (list))) - @.python (at io.monad each (array.list {.#None}) (os/environ::keys [])) - ... Lua offers no way to get all the environment variables available. - @.lua (io.io (list)) - @.ruby (io.io (array.list {.#None} (Env::keys []))) - ... @.php (do io.monad - ... [environment (..getenv/0 [])] - ... (in (|> environment - ... ..array_keys - ... (array.list {.#None}) - ... (list#each (function (_ variable) - ... [variable ("php array read" (as Nat variable) environment)])) - ... (dictionary.of_list text.hash)))) - ... @.scheme (do io.monad - ... [input (..get-environment-variables [])] - ... (loop (again [input input - ... output environment.empty]) - ... (if ("scheme object nil?" input) - ... (in output) - ... (let [entry (..head input)] - ... (again (..tail input) - ... (dictionary.has (..car entry) (..cdr entry) output)))))) - ))) - - (def (variable name) - (template.let [(!fetch ) - [(do io.monad - [value (|> name )] - (in (case value - {.#Some value} - {try.#Success ( value)} - - {.#None} - (exception.except ..unknown_environment_variable [name]))))]] - (with_expansions [ (!fetch (<| java/lang/System::resolveEnv ffi.as_string) ffi.of_string)] - (for @.old - @.jvm - @.js (io.io (if ffi.on_node_js? - (case (do maybe.monad - [process/env (ffi.global Object [process env])] - (array.item (as Nat name) - (as (Array Text) process/env))) - {.#Some value} - {try.#Success value} - - {.#None} - (exception.except ..unknown_environment_variable [name])) - (exception.except ..unknown_environment_variable [name]))) - @.python (!fetch os/environ::get |>) - @.lua (!fetch os/getenv |>) - @.ruby (!fetch Env::fetch |>) - )))) - - (def home - (io.run! - (with_expansions [ (io.io "~") - (|> (java/lang/System::getProperty (ffi.as_string "user.home")) - (maybe#each (|>> ffi.of_string)) - (maybe.else "") - io.io)] - (for @.old - @.jvm - @.js (if ffi.on_node_js? - (|> (node_js.require "os") - maybe.trusted - (as NodeJs_OS) - NodeJs_OS::homedir) - ) - @.python (os/path::expanduser "~") - @.lua (..run_command "~" "echo ~") - @.ruby (io.io (Dir::home)) - ... @.php (do io.monad - ... [output (..getenv/1 ["HOME"])] - ... (in (if (bit#= false (as Bit output)) - ... "~" - ... output))) - - ... TODO: Replace dummy implementation. - )))) - - (def directory - (io.run! - (with_expansions [ "." - (|> (java/lang/System::getProperty (ffi.as_string "user.dir")) - (maybe#each (|>> ffi.of_string)) - (maybe.else "") - io.io)] - (for @.old - @.jvm - @.js (if ffi.on_node_js? - (case (ffi.global ..NodeJs_Process [process]) - {.#Some process} - (NodeJs_Process::cwd process) - - {.#None} - (io.io )) - (io.io )) - @.python (os::getcwd []) - @.lua (do io.monad - [.let [default ] - on_windows (..run_command default "cd")] - (if (same? default on_windows) - (..run_command default "pwd") - (in on_windows))) - @.ruby (io.io (FileUtils::pwd)) - ... @.php (do io.monad - ... [output (..getcwd [])] - ... (in (if (bit#= false (as Bit output)) - ... "." - ... output))) - - ... TODO: Replace dummy implementation. - (io.io ))))) - - (def (exit code) - (with_expansions [ (do io.monad - [_ (java/lang/System::exit (ffi.as_int code))] - (in (undefined)))] - (for @.old - @.jvm - @.js (cond ffi.on_node_js? - (..exit_node_js! code) - - ffi.on_browser? - (..exit_browser! code) - - ... else - (..default_exit! code)) - @.python (os::_exit code) - @.lua (os/exit code) - @.ruby (Kernel::exit code) - ... @.php (..exit [code]) - ... @.scheme (..exit [code]) - ))))) diff --git a/stdlib/source/library/lux/world/shell.lux b/stdlib/source/library/lux/world/shell.lux index 9c6b37c12..f9d7a6fd6 100644 --- a/stdlib/source/library/lux/world/shell.lux +++ b/stdlib/source/library/lux/world/shell.lux @@ -14,9 +14,7 @@ ["?" policy (.only Context Safety Safe)]] [concurrency ["[0]" atom (.only Atom)] - ["[0]" async (.only Async)]] - [parser - [environment (.only Environment)]]] + ["[0]" async (.only Async)]]] [data ["[0]" product] ["[0]" text (.only) @@ -31,7 +29,9 @@ [number (.only hex) ["n" nat]]]]] [// - [file (.only Path)]]) + [file (.only Path)] + [environment + [\\parser (.only Environment)]]]) (type .public Exit Int) -- cgit v1.2.3