Merge pull request #7463 from smores56/auto-snake-case

Move builtins to snake_case
This commit is contained in:
Sam Mohr 2025-01-08 12:02:42 -08:00 committed by GitHub
commit 96fc573b6b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
398 changed files with 17912 additions and 12239 deletions

View file

@ -23,8 +23,8 @@ initial_model = \start -> {
cheapest_open : (position -> F64), Model position -> Result position {} where position implements Hash & Eq
cheapest_open = \cost_fn, model ->
model.open_set
|> Set.toList
|> List.keepOks(
|> Set.to_list
|> List.keep_oks(
\position ->
when Dict.get(model.costs, position) is
Err(_) -> Err({})
@ -33,7 +33,7 @@ cheapest_open = \cost_fn, model ->
|> Quicksort.sort_by(.cost)
|> List.first
|> Result.map(.position)
|> Result.mapErr(\_ -> {})
|> Result.map_err(\_ -> {})
reconstruct_path : Dict position position, position -> List position where position implements Hash & Eq
reconstruct_path = \came_from, goal ->
@ -52,7 +52,7 @@ update_cost = \current, neighbor, model ->
distance_to =
reconstruct_path(new_came_from, neighbor)
|> List.len
|> Num.toFrac
|> Num.to_frac
new_model =
{ model &

View file

@ -16,7 +16,7 @@ from_bytes = \bytes ->
# base 64 encoding from a string
from_str : Str -> Result Str [InvalidInput]
from_str = \str ->
from_bytes(Str.toUtf8(str))
from_bytes(Str.to_utf8(str))
# base64-encode bytes to the original
to_bytes : Str -> Result (List U8) [InvalidInput]
@ -27,7 +27,7 @@ to_str : Str -> Result Str [InvalidInput]
to_str = \str ->
when to_bytes(str) is
Ok(bytes) ->
when Str.fromUtf8(bytes) is
when Str.from_utf8(bytes) is
Ok(v) ->
Ok(v)

View file

@ -14,12 +14,12 @@ loop_help = \{ remaining, string } ->
if remaining >= 3 then
Bytes.Decode.map3(Bytes.Decode.u8, Bytes.Decode.u8, Bytes.Decode.u8, \x, y, z ->
a : U32
a = Num.intCast(x)
a = Num.int_cast(x)
b : U32
b = Num.intCast(y)
b = Num.int_cast(y)
c : U32
c = Num.intCast(z)
combined = Num.bitwiseOr(Num.bitwiseOr(Num.shiftLeftBy(a, 16), Num.shiftLeftBy(b, 8)), c)
c = Num.int_cast(z)
combined = Num.bitwise_or(Num.bitwise_or(Num.shift_left_by(a, 16), Num.shift_left_by(b, 8)), c)
Loop({
remaining: remaining - 3,
@ -31,10 +31,10 @@ loop_help = \{ remaining, string } ->
Bytes.Decode.map2(Bytes.Decode.u8, Bytes.Decode.u8, \x, y ->
a : U32
a = Num.intCast(x)
a = Num.int_cast(x)
b : U32
b = Num.intCast(y)
combined = Num.bitwiseOr(Num.shiftLeftBy(a, 16), Num.shiftLeftBy(b, 8))
b = Num.int_cast(y)
combined = Num.bitwise_or(Num.shift_left_by(a, 16), Num.shift_left_by(b, 8))
Done(Str.concat(string, bits_to_chars(combined, 1))))
else
@ -42,13 +42,13 @@ loop_help = \{ remaining, string } ->
Bytes.Decode.map(Bytes.Decode.u8, \x ->
a : U32
a = Num.intCast(x)
a = Num.int_cast(x)
Done(Str.concat(string, bits_to_chars(Num.shiftLeftBy(a, 16), 2))))
Done(Str.concat(string, bits_to_chars(Num.shift_left_by(a, 16), 2))))
bits_to_chars : U32, Int * -> Str
bits_to_chars = \bits, missing ->
when Str.fromUtf8(bits_to_chars_help(bits, missing)) is
when Str.from_utf8(bits_to_chars_help(bits, missing)) is
Ok(str) -> str
Err(_) -> ""
@ -63,23 +63,23 @@ bits_to_chars_help = \bits, missing ->
# with `0b111111` (which is 2^6 - 1 or 63) (so, 6 1s) to remove unwanted bits on the left.
# any 6-bit number is a valid base64 digit, so this is actually safe
p =
Num.shiftRightZfBy(bits, 18)
|> Num.intCast
Num.shift_right_zf_by(bits, 18)
|> Num.int_cast
|> unsafe_to_char
q =
Num.bitwiseAnd(Num.shiftRightZfBy(bits, 12), lowest6_bits_mask)
|> Num.intCast
Num.bitwise_and(Num.shift_right_zf_by(bits, 12), lowest6_bits_mask)
|> Num.int_cast
|> unsafe_to_char
r =
Num.bitwiseAnd(Num.shiftRightZfBy(bits, 6), lowest6_bits_mask)
|> Num.intCast
Num.bitwise_and(Num.shift_right_zf_by(bits, 6), lowest6_bits_mask)
|> Num.int_cast
|> unsafe_to_char
s =
Num.bitwiseAnd(bits, lowest6_bits_mask)
|> Num.intCast
Num.bitwise_and(bits, lowest6_bits_mask)
|> Num.int_cast
|> unsafe_to_char
equals : U8

View file

@ -8,7 +8,7 @@ InvalidChar : U8
to_bytes : Str -> List U8
to_bytes = \str ->
str
|> Str.toUtf8
|> Str.to_utf8
|> encode_chunks
|> Bytes.Encode.sequence
|> Bytes.Encode.encode
@ -73,18 +73,18 @@ encode_characters = \a, b, c, d ->
n2 = unsafe_convert_char(b)
x : U32
x = Num.intCast(n1)
x = Num.int_cast(n1)
y : U32
y = Num.intCast(n2)
y = Num.int_cast(n2)
if d == equals then
if c == equals then
n = Num.bitwiseOr(Num.shiftLeftBy(x, 18), Num.shiftLeftBy(y, 12))
n = Num.bitwise_or(Num.shift_left_by(x, 18), Num.shift_left_by(y, 12))
# masking higher bits is not needed, Encode.unsignedInt8 ignores higher bits
b1 : U8
b1 = Num.intCast(Num.shiftRightBy(n, 16))
b1 = Num.int_cast(Num.shift_right_by(n, 16))
Ok(Bytes.Encode.u8(b1))
else if !(is_valid_char(c)) then
@ -93,12 +93,12 @@ encode_characters = \a, b, c, d ->
n3 = unsafe_convert_char(c)
z : U32
z = Num.intCast(n3)
z = Num.int_cast(n3)
n = Num.bitwiseOr(Num.bitwiseOr(Num.shiftLeftBy(x, 18), Num.shiftLeftBy(y, 12)), Num.shiftLeftBy(z, 6))
n = Num.bitwise_or(Num.bitwise_or(Num.shift_left_by(x, 18), Num.shift_left_by(y, 12)), Num.shift_left_by(z, 6))
combined : U16
combined = Num.intCast(Num.shiftRightBy(n, 8))
combined = Num.int_cast(Num.shift_right_by(n, 8))
Ok(Bytes.Encode.u16(BE, combined))
else if !(is_valid_char(d)) then
@ -108,22 +108,22 @@ encode_characters = \a, b, c, d ->
n4 = unsafe_convert_char(d)
z : U32
z = Num.intCast(n3)
z = Num.int_cast(n3)
w : U32
w = Num.intCast(n4)
w = Num.int_cast(n4)
n =
Num.bitwiseOr(
Num.bitwiseOr(Num.shiftLeftBy(x, 18), Num.shiftLeftBy(y, 12)),
Num.bitwiseOr(Num.shiftLeftBy(z, 6), w),
Num.bitwise_or(
Num.bitwise_or(Num.shift_left_by(x, 18), Num.shift_left_by(y, 12)),
Num.bitwise_or(Num.shift_left_by(z, 6), w),
)
b3 : U8
b3 = Num.intCast(n)
b3 = Num.int_cast(n)
combined : U16
combined = Num.intCast(Num.shiftRightBy(n, 8))
combined = Num.int_cast(Num.shift_right_by(n, 8))
Ok(Bytes.Encode.sequence([Bytes.Encode.u16(BE, combined), Bytes.Encode.u8(b3)]))

View file

@ -7,105 +7,111 @@ DecodeProblem : [OutOfBytes]
ByteDecoder a := State -> [Good State a, Bad DecodeProblem]
decode : List U8, ByteDecoder a -> Result a DecodeProblem
decode = \bytes, @ByteDecoder decoder ->
when decoder { bytes, cursor: 0 } is
Good _ value ->
Ok value
decode = \bytes, @ByteDecoder(decoder) ->
when decoder({ bytes, cursor: 0 }) is
Good(_, value) ->
Ok(value)
Bad e ->
Err e
Bad(e) ->
Err(e)
succeed : a -> ByteDecoder a
succeed = \value -> @ByteDecoder \state -> Good state value
succeed = \value -> @ByteDecoder(\state -> Good(state, value))
map : ByteDecoder a, (a -> b) -> ByteDecoder b
map = \@ByteDecoder decoder, transform ->
@ByteDecoder
map = \@ByteDecoder(decoder), transform ->
@ByteDecoder(
\state ->
when decoder state is
Good state1 value ->
Good state1 (transform value)
when decoder(state) is
Good(state1, value) ->
Good(state1, transform(value))
Bad e ->
Bad e
Bad(e) ->
Bad(e),
)
map2 : ByteDecoder a, ByteDecoder b, (a, b -> c) -> ByteDecoder c
map2 = \@ByteDecoder decoder1, @ByteDecoder decoder2, transform ->
@ByteDecoder
map2 = \@ByteDecoder(decoder1), @ByteDecoder(decoder2), transform ->
@ByteDecoder(
\state1 ->
when decoder1 state1 is
Good state2 a ->
when decoder2 state2 is
Good state3 b ->
Good state3 (transform a b)
when decoder1(state1) is
Good(state2, a) ->
when decoder2(state2) is
Good(state3, b) ->
Good(state3, transform(a, b))
Bad e ->
Bad e
Bad(e) ->
Bad(e)
Bad e ->
Bad e
Bad(e) ->
Bad(e),
)
map3 : ByteDecoder a, ByteDecoder b, ByteDecoder c, (a, b, c -> d) -> ByteDecoder d
map3 = \@ByteDecoder decoder1, @ByteDecoder decoder2, @ByteDecoder decoder3, transform ->
@ByteDecoder
map3 = \@ByteDecoder(decoder1), @ByteDecoder(decoder2), @ByteDecoder(decoder3), transform ->
@ByteDecoder(
\state1 ->
when decoder1 state1 is
Good state2 a ->
when decoder2 state2 is
Good state3 b ->
when decoder3 state3 is
Good state4 c ->
Good state4 (transform a b c)
when decoder1(state1) is
Good(state2, a) ->
when decoder2(state2) is
Good(state3, b) ->
when decoder3(state3) is
Good(state4, c) ->
Good(state4, transform(a, b, c))
Bad e ->
Bad e
Bad(e) ->
Bad(e)
Bad e ->
Bad e
Bad(e) ->
Bad(e)
Bad e ->
Bad e
Bad(e) ->
Bad(e),
)
after : ByteDecoder a, (a -> ByteDecoder b) -> ByteDecoder b
after = \@ByteDecoder decoder, transform ->
@ByteDecoder
after = \@ByteDecoder(decoder), transform ->
@ByteDecoder(
\state ->
when decoder state is
Good state1 value ->
(@ByteDecoder decoder1) = transform value
when decoder(state) is
Good(state1, value) ->
@ByteDecoder(decoder1) = transform(value)
decoder1 state1
decoder1(state1)
Bad e ->
Bad e
Bad(e) ->
Bad(e),
)
u8 : ByteDecoder U8
u8 = @ByteDecoder
u8 = @ByteDecoder(
\state ->
when List.get state.bytes state.cursor is
Ok b ->
Good { state & cursor: state.cursor + 1 } b
when List.get(state.bytes, state.cursor) is
Ok(b) ->
Good({ state & cursor: state.cursor + 1 }, b)
Err _ ->
Bad OutOfBytes
Err(_) ->
Bad(OutOfBytes),
)
Step state b : [Loop state, Done b]
loop : (state -> ByteDecoder (Step state a)), state -> ByteDecoder a
loop = \stepper, initial ->
@ByteDecoder
@ByteDecoder(
\state ->
loopHelp stepper initial state
loop_help(stepper, initial, state),
)
loopHelp = \stepper, accum, state ->
(@ByteDecoder stepper1) = stepper accum
loop_help = \stepper, accum, state ->
@ByteDecoder(stepper1) = stepper(accum)
when stepper1 state is
Good newState (Done value) ->
Good newState value
when stepper1(state) is
Good(new_state, Done(value)) ->
Good(new_state, value)
Good newState (Loop newAccum) ->
loopHelp stepper newAccum newState
Good(new_state, Loop(new_accum)) ->
loop_help(stepper, new_accum, new_state)
Bad e ->
Bad e
Bad(e) ->
Bad(e)

View file

@ -5,130 +5,132 @@ Endianness : [BE, LE]
ByteEncoder : [Signed8 I8, Unsigned8 U8, Signed16 Endianness I16, Unsigned16 Endianness U16, Sequence U64 (List ByteEncoder), Bytes (List U8)]
u8 : U8 -> ByteEncoder
u8 = \value -> Unsigned8 value
u8 = \value -> Unsigned8(value)
empty : ByteEncoder
empty =
foo : List ByteEncoder
foo = []
Sequence 0 foo
Sequence(0, foo)
u16 : Endianness, U16 -> ByteEncoder
u16 = \endianness, value -> Unsigned16 endianness value
u16 = \endianness, value -> Unsigned16(endianness, value)
bytes : List U8 -> ByteEncoder
bytes = \bs -> Bytes bs
bytes = \bs -> Bytes(bs)
sequence : List ByteEncoder -> ByteEncoder
sequence = \encoders ->
Sequence (getWidths encoders 0) encoders
Sequence(get_widths(encoders, 0), encoders)
getWidth : ByteEncoder -> U64
getWidth = \encoder ->
get_width : ByteEncoder -> U64
get_width = \encoder ->
when encoder is
Signed8 _ -> 1
Unsigned8 _ -> 1
Signed16 _ _ -> 2
Unsigned16 _ _ -> 2
Signed8(_) -> 1
Unsigned8(_) -> 1
Signed16(_, _) -> 2
Unsigned16(_, _) -> 2
# Signed32 _ -> 4
# Unsigned32 _ -> 4
# Signed64 _ -> 8
# Unsigned64 _ -> 8
# Signed128 _ -> 16
# Unsigned128 _ -> 16
Sequence w _ -> w
Bytes bs -> List.len bs
Sequence(w, _) -> w
Bytes(bs) -> List.len(bs)
getWidths : List ByteEncoder, U64 -> U64
getWidths = \encoders, initial ->
List.walk encoders initial \accum, encoder -> accum + getWidth encoder
get_widths : List ByteEncoder, U64 -> U64
get_widths = \encoders, initial ->
List.walk(encoders, initial, \accum, encoder -> accum + get_width(encoder))
encode : ByteEncoder -> List U8
encode = \encoder ->
output = List.repeat 0 (getWidth encoder)
output = List.repeat(0, get_width(encoder))
encodeHelp encoder 0 output
encode_help(encoder, 0, output)
|> .output
encodeHelp : ByteEncoder, U64, List U8 -> { output : List U8, offset : U64 }
encodeHelp = \encoder, offset, output ->
encode_help : ByteEncoder, U64, List U8 -> { output : List U8, offset : U64 }
encode_help = \encoder, offset, output ->
when encoder is
Unsigned8 value ->
Unsigned8(value) ->
{
output: List.set output offset value,
output: List.set(output, offset, value),
offset: offset + 1,
}
Signed8 value ->
Signed8(value) ->
cast : U8
cast = Num.intCast value
cast = Num.int_cast(value)
{
output: List.set output offset cast,
output: List.set(output, offset, cast),
offset: offset + 1,
}
Unsigned16 endianness value ->
Unsigned16(endianness, value) ->
a : U8
a = Num.intCast (Num.shiftRightBy value 8)
a = Num.int_cast(Num.shift_right_by(value, 8))
b : U8
b = Num.intCast value
b = Num.int_cast(value)
newOutput =
new_output =
when endianness is
BE ->
output
|> List.set (offset + 0) a
|> List.set (offset + 1) b
|> List.set((offset + 0), a)
|> List.set((offset + 1), b)
LE ->
output
|> List.set (offset + 0) b
|> List.set (offset + 1) a
|> List.set((offset + 0), b)
|> List.set((offset + 1), a)
{
output: newOutput,
output: new_output,
offset: offset + 2,
}
Signed16 endianness value ->
Signed16(endianness, value) ->
a : U8
a = Num.intCast (Num.shiftRightBy value 8)
a = Num.int_cast(Num.shift_right_by(value, 8))
b : U8
b = Num.intCast value
b = Num.int_cast(value)
newOutput =
new_output =
when endianness is
BE ->
output
|> List.set (offset + 0) a
|> List.set (offset + 1) b
|> List.set((offset + 0), a)
|> List.set((offset + 1), b)
LE ->
output
|> List.set (offset + 0) b
|> List.set (offset + 1) a
|> List.set((offset + 0), b)
|> List.set((offset + 1), a)
{
output: newOutput,
output: new_output,
offset: offset + 1,
}
Bytes bs ->
List.walk
bs
{ output, offset }
Bytes(bs) ->
List.walk(
bs,
{ output, offset },
\accum, byte -> {
offset: accum.offset + 1,
output: List.set accum.output offset byte,
}
output: List.set(accum.output, offset, byte),
},
)
Sequence _ encoders ->
List.walk
encoders
{ output, offset }
Sequence(_, encoders) ->
List.walk(
encoders,
{ output, offset },
\accum, single ->
encodeHelp single accum.offset accum.output
encode_help(single, accum.offset, accum.output),
)

View file

@ -2,4 +2,4 @@ module [text, as_text]
text = "Hello, world!"
as_text = Num.toStr
as_text = Num.to_str

View file

@ -2,13 +2,13 @@ module [sort_by, sort_with, show]
show : List I64 -> Str
show = \list ->
if List.isEmpty(list) then
if List.is_empty(list) then
"[]"
else
content =
list
|> List.map(Num.toStr)
|> Str.joinWith(", ")
|> List.map(Num.to_str)
|> Str.join_with(", ")
"[$(content)]"
@ -30,7 +30,7 @@ quicksort_help = \list, order, low, high ->
when partition(low, high, list, order) is
Pair(partition_index, partitioned) ->
partitioned
|> quicksort_help(order, low, Num.subSaturated(partition_index, 1))
|> quicksort_help(order, low, Num.sub_saturated(partition_index, 1))
|> quicksort_help(order, (partition_index + 1), high)
else
list

View file

@ -19,9 +19,9 @@ main! = \{} ->
optimized = eval(const_folding(reassoc(e)))
unoptimized
|> Num.toStr
|> Num.to_str
|> Str.concat(" & ")
|> Str.concat(Num.toStr(optimized))
|> Str.concat(Num.to_str(optimized))
|> Host.put_line!
Err(GetIntError) ->

View file

@ -6,7 +6,7 @@ main! = \{} ->
|> Result.try(closure2)
|> Result.try(closure3)
|> Result.try(closure4)
|> Result.withDefault({})
|> Result.with_default({})
# ---
closure1 : {} -> Result {} []
@ -14,7 +14,7 @@ closure1 = \_ ->
Ok(foo(to_unit_borrowed, "a long string such that it's malloced"))
|> Result.map(\_ -> {})
to_unit_borrowed = \x -> Str.countUtf8Bytes(x)
to_unit_borrowed = \x -> Str.count_utf8_bytes(x)
foo = \f, x -> f(x)

View file

@ -41,7 +41,7 @@ Expr : [Val I64, Var Str, Add Expr Expr, Mul Expr Expr, Pow Expr Expr, Ln Expr]
divmod : I64, I64 -> Result { div : I64, mod : I64 } [DivByZero]
divmod = \l, r ->
when Pair(Num.divTruncChecked(l, r), Num.remChecked(l, r)) is
when Pair(Num.div_trunc_checked(l, r), Num.rem_checked(l, r)) is
Pair(Ok(div), Ok(mod)) -> Ok({ div, mod })
_ -> Err(DivByZero)
@ -162,8 +162,8 @@ deriv! : I64, Expr => Expr
deriv! = \i, f ->
fprime = d("x", f)
line =
Num.toStr((i + 1))
Num.to_str((i + 1))
|> Str.concat(" count: ")
|> Str.concat(Num.toStr(count(fprime)))
|> Str.concat(Num.to_str(count(fprime)))
Host.put_line!(line)
fprime

View file

@ -14,7 +14,7 @@ main! = \{} ->
when input_result is
Ok(n) ->
queens(n) # original koka 13
|> Num.toStr
|> Num.to_str
|> Host.put_line!
Err(GetIntError) ->

View file

@ -0,0 +1,9 @@
hosted PlatformTasks
exposes [put_line, put_int, get_int]
imports []
put_line : Str -> Task {} *
put_int : I64 -> Task {} *
get_int : Task { value : I64, is_error : Bool } *

View file

@ -6,4 +6,4 @@ platform "benchmarks"
provides [main_for_host!]
main_for_host! : {} => {}
main_for_host! = \{} -> main! {}
main_for_host! = \{} -> main!({})

View file

@ -5,7 +5,7 @@ import Quicksort
main! : {} => {}
main! = \{} ->
{ value, is_error } = Host.get_int! {}
{ value, is_error } = Host.get_int!({})
input_result =
if is_error then
Err(GetIntError)

View file

@ -57,7 +57,7 @@ main! = \{} ->
val = fold(\_, v, r -> if v then r + 1 else r, head, 0)
val
|> Num.toStr
|> Num.to_str
|> Host.put_line!
Nil ->

View file

@ -12,7 +12,7 @@ main! = \{} ->
|> Host.put_line!
show : RedBlackTree I64 {} -> Str
show = \tree -> show_rb_tree(tree, Num.toStr, \{} -> "{}")
show = \tree -> show_rb_tree(tree, Num.to_str, \{} -> "{}")
show_rb_tree : RedBlackTree k v, (k -> Str), (v -> Str) -> Str
show_rb_tree = \tree, show_key, show_value ->

View file

@ -24,10 +24,10 @@ example1 =
step : I64 -> Set I64
step = \n ->
when n is
1 -> Set.fromList([2, 3])
2 -> Set.fromList([4])
3 -> Set.fromList([4])
_ -> Set.fromList([])
1 -> Set.from_list([2, 3])
2 -> Set.from_list([4])
3 -> Set.from_list([4])
_ -> Set.from_list([])
cost : I64, I64 -> F64
cost = \_, _ -> 1

View file

@ -5,7 +5,7 @@ import pf.Host
main! : {} => {}
main! = \{} ->
when Base64.from_bytes(Str.toUtf8("Hello World")) is
when Base64.from_bytes(Str.to_utf8("Hello World")) is
Err(_) -> Host.put_line!("sadness")
Ok(encoded) ->
Host.put_line!(Str.concat("encoded: ", encoded))

View file

@ -188,7 +188,8 @@ mod cli_tests {
}
#[test]
#[cfg_attr(windows, ignore)]
// #[cfg_attr(windows, ignore)]
#[ignore]
fn false_interpreter() {
let cli_build = ExecCli::new(
CMD_BUILD,
@ -852,7 +853,7 @@ mod cli_tests {
),
);
let expected_output = "(@Community {friends: [{2}, {2}, {0, 1}], people: [(@Person {age: 27, favoriteColor: Blue, firstName: \"John\", hasBeard: Bool.true, lastName: \"Smith\"}), (@Person {age: 47, favoriteColor: Green, firstName: \"Debby\", hasBeard: Bool.false, lastName: \"Johnson\"}), (@Person {age: 33, favoriteColor: (RGB (255, 255, 0)), firstName: \"Jane\", hasBeard: Bool.false, lastName: \"Doe\"})]})\n";
let expected_output = "(@Community {friends: [{2}, {2}, {0, 1}], people: [(@Person {age: 27, favorite_color: Blue, first_name: \"John\", has_beard: Bool.true, last_name: \"Smith\"}), (@Person {age: 47, favorite_color: Green, first_name: \"Debby\", has_beard: Bool.false, last_name: \"Johnson\"}), (@Person {age: 33, favorite_color: (RGB (255, 255, 0)), first_name: \"Jane\", has_beard: Bool.false, last_name: \"Doe\"})]})\n";
cli_build.full_check_build_and_run(
expected_output,
@ -963,7 +964,7 @@ mod cli_tests {
),
);
let expected_output = "notEffectful: hardcoded\neffectful: from stdin\n";
let expected_output = "not_effectful: hardcoded\neffectful: from stdin\n";
cli_build.check_build_and_run(
expected_output,

View file

@ -85,12 +85,12 @@ size_t roc_str_len(struct RocStr str) {
}
}
extern void roc__mainForHost_1_exposed_generic(struct RocStr *string);
extern void roc__main_for_host_1_exposed_generic(struct RocStr *string);
int main() {
struct RocStr str;
roc__mainForHost_1_exposed_generic(&str);
roc__main_for_host_1_exposed_generic(&str);
// Determine str_len and the str_bytes pointer,
// taking into account the small string optimization.

View file

@ -3,7 +3,7 @@ platform "echo-in-c"
exposes []
packages {}
imports []
provides [mainForHost]
provides [main_for_host]
mainForHost : Str
mainForHost = main
main_for_host : Str
main_for_host = main

View file

@ -2,7 +2,7 @@
//
// ```
// = note: Undefined symbols for architecture arm64:
// "_roc__mainForHost_1_exposed_generic", referenced from:
// "_roc__main_for_host_1_exposed_generic", referenced from:
// _main in rustplatform-df9e357e0cc989a6.rustplatform.863be87f3956573-cgu.0.rcgu.o
// ld: symbol(s) not found for architecture arm64
// clang-16: error: linker command failed with exit code 1 (use -v to see invocation)

View file

@ -3,7 +3,7 @@ platform "echo-in-rust"
exposes []
packages {}
imports []
provides [mainForHost]
provides [main_for_host]
mainForHost : Str
mainForHost = main
main_for_host : Str
main_for_host = main

View file

@ -6,7 +6,7 @@ use roc_std::RocStr;
use std::io::Write;
extern "C" {
#[link_name = "roc__mainForHost_1_exposed_generic"]
#[link_name = "roc__main_for_host_1_exposed_generic"]
fn roc_main(_: &mut RocStr);
}

View file

@ -35,14 +35,14 @@ export fn roc_dealloc(c_ptr: *anyopaque, alignment: u32) callconv(.C) void {
// NOTE roc_panic and roc_dbg is provided in the JS file, so it can throw an exception
extern fn roc__mainForHost_1_exposed(*RocStr) void;
extern fn roc__main_for_host_1_exposed(*RocStr) void;
extern fn js_display_roc_string(str_bytes: ?[*]u8, str_len: usize) void;
pub export fn main() u8 {
// actually call roc to populate the callresult
var callresult = RocStr.empty();
roc__mainForHost_1_exposed(&callresult);
roc__main_for_host_1_exposed(&callresult);
// display the result using JavaScript
js_display_roc_string(callresult.asU8ptrMut(), callresult.len());

View file

@ -3,7 +3,7 @@ platform "echo-in-web-assembly"
exposes []
packages {}
imports []
provides [mainForHost]
provides [main_for_host]
mainForHost : Str
mainForHost = main
main_for_host : Str
main_for_host = main

View file

@ -102,7 +102,7 @@ comptime {
const mem = std.mem;
const Allocator = mem.Allocator;
extern fn roc__mainForHost_1_exposed_generic(*RocStr) void;
extern fn roc__main_for_host_1_exposed_generic(*RocStr) void;
const Unit = extern struct {};
@ -111,7 +111,7 @@ pub export fn main() u8 {
// actually call roc to populate the callresult
var callresult = RocStr.empty();
roc__mainForHost_1_exposed_generic(&callresult);
roc__main_for_host_1_exposed_generic(&callresult);
// stdout the result
stdout.print("{s}", .{callresult.asSlice()}) catch unreachable;

View file

@ -3,7 +3,7 @@ platform "echo-in-zig"
exposes []
packages {}
imports []
provides [mainForHost]
provides [main_for_host]
mainForHost : Str
mainForHost = main
main_for_host : Str
main_for_host = main

View file

@ -1,6 +1,7 @@
---
source: crates/cli/tests/cli_tests.rs
expression: cli_test_out.normalize_stdout_and_stderr()
snapshot_kind: text
---
── EXPECT FAILED in tests/test-projects/expects/expects.roc ────────────────────
@ -31,7 +32,7 @@ a = 1
This expectation failed:
11│> expect
12│> a = makeA
12│> a = make_a
13│> b = 2i64
14│>
15│> a == b

View file

@ -6,10 +6,10 @@ snapshot_kind: text
── TOO MANY ARGS in tests/test-projects/module_params/arity_mismatch.roc ───────
The getUser function expects 1 argument, but it got 2 instead:
The get_user function expects 1 argument, but it got 2 instead:
12│ $(Api.getUser 1 2)
^^^^^^^^^^^
12│ $(Api.get_user(1, 2))
^^^^^^^^^^^^
Are there any missing commas? Or missing parentheses?
@ -18,18 +18,18 @@ Are there any missing commas? Or missing parentheses?
This value is not a function, but it was given 1 argument:
13│ $(Api.baseUrl 1)
^^^^^^^^^^^
13│ $(Api.base_url(1))
^^^^^^^^^^^^
Are there any missing commas? Or missing parentheses?
── TOO FEW ARGS in tests/test-projects/module_params/arity_mismatch.roc ────────
The getPostComment function expects 2 arguments, but it got only 1:
The get_post_comment function expects 2 arguments, but it got only 1:
16│ $(Api.getPostComment 1)
^^^^^^^^^^^^^^^^^^
16│ $(Api.get_post_comment(1))
^^^^^^^^^^^^^^^^^^^^
Roc does not allow functions to be partially applied. Use a closure to
make partial application explicit.

View file

@ -6,34 +6,35 @@ snapshot_kind: text
── TYPE MISMATCH in tests/test-projects/module_params/BadAnn.roc ───────────────
Something is off with the body of the fnAnnotatedAsValue definition:
Something is off with the body of the
fn_annotated_as_value definition:
3│ fnAnnotatedAsValue : Str
4│> fnAnnotatedAsValue = \postId, commentId ->
5│> "/posts/$(postId)/comments/$(Num.toStr commentId)"
3│ fn_annotated_as_value : Str
4│> fn_annotated_as_value = \post_id, comment_id ->
5│> "/posts/$(post_id)/comments/$(Num.to_str(comment_id))"
The body is an anonymous function of type:
Str, Num * -> Str
But the type annotation on fnAnnotatedAsValue says it should be:
But the type annotation on fn_annotated_as_value says it should be:
Str
── TYPE MISMATCH in tests/test-projects/module_params/BadAnn.roc ───────────────
Something is off with the body of the missingArg definition:
Something is off with the body of the missing_arg definition:
7│ missingArg : Str -> Str
8│> missingArg = \postId, _ ->
9│> "/posts/$(postId)/comments"
7│ missing_arg : Str -> Str
8│> missing_arg = \post_id, _ ->
9│> "/posts/$(post_id)/comments"
The body is an anonymous function of type:
(Str, ? -> Str)
But the type annotation on missingArg says it should be:
But the type annotation on missing_arg says it should be:
(Str -> Str)

View file

@ -8,9 +8,8 @@ snapshot_kind: text
This argument to this string interpolation has an unexpected type:
10│ """
11│> $(Api.getPost)
12│ """
10│ "$(Api.get_post)"
^^^^^^^^^^^^
The argument is an anonymous function of type:

View file

@ -11,8 +11,8 @@ const mem = std.mem;
const Allocator = mem.Allocator;
// NOTE the LLVM backend expects this signature
// extern fn roc__mainForHost_1_exposed(i64, *i64) void;
extern fn roc__mainForHost_1_exposed(i64) i64;
// extern fn roc__main_for_host_1_exposed(i64, *i64) void;
extern fn roc__main_for_host_1_exposed(i64) i64;
const Align = 2 * @alignOf(usize);
extern fn malloc(size: usize) callconv(.C) ?*align(Align) anyopaque;
@ -110,7 +110,7 @@ comptime {
pub export fn main() u8 {
const stdout = std.io.getStdOut().writer();
const result = roc__mainForHost_1_exposed(10);
const result = roc__main_for_host_1_exposed(10);
stdout.print("{d}\n", .{result}) catch unreachable;

View file

@ -3,7 +3,7 @@ platform "fibonacci"
exposes []
packages {}
imports []
provides [mainForHost]
provides [main_for_host]
mainForHost : I64 -> I64
mainForHost = \a -> main a
main_for_host : I64 -> I64
main_for_host = \a -> main(a)

View file

@ -1,10 +1,10 @@
app [main] { pf: platform "fibonacci-platform/main.roc" }
main = \n -> fib n 0 1
main = \n -> fib(n, 0, 1)
# the clever implementation requires join points
fib = \n, a, b ->
if n == 0 then
a
else
fib (n - 1) b (a + b)
fib((n - 1), b, (a + b))

View file

@ -9,7 +9,7 @@ const expect = testing.expect;
const mem = std.mem;
const Allocator = mem.Allocator;
extern fn roc__mainForHost_1_exposed(input: RocList) callconv(.C) RocList;
extern fn roc__main_for_host_1_exposed(input: RocList) callconv(.C) RocList;
const Align = 2 * @alignOf(usize);
extern fn malloc(size: usize) callconv(.C) ?*align(Align) anyopaque;
@ -128,7 +128,7 @@ pub export fn main() u8 {
const roc_list = RocList{ .elements = numbers, .length = NUM_NUMS, .capacity = NUM_NUMS };
// actually call roc to populate the callresult
const callresult: RocList = roc__mainForHost_1_exposed(roc_list);
const callresult: RocList = roc__main_for_host_1_exposed(roc_list);
// stdout the result
const length = @min(20, callresult.length);

View file

@ -3,7 +3,7 @@ platform "quicksort"
exposes []
packages {}
imports []
provides [mainForHost]
provides [main_for_host]
mainForHost : List I64 -> List I64
mainForHost = \list -> quicksort list
main_for_host : List I64 -> List I64
main_for_host = \list -> quicksort(list)

View file

@ -1,54 +1,54 @@
app [quicksort] { pf: platform "quicksort-platform/main.roc" }
quicksort = \originalList ->
n = List.len originalList
quicksort = \original_list ->
n = List.len(original_list)
quicksortHelp originalList 0 (n - 1)
quicksort_help(original_list, 0, (n - 1))
quicksortHelp : List (Num a), U64, U64 -> List (Num a)
quicksortHelp = \list, low, high ->
quicksort_help : List (Num a), U64, U64 -> List (Num a)
quicksort_help = \list, low, high ->
if low < high then
when partition low high list is
Pair partitionIndex partitioned ->
when partition(low, high, list) is
Pair(partition_index, partitioned) ->
partitioned
|> quicksortHelp low (partitionIndex - 1)
|> quicksortHelp (partitionIndex + 1) high
|> quicksort_help(low, (partition_index - 1))
|> quicksort_help((partition_index + 1), high)
else
list
partition : U64, U64, List (Num a) -> [Pair U64 (List (Num a))]
partition = \low, high, initialList ->
when List.get initialList high is
Ok pivot ->
when partitionHelp low low initialList high pivot is
Pair newI newList ->
Pair newI (swap newI high newList)
partition = \low, high, initial_list ->
when List.get(initial_list, high) is
Ok(pivot) ->
when partition_help(low, low, initial_list, high, pivot) is
Pair(new_i, new_list) ->
Pair(new_i, swap(new_i, high, new_list))
Err _ ->
Pair low initialList
Err(_) ->
Pair(low, initial_list)
partitionHelp : U64, U64, List (Num c), U64, Num c -> [Pair U64 (List (Num c))]
partitionHelp = \i, j, list, high, pivot ->
partition_help : U64, U64, List (Num c), U64, Num c -> [Pair U64 (List (Num c))]
partition_help = \i, j, list, high, pivot ->
if j < high then
when List.get list j is
Ok value ->
when List.get(list, j) is
Ok(value) ->
if value <= pivot then
partitionHelp (i + 1) (j + 1) (swap i j list) high pivot
partition_help((i + 1), (j + 1), swap(i, j, list), high, pivot)
else
partitionHelp i (j + 1) list high pivot
partition_help(i, (j + 1), list, high, pivot)
Err _ ->
Pair i list
Err(_) ->
Pair(i, list)
else
Pair i list
Pair(i, list)
swap : U64, U64, List a -> List a
swap = \i, j, list ->
when Pair (List.get list i) (List.get list j) is
Pair (Ok atI) (Ok atJ) ->
when Pair(List.get(list, i), List.get(list, j)) is
Pair(Ok(at_i), Ok(at_j)) ->
list
|> List.set i atJ
|> List.set j atI
|> List.set(i, at_j)
|> List.set(j, at_i)
_ ->
# to prevent a decrement on list

View file

@ -1,10 +1,10 @@
module [
Community,
empty,
addPerson,
addFriend,
add_person,
add_friend,
Person,
walkFriendNames,
walk_friend_names,
]
## Datatype representing a community for demonstration purposes in inspect-gui.roc and inspect-logging.roc
@ -16,11 +16,11 @@ Community := {
implements [Inspect]
Person := {
firstName : Str,
lastName : Str,
first_name : Str,
last_name : Str,
age : U8,
hasBeard : Bool,
favoriteColor : Color,
has_beard : Bool,
favorite_color : Color,
}
implements [Inspect]
@ -31,52 +31,52 @@ Color : [
RGB (U8, U8, U8),
]
empty = @Community { people: [], friends: [] }
empty = @Community({ people: [], friends: [] })
addPerson = \@Community { people, friends }, person ->
@Community {
people: List.append people (@Person person),
friends: List.append friends (Set.empty {}),
}
add_person = \@Community({ people, friends }), person ->
@Community({
people: List.append(people, @Person(person)),
friends: List.append(friends, Set.empty({})),
})
addFriend = \@Community { people, friends }, from, to ->
when (List.get friends from, List.get friends to) is
(Ok fromSet, Ok toSet) ->
@Community {
add_friend = \@Community({ people, friends }), from, to ->
when (List.get(friends, from), List.get(friends, to)) is
(Ok(from_set), Ok(to_set)) ->
@Community({
people,
friends: friends
|> List.set from (Set.insert fromSet to)
|> List.set to (Set.insert toSet from),
}
|> List.set(from, Set.insert(from_set, to))
|> List.set(to, Set.insert(to_set, from)),
})
_ ->
@Community { people, friends }
@Community({ people, friends })
walkFriendNames : Community, state, (state, Str, Set Str -> state) -> state
walkFriendNames = \@Community { people, friends }, s0, nextFn ->
walk_friend_names : Community, state, (state, Str, Set Str -> state) -> state
walk_friend_names = \@Community({ people, friends }), s0, next_fn ->
(out, _) =
List.walk friends (s0, 0) \(s1, id), friendSet ->
(@Person person) =
when List.get people id is
Ok v -> v
Err _ -> crash "Unknown Person"
personName =
person.firstName
|> Str.concat " "
|> Str.concat person.lastName
List.walk(friends, (s0, 0), \(s1, id), friend_set ->
@Person(person) =
when List.get(people, id) is
Ok(v) -> v
Err(_) -> crash("Unknown Person")
person_name =
person.first_name
|> Str.concat(" ")
|> Str.concat(person.last_name)
friendNames =
Set.walk friendSet (Set.empty {}) \friendsSet, friendId ->
(@Person friend) =
when List.get people friendId is
Ok v -> v
Err _ -> crash "Unknown Person"
friendName =
friend.firstName
|> Str.concat " "
|> Str.concat friend.lastName
Set.insert friendsSet friendName
friend_names =
Set.walk(friend_set, Set.empty({}), \friends_set, friend_id ->
@Person(friend) =
when List.get(people, friend_id) is
Ok(v) -> v
Err(_) -> crash("Unknown Person")
friend_name =
friend.first_name
|> Str.concat(" ")
|> Str.concat(friend.last_name)
Set.insert(friends_set, friend_name))
(nextFn s1 personName friendNames, id + 1)
(next_fn(s1, person_name, friend_names), id + 1))
out

View file

@ -3,19 +3,19 @@ app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/downlo
import pf.Stdout
main =
multipleIn =
multiple_in =
{ sequential <-
a: Task.ok 123,
b: Task.ok "abc",
c: Task.ok [123],
_d: Task.ok ["abc"],
_: Task.ok (Dict.single "a" "b"),
a: Task.ok(123),
b: Task.ok("abc"),
c: Task.ok([123]),
_d: Task.ok(["abc"]),
_: Task.ok(Dict.single("a", "b")),
}!
Stdout.line! "For multiple tasks: $(Inspect.toStr multipleIn)"
Stdout.line!("For multiple tasks: $(Inspect.to_str(multiple_in))")
sequential : Task a err, Task b err, (a, b -> c) -> Task c err
sequential = \firstTask, secondTask, mapper ->
first = firstTask!
second = secondTask!
Task.ok (mapper first second)
sequential = \first_task, second_task, mapper ->
first = first_task!
second = second_task!
Task.ok(mapper(first, second))

View file

@ -3,33 +3,33 @@ app [main!] { pf: platform "../test-platform-effects-zig/main.roc" }
import pf.Effect
main! : {} => {}
main! = \{} -> tick! {}
main! = \{} -> tick!({})
tick! = \{} ->
line = Effect.getLine! {}
line = Effect.get_line!({})
if !(Str.isEmpty line) then
Effect.putLine! (echo line)
if !(Str.is_empty(line)) then
Effect.put_line!(echo(line))
else
Effect.putLine! "Received no input."
Effect.put_line!("Received no input.")
echo : Str -> Str
echo = \shout ->
silence = \length -> List.repeat ' ' length
silence = \length -> List.repeat(' ', length)
shout
|> Str.toUtf8
|> List.mapWithIndex \_, i ->
length = (List.len (Str.toUtf8 shout) - i)
phrase = (List.splitAt (Str.toUtf8 shout) length).before
|> Str.to_utf8
|> List.map_with_index(\_, i ->
length = (List.len(Str.to_utf8(shout)) - i)
phrase = (List.split_at(Str.to_utf8(shout), length)).before
List.concat (silence (if i == 0 then 2 * length else length)) phrase
List.concat(silence((if i == 0 then 2 * length else length)), phrase))
|> List.join
|> Str.fromUtf8
|> Result.withDefault ""
|> Str.from_utf8
|> Result.with_default("")
expect
message = "hello!"
echoedMessage = echo message
echoed_message = echo(message)
echoedMessage == " hello! hello hell hel he h"
echoed_message == " hello! hello hell hel he h"

View file

@ -4,20 +4,19 @@ import pf.Effect
main! : {} => {}
main! = \{} ->
good = [0, 2, 4] |> List.forEachTry! validate!
expect good == Ok {}
good = [0, 2, 4] |> List.for_each_try!(validate!)
expect good == Ok({})
bad = [6, 8, 9, 10] |> List.forEachTry! validate!
expect bad == Err 9
bad = [6, 8, 9, 10] |> List.for_each_try!(validate!)
expect bad == Err(9)
{}
validate! : U32 => Result {} U32
validate! = \x ->
if Num.isEven x then
Effect.putLine! "✅ $(Num.toStr x)"
Ok {}
if Num.is_even(x) then
Effect.put_line!("✅ $(Num.to_str(x))")
Ok({})
else
Effect.putLine! "$(Num.toStr x) is not even! ABORT!"
Err x
Effect.put_line!("$(Num.to_str(x)) is not even! ABORT!")
Err(x)

View file

@ -4,24 +4,24 @@ import pf.Effect
main! : {} => {}
main! = \{} ->
first = ask! "What's your first name?"
last = ask! "What's your last name?"
first = ask!("What's your first name?")
last = ask!("What's your last name?")
Effect.putLine! "\nHi, $(first) $(last)!\n"
Effect.put_line!("\nHi, $(first) $(last)!\n")
when Str.toU8 (ask! "How old are you?") is
Err InvalidNumStr ->
Effect.putLine! "Enter a valid number"
when Str.to_u8(ask!("How old are you?")) is
Err(InvalidNumStr) ->
Effect.put_line!("Enter a valid number")
Ok age if age >= 18 ->
Effect.putLine! "\nNice! You can vote!"
Ok(age) if age >= 18 ->
Effect.put_line!("\nNice! You can vote!")
Ok age ->
Effect.putLine! "\nYou'll be able to vote in $(Num.toStr (18 - age)) years"
Ok(age) ->
Effect.put_line!("\nYou'll be able to vote in $(Num.to_str((18 - age))) years")
Effect.putLine! "\nBye! 👋"
Effect.put_line!("\nBye! 👋")
ask! : Str => Str
ask! = \question ->
Effect.putLine! question
Effect.getLine! {}
Effect.put_line!(question)
Effect.get_line!({})

View file

@ -4,4 +4,4 @@ import pf.Effect
main! : {} => {}
main! = \{} ->
Effect.putLine! "I'm an effect 👻"
Effect.put_line!("I'm an effect 👻")

View file

@ -4,5 +4,5 @@ import pf.Effect
main! : {} => {}
main! = \{} ->
_ = Effect.getLine! {}
Effect.putLine! "I asked for input and I ignored it. Deal with it! 😎"
_ = Effect.get_line!({})
Effect.put_line!("I asked for input and I ignored it. Deal with it! 😎")

View file

@ -8,28 +8,28 @@ import Community
main! = \{} ->
Community.empty
|> Community.addPerson {
firstName: "John",
lastName: "Smith",
|> Community.add_person({
first_name: "John",
last_name: "Smith",
age: 27,
hasBeard: Bool.true,
favoriteColor: Blue,
}
|> Community.addPerson {
firstName: "Debby",
lastName: "Johnson",
has_beard: Bool.true,
favorite_color: Blue,
})
|> Community.add_person({
first_name: "Debby",
last_name: "Johnson",
age: 47,
hasBeard: Bool.false,
favoriteColor: Green,
}
|> Community.addPerson {
firstName: "Jane",
lastName: "Doe",
has_beard: Bool.false,
favorite_color: Green,
})
|> Community.add_person({
first_name: "Jane",
last_name: "Doe",
age: 33,
hasBeard: Bool.false,
favoriteColor: RGB (255, 255, 0),
}
|> Community.addFriend 0 2
|> Community.addFriend 1 2
|> Inspect.toStr
|> Effect.putLine!
has_beard: Bool.false,
favorite_color: RGB((255, 255, 0)),
})
|> Community.add_friend(0, 2)
|> Community.add_friend(1, 2)
|> Inspect.to_str
|> Effect.put_line!

View file

@ -5,12 +5,12 @@ import pf.Effect
main! : {} => {}
main! = \{} ->
friends = ["Lu", "Marce", "Joaquin", "Chloé", "Mati", "Pedro"]
printAll! friends
print_all!(friends)
printAll! : List Str => {}
printAll! = \friends ->
print_all! : List Str => {}
print_all! = \friends ->
when friends is
[] -> {}
[first, .. as remaining] ->
Effect.putLine! first
printAll! remaining
Effect.put_line!(first)
print_all!(remaining)

View file

@ -5,20 +5,20 @@ import pf.Effect
main! : {} => {}
main! = \{} ->
_ =
authenticate! {}
|> Result.onErr! \BadPass ->
Effect.putLine! "LOG: Failed login attempt"
Ok "Bad password"
authenticate!({})
|> Result.on_err!(\BadPass ->
Effect.put_line!("LOG: Failed login attempt")
Ok("Bad password"))
{}
authenticate! : {} => Result Str [BadPass]
authenticate! = \{} ->
Effect.putLine! "Enter your password:"
Effect.put_line!("Enter your password:")
password = Effect.getLine! {}
password = Effect.get_line!({})
if password == "password" then
Ok "You are in"
Ok("You are in")
else
Err BadPass
Err(BadPass)

View file

@ -5,15 +5,15 @@ import pf.Effect
main! : {} => {}
main! = \{} ->
["Welcome!", "What's your name?"]
|> List.forEach! Effect.putLine!
|> List.for_each!(Effect.put_line!)
line = Effect.getLine! {}
line = Effect.get_line!({})
if line == "secret" then
Effect.putLine! "You found the secret"
Effect.putLine! "Congratulations!"
Effect.put_line!("You found the secret")
Effect.put_line!("Congratulations!")
else
{}
Effect.putLine! "You entered: $(line)"
Effect.putLine! "It is known"
Effect.put_line!("You entered: $(line)")
Effect.put_line!("It is known")

View file

@ -3,20 +3,20 @@ app [main!] { pf: platform "../test-platform-effects-zig/main.roc" }
import pf.Effect
Fx : {
getLine!: {} => Str,
get_line! : {} => Str,
}
main! : {} => {}
main! = \{} ->
notEffectful : Fx
notEffectful = {
getLine!: \{} -> "hardcoded"
not_effectful : Fx
not_effectful = {
get_line!: \{} -> "hardcoded",
}
effectful : Fx
effectful = {
getLine!: Effect.getLine!
get_line!: Effect.get_line!,
}
Effect.putLine! "notEffectful: $(notEffectful.getLine! {})"
Effect.putLine! "effectful: $(effectful.getLine! {})"
Effect.put_line!("not_effectful: $(not_effectful.get_line!({}))")
Effect.put_line!("effectful: $(effectful.get_line!({}))")

View file

@ -4,9 +4,9 @@ import pf.Effect
main! : {} => {}
main! = \{} ->
logged! "hello" (\{} -> Effect.putLine! "Hello, World!")
logged!("hello", \{} -> Effect.put_line!("Hello, World!"))
logged! = \name, fx! ->
Effect.putLine! "Before $(name)"
fx! {}
Effect.putLine! "After $(name)"
Effect.put_line!("Before $(name)")
fx!({})
Effect.put_line!("After $(name)")

View file

@ -1,6 +1,6 @@
app [main] { pf: platform "../test-platform-simple-zig/main.roc" }
makeA =
make_a =
a = 1
expect a == 2
@ -9,29 +9,29 @@ makeA =
a
expect
a = makeA
a = make_a
b = 2i64
a == b
polyDbg = \x ->
dbg x
poly_dbg = \x ->
dbg(x)
x
main =
str = "this will for sure be a large string so when we split it it will use seamless slices which affect printing"
words = Str.splitOn str " "
words = Str.split_on(str, " ")
expect words == []
x = 42
dbg x
dbg(x)
dbg "Fjoer en ferdjer frieten oan dyn geve lea"
dbg("Fjoer en ferdjer frieten oan dyn geve lea")
dbg "this is line 24"
dbg("this is line 24")
r = { x: polyDbg "abc", y: polyDbg 10u8, z: polyDbg (A (B C)) }
r = { x: poly_dbg("abc"), y: poly_dbg(10u8), z: poly_dbg(A(B(C))) }
when r is
_ -> "Program finished!\n"

View file

@ -1,12 +1,12 @@
module [
addAndStringify,
add_and_stringify,
]
import Transitive
addAndStringify = \num1, num2 ->
Num.toStr (Transitive.add num1 num2)
add_and_stringify = \num1, num2 ->
Num.to_str(Transitive.add(num1, num2))
expect addAndStringify 1 2 == "3"
expect add_and_stringify(1, 2) == "3"
expect addAndStringify 3 4 == "7"
expect add_and_stringify(3, 4) == "7"

View file

@ -4,4 +4,4 @@ module [
add = \num1, num2 -> (num1 + num2)
expect add 1 2 == 3
expect add(1, 2) == 3

View file

@ -1,4 +1,4 @@
module [Context, Data, with!, getChar!, Option, pushStack, popStack, toStr, inWhileScope]
module [Context, Data, with!, get_char!, Option, push_stack, pop_stack, to_str, in_while_scope]
import pf.File
import Variable exposing [Variable]
@ -9,100 +9,100 @@ Option a : [Some a, None]
Data : [Lambda (List U8), Number I32, Var Variable]
# While loops are special and have their own Scope specific state.
WhileState : { cond : List U8, body : List U8, state : [InCond, InBody] }
Scope : { data : Option File.Handle, index : U64, buf : List U8, whileInfo : Option WhileState }
Scope : { data : Option File.Handle, index : U64, buf : List U8, while_info : Option WhileState }
State : [Executing, InComment, InLambda U64 (List U8), InString (List U8), InNumber I32, InSpecialChar, LoadChar]
Context : { scopes : List Scope, stack : List Data, vars : List Data, state : State }
pushStack : Context, Data -> Context
pushStack = \ctx, data ->
{ ctx & stack: List.append ctx.stack data }
push_stack : Context, Data -> Context
push_stack = \ctx, data ->
{ ctx & stack: List.append(ctx.stack, data) }
# I think an open tag union should just work here.
# Instead at a call sites, I need to match on the error and then return the same error.
# Otherwise it hits unreachable code in ir.rs
popStack : Context -> Result (Context, Data) [EmptyStack]
popStack = \ctx ->
when List.last ctx.stack is
Ok val ->
poppedCtx = { ctx & stack: List.dropAt ctx.stack (List.len ctx.stack - 1) }
pop_stack : Context -> Result (Context, Data) [EmptyStack]
pop_stack = \ctx ->
when List.last(ctx.stack) is
Ok(val) ->
popped_ctx = { ctx & stack: List.drop_at(ctx.stack, (List.len(ctx.stack) - 1)) }
Ok (poppedCtx, val)
Ok((popped_ctx, val))
Err ListWasEmpty ->
Err EmptyStack
Err(ListWasEmpty) ->
Err(EmptyStack)
toStrData : Data -> Str
toStrData = \data ->
to_str_data : Data -> Str
to_str_data = \data ->
when data is
Lambda _ -> "[]"
Number n -> Num.toStr (Num.intCast n)
Var v -> Variable.toStr v
Lambda(_) -> "[]"
Number(n) -> Num.to_str(Num.int_cast(n))
Var(v) -> Variable.to_str(v)
toStrState : State -> Str
toStrState = \state ->
to_str_state : State -> Str
to_str_state = \state ->
when state is
Executing -> "Executing"
InComment -> "InComment"
InString _ -> "InString"
InNumber _ -> "InNumber"
InLambda _ _ -> "InLambda"
InString(_) -> "InString"
InNumber(_) -> "InNumber"
InLambda(_, _) -> "InLambda"
InSpecialChar -> "InSpecialChar"
LoadChar -> "LoadChar"
toStr : Context -> Str
toStr = \{ scopes, stack, state, vars } ->
depth = Num.toStr (List.len scopes)
stateStr = toStrState state
stackStr = Str.joinWith (List.map stack toStrData) " "
varsStr = Str.joinWith (List.map vars toStrData) " "
to_str : Context -> Str
to_str = \{ scopes, stack, state, vars } ->
depth = Num.to_str(List.len(scopes))
state_str = to_str_state(state)
stack_str = Str.join_with(List.map(stack, to_str_data), " ")
vars_str = Str.join_with(List.map(vars, to_str_data), " ")
"\n============\nDepth: $(depth)\nState: $(stateStr)\nStack: [$(stackStr)]\nVars: [$(varsStr)]\n============\n"
"\n============\nDepth: $(depth)\nState: $(state_str)\nStack: [$(stack_str)]\nVars: [$(vars_str)]\n============\n"
with! : Str, (Context => a) => a
with! = \path, callback! ->
File.withOpen! path \handle ->
File.with_open!(path, \handle ->
# I cant define scope here and put it in the list in callback. It breaks alias anaysis.
# Instead I have to inline this.
# root_scope = { data: Some handle, index: 0, buf: [], whileInfo: None }
callback! { scopes: [{ data: Some handle, index: 0, buf: [], whileInfo: None }], state: Executing, stack: [], vars: List.repeat (Number 0) Variable.totalCount }
callback!({ scopes: [{ data: Some(handle), index: 0, buf: [], while_info: None }], state: Executing, stack: [], vars: List.repeat(Number(0), Variable.total_count) }))
# I am pretty sure there is a syntax to destructure and keep a reference to the whole, but Im not sure what it is.
getChar! : Context => Result (U8, Context) [EndOfData, NoScope]
getChar! = \ctx ->
when List.last ctx.scopes is
Ok scope ->
(val, newScope) = getCharScope!? scope
Ok (val, { ctx & scopes: List.set ctx.scopes (List.len ctx.scopes - 1) newScope })
get_char! : Context => Result (U8, Context) [EndOfData, NoScope]
get_char! = \ctx ->
when List.last(ctx.scopes) is
Ok(scope) ->
(val, new_scope) = get_char_scope!?(scope)
Ok((val, { ctx & scopes: List.set(ctx.scopes, (List.len(ctx.scopes) - 1), new_scope) }))
Err ListWasEmpty ->
Err NoScope
Err(ListWasEmpty) ->
Err(NoScope)
getCharScope! : Scope => Result (U8, Scope) [EndOfData, NoScope]
getCharScope! = \scope ->
when List.get scope.buf scope.index is
Ok val ->
Ok (val, { scope & index: scope.index + 1 })
get_char_scope! : Scope => Result (U8, Scope) [EndOfData, NoScope]
get_char_scope! = \scope ->
when List.get(scope.buf, scope.index) is
Ok(val) ->
Ok((val, { scope & index: scope.index + 1 }))
Err OutOfBounds ->
Err(OutOfBounds) ->
when scope.data is
Some h ->
bytes = File.chunk! h
when List.first bytes is
Ok val ->
Some(h) ->
bytes = File.chunk!(h)
when List.first(bytes) is
Ok(val) ->
# This starts at 1 because the first character is already being returned.
Ok (val, { scope & buf: bytes, index: 1 })
Ok((val, { scope & buf: bytes, index: 1 }))
Err ListWasEmpty ->
Err EndOfData
Err(ListWasEmpty) ->
Err(EndOfData)
None ->
Err EndOfData
Err(EndOfData)
inWhileScope : Context -> Bool
inWhileScope = \ctx ->
when List.last ctx.scopes is
Ok scope ->
scope.whileInfo != None
in_while_scope : Context -> Bool
in_while_scope = \ctx ->
when List.last(ctx.scopes) is
Ok(scope) ->
scope.while_info != None
Err ListWasEmpty ->
Err(ListWasEmpty) ->
Bool.false

View file

@ -1,33 +1,33 @@
module [Variable, fromUtf8, toIndex, totalCount, toStr]
module [Variable, from_utf8, to_index, total_count, to_str]
# Variables in False can only be single letters. Thus, the valid variables are "a" to "z".
# This opaque type deals with ensure we always have valid variables.
Variable := U8
totalCount : U64
totalCount =
total_count : U64
total_count =
0x7A # "z"
- 0x61 # "a"
+ 1
toStr : Variable -> Str
toStr = \@Variable char ->
when Str.fromUtf8 [char] is
Ok str -> str
to_str : Variable -> Str
to_str = \@Variable(char) ->
when Str.from_utf8([char]) is
Ok(str) -> str
_ -> "_"
fromUtf8 : U8 -> Result Variable [InvalidVariableUtf8]
fromUtf8 = \char ->
from_utf8 : U8 -> Result Variable [InvalidVariableUtf8]
from_utf8 = \char ->
if
char
>= 0x61 # "a"
&& char
<= 0x7A # "z"
then
Ok (@Variable char)
Ok(@Variable(char))
else
Err InvalidVariableUtf8
Err(InvalidVariableUtf8)
toIndex : Variable -> U64
toIndex = \@Variable char ->
Num.intCast (char - 0x61) # "a"
to_index : Variable -> U64
to_index = \@Variable(char) ->
Num.int_cast((char - 0x61)) # "a"

View file

@ -16,454 +16,454 @@ InterpreterErrors : [BadUtf8, DivByZero, EmptyStack, InvalidBooleanValue, Invali
main! : Str => {}
main! = \filename ->
when interpretFile! filename is
Ok {} ->
when interpret_file!(filename) is
Ok({}) ->
{}
Err (StringErr e) ->
Stdout.line! "Ran into problem:\n$(e)\n"
Err(StringErr(e)) ->
Stdout.line!("Ran into problem:\n$(e)\n")
interpretFile! : Str => Result {} [StringErr Str]
interpretFile! = \filename ->
Context.with! filename \ctx ->
result = interpretCtx! ctx
interpret_file! : Str => Result {} [StringErr Str]
interpret_file! = \filename ->
Context.with!(filename, \ctx ->
result = interpret_ctx!(ctx)
when result is
Ok _ ->
Ok {}
Ok(_) ->
Ok({})
Err BadUtf8 ->
Err (StringErr "Failed to convert string from Utf8 bytes")
Err(BadUtf8) ->
Err(StringErr("Failed to convert string from Utf8 bytes"))
Err DivByZero ->
Err (StringErr "Division by zero")
Err(DivByZero) ->
Err(StringErr("Division by zero"))
Err EmptyStack ->
Err (StringErr "Tried to pop a value off of the stack when it was empty")
Err(EmptyStack) ->
Err(StringErr("Tried to pop a value off of the stack when it was empty"))
Err InvalidBooleanValue ->
Err (StringErr "Ran into an invalid boolean that was neither false (0) or true (-1)")
Err(InvalidBooleanValue) ->
Err(StringErr("Ran into an invalid boolean that was neither false (0) or true (-1)"))
Err (InvalidChar char) ->
Err (StringErr "Ran into an invalid character with ascii code: $(char)")
Err(InvalidChar(char)) ->
Err(StringErr("Ran into an invalid character with ascii code: $(char)"))
Err MaxInputNumber ->
Err (StringErr "Like the original false compiler, the max input number is 320,000")
Err(MaxInputNumber) ->
Err(StringErr("Like the original false compiler, the max input number is 320,000"))
Err NoLambdaOnStack ->
Err (StringErr "Tried to run a lambda when no lambda was on the stack")
Err(NoLambdaOnStack) ->
Err(StringErr("Tried to run a lambda when no lambda was on the stack"))
Err NoNumberOnStack ->
Err (StringErr "Tried to run a number when no number was on the stack")
Err(NoNumberOnStack) ->
Err(StringErr("Tried to run a number when no number was on the stack"))
Err NoVariableOnStack ->
Err (StringErr "Tried to load a variable when no variable was on the stack")
Err(NoVariableOnStack) ->
Err(StringErr("Tried to load a variable when no variable was on the stack"))
Err NoScope ->
Err (StringErr "Tried to run code when not in any scope")
Err(NoScope) ->
Err(StringErr("Tried to run code when not in any scope"))
Err OutOfBounds ->
Err (StringErr "Tried to load from an offset that was outside of the stack")
Err(OutOfBounds) ->
Err(StringErr("Tried to load from an offset that was outside of the stack"))
Err UnexpectedEndOfData ->
Err (StringErr "Hit end of data while still parsing something")
Err(UnexpectedEndOfData) ->
Err(StringErr("Hit end of data while still parsing something")))
interpretCtx! : Context => Result Context InterpreterErrors
interpretCtx! = \ctx ->
when interpretCtxLoop! ctx is
Ok (Step next) ->
interpretCtx! next
interpret_ctx! : Context => Result Context InterpreterErrors
interpret_ctx! = \ctx ->
when interpret_ctx_loop!(ctx) is
Ok(Step(next)) ->
interpret_ctx!(next)
Ok (Done next) ->
Ok next
Ok(Done(next)) ->
Ok(next)
Err e ->
Err e
Err(e) ->
Err(e)
interpretCtxLoop! : Context => Result [Step Context, Done Context] InterpreterErrors
interpretCtxLoop! = \ctx ->
interpret_ctx_loop! : Context => Result [Step Context, Done Context] InterpreterErrors
interpret_ctx_loop! = \ctx ->
when ctx.state is
Executing if Context.inWhileScope ctx ->
Executing if Context.in_while_scope(ctx) ->
# Deal with the current while loop potentially looping.
last = (List.len ctx.scopes - 1)
last = (List.len(ctx.scopes) - 1)
scope = List.get ctx.scopes last |> Result.mapErr? \_ -> NoScope
when scope.whileInfo is
Some { state: InCond, body, cond } ->
scope = List.get(ctx.scopes, last) |> Result.map_err?(\_ -> NoScope)
when scope.while_info is
Some({ state: InCond, body, cond }) ->
# Just ran condition. Check the top of stack to see if body should run.
(popCtx, n) = popNumber? ctx
(pop_ctx, n) = pop_number?(ctx)
if n == 0 then
newScope = { scope & whileInfo: None }
new_scope = { scope & while_info: None }
Ok (Step { popCtx & scopes: List.set ctx.scopes last newScope })
Ok(Step({ pop_ctx & scopes: List.set(ctx.scopes, last, new_scope) }))
else
newScope = { scope & whileInfo: Some { state: InBody, body, cond } }
new_scope = { scope & while_info: Some({ state: InBody, body, cond }) }
Ok (Step { popCtx & scopes: List.append (List.set ctx.scopes last newScope) { data: None, buf: body, index: 0, whileInfo: None } })
Ok(Step({ pop_ctx & scopes: List.append(List.set(ctx.scopes, last, new_scope), { data: None, buf: body, index: 0, while_info: None }) }))
Some { state: InBody, body, cond } ->
Some({ state: InBody, body, cond }) ->
# Just rand the body. Run the condition again.
newScope = { scope & whileInfo: Some { state: InCond, body, cond } }
new_scope = { scope & while_info: Some({ state: InCond, body, cond }) }
Ok (Step { ctx & scopes: List.append (List.set ctx.scopes last newScope) { data: None, buf: cond, index: 0, whileInfo: None } })
Ok(Step({ ctx & scopes: List.append(List.set(ctx.scopes, last, new_scope), { data: None, buf: cond, index: 0, while_info: None }) }))
None ->
Err NoScope
Err(NoScope)
Executing ->
# Stdout.line! (Context.toStr ctx)
result = Context.getChar! ctx
# Stdout.line! (Context.to_str ctx)
result = Context.get_char!(ctx)
when result is
Ok (val, newCtx) ->
execCtx = stepExecCtx!? newCtx val
Ok (Step execCtx)
Ok((val, new_ctx)) ->
exec_ctx = step_exec_ctx!?(new_ctx, val)
Ok(Step(exec_ctx))
Err NoScope ->
Err NoScope
Err(NoScope) ->
Err(NoScope)
Err EndOfData ->
Err(EndOfData) ->
# Computation complete for this scope.
# Drop a scope.
dropCtx = { ctx & scopes: List.dropAt ctx.scopes (List.len ctx.scopes - 1) }
drop_ctx = { ctx & scopes: List.drop_at(ctx.scopes, (List.len(ctx.scopes) - 1)) }
# If no scopes left, all execution complete.
if List.isEmpty dropCtx.scopes then
Ok (Done dropCtx)
if List.is_empty(drop_ctx.scopes) then
Ok(Done(drop_ctx))
else
Ok (Step dropCtx)
Ok(Step(drop_ctx))
InComment ->
(val, newCtx) = Context.getChar! ctx |> Result.mapErr? endUnexpected
(val, new_ctx) = Context.get_char!(ctx) |> Result.map_err?(end_unexpected)
if val == 0x7D then
# `}` end of comment
Ok (Step { newCtx & state: Executing })
Ok(Step({ new_ctx & state: Executing }))
else
Ok (Step { newCtx & state: InComment })
Ok(Step({ new_ctx & state: InComment }))
InNumber accum ->
(val, newCtx) = Context.getChar! ctx |> Result.mapErr? endUnexpected
if isDigit val then
InNumber(accum) ->
(val, new_ctx) = Context.get_char!(ctx) |> Result.map_err?(end_unexpected)
if is_digit(val) then
# still in the number
# i32 multiplication is kinda broken because it implicitly seems to want to upcast to i64.
# so like should be (i32, i32) -> i32, but seems to be (i32, i32) -> i64
# so this is make i64 mul by 10 then convert back to i32.
nextAccum = (10 * Num.intCast accum) + Num.intCast (val - 0x30)
next_accum = (10 * Num.int_cast(accum)) + Num.int_cast((val - 0x30))
Ok (Step { newCtx & state: InNumber (Num.intCast nextAccum) })
Ok(Step({ new_ctx & state: InNumber(Num.int_cast(next_accum)) }))
else
# outside of number now, this needs to be executed.
pushCtx = Context.pushStack newCtx (Number accum)
push_ctx = Context.push_stack(new_ctx, Number(accum))
execCtx = stepExecCtx!? { pushCtx & state: Executing } val
Ok (Step execCtx)
exec_ctx = step_exec_ctx!?({ push_ctx & state: Executing }, val)
Ok(Step(exec_ctx))
InString bytes ->
(val, newCtx) = Context.getChar! ctx |> Result.mapErr? endUnexpected
InString(bytes) ->
(val, new_ctx) = Context.get_char!(ctx) |> Result.map_err?(end_unexpected)
if val == 0x22 then
# `"` end of string
when Str.fromUtf8 bytes is
Ok str ->
Stdout.raw! str
Ok (Step { newCtx & state: Executing })
when Str.from_utf8(bytes) is
Ok(str) ->
Stdout.raw!(str)
Ok(Step({ new_ctx & state: Executing }))
Err _ ->
Err BadUtf8
Err(_) ->
Err(BadUtf8)
else
Ok (Step { newCtx & state: InString (List.append bytes val) })
Ok(Step({ new_ctx & state: InString(List.append(bytes, val)) }))
InLambda depth bytes ->
(val, newCtx) = Context.getChar! ctx |> Result.mapErr? endUnexpected
InLambda(depth, bytes) ->
(val, new_ctx) = Context.get_char!(ctx) |> Result.map_err?(end_unexpected)
if val == 0x5B then
# start of a nested lambda `[`
Ok (Step { newCtx & state: InLambda (depth + 1) (List.append bytes val) })
Ok(Step({ new_ctx & state: InLambda((depth + 1), List.append(bytes, val)) }))
else if val == 0x5D then
# `]` end of current lambda
if depth == 0 then
# end of all lambdas
Ok (Step (Context.pushStack { newCtx & state: Executing } (Lambda bytes)))
Ok(Step(Context.push_stack({ new_ctx & state: Executing }, Lambda(bytes))))
else
# end of nested lambda
Ok (Step { newCtx & state: InLambda (depth - 1) (List.append bytes val) })
Ok(Step({ new_ctx & state: InLambda((depth - 1), List.append(bytes, val)) }))
else
Ok (Step { newCtx & state: InLambda depth (List.append bytes val) })
Ok(Step({ new_ctx & state: InLambda(depth, List.append(bytes, val)) }))
InSpecialChar ->
val = Context.getChar! { ctx & state: Executing } |> Result.mapErr? endUnexpected
val = Context.get_char!({ ctx & state: Executing }) |> Result.map_err?(end_unexpected)
when val is
(0xB8, newCtx) ->
(popCtx, index) = popNumber? newCtx
(0xB8, new_ctx) ->
(pop_ctx, index) = pop_number?(new_ctx)
# I think Num.abs is too restrictive, it should be able to produce a natural number, but it seem to be restricted to signed numbers.
size = List.len popCtx.stack - 1
offset = Num.intCast size - index
size = List.len(pop_ctx.stack) - 1
offset = Num.int_cast(size) - index
if offset >= 0 then
stackVal = List.get? popCtx.stack (Num.intCast offset)
Ok (Step (Context.pushStack popCtx stackVal))
stack_val = List.get?(pop_ctx.stack, Num.int_cast(offset))
Ok(Step(Context.push_stack(pop_ctx, stack_val)))
else
Err OutOfBounds
Err(OutOfBounds)
(0x9F, newCtx) ->
(0x9F, new_ctx) ->
# This is supposed to flush io buffers. We don't buffer, so it does nothing
Ok (Step newCtx)
Ok(Step(new_ctx))
(x, _) ->
data = Num.toStr (Num.intCast x)
data = Num.to_str(Num.int_cast(x))
Err (InvalidChar data)
Err(InvalidChar(data))
LoadChar ->
(x, newCtx) = Context.getChar! { ctx & state: Executing } |> Result.mapErr? endUnexpected
Ok (Step (Context.pushStack newCtx (Number (Num.intCast x))))
(x, new_ctx) = Context.get_char!({ ctx & state: Executing }) |> Result.map_err?(end_unexpected)
Ok(Step(Context.push_stack(new_ctx, Number(Num.int_cast(x)))))
# If it weren't for reading stdin or writing to stdout, this could return a result.
stepExecCtx! : Context, U8 => Result Context InterpreterErrors
stepExecCtx! = \ctx, char ->
step_exec_ctx! : Context, U8 => Result Context InterpreterErrors
step_exec_ctx! = \ctx, char ->
when char is
0x21 ->
# `!` execute lambda
(popCtx, bytes) = popLambda? ctx
Ok { popCtx & scopes: List.append popCtx.scopes { data: None, buf: bytes, index: 0, whileInfo: None } }
(pop_ctx, bytes) = pop_lambda?(ctx)
Ok({ pop_ctx & scopes: List.append(pop_ctx.scopes, { data: None, buf: bytes, index: 0, while_info: None }) })
0x3F ->
# `?` if
(popCtx1, bytes) = popLambda? ctx
(popCtx2, n1) = popNumber? popCtx1
(pop_ctx1, bytes) = pop_lambda?(ctx)
(pop_ctx2, n1) = pop_number?(pop_ctx1)
if n1 == 0 then
Ok popCtx2
Ok(pop_ctx2)
else
Ok { popCtx2 & scopes: List.append popCtx2.scopes { data: None, buf: bytes, index: 0, whileInfo: None } }
Ok({ pop_ctx2 & scopes: List.append(pop_ctx2.scopes, { data: None, buf: bytes, index: 0, while_info: None }) })
0x23 ->
# `#` while
(popCtx1, body) = popLambda? ctx
(popCtx2, cond) = popLambda? popCtx1
last = (List.len popCtx2.scopes - 1)
(pop_ctx1, body) = pop_lambda?(ctx)
(pop_ctx2, cond) = pop_lambda?(pop_ctx1)
last = (List.len(pop_ctx2.scopes) - 1)
scope = List.get popCtx2.scopes last |> Result.mapErr? \_ -> NoScope
scope = List.get(pop_ctx2.scopes, last) |> Result.map_err?(\_ -> NoScope)
# set the current scope to be in a while loop.
scopes = List.set popCtx2.scopes last { scope & whileInfo: Some { cond: cond, body: body, state: InCond } }
scopes = List.set(pop_ctx2.scopes, last, { scope & while_info: Some({ cond: cond, body: body, state: InCond }) })
# push a scope to execute the condition.
Ok { popCtx2 & scopes: List.append scopes { data: None, buf: cond, index: 0, whileInfo: None } }
Ok({ pop_ctx2 & scopes: List.append(scopes, { data: None, buf: cond, index: 0, while_info: None }) })
0x24 ->
# `$` dup
# Switching this to List.last and changing the error to ListWasEmpty leads to a compiler bug.
# Complains about the types eq not matching.
when List.get ctx.stack (List.len ctx.stack - 1) is
Ok dupItem -> Ok (Context.pushStack ctx dupItem)
Err OutOfBounds -> Err EmptyStack
when List.get(ctx.stack, (List.len(ctx.stack) - 1)) is
Ok(dup_item) -> Ok(Context.push_stack(ctx, dup_item))
Err(OutOfBounds) -> Err(EmptyStack)
0x25 ->
# `%` drop
when Context.popStack ctx is
when Context.pop_stack(ctx) is
# Dropping with an empty stack, all results here are fine
Ok (popCtx, _) -> Ok popCtx
Err _ -> Ok ctx
Ok((pop_ctx, _)) -> Ok(pop_ctx)
Err(_) -> Ok(ctx)
0x5C ->
# `\` swap
(popCtx1, n1) = Context.popStack? ctx
(popCtx2, n2) = Context.popStack? popCtx1
Ok (Context.pushStack (Context.pushStack popCtx2 n1) n2)
(pop_ctx1, n1) = Context.pop_stack?(ctx)
(pop_ctx2, n2) = Context.pop_stack?(pop_ctx1)
Ok(Context.push_stack(Context.push_stack(pop_ctx2, n1), n2))
0x40 ->
# `@` rot
result2 =
(popCtx1, n1) = Context.popStack? ctx
(popCtx2, n2) = Context.popStack? popCtx1
(popCtx3, n3) = Context.popStack? popCtx2
Ok (Context.pushStack (Context.pushStack (Context.pushStack popCtx3 n2) n1) n3)
(pop_ctx1, n1) = Context.pop_stack?(ctx)
(pop_ctx2, n2) = Context.pop_stack?(pop_ctx1)
(pop_ctx3, n3) = Context.pop_stack?(pop_ctx2)
Ok(Context.push_stack(Context.push_stack(Context.push_stack(pop_ctx3, n2), n1), n3))
when result2 is
Ok a ->
Ok a
Ok(a) ->
Ok(a)
# Being explicit with error type is required to stop the need to propogate the error parameters to Context.popStack
Err EmptyStack ->
Err EmptyStack
Err(EmptyStack) ->
Err(EmptyStack)
0xC3 ->
# `ø` pick or `ß` flush
# these are actually 2 bytes, 0xC3 0xB8 or 0xC3 0x9F
# requires special parsing
Ok { ctx & state: InSpecialChar }
Ok({ ctx & state: InSpecialChar })
0x4F ->
# `O` also treat this as pick for easier script writing
(popCtx, index) = popNumber? ctx
(pop_ctx, index) = pop_number?(ctx)
# I think Num.abs is too restrictive, it should be able to produce a natural number, but it seem to be restricted to signed numbers.
size = List.len popCtx.stack - 1
offset = Num.intCast size - index
size = List.len(pop_ctx.stack) - 1
offset = Num.int_cast(size) - index
if offset >= 0 then
stackVal = List.get? popCtx.stack (Num.intCast offset)
Ok (Context.pushStack popCtx stackVal)
stack_val = List.get?(pop_ctx.stack, Num.int_cast(offset))
Ok(Context.push_stack(pop_ctx, stack_val))
else
Err OutOfBounds
Err(OutOfBounds)
0x42 ->
# `B` also treat this as flush for easier script writing
# This is supposed to flush io buffers. We don't buffer, so it does nothing
Ok ctx
Ok(ctx)
0x27 ->
# `'` load next char
Ok { ctx & state: LoadChar }
Ok({ ctx & state: LoadChar })
0x2B ->
# `+` add
binaryOp ctx Num.addWrap
binary_op(ctx, Num.add_wrap)
0x2D ->
# `-` sub
binaryOp ctx Num.subWrap
binary_op(ctx, Num.sub_wrap)
0x2A ->
# `*` mul
binaryOp ctx Num.mulWrap
binary_op(ctx, Num.mul_wrap)
0x2F ->
# `/` div
# Due to possible division by zero error, this must be handled specially.
(popCtx1, numR) = popNumber? ctx
(popCtx2, numL) = popNumber? popCtx1
res = Num.divTruncChecked? numL numR
Ok (Context.pushStack popCtx2 (Number res))
(pop_ctx1, num_r) = pop_number?(ctx)
(pop_ctx2, num_l) = pop_number?(pop_ctx1)
res = Num.div_trunc_checked?(num_l, num_r)
Ok(Context.push_stack(pop_ctx2, Number(res)))
0x26 ->
# `&` bitwise and
binaryOp ctx Num.bitwiseAnd
binary_op(ctx, Num.bitwise_and)
0x7C ->
# `|` bitwise or
binaryOp ctx Num.bitwiseOr
binary_op(ctx, Num.bitwise_or)
0x3D ->
# `=` equals
binaryOp ctx \a, b ->
binary_op(ctx, \a, b ->
if a == b then
-1
else
0
0)
0x3E ->
# `>` greater than
binaryOp ctx \a, b ->
binary_op(ctx, \a, b ->
if a > b then
-1
else
0
0)
0x5F ->
# `_` negate
unaryOp ctx Num.neg
unary_op(ctx, Num.neg)
0x7E ->
# `~` bitwise not
unaryOp ctx (\x -> Num.bitwiseXor x -1) # xor with -1 should be bitwise not
unary_op(ctx, \x -> Num.bitwise_xor(x, -1)) # xor with -1 should be bitwise not
0x2C ->
# `,` write char
(popCtx, num) = popNumber? ctx
str = Str.fromUtf8 [Num.intCast num] |> Result.mapErr? \_ -> BadUtf8
Stdout.raw! str
Ok popCtx
(pop_ctx, num) = pop_number?(ctx)
str = Str.from_utf8([Num.int_cast(num)]) |> Result.map_err?(\_ -> BadUtf8)
Stdout.raw!(str)
Ok(pop_ctx)
0x2E ->
# `.` write int
(popCtx, num) = popNumber? ctx
Stdout.raw! (Num.toStr (Num.intCast num))
Ok popCtx
(pop_ctx, num) = pop_number?(ctx)
Stdout.raw!(Num.to_str(Num.int_cast(num)))
Ok(pop_ctx)
0x5E ->
# `^` read char as int
in = Stdin.char! {}
in = Stdin.char!({})
if in == 255 then
# max char sent on EOF. Change to -1
Ok (Context.pushStack ctx (Number -1))
Ok(Context.push_stack(ctx, Number(-1)))
else
Ok (Context.pushStack ctx (Number (Num.intCast in)))
Ok(Context.push_stack(ctx, Number(Num.int_cast(in))))
0x3A ->
# `:` store to variable
(popCtx1, var) = popVariable? ctx
(popCtx2, n1) = Context.popStack? popCtx1
Ok { popCtx2 & vars: List.set popCtx2.vars (Variable.toIndex var) n1 }
(pop_ctx1, var) = pop_variable?(ctx)
(pop_ctx2, n1) = Context.pop_stack?(pop_ctx1)
Ok({ pop_ctx2 & vars: List.set(pop_ctx2.vars, Variable.to_index(var), n1) })
0x3B ->
# `;` load from variable
(popCtx, var) = popVariable? ctx
elem = List.get? popCtx.vars (Variable.toIndex var)
Ok (Context.pushStack popCtx elem)
(pop_ctx, var) = pop_variable?(ctx)
elem = List.get?(pop_ctx.vars, Variable.to_index(var))
Ok(Context.push_stack(pop_ctx, elem))
0x22 ->
# `"` string start
Ok { ctx & state: InString [] }
Ok({ ctx & state: InString([]) })
0x5B ->
# `"` string start
Ok { ctx & state: InLambda 0 [] }
Ok({ ctx & state: InLambda(0, []) })
0x7B ->
# `{` comment start
Ok { ctx & state: InComment }
Ok({ ctx & state: InComment })
x if isDigit x ->
x if is_digit(x) ->
# number start
Ok { ctx & state: InNumber (Num.intCast (x - 0x30)) }
Ok({ ctx & state: InNumber(Num.int_cast((x - 0x30))) })
x if isWhitespace x ->
Ok ctx
x if is_whitespace(x) ->
Ok(ctx)
x ->
when Variable.fromUtf8 x is
when Variable.from_utf8(x) is
# letters are variable names
Ok var ->
Ok (Context.pushStack ctx (Var var))
Ok(var) ->
Ok(Context.push_stack(ctx, Var(var)))
Err _ ->
data = Num.toStr (Num.intCast x)
Err(_) ->
data = Num.to_str(Num.int_cast(x))
Err (InvalidChar data)
Err(InvalidChar(data))
unaryOp : Context, (I32 -> I32) -> Result Context InterpreterErrors
unaryOp = \ctx, op ->
(popCtx, num) = popNumber? ctx
Ok (Context.pushStack popCtx (Number (op num)))
unary_op : Context, (I32 -> I32) -> Result Context InterpreterErrors
unary_op = \ctx, op ->
(pop_ctx, num) = pop_number?(ctx)
Ok(Context.push_stack(pop_ctx, Number(op(num))))
binaryOp : Context, (I32, I32 -> I32) -> Result Context InterpreterErrors
binaryOp = \ctx, op ->
(popCtx1, numR) = popNumber? ctx
(popCtx2, numL) = popNumber? popCtx1
Ok (Context.pushStack popCtx2 (Number (op numL numR)))
binary_op : Context, (I32, I32 -> I32) -> Result Context InterpreterErrors
binary_op = \ctx, op ->
(pop_ctx1, num_r) = pop_number?(ctx)
(pop_ctx2, num_l) = pop_number?(pop_ctx1)
Ok(Context.push_stack(pop_ctx2, Number(op(num_l, num_r))))
popNumber : Context -> Result (Context, I32) InterpreterErrors
popNumber = \ctx ->
when Context.popStack? ctx is
(popCtx, Number num) -> Ok (popCtx, num)
_ -> Err NoNumberOnStack
pop_number : Context -> Result (Context, I32) InterpreterErrors
pop_number = \ctx ->
when Context.pop_stack?(ctx) is
(pop_ctx, Number(num)) -> Ok((pop_ctx, num))
_ -> Err(NoNumberOnStack)
popLambda : Context -> Result (Context, List U8) InterpreterErrors
popLambda = \ctx ->
when Context.popStack? ctx is
(popCtx, Lambda bytes) -> Ok (popCtx, bytes)
_ -> Err NoLambdaOnStack
pop_lambda : Context -> Result (Context, List U8) InterpreterErrors
pop_lambda = \ctx ->
when Context.pop_stack?(ctx) is
(pop_ctx, Lambda(bytes)) -> Ok((pop_ctx, bytes))
_ -> Err(NoLambdaOnStack)
popVariable : Context -> Result (Context, Variable) InterpreterErrors
popVariable = \ctx ->
when Context.popStack? ctx is
(popCtx, Var var) -> Ok (popCtx, var)
_ -> Err NoVariableOnStack
pop_variable : Context -> Result (Context, Variable) InterpreterErrors
pop_variable = \ctx ->
when Context.pop_stack?(ctx) is
(pop_ctx, Var(var)) -> Ok((pop_ctx, var))
_ -> Err(NoVariableOnStack)
isDigit : U8 -> Bool
isDigit = \char ->
is_digit : U8 -> Bool
is_digit = \char ->
char
>= 0x30 # `0`
&& char
<= 0x39 # `0`
isWhitespace : U8 -> Bool
isWhitespace = \char ->
is_whitespace : U8 -> Bool
is_whitespace = \char ->
char
== 0xA # new line
|| char
@ -473,7 +473,7 @@ isWhitespace = \char ->
|| char
== 0x9 # tab
endUnexpected = \err ->
end_unexpected = \err ->
when err is
NoScope ->
NoScope

View file

@ -1,30 +1,30 @@
module [line!, withOpen!, chunk!, Handle]
module [line!, with_open!, chunk!, Handle]
import pf.Host
Handle := U64
line! : Handle => Str
line! = \@Handle handle ->
Host.getFileLine! handle
line! = \@Handle(handle) ->
Host.get_file_line!(handle)
chunk! : Handle => List U8
chunk! = \@Handle handle ->
Host.getFileBytes! handle
chunk! = \@Handle(handle) ->
Host.get_file_bytes!(handle)
open! : Str => Handle
open! = \path ->
Host.openFile! path
Host.open_file!(path)
|> @Handle
close! : Handle => {}
close! = \@Handle handle ->
Host.closeFile! handle
close! = \@Handle(handle) ->
Host.close_file!(handle)
withOpen! : Str, (Handle => a) => a
withOpen! = \path, callback! ->
handle = open! path
result = callback! handle
close! handle
with_open! : Str, (Handle => a) => a
with_open! = \path, callback! ->
handle = open!(path)
result = callback!(handle)
close!(handle)
result

View file

@ -1,19 +1,19 @@
hosted Host
exposes [openFile!, closeFile!, getFileLine!, getFileBytes!, putLine!, putRaw!, getLine!, getChar!]
exposes [open_file!, close_file!, get_file_line!, get_file_bytes!, put_line!, put_raw!, get_line!, get_char!]
imports []
openFile! : Str => U64
open_file! : Str => U64
closeFile! : U64 => {}
close_file! : U64 => {}
getFileLine! : U64 => Str
get_file_line! : U64 => Str
getFileBytes! : U64 => List U8
get_file_bytes! : U64 => List U8
putLine! : Str => {}
put_line! : Str => {}
putRaw! : Str => {}
put_raw! : Str => {}
getLine! : {} => Str
get_line! : {} => Str
getChar! : {} => U8
get_char! : {} => U8

View file

@ -4,8 +4,8 @@ import pf.Host
line! : {} => Str
line! = \{} ->
Host.getLine! {}
Host.get_line!({})
char! : {} => U8
char! = \{} ->
Host.getChar! {}
Host.get_char!({})

View file

@ -4,8 +4,8 @@ import pf.Host
line! : Str => {}
line! = \text ->
Host.putLine! text
Host.put_line!(text)
raw! : Str => {}
raw! = \text ->
Host.putRaw! text
Host.put_raw!(text)

View file

@ -3,7 +3,7 @@ platform "false-interpreter"
exposes []
packages {}
imports []
provides [mainForHost!]
provides [main_for_host!]
mainForHost! : Str => {}
mainForHost! = \file -> main! file
main_for_host! : Str => {}
main_for_host! = \file -> main!(file)

View file

@ -19,7 +19,7 @@ fn file_handles() -> &'static Mutex<HashMap<u64, BufReader<File>>> {
}
extern "C" {
#[link_name = "roc__mainForHost_1_exposed_generic"]
#[link_name = "roc__main_for_host_1_exposed_generic"]
fn roc_main(void: *const c_void, args: *mut RocStr);
}

View file

@ -1,4 +1,4 @@
app [main] { pf: "platform/main.roc" }
main : Str
main = Dep1.value1 {}
main = Dep1.value1({})

View file

@ -1,4 +1,4 @@
app [main] { pf: "platform/main.roc" }
main : Str
main = Dep1.value1 {}
main = Dep1.value1({})

View file

@ -1,4 +1,4 @@
app [main] { pf: "platform/main.roc" }
app [main] { pf: "platform/main.roc" }
main : Str
main = Dep1.value1 {}
main = Dep1.value1({})

View file

@ -3,4 +3,4 @@ module [value1]
import Dep2
value1 : {} -> Str
value1 = \_ -> Dep2.value2 {}
value1 = \_ -> Dep2.value2({})

View file

@ -3,4 +3,4 @@ app [main] { pf: platform "../../test-platform-simple-zig/main.roc" }
import Dep1
main : Str
main = Dep1.value1 {}
main = Dep1.value1({})

View file

@ -1,7 +1,7 @@
module [plainText, emText]
module [plain_text, em_text]
import Symbol exposing [Ident]
plainText = \str -> PlainText str
plain_text = \str -> PlainText(str)
emText = \str -> EmText str
em_text = \str -> EmText(str)

View file

@ -1,7 +1,7 @@
module [plainText, emText]
module [plain_text, em_text]
import Symbol exposing [Ident]
plainText = \str -> PlainText str
plain_text = \str -> PlainText(str)
emText = \str -> EmText str
em_text = \str -> EmText(str)

View file

@ -1,7 +1,7 @@
module [valueFromPkg]
module [value_from_pkg]
import cli.Foo
valueFromPkg = Foo.foo
value_from_pkg = Foo.foo
expect valueFromPkg == "Foo"
expect value_from_pkg == "Foo"

View file

@ -1,7 +1,7 @@
module [valueFromPkg]
module [value_from_pkg]
import pkg.Foo
valueFromPkg = Foo.foo
value_from_pkg = Foo.foo
expect valueFromPkg == "Foo"
expect value_from_pkg == "Foo"

View file

@ -5,4 +5,4 @@ app [main] {
import Module
main =
Module.valueFromPkg
Module.value_from_pkg

View file

@ -1,69 +1,69 @@
module { appId, protocol } -> [
baseUrl,
getUser,
getPost,
getPosts,
getPostComments,
getCompanies,
baseUrlAliased,
getPostAliased,
getUserSafe,
getPostComment,
module { app_id, protocol } -> [
base_url,
get_user,
get_post,
get_posts,
get_post_comments,
get_companies,
base_url_aliased,
get_post_aliased,
get_user_safe,
get_post_comment,
]
## value def referencing params
baseUrl : Str
baseUrl =
protocol "api.example.com/$(appId)"
base_url : Str
base_url =
protocol("api.example.com/$(app_id)")
## function def referencing params
getUser : U32 -> Str
getUser = \userId ->
get_user : U32 -> Str
get_user = \user_id ->
# purposefully not using baseUrl to test top-level fn referencing param
protocol "api.example.com/$(appId)/users/$(Num.toStr userId)"
protocol("api.example.com/$(app_id)/users/$(Num.to_str(user_id))")
## function def referencing top-level value
getPost : U32 -> Str
getPost = \postId ->
"$(baseUrl)/posts/$(Num.toStr postId)"
get_post : U32 -> Str
get_post = \post_id ->
"$(base_url)/posts/$(Num.to_str(post_id))"
## function def passing top-level function
getPosts : List U32 -> List Str
getPosts = \ids ->
List.map ids getPost
get_posts : List U32 -> List Str
get_posts = \ids ->
List.map(ids, get_post)
## function def calling top-level function
getPostComments : U32 -> Str
getPostComments = \postId ->
"$(getPost postId)/comments"
get_post_comments : U32 -> Str
get_post_comments = \post_id ->
"$(get_post(post_id))/comments"
## function def passing nested function
getCompanies : List U32 -> List Str
getCompanies = \ids ->
getCompany = \id ->
protocol "api.example.com/$(appId)/companies/$(Num.toStr id)"
get_companies : List U32 -> List Str
get_companies = \ids ->
get_company = \id ->
protocol("api.example.com/$(app_id)/companies/$(Num.to_str(id))")
List.map ids getCompany
List.map(ids, get_company)
## aliasing top-level value
baseUrlAliased : Str
baseUrlAliased =
baseUrl
base_url_aliased : Str
base_url_aliased =
base_url
## aliasing top-level fn
getPostAliased : U32 -> Str
getPostAliased =
getPost
get_post_aliased : U32 -> Str
get_post_aliased =
get_post
## top-level value returning functions
getUserSafe : U32 -> Str
getUserSafe =
if Str.startsWith appId "prod_" then
\id -> "$(getUser id)?safe=true"
get_user_safe : U32 -> Str
get_user_safe =
if Str.starts_with(app_id, "prod_") then
\id -> "$(get_user(id))?safe=true"
else
getUser
get_user
## two-argument function
getPostComment : U32, U32 -> Str
getPostComment = \postId, commentId ->
"$(getPost postId)/comments/$(Num.toStr commentId)"
get_post_comment : U32, U32 -> Str
get_post_comment = \post_id, comment_id ->
"$(get_post(post_id))/comments/$(Num.to_str(comment_id))"

View file

@ -1,9 +1,9 @@
module { appId } -> [fnAnnotatedAsValue, missingArg]
module { app_id } -> [fn_annotated_as_value, missing_arg]
fnAnnotatedAsValue : Str
fnAnnotatedAsValue = \postId, commentId ->
"/posts/$(postId)/comments/$(Num.toStr commentId)"
fn_annotated_as_value : Str
fn_annotated_as_value = \post_id, comment_id ->
"/posts/$(post_id)/comments/$(Num.to_str(comment_id))"
missingArg : Str -> Str
missingArg = \postId, _ ->
"/posts/$(postId)/comments"
missing_arg : Str -> Str
missing_arg = \post_id, _ ->
"/posts/$(post_id)/comments"

View file

@ -3,12 +3,12 @@ module []
https = \url -> "https://$(url)"
expect
import Api { appId: "one", protocol: https }
Api.baseUrl == "https://api.example.com/one"
import Api { app_id: "one", protocol: https }
Api.base_url == "https://api.example.com/one"
expect
import Api { appId: "two", protocol: https }
Api.getUser 1 == "https://api.example.com/two/users/1"
import Api { app_id: "two", protocol: https }
Api.get_user(1) == "https://api.example.com/two/users/1"
expect
import NoParams

View file

@ -1,7 +1,7 @@
module { echo } -> [menu]
menu = \name ->
indirect name
indirect(name)
indirect = \name ->
echo "Hi, $(name)!"
echo("Hi, $(name)!")

View file

@ -1,4 +1,4 @@
module { sendHttpReq, getEnvVar } -> [hi]
module { send_http_req, get_env_var } -> [hi]
hi : Str
hi =

View file

@ -2,58 +2,58 @@ app [main] {
pf: platform "../test-platform-simple-zig/main.roc",
}
import Api { appId: "one", protocol: https } as App1
import Api { appId: "two", protocol: http } as App2
import Api { appId: "prod_1", protocol: http } as Prod
import Api { app_id: "one", protocol: https } as App1
import Api { app_id: "two", protocol: http } as App2
import Api { app_id: "prod_1", protocol: http } as Prod
https = \url -> "https://$(url)"
http = \url -> "http://$(url)"
usersApp1 =
users_app1 =
# pass top-level fn in a module with params
List.map [1, 2, 3] App1.getUser
List.map([1, 2, 3], App1.get_user)
main =
app3Id = "three"
app3_id = "three"
import Api { appId: app3Id, protocol: https } as App3
import Api { app_id: app3_id, protocol: https } as App3
getUserApp3Nested = \userId ->
get_user_app3_nested = \user_id ->
# use captured params def
App3.getUser userId
App3.get_user(user_id)
usersApp3Passed =
users_app3_passed =
# pass top-level fn in a nested def
List.map [1, 2, 3] App3.getUser
List.map([1, 2, 3], App3.get_user)
"""
App1.baseUrl: $(App1.baseUrl)
App2.baseUrl: $(App2.baseUrl)
App3.baseUrl: $(App3.baseUrl)
App1.getUser 1: $(App1.getUser 1)
App2.getUser 2: $(App2.getUser 2)
App3.getUser 3: $(App3.getUser 3)
App1.getPost 1: $(App1.getPost 1)
App2.getPost 2: $(App2.getPost 2)
App3.getPost 3: $(App3.getPost 3)
App1.getPosts [1, 2]: $(Inspect.toStr (App1.getPosts [1, 2]))
App2.getPosts [3, 4]: $(Inspect.toStr (App2.getPosts [3, 4]))
App2.getPosts [5, 6]: $(Inspect.toStr (App2.getPosts [5, 6]))
App1.getPostComments 1: $(App1.getPostComments 1)
App2.getPostComments 2: $(App2.getPostComments 2)
App2.getPostComments 3: $(App2.getPostComments 3)
App1.getCompanies [1, 2]: $(Inspect.toStr (App1.getCompanies [1, 2]))
App2.getCompanies [3, 4]: $(Inspect.toStr (App2.getCompanies [3, 4]))
App2.getCompanies [5, 6]: $(Inspect.toStr (App2.getCompanies [5, 6]))
App1.getPostAliased 1: $(App1.getPostAliased 1)
App2.getPostAliased 2: $(App2.getPostAliased 2)
App3.getPostAliased 3: $(App3.getPostAliased 3)
App1.baseUrlAliased: $(App1.baseUrlAliased)
App2.baseUrlAliased: $(App2.baseUrlAliased)
App3.baseUrlAliased: $(App3.baseUrlAliased)
App1.getUserSafe 1: $(App1.getUserSafe 1)
Prod.getUserSafe 2: $(Prod.getUserSafe 2)
usersApp1: $(Inspect.toStr usersApp1)
getUserApp3Nested 3: $(getUserApp3Nested 3)
usersApp3Passed: $(Inspect.toStr usersApp3Passed)
App1.baseUrl: $(App1.base_url)
App2.baseUrl: $(App2.base_url)
App3.baseUrl: $(App3.base_url)
App1.getUser 1: $(App1.get_user(1))
App2.getUser 2: $(App2.get_user(2))
App3.getUser 3: $(App3.get_user(3))
App1.getPost 1: $(App1.get_post(1))
App2.getPost 2: $(App2.get_post(2))
App3.getPost 3: $(App3.get_post(3))
App1.getPosts [1, 2]: $(Inspect.to_str(App1.get_posts([1, 2])))
App2.getPosts [3, 4]: $(Inspect.to_str(App2.get_posts([3, 4])))
App2.getPosts [5, 6]: $(Inspect.to_str(App2.get_posts([5, 6])))
App1.getPostComments 1: $(App1.get_post_comments(1))
App2.getPostComments 2: $(App2.get_post_comments(2))
App2.getPostComments 3: $(App2.get_post_comments(3))
App1.getCompanies [1, 2]: $(Inspect.to_str(App1.get_companies([1, 2])))
App2.getCompanies [3, 4]: $(Inspect.to_str(App2.get_companies([3, 4])))
App2.getCompanies [5, 6]: $(Inspect.to_str(App2.get_companies([5, 6])))
App1.getPostAliased 1: $(App1.get_post_aliased(1))
App2.getPostAliased 2: $(App2.get_post_aliased(2))
App3.getPostAliased 3: $(App3.get_post_aliased(3))
App1.baseUrlAliased: $(App1.base_url_aliased)
App2.baseUrlAliased: $(App2.base_url_aliased)
App3.baseUrlAliased: $(App3.base_url_aliased)
App1.getUserSafe 1: $(App1.get_user_safe(1))
Prod.getUserSafe 2: $(Prod.get_user_safe(2))
usersApp1: $(Inspect.to_str(users_app1))
getUserApp3Nested 3: $(get_user_app3_nested(3))
usersApp3Passed: $(Inspect.to_str(users_app3_passed))
"""

View file

@ -2,16 +2,16 @@ app [main] {
pf: platform "../test-platform-simple-zig/main.roc",
}
import Api { appId: "one", protocol: https }
import Api { app_id: "one", protocol: https }
https = \url -> "https://$(url)"
main =
"""
# too many args
$(Api.getUser 1 2)
$(Api.baseUrl 1)
$(Api.get_user(1, 2))
$(Api.base_url(1))
# too few args
$(Api.getPostComment 1)
$(Api.get_post_comment(1))
"""

View file

@ -2,7 +2,7 @@ app [main] {
pf: platform "../test-platform-simple-zig/main.roc",
}
import BadAnn { appId: "one" }
import BadAnn { app_id: "one" }
main =
""

View file

@ -9,6 +9,6 @@ import Alias { passed: Stdin.line } as In
import Alias { passed: Stdout.line } as Out
main =
Out.exposed! "Write something:"
Out.exposed!("Write something:")
input = In.exposed!
Out.exposed! input
Out.exposed!(input)

View file

@ -1,3 +1,3 @@
module { stdout! } -> [log!]
log! = \msg, level -> stdout! "$(level):$(msg)"
log! = \msg, level -> stdout!("$(level):$(msg)")

View file

@ -2,10 +2,10 @@ app [main] {
cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.17.0/lZFLstMUCUvd5bjnnpYromZJXkQUrdhbva4xdBInicE.tar.br",
}
import Alias { passed: Task.ok {} }
import Alias { passed: Task.ok({}) }
main =
Task.loop! {} loop
Task.loop!({}, loop)
loop = \{} ->
Task.map Alias.exposed \x -> Done x
Task.map(Alias.exposed, \x -> Done(x))

View file

@ -3,8 +3,8 @@ app [main] {
}
import MultilineParams {
sendHttpReq: \_ -> crash "todo",
getEnvVar: \_ -> crash "todo",
send_http_req: \_ -> crash("todo"),
get_env_var: \_ -> crash("todo"),
}
main =

View file

@ -1,7 +1,7 @@
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.17.0/lZFLstMUCUvd5bjnnpYromZJXkQUrdhbva4xdBInicE.tar.br" }
import pf.Stdout
import Menu { echo: \str -> Stdout.line str }
import Menu { echo: \str -> Stdout.line(str) }
main =
Menu.menu "Agus"
Menu.menu("Agus")

View file

@ -2,11 +2,9 @@ app [main] {
pf: platform "../test-platform-simple-zig/main.roc",
}
import Api { appId: "one", protocol: https }
import Api { app_id: "one", protocol: https }
https = \url -> "https://$(url)"
main =
"""
$(Api.getPost)
"""
"$(Api.get_post)"

View file

@ -1,20 +1,20 @@
app [exposed1, exposed2, add1, sub1] { pf: platform "platform/main.roc" }
exposed1 = \n -> fib n 0 1
exposed1 = \n -> fib(n, 0, 1)
fib = \n, a, b ->
if n == 0 then
a
else
fib (n - 1) b (a + b)
fib((n - 1), b, (a + b))
exposed2 = \n -> fact n 1
exposed2 = \n -> fact(n, 1)
fact = \n, x ->
if n == 0 then
x
else
fact (n - 1) (n * x)
fact((n - 1), (n * x))
add1 = \n -> n + 1
sub1 = \n -> n - 1

View file

@ -10,8 +10,8 @@ const maxInt = std.math.maxInt;
const mem = std.mem;
const Allocator = mem.Allocator;
extern fn roc__exposedForHost1_1_exposed(i64) i64;
extern fn roc__exposedForHost2_1_exposed(i64) i64;
extern fn roc__exposed_for_host1_1_exposed(i64) i64;
extern fn roc__exposed_for_host2_1_exposed(i64) i64;
const Align = 2 * @alignOf(usize);
extern fn malloc(size: usize) callconv(.C) ?*align(Align) anyopaque;
@ -109,8 +109,8 @@ comptime {
pub export fn main() u8 {
const stdout = std.io.getStdOut().writer();
const result = roc__exposedForHost1_1_exposed(10);
const result2 = roc__exposedForHost2_1_exposed(10);
const result = roc__exposed_for_host1_1_exposed(10);
const result2 = roc__exposed_for_host2_1_exposed(10);
stdout.print("{d}\n", .{result}) catch unreachable;
stdout.print("{d}\n", .{result2}) catch unreachable;

View file

@ -3,10 +3,10 @@ platform "multiple_exposed"
exposes []
packages {}
imports []
provides [exposedForHost1, exposedForHost2]
provides [exposed_for_host1, exposed_for_host2]
exposedForHost1 : I64 -> I64
exposedForHost1 = \a -> exposed1 a |> sub1 |> add1
exposed_for_host1 : I64 -> I64
exposed_for_host1 = \a -> exposed1(a) |> sub1 |> add1
exposedForHost2 : I64 -> I64
exposedForHost2 = \a -> exposed2 a |> add1 |> sub1
exposed_for_host2 : I64 -> I64
exposed_for_host2 = \a -> exposed2(a) |> add1 |> sub1

View file

@ -101,7 +101,7 @@ comptime {
const mem = std.mem;
const Allocator = mem.Allocator;
extern fn roc__mainForHost_1_exposed_generic(*RocStr) void;
extern fn roc__main_for_host_1_exposed_generic(*RocStr) void;
const Unit = extern struct {};
@ -110,7 +110,7 @@ pub export fn main() u8 {
// actually call roc to populate the callresult
var callresult = RocStr.empty();
roc__mainForHost_1_exposed_generic(&callresult);
roc__main_for_host_1_exposed_generic(&callresult);
// stdout the result
stdout.print("{s}", .{callresult.asSlice()}) catch unreachable;

View file

@ -5,10 +5,10 @@ platform "test"
foo: "../foo/main.roc",
}
imports []
provides [mainForHost]
provides [main_for_host]
import foo.Foo
mainForHost : Str
mainForHost =
main_for_host : Str
main_for_host =
"$(main) $(Foo.foo)"

View file

@ -1,7 +1,7 @@
hosted Effect
exposes [putLine!, getLine!]
exposes [put_line!, get_line!]
imports []
putLine! : Str => {}
put_line! : Str => {}
getLine! : {} => Str
get_line! : {} => Str

View file

@ -5,6 +5,6 @@ import pf.Effect
# just a stubbed app for building the test platform
main! = \{} ->
Effect.putLine! ""
Effect.put_line!("")
{}

View file

@ -10,8 +10,8 @@ const maxInt = std.math.maxInt;
const mem = std.mem;
const Allocator = mem.Allocator;
extern fn roc__mainForHost_1_exposed_generic([*]u8) void;
extern fn roc__mainForHost_1_exposed_size() i64;
extern fn roc__main_for_host_1_exposed_generic([*]u8) void;
extern fn roc__main_for_host_1_exposed_size() i64;
const Align = 2 * @alignOf(usize);
extern fn malloc(size: usize) callconv(.C) ?*align(Align) anyopaque;
@ -111,7 +111,7 @@ pub export fn main() u8 {
const allocator = std.heap.page_allocator;
// NOTE the return size can be zero, which will segfault. Always allocate at least 8 bytes
const size = @max(8, @as(usize, @intCast(roc__mainForHost_1_exposed_size())));
const size = @max(8, @as(usize, @intCast(roc__main_for_host_1_exposed_size())));
const raw_output = allocator.alignedAlloc(u8, @alignOf(u64), @as(usize, @intCast(size))) catch unreachable;
const output = @as([*]u8, @ptrCast(raw_output));
@ -119,16 +119,16 @@ pub export fn main() u8 {
allocator.free(raw_output);
}
roc__mainForHost_1_exposed_generic(output);
roc__main_for_host_1_exposed_generic(output);
return 0;
}
pub export fn roc_fx_getLine() str.RocStr {
return roc_fx_getLine_help() catch return str.RocStr.empty();
pub export fn roc_fx_get_line() str.RocStr {
return roc_fx_get_line_help() catch return str.RocStr.empty();
}
fn roc_fx_getLine_help() !RocStr {
fn roc_fx_get_line_help() !RocStr {
const stdin = std.io.getStdIn().reader();
var buf: [400]u8 = undefined;
@ -137,7 +137,7 @@ fn roc_fx_getLine_help() !RocStr {
return str.RocStr.init(@as([*]const u8, @ptrCast(line)), line.len);
}
pub export fn roc_fx_putLine(rocPath: *str.RocStr) i64 {
pub export fn roc_fx_put_line(rocPath: *str.RocStr) i64 {
const stdout = std.io.getStdOut().writer();
for (rocPath.asSlice()) |char| {
@ -155,8 +155,8 @@ const GetInt = extern struct {
is_error: bool,
};
pub export fn roc_fx_getInt() GetInt {
if (roc_fx_getInt_help()) |value| {
pub export fn roc_fx_get_int() GetInt {
if (roc_fx_get_int_help()) |value| {
const get_int = GetInt{ .is_error = false, .value = value, .error_code = 0 };
return get_int;
} else |err| switch (err) {
@ -171,7 +171,7 @@ pub export fn roc_fx_getInt() GetInt {
return 0;
}
fn roc_fx_getInt_help() !i64 {
fn roc_fx_get_int_help() !i64 {
const stdin = std.io.getStdIn().reader();
var buf: [40]u8 = undefined;

View file

@ -3,7 +3,7 @@ platform "effects"
exposes []
packages {}
imports []
provides [mainForHost!]
provides [main_for_host!]
mainForHost! : {} => {}
mainForHost! = \{} -> main! {}
main_for_host! : {} => {}
main_for_host! = \{} -> main!({})

View file

@ -9,7 +9,7 @@ const expect = testing.expect;
const mem = std.mem;
const Allocator = mem.Allocator;
extern fn roc__mainForHost_1_exposed_generic(*RocStr) void;
extern fn roc__main_for_host_1_exposed_generic(*RocStr) void;
const Align = 2 * @alignOf(usize);
extern fn malloc(size: usize) callconv(.C) ?*align(Align) anyopaque;
@ -96,7 +96,7 @@ pub export fn main() i32 {
// actually call roc to populate the callresult
var callresult = RocStr.empty();
roc__mainForHost_1_exposed_generic(&callresult);
roc__main_for_host_1_exposed_generic(&callresult);
// stdout the result
stdout.print("{s}\n", .{callresult.asSlice()}) catch unreachable;

View file

@ -3,7 +3,7 @@ platform ""
exposes []
packages {}
imports []
provides [mainForHost]
provides [main_for_host]
mainForHost : Str
mainForHost = main
main_for_host : Str
main_for_host = main

View file

@ -7,6 +7,6 @@ Model : Str
main : Program Model
main = {
init: \{} -> "Hello World",
update: \model, new -> Str.concat model new,
view: \model -> Str.concat model "!",
update: \model, new -> Str.concat(model, new),
view: \model -> Str.concat(model, "!"),
}

Some files were not shown because too many files have changed in this diff Show more