runtime¶
In [ ]:
open rust
open rust_operators
open sm'_operators
In [ ]:
//// test
open testing
open file_system_operators
runtime¶
split_args¶
In [ ]:
let split_args (args : string) : result (array_base string) string =
open parsing
inl esc = [ '\\'; '`' ]
inl quotes = [ '"' ]
inl special = esc ++ quotes
inl p_esc_char c =
p_char c >>. any_char () |>> fun c' => $'$"{!c}{!c'}"'
inl p_word = special |> none_of |>> sm'.obj_to_string
inl p_plain = special ++ [ ' ' ] |> none_of |> many1_chars
inl p_text = p_word |> many1_strings
inl p_esc = esc |> listm.map p_esc_char |> choice
inl p_quoted = (p_word <|> p_esc) |> many |>> sm'.concat_list ""
inl p_quoted_all = p_quoted |> between (p_char '"') (p_char '"')
inl p_esc_root = p_esc >>% "" >>. (p_word |> many) |>> sm'.concat_list ""
inl p_content = p_plain <|> p_quoted_all <|> p_esc_root
inl p_args = spaces1 () |> sep_by p_content
args
|> parse p_args
|> resultm.map (fst >> listm'.box >> listm'.to_array')
In [ ]:
//// test
///! fsharp
////! cuda // Only stack allocated primitive types (i8,i16,i32,i64 and u8,u16,u32,u64 and f32,f64 and bool) are allowed in CuPy arrays.
///! rust
///! typescript
///! python
[
"a b c",
;[ "a"; "b"; "c" ]
"e f \"g h\" i",
;[ "e"; "f"; "g h"; "i" ]
"\"j k\" \"l\" \"m\"",
;[ "j k"; "l"; "m" ]
"s -t \"u \`\"v\`\" w\"",
;[ "s"; "-t"; "u \`\"v\`\" w" ]
"n -o \"p \\\"q\\\" r\"",
;[ "n"; "-o"; "p \\\"q\\\" r" ]
"r -s \"t \\\"u\\\"\"",
;[ "r"; "-s"; "t \\\"u\\\"" ]
$'$"x -y \\\"$z -a \'(b=\\\\\\"c-id=)[a-fA-F0-9]{{8}}\', {{ \`$_[1] + \`$d++ }}\\\""',
;[ "x"; "-y"; "$z -a '(b=\\\"c-id=)[a-fA-F0-9]{8}', { `$_[1] + `$d++ }" ]
"e -f \"$g -h '(i=`\"j-id=)[a-fA-F0-9]{8}', { `$_[1] + `$k++ }\"",
;[ "e"; "-f"; "$g -h '(i=`\"j-id=)[a-fA-F0-9]{8}', { `$_[1] + `$k++ }" ]
$'$"--l \\\\\\"\'\'\' m \'\'\'\\\\\\" "',
;[ "--l"; "''' m '''" ]
$'$"n --o --p q --r \\\"s:/t u/v.w\\\" --x \\\"y:/z.a\\\" --b c.d \\\"\\\\e{{f-g}}\\\" h.i \\\"j (k)\\\""',
;[ "n"; "--o"; "--p"; "q"; "--r"; "s:/t u/v.w"; "--x"; "y:/z.a"; "--b"; "c.d"; "\\e{f-g}"; "h.i"; "j (k)" ]
$'\@$"l ""m n:\\o.p"""',
;[ "l"; "m n:\\o.p" ]
]
|> _assert_fn split_args
.rs output: 00:00:00 v #1 _assert_fn / { input = a b c } __assert_eq' / actual: Array(MutCell(["a", "b", "c"])) / expected: Array(MutCell(["a", "b", "c"])) 00:00:00 v #2 _assert_fn / { input = e f "g h" i } __assert_eq' / actual: Array(MutCell(["e", "f", "g h", "i"])) / expected: Array(MutCell(["e", "f", "g h", "i"])) 00:00:00 v #3 _assert_fn / { input = "j k" "l" "m" } __assert_eq' / actual: Array(MutCell(["j k", "l", "m"])) / expected: Array(MutCell(["j k", "l", "m"])) 00:00:00 v #4 _assert_fn / { input = s -t "u `"v`" w" } __assert_eq' / actual: Array(MutCell(["s", "-t", "u `"v`" w"])) / expected: Array(MutCell(["s", "-t", "u `"v`" w"])) 00:00:00 v #5 _assert_fn / { input = n -o "p \"q\" r" } __assert_eq' / actual: Array(MutCell(["n", "-o", "p \"q\" r"])) / expected: Array(MutCell(["n", "-o", "p \"q\" r"])) 00:00:00 v #6 _assert_fn / { input = r -s "t \"u\"" } __assert_eq' / actual: Array(MutCell(["r", "-s", "t \"u\""])) / expected: Array(MutCell(["r", "-s", "t \"u\""])) 00:00:00 v #7 _assert_fn / { input = x -y "$z -a '(b=\"c-id=)[a-fA-F0-9]{8}', { `$_[1] + `$d++ }" } __assert_eq' / actual: Array(MutCell(["x", "-y", "$z -a '(b=\"c-id=)[a-fA-F0-9]{8}', { `$_[1] + `$d++ }"])) / expected: Array(MutCell(["x", "-y", "$z -a '(b=\"c-id=)[a-fA-F0-9]{8}', { `$_[1] + `$d++ }"])) 00:00:00 v #8 _assert_fn / { input = e -f "$g -h '(i=`"j-id=)[a-fA-F0-9]{8}', { `$_[1] + `$k++ }" } __assert_eq' / actual: Array(MutCell(["e", "-f", "$g -h '(i=`"j-id=)[a-fA-F0-9]{8}', { `$_[1] + `$k++ }"])) / expected: Array(MutCell(["e", "-f", "$g -h '(i=`"j-id=)[a-fA-F0-9]{8}', { `$_[1] + `$k++ }"])) 00:00:00 v #9 _assert_fn / { input = --l \"''' m '''\" } __assert_eq' / actual: Array(MutCell(["--l", "''' m '''"])) / expected: Array(MutCell(["--l", "''' m '''"])) 00:00:00 v #10 _assert_fn / { input = n --o --p q --r "s:/t u/v.w" --x "y:/z.a" --b c.d "\e{f-g}" h.i "j (k)" } __assert_eq' / actual: Array(MutCell(["n", "--o", "--p", "q", "--r", "s:/t u/v.w", "--x", "y:/z.a", "--b", "c.d", "\e{f-g}", "h.i", "j (k)"])) / expected: Array(MutCell(["n", "--o", "--p", "q", "--r", "s:/t u/v.w", "--x", "y:/z.a", "--b", "c.d", "\e{f-g}", "h.i", "j (k)"])) 00:00:00 v #11 _assert_fn / { input = l "m n:\o.p" } __assert_eq' / actual: Array(MutCell(["l", "m n:\o.p"])) / expected: Array(MutCell(["l", "m n:\o.p"])) .ts output: 00:00:00 v #1 _assert_fn / { input = a b c } __assert_eq' / actual: a,b,c / expected: a,b,c 00:00:00 v #2 _assert_fn / { input = e f "g h" i } __assert_eq' / actual: e,f,g h,i / expected: e,f,g h,i 00:00:00 v #3 _assert_fn / { input = "j k" "l" "m" } __assert_eq' / actual: j k,l,m / expected: j k,l,m 00:00:00 v #4 _assert_fn / { input = s -t "u `"v`" w" } __assert_eq' / actual: s,-t,u `"v`" w / expected: s,-t,u `"v`" w 00:00:00 v #5 _assert_fn / { input = n -o "p \"q\" r" } __assert_eq' / actual: n,-o,p \"q\" r / expected: n,-o,p \"q\" r 00:00:00 v #6 _assert_fn / { input = r -s "t \"u\"" } __assert_eq' / actual: r,-s,t \"u\" / expected: r,-s,t \"u\" 00:00:00 v #7 _assert_fn / { input = x -y "$z -a '(b=\"c-id=)[a-fA-F0-9]{8}', { `$_[1] + `$d++ }" } __assert_eq' / actual: x,-y,$z -a '(b=\"c-id=)[a-fA-F0-9]{8}', { `$_[1] + `$d++ } / expected: x,-y,$z -a '(b=\"c-id=)[a-fA-F0-9]{8}', { `$_[1] + `$d++ } 00:00:00 v #8 _assert_fn / { input = e -f "$g -h '(i=`"j-id=)[a-fA-F0-9]{8}', { `$_[1] + `$k++ }" } __assert_eq' / actual: e,-f,$g -h '(i=`"j-id=)[a-fA-F0-9]{8}', { `$_[1] + `$k++ } / expected: e,-f,$g -h '(i=`"j-id=)[a-fA-F0-9]{8}', { `$_[1] + `$k++ } 00:00:00 v #9 _assert_fn / { input = --l \"''' m '''\" } __assert_eq' / actual: --l,''' m ''' / expected: --l,''' m ''' 00:00:00 v #10 _assert_fn / { input = n --o --p q --r "s:/t u/v.w" --x "y:/z.a" --b c.d "\e{f-g}" h.i "j (k)" } __assert_eq' / actual: n,--o,--p,q,--r,s:/t u/v.w,--x,y:/z.a,--b,c.d,\e{f-g},h.i,j (k) / expected: n,--o,--p,q,--r,s:/t u/v.w,--x,y:/z.a,--b,c.d,\e{f-g},h.i,j (k) 00:00:00 v #11 _assert_fn / { input = l "m n:\o.p" } __assert_eq' / actual: l,m n:\o.p / expected: l,m n:\o.p .py output: 00:00:00 v #1 _assert_fn / { input = a b c } __assert_eq' / actual: ['a', 'b', 'c'] / expected: ['a', 'b', 'c'] 00:00:00 v #2 _assert_fn / { input = e f "g h" i } __assert_eq' / actual: ['e', 'f', 'g h', 'i'] / expected: ['e', 'f', 'g h', 'i'] 00:00:00 v #3 _assert_fn / { input = "j k" "l" "m" } __assert_eq' / actual: ['j k', 'l', 'm'] / expected: ['j k', 'l', 'm'] 00:00:00 v #4 _assert_fn / { input = s -t "u `"v`" w" } __assert_eq' / actual: ['s', '-t', 'u `"v`" w'] / expected: ['s', '-t', 'u `"v`" w'] 00:00:00 v #5 _assert_fn / { input = n -o "p \"q\" r" } __assert_eq' / actual: ['n', '-o', 'p \\"q\\" r'] / expected: ['n', '-o', 'p \\"q\\" r'] 00:00:00 v #6 _assert_fn / { input = r -s "t \"u\"" } __assert_eq' / actual: ['r', '-s', 't \\"u\\"'] / expected: ['r', '-s', 't \\"u\\"'] 00:00:00 v #7 _assert_fn / { input = x -y "$z -a '(b=\"c-id=)[a-fA-F0-9]{8}', { `$_[1] + `$d++ }" } __assert_eq' / actual: ['x', '-y', '$z -a \'(b=\\"c-id=)[a-fA-F0-9]{8}\', { `$_[1] + `$d++ }'] / expected: ['x', '-y', '$z -a \'(b=\\"c-id=)[a-fA-F0-9]{8}\', { `$_[1] + `$d++ }'] 00:00:00 v #8 _assert_fn / { input = e -f "$g -h '(i=`"j-id=)[a-fA-F0-9]{8}', { `$_[1] + `$k++ }" } __assert_eq' / actual: ['e', '-f', '$g -h \'(i=`"j-id=)[a-fA-F0-9]{8}\', { `$_[1] + `$k++ }'] / expected: ['e', '-f', '$g -h \'(i=`"j-id=)[a-fA-F0-9]{8}\', { `$_[1] + `$k++ }'] 00:00:00 v #9 _assert_fn / { input = --l \"''' m '''\" } __assert_eq' / actual: ['--l', "''' m '''"] / expected: ['--l', "''' m '''"] 00:00:00 v #10 _assert_fn / { input = n --o --p q --r "s:/t u/v.w" --x "y:/z.a" --b c.d "\e{f-g}" h.i "j (k)" } __assert_eq' / actual: ['n', '--o', '--p', 'q', '--r', 's:/t u/v.w', '--x', 'y:/z.a', '--b', 'c.d', '\\e{f-g}', 'h.i', 'j (k)'] / expected: ['n', '--o', '--p', 'q', '--r', 's:/t u/v.w', '--x', 'y:/z.a', '--b', 'c.d', '\\e{f-g}', 'h.i', 'j (k)'] 00:00:00 v #11 _assert_fn / { input = l "m n:\o.p" } __assert_eq' / actual: ['l', 'm n:\\o.p'] / expected: ['l', 'm n:\\o.p']
.fsx output: 00:00:00 v #1 _assert_fn / { input = a b c } __assert_eq' / actual: [|"a"; "b"; "c"|] / expected: [|"a"; "b"; "c"|] 00:00:00 v #2 _assert_fn / { input = e f "g h" i } __assert_eq' / actual: [|"e"; "f"; "g h"; "i"|] / expected: [|"e"; "f"; "g h"; "i"|] 00:00:00 v #3 _assert_fn / { input = "j k" "l" "m" } __assert_eq' / actual: [|"j k"; "l"; "m"|] / expected: [|"j k"; "l"; "m"|] 00:00:00 v #4 _assert_fn / { input = s -t "u `"v`" w" } __assert_eq' / actual: [|"s"; "-t"; "u `"v`" w"|] / expected: [|"s"; "-t"; "u `"v`" w"|] 00:00:00 v #5 _assert_fn / { input = n -o "p \"q\" r" } __assert_eq' / actual: [|"n"; "-o"; "p \"q\" r"|] / expected: [|"n"; "-o"; "p \"q\" r"|] 00:00:00 v #6 _assert_fn / { input = r -s "t \"u\"" } __assert_eq' / actual: [|"r"; "-s"; "t \"u\""|] / expected: [|"r"; "-s"; "t \"u\""|] 00:00:00 v #7 _assert_fn / { input = x -y "$z -a '(b=\"c-id=)[a-fA-F0-9]{8}', { `$_[1] + `$d++ }" } __assert_eq' / actual: [|"x"; "-y"; "$z -a '(b=\"c-id=)[a-fA-F0-9]{8}', { `$_[1] + `$d++ }"|] / expected: [|"x"; "-y"; "$z -a '(b=\"c-id=)[a-fA-F0-9]{8}', { `$_[1] + `$d++ }"|] 00:00:00 v #8 _assert_fn / { input = e -f "$g -h '(i=`"j-id=)[a-fA-F0-9]{8}', { `$_[1] + `$k++ }" } __assert_eq' / actual: [|"e"; "-f"; "$g -h '(i=`"j-id=)[a-fA-F0-9]{8}', { `$_[1] + `$k++ }"|] / expected: [|"e"; "-f"; "$g -h '(i=`"j-id=)[a-fA-F0-9]{8}', { `$_[1] + `$k++ }"|] 00:00:00 v #9 _assert_fn / { input = --l \"''' m '''\" } __assert_eq' / actual: [|"--l"; "''' m '''"|] / expected: [|"--l"; "''' m '''"|] 00:00:00 v #10 _assert_fn / { input = n --o --p q --r "s:/t u/v.w" --x "y:/z.a" --b c.d "\e{f-g}" h.i "j (k)" } __assert_eq' / actual: [|"n"; "--o"; "--p"; "q"; "--r"; "s:/t u/v.w"; "--x"; "y:/z.a"; "--b"; "c.d"; "\e{f-g}"; "h.i"; "j (k)"|] / expected: [|"n"; "--o"; "--p"; "q"; "--r"; "s:/t u/v.w"; "--x"; "y:/z.a"; "--b"; "c.d"; "\e{f-g}"; "h.i"; "j (k)"|] 00:00:00 v #11 _assert_fn / { input = l "m n:\o.p" } __assert_eq' / actual: [|"l"; "m n:\o.p"|] / expected: [|"l"; "m n:\o.p"|]
split_command¶
In [ ]:
let split_command (command : string) : result (string * option string) string =
open parsing
inl quotes = [ '"'; '\'' ]
inl p_quoted_char = quotes |> listm.map p_char |> choice
inl normalize = function '\\' => '/' | c => c
inl p_quoted = quotes |> none_of |>> normalize |> many_chars |> between p_quoted_char p_quoted_char
inl p_unquoted = quotes ++ [ ' ' ] |> none_of |>> normalize |> many1_chars
inl p_path = p_quoted <|> p_unquoted <|> eof () >>% "" .>> spaces ()
inl p_args = p_char ' ' |> opt >>. (any_char () |> many1_chars)
inl p_command = p_path .>>. (p_args |> opt)
command
|> parse p_command
|> resultm.map fst
In [ ]:
//// test
///! fsharp
////! cuda // Only stack allocated primitive types (i8,i16,i32,i64 and u8,u16,u32,u64 and f32,f64 and bool) are allowed in CuPy arrays.
///! rust
///! typescript
///! python
[
"",
("", None)
"/a/b/c",
("/a/b/c", None)
"d e.f",
("d", Some "e.f")
$'"""..\\..\\g.h i.j k.l"""',
("../../g.h", Some "i.j k.l")
$'\@"m:\\n\\o.p ""q.r s.t"""',
("m:/n/o.p", Some $'\@"""q.r s.t"""')
$'\@"""..\\..\\u v\\w.x"" ""y z.a"" b.c"',
("../../u v/w.x", Some $'\@"""y z.a"" b.c"')
$'\@"""..\\..\\d e.f"" -g \\\\""h i\\\\"""',
("../../d e.f", Some $'\@"-g \\\\""h i\\\\"""')
$'\@"..\\..\\j k.l -m \\\\""n o\\\\"""',
("../../j", Some $'\@"k.l -m \\\\""n o\\\\"""')
]
|> _assert_fn split_command
.rs output: 00:00:00 v #1 _assert_fn / { input = } __assert_eq' / actual: ("", US1_1) / expected: ("", US1_1) 00:00:00 v #2 _assert_fn / { input = /a/b/c } __assert_eq' / actual: ("/a/b/c", US1_1) / expected: ("/a/b/c", US1_1) 00:00:00 v #3 _assert_fn / { input = d e.f } __assert_eq' / actual: ("d", US1_0("e.f")) / expected: ("d", US1_0("e.f")) 00:00:00 v #4 _assert_fn / { input = ..\..\g.h i.j k.l } __assert_eq' / actual: ("../../g.h", US1_0("i.j k.l")) / expected: ("../../g.h", US1_0("i.j k.l")) 00:00:00 v #5 _assert_fn / { input = m:\n\o.p "q.r s.t" } __assert_eq' / actual: ("m:/n/o.p", US1_0(""q.r s.t"")) / expected: ("m:/n/o.p", US1_0(""q.r s.t"")) 00:00:00 v #6 _assert_fn / { input = "..\..\u v\w.x" "y z.a" b.c } __assert_eq' / actual: ("../../u v/w.x", US1_0(""y z.a" b.c")) / expected: ("../../u v/w.x", US1_0(""y z.a" b.c")) 00:00:00 v #7 _assert_fn / { input = "..\..\d e.f" -g \\"h i\\" } __assert_eq' / actual: ("../../d e.f", US1_0("-g \\"h i\\"")) / expected: ("../../d e.f", US1_0("-g \\"h i\\"")) 00:00:00 v #8 _assert_fn / { input = ..\..\j k.l -m \\"n o\\" } __assert_eq' / actual: ("../../j", US1_0("k.l -m \\"n o\\"")) / expected: ("../../j", US1_0("k.l -m \\"n o\\"")) .ts output: 00:00:00 v #1 _assert_fn / { input = } __assert_eq' / actual: ,US1_1 / expected: ,US1_1 00:00:00 v #2 _assert_fn / { input = /a/b/c } __assert_eq' / actual: /a/b/c,US1_1 / expected: /a/b/c,US1_1 00:00:00 v #3 _assert_fn / { input = d e.f } __assert_eq' / actual: d,US1_0 e.f / expected: d,US1_0 e.f 00:00:00 v #4 _assert_fn / { input = ..\..\g.h i.j k.l } __assert_eq' / actual: ../../g.h,US1_0 (i.j k.l) / expected: ../../g.h,US1_0 (i.j k.l) 00:00:00 v #5 _assert_fn / { input = m:\n\o.p "q.r s.t" } __assert_eq' / actual: m:/n/o.p,US1_0 ("q.r s.t") / expected: m:/n/o.p,US1_0 ("q.r s.t") 00:00:00 v #6 _assert_fn / { input = "..\..\u v\w.x" "y z.a" b.c } __assert_eq' / actual: ../../u v/w.x,US1_0 ("y z.a" b.c) / expected: ../../u v/w.x,US1_0 ("y z.a" b.c) 00:00:00 v #7 _assert_fn / { input = "..\..\d e.f" -g \\"h i\\" } __assert_eq' / actual: ../../d e.f,US1_0 (-g \\"h i\\") / expected: ../../d e.f,US1_0 (-g \\"h i\\") 00:00:00 v #8 _assert_fn / { input = ..\..\j k.l -m \\"n o\\" } __assert_eq' / actual: ../../j,US1_0 (k.l -m \\"n o\\") / expected: ../../j,US1_0 (k.l -m \\"n o\\") .py output: 00:00:00 v #1 _assert_fn / { input = } __assert_eq' / actual: ('', US1_1) / expected: ('', US1_1) 00:00:00 v #2 _assert_fn / { input = /a/b/c } __assert_eq' / actual: ('/a/b/c', US1_1) / expected: ('/a/b/c', US1_1) 00:00:00 v #3 _assert_fn / { input = d e.f } __assert_eq' / actual: ('d', US1_0 "e.f") / expected: ('d', US1_0 "e.f") 00:00:00 v #4 _assert_fn / { input = ..\..\g.h i.j k.l } __assert_eq' / actual: ('../../g.h', US1_0 ("i.j k.l")) / expected: ('../../g.h', US1_0 ("i.j k.l")) 00:00:00 v #5 _assert_fn / { input = m:\n\o.p "q.r s.t" } __assert_eq' / actual: ('m:/n/o.p', US1_0 (""q.r s.t"")) / expected: ('m:/n/o.p', US1_0 (""q.r s.t"")) 00:00:00 v #6 _assert_fn / { input = "..\..\u v\w.x" "y z.a" b.c } __assert_eq' / actual: ('../../u v/w.x', US1_0 (""y z.a" b.c")) / expected: ('../../u v/w.x', US1_0 (""y z.a" b.c")) 00:00:00 v #7 _assert_fn / { input = "..\..\d e.f" -g \\"h i\\" } __assert_eq' / actual: ('../../d e.f', US1_0 ("-g \\"h i\\"")) / expected: ('../../d e.f', US1_0 ("-g \\"h i\\"")) 00:00:00 v #8 _assert_fn / { input = ..\..\j k.l -m \\"n o\\" } __assert_eq' / actual: ('../../j', US1_0 ("k.l -m \\"n o\\"")) / expected: ('../../j', US1_0 ("k.l -m \\"n o\\""))
.fsx output: 00:00:00 v #1 _assert_fn / { input = } __assert_eq' / actual: struct ("", US1_1) / expected: struct ("", US1_1) 00:00:00 v #2 _assert_fn / { input = /a/b/c } __assert_eq' / actual: struct ("/a/b/c", US1_1) / expected: struct ("/a/b/c", US1_1) 00:00:00 v #3 _assert_fn / { input = d e.f } __assert_eq' / actual: struct ("d", US1_0 "e.f") / expected: struct ("d", US1_0 "e.f") 00:00:00 v #4 _assert_fn / { input = ..\..\g.h i.j k.l } __assert_eq' / actual: struct ("../../g.h", US1_0 "i.j k.l") / expected: struct ("../../g.h", US1_0 "i.j k.l") 00:00:00 v #5 _assert_fn / { input = m:\n\o.p "q.r s.t" } __assert_eq' / actual: struct ("m:/n/o.p", US1_0 ""q.r s.t"") / expected: struct ("m:/n/o.p", US1_0 ""q.r s.t"") 00:00:00 v #6 _assert_fn / { input = "..\..\u v\w.x" "y z.a" b.c } __assert_eq' / actual: struct ("../../u v/w.x", US1_0 ""y z.a" b.c") / expected: struct ("../../u v/w.x", US1_0 ""y z.a" b.c") 00:00:00 v #7 _assert_fn / { input = "..\..\d e.f" -g \\"h i\\" } __assert_eq' / actual: struct ("../../d e.f", US1_0 "-g \\"h i\\"") / expected: struct ("../../d e.f", US1_0 "-g \\"h i\\"") 00:00:00 v #8 _assert_fn / { input = ..\..\j k.l -m \\"n o\\" } __assert_eq' / actual: struct ("../../j", US1_0 "k.l -m \\"n o\\"") / expected: struct ("../../j", US1_0 "k.l -m \\"n o\\"")
execution_line¶
In [ ]:
type execution_line =
{
process_id : int
line : string
error : bool
}
rust¶
process_child¶
In [ ]:
nominal process_child =
`(
global "#if FABLE_COMPILER\n[<Fable.Core.Erase; Fable.Core.Emit(\"std::process::Child\")>]\n#endif\ntype std_process_Child = class end"
$'' : $'std_process_Child'
)
process_child_stdin¶
In [ ]:
nominal process_child_stdin =
`(
global "#if FABLE_COMPILER\n[<Fable.Core.Erase; Fable.Core.Emit(\"std::process::ChildStdin\")>]\n#endif\ntype std_process_ChildStdin = class end"
$'' : $'std_process_ChildStdin'
)
inl process_child_stdin
(child : rust.ref (rust.mut' process_child))
: rust.ref (rust.mut' (optionm'.option' process_child_stdin))
=
!\\(child, $'"&mut $0.stdin"')
runtime¶
execution_options¶
In [ ]:
type execution_options =
{
command : string
cancellation_token : optionm'.option' threading.cancellation_token
environment_variables : array_base (string * string)
on_line : optionm'.option' (execution_line -> async.async ())
stdin : optionm'.option' (threading.arc (threading.mutex process_child_stdin) -> ())
trace : bool
working_directory : optionm'.option' string
}
inl execution_options (fn : execution_options -> execution_options) : execution_options =
{
command = ""
cancellation_token = None |> optionm'.box
environment_variables = ;[]
on_line = None |> optionm'.box
stdin = None |> optionm'.box
trace = true
working_directory = None |> optionm'.box
}
|> fn
rust¶
process_child_stderr¶
In [ ]:
nominal process_child_stderr =
`(
global "#if FABLE_COMPILER\n[<Fable.Core.Erase; Fable.Core.Emit(\"std::process::ChildStderr\")>]\n#endif\ntype std_process_ChildStderr = class end"
$'' : $'std_process_ChildStderr'
)
inl process_child_stderr
(child : rust.ref (rust.mut' process_child))
: rust.ref (rust.mut' (optionm'.option' process_child_stderr))
=
!\\(child, $'"&mut $0.stderr"')
process_child_stdout¶
In [ ]:
nominal process_child_stdout =
`(
global "#if FABLE_COMPILER\n[<Fable.Core.Erase; Fable.Core.Emit(\"std::process::ChildStdout\")>]\n#endif\ntype std_process_ChildStdout = class end"
$'' : $'std_process_ChildStdout'
)
inl process_child_stdout
(child : rust.ref (rust.mut' process_child))
: rust.ref (rust.mut' (optionm'.option' process_child_stdout))
=
!\\(child, $'"&mut $0.stdout"')
process_command¶
In [ ]:
nominal process_command =
`(
global "#if FABLE_COMPILER\n[<Fable.Core.Erase; Fable.Core.Emit(\"std::process::Command\")>]\n#endif\ntype std_process_Command = class end"
$'' : $'std_process_Command'
)
process_stdio¶
In [ ]:
nominal process_stdio =
`(
global "#if FABLE_COMPILER\n[<Fable.Core.Erase; Fable.Core.Emit(\"std::process::Stdio\")>]\n#endif\ntype std_process_Stdio = class end"
$'' : $'std_process_Stdio'
)
process_output¶
In [ ]:
nominal process_output =
`(
global "#if FABLE_COMPILER\n[<Fable.Core.Erase; Fable.Core.Emit(\"std::process::Output\")>]\n#endif\ntype std_process_Output = class end"
$'' : $'std_process_Output'
)
process_exit_status¶
In [ ]:
nominal process_exit_status =
`(
global "#if FABLE_COMPILER\n[<Fable.Core.Erase; Fable.Core.Emit(\"std::process::ExitStatus\")>]\n#endif\ntype std_process_ExitStatus = class end"
$'' : $'std_process_ExitStatus'
)
process_output_status¶
In [ ]:
inl process_output_status (output : process_output) : process_exit_status =
!\\(output, $'"$0.status"')
process_exit_status_code¶
In [ ]:
inl process_exit_status_code (status : process_exit_status) : optionm'.option' i32 =
!\\(status, $'"$0.code()"')
stdin_write_all¶
In [ ]:
inl stdin_write_all (stdin : threading.mutex_guard process_child_stdin) (text : string) : () =
inl stream = text |> sm'.as_bytes
inl stdin = join stdin
(!\($'"true; let mut !stdin = !stdin"') : bool) |> ignore
(!\\(stdin, $'"true; std::io::Write::write_all(&mut *$0, !stream).unwrap()"') : bool) |> ignore
stdin_flush¶
In [ ]:
inl stdin_flush (stdin : threading.mutex_guard process_child_stdin) : () =
inl stdin = join stdin
(!\($'"true; let mut !stdin = !stdin"') : bool) |> ignore
(!\\(stdin, $'"true; std::io::Write::flush(&mut *$0).unwrap()"') : bool) |> ignore
new_process_command¶
In [ ]:
inl new_process_command (file_name : string) : process_command =
!\\(file_name, $'"std::process::Command::new(&*$0)"')
process_stdio_piped¶
In [ ]:
inl process_stdio_piped () : process_stdio =
!\($'"std::process::Stdio::piped()"')
process_command_args¶
In [ ]:
inl process_command_args (args : am'.vec sm'.std_string) (c : process_command) : rust.ref (rust.mut' process_command) =
(!\($'"true; let mut !c = !c"') : bool) |> ignore
!\\((c, args), $'"std::process::Command::args(&mut $0, &*$1)"')
process_command_stdout¶
In [ ]:
inl process_command_stdout (stdio : process_stdio) (c : rust.ref (rust.mut' process_command)) : rust.ref (rust.mut' process_command) =
!\\(c, $'"std::process::Command::stdout($0, std::process::Stdio::piped())"')
process_command_stderr¶
In [ ]:
inl process_command_stderr (stdio : process_stdio) (c : rust.ref (rust.mut' process_command)) : rust.ref (rust.mut' process_command) =
!\\(c, $'"std::process::Command::stderr($0, std::process::Stdio::piped())"')
process_command_stdin¶
In [ ]:
inl process_command_stdin (stdio : process_stdio) (c : rust.ref (rust.mut' process_command)) : rust.ref (rust.mut' process_command) =
!\\(c, $'"std::process::Command::stdin($0, std::process::Stdio::piped())"')
process_command_current_dir¶
In [ ]:
inl process_command_current_dir
(dir : string)
(c : rust.ref (rust.mut' process_command))
: rust.ref (rust.mut' process_command)
=
!\\(dir, $'"std::process::Command::current_dir(!c, &*$0)"')
process_command_env¶
In [ ]:
inl process_command_env
(key : string)
(value : string)
(c : rust.ref (rust.mut' process_command))
: rust.ref (rust.mut' process_command)
=
!\\((key, value), $'"std::process::Command::env(!c, &*$0, &*$1)"')
process_command_spawn¶
In [ ]:
inl process_command_spawn
(c : rust.ref (rust.mut' process_command))
: resultm.result' process_child stream.io_error
=
!\\(c, $'"std::process::Command::spawn($0)"')
child_wait_with_output¶
In [ ]:
inl child_wait_with_output
(child : process_child)
: resultm.result' process_output stream.io_error
=
!\\(child, $'"$0.wait_with_output()"')
stdio_line¶
In [ ]:
inl stdio_line
(stdio : result () ())
(trace' : bool)
(channel_sender : threading.arc (threading.mutex (threading.channel_sender sm'.std_string)))
(line : resultm.result' sm'.std_string stream.io_error)
: resultm.result' () sm'.std_string
=
inl highlight text =
$'$"\\u001b[4;7m{!text}\\u001b[0m"'
inl line =
match
line
|> resultm.map_error' sm'.format'
|> resultm.unbox'
with
| Ok line =>
inl line =
line
|> sm'.from_std_string
// |> sm'.as_bytes
// |> am'.slice_to_vec
|> sm'.encoding_encode' (sm'.encoding_utf8' ())
|> rust.cow_as_ref
|> sm'.str_from_utf8
// |> sm'.utf8_decode
|> resultm.unwrap'
|> sm'.ref_to_std_string
// String::from_utf8_lossy(line.as_bytes()).into()
inl line_log = line |> sm'.from_std_string
inl text =
match stdio with
| Ok () => $'$"> {!line_log}"'
| Error () => $'$"\! {!line_log}"'
if trace'
then trace Verbose (fun () => text) id
else text |> console.write_line
match stdio with
| Ok () => line
| Error () => line |> highlight |> sm'.to_std_string
| Error e =>
trace Critical
fun () => "runtime.stdio_line"
fun () => { trace' e }
e |> highlight |> sm'.to_std_string
channel_sender
|> threading.arc_mutex_lock
|> resultm.unwrap'
|> threading.mutex_guard_ref
|> threading.channel_send line
|> resultm.map_error' sm'.format'
command¶
In [ ]:
nominal command =
`(
global "#if FABLE_COMPILER\n[<Fable.Core.Erase; Fable.Core.Emit(\"clap::Command\")>]\n#endif\ntype clap_Command = class end"
$'' : $'clap_Command'
)
new_command¶
In [ ]:
inl new_command (s : rust.static_ref sm'.str) : command =
!\\(s, $'"clap::Command::new($0)"')
In [ ]:
//// test
///! rust -d clap
##"command"
|> new_command
|> sm'.format_pretty
|> _assert sm'.contains "\"command\""
__assert / actual: ""command"" / expected: "Command { name: "command", long_flag: None, short_flag: None, display_name: None, bin_name: None, author: None, version: None, long_version: None, about: None, long_about: None, before_help: None, before_long_help: None, after_help: None, after_long_help: None, aliases: [], short_flag_aliases: [], long_flag_aliases: [], usage_str: None, usage_name: None, help_str: None, disp_ord: None, template: None, settings: AppFlags( 0, ), g_settings: AppFlags( 0, ), args: MKeyMap { args: [], keys: [], }, subcommands: [], groups: [], current_help_heading: None, current_disp_ord: Some( 0, ), subcommand_value_name: None, subcommand_heading: None, external_value_parser: None, long_help_exists: false, deferred: None, app_ext: Extensions { extensions: FlatMap { keys: [], values: [], }, }, }"
arg¶
In [ ]:
nominal arg =
`(
global "#if FABLE_COMPILER\n[<Fable.Core.Erase; Fable.Core.Emit(\"clap::Arg\")>]\n#endif\ntype clap_Arg = class end"
$'' : $'clap_Arg'
)
new_arg¶
In [ ]:
inl new_arg (s : rust.static_ref sm'.str) : arg =
!\\(s, $'"clap::Arg::new($0)"')
In [ ]:
//// test
///! rust -d clap
##"arg"
|> new_arg
|> sm'.format_pretty
|> _assert sm'.contains "\"arg\""
__assert / actual: ""arg"" / expected: "Arg { id: "arg", help: None, long_help: None, action: None, value_parser: None, blacklist: [], settings: ArgFlags( 0, ), overrides: [], groups: [], requires: [], r_ifs: [], r_unless: [], short: None, long: None, aliases: [], short_aliases: [], disp_ord: None, val_names: [], num_vals: None, val_delim: None, default_vals: [], default_vals_ifs: [], terminator: None, index: None, help_heading: None, default_missing_vals: [], ext: Extensions { extensions: FlatMap { keys: [], values: [], }, }, }"
command_arg¶
In [ ]:
inl command_arg (arg : arg) (command : command) : command =
!\\((command, arg), $'"clap::Command::arg($0, $1)"')
arg_required¶
In [ ]:
inl arg_required (value : bool) (arg : arg) : arg =
!\\((arg, value), $'"$0.required($1)"')
arg_require_equals¶
In [ ]:
inl arg_require_equals (value : bool) (arg : arg) : arg =
!\\((arg, value), $'"$0.require_equals($1)"')
arg_default_value¶
In [ ]:
inl arg_default_value (value : string) (arg : arg) : arg =
inl value = #value
!\\((arg, value), $'"$0.default_value($1)"')
arg_default_missing_value¶
In [ ]:
inl arg_default_missing_value (value : string) (arg : arg) : arg =
inl value = #value
!\\((arg, value), $'"$0.default_missing_value($1)"')
arg_overrides_with¶
In [ ]:
inl arg_overrides_with (value : string) (arg : arg) : arg =
inl value = #value
!\\((arg, value), $'"$0.overrides_with($1)"')
arg_short¶
In [ ]:
inl arg_short (value : char) (arg : arg) : arg =
!\\((arg, value), $'"$0.short($1)"')
arg_long¶
In [ ]:
inl arg_long (value : rust.static_ref sm'.str) (arg : arg) : arg =
!\\((arg, value), $'"$0.long($1)"')
arg_value_names¶
In [ ]:
inl arg_value_names (values : array_base (rust.static_ref sm'.str)) (arg : arg) : arg =
inl values = values |> am'.to_vec
!\\((arg, values), $'"$0.value_names($1)"')
arg_num_args¶
In [ ]:
inl arg_num_args (value : i32) (arg : arg) : arg =
!\\((arg, value), $'"$0.num_args($1)"')
value_range¶
In [ ]:
nominal value_range =
`(
global "#if FABLE_COMPILER\n[<Fable.Core.Erase; Fable.Core.Emit(\"clap::builder::ValueRange\")>]\n#endif\ntype clap_builder_ValueRange = class end"
$'' : $'clap_builder_ValueRange'
)
new_value_range¶
In [ ]:
inl new_value_range inclusive start end : value_range =
inl len = 0i32 |> convert
inl start, end =
open am'
match start, end with
| Start start, End fn =>
start, len |> fn
| End start_fn, End end_fn =>
start_fn len, end_fn len
inl inclusive =
if inclusive
then "="
else ""
match start, end with
| start, end when end =. len => !\\(start, $'"clap::builder::ValueRange::new($0..)"')
| start, end => !\\((start, end), $'"clap::builder::ValueRange::new($0.." + !inclusive + "$1)"')
arg_num_args_range¶
In [ ]:
inl arg_num_args_range (value : value_range) (arg : arg) : arg =
!\\((arg, value), $'"$0.num_args($1)"')
arg_value_name¶
In [ ]:
inl arg_value_name (value : string) (arg : arg) : arg =
inl value = value |> sm'.as_str
!\\((arg, value), $'"$0.value_name($1)"')
value_parser¶
In [ ]:
nominal value_parser =
`(
global "#if FABLE_COMPILER\n[<Fable.Core.Erase; Fable.Core.Emit(\"clap::builder::ValueParser\")>]\n#endif\ntype clap_builder_ValueParser = class end"
$'' : $'clap_builder_ValueParser'
)
possible_value¶
In [ ]:
nominal possible_value =
`(
global "#if FABLE_COMPILER\n[<Fable.Core.Erase; Fable.Core.Emit(\"clap::builder::PossibleValue\")>]\n#endif\ntype clap_builder_PossibleValue = class end"
$'' : $'clap_builder_PossibleValue'
)
new_possible_value¶
In [ ]:
inl new_possible_value forall t. (x : t) : possible_value =
!\\(x, $'"clap::builder::PossibleValue::new(&**$0)"')
value_parser_path_buf¶
In [ ]:
inl value_parser_path_buf () : value_parser =
!\($'"clap::value_parser\!(std::path::PathBuf)"')
value_parser_expr¶
In [ ]:
inl value_parser_expr (expr : string) : value_parser =
!\($'"clap::value_parser\!(" + !expr + ").into()"')
arg_value_parser¶
In [ ]:
inl arg_value_parser (values : value_parser) (arg : arg) : arg =
!\\((arg, values), $'"$0.value_parser($1)"')
arg_action¶
In [ ]:
nominal arg_action' =
`(
global "#if FABLE_COMPILER\n[<Fable.Core.Erase; Fable.Core.Emit(\"clap::ArgAction\")>]\n#endif\ntype clap_ArgAction = class end"
$'' : $'clap_ArgAction'
)
union arg_action =
| Set
| Append
| SetTrue
| SetFalse
| Count
| Help
| HelpShort
| HelpLong
| Version
inl arg_action = function
| Set => !\($'"clap::ArgAction::Set"') : arg_action'
| Append => !\($'"clap::ArgAction::Append"') : arg_action'
| SetTrue => !\($'"clap::ArgAction::SetTrue"') : arg_action'
| SetFalse => !\($'"clap::ArgAction::SetFalse"') : arg_action'
| Count => !\($'"clap::ArgAction::Count"') : arg_action'
| Help => !\($'"clap::ArgAction::Help"') : arg_action'
| HelpShort => !\($'"clap::ArgAction::HelpShort"') : arg_action'
| HelpLong => !\($'"clap::ArgAction::HelpLong"') : arg_action'
| Version => !\($'"clap::ArgAction::Version"') : arg_action'
inl arg_action (value : arg_action) (arg : arg) : arg =
inl value = value |> arg_action
!\\((arg, value), $'"$0.action($1)"')
arg_index¶
In [ ]:
inl arg_index (value : i32) (arg : arg) : arg =
!\\((arg, value), $'"$0.index($1)"')
arg_matches¶
In [ ]:
nominal arg_matches =
`(
global "#if FABLE_COMPILER\n[<Fable.Core.Erase; Fable.Core.Emit(\"clap::ArgMatches\")>]\n#endif\ntype clap_ArgMatches = class end"
$'' : $'clap_ArgMatches'
)
command_get_matches¶
In [ ]:
inl command_get_matches (command : command) : arg_matches =
!\\(command, $'"clap::Command::get_matches($0)"')
command_get_matches_from¶
In [ ]:
inl command_get_matches_from (args : array_base string) (command : command) : arg_matches =
inl args = args |> am'.to_vec |> am'.vec_map sm'.to_std_string
!\\(command, $'"clap::Command::get_matches_from($0, !args)"')
command_args_override_self¶
In [ ]:
inl command_args_override_self (yes : bool) (command : command) : command =
!\\(command, $'"clap::Command::args_override_self($0, !yes)"')
command_init_arg¶
In [ ]:
inl command_init_arg (long, short) fn command =
command
|> command_arg (
##long
|> new_arg
|> arg_short short
|> arg_long ##long
|> fn
)
matches_get_one¶
In [ ]:
inl matches_get_one forall t. (x : string) (matches : arg_matches) : optionm'.option' t =
inl x = join x
inl x = x |> sm'.as_str
!\\((matches, x), $'"clap::ArgMatches::get_one(&$0, $1).cloned()"')
matches_get_flag¶
In [ ]:
inl matches_get_flag (x : string) (matches : arg_matches) : bool =
inl x = join x
inl x = x |> sm'.as_str
!\\((matches, x), $'"clap::ArgMatches::get_flag(&$0, $1)"')
matches_get_many¶
In [ ]:
inl matches_get_many forall t. (x : string) (matches : arg_matches) : optionm'.option' (am'.vec t) =
inl x = join x
inl x = x |> sm'.as_str
!\\((matches, x), $'"clap::ArgMatches::get_many(&$0, $1).map(|x| x.cloned().into_iter().collect())"')
matches_get_occurrences¶
In [ ]:
inl matches_get_occurrences (x : string) (matches : arg_matches) : optionm'.option' (array_base sm'.std_string) =
inl x = join x
inl x = x |> sm'.as_str
!\($'"clap::ArgMatches::get_occurrences(&!matches, !x).cloned()"')
matches_subcommand¶
In [ ]:
inl matches_subcommand (matches : arg_matches) : optionm'.option' (sm'.std_string * arg_matches) =
!\\((matches, sm'.ref_to_std_string), $'"clap::ArgMatches::subcommand(Box::leak(Box::new($0))).map(|(a, b)| ($1(a), b.clone()))"')
matches_values_of¶
In [ ]:
inl matches_values_of (x : string) (matches : arg_matches) : array_base sm'.std_string =
!\\((matches, x), $'"clap::ArgMatches::values_of($0, &*$1)"')
command_subcommand_required¶
In [ ]:
inl command_subcommand_required (value : bool) (command : command) : command =
!\\(command, $'"clap::Command::subcommand_required($0, !value)"')
command_subcommand¶
In [ ]:
inl command_subcommand (subcommand : command) (command : command) : command =
!\\(command, $'"clap::Command::subcommand($0, !subcommand)"')
value_parser_possible_values¶
In [ ]:
inl value_parser_possible_values (values : array_base string) : value_parser =
inl values =
values
|> am'.to_vec
|> am'.vec_map (sm'.to_std_string >> rust.new_box >> rust.box_leak >> new_possible_value)
!\\(values, $'"Into::<clap::builder::ValueParser>::into(clap::builder::PossibleValuesParser::new($0))"')
arg_union¶
In [ ]:
inl arg_union forall union_type. (fn : union_type -> ()) (arg : arg) : arg =
arg
|> arg_value_parser (
real reflection.get_union_fields_untag `union_type ()
|> fun x => x : _ (string * union_type)
|> listm.map fst
|> listm'.box
|> listm'.to_array'
|> value_parser_possible_values
)
In [ ]:
//// test
///! rust -d clap
##"command"
|> new_command
|> command_init_arg ("trace-level", 't') (
real arg_union `trace_level ignore
)
|> command_get_matches_from ;[ "_"; "--trace-level"; "Critical" ]
|> matches_get_one "trace-level"
|> optionm'.unwrap
|> sm'.from_std_string
|> reflection.union_try_pick
|> optionm.value
|> _assert_eq Critical
__assert_eq / actual: US1_4 / expected: US1_4
command_debug_assert¶
In [ ]:
inl command_debug_assert (command : command) : () =
!\\(command, $'"clap::Command::debug_assert($0)"')
fsharp¶
process¶
In [ ]:
nominal process = $'System.Diagnostics.Process'
process_start_info¶
In [ ]:
nominal process_start_info = $'System.Diagnostics.ProcessStartInfo'
data_received_event_args¶
In [ ]:
nominal data_received_event_args = $'System.Diagnostics.DataReceivedEventArgs'
new_process¶
In [ ]:
inl new_process (process_start_info : process_start_info) : process =
$'new `process (StartInfo = !process_start_info)'
process_start¶
In [ ]:
inl process_start (process : process) : bool =
$'!process.Start' ()
process_exit_code¶
In [ ]:
inl process_exit_code (process : process) : i32 =
$'!process.ExitCode'
process_id¶
In [ ]:
inl process_id (process : process) : i32 =
$'!process.Id'
process_has_exited¶
In [ ]:
inl process_has_exited (process : process) : bool =
run_target function
| Fsharp (Native) => fun () =>
$'!process.HasExited'
| _ => fun () => null ()
process_kill¶
In [ ]:
inl process_kill (process : process) : () =
run_target function
| Fsharp (Native) => fun () =>
$'!process.Kill' ()
| _ => fun () => ()
process_begin_error_read_line¶
In [ ]:
inl process_begin_error_read_line (process : process) : () =
$'!process.BeginErrorReadLine' ()
process_begin_output_read_line¶
In [ ]:
inl process_begin_output_read_line (process : process) : () =
$'!process.BeginOutputReadLine' ()
process_add_output_data_received¶
In [ ]:
inl process_add_output_data_received fn (process : process) : () =
$'!process.OutputDataReceived.Add !fn '
process_add_error_data_received¶
In [ ]:
inl process_add_error_data_received fn (process : process) : () =
$'!process.ErrorDataReceived.Add !fn '
process_wait_for_exit_async¶
In [ ]:
inl process_wait_for_exit_async (ct : threading.cancellation_token) (process : process) : async.task () =
$'!process.WaitForExitAsync !ct '
event_data¶
In [ ]:
inl event_data (e : data_received_event_args) : string =
$'!e.Data'
execute_with_options_async¶
In [ ]:
let execute_with_options_async (options : execution_options) : _ (i32 * string) =
run_target_args (fun () => options) function
| Fsharp (Native) => fun options =>
fun () =>
inl file_name, arguments = options.command |> split_command |> resultm.get
inl working_directory = options.working_directory |> optionm'.unbox |> optionm'.default_value ""
trace Debug
fun () => "runtime.execute_with_options_async"
fun () => { file_name arguments options }
inl utf8 = sm'.encoding_utf8 ()
inl arguments = arguments |> optionm'.default_value ""
$'let start_info = System.Diagnostics.ProcessStartInfo ('
$' Arguments = !arguments,'
$' StandardOutputEncoding = !utf8,'
$' WorkingDirectory = !working_directory,'
$' FileName = !file_name,'
$' CreateNoWindow = true,'
$' RedirectStandardError = true,'
$' RedirectStandardOutput = true,'
$' UseShellExecute = false'
$')'
inl start_info : process_start_info = $'start_info'
inl environment_variables = join options.environment_variables
(a environment_variables : _ i32 _)
|> am.iter fun key, value =>
$'!start_info.EnvironmentVariables.[!key] <- !value '
inl proc = start_info |> new_process |> use
inl output : _ string = threading.new_concurrent_stack ()
inl event error (e : data_received_event_args) = async.new_async fun () =>
inl data = e |> event_data
if data <> null () then
match options.on_line |> optionm'.unbox with
| Some on_line =>
on_line
{
process_id = proc |> process_id
line = data
error = error
}
|> async.do
| None => ()
inl text =
if error
then $'$"\! {!data}"'
else $'$"> {!data}"'
if options.trace
then trace Verbose (fun () => text) id
else text |> console.write_line
inl l = if error then $'"\\u001b[7;4m"' else ""
inl r = if error then $'"\\u001b[0m"' else ""
output |> threading.concurrent_stack_push $'$"{!l}{!data}{!r}"'
proc |> process_add_output_data_received (event false >> async.start_immediate)
proc |> process_add_error_data_received (event true >> async.start_immediate)
if proc |> process_start |> not
then failwith $'$"runtime.execute_with_options_async / process_start error"'
proc |> process_begin_error_read_line
proc |> process_begin_output_read_line
inl ct =
options.cancellation_token
|> optionm'.unbox
|> optionm'.default_with threading.token_none
|> async.merge_cancellation_token_with_default_async
|> async.let'
ct |> threading.token_register fun () =>
if proc |> process_has_exited |> not
then proc |> process_kill
|> use
|> ignore
inl exit_code : i32 =
fun () =>
try_unit
fun () =>
proc
|> process_wait_for_exit_async ct
|> async.await_task
|> async.do
proc |> process_exit_code |> return
fun ex =>
// with :? System.Threading.Tasks.TaskCanceledException as ex =>
inl ex' = ex |> sm'.format_exception
output |> threading.concurrent_stack_push ex'
inl ex : async.task_canceled_exception = ex |> unbox
trace Warning
fun () => "runtime.execute_with_options_async / WaitForExitAsync"
fun () => { ex }
(limit.min : i32) |> return
|> async.new_async_unit
|> async.let'
inl output =
output
|> seq.rev''
|> fun x => x : seq.seq' string
|> sm'.concat "\n"
trace Debug
fun () => "runtime.execute_with_options_async"
fun () => { exit_code output_length = output |> sm'.length : i32 }
(exit_code, output) |> return
|> async.new_async_unit
| _ => fun _ =>
global "#if FABLE_COMPILER\n[<CompilationRepresentation (CompilationRepresentationFlags.ModuleSuffix)>]\nmodule System =\n module Diagnostics =\n type Process = unit\n type DataReceivedEventArgs = unit\n#endif"
null ()
execute_async¶
In [ ]:
inl execute_async command =
execution_options fun x => { x with
command = command
}
|> execute_with_options_async
In [ ]:
//// test
inl content = "╭─[ 你好,世界!こんにちは世界! ]─╮"
fun () =>
inl file_name = "test.txt"
inl temp_dir, disposable =
(file_name, content)
|> sm'.format_debug
|> crypto.hash_text
|> file_system.create_temp_dir'
disposable |> use |> ignore
inl path = temp_dir </> file_name
inl exit_code, result = execute_async $'\@$"pwsh -c ""Get-Content {!path}"""' |> async.let'
exit_code |> join _assert_eq 1
result |> _assert sm'.contains "not exist"
content |> file_system.write_all_text_async path |> async.do
execution_options fun x => { x with
command = $'\@$"cat ""{!file_name}"""'
working_directory = Some temp_dir |> optionm'.box
}
|> execute_with_options_async
|> async.let'
|> ignore
execution_options fun x => { x with
command = $'\@$"pwsh -c ""[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8; Get-Content {!file_name}"""'
working_directory = Some temp_dir |> optionm'.box
}
|> execute_with_options_async
|> async.return_await
|> async.new_async_unit
|> async.run_with_timeout 10000
|> function
| Some (exit_code, output) =>
exit_code |> join _assert_eq 0i32
output |> join _assert_eq content
true
| _ => false
|> _assert_eq true
00:00:00 d #1 runtime.execute_with_options_async / { file_name = pwsh; arguments = US2_0 "-c "Get-Content /tmp/!create_temp_path_/dotnet-repl/76793606-813b-88ad-7791-7ce2871edce9/test.txt""; options = { command = pwsh -c "Get-Content /tmp/!create_temp_path_/dotnet-repl/76793606-813b-88ad-7791-7ce2871edce9/test.txt"; cancellation_token = None; environment_variables = [||]; on_line = None; stdin = None; trace = true; working_directory = None } } 00:00:00 v #2 ! Get-Content: Cannot find path '/tmp/!create_temp_path_/dotnet-repl/76793606-813b-88ad-7791-7ce2871edce9/test.txt' because it does not exist. 00:00:00 d #3 runtime.execute_with_options_async / { exit_code = 1; output_length = 168 } __assert_eq / actual: 1 / expected: 1 __assert / actual: "not exist" / expected: "Get-Content: Cannot find path '/tmp/!create_temp_path_/dotnet-repl/76793606-813b-88ad-7791-7ce2871edce9/test.txt' because it does not exist." 00:00:00 d #4 runtime.execute_with_options_async / { file_name = cat; arguments = US2_0 ""test.txt""; options = { command = cat "test.txt"; cancellation_token = None; environment_variables = [||]; on_line = None; stdin = None; trace = true; working_directory = Some "/tmp/!create_temp_path_/dotnet-repl/76793606-813b-88ad-7791-7ce2871edce9" } } 00:00:00 v #5 > ╭─[ 你好,世界!こんにちは世界! ]─╮ 00:00:00 d #6 runtime.execute_with_options_async / { exit_code = 0; output_length = 22 } 00:00:00 d #7 runtime.execute_with_options_async / { file_name = pwsh; arguments = US2_0 "-c "[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8; Get-Content test.txt""; options = { command = pwsh -c "[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8; Get-Content test.txt"; cancellation_token = None; environment_variables = [||]; on_line = None; stdin = None; trace = true; working_directory = Some "/tmp/!create_temp_path_/dotnet-repl/76793606-813b-88ad-7791-7ce2871edce9" } } 00:00:00 v #8 > ╭─[ 你好,世界!こんにちは世界! ]─╮ 00:00:01 d #9 runtime.execute_with_options_async / { exit_code = 0; output_length = 22 } __assert_eq / actual: 0 / expected: 0 __assert_eq / actual: "╭─[ 你好,世界!こんにちは世界! ]─╮" / expected: "╭─[ 你好,世界!こんにちは世界! ]─╮" __assert_eq / actual: true / expected: true
In [ ]:
//// test
fun () =>
inl file_name = "test.txt"
inl text = "0"
inl temp_dir, disposable =
(file_name, text)
|> sm'.format_debug
|> crypto.hash_text
|> file_system.create_temp_dir'
disposable |> use |> ignore
inl path = temp_dir </> file_name
text |> file_system.write_all_text_async path |> async.do
inl cts = threading.new_cancellation_token_source ()
trace Debug (fun () => "1") id
inl result =
execution_options fun x => { x with
command = $'\@$"pwsh -c ""Get-Content {!path}"""'
cancellation_token = cts |> threading.cancellation_source_token |> Some |> optionm'.box
}
|> execute_with_options_async
|> async.start_child
|> async.let'
trace Debug (fun () => "2") id
async.sleep 100 |> async.do
trace Debug (fun () => "3") id
cts |> threading.cancellation_source_cancel
trace Debug (fun () => "4") id
inl exit_code, output = result |> async.let'
trace Debug (fun () => "5") id
(exit_code, output) |> return
|> async.new_async_unit
|> async.run_with_timeout 10000
|> function
| Some (exit_code, output) =>
exit_code |> _assert_eq -2147483648i32
output |> _assert_eq (join "System.Threading.Tasks.TaskCanceledException: A task was canceled.")
true
| _ => false
|> _assert_eq true
00:00:00 d #1 1 00:00:00 d #2 2 00:00:00 d #3 runtime.execute_with_options_async / { file_name = pwsh; arguments = US2_0 "-c "Get-Content /tmp/!create_temp_path_/dotnet-repl/613830ed-016e-d959-8d21-02dc1c63c252/test.txt""; options = { command = pwsh -c "Get-Content /tmp/!create_temp_path_/dotnet-repl/613830ed-016e-d959-8d21-02dc1c63c252/test.txt"; cancellation_token = Some System.Threading.CancellationToken; environment_variables = [||]; on_line = None; stdin = None; trace = true; working_directory = None } } 00:00:00 d #4 3 00:00:00 d #5 4 00:00:00 w #6 runtime.execute_with_options_async / WaitForExitAsync / { ex = System.Threading.Tasks.TaskCanceledException: A task was canceled. } 00:00:00 d #7 runtime.execute_with_options_async / { exit_code = -2147483648; output_length = 66 } 00:00:00 d #8 5 __assert_eq / actual: -2147483648 / expected: -2147483648 __assert_eq / actual: "System.Threading.Tasks.TaskCanceledException: A task was canceled." / expected: "System.Threading.Tasks.TaskCanceledException: A task was canceled." __assert_eq / actual: true / expected: true
current_process_kill¶
In [ ]:
inl current_process_kill () =
run_target function
| Fsharp (Native) => fun () =>
inl fn () =
run_target function
| Fsharp (Native) => fun () =>
trace Warning (fun () => "runtime.current_process_kill / exiting... 3") id
$'System.Threading.Thread.Sleep 300'
trace Warning (fun () => "runtime.current_process_kill / exiting... 2") id
$'System.Console.Out.Flush ()'
$'System.Threading.Thread.Sleep 60'
trace Warning (fun () => "runtime.current_process_kill / exiting... 1") id
$'System.Diagnostics.Process.GetCurrentProcess().Kill ()' : ()
| _ => fun () => ()
inl thread : threading.thread = $'new System.Threading.Thread (!fn)'
thread |> $'_.Start()' : ()
| _ => fun () => ()
gc_collect¶
In [ ]:
inl gc_collect () =
run_target function
| Fsharp _ => fun () => $'System.GC.Collect' () : ()
| Python _ => fun () =>
backend_switch {
Python = fun () => global "import gc"
}
($'gc.collect()' : int) |> ignore
| _ => fun () => ()
runtime¶
execute_with_options¶
In [ ]:
let execute_with_options (options : execution_options) : i32 * string =
run_target function
| Fsharp (Native) => fun () =>
options |> execute_with_options_async |> async.run_synchronously
| Rust (Native) => fun () =>
inl command = join options.command
inl file_name, arguments = command |> split_command |> resultm.get
inl arguments =
arguments
|> optionm'.default_value ""
|> split_args
|> resultm.get
|> am'.to_vec
|> am'.vec_map sm'.to_std_string
trace Debug
fun () => "runtime.execute_with_options"
fun () => { file_name arguments = arguments |> sm'.format_debug; options }
fun () =>
fun () =>
file_name
|> new_process_command
|> process_command_args arguments
|> process_command_stdout (process_stdio_piped ())
|> process_command_stderr (process_stdio_piped ())
|> process_command_stdin (process_stdio_piped ())
|> fun command =>
match options.working_directory |> optionm'.unbox with
| Some working_directory =>
command
|> process_command_current_dir working_directory
| None => command
|> fun command =>
match options.environment_variables with
| ;[] => command
| vars =>
(command, vars |> am'.to_vec)
||> am'.vec_fold' fun command (key, value) =>
command |> process_command_env key value
|> process_command_spawn
|> resultm.map_error' sm'.format'
|> resultm.map' (optionm'.some' >> (join id) >> threading.new_arc_mutex)
|> resultm.unbox'
|> function
| Ok child =>
inl stdout =
fun () =>
child
|> threading.arc_mutex_lock
|> resultm.unwrap'
|> threading.mutex_guard_ref_mut
|> optionm'.as_mut
|> optionm'.unwrap
|> process_child_stdout
|> optionm'.take_ref_mut
|> optionm'.unwrap
|> rust.capture
inl stderr =
fun () =>
child
|> threading.arc_mutex_lock
|> resultm.unwrap'
|> threading.mutex_guard_ref_mut
|> optionm'.as_mut
|> optionm'.unwrap
|> process_child_stderr
|> optionm'.take_ref_mut
|> optionm'.unwrap
|> rust.capture
inl stdin =
fun () =>
child
|> threading.arc_mutex_lock
|> resultm.unwrap'
|> threading.mutex_guard_ref_mut
|> optionm'.as_mut
|> optionm'.unwrap
|> process_child_stdin
|> optionm'.take_ref_mut
|> optionm'.unwrap
|> optionm'.some'
|> join id
|> threading.new_arc_mutex
|> rust.capture
inl channel_sender, channel_receiver = threading.new_channel ()
inl channel_sender'' = channel_sender |> (join id) |> threading.new_arc_mutex
inl channel_sender' = channel_sender |> (join id) |> threading.new_arc_mutex
inl channel_receiver' = channel_receiver |> (join id) |> threading.new_arc_mutex
inl stdout_handle =
fun () =>
stdout
|> stream.decode_reader_bytes_build
|> stream.new_buf_reader
|> stream.buf_read_lines
|> iter.try_for_each fun lines =>
inl channel_sender'' = channel_sender'' |> rust.clone
lines
|> stdio_line (Ok ()) options.trace channel_sender''
|> resultm.to_try
|> threading.spawn (1, 0) 1
inl stderr_handle =
fun () =>
stderr
|> stream.decode_reader_bytes_build
|> stream.new_buf_reader
|> stream.buf_read_lines
|> iter.try_for_each fun lines =>
inl channel_sender' = channel_sender' |> rust.clone
lines
|> stdio_line (Error ()) options.trace channel_sender'
|> resultm.to_try
|> threading.spawn (1, 0) 1
match options.stdin |> optionm'.unbox with
| Some stdin' =>
stdin
|> threading.arc_mutex_lock
|> resultm.unwrap'
|> threading.mutex_guard_ref_mut
|> optionm'.take_ref_mut
|> optionm'.map' threading.new_arc_mutex
|> optionm'.unbox
|> function
| Some stdin =>
stdin |> stdin'
stdin
|> threading.arc_mutex_lock
|> resultm.unwrap'
|> stdin_flush
| None => ()
| None => ()
inl output =
child
|> threading.arc_mutex_lock
|> resultm.unwrap'
|> threading.mutex_guard_ref_mut
|> optionm'.take_ref_mut
|> optionm'.unwrap
|> child_wait_with_output
|> resultm.map_error' sm'.format'
[ stdout_handle; stderr_handle ]
|> am'.new_vec
|> am'.vec_for_each' (threading.join' >> resultm.unwrap' >> resultm.unwrap')
match output |> resultm.unbox with
| Ok output =>
inl exit_code =
output
|> process_output_status
|> process_exit_status_code
|> optionm'.unbox
match exit_code with
| Some exit_code => exit_code, None, Some channel_receiver'
| None =>
-1,
("runtime.execute_with_options / exit_code=None" |> sm'.to_std_string |> Some),
Some channel_receiver'
| Error error =>
trace Critical
fun () => "runtime.execute_with_options / output error"
fun () => { error }
-2i32, error |> Some, None
| Error error =>
trace Critical
fun () => "runtime.execute_with_options / child error"
fun () => { error }
-1i32, error |> Some, None
|> function
| exit_code, std_trace, channel_receiver =>
inl std_trace =
channel_receiver
|> optionm'.box
|> optionm'.map' fun channel_receiver =>
channel_receiver
|> threading.arc_mutex_lock
|> resultm.unwrap'
|> iter.iter
|> iter_collect''
|> am'.vec_map sm'.from_std_string
|> am'.from_vec
|> fun x => x : _ i32 _
|> seq.of_array
|> sm'.concat "\n"
|> optionm'.default_value' (
std_trace
|> optionm.map sm'.from_std_string
|> optionm'.default_value ""
)
trace Verbose
fun () => "runtime.execute_with_options / result"
fun () => { exit_code std_trace_length = std_trace |> sm'.length : i32 }
new_pair exit_code std_trace
|> capture
// |> async.new_future_move
// |> async.block_on
|> fun x => x ()
|> from_pair
| _ => fun () => null ()
execute¶
In [ ]:
inl execute command =
execution_options fun x => { x with
command = command
}
|> execute_with_options
tests¶
In [ ]:
//// test
///! rust -d chrono encoding_rs encoding_rs_io regex sha2
inl content = "╭─[ 你好,世界!こんにちは世界! ]─╮"
inl file_name = join "test.txt"
inl temp_dir, disposable =
(file_name, content)
|> sm'.format_debug
|> crypto.hash_text
|> file_system.create_temp_dir'
inl path = temp_dir </> file_name |> file_system.normalize_path
inl exit_code, result =
execute $'\@$"pwsh -c ""[IO.File]::ReadAllText(\'{!path}\')"""'
exit_code |> _assert_eq 1
result |> _assert sm'.contains "not find file"
content |> file_system.write_all_text path
execution_options fun x => { x with
command = $'\@$"cat ""{!file_name}"""'
working_directory = Some temp_dir |> optionm'.box
}
|> execute_with_options
|> ignore
inl exit_code, output =
execution_options fun x => { x with
command = $'\@$"pwsh -c ""[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8; [IO.File]::ReadAllText(\'{!file_name}\')"""'
working_directory = Some temp_dir |> optionm'.box
}
|> execute_with_options
exit_code |> _assert_eq 0i32
output |> _assert_eq content
disposable |> use |> ignore
00:00:00 v #1 file_system.create_dir / { dir = /tmp/!create_temp_path_/spiral_builder_c46958ffc87f3f2efb369498e1af5b7c2a41ff41a817f350eb6eb426a4d8f338/9242780b-ce0e-9155-5e07-f6ee5667aa16 } 00:00:00 d #2 runtime.execute_with_options / { file_name = pwsh; arguments = ["-c", "[IO.File]::ReadAllText('/tmp/!create_temp_path_/spiral_builder_c46958ffc87f3f2efb369498e1af5b7c2a41ff41a817f350eb6eb426a4d8f338/9242780b-ce0e-9155-5e07-f6ee5667aa16/test.txt')"]; options = { command = pwsh -c "[IO.File]::ReadAllText('/tmp/!create_temp_path_/spiral_builder_c46958ffc87f3f2efb369498e1af5b7c2a41ff41a817f350eb6eb426a4d8f338/9242780b-ce0e-9155-5e07-f6ee5667aa16/test.txt')"; cancellation_token = None; environment_variables = Array(MutCell([])); on_line = None; stdin = None; trace = true; working_directory = None } } 00:00:00 v #3 ! MethodInvocationException: Exception calling "ReadAllText" with "1" argument(s): "Could not find file '/tmp/!create_temp_path_/spiral_builder_c46958ffc87f3f2efb369498e1af5b7c2a41ff41a817f350eb6eb426a4d8f338/9242780b-ce0e-9155-5e07-f6ee5667aa16/test.txt'." 00:00:00 v #4 runtime.execute_with_options / result / { exit_code = 1; std_trace_length = 283 } __assert_eq / actual: 1 / expected: 1 __assert / actual: "not find file" / expected: "MethodInvocationException: Exception calling "ReadAllText" with "1" argument(s): "Could not find file '/tmp/!create_temp_path_/spiral_builder_c46958ffc87f3f2efb369498e1af5b7c2a41ff41a817f350eb6eb426a4d8f338/9242780b-ce0e-9155-5e07-f6ee5667aa16/test.txt'."" 00:00:00 d #5 runtime.execute_with_options / { file_name = cat; arguments = ["test.txt"]; options = { command = cat "test.txt"; cancellation_token = None; environment_variables = Array(MutCell([])); on_line = None; stdin = None; trace = true; working_directory = Some( "/tmp/!create_temp_path_/spiral_builder_c46958ffc87f3f2efb369498e1af5b7c2a41ff41a817f350eb6eb426a4d8f338/9242780b-ce0e-9155-5e07-f6ee5667aa16", ) } } 00:00:00 v #6 > ╭─[ 你好,世界!こんにちは世界! ]─╮ 00:00:00 v #7 runtime.execute_with_options / result / { exit_code = 0; std_trace_length = 22 } 00:00:00 d #8 runtime.execute_with_options / { file_name = pwsh; arguments = ["-c", "[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8; [IO.File]::ReadAllText('test.txt')"]; options = { command = pwsh -c "[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8; [IO.File]::ReadAllText('test.txt')"; cancellation_token = None; environment_variables = Array(MutCell([])); on_line = None; stdin = None; trace = true; working_directory = Some( "/tmp/!create_temp_path_/spiral_builder_c46958ffc87f3f2efb369498e1af5b7c2a41ff41a817f350eb6eb426a4d8f338/9242780b-ce0e-9155-5e07-f6ee5667aa16", ) } } 00:00:00 v #9 > ╭─[ 你好,世界!こんにちは世界! ]─╮ 00:00:00 v #10 runtime.execute_with_options / result / { exit_code = 0; std_trace_length = 22 } __assert_eq / actual: 0 / expected: 0 __assert_eq / actual: "╭─[ 你好,世界!こんにちは世界! ]─╮" / expected: "╭─[ 你好,世界!こんにちは世界! ]─╮"
execute_retry¶
In [ ]:
let execute_retry retries options =
fun () =>
inl exit_code, result = options |> execute_with_options
if exit_code = 0
then Ok (exit_code, result)
else Error (exit_code, result)
|> retry_fn' retries
main¶
In [ ]:
inl main () =
init_trace_state None
$'let current_process_kill () = !current_process_kill ()' : ()
$'let execute_async x = !execute_async x' : ()
$'let execute_with_options_async x = !execute_with_options_async x' : ()
inl execution_options fn =
execution_options fun x =>
x
|> heap
|> fn
|> fun x => !x
$'let execution_options x = !execution_options x' : ()
inl split_args x = x |> split_args |> resultm.box
$'let split_args x = !split_args x' : ()