diff --git a/crates/roc_host/src/lib.rs b/crates/roc_host/src/lib.rs index b68ce76a..ba514aba 100644 --- a/crates/roc_host/src/lib.rs +++ b/crates/roc_host/src/lib.rs @@ -347,10 +347,10 @@ pub extern "C" fn rust_main(args: ReadOnlyRocList) -> i32 { init(); extern "C" { - #[link_name = "roc__mainForHost_1_exposed"] + #[link_name = "roc__main_for_host_1_exposed"] pub fn roc_main_for_host_caller(not_used: i32) -> i32; - #[link_name = "roc__mainForHost_1_exposed_size"] + #[link_name = "roc__main_for_host_1_exposed_size"] pub fn roc_main__for_host_size() -> usize; } diff --git a/examples/file-mixed.roc b/examples/file-mixed.roc index bb934a6d..60fe3b2c 100644 --- a/examples/file-mixed.roc +++ b/examples/file-mixed.roc @@ -7,7 +7,7 @@ import pf.Path import pf.Env import pf.Dir -outTxtPath = "out.txt" +out_txt_path = "out.txt" task! = \{} -> @@ -23,9 +23,9 @@ task! = \{} -> try Stdout.line! "Writing a string to out.txt" - try File.write_utf8! "a string!" outTxtPath + try File.write_utf8! "a string!" out_txt_path - contents = try File.read_utf8! outTxtPath + contents = try File.read_utf8! out_txt_path Stdout.line! "I read the file back. Its contents: \"$(contents)\"" diff --git a/examples/stdin.roc b/examples/stdin.roc index 90001adb..4afa0c5d 100644 --- a/examples/stdin.roc +++ b/examples/stdin.roc @@ -13,8 +13,8 @@ main! = \{} -> Stderr.line! "Expected a series of number characters (0-9)" else when Str.fromUtf8 number_bytes is - Ok nStr -> - Stdout.line! "Got number $(nStr)" + Ok n_str -> + Stdout.line! "Got number $(n_str)" Err _ -> Stderr.line! "Error, bad utf8" diff --git a/examples/tcp-client.roc b/examples/tcp-client.roc index 72123700..35fe2bdc 100644 --- a/examples/tcp-client.roc +++ b/examples/tcp-client.roc @@ -14,10 +14,10 @@ handle_err! : []_ => Result {} _ handle_err! = \error -> when error is TcpConnectErr err -> - errStr = Tcp.connect_err_to_str err + err_str = Tcp.connect_err_to_str err Stderr.line! """ - Failed to connect: $(errStr) + Failed to connect: $(err_str) If you don't have anything listening on port 8085, run: \$ nc -l 8085 @@ -30,12 +30,12 @@ handle_err! = \error -> Stderr.line! "Received invalid UTF-8 data" TcpReadErr err -> - errStr = Tcp.stream_err_to_str err - Stderr.line! "Error while reading: $(errStr)" + err_str = Tcp.stream_err_to_str err + Stderr.line! "Error while reading: $(err_str)" TcpWriteErr err -> - errStr = Tcp.stream_err_to_str err - Stderr.line! "Error while writing: $(errStr)" + err_str = Tcp.stream_err_to_str err + Stderr.line! "Error while writing: $(err_str)" other -> Stderr.line! "Got other error: $(Inspect.toStr other)" diff --git a/platform/Cmd.roc b/platform/Cmd.roc index 701a17ff..109cd66d 100644 --- a/platform/Cmd.roc +++ b/platform/Cmd.roc @@ -79,12 +79,9 @@ env = \@Cmd cmd, key, value -> ## ``` ## envs : Cmd, List (Str, Str) -> Cmd -envs = \@Cmd cmd, keyValues -> - values = keyValues |> List.joinMap \(key, value) -> [key, value] - @Cmd - { cmd & - envs: List.concat cmd.envs values, - } +envs = \@Cmd cmd, key_values -> + values = key_values |> List.joinMap \(key, value) -> [key, value] + @Cmd { cmd & envs: List.concat cmd.envs values } ## Clear all environment variables, and prevent inheriting from parent, only ## the environment variables provided to command are available to the child. diff --git a/platform/Env.roc b/platform/Env.roc index 3c968e8f..861a19b1 100644 --- a/platform/Env.roc +++ b/platform/Env.roc @@ -78,8 +78,8 @@ decode! : Str => Result val [VarNotFound, DecodeErr DecodeError] where val imple decode! = \name -> when Host.env_var! name is Err {} -> Err VarNotFound - Ok varStr -> - Str.toUtf8 varStr + Ok var_str -> + Str.toUtf8 var_str |> Decode.fromBytes (EnvDecoding.format {}) |> Result.mapErr (\_ -> DecodeErr TooShort) @@ -138,22 +138,22 @@ OS : [LINUX, MACOS, WINDOWS, OTHER Str] platform! : {} => { arch : ARCH, os : OS } platform! = \{} -> - fromRust = Host.current_arch_os! {} + from_rust = Host.current_arch_os! {} arch = - when fromRust.arch is + when from_rust.arch is "x86" -> X86 "x86_64" -> X64 "arm" -> ARM "aarch64" -> AARCH64 - _ -> OTHER fromRust.arch + _ -> OTHER from_rust.arch os = - when fromRust.os is + when from_rust.os is "linux" -> LINUX "macos" -> MACOS "windows" -> WINDOWS - _ -> OTHER fromRust.os + _ -> OTHER from_rust.os { arch, os } @@ -169,4 +169,4 @@ platform! = \{} -> temp_dir! : {} => Path temp_dir! = \{} -> Host.temp_dir! {} - |> \pathOSStringBytes -> InternalPath.from_os_bytes pathOSStringBytes + |> InternalPath.from_os_bytes diff --git a/platform/EnvDecoding.roc b/platform/EnvDecoding.roc index 5ecbdfcb..0ca77b55 100644 --- a/platform/EnvDecoding.roc +++ b/platform/EnvDecoding.roc @@ -5,31 +5,31 @@ module [ EnvFormat := {} implements [ DecoderFormatting { - u8: envU8, - u16: envU16, - u32: envU32, - u64: envU64, - u128: envU128, - i8: envI8, - i16: envI16, - i32: envI32, - i64: envI64, - i128: envI128, - f32: envF32, - f64: envF64, - dec: envDec, - bool: envBool, - string: envString, - list: envList, - record: envRecord, - tuple: envTuple, + u8: env_u8, + u16: env_u16, + u32: env_u32, + u64: env_u64, + u128: env_u128, + i8: env_i8, + i16: env_i16, + i32: env_i32, + i64: env_i64, + i128: env_i128, + f32: env_f32, + f64: env_f64, + dec: env_dec, + bool: env_bool, + string: env_string, + list: env_list, + record: env_record, + tuple: env_tuple, }, ] format : {} -> EnvFormat format = \{} -> @EnvFormat {} -decodeBytesToNum = \bytes, transformer -> +decode_bytes_to_num = \bytes, transformer -> when Str.fromUtf8 bytes is Ok s -> when transformer s is @@ -38,69 +38,71 @@ decodeBytesToNum = \bytes, transformer -> Err _ -> { result: Err TooShort, rest: bytes } -envU8 = Decode.custom \bytes, @EnvFormat {} -> decodeBytesToNum bytes Str.toU8 -envU16 = Decode.custom \bytes, @EnvFormat {} -> decodeBytesToNum bytes Str.toU16 -envU32 = Decode.custom \bytes, @EnvFormat {} -> decodeBytesToNum bytes Str.toU32 -envU64 = Decode.custom \bytes, @EnvFormat {} -> decodeBytesToNum bytes Str.toU64 -envU128 = Decode.custom \bytes, @EnvFormat {} -> decodeBytesToNum bytes Str.toU128 -envI8 = Decode.custom \bytes, @EnvFormat {} -> decodeBytesToNum bytes Str.toI8 -envI16 = Decode.custom \bytes, @EnvFormat {} -> decodeBytesToNum bytes Str.toI16 -envI32 = Decode.custom \bytes, @EnvFormat {} -> decodeBytesToNum bytes Str.toI32 -envI64 = Decode.custom \bytes, @EnvFormat {} -> decodeBytesToNum bytes Str.toI64 -envI128 = Decode.custom \bytes, @EnvFormat {} -> decodeBytesToNum bytes Str.toI128 -envF32 = Decode.custom \bytes, @EnvFormat {} -> decodeBytesToNum bytes Str.toF32 -envF64 = Decode.custom \bytes, @EnvFormat {} -> decodeBytesToNum bytes Str.toF64 -envDec = Decode.custom \bytes, @EnvFormat {} -> decodeBytesToNum bytes Str.toDec -envBool = Decode.custom \bytes, @EnvFormat {} -> +env_u8 = Decode.custom \bytes, @EnvFormat {} -> decode_bytes_to_num bytes Str.toU8 +env_u16 = Decode.custom \bytes, @EnvFormat {} -> decode_bytes_to_num bytes Str.toU16 +env_u32 = Decode.custom \bytes, @EnvFormat {} -> decode_bytes_to_num bytes Str.toU32 +env_u64 = Decode.custom \bytes, @EnvFormat {} -> decode_bytes_to_num bytes Str.toU64 +env_u128 = Decode.custom \bytes, @EnvFormat {} -> decode_bytes_to_num bytes Str.toU128 +env_i8 = Decode.custom \bytes, @EnvFormat {} -> decode_bytes_to_num bytes Str.toI8 +env_i16 = Decode.custom \bytes, @EnvFormat {} -> decode_bytes_to_num bytes Str.toI16 +env_i32 = Decode.custom \bytes, @EnvFormat {} -> decode_bytes_to_num bytes Str.toI32 +env_i64 = Decode.custom \bytes, @EnvFormat {} -> decode_bytes_to_num bytes Str.toI64 +env_i128 = Decode.custom \bytes, @EnvFormat {} -> decode_bytes_to_num bytes Str.toI128 +env_f32 = Decode.custom \bytes, @EnvFormat {} -> decode_bytes_to_num bytes Str.toF32 +env_f64 = Decode.custom \bytes, @EnvFormat {} -> decode_bytes_to_num bytes Str.toF64 +env_dec = Decode.custom \bytes, @EnvFormat {} -> decode_bytes_to_num bytes Str.toDec + +env_bool = Decode.custom \bytes, @EnvFormat {} -> when Str.fromUtf8 bytes is Ok "true" -> { result: Ok Bool.true, rest: [] } Ok "false" -> { result: Ok Bool.false, rest: [] } _ -> { result: Err TooShort, rest: bytes } -envString = Decode.custom \bytes, @EnvFormat {} -> + +env_string = Decode.custom \bytes, @EnvFormat {} -> when Str.fromUtf8 bytes is Ok s -> { result: Ok s, rest: [] } Err _ -> { result: Err TooShort, rest: bytes } -envList = \decodeElem -> Decode.custom \bytes, @EnvFormat {} -> - # Per our supported methods of decoding, this is either a list of strings or - # a list of numbers; in either case, the list of bytes must be Utf-8 - # decodable. So just parse it as a list of strings and pass each chunk to - # the element decoder. By construction, our element decoders expect to parse - # a whole list of bytes anyway. - decodeElems = \allBytes, accum -> - { toParse, remainder } = - when List.splitFirst allBytes (Num.toU8 ',') is - Ok { before, after } -> - { toParse: before, remainder: Some after } +env_list = \decode_elem -> Decode.custom \bytes, @EnvFormat {} -> + # Per our supported methods of decoding, this is either a list of strings or + # a list of numbers; in either case, the list of bytes must be Utf-8 + # decodable. So just parse it as a list of strings and pass each chunk to + # the element decoder. By construction, our element decoders expect to parse + # a whole list of bytes anyway. + decode_elems = \all_bytes, accum -> + { to_parse, remainder } = + when List.splitFirst all_bytes (Num.toU8 ',') is + Ok { before, after } -> + { to_parse: before, remainder: Some after } - Err NotFound -> - { toParse: allBytes, remainder: None } + Err NotFound -> + { to_parse: all_bytes, remainder: None } - when Decode.decodeWith toParse decodeElem (@EnvFormat {}) is - { result, rest } -> - when result is - Ok val -> - when remainder is - Some restBytes -> decodeElems restBytes (List.append accum val) - None -> Done (List.append accum val) + when Decode.decodeWith to_parse decode_elem (@EnvFormat {}) is + { result, rest } -> + when result is + Ok val -> + when remainder is + Some rest_bytes -> decode_elems rest_bytes (List.append accum val) + None -> Done (List.append accum val) - Err e -> Errored e rest + Err e -> Errored e rest - when decodeElems bytes [] is - Errored e rest -> { result: Err e, rest } - Done vals -> - { result: Ok vals, rest: [] } + when decode_elems bytes [] is + Errored e rest -> { result: Err e, rest } + Done vals -> + { result: Ok vals, rest: [] } # TODO: we must currently annotate the arrows here so that the lambda sets are # exercised, and the solver can find an ambient lambda set for the # specialization. -envRecord : _, (_, _ -> [Keep (Decoder _ _), Skip]), (_, _ -> _) -> Decoder _ _ -envRecord = \_initialState, _stepField, _finalizer -> Decode.custom \bytes, @EnvFormat {} -> - { result: Err TooShort, rest: bytes } +env_record : _, (_, _ -> [Keep (Decoder _ _), Skip]), (_, _ -> _) -> Decoder _ _ +env_record = \_initialState, _stepField, _finalizer -> Decode.custom \bytes, @EnvFormat {} -> + { result: Err TooShort, rest: bytes } # TODO: we must currently annotate the arrows here so that the lambda sets are # exercised, and the solver can find an ambient lambda set for the # specialization. -envTuple : _, (_, _ -> [Next (Decoder _ _), TooLong]), (_ -> _) -> Decoder _ _ -envTuple = \_initialState, _stepElem, _finalizer -> Decode.custom \bytes, @EnvFormat {} -> - { result: Err TooShort, rest: bytes } +env_tuple : _, (_, _ -> [Next (Decoder _ _), TooLong]), (_ -> _) -> Decoder _ _ +env_tuple = \_initialState, _stepElem, _finalizer -> Decode.custom \bytes, @EnvFormat {} -> + { result: Err TooShort, rest: bytes } diff --git a/platform/File.roc b/platform/File.roc index 5e85bc79..7dd0a401 100644 --- a/platform/File.roc +++ b/platform/File.roc @@ -222,11 +222,11 @@ Reader := { reader : Host.FileReader, path : Path } ## ## Use [read_utf8!] if you want to get the entire file contents at once. open_reader! : Str => Result Reader [GetFileReadErr Path Err] -open_reader! = \pathStr -> - path = Path.from_str pathStr +open_reader! = \path_str -> + path = Path.from_str path_str # 0 means with default capacity - Host.file_reader! (Str.toUtf8 pathStr) 0 + Host.file_reader! (Str.toUtf8 path_str) 0 |> Result.mapErr \err -> GetFileReadErr path (InternalIOErr.handle_err err) |> Result.map \reader -> @Reader { reader, path } @@ -238,10 +238,10 @@ open_reader! = \pathStr -> ## ## Use [read_utf8!] if you want to get the entire file contents at once. open_reader_with_capacity! : Str, U64 => Result Reader [GetFileReadErr Path Err] -open_reader_with_capacity! = \pathStr, capacity -> - path = Path.from_str pathStr +open_reader_with_capacity! = \path_str, capacity -> + path = Path.from_str path_str - Host.file_reader! (Str.toUtf8 pathStr) capacity + Host.file_reader! (Str.toUtf8 path_str) capacity |> Result.mapErr \err -> GetFileReadErr path (InternalIOErr.handle_err err) |> Result.map \reader -> @Reader { reader, path } diff --git a/platform/Http.roc b/platform/Http.roc index 750ddeec..374e4170 100644 --- a/platform/Http.roc +++ b/platform/Http.roc @@ -7,6 +7,7 @@ module [ default_request, send!, get!, + get_utf8!, ] import InternalHttp @@ -85,3 +86,11 @@ get! = \uri, fmt -> Decode.fromBytes response.body fmt |> Result.mapErr \_ -> HttpDecodingFailed + +get_utf8! : Str => Result Str [BadBody Str] +get_utf8! = \uri -> + response = send! { default_request & uri } + + response.body + |> Str.fromUtf8 + |> Result.mapErr \_ -> BadBody "Invalid UTF-8" diff --git a/platform/InternalDateTime.roc b/platform/InternalDateTime.roc index bde2748a..0b219e73 100644 --- a/platform/InternalDateTime.roc +++ b/platform/InternalDateTime.roc @@ -8,49 +8,49 @@ DateTime : { year : I128, month : I128, day : I128, hours : I128, minutes : I128 to_iso_8601 : DateTime -> Str to_iso_8601 = \{ year, month, day, hours, minutes, seconds } -> - yearStr = yearWithPaddedZeros year - monthStr = monthWithPaddedZeros month - dayStr = dayWithPaddedZeros day - hourStr = hoursWithPaddedZeros hours - minuteStr = minutesWithPaddedZeros minutes - secondsStr = secondsWithPaddedZeros seconds - - "$(yearStr)-$(monthStr)-$(dayStr)T$(hourStr):$(minuteStr):$(secondsStr)Z" - -yearWithPaddedZeros : I128 -> Str -yearWithPaddedZeros = \year -> - yearStr = Num.toStr year + year_str = year_with_padded_zeros year + month_str = month_with_padded_zeros month + day_str = day_with_padded_zeros day + hour_str = hours_with_padded_zeros hours + minute_str = minutes_with_padded_zeros minutes + seconds_str = seconds_with_padded_zeros seconds + + "$(year_str)-$(month_str)-$(day_str)T$(hour_str):$(minute_str):$(seconds_str)Z" + +year_with_padded_zeros : I128 -> Str +year_with_padded_zeros = \year -> + year_str = Num.toStr year if year < 10 then - "000$(yearStr)" + "000$(year_str)" else if year < 100 then - "00$(yearStr)" + "00$(year_str)" else if year < 1000 then - "0$(yearStr)" + "0$(year_str)" else - yearStr + year_str -monthWithPaddedZeros : I128 -> Str -monthWithPaddedZeros = \month -> - monthStr = Num.toStr month +month_with_padded_zeros : I128 -> Str +month_with_padded_zeros = \month -> + month_str = Num.toStr month if month < 10 then - "0$(monthStr)" + "0$(month_str)" else - monthStr + month_str -dayWithPaddedZeros : I128 -> Str -dayWithPaddedZeros = monthWithPaddedZeros +day_with_padded_zeros : I128 -> Str +day_with_padded_zeros = month_with_padded_zeros -hoursWithPaddedZeros : I128 -> Str -hoursWithPaddedZeros = monthWithPaddedZeros +hours_with_padded_zeros : I128 -> Str +hours_with_padded_zeros = month_with_padded_zeros -minutesWithPaddedZeros : I128 -> Str -minutesWithPaddedZeros = monthWithPaddedZeros +minutes_with_padded_zeros : I128 -> Str +minutes_with_padded_zeros = month_with_padded_zeros -secondsWithPaddedZeros : I128 -> Str -secondsWithPaddedZeros = monthWithPaddedZeros +seconds_with_padded_zeros : I128 -> Str +seconds_with_padded_zeros = month_with_padded_zeros -isLeapYear : I128 -> Bool -isLeapYear = \year -> +is_leap_year : I128 -> Bool +is_leap_year = \year -> (year % 4 == 0) && # divided evenly by 4 unless... ( @@ -59,37 +59,37 @@ isLeapYear = \year -> (year % 400 == 0) # expecpt when also divisible by 400 ) -expect isLeapYear 2000 -expect isLeapYear 2012 -expect !(isLeapYear 1900) -expect !(isLeapYear 2015) -expect List.map [2023, 1988, 1992, 1996] isLeapYear == [Bool.false, Bool.true, Bool.true, Bool.true] -expect List.map [1700, 1800, 1900, 2100, 2200, 2300, 2500, 2600] isLeapYear == [Bool.false, Bool.false, Bool.false, Bool.false, Bool.false, Bool.false, Bool.false, Bool.false] +expect is_leap_year 2000 +expect is_leap_year 2012 +expect !(is_leap_year 1900) +expect !(is_leap_year 2015) +expect List.map [2023, 1988, 1992, 1996] is_leap_year == [Bool.false, Bool.true, Bool.true, Bool.true] +expect List.map [1700, 1800, 1900, 2100, 2200, 2300, 2500, 2600] is_leap_year == [Bool.false, Bool.false, Bool.false, Bool.false, Bool.false, Bool.false, Bool.false, Bool.false] -daysInMonth : I128, I128 -> I128 -daysInMonth = \year, month -> +days_in_month : I128, I128 -> I128 +days_in_month = \year, month -> if List.contains [1, 3, 5, 7, 8, 10, 12] month then 31 else if List.contains [4, 6, 9, 11] month then 30 else if month == 2 then - (if isLeapYear year then 29 else 28) + (if is_leap_year year then 29 else 28) else 0 -expect daysInMonth 2023 1 == 31 # January -expect daysInMonth 2023 2 == 28 # February -expect daysInMonth 1996 2 == 29 # February in a leap year -expect daysInMonth 2023 3 == 31 # March -expect daysInMonth 2023 4 == 30 # April -expect daysInMonth 2023 5 == 31 # May -expect daysInMonth 2023 6 == 30 # June -expect daysInMonth 2023 7 == 31 # July -expect daysInMonth 2023 8 == 31 # August -expect daysInMonth 2023 9 == 30 # September -expect daysInMonth 2023 10 == 31 # October -expect daysInMonth 2023 11 == 30 # November -expect daysInMonth 2023 12 == 31 # December +expect days_in_month 2023 1 == 31 # January +expect days_in_month 2023 2 == 28 # February +expect days_in_month 1996 2 == 29 # February in a leap year +expect days_in_month 2023 3 == 31 # March +expect days_in_month 2023 4 == 30 # April +expect days_in_month 2023 5 == 31 # May +expect days_in_month 2023 6 == 30 # June +expect days_in_month 2023 7 == 31 # July +expect days_in_month 2023 8 == 31 # August +expect days_in_month 2023 9 == 30 # September +expect days_in_month 2023 10 == 31 # October +expect days_in_month 2023 11 == 30 # November +expect days_in_month 2023 12 == 31 # December epoch_millis_to_datetime : I128 -> DateTime epoch_millis_to_datetime = \millis -> @@ -111,19 +111,19 @@ epoch_millis_to_datetime = \millis -> epoch_millis_to_datetimeHelp : DateTime -> DateTime epoch_millis_to_datetimeHelp = \current -> - countDaysInMonth = daysInMonth current.year current.month - countDaysInPrevMonth = + count_days_in_month = days_in_month current.year current.month + count_days_in_prev_month = if current.month == 1 then - daysInMonth (current.year - 1) 12 + days_in_month (current.year - 1) 12 else - daysInMonth current.year (current.month - 1) + days_in_month current.year (current.month - 1) if current.day < 1 then epoch_millis_to_datetimeHelp { current & year: if current.month == 1 then current.year - 1 else current.year, month: if current.month == 1 then 12 else current.month - 1, - day: current.day + countDaysInPrevMonth, + day: current.day + count_days_in_prev_month, } else if current.hours < 0 then epoch_millis_to_datetimeHelp @@ -143,12 +143,12 @@ epoch_millis_to_datetimeHelp = \current -> minutes: current.minutes - 1, seconds: current.seconds + 60, } - else if current.day > countDaysInMonth then + else if current.day > count_days_in_month then epoch_millis_to_datetimeHelp { current & year: if current.month == 12 then current.year + 1 else current.year, month: if current.month == 12 then 1 else current.month + 1, - day: current.day - countDaysInMonth, + day: current.day - count_days_in_month, } else current diff --git a/platform/Path.roc b/platform/Path.roc index 53171604..c4785090 100644 --- a/platform/Path.roc +++ b/platform/Path.roc @@ -86,9 +86,9 @@ write! = \val, path, fmt -> ## > To format data before writing it to a file, you can use [Path.write!] instead. write_bytes! : List U8, Path => Result {} [FileWriteErr Path Err] write_bytes! = \bytes, path -> - pathBytes = InternalPath.to_bytes path + path_bytes = InternalPath.to_bytes path - Host.file_write_bytes! pathBytes bytes + Host.file_write_bytes! path_bytes bytes |> Result.mapErr \err -> FileWriteErr path (InternalIOErr.handle_err err) ## Writes a [Str] to a file, encoded as [UTF-8](https://en.wikipedia.org/wiki/UTF-8). @@ -103,9 +103,9 @@ write_bytes! = \bytes, path -> ## > To write unformatted bytes to a file, you can use [Path.write_bytes!] instead. write_utf8! : Str, Path => Result {} [FileWriteErr Path Err] write_utf8! = \str, path -> - pathBytes = InternalPath.to_bytes path + path_bytes = InternalPath.to_bytes path - Host.file_write_utf8! pathBytes str + Host.file_write_utf8! path_bytes str |> Result.mapErr \err -> FileWriteErr path (InternalIOErr.handle_err err) ## Note that the path may not be valid depending on the filesystem where it is used. @@ -237,12 +237,12 @@ with_extension : Path, Str -> Path with_extension = \path, extension -> when InternalPath.unwrap path is FromOperatingSystem bytes | ArbitraryBytes bytes -> - beforeDot = + before_dot = when List.splitLast bytes (Num.toU8 '.') is Ok { before } -> before Err NotFound -> bytes - beforeDot + before_dot |> List.reserve (Str.countUtf8Bytes extension |> Num.intCast |> Num.addSaturated 1) |> List.append (Num.toU8 '.') |> List.concat (Str.toUtf8 extension) @@ -250,12 +250,12 @@ with_extension = \path, extension -> |> InternalPath.wrap FromStr str -> - beforeDot = + before_dot = when Str.splitLast str "." is Ok { before } -> before Err NotFound -> str - beforeDot + before_dot |> Str.reserve (Str.countUtf8Bytes extension |> Num.addSaturated 1) |> Str.concat "." |> Str.concat extension @@ -304,7 +304,7 @@ read_utf8! : Path => Result Str [FileReadErr Path Err, FileReadUtf8Err Path _] read_utf8! = \path -> bytes = Host.file_read_bytes! (InternalPath.to_bytes path) - |> Result.mapErr? \readErr -> FileReadErr path (InternalIOErr.handle_err readErr) + |> Result.mapErr? \read_err -> FileReadErr path (InternalIOErr.handle_err read_err) Str.fromUtf8 bytes |> Result.mapErr \err -> FileReadUtf8Err path err diff --git a/platform/Stderr.roc b/platform/Stderr.roc index b87eb15d..ade7ca0d 100644 --- a/platform/Stderr.roc +++ b/platform/Stderr.roc @@ -33,8 +33,8 @@ Err : [ Other Str, ] -handleErr : InternalIOErr.IOErrFromHost -> [StderrErr Err] -handleErr = \{ tag, msg } -> +handle_err : InternalIOErr.IOErrFromHost -> [StderrErr Err] +handle_err = \{ tag, msg } -> when tag is NotFound -> StderrErr NotFound PermissionDenied -> StderrErr PermissionDenied @@ -52,7 +52,7 @@ handleErr = \{ tag, msg } -> line! : Str => Result {} [StderrErr Err] line! = \str -> Host.stderr_line! str - |> Result.mapErr handleErr + |> Result.mapErr handle_err ## Write the given string to [standard error](https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr)). ## @@ -63,4 +63,4 @@ line! = \str -> write! : Str => Result {} [StderrErr Err] write! = \str -> Host.stderr_write! str - |> Result.mapErr handleErr + |> Result.mapErr handle_err diff --git a/platform/Stdin.roc b/platform/Stdin.roc index f74d69d1..c9be7521 100644 --- a/platform/Stdin.roc +++ b/platform/Stdin.roc @@ -2,7 +2,7 @@ module [ Err, line!, bytes!, - readToEnd!, + read_to_end!, ] import Host @@ -34,8 +34,8 @@ Err : [ Other Str, ] -handleErr : InternalIOErr.IOErrFromHost -> [EndOfFile, StdinErr Err] -handleErr = \{ tag, msg } -> +handle_err : InternalIOErr.IOErrFromHost -> [EndOfFile, StdinErr Err] +handle_err = \{ tag, msg } -> when tag is NotFound -> StdinErr NotFound PermissionDenied -> StdinErr PermissionDenied @@ -56,7 +56,7 @@ handleErr = \{ tag, msg } -> line! : {} => Result Str [EndOfFile, StdinErr Err] line! = \{} -> Host.stdin_line! {} - |> Result.mapErr handleErr + |> Result.mapErr handle_err ## Read bytes from [standard input](https://en.wikipedia.org/wiki/Standard_streams#Standard_input_(stdin)). ## ‼️ This function can read no more than 16,384 bytes at a time. Use [readToEnd!] if you need more. @@ -67,11 +67,11 @@ line! = \{} -> bytes! : {} => Result (List U8) [EndOfFile, StdinErr Err] bytes! = \{} -> Host.stdin_bytes! {} - |> Result.mapErr handleErr + |> Result.mapErr handle_err ## Read all bytes from [standard input](https://en.wikipedia.org/wiki/Standard_streams#Standard_input_(stdin)) until EOF in this source. -readToEnd! : {} => Result (List U8) [StdinErr Err] -readToEnd! = \{} -> +read_to_end! : {} => Result (List U8) [StdinErr Err] +read_to_end! = \{} -> Host.stdin_read_to_end! {} |> Result.mapErr \{ tag, msg } -> when tag is diff --git a/platform/Tcp.roc b/platform/Tcp.roc index 2209dc52..93ef1c2d 100644 --- a/platform/Tcp.roc +++ b/platform/Tcp.roc @@ -15,7 +15,7 @@ module [ import Host -unexpectedEofErrorMessage = "UnexpectedEof" +unexpected_eof_error_message = "UnexpectedEof" ## Represents a TCP stream. Stream := Host.TcpStream @@ -32,8 +32,8 @@ ConnectErr : [ Unrecognized Str, ] -parseConnectErr : Str -> ConnectErr -parseConnectErr = \err -> +parse_connect_err : Str -> ConnectErr +parse_connect_err = \err -> when err is "ErrorKind::PermissionDenied" -> PermissionDenied "ErrorKind::AddrInUse" -> AddrInUse @@ -56,8 +56,8 @@ StreamErr : [ Unrecognized Str, ] -parseStreamErr : Str -> StreamErr -parseStreamErr = \err -> +parse_stream_err : Str -> StreamErr +parse_stream_err = \err -> when err is "StreamNotFound" -> StreamNotFound "ErrorKind::PermissionDenied" -> PermissionDenied @@ -87,7 +87,7 @@ connect! : Str, U16 => Result Stream ConnectErr connect! = \host, port -> Host.tcp_connect! host port |> Result.map @Stream - |> Result.mapErr parseConnectErr + |> Result.mapErr parse_connect_err ## Read up to a number of bytes from the TCP stream. ## @@ -99,9 +99,9 @@ connect! = \host, port -> ## ## > To read an exact number of bytes or fail, you can use [Tcp.read_exactly!] instead. read_up_to! : Stream, U64 => Result (List U8) [TcpReadErr StreamErr] -read_up_to! = \@Stream stream, bytesToRead -> - Host.tcp_read_up_to! stream bytesToRead - |> Result.mapErr \err -> TcpReadErr (parseStreamErr err) +read_up_to! = \@Stream stream, bytes_to_read -> + Host.tcp_read_up_to! stream bytes_to_read + |> Result.mapErr \err -> TcpReadErr (parse_stream_err err) ## Read an exact number of bytes or fail. ## @@ -112,13 +112,13 @@ read_up_to! = \@Stream stream, bytesToRead -> ## `TcpUnexpectedEOF` is returned if the stream ends before the specfied number of bytes is reached. ## read_exactly! : Stream, U64 => Result (List U8) [TcpReadErr StreamErr, TcpUnexpectedEOF] -read_exactly! = \@Stream stream, bytesToRead -> - Host.tcp_read_exactly! stream bytesToRead +read_exactly! = \@Stream stream, bytes_to_read -> + Host.tcp_read_exactly! stream bytes_to_read |> Result.mapErr \err -> - if err == unexpectedEofErrorMessage then + if err == unexpected_eof_error_message then TcpUnexpectedEOF else - TcpReadErr (parseStreamErr err) + TcpReadErr (parse_stream_err err) ## Read until a delimiter or EOF is reached. ## @@ -134,7 +134,7 @@ read_exactly! = \@Stream stream, bytesToRead -> read_until! : Stream, U8 => Result (List U8) [TcpReadErr StreamErr] read_until! = \@Stream stream, byte -> Host.tcp_read_until! stream byte - |> Result.mapErr \err -> TcpReadErr (parseStreamErr err) + |> Result.mapErr \err -> TcpReadErr (parse_stream_err err) ## Read until a newline or EOF is reached. ## @@ -164,7 +164,7 @@ read_line! = \stream -> write! : Stream, List U8 => Result {} [TcpWriteErr StreamErr] write! = \@Stream stream, bytes -> Host.tcp_write! stream bytes - |> Result.mapErr \err -> TcpWriteErr (parseStreamErr err) + |> Result.mapErr \err -> TcpWriteErr (parse_stream_err err) ## Writes a [Str] to a TCP stream, encoded as [UTF-8](https://en.wikipedia.org/wiki/UTF-8). ## diff --git a/platform/Url.roc b/platform/Url.roc index 31ea33b8..6f00f254 100644 --- a/platform/Url.roc +++ b/platform/Url.roc @@ -11,6 +11,7 @@ module [ reserve, with_query, with_fragment, + query_params, ] ## A [Uniform Resource Locator](https://en.wikipedia.org/wiki/URL). @@ -113,7 +114,7 @@ append = \@Url url_str, suffix_unencoded -> before |> Str.reserve bytes - |> appendHelp suffix + |> append_help suffix |> Str.concat "?" |> Str.concat after |> @Url @@ -131,18 +132,18 @@ append = \@Url url_str, suffix_unencoded -> before |> Str.reserve bytes - |> appendHelp suffix + |> append_help suffix |> Str.concat "#" |> Str.concat after |> @Url Err NotFound -> # No query and no fragment, so just append it - @Url (appendHelp url_str suffix) + @Url (append_help url_str suffix) ## Internal helper -appendHelp : Str, Str -> Str -appendHelp = \prefix, suffix -> +append_help : Str, Str -> Str +append_help = \prefix, suffix -> if Str.endsWith prefix "/" then if Str.startsWith suffix "/" then # Avoid a double-slash by appending only the part of the suffix after the "/" @@ -192,10 +193,10 @@ percent_encode : Str -> Str percent_encode = \input -> # Optimistically assume we won't need any percent encoding, and can have # the same capacity as the input string. If we're wrong, it will get doubled. - initialOutput = List.withCapacity (Str.countUtf8Bytes input |> Num.intCast) + initial_output = List.withCapacity (Str.countUtf8Bytes input |> Num.intCast) answer = - List.walk (Str.toUtf8 input) initialOutput \output, byte -> + List.walk (Str.toUtf8 input) initial_output \output, byte -> # Spec for percent-encoding: https://www.ietf.org/rfc/rfc3986.txt if (byte >= 97 && byte <= 122) # lowercase ASCII @@ -217,7 +218,7 @@ percent_encode = \input -> _ -> # This needs encoding in a path suffix = - Str.toUtf8 percentEncoded + Str.toUtf8 percent_encoded |> List.sublist { len: 3, start: 3 * Num.intCast byte } List.concat output suffix @@ -246,34 +247,34 @@ percent_encode = \input -> ## append_param : Url, Str, Str -> Url append_param = \@Url url_str, key, value -> - { withoutFragment, afterQuery } = + { without_fragment, after_query } = when Str.splitLast url_str "#" is Ok { before, after } -> # The fragment is almost certainly going to be a small string, # so this interpolation should happen on the stack. - { withoutFragment: before, afterQuery: "#$(after)" } + { without_fragment: before, after_query: "#$(after)" } Err NotFound -> - { withoutFragment: url_str, afterQuery: "" } + { without_fragment: url_str, after_query: "" } - encodedKey = percent_encode key - encodedValue = percent_encode value + encoded_key = percent_encode key + encoded_value = percent_encode value bytes = - Str.countUtf8Bytes withoutFragment + Str.countUtf8Bytes without_fragment + 1 # for "?" or "&" - + Str.countUtf8Bytes encodedKey + + Str.countUtf8Bytes encoded_key + 1 # for "=" - + Str.countUtf8Bytes encodedValue - + Str.countUtf8Bytes afterQuery + + Str.countUtf8Bytes encoded_value + + Str.countUtf8Bytes after_query - withoutFragment + without_fragment |> Str.reserve bytes - |> Str.concat (if has_query (@Url withoutFragment) then "&" else "?") - |> Str.concat encodedKey + |> Str.concat (if has_query (@Url without_fragment) then "&" else "?") + |> Str.concat encoded_key |> Str.concat "=" - |> Str.concat encodedValue - |> Str.concat afterQuery + |> Str.concat encoded_value + |> Str.concat after_query |> @Url ## Replaces the URL's [query](https://en.wikipedia.org/wiki/URL#Syntax)—the part @@ -291,36 +292,36 @@ append_param = \@Url url_str, key, value -> ## |> Url.with_query "" ## ``` with_query : Url, Str -> Url -with_query = \@Url url_str, queryStr -> - { withoutFragment, afterQuery } = +with_query = \@Url url_str, query_str -> + { without_fragment, after_query } = when Str.splitLast url_str "#" is Ok { before, after } -> # The fragment is almost certainly going to be a small string, # so this interpolation should happen on the stack. - { withoutFragment: before, afterQuery: "#$(after)" } + { without_fragment: before, after_query: "#$(after)" } Err NotFound -> - { withoutFragment: url_str, afterQuery: "" } + { without_fragment: url_str, after_query: "" } - beforeQuery = - when Str.splitLast withoutFragment "?" is + before_query = + when Str.splitLast without_fragment "?" is Ok { before } -> before - Err NotFound -> withoutFragment + Err NotFound -> without_fragment - if Str.isEmpty queryStr then - @Url (Str.concat beforeQuery afterQuery) + if Str.isEmpty query_str then + @Url (Str.concat before_query after_query) else bytes = - Str.countUtf8Bytes beforeQuery + Str.countUtf8Bytes before_query + 1 # for "?" - + Str.countUtf8Bytes queryStr - + Str.countUtf8Bytes afterQuery + + Str.countUtf8Bytes query_str + + Str.countUtf8Bytes after_query - beforeQuery + before_query |> Str.reserve bytes |> Str.concat "?" - |> Str.concat queryStr - |> Str.concat afterQuery + |> Str.concat query_str + |> Str.concat after_query |> @Url ## Returns the URL's [query](https://en.wikipedia.org/wiki/URL#Syntax)—the part after @@ -340,12 +341,12 @@ with_query = \@Url url_str, queryStr -> ## query : Url -> Str query = \@Url url_str -> - withoutFragment = + without_fragment = when Str.splitLast url_str "#" is Ok { before } -> before Err NotFound -> url_str - when Str.splitLast withoutFragment "?" is + when Str.splitLast without_fragment "?" is Ok { after } -> after Err NotFound -> "" @@ -405,23 +406,23 @@ fragment = \@Url url_str -> ## ``` ## with_fragment : Url, Str -> Url -with_fragment = \@Url url_str, fragmentStr -> +with_fragment = \@Url url_str, fragment_str -> when Str.splitLast url_str "#" is Ok { before } -> - if Str.isEmpty fragmentStr then + if Str.isEmpty fragment_str then # If the given fragment is empty, remove the URL's fragment @Url before else # Replace the URL's old fragment with this one, discarding `after` - @Url "$(before)#$(fragmentStr)" + @Url "$(before)#$(fragment_str)" Err NotFound -> - if Str.isEmpty fragmentStr then + if Str.isEmpty fragment_str then # If the given fragment is empty, leave the URL as having no fragment @Url url_str else # The URL didn't have a fragment, so give it this one - @Url "$(url_str)#$(fragmentStr)" + @Url "$(url_str)#$(fragment_str)" ## Returns [Bool.true] if the URL has a `#` in it. ## @@ -442,5 +443,14 @@ has_fragment = \@Url url_str -> # Adapted from the percent-encoding crate, © The rust-url developers, Apache2-licensed # # https://github.com/servo/rust-url/blob/e12d76a61add5bc09980599c738099feaacd1d0d/percent_encoding/src/lib.rs#L183 -percentEncoded : Str -percentEncoded = "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F%30%31%32%33%34%35%36%37%38%39%3A%3B%3C%3D%3E%3F%40%41%42%43%44%45%46%47%48%49%4A%4B%4C%4D%4E%4F%50%51%52%53%54%55%56%57%58%59%5A%5B%5C%5D%5E%5F%60%61%62%63%64%65%66%67%68%69%6A%6B%6C%6D%6E%6F%70%71%72%73%74%75%76%77%78%79%7A%7B%7C%7D%7E%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF" +percent_encoded : Str +percent_encoded = "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F%30%31%32%33%34%35%36%37%38%39%3A%3B%3C%3D%3E%3F%40%41%42%43%44%45%46%47%48%49%4A%4B%4C%4D%4E%4F%50%51%52%53%54%55%56%57%58%59%5A%5B%5C%5D%5E%5F%60%61%62%63%64%65%66%67%68%69%6A%6B%6C%6D%6E%6F%70%71%72%73%74%75%76%77%78%79%7A%7B%7C%7D%7E%7F%80%81%82%83%84%85%86%87%88%89%8A%8B%8C%8D%8E%8F%90%91%92%93%94%95%96%97%98%99%9A%9B%9C%9D%9E%9F%A0%A1%A2%A3%A4%A5%A6%A7%A8%A9%AA%AB%AC%AD%AE%AF%B0%B1%B2%B3%B4%B5%B6%B7%B8%B9%BA%BB%BC%BD%BE%BF%C0%C1%C2%C3%C4%C5%C6%C7%C8%C9%CA%CB%CC%CD%CE%CF%D0%D1%D2%D3%D4%D5%D6%D7%D8%D9%DA%DB%DC%DD%DE%DF%E0%E1%E2%E3%E4%E5%E6%E7%E8%E9%EA%EB%EC%ED%EE%EF%F0%F1%F2%F3%F4%F5%F6%F7%F8%F9%FA%FB%FC%FD%FE%FF" + +query_params : Url -> Dict Str Str +query_params = \url -> + query url + |> Str.splitOn "&" + |> List.walk (Dict.empty {}) \dict, pair -> + when Str.splitFirst pair "=" is + Ok { before, after } -> Dict.insert dict before after + Err NotFound -> Dict.insert dict pair "" diff --git a/platform/Utc.roc b/platform/Utc.roc index 3b0d6824..9415b405 100644 --- a/platform/Utc.roc +++ b/platform/Utc.roc @@ -45,15 +45,15 @@ from_nanos_since_epoch = @Utc ## Calculate milliseconds between two Utc timestamps delta_as_millis : Utc, Utc -> U128 -delta_as_millis = \utcA, utcB -> - (delta_as_nanos utcA utcB) // nanos_per_milli +delta_as_millis = \utc_a, utc_b -> + (delta_as_nanos utc_a utc_b) // nanos_per_milli ## Calculate nanoseconds between two Utc timestamps delta_as_nanos : Utc, Utc -> U128 -delta_as_nanos = \@Utc nanosA, @Utc nanosB -> +delta_as_nanos = \@Utc nanos_a, @Utc nanos_b -> # bitwiseXor for best performance - nanos_a_shifted = Num.bitwiseXor (Num.toU128 nanosA) (Num.shiftLeftBy 1 127) - nanos_b_shifted = Num.bitwiseXor (Num.toU128 nanosB) (Num.shiftLeftBy 1 127) + nanos_a_shifted = Num.bitwiseXor (Num.toU128 nanos_a) (Num.shiftLeftBy 1 127) + nanos_b_shifted = Num.bitwiseXor (Num.toU128 nanos_b) (Num.shiftLeftBy 1 127) Num.absDiff nanos_a_shifted nanos_b_shifted diff --git a/platform/glue-internal-cmd.roc b/platform/glue-internal-cmd.roc index 26484eea..ad9d8696 100644 --- a/platform/glue-internal-cmd.roc +++ b/platform/glue-internal-cmd.roc @@ -16,7 +16,5 @@ platform "glue-types" import InternalCmd -mainForHost : { - a : InternalCmd.OutputFromHost, -} +mainForHost : InternalCmd.OutputFromHost mainForHost = main diff --git a/platform/glue.roc b/platform/glue.roc deleted file mode 100644 index e0e6d7e9..00000000 --- a/platform/glue.roc +++ /dev/null @@ -1,11 +0,0 @@ -platform "" - requires {} { main : _ } - exposes [] - packages {} - imports [] - provides [mainForHost] - -import Host - -mainForHost : Host.InternalIOErr -mainForHost = main diff --git a/platform/main.roc b/platform/main.roc index d8a20a25..e813bf9e 100644 --- a/platform/main.roc +++ b/platform/main.roc @@ -21,12 +21,12 @@ platform "cli" ] packages {} imports [] - provides [mainForHost!] + provides [main_for_host!] import Stderr -mainForHost! : I32 => I32 -mainForHost! = \_ -> +main_for_host! : I32 => I32 +main_for_host! = \_ -> when main! {} is Ok {} -> 0 Err (Exit code msg) -> @@ -37,7 +37,7 @@ mainForHost! = \_ -> code Err msg -> - helpMsg = + help_msg = """ Program exited with error: $(Inspect.toStr msg) @@ -45,5 +45,5 @@ mainForHost! = \_ -> Tip: If you do not want to exit on this error, use `Result.mapErr` to handle the error. Docs for `Result.mapErr`: """ - _ = Stderr.line! helpMsg + _ = Stderr.line! help_msg 1