mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-11 18:58:24 +03:00
update to new interpolation syntax
This commit is contained in:
parent
fc6b519b59
commit
3c7a834da1
@ -883,7 +883,7 @@ mod cli_run {
|
||||
provides [main] to pf
|
||||
|
||||
main =
|
||||
Stdout.line "\nThis roc file can print it's own source code. The source is:\n\n\(ownCode)"
|
||||
Stdout.line "\nThis roc file can print it's own source code. The source is:\n\n$(ownCode)"
|
||||
|
||||
"#
|
||||
),
|
||||
|
2
crates/cli/tests/fixtures/packages/app.roc
vendored
2
crates/cli/tests/fixtures/packages/app.roc
vendored
@ -3,4 +3,4 @@ app "packages-test"
|
||||
imports [json.JsonParser, csv.Csv]
|
||||
provides [main] to pf
|
||||
|
||||
main = "Hello, World! \(JsonParser.example) \(Csv.example)"
|
||||
main = "Hello, World! $(JsonParser.example) $(Csv.example)"
|
||||
|
@ -10,7 +10,7 @@ show = \list ->
|
||||
|> List.map Num.toStr
|
||||
|> Str.joinWith ", "
|
||||
|
||||
"[\(content)]"
|
||||
"[$(content)]"
|
||||
|
||||
sortBy : List a, (a -> Num *) -> List a
|
||||
sortBy = \list, toComparable ->
|
||||
|
@ -26,7 +26,7 @@ showRBTree = \tree, showKey, showValue ->
|
||||
sL = nodeInParens left showKey showValue
|
||||
sR = nodeInParens right showKey showValue
|
||||
|
||||
"Node \(sColor) \(sKey) \(sValue) \(sL) \(sR)"
|
||||
"Node $(sColor) $(sKey) $(sValue) $(sL) $(sR)"
|
||||
|
||||
nodeInParens : RedBlackTree k v, (k -> Str), (v -> Str) -> Str
|
||||
nodeInParens = \tree, showKey, showValue ->
|
||||
@ -37,7 +37,7 @@ nodeInParens = \tree, showKey, showValue ->
|
||||
Node _ _ _ _ _ ->
|
||||
inner = showRBTree tree showKey showValue
|
||||
|
||||
"(\(inner))"
|
||||
"($(inner))"
|
||||
|
||||
showColor : NodeColor -> Str
|
||||
showColor = \color ->
|
||||
|
@ -14,7 +14,7 @@ main =
|
||||
#
|
||||
# _ ->
|
||||
# ns = Num.toStr n
|
||||
# Task.putLine "No test \(ns)"
|
||||
# Task.putLine "No test $(ns)"
|
||||
showBool : Bool -> Str
|
||||
showBool = \b ->
|
||||
if
|
||||
|
@ -857,7 +857,7 @@ increaseSize = \@Dict { data, maxBucketCapacity, maxLoadFactor, shifts } ->
|
||||
shifts: newShifts,
|
||||
}
|
||||
else
|
||||
crash "Dict hit limit of \(Num.toStr maxBucketCount) elements. Unable to grow more."
|
||||
crash "Dict hit limit of $(Num.toStr maxBucketCount) elements. Unable to grow more."
|
||||
|
||||
allocBucketsFromShift : U8, F32 -> (List Bucket, U64)
|
||||
allocBucketsFromShift = \shifts, maxLoadFactor ->
|
||||
|
@ -844,7 +844,7 @@ replaceFirst : Str, Str, Str -> Str
|
||||
replaceFirst = \haystack, needle, flower ->
|
||||
when splitFirst haystack needle is
|
||||
Ok { before, after } ->
|
||||
"\(before)\(flower)\(after)"
|
||||
"$(before)$(flower)$(after)"
|
||||
|
||||
Err NotFound -> haystack
|
||||
|
||||
@ -862,7 +862,7 @@ replaceLast : Str, Str, Str -> Str
|
||||
replaceLast = \haystack, needle, flower ->
|
||||
when splitLast haystack needle is
|
||||
Ok { before, after } ->
|
||||
"\(before)\(flower)\(after)"
|
||||
"$(before)$(flower)$(after)"
|
||||
|
||||
Err NotFound -> haystack
|
||||
|
||||
|
@ -1831,7 +1831,7 @@ mod test_can {
|
||||
// "abcd\$(efg)hij"
|
||||
// "#
|
||||
// ),
|
||||
// Str(r"abcd\(efg)hij".into()),
|
||||
// Str(r"abcd$(efg)hij".into()),
|
||||
// );
|
||||
// }
|
||||
|
||||
|
@ -5549,7 +5549,7 @@ mod test_reporting {
|
||||
r#"
|
||||
greeting = "Privet"
|
||||
|
||||
if Bool.true then 1 else "\(greeting), World!"
|
||||
if Bool.true then 1 else "$(greeting), World!"
|
||||
"#,
|
||||
),
|
||||
@r#"
|
||||
@ -5557,7 +5557,7 @@ mod test_reporting {
|
||||
|
||||
This `if` has an `else` branch with a different type from its `then` branch:
|
||||
|
||||
6│ if Bool.true then 1 else "\(greeting), World!"
|
||||
6│ if Bool.true then 1 else "$(greeting), World!"
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The `else` branch is a string of type:
|
||||
|
@ -86,7 +86,7 @@ pub enum CalledVia {
|
||||
UnaryOp(UnaryOp),
|
||||
|
||||
/// This call is the result of desugaring string interpolation,
|
||||
/// e.g. "\(first) \(last)" is transformed into Str.concat (Str.concat first " ") last.
|
||||
/// e.g. "$(first) $(last)" is transformed into Str.concat (Str.concat first " ") last.
|
||||
StringInterpolation,
|
||||
|
||||
/// This call is the result of desugaring a Record Builder field.
|
||||
|
@ -312,7 +312,7 @@ mod solve_expr {
|
||||
r#"
|
||||
whatItIs = "great"
|
||||
|
||||
"type inference is \(whatItIs)!"
|
||||
"type inference is $(whatItIs)!"
|
||||
"#
|
||||
),
|
||||
"Str",
|
||||
@ -326,7 +326,7 @@ mod solve_expr {
|
||||
r#"
|
||||
whatItIs = "great"
|
||||
|
||||
str = "type inference is \(whatItIs)!"
|
||||
str = "type inference is $(whatItIs)!"
|
||||
|
||||
whatItIs
|
||||
"#
|
||||
@ -342,7 +342,7 @@ mod solve_expr {
|
||||
r#"
|
||||
rec = { whatItIs: "great" }
|
||||
|
||||
str = "type inference is \(rec.whatItIs)!"
|
||||
str = "type inference is $(rec.whatItIs)!"
|
||||
|
||||
rec
|
||||
"#
|
||||
@ -4739,7 +4739,7 @@ mod solve_expr {
|
||||
r#"
|
||||
setRocEmail : _ -> { name: Str, email: Str }_
|
||||
setRocEmail = \person ->
|
||||
{ person & email: "\(person.name)@roclang.com" }
|
||||
{ person & email: "$(person.name)@roclang.com" }
|
||||
setRocEmail
|
||||
"#
|
||||
),
|
||||
|
@ -948,7 +948,7 @@ fn specialize_unique_newtype_records() {
|
||||
main =
|
||||
when Str.fromUtf8 (Encode.toBytes {a: Bool.true} TotallyNotJson.json) is
|
||||
Ok s -> when Str.fromUtf8 (Encode.toBytes {b: Bool.true} TotallyNotJson.json) is
|
||||
Ok t -> "\(s)\(t)"
|
||||
Ok t -> "$(s)$(t)"
|
||||
_ -> "<bad>"
|
||||
_ -> "<bad>"
|
||||
"#
|
||||
|
@ -330,7 +330,7 @@ fn list_map_try_ok() {
|
||||
List.mapTry [1, 2, 3] \num ->
|
||||
str = Num.toStr (num * 2)
|
||||
|
||||
Ok "\(str)!"
|
||||
Ok "$(str)!"
|
||||
"#,
|
||||
// Result Str [] is unwrapped to just Str
|
||||
RocList::<RocStr>::from_slice(&[
|
||||
@ -3738,10 +3738,10 @@ fn issue_3571_lowlevel_call_function_with_bool_lambda_set() {
|
||||
List.concat state mappedVals
|
||||
|
||||
add2 : Str -> Str
|
||||
add2 = \x -> "added \(x)"
|
||||
add2 = \x -> "added $(x)"
|
||||
|
||||
mul2 : Str -> Str
|
||||
mul2 = \x -> "multiplied \(x)"
|
||||
mul2 = \x -> "multiplied $(x)"
|
||||
|
||||
foo = [add2, mul2]
|
||||
bar = ["1", "2", "3", "4"]
|
||||
|
@ -3197,7 +3197,7 @@ fn recursively_build_effect() {
|
||||
hi = "Hello"
|
||||
name = "World"
|
||||
|
||||
"\(hi), \(name)!"
|
||||
"$(hi), $(name)!"
|
||||
|
||||
main =
|
||||
when nestHelp 4 is
|
||||
@ -3953,8 +3953,8 @@ fn compose_recursive_lambda_set_productive_toplevel() {
|
||||
compose = \f, g -> \x -> g (f x)
|
||||
|
||||
identity = \x -> x
|
||||
exclaim = \s -> "\(s)!"
|
||||
whisper = \s -> "(\(s))"
|
||||
exclaim = \s -> "$(s)!"
|
||||
whisper = \s -> "($(s))"
|
||||
|
||||
main =
|
||||
res: Str -> Str
|
||||
@ -3976,8 +3976,8 @@ fn compose_recursive_lambda_set_productive_nested() {
|
||||
compose = \f, g -> \x -> g (f x)
|
||||
|
||||
identity = \x -> x
|
||||
exclaim = \s -> "\(s)!"
|
||||
whisper = \s -> "(\(s))"
|
||||
exclaim = \s -> "$(s)!"
|
||||
whisper = \s -> "($(s))"
|
||||
|
||||
res: Str -> Str
|
||||
res = List.walk [ exclaim, whisper ] identity compose
|
||||
@ -3998,8 +3998,8 @@ fn compose_recursive_lambda_set_productive_inferred() {
|
||||
compose = \f, g -> \x -> g (f x)
|
||||
|
||||
identity = \x -> x
|
||||
exclaim = \s -> "\(s)!"
|
||||
whisper = \s -> "(\(s))"
|
||||
exclaim = \s -> "$(s)!"
|
||||
whisper = \s -> "($(s))"
|
||||
|
||||
res = List.walk [ exclaim, whisper ] identity compose
|
||||
res "hello"
|
||||
@ -4024,8 +4024,8 @@ fn compose_recursive_lambda_set_productive_nullable_wrapped() {
|
||||
else \x -> f (g x)
|
||||
|
||||
identity = \x -> x
|
||||
exclame = \s -> "\(s)!"
|
||||
whisper = \s -> "(\(s))"
|
||||
exclame = \s -> "$(s)!"
|
||||
whisper = \s -> "($(s))"
|
||||
|
||||
main =
|
||||
res: Str -> Str
|
||||
@ -4552,7 +4552,7 @@ fn reset_recursive_type_wraps_in_named_type() {
|
||||
Cons x xs ->
|
||||
strX = f x
|
||||
strXs = printLinkedList xs f
|
||||
"Cons \(strX) (\(strXs))"
|
||||
"Cons $(strX) ($(strXs))"
|
||||
"#
|
||||
),
|
||||
RocStr::from("Cons 2 (Cons 3 (Cons 4 (Nil)))"),
|
||||
|
@ -1679,7 +1679,7 @@ fn lambda_capture_niches_with_other_lambda_capture() {
|
||||
when val is
|
||||
_ -> ""
|
||||
|
||||
capture2 = \val -> \{} -> "\(val)"
|
||||
capture2 = \val -> \{} -> "$(val)"
|
||||
|
||||
x : [A, B, C]
|
||||
x = A
|
||||
@ -1984,7 +1984,7 @@ fn polymorphic_expression_unification() {
|
||||
]
|
||||
parseFunction : Str -> RenderTree
|
||||
parseFunction = \name ->
|
||||
last = Indent [Text ".trace(\"\(name)\")" ]
|
||||
last = Indent [Text ".trace(\"$(name)\")" ]
|
||||
Indent [last]
|
||||
|
||||
values = parseFunction "interface_header"
|
||||
@ -2540,7 +2540,7 @@ fn recursively_build_effect() {
|
||||
hi = "Hello"
|
||||
name = "World"
|
||||
|
||||
"\(hi), \(name)!"
|
||||
"$(hi), $(name)!"
|
||||
|
||||
main =
|
||||
when nestHelp 4 is
|
||||
@ -2856,8 +2856,8 @@ fn compose_recursive_lambda_set_productive_nullable_wrapped() {
|
||||
else \x -> f (g x)
|
||||
|
||||
identity = \x -> x
|
||||
exclame = \s -> "\(s)!"
|
||||
whisper = \s -> "(\(s))"
|
||||
exclame = \s -> "$(s)!"
|
||||
whisper = \s -> "($(s))"
|
||||
|
||||
main =
|
||||
res: Str -> Str
|
||||
|
@ -45,7 +45,7 @@ shape = \@Types types, id ->
|
||||
Err OutOfBounds ->
|
||||
idStr = Num.toStr (InternalTypeId.toNat id)
|
||||
|
||||
crash "TypeId #\(idStr) was not found in Types. This should never happen, and means there was a bug in `roc glue`. If you have time, please open an issue at <https://github.com/roc-lang/roc/issues>"
|
||||
crash "TypeId #$(idStr) was not found in Types. This should never happen, and means there was a bug in `roc glue`. If you have time, please open an issue at <https://github.com/roc-lang/roc/issues>"
|
||||
|
||||
alignment : Types, TypeId -> U32
|
||||
alignment = \@Types types, id ->
|
||||
@ -54,7 +54,7 @@ alignment = \@Types types, id ->
|
||||
Err OutOfBounds ->
|
||||
idStr = Num.toStr (InternalTypeId.toNat id)
|
||||
|
||||
crash "TypeId #\(idStr) was not found in Types. This should never happen, and means there was a bug in `roc glue`. If you have time, please open an issue at <https://github.com/roc-lang/roc/issues>"
|
||||
crash "TypeId #$(idStr) was not found in Types. This should never happen, and means there was a bug in `roc glue`. If you have time, please open an issue at <https://github.com/roc-lang/roc/issues>"
|
||||
|
||||
size : Types, TypeId -> U32
|
||||
size = \@Types types, id ->
|
||||
@ -63,4 +63,4 @@ size = \@Types types, id ->
|
||||
Err OutOfBounds ->
|
||||
idStr = Num.toStr (InternalTypeId.toNat id)
|
||||
|
||||
crash "TypeId #\(idStr) was not found in Types. This should never happen, and means there was a bug in `roc glue`. If you have time, please open an issue at <https://github.com/roc-lang/roc/issues>"
|
||||
crash "TypeId #$(idStr) was not found in Types. This should never happen, and means there was a bug in `roc glue`. If you have time, please open an issue at <https://github.com/roc-lang/roc/issues>"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -739,14 +739,14 @@ fn type_problem_unary_operator() {
|
||||
#[test]
|
||||
fn type_problem_string_interpolation() {
|
||||
expect_failure(
|
||||
"\"This is not a string -> \\(1)\"",
|
||||
"\"This is not a string -> $(1)\"",
|
||||
indoc!(
|
||||
r#"
|
||||
── TYPE MISMATCH ───────────────────────────────────────────────────────────────
|
||||
|
||||
This argument to this string interpolation has an unexpected type:
|
||||
|
||||
4│ "This is not a string -> \(1)"
|
||||
4│ "This is not a string -> $(1)"
|
||||
^
|
||||
|
||||
The argument is a number of type:
|
||||
@ -1503,7 +1503,7 @@ fn interpolation_with_nested_strings() {
|
||||
expect_success(
|
||||
indoc!(
|
||||
r#"
|
||||
"foo \(Str.joinWith ["a", "b", "c"] ", ") bar"
|
||||
"foo $(Str.joinWith ["a", "b", "c"] ", ") bar"
|
||||
"#
|
||||
),
|
||||
r#""foo a, b, c bar" : Str"#,
|
||||
@ -1515,7 +1515,7 @@ fn interpolation_with_num_to_str() {
|
||||
expect_success(
|
||||
indoc!(
|
||||
r#"
|
||||
"foo \(Num.toStr Num.maxI8) bar"
|
||||
"foo $(Num.toStr Num.maxI8) bar"
|
||||
"#
|
||||
),
|
||||
r#""foo 127 bar" : Str"#,
|
||||
@ -1527,7 +1527,7 @@ fn interpolation_with_operator_desugaring() {
|
||||
expect_success(
|
||||
indoc!(
|
||||
r#"
|
||||
"foo \(Num.toStr (1 + 2)) bar"
|
||||
"foo $(Num.toStr (1 + 2)) bar"
|
||||
"#
|
||||
),
|
||||
r#""foo 3 bar" : Str"#,
|
||||
@ -1542,7 +1542,7 @@ fn interpolation_with_nested_interpolation() {
|
||||
expect_failure(
|
||||
indoc!(
|
||||
r#"
|
||||
"foo \(Str.joinWith ["a\(Num.toStr 5)", "b"] "c")"
|
||||
"foo $(Str.joinWith ["a$(Num.toStr 5)", "b"] "c")"
|
||||
"#
|
||||
),
|
||||
indoc!(
|
||||
@ -1551,7 +1551,7 @@ fn interpolation_with_nested_interpolation() {
|
||||
|
||||
This string interpolation is invalid:
|
||||
|
||||
4│ "foo \(Str.joinWith ["a\(Num.toStr 5)", "b"] "c")"
|
||||
4│ "foo $(Str.joinWith ["a$(Num.toStr 5)", "b"] "c")"
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
String interpolations cannot contain newlines or other interpolations.
|
||||
|
@ -345,7 +345,7 @@ fn joinpoint_with_closure() {
|
||||
catSound = makeSound Cat
|
||||
dogSound = makeSound Dog
|
||||
gooseSound = makeSound Goose
|
||||
"Cat: \(catSound), Dog: \(dogSound), Goose: \(gooseSound)"
|
||||
"Cat: $(catSound), Dog: $(dogSound), Goose: $(gooseSound)"
|
||||
|
||||
test
|
||||
)
|
||||
@ -374,7 +374,7 @@ fn joinpoint_with_reuse() {
|
||||
Cons x xs ->
|
||||
strX = f x
|
||||
strXs = printLinkedList xs f
|
||||
"Cons \(strX) (\(strXs))"
|
||||
"Cons $(strX) ($(strXs))"
|
||||
|
||||
test =
|
||||
newList = mapLinkedList (Cons 1 (Cons 2 (Cons 3 Nil))) (\x -> x + 1)
|
||||
@ -461,7 +461,7 @@ fn tree_rebalance() {
|
||||
sL = nodeInParens left showKey showValue
|
||||
sR = nodeInParens right showKey showValue
|
||||
|
||||
"Node \(sColor) \(sKey) \(sValue) \(sL) \(sR)"
|
||||
"Node $(sColor) $(sKey) $(sValue) $(sL) $(sR)"
|
||||
|
||||
nodeInParens : RedBlackTree k v, (k -> Str), (v -> Str) -> Str
|
||||
nodeInParens = \tree, showKey, showValue ->
|
||||
@ -472,7 +472,7 @@ fn tree_rebalance() {
|
||||
Node _ _ _ _ _ ->
|
||||
inner = showRBTree tree showKey showValue
|
||||
|
||||
"(\(inner))"
|
||||
"($(inner))"
|
||||
|
||||
showColor : NodeColor -> Str
|
||||
showColor = \color ->
|
||||
@ -521,7 +521,7 @@ fn joinpoint_nullpointer() {
|
||||
Nil -> "Nil"
|
||||
Cons x xs ->
|
||||
strXs = printLinkedList xs
|
||||
"Cons \(x) (\(strXs))"
|
||||
"Cons $(x) ($(strXs))"
|
||||
|
||||
linkedListHead : LinkedList Str -> LinkedList Str
|
||||
linkedListHead = \linkedList ->
|
||||
@ -533,7 +533,7 @@ fn joinpoint_nullpointer() {
|
||||
test =
|
||||
cons = printLinkedList (linkedListHead (Cons "foo" Nil))
|
||||
nil = printLinkedList (linkedListHead (Nil))
|
||||
"\(cons) - \(nil)"
|
||||
"$(cons) - $(nil)"
|
||||
|
||||
test
|
||||
)
|
||||
|
@ -149,7 +149,7 @@ bool = \b ->
|
||||
str : Str -> Inspector GuiFormatter
|
||||
str = \s ->
|
||||
f0 <- Inspect.custom
|
||||
addNode f0 (Text "\"\(s)\"")
|
||||
addNode f0 (Text "\"$(s)\"")
|
||||
|
||||
opaque : * -> Inspector GuiFormatter
|
||||
opaque = \_ ->
|
||||
|
@ -13,6 +13,6 @@ tick = \n ->
|
||||
_ <- await (Stdout.line "🎉 SURPRISE! Happy Birthday! 🎂")
|
||||
Task.ok (Done {})
|
||||
else
|
||||
_ <- await (n |> Num.toStr |> \s -> "\(s)..." |> Stdout.line)
|
||||
_ <- await (n |> Num.toStr |> \s -> "$(s)..." |> Stdout.line)
|
||||
_ <- await Stdin.line
|
||||
Task.ok (Step (n - 1))
|
||||
|
@ -9,7 +9,7 @@ main =
|
||||
(Effect.getLine)
|
||||
\line ->
|
||||
Effect.after
|
||||
(Effect.putLine "You entered: \(line)")
|
||||
(Effect.putLine "You entered: $(line)")
|
||||
\{} ->
|
||||
Effect.after
|
||||
(Effect.putLine "It is known")
|
||||
|
@ -7,7 +7,7 @@ main : Task {} I32
|
||||
main =
|
||||
task =
|
||||
Env.decode "EDITOR"
|
||||
|> Task.await (\editor -> Stdout.line "Your favorite editor is \(editor)!")
|
||||
|> Task.await (\editor -> Stdout.line "Your favorite editor is $(editor)!")
|
||||
|> Task.await (\{} -> Env.decode "SHLVL")
|
||||
|> Task.await
|
||||
(\lvl ->
|
||||
@ -16,7 +16,7 @@ main =
|
||||
n ->
|
||||
lvlStr = Num.toStr n
|
||||
|
||||
Stdout.line "Your current shell level is \(lvlStr)!")
|
||||
Stdout.line "Your current shell level is $(lvlStr)!")
|
||||
|> Task.await \{} -> Env.decode "LETTERS"
|
||||
|
||||
Task.attempt task \result ->
|
||||
@ -24,7 +24,7 @@ main =
|
||||
Ok letters ->
|
||||
joinedLetters = Str.joinWith letters " "
|
||||
|
||||
Stdout.line "Your favorite letters are: \(joinedLetters)"
|
||||
Stdout.line "Your favorite letters are: $(joinedLetters)"
|
||||
|
||||
Err _ ->
|
||||
Stderr.line "I couldn't find your favorite letters in the environment variables!"
|
||||
|
@ -55,7 +55,7 @@ toStr = \{ scopes, stack, state, vars } ->
|
||||
stackStr = Str.joinWith (List.map stack toStrData) " "
|
||||
varsStr = Str.joinWith (List.map vars toStrData) " "
|
||||
|
||||
"\n============\nDepth: \(depth)\nState: \(stateStr)\nStack: [\(stackStr)]\nVars: [\(varsStr)]\n============\n"
|
||||
"\n============\nDepth: $(depth)\nState: $(stateStr)\nStack: [$(stackStr)]\nVars: [$(varsStr)]\n============\n"
|
||||
|
||||
with : Str, (Context -> Task {} a) -> Task {} a
|
||||
with = \path, callback ->
|
||||
|
@ -21,7 +21,7 @@ InterpreterErrors : [BadUtf8, DivByZero, EmptyStack, InvalidBooleanValue, Invali
|
||||
main : Str -> Task {} []
|
||||
main = \filename ->
|
||||
interpretFile filename
|
||||
|> Task.onFail \StringErr e -> Stdout.line "Ran into problem:\n\(e)\n"
|
||||
|> Task.onFail \StringErr e -> Stdout.line "Ran into problem:\n$(e)\n"
|
||||
|
||||
interpretFile : Str -> Task {} [StringErr Str]
|
||||
interpretFile = \filename ->
|
||||
@ -44,7 +44,7 @@ interpretFile = \filename ->
|
||||
Task.fail (StringErr "Ran into an invalid boolean that was neither false (0) or true (-1)")
|
||||
|
||||
Err (InvalidChar char) ->
|
||||
Task.fail (StringErr "Ran into an invalid character with ascii code: \(char)")
|
||||
Task.fail (StringErr "Ran into an invalid character with ascii code: $(char)")
|
||||
|
||||
Err MaxInputNumber ->
|
||||
Task.fail (StringErr "Like the original false compiler, the max input number is 320,000")
|
||||
|
@ -18,15 +18,15 @@ main =
|
||||
cwd <- Env.cwd |> Task.await
|
||||
cwdStr = Path.display cwd
|
||||
|
||||
_ <- Stdout.line "cwd: \(cwdStr)" |> Task.await
|
||||
_ <- Stdout.line "cwd: $(cwdStr)" |> Task.await
|
||||
dirEntries <- Dir.list cwd |> Task.await
|
||||
contentsStr = Str.joinWith (List.map dirEntries Path.display) "\n "
|
||||
|
||||
_ <- Stdout.line "Directory contents:\n \(contentsStr)\n" |> Task.await
|
||||
_ <- Stdout.line "Directory contents:\n $(contentsStr)\n" |> Task.await
|
||||
_ <- Stdout.line "Writing a string to out.txt" |> Task.await
|
||||
_ <- File.writeUtf8 path "a string!" |> Task.await
|
||||
contents <- File.readUtf8 path |> Task.await
|
||||
Stdout.line "I read the file back. Its contents: \"\(contents)\""
|
||||
Stdout.line "I read the file back. Its contents: \"$(contents)\""
|
||||
|
||||
Task.attempt task \result ->
|
||||
when result is
|
||||
|
@ -11,7 +11,7 @@ main =
|
||||
_ <- await (Stdout.line "What's your last name?")
|
||||
lastName <- await Stdin.line
|
||||
|
||||
Stdout.line "Hi, \(unwrap firstName) \(unwrap lastName)! 👋"
|
||||
Stdout.line "Hi, $(unwrap firstName) $(unwrap lastName)! 👋"
|
||||
|
||||
unwrap : [Input Str, End] -> Str
|
||||
unwrap = \input ->
|
||||
|
@ -7,4 +7,4 @@ app "ingested-file"
|
||||
provides [main] to pf
|
||||
|
||||
main =
|
||||
Stdout.line "\nThis roc file can print it's own source code. The source is:\n\n\(ownCode)"
|
||||
Stdout.line "\nThis roc file can print it's own source code. The source is:\n\n$(ownCode)"
|
||||
|
@ -39,7 +39,7 @@ Just so you know what to expect, our Roc functions look like this;
|
||||
``` coffee
|
||||
interpolateString : Str -> Str
|
||||
interpolateString = \name ->
|
||||
"Hello from Roc \(name)!!!🤘🤘🤘"
|
||||
"Hello from Roc $(name)!!!🤘🤘🤘"
|
||||
|
||||
|
||||
mulArrByScalar : List I32, I32 -> List I32
|
||||
|
@ -5,7 +5,7 @@ app "rocdemo"
|
||||
|
||||
interpolateString : Str -> Str
|
||||
interpolateString = \name ->
|
||||
"Hello from Roc \(name)!!!🤘🤘🤘"
|
||||
"Hello from Roc $(name)!!!🤘🤘🤘"
|
||||
|
||||
# jint is i32
|
||||
mulArrByScalar : List I32, I32 -> List I32
|
||||
|
@ -5,4 +5,4 @@ app "libhello"
|
||||
|
||||
main : Str -> Str
|
||||
main = \message ->
|
||||
"TypeScript said to Roc: \(message)! 🎉"
|
||||
"TypeScript said to Roc: $(message)! 🎉"
|
||||
|
@ -21,7 +21,7 @@ main =
|
||||
|> List.map \_ -> 1
|
||||
|> List.sum
|
||||
|> Num.toStr
|
||||
|> \countLetterA -> Stdout.line "I counted \(countLetterA) letter A's!"
|
||||
|> \countLetterA -> Stdout.line "I counted $(countLetterA) letter A's!"
|
||||
|
||||
Err _ -> Stderr.line "Ooops, something went wrong parsing letters"
|
||||
|
||||
|
@ -26,20 +26,20 @@ main =
|
||||
|> Str.joinWith ("\n")
|
||||
nMovies = List.len movies |> Num.toStr
|
||||
|
||||
Stdout.line "\(nMovies) movies were found:\n\n\(moviesString)\n\nParse success!\n"
|
||||
Stdout.line "$(nMovies) movies were found:\n\n$(moviesString)\n\nParse success!\n"
|
||||
|
||||
Err problem ->
|
||||
when problem is
|
||||
ParsingFailure failure ->
|
||||
Stderr.line "Parsing failure: \(failure)\n"
|
||||
Stderr.line "Parsing failure: $(failure)\n"
|
||||
|
||||
ParsingIncomplete leftover ->
|
||||
leftoverStr = leftover |> List.map strFromUtf8 |> List.map (\val -> "\"\(val)\"") |> Str.joinWith ", "
|
||||
leftoverStr = leftover |> List.map strFromUtf8 |> List.map (\val -> "\"$(val)\"") |> Str.joinWith ", "
|
||||
|
||||
Stderr.line "Parsing incomplete. Following leftover fields while parsing a record: \(leftoverStr)\n"
|
||||
Stderr.line "Parsing incomplete. Following leftover fields while parsing a record: $(leftoverStr)\n"
|
||||
|
||||
SyntaxError error ->
|
||||
Stderr.line "Parsing failure. Syntax error in the CSV: \(error)"
|
||||
Stderr.line "Parsing failure. Syntax error in the CSV: $(error)"
|
||||
|
||||
MovieInfo := { title : Str, releaseYear : U64, actors : List Str }
|
||||
|
||||
@ -57,7 +57,7 @@ movieInfoExplanation = \@MovieInfo { title, releaseYear, actors } ->
|
||||
enumeratedActors = enumerate actors
|
||||
releaseYearStr = Num.toStr releaseYear
|
||||
|
||||
"The movie '\(title)' was released in \(releaseYearStr) and stars \(enumeratedActors)"
|
||||
"The movie '$(title)' was released in $(releaseYearStr) and stars $(enumeratedActors)"
|
||||
|
||||
enumerate : List Str -> Str
|
||||
enumerate = \elements ->
|
||||
|
@ -10,4 +10,4 @@ main = \num ->
|
||||
else
|
||||
str = Num.toStr num
|
||||
|
||||
"The number was \(str), OH YEAH!!! 🤘🤘"
|
||||
"The number was $(str), OH YEAH!!! 🤘🤘"
|
||||
|
@ -10,4 +10,4 @@ main = \num ->
|
||||
else
|
||||
str = Num.toStr num
|
||||
|
||||
"The number was \(str), OH YEAH!!! 🤘🤘"
|
||||
"The number was $(str), OH YEAH!!! 🤘🤘"
|
||||
|
@ -208,29 +208,29 @@ renderHelp = \buffer, node ->
|
||||
Str.concat buffer content
|
||||
|
||||
Element tagName _ attrs children ->
|
||||
withTagName = "\(buffer)<\(tagName)"
|
||||
withTagName = "$(buffer)<$(tagName)"
|
||||
withAttrs =
|
||||
if List.isEmpty attrs then
|
||||
withTagName
|
||||
else
|
||||
List.walk attrs "\(withTagName) " renderAttr
|
||||
List.walk attrs "$(withTagName) " renderAttr
|
||||
withTag = Str.concat withAttrs ">"
|
||||
withChildren = List.walk children withTag renderHelp
|
||||
|
||||
"\(withChildren)</\(tagName)>"
|
||||
"$(withChildren)</$(tagName)>"
|
||||
|
||||
UnclosedElem tagName _ attrs ->
|
||||
if List.isEmpty attrs then
|
||||
"\(buffer)<\(tagName)>"
|
||||
"$(buffer)<$(tagName)>"
|
||||
else
|
||||
attrs
|
||||
|> List.walk "\(buffer)<\(tagName) " renderAttr
|
||||
|> List.walk "$(buffer)<$(tagName) " renderAttr
|
||||
|> Str.concat ">"
|
||||
|
||||
# internal helper
|
||||
renderAttr : Str, Attribute -> Str
|
||||
renderAttr = \buffer, Attribute key val ->
|
||||
"\(buffer) \(key)=\"\(val)\""
|
||||
"$(buffer) $(key)=\"$(val)\""
|
||||
|
||||
# Main root
|
||||
html = element "html"
|
||||
|
@ -184,7 +184,7 @@ coords = attribute "coords"
|
||||
crossorigin = attribute "crossorigin"
|
||||
csp = attribute "csp"
|
||||
data = attribute "data"
|
||||
dataAttr = \dataName, dataVal -> Attribute "data-\(dataName)" dataVal
|
||||
dataAttr = \dataName, dataVal -> Attribute "data-$(dataName)" dataVal
|
||||
datetime = attribute "datetime"
|
||||
decoding = attribute "decoding"
|
||||
default = attribute "default"
|
||||
|
@ -28,7 +28,7 @@ render = \state ->
|
||||
head [] [],
|
||||
body [] [
|
||||
h1 [] [text "The app"],
|
||||
div [] [text "The answer is \(num)"],
|
||||
div [] [text "The answer is $(num)"],
|
||||
],
|
||||
]
|
||||
|
||||
|
@ -762,7 +762,7 @@ expect
|
||||
# Sizes don't matter, use zero. We are not creating a HTML string so we don't care what size it would be.
|
||||
Element "body" 0 [] [
|
||||
Element "h1" 0 [] [Text "The app"],
|
||||
Element "div" 0 [onClickAttr] [Text "The answer is \(num)"],
|
||||
Element "div" 0 [onClickAttr] [Text "The answer is $(num)"],
|
||||
]
|
||||
|
||||
app : App State State
|
||||
|
@ -38,7 +38,7 @@ logRequest : Request -> Task {} AppError
|
||||
logRequest = \req ->
|
||||
dateTime <- Utc.now |> Task.map Utc.toIso8601Str |> Task.await
|
||||
|
||||
Stdout.line "\(dateTime) \(Http.methodToStr req.method) \(req.url)"
|
||||
Stdout.line "$(dateTime) $(Http.methodToStr req.method) $(req.url)"
|
||||
|
||||
readUrlEnv : Str -> Task Str AppError
|
||||
readUrlEnv = \target ->
|
||||
@ -60,7 +60,7 @@ handleErr = \err ->
|
||||
HttpError _ -> "Http error fetching content"
|
||||
|
||||
# Log error to stderr
|
||||
{} <- Stderr.line "Internal Server Error: \(message)" |> Task.await
|
||||
{} <- Stderr.line "Internal Server Error: $(message)" |> Task.await
|
||||
_ <- Stderr.flush |> Task.attempt
|
||||
|
||||
# Respond with Http 500 Error
|
||||
|
@ -13,7 +13,7 @@ main = \req ->
|
||||
|
||||
# Log request date, method and url
|
||||
date <- Utc.now |> Task.map Utc.toIso8601Str |> Task.await
|
||||
{} <- Stdout.line "\(date) \(Http.methodToStr req.method) \(req.url)" |> Task.await
|
||||
{} <- Stdout.line "$(date) $(Http.methodToStr req.method) $(req.url)" |> Task.await
|
||||
|
||||
# Respond with request body
|
||||
when req.body is
|
||||
|
@ -36,7 +36,7 @@ view =
|
||||
Newline,
|
||||
Desc [Ident "user", Kw "<-", Ident "Http.get", Ident "url", Ident "Json.codec", Kw "|>", Ident "Task.await"] "<p>This fetches the contents of the URL and decodes them as <a href=\"https://www.json.org\">JSON</a>.</p><p>If the shape of the JSON isn't compatible with the type of <code>user</code> (based on type inference), this will give a decoding error immediately.</p><p>As with all the other lines ending in <code>|> Task.await</code>, if there's an error, nothing else in <code>storeEmail</code> will be run, and <code>handleErr</code> will end up handling the error.</p>",
|
||||
Newline,
|
||||
Desc [Ident "dest", Kw "=", Ident "Path.fromStr", StrInterpolation "\"" "user.name" ".txt\""] "<p>The <code>\\(user.name)</code> in this string literal will be replaced with the value in <code>name</code>. This is <a href=\"/tutorial#string-interpolation\">string interpolation</a>.</p><p>Note that this line doesn't end with <code>|> Task.await</code>. Earlier lines needed that because they were I/O <a href=\"/tutorial#tasks\">tasks</a>, but this is a plain old <a href=\"/tutorial#defs\">definition</a>, so there's no task to await.</p>",
|
||||
Desc [Ident "dest", Kw "=", Ident "Path.fromStr", StrInterpolation "\"" "user.name" ".txt\""] "<p>The <code>\$(user.name)</code> in this string literal will be replaced with the value in <code>name</code>. This is <a href=\"/tutorial#string-interpolation\">string interpolation</a>.</p><p>Note that this line doesn't end with <code>|> Task.await</code>. Earlier lines needed that because they were I/O <a href=\"/tutorial#tasks\">tasks</a>, but this is a plain old <a href=\"/tutorial#defs\">definition</a>, so there's no task to await.</p>",
|
||||
Newline,
|
||||
Desc [Literal "_", Kw "<-", Ident "File.writeUtf8", Ident "dest", Ident "user.email", Kw "|>", Ident "Task.await"] "<p>This writes <code>user.email</code> to the file, encoded as <a href=\"https://en.wikipedia.org/wiki/UTF-8\">UTF-8</a>.</p><p>We won't be using the output of <code>writeUtf8</code>, so we name it <code>_</code>. The special name <code>_</code> is for when you don't want to use something.</p><p>You can name as many things as you like <code>_</code>, but you can never reference anything named <code>_</code>. So it's only useful for when you don't want to choose a name.</p>",
|
||||
Newline,
|
||||
@ -89,7 +89,7 @@ tokensToStr = \tokens ->
|
||||
# Don't put spaces after opening parens or before closing parens
|
||||
argsWithCommas =
|
||||
args
|
||||
|> List.map \ident -> "<span class=\"ident\">\(ident)</span>"
|
||||
|> List.map \ident -> "<span class=\"ident\">$(ident)</span>"
|
||||
|> Str.joinWith "<span class=\"literal\">,</span> "
|
||||
|
||||
bufWithSpace
|
||||
@ -98,32 +98,32 @@ tokensToStr = \tokens ->
|
||||
|> Str.concat "<span class=\"kw\"> -></span>"
|
||||
|
||||
Kw str ->
|
||||
Str.concat bufWithSpace "<span class=\"kw\">\(str)</span>"
|
||||
Str.concat bufWithSpace "<span class=\"kw\">$(str)</span>"
|
||||
|
||||
Num str | Str str | Literal str -> # We may render these differently in the future
|
||||
Str.concat bufWithSpace "<span class=\"literal\">\(str)</span>"
|
||||
Str.concat bufWithSpace "<span class=\"literal\">$(str)</span>"
|
||||
|
||||
Comment str ->
|
||||
Str.concat bufWithSpace "<span class=\"comment\"># \(str)</span>"
|
||||
Str.concat bufWithSpace "<span class=\"comment\"># $(str)</span>"
|
||||
|
||||
Ident str ->
|
||||
Str.concat bufWithSpace (identToHtml str)
|
||||
|
||||
StrInterpolation before interp after ->
|
||||
bufWithSpace
|
||||
|> Str.concat (if Str.isEmpty before then "" else "<span class=\"literal\">\(before)</span>")
|
||||
|> Str.concat "<span class=\"kw\">\\(</span>\(identToHtml interp)<span class=\"kw\">)</span>"
|
||||
|> Str.concat (if Str.isEmpty after then "" else "<span class=\"literal\">\(after)</span>")
|
||||
|> Str.concat (if Str.isEmpty before then "" else "<span class=\"literal\">$(before)</span>")
|
||||
|> Str.concat "<span class=\"kw\">\$(</span>$(identToHtml interp)<span class=\"kw\">)</span>"
|
||||
|> Str.concat (if Str.isEmpty after then "" else "<span class=\"literal\">$(after)</span>")
|
||||
|
||||
identToHtml : Str -> Str
|
||||
identToHtml = \str ->
|
||||
List.walk (Str.split str ".") "" \accum, ident ->
|
||||
identHtml = "<span class=\"ident\">\(ident)</span>"
|
||||
identHtml = "<span class=\"ident\">$(ident)</span>"
|
||||
|
||||
if Str.isEmpty accum then
|
||||
identHtml
|
||||
else
|
||||
"\(accum)<span class=\"kw\">.</span>\(identHtml)"
|
||||
"$(accum)<span class=\"kw\">.</span>$(identHtml)"
|
||||
|
||||
sectionsToStr : List Section -> Str
|
||||
sectionsToStr = \sections ->
|
||||
@ -168,5 +168,5 @@ radio = \index, labelHtml, descHtml ->
|
||||
checkedHtml = if index == 0 then " checked" else ""
|
||||
|
||||
"""
|
||||
<input class="interactive-radio" type="radio" name="r" id="r\(Num.toStr index)" \(checkedHtml)><label for="r\(Num.toStr index)" title="Tap to learn about this syntax">\(labelHtml)</label><span class="interactive-desc" role="presentation"><button class="close-desc">X</button>\(descHtml)</span>
|
||||
<input class="interactive-radio" type="radio" name="r" id="r$(Num.toStr index)" $(checkedHtml)><label for="r$(Num.toStr index)" title="Tap to learn about this syntax">$(labelHtml)</label><span class="interactive-desc" role="presentation"><button class="close-desc">X</button>$(descHtml)</span>
|
||||
"""
|
||||
|
@ -9,7 +9,7 @@ Roc's syntax isn't trivial, but there also isn't much of it to learn. It's desig
|
||||
- `user.email` always accesses the `email` field of a record named `user`. <span class="nowrap">(Roc has</span> no inheritance, subclassing, or proxying.)
|
||||
- `Email.isValid` always refers to something named `isValid` exported by a module named `Email`. (Module names are always capitalized, and variables/constants never are.) Modules are always defined statically and can't be modified at runtime; there's no [monkey patching](https://en.wikipedia.org/wiki/Monkey_patch) to consider either.
|
||||
- `x = doSomething y z` always declares a new constant `x` (Roc has [no mutable variables, reassignment, or shadowing](/functional)) to be whatever the `doSomething` function returns when passed the arguments `y` and `z`. (Function calls in Roc don't need parentheses or commas.)
|
||||
- `"Name: \(Str.trim name)"` uses *string interpolation* syntax: a backslash inside a string literal, followed by an expression in parentheses. This code is the same as combining the string `"Name: "` with the string returned by the function call `Str.trim name`.<br><br>Because Roc's string interpolation syntax begins with a backslash (just like other backlash-escapes such as `\n` and `\"`), you can always tell which parts of a string involve special handling: the parts that begin with backslashes. Everything else works as normal.
|
||||
- `"Name: $(Str.trim name)"` uses *string interpolation* syntax: a backslash inside a string literal, followed by an expression in parentheses. This code is the same as combining the string `"Name: "` with the string returned by the function call `Str.trim name`.<br><br>Because Roc's string interpolation syntax begins with a backslash (just like other backlash-escapes such as `\n` and `\"`), you can always tell which parts of a string involve special handling: the parts that begin with backslashes. Everything else works as normal.
|
||||
|
||||
Roc also ships with a source code formatter that helps you maintain a consistent style with little effort. The `roc format` command neatly formats your source code according to a common style, and it's designed with the time-saving feature of having no configuration options. This feature saves teams all the time they would otherwise spend debating which stylistic tweaks to settle on!
|
||||
|
||||
|
@ -65,7 +65,7 @@ A benefit of this design is that it makes Roc code easier to rearrange without c
|
||||
|
||||
<pre><samp class="code-snippet">func <span class="kw">=</span> <span class="kw">\</span>arg <span class="kw">-></span>
|
||||
greeting <span class="kw">=</span> <span class="string">"Hello"</span>
|
||||
welcome <span class="kw">=</span> <span class="kw">\</span>name <span class="kw">-></span> <span class="string">"</span><span class="kw">\(</span>greeting<span class="kw">)</span><span class="string">, </span><span class="kw">\(</span>name<span class="kw">)</span><span class="string">!"</span>
|
||||
welcome <span class="kw">=</span> <span class="kw">\</span>name <span class="kw">-></span> <span class="string">"</span><span class="kw">$(</span>greeting<span class="kw">)</span><span class="string">, </span><span class="kw">$(</span>name<span class="kw">)</span><span class="string">!"</span>
|
||||
|
||||
<span class="comment"># …</span>
|
||||
|
||||
@ -82,7 +82,7 @@ Suppose I decide to extract the `welcome` function to the top level, so I can re
|
||||
|
||||
<span class="comment"># …</span>
|
||||
|
||||
welcome <span class="kw">=</span> <span class="kw">\</span>prefix<span class="punctuation section">,</span> name <span class="kw">-></span> <span class="string">"</span><span class="kw">\(</span>prefix<span class="kw">)</span><span class="string">, </span><span class="kw">\(</span>name<span class="kw">)</span><span class="string">!"</span></samp></pre>
|
||||
welcome <span class="kw">=</span> <span class="kw">\</span>prefix<span class="punctuation section">,</span> name <span class="kw">-></span> <span class="string">"</span><span class="kw">$(</span>prefix<span class="kw">)</span><span class="string">, </span><span class="kw">$(</span>name<span class="kw">)</span><span class="string">!"</span></samp></pre>
|
||||
|
||||
Even without knowing the rest of `func`, we can be confident this change will not alter the code's behavior.
|
||||
|
||||
@ -90,7 +90,7 @@ In contrast, suppose Roc allowed reassignment. Then it's possible something in t
|
||||
|
||||
<pre><samp class="code-snippet">func <span class="kw">=</span> <span class="kw">\</span>arg <span class="kw">-></span>
|
||||
greeting <span class="kw">=</span> <span class="string">"Hello"</span>
|
||||
welcome <span class="kw">=</span> <span class="kw">\</span>name <span class="kw">-></span> <span class="string">"</span><span class="kw">\(</span>greeting<span class="kw">)</span><span class="string">, </span><span class="kw">\(</span>name<span class="kw">)</span><span class="string">!"</span>
|
||||
welcome <span class="kw">=</span> <span class="kw">\</span>name <span class="kw">-></span> <span class="string">"</span><span class="kw">$(</span>greeting<span class="kw">)</span><span class="string">, </span><span class="kw">$(</span>name<span class="kw">)</span><span class="string">!"</span>
|
||||
|
||||
<span class="comment"># …</span>
|
||||
|
||||
|
@ -40,10 +40,10 @@ const repl = {
|
||||
},
|
||||
{
|
||||
match: (input) => input.replace(/ /g, "").match(/^name="/i),
|
||||
show: '<p>This created a new <a href="https://www.roc-lang.org/tutorial#defs">definition</a>—<code>name</code> is now defined to be equal to the <a href="/tutorial#strings-and-numbers">string</a> you entered.</p><p>Try using this definition by entering <code>"Hi, \\(name)!"</code></p>',
|
||||
show: '<p>This created a new <a href="https://www.roc-lang.org/tutorial#defs">definition</a>—<code>name</code> is now defined to be equal to the <a href="/tutorial#strings-and-numbers">string</a> you entered.</p><p>Try using this definition by entering <code>"Hi, \$(name)!"</code></p>',
|
||||
},
|
||||
{
|
||||
match: (input) => input.match(/^["][^\\]+\\\(name\)/i),
|
||||
match: (input) => input.match(/^["][^\\]+\\$(name\)/i),
|
||||
show: `<p>Nicely done! This is an example of <a href=\"/tutorial#string-interpolation\">string interpolation</a>, which replaces part of a string with whatever you put inside the parentheses after a <code>\\</code>.</p><p>Now that you’ve written a few <a href=\"/tutorial#naming-things\">expressions</a>, you can either continue exploring in this REPL, or move on to the <a href=\"/tutorial\">tutorial</a> to learn how to make full programs.<p><p><span class='welcome-to-roc'>Welcome to Roc!</span> <a href='/tutorial' class='btn-small'>${tutorialButtonSvg} Start Tutorial</a></p>`,
|
||||
},
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user